Reworking bssl_crypto: support AES-GCM-SIV open_gather. On x86-64, the Rust tests notice that open_gather wasn't implemented for AES-GCM-SIV when the assembly code is used. Fix that. Change-Id: I7de9d009922bcc0ed7e3e2f8a7a3cfb671893d63 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65187 Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/cipher_extra/asm/aes128gcmsiv-x86_64.pl b/crypto/cipher_extra/asm/aes128gcmsiv-x86_64.pl index e044259..6241237 100644 --- a/crypto/cipher_extra/asm/aes128gcmsiv-x86_64.pl +++ b/crypto/cipher_extra/asm/aes128gcmsiv-x86_64.pl
@@ -1257,14 +1257,15 @@ .L${labelPrefix}_dec_start: vzeroupper vmovdqa ($POL), $T + # The claimed tag is provided after the current calculated tag value. + # CTRBLKs is made from it. + vmovdqu 16($POL), $CTR + vpor OR_MASK(%rip), $CTR, $CTR # CTR = [1]TAG[126...32][00..00] movq $POL, $secureBuffer leaq 32($secureBuffer), $secureBuffer leaq 32($Htbl), $Htbl - # make CTRBLKs from given tag. - vmovdqu ($CT,$LEN), $CTR - vpor OR_MASK(%rip), $CTR, $CTR # CTR = [1]TAG[126...32][00..00] andq \$~15, $LEN # If less then 6 blocks, make singles
diff --git a/crypto/cipher_extra/e_aesgcmsiv.c b/crypto/cipher_extra/e_aesgcmsiv.c index 15601e1..63deb05 100644 --- a/crypto/cipher_extra/e_aesgcmsiv.c +++ b/crypto/cipher_extra/e_aesgcmsiv.c
@@ -126,16 +126,16 @@ uint8_t in_out_poly[16]); // aes128gcmsiv_dec decrypts |in_len| & ~15 bytes from |out| and writes them to -// |in|. (The full value of |in_len| is still used to find the authentication -// tag appended to the ciphertext, however, so must not be pre-masked.) +// |in|. |in| and |out| may be equal, but must not otherwise alias. // -// |in| and |out| may be equal, but must not otherwise overlap. +// |in_out_calculated_tag_and_scratch|, on entry, must contain: +// 1. The current value of the calculated tag, which will be updated during +// decryption and written back to the beginning of this buffer on exit. +// 2. The claimed tag, which is needed to derive counter values. // -// While decrypting, it updates the POLYVAL value found at the beginning of -// |in_out_calculated_tag_and_scratch| and writes the updated value back before -// return. During executation, it may use the whole of this space for other -// purposes. In order to decrypt and update the POLYVAL value, it uses the -// expanded key from |key| and the table of powers in |htable|. +// While decrypting, the whole of |in_out_calculated_tag_and_scratch| may be +// used for other purposes. In order to decrypt and update the POLYVAL value, it +// uses the expanded key from |key| and the table of powers in |htable|. extern void aes128gcmsiv_dec(const uint8_t *in, uint8_t *out, uint8_t in_out_calculated_tag_and_scratch[16 * 8], const uint8_t htable[16 * 6], @@ -393,14 +393,10 @@ return 1; } -// TODO(martinkr): Add aead_aes_gcm_siv_asm_open_gather. N.B. aes128gcmsiv_dec -// expects ciphertext and tag in a contiguous buffer. - -static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out, - size_t *out_len, size_t max_out_len, - const uint8_t *nonce, size_t nonce_len, - const uint8_t *in, size_t in_len, - const uint8_t *ad, size_t ad_len) { +static int aead_aes_gcm_siv_asm_open_gather( + const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce, + size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag, + size_t in_tag_len, const uint8_t *ad, size_t ad_len) { const uint64_t ad_len_64 = ad_len; if (ad_len_64 >= (UINT64_C(1) << 61)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); @@ -408,8 +404,8 @@ } const uint64_t in_len_64 = in_len; - if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN || - in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) { + if (in_len_64 > UINT64_C(1) << 36 || + in_tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } @@ -420,13 +416,6 @@ } const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx); - const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN; - const uint8_t *const given_tag = in + plaintext_len; - - if (max_out_len < plaintext_len) { - OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); - return 0; - } alignas(16) uint64_t record_auth_key[2]; alignas(16) uint64_t record_enc_key[4]; @@ -459,27 +448,27 @@ alignas(16) uint8_t htable[16 * 6]; aesgcmsiv_htable6_init(htable, (const uint8_t *)record_auth_key); + // aes[128|256]gcmsiv_dec needs access to the claimed tag. So it's put into + // its scratch space. + memcpy(calculated_tag + 16, in_tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN); if (gcm_siv_ctx->is_128_bit) { - aes128gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key, - plaintext_len); + aes128gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key, in_len); } else { - aes256gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key, - plaintext_len); + aes256gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key, in_len); } - if (plaintext_len & 15) { + if (in_len & 15) { aead_aes_gcm_siv_asm_crypt_last_block(gcm_siv_ctx->is_128_bit, out, in, - plaintext_len, given_tag, - &expanded_key); + in_len, in_tag, &expanded_key); OPENSSL_memset(scratch, 0, sizeof(scratch)); - OPENSSL_memcpy(scratch, out + (plaintext_len & ~15), plaintext_len & 15); + OPENSSL_memcpy(scratch, out + (in_len & ~15), in_len & 15); aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key, scratch, 1); } uint8_t length_block[16]; CRYPTO_store_u64_le(length_block, ad_len * 8); - CRYPTO_store_u64_le(length_block + 8, plaintext_len * 8); + CRYPTO_store_u64_le(length_block + 8, in_len * 8); aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key, length_block, 1); @@ -495,13 +484,12 @@ aes256gcmsiv_ecb_enc_block(calculated_tag, calculated_tag, &expanded_key); } - if (CRYPTO_memcmp(calculated_tag, given_tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN) != + if (CRYPTO_memcmp(calculated_tag, in_tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN) != 0) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } - *out_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN; return 1; } @@ -515,9 +503,9 @@ aead_aes_gcm_siv_asm_init, NULL /* init_with_direction */, aead_aes_gcm_siv_asm_cleanup, - aead_aes_gcm_siv_asm_open, + NULL /* open */, aead_aes_gcm_siv_asm_seal_scatter, - NULL /* open_gather */, + aead_aes_gcm_siv_asm_open_gather, NULL /* get_iv */, NULL /* tag_len */, }; @@ -532,9 +520,9 @@ aead_aes_gcm_siv_asm_init, NULL /* init_with_direction */, aead_aes_gcm_siv_asm_cleanup, - aead_aes_gcm_siv_asm_open, + NULL /* open */, aead_aes_gcm_siv_asm_seal_scatter, - NULL /* open_gather */, + aead_aes_gcm_siv_asm_open_gather, NULL /* get_iv */, NULL /* tag_len */, };