/* Decrypt from libsodium will perform itself the tag comparaison. So ct is holding: cipher text || tag . The provided length (ctLen) must reflect this */ int32_t psAesDecryptGCM(psAesGcm_t *ctx, const unsigned char *ct, uint32_t ctLen, unsigned char *pt, uint32_t ptLen) { unsigned long long decrypted_len; if ((ctLen - ptLen) != crypto_aead_aes256gcm_ABYTES) { psTraceCrypto("Cipher text must include the tag\n"); return PS_ARG_FAIL; } if (crypto_aead_aes256gcm_decrypt_afternm(pt, &decrypted_len, NULL, ct, (unsigned long long) ctLen, (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen, (const unsigned char *) ctx->IV, (crypto_aead_aes256gcm_state *) &(ctx->libSodiumCtx)) != 0) { psTraceCrypto("GCM didn't authenticate\n"); return PS_AUTH_FAIL; } if (decrypted_len != ptLen) { psTraceCrypto("Problem during decryption\n"); return PS_AUTH_FAIL; } return PS_SUCCESS; }
static int aead_cipher_decrypt(cipher_ctx_t *cipher_ctx, uint8_t *p, size_t *plen, uint8_t *m, size_t mlen, uint8_t *ad, size_t adlen, uint8_t *n, uint8_t *k) { int err = CRYPTO_ERROR; unsigned long long long_plen = 0; size_t nlen = cipher_ctx->cipher->nonce_len; size_t tlen = cipher_ctx->cipher->tag_len; switch (cipher_ctx->cipher->method) { case AES256GCM: // Only AES-256-GCM is supported by libsodium. if (cipher_ctx->aes256gcm_ctx != NULL) { // Use it if availble err = crypto_aead_aes256gcm_decrypt_afternm(p, &long_plen, NULL, m, mlen, ad, adlen, n, (const aes256gcm_ctx *)cipher_ctx->aes256gcm_ctx); *plen = (size_t)long_plen; // it's safe to cast 64bit to 32bit length here break; } // Otherwise, just use the mbedTLS one with crappy AES-NI. case AES192GCM: case AES128GCM: err = mbedtls_cipher_auth_decrypt(cipher_ctx->evp, n, nlen, ad, adlen, m, mlen - tlen, p, plen, m + mlen - tlen, tlen); break; case CHACHA20POLY1305IETF: err = crypto_aead_chacha20poly1305_ietf_decrypt(p, &long_plen, NULL, m, mlen, ad, adlen, n, k); *plen = (size_t)long_plen; // it's safe to cast 64bit to 32bit length here break; #ifdef FS_HAVE_XCHACHA20IETF case XCHACHA20POLY1305IETF: err = crypto_aead_xchacha20poly1305_ietf_decrypt(p, &long_plen, NULL, m, mlen, ad, adlen, n, k); *plen = (size_t)long_plen; // it's safe to cast 64bit to 32bit length here break; #endif default: return CRYPTO_ERROR; } return err; }