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>
This commit is contained in:
committed by
Adam Langley
parent
321f3a70be
commit
e5d6b2fbb4
@@ -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
|
||||
|
||||
@@ -126,16 +126,16 @@ extern void aesgcmsiv_htable_polyval(const uint8_t htable[16 * 8],
|
||||
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 @@ static int aead_aes_gcm_siv_asm_seal_scatter(
|
||||
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 @@ static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
}
|
||||
|
||||
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 @@ static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
}
|
||||
|
||||
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 @@ static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
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 @@ static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
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 @@ static const EVP_AEAD aead_aes_128_gcm_siv_asm = {
|
||||
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 @@ static const EVP_AEAD aead_aes_256_gcm_siv_asm = {
|
||||
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 */,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user