Add missing nonce_len check to aead_aes_gcm_siv_asm_open.
Test invalid nonce lengths more thoroughly to cover this case on all our AEADs. Thanks to Guido Vranken for catching this! In doing so, this also reveals we have a ton of redundant error codes (https://crbug.com/boringssl/269). I'll tidy that up in a separate change as it may require some changes to code in Android. For now, this change uses CIPHER_R_UNSUPPORTED_NONCE_SIZE just to be consistent with the rest of that file. Bug: 268 Change-Id: I0a479000ec3005ee55c828eaa92c8302b4625847 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/35545 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
4a136ea005
commit
31ef16ac2d
@ -42,56 +42,58 @@ struct KnownAEAD {
|
||||
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
|
||||
// lengths.
|
||||
bool truncated_tags;
|
||||
// variable_nonce is true if the AEAD supports a variable nonce length.
|
||||
bool variable_nonce;
|
||||
// ad_len, if non-zero, is the required length of the AD.
|
||||
size_t ad_len;
|
||||
};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{"AES_128_GCM", EVP_aead_aes_128_gcm, "aes_128_gcm_tests.txt", false, true,
|
||||
0},
|
||||
true, 0},
|
||||
{"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
|
||||
false, true, 0},
|
||||
false, true, true, 0},
|
||||
{"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true,
|
||||
0},
|
||||
true, 0},
|
||||
{"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
|
||||
false, true, 0},
|
||||
false, true, true, 0},
|
||||
{"AES_128_GCM_SIV", EVP_aead_aes_128_gcm_siv, "aes_128_gcm_siv_tests.txt",
|
||||
false, false, 0},
|
||||
false, false, false, 0},
|
||||
{"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
|
||||
false, false, 0},
|
||||
false, false, false, 0},
|
||||
{"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
|
||||
"chacha20_poly1305_tests.txt", false, true, 0},
|
||||
"chacha20_poly1305_tests.txt", false, true, false, 0},
|
||||
{"XChaCha20Poly1305", EVP_aead_xchacha20_poly1305,
|
||||
"xchacha20_poly1305_tests.txt", false, true, 0},
|
||||
"xchacha20_poly1305_tests.txt", false, true, false, 0},
|
||||
{"AES_128_CBC_SHA1_TLS", EVP_aead_aes_128_cbc_sha1_tls,
|
||||
"aes_128_cbc_sha1_tls_tests.txt", true, false, 11},
|
||||
"aes_128_cbc_sha1_tls_tests.txt", true, false, false, 11},
|
||||
{"AES_128_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_aes_128_cbc_sha1_tls_implicit_iv,
|
||||
"aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
|
||||
"aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
|
||||
{"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
|
||||
"aes_128_cbc_sha256_tls_tests.txt", true, false, 11},
|
||||
"aes_128_cbc_sha256_tls_tests.txt", true, false, false, 11},
|
||||
{"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
|
||||
"aes_256_cbc_sha1_tls_tests.txt", true, false, 11},
|
||||
"aes_256_cbc_sha1_tls_tests.txt", true, false, false, 11},
|
||||
{"AES_256_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_aes_256_cbc_sha1_tls_implicit_iv,
|
||||
"aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
|
||||
"aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
|
||||
{"AES_256_CBC_SHA256_TLS", EVP_aead_aes_256_cbc_sha256_tls,
|
||||
"aes_256_cbc_sha256_tls_tests.txt", true, false, 11},
|
||||
"aes_256_cbc_sha256_tls_tests.txt", true, false, false, 11},
|
||||
{"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
|
||||
"aes_256_cbc_sha384_tls_tests.txt", true, false, 11},
|
||||
"aes_256_cbc_sha384_tls_tests.txt", true, false, false, 11},
|
||||
{"DES_EDE3_CBC_SHA1_TLS", EVP_aead_des_ede3_cbc_sha1_tls,
|
||||
"des_ede3_cbc_sha1_tls_tests.txt", true, false, 11},
|
||||
"des_ede3_cbc_sha1_tls_tests.txt", true, false, false, 11},
|
||||
{"DES_EDE3_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv,
|
||||
"des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
|
||||
"des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
|
||||
{"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256,
|
||||
"aes_128_ctr_hmac_sha256.txt", false, true, 0},
|
||||
"aes_128_ctr_hmac_sha256.txt", false, true, false, 0},
|
||||
{"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
|
||||
"aes_256_ctr_hmac_sha256.txt", false, true, 0},
|
||||
"aes_256_ctr_hmac_sha256.txt", false, true, false, 0},
|
||||
{"AES_128_CCM_BLUETOOTH", EVP_aead_aes_128_ccm_bluetooth,
|
||||
"aes_128_ccm_bluetooth_tests.txt", false, false, 0},
|
||||
"aes_128_ccm_bluetooth_tests.txt", false, false, false, 0},
|
||||
{"AES_128_CCM_BLUETOOTH_8", EVP_aead_aes_128_ccm_bluetooth_8,
|
||||
"aes_128_ccm_bluetooth_8_tests.txt", false, false, 0},
|
||||
"aes_128_ccm_bluetooth_8_tests.txt", false, false, false, 0},
|
||||
};
|
||||
|
||||
class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
|
||||
@ -605,50 +607,59 @@ TEST_P(PerAEADTest, Overflow) {
|
||||
// as the input.)
|
||||
}
|
||||
|
||||
// Test that EVP_aead_aes_128_gcm and EVP_aead_aes_256_gcm reject empty nonces.
|
||||
// AES-GCM is not defined for those.
|
||||
TEST(AEADTest, AESGCMEmptyNonce) {
|
||||
static const uint8_t kZeros[32] = {0};
|
||||
TEST_P(PerAEADTest, InvalidNonceLength) {
|
||||
size_t valid_nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
std::vector<size_t> nonce_lens;
|
||||
if (valid_nonce_len != 0) {
|
||||
// Other than the implicit IV TLS "AEAD"s, none of our AEADs allow empty
|
||||
// nonces. In particular, although AES-GCM was incorrectly specified with
|
||||
// variable-length nonces, it does not allow the empty nonce.
|
||||
nonce_lens.push_back(0);
|
||||
}
|
||||
if (!GetParam().variable_nonce) {
|
||||
nonce_lens.push_back(valid_nonce_len + 1);
|
||||
if (valid_nonce_len != 0) {
|
||||
nonce_lens.push_back(valid_nonce_len - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Test AES-128-GCM.
|
||||
uint8_t buf[16];
|
||||
size_t len;
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), kZeros, 16,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
static const uint8_t kZeros[EVP_AEAD_MAX_KEY_LENGTH] = {0};
|
||||
const size_t ad_len = GetParam().ad_len != 0 ? GetParam().ad_len : 16;
|
||||
ASSERT_LE(ad_len, sizeof(kZeros));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
for (size_t nonce_len : nonce_lens) {
|
||||
SCOPED_TRACE(nonce_len);
|
||||
uint8_t buf[256];
|
||||
size_t len;
|
||||
std::vector<uint8_t> nonce(nonce_len);
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), kZeros, EVP_AEAD_key_length(aead()),
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_seal));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nonce.data(), nonce.size(), nullptr /* in */,
|
||||
0, kZeros /* ad */, ad_len));
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
// TODO(davidben): Merge these errors. https://crbug.com/boringssl/129.
|
||||
if (ERR_GET_REASON(err) != CIPHER_R_UNSUPPORTED_NONCE_SIZE) {
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
}
|
||||
|
||||
// Test AES-256-GCM.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(), kZeros, 32,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), kZeros, EVP_AEAD_key_length(aead()),
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_open));
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nonce.data(), nonce.size(), kZeros /* in */,
|
||||
sizeof(kZeros), kZeros /* ad */, ad_len));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
if (ERR_GET_REASON(err) != CIPHER_R_UNSUPPORTED_NONCE_SIZE) {
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AEADTest, AESCCMLargeAD) {
|
||||
|
@ -426,6 +426,11 @@ static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user