Require only that the nonce be strictly monotonic in TLS's AES-GCM

Previously we required that the calls to TLS's AES-GCM use an
incrementing nonce. This change relaxes that requirement so that nonces
need only be strictly monotonic (i.e. values can now be skipped). This
still meets the uniqueness requirements of a nonce.

Change-Id: Ib649a58bb93bf4dc0e081de8a5971daefffe9c70
Reviewed-on: https://boringssl-review.googlesource.com/25384
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Adam Langley 2018-01-25 15:43:48 -08:00 committed by CQ bot account: commit-bot@chromium.org
parent 449a9e6a9e
commit 0ab86cf6f9

View File

@ -1148,7 +1148,7 @@ struct aead_aes_gcm_ctx {
struct aead_aes_gcm_tls12_ctx { struct aead_aes_gcm_tls12_ctx {
struct aead_aes_gcm_ctx gcm_ctx; struct aead_aes_gcm_ctx gcm_ctx;
uint64_t counter; uint64_t min_next_nonce;
}; };
static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx, static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx,
@ -1349,7 +1349,7 @@ static int aead_aes_gcm_tls12_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
return 0; return 0;
} }
gcm_ctx->counter = 0; gcm_ctx->min_next_nonce = 0;
size_t actual_tag_len; size_t actual_tag_len;
if (!aead_aes_gcm_init_impl(&gcm_ctx->gcm_ctx, &actual_tag_len, key, key_len, if (!aead_aes_gcm_init_impl(&gcm_ctx->gcm_ctx, &actual_tag_len, key, key_len,
@ -1373,23 +1373,23 @@ static int aead_aes_gcm_tls12_seal_scatter(
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in, size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) { size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
struct aead_aes_gcm_tls12_ctx *gcm_ctx = ctx->aead_state; struct aead_aes_gcm_tls12_ctx *gcm_ctx = ctx->aead_state;
if (gcm_ctx->counter == UINT64_MAX) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
return 0;
}
if (nonce_len != 12) { if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0; return 0;
} }
const uint64_t be_counter = CRYPTO_bswap8(gcm_ctx->counter); // The given nonces must be strictly monotonically increasing.
if (OPENSSL_memcmp((uint8_t *)&be_counter, nonce + nonce_len - 8, 8) != 0) { uint64_t given_counter;
OPENSSL_memcpy(&given_counter, nonce + nonce_len - sizeof(given_counter),
sizeof(given_counter));
given_counter = CRYPTO_bswap8(given_counter);
if (given_counter == UINT64_MAX ||
given_counter < gcm_ctx->min_next_nonce) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE); OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
return 0; return 0;
} }
gcm_ctx->counter++; gcm_ctx->min_next_nonce = given_counter + 1;
return aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len, return aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len,
max_out_tag_len, nonce, nonce_len, in, max_out_tag_len, nonce, nonce_len, in,