/* Decrypt data using chach20-poly1305 authenticated encryption function. */ psResSize_t psChacha20Poly1305IetfDecrypt( psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], const unsigned char Ciphertext_p[PS_EXACTLY_EXPR(CiphertextNBytes)], psSizeL_t CiphertextNBytes, const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], const unsigned char *Aad_p, psSizeL_t AadNBytes, unsigned char *Plaintext_p) { #ifdef USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_DECRYPT /* Old path, which can be enabled by setting USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_DECRYPT. */ psSizeL_t plaintextNBytes = CiphertextNBytes - PS_CHACHA20POLY1305_IETF_ABYTES; if (CiphertextNBytes < PS_CHACHA20POLY1305_IETF_ABYTES) { return PS_ARG_FAIL; } /* Check input is not too large for this API. */ if (plaintextNBytes > (psSizeL_t)(psResSize_t)PS_RES_SIZE_OK_MAX) { return PS_ARG_FAIL; } if (crypto_aead_chacha20poly1305_ietf_decrypt( Plaintext_p, NULL, NULL, Ciphertext_p, (unsigned long long)CiphertextNBytes, (const unsigned char *)Aad_p, (unsigned long long)AadNBytes, (const unsigned char *)Iv_p, (const unsigned char *)Context_p->key) != 0) { psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); return PS_AUTH_FAIL; } return (psResSize_t)plaintextNBytes; #else psSizeL_t plaintextNBytes; /* Ensure input is not too short. */ if (CiphertextNBytes < PS_CHACHA20POLY1305_IETF_ABYTES) { return PS_ARG_FAIL; } plaintextNBytes = CiphertextNBytes - PS_CHACHA20POLY1305_IETF_ABYTES; return psChacha20Poly1305IetfDecryptDetached( Context_p, Ciphertext_p, plaintextNBytes, Iv_p, Aad_p, AadNBytes, Ciphertext_p + plaintextNBytes, Plaintext_p); #endif }
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; }
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 AES128GCM: case AES192GCM: case AES256GCM: 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; }