diff options
author | Robert Sloan <varomodt@google.com> | 2019-04-17 13:17:34 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-04-17 13:17:34 -0700 |
commit | 2669718082106ff65c13a73fc6f058e0713167b3 (patch) | |
tree | 5bfdfa9db8642d577ef86e52257844b934be87c4 /src/crypto | |
parent | 62c374e4170390cb3ca19cef283a8dc33c95211a (diff) | |
parent | f63bd1f440905963647c68a896db0c85e8914d11 (diff) | |
download | boringssl-2669718082106ff65c13a73fc6f058e0713167b3.tar.gz |
external/boringssl: Sync to c9827e073f64e353c4891ecc2c73721882543ee0.
am: f63bd1f440
Change-Id: I3b6a5db1dab391cd490dd40dfba716bd48359b39
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/base64/base64_test.cc | 2 | ||||
-rw-r--r-- | src/crypto/bio/bio_test.cc | 4 | ||||
-rw-r--r-- | src/crypto/bytestring/cbb.c | 17 | ||||
-rw-r--r-- | src/crypto/cipher_extra/aead_test.cc | 143 | ||||
-rw-r--r-- | src/crypto/cipher_extra/cipher_test.cc | 52 | ||||
-rw-r--r-- | src/crypto/cipher_extra/e_aesgcmsiv.c | 5 | ||||
-rw-r--r-- | src/crypto/digest_extra/digest_test.cc | 22 | ||||
-rw-r--r-- | src/crypto/evp/evp_test.cc | 142 | ||||
-rw-r--r-- | src/crypto/evp/evp_tests.txt | 11 | ||||
-rw-r--r-- | src/crypto/evp/p_rsa.c | 1 | ||||
-rw-r--r-- | src/crypto/fipsmodule/aes/aes.c | 6 | ||||
-rw-r--r-- | src/crypto/fipsmodule/aes/aes_test.cc | 7 | ||||
-rw-r--r-- | src/crypto/fipsmodule/cipher/e_aes.c | 9 | ||||
-rw-r--r-- | src/crypto/fipsmodule/digest/digest.c | 39 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/ec_test.cc | 4 | ||||
-rw-r--r-- | src/crypto/rsa_extra/rsa_test.cc | 3 |
16 files changed, 290 insertions, 177 deletions
diff --git a/src/crypto/base64/base64_test.cc b/src/crypto/base64/base64_test.cc index 28b5c8e0..9122deeb 100644 --- a/src/crypto/base64/base64_test.cc +++ b/src/crypto/base64/base64_test.cc @@ -105,7 +105,7 @@ static const TestVector kTestVectors[] = { class Base64Test : public testing::TestWithParam<TestVector> {}; -INSTANTIATE_TEST_CASE_P(, Base64Test, testing::ValuesIn(kTestVectors)); +INSTANTIATE_TEST_SUITE_P(, Base64Test, testing::ValuesIn(kTestVectors)); // RemoveNewlines returns a copy of |in| with all '\n' characters removed. static std::string RemoveNewlines(const char *in) { diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc index 8479c8e8..797a7337 100644 --- a/src/crypto/bio/bio_test.cc +++ b/src/crypto/bio/bio_test.cc @@ -220,7 +220,7 @@ TEST_P(BIOASN1Test, ReadASN1) { } } -INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams)); +INSTANTIATE_TEST_SUITE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams)); // Run through the tests twice, swapping |bio1| and |bio2|, for symmetry. class BIOPairTest : public testing::TestWithParam<bool> {}; @@ -322,4 +322,4 @@ TEST_P(BIOPairTest, TestPair) { EXPECT_EQ(Bytes("12345"), Bytes(buf, 5)); } -INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true)); +INSTANTIATE_TEST_SUITE_P(, BIOPairTest, testing::Values(false, true)); diff --git a/src/crypto/bytestring/cbb.c b/src/crypto/bytestring/cbb.c index 7998a48e..1ddc73c6 100644 --- a/src/crypto/bytestring/cbb.c +++ b/src/crypto/bytestring/cbb.c @@ -44,7 +44,7 @@ static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { base->error = 0; cbb->base = base; - cbb->is_top_level = 1; + cbb->is_child = 0; return 1; } @@ -76,11 +76,14 @@ int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { } void CBB_cleanup(CBB *cbb) { - if (cbb->base) { - // Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They - // are implicitly discarded when the parent is flushed or cleaned up. - assert(cbb->is_top_level); + // Child |CBB|s are non-owning. They are implicitly discarded and should not + // be used with |CBB_cleanup| or |ScopedCBB|. + assert(!cbb->is_child); + if (cbb->is_child) { + return; + } + if (cbb->base) { if (cbb->base->can_resize) { OPENSSL_free(cbb->base->buf); } @@ -169,7 +172,7 @@ static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint64_t v, } int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { - if (!cbb->is_top_level) { + if (cbb->is_child) { return 0; } @@ -310,6 +313,7 @@ static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, OPENSSL_memset(prefix_bytes, 0, len_len); OPENSSL_memset(out_contents, 0, sizeof(CBB)); out_contents->base = cbb->base; + out_contents->is_child = 1; cbb->child = out_contents; cbb->child->offset = offset; cbb->child->pending_len_len = len_len; @@ -381,6 +385,7 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) { OPENSSL_memset(out_contents, 0, sizeof(CBB)); out_contents->base = cbb->base; + out_contents->is_child = 1; cbb->child = out_contents; cbb->child->offset = offset; cbb->child->pending_len_len = 1; diff --git a/src/crypto/cipher_extra/aead_test.cc b/src/crypto/cipher_extra/aead_test.cc index fff7d439..25924bd5 100644 --- a/src/crypto/cipher_extra/aead_test.cc +++ b/src/crypto/cipher_extra/aead_test.cc @@ -42,58 +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}, -#if !defined(OPENSSL_SMALL) + 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}, -#endif + 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> { @@ -101,9 +101,9 @@ class PerAEADTest : public testing::TestWithParam<KnownAEAD> { const EVP_AEAD *aead() { return GetParam().func(); } }; -INSTANTIATE_TEST_CASE_P(, PerAEADTest, testing::ValuesIn(kAEADs), - [](const testing::TestParamInfo<KnownAEAD> ¶ms) - -> std::string { return params.param.name; }); +INSTANTIATE_TEST_SUITE_P(, PerAEADTest, testing::ValuesIn(kAEADs), + [](const testing::TestParamInfo<KnownAEAD> ¶ms) + -> std::string { return params.param.name; }); // Tests an AEAD against a series of test vectors from a file, using the // FileTest format. As an example, here's a valid test case: @@ -607,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)); - - 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)); - - // 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)); + 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_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)); + } - 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) { diff --git a/src/crypto/cipher_extra/cipher_test.cc b/src/crypto/cipher_extra/cipher_test.cc index 62ef9396..0a96bf39 100644 --- a/src/crypto/cipher_extra/cipher_test.cc +++ b/src/crypto/cipher_extra/cipher_test.cc @@ -150,7 +150,8 @@ static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out, } static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt, - size_t chunk_size, const std::vector<uint8_t> &key, + bool copy, size_t chunk_size, + const std::vector<uint8_t> &key, const std::vector<uint8_t> &iv, const std::vector<uint8_t> &plaintext, const std::vector<uint8_t> &ciphertext, @@ -167,45 +168,52 @@ static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt, bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE; - bssl::ScopedEVP_CIPHER_CTX ctx; - ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr, - encrypt ? 1 : 0)); + bssl::ScopedEVP_CIPHER_CTX ctx1; + ASSERT_TRUE(EVP_CipherInit_ex(ctx1.get(), cipher, nullptr, nullptr, nullptr, + encrypt ? 1 : 0)); if (t->HasAttribute("IV")) { if (is_aead) { - ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_IVLEN, + ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx1.get(), EVP_CTRL_AEAD_SET_IVLEN, iv.size(), 0)); } else { - ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get())); + ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx1.get())); } } + + bssl::ScopedEVP_CIPHER_CTX ctx2; + EVP_CIPHER_CTX *ctx = ctx1.get(); + if (copy) { + ASSERT_TRUE(EVP_CIPHER_CTX_copy(ctx2.get(), ctx1.get())); + ctx = ctx2.get(); + } + if (is_aead && !encrypt) { - ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_TAG, - tag.size(), + ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size(), const_cast<uint8_t *>(tag.data()))); } // The ciphers are run with no padding. For each of the ciphers we test, the // output size matches the input size. ASSERT_EQ(in->size(), out->size()); - ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size())); - ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), - iv.data(), -1)); + ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx, key.size())); + ASSERT_TRUE( + EVP_CipherInit_ex(ctx, nullptr, nullptr, key.data(), iv.data(), -1)); // Note: the deprecated |EVP_CIPHER|-based AEAD API is sensitive to whether // parameters are NULL, so it is important to skip the |in| and |aad| // |EVP_CipherUpdate| calls when empty. if (!aad.empty()) { int unused; ASSERT_TRUE( - EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(), aad.size())); + EVP_CipherUpdate(ctx, nullptr, &unused, aad.data(), aad.size())); } - ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0)); + ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx, 0)); std::vector<uint8_t> result; - ASSERT_TRUE(DoCipher(ctx.get(), &result, *in, chunk_size)); + ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size)); EXPECT_EQ(Bytes(*out), Bytes(result)); if (encrypt && is_aead) { uint8_t rtag[16]; ASSERT_LE(tag.size(), sizeof(rtag)); - ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG, - tag.size(), rtag)); + ASSERT_TRUE( + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag.size(), rtag)); EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size())); } } @@ -252,14 +260,18 @@ static void TestCipher(FileTest *t) { // By default, both directions are run, unless overridden by the operation. if (operation != kDecrypt) { SCOPED_TRACE("encrypt"); - TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv, - plaintext, ciphertext, aad, tag); + TestOperation(t, cipher, true /* encrypt */, false /* no copy */, + chunk_size, key, iv, plaintext, ciphertext, aad, tag); + TestOperation(t, cipher, true /* encrypt */, true /* copy */, chunk_size, + key, iv, plaintext, ciphertext, aad, tag); } if (operation != kEncrypt) { SCOPED_TRACE("decrypt"); - TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv, - plaintext, ciphertext, aad, tag); + TestOperation(t, cipher, false /* decrypt */, false /* no copy */, + chunk_size, key, iv, plaintext, ciphertext, aad, tag); + TestOperation(t, cipher, false /* decrypt */, true /* copy */, chunk_size, + key, iv, plaintext, ciphertext, aad, tag); } } } diff --git a/src/crypto/cipher_extra/e_aesgcmsiv.c b/src/crypto/cipher_extra/e_aesgcmsiv.c index 71a71fac..64febae4 100644 --- a/src/crypto/cipher_extra/e_aesgcmsiv.c +++ b/src/crypto/cipher_extra/e_aesgcmsiv.c @@ -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; diff --git a/src/crypto/digest_extra/digest_test.cc b/src/crypto/digest_extra/digest_test.cc index de2e9d13..7d07c04d 100644 --- a/src/crypto/digest_extra/digest_test.cc +++ b/src/crypto/digest_extra/digest_test.cc @@ -198,6 +198,28 @@ static void TestDigest(const TestVector *test) { ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len)); CompareDigest(test, digest.get(), digest_len); + // Make a copy of the digest in the initial state. + ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)); + bssl::ScopedEVP_MD_CTX copy; + ASSERT_TRUE(EVP_MD_CTX_copy_ex(copy.get(), ctx.get())); + for (size_t i = 0; i < test->repeat; i++) { + ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input))); + } + ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len)); + CompareDigest(test, digest.get(), digest_len); + + // Make a copy of the digest with half the input provided. + size_t half = strlen(test->input) / 2; + ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), test->input, half)); + ASSERT_TRUE(EVP_MD_CTX_copy_ex(copy.get(), ctx.get())); + ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input + half, + strlen(test->input) - half)); + for (size_t i = 1; i < test->repeat; i++) { + ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input))); + } + ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len)); + CompareDigest(test, digest.get(), digest_len); + // Test the one-shot function. if (test->md.one_shot_func && test->repeat == 1) { uint8_t *out = test->md.one_shot_func((const uint8_t *)test->input, diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc index 6571c302..4d742920 100644 --- a/src/crypto/evp/evp_test.cc +++ b/src/crypto/evp/evp_test.cc @@ -297,16 +297,19 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { } if (md_op_init) { - bssl::ScopedEVP_MD_CTX ctx; + bssl::ScopedEVP_MD_CTX ctx, copy; EVP_PKEY_CTX *pctx; if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) || - !SetupContext(t, pctx)) { + !SetupContext(t, pctx) || + !EVP_MD_CTX_copy_ex(copy.get(), ctx.get())) { return false; } if (is_verify) { - return !!EVP_DigestVerify(ctx.get(), output.data(), output.size(), - input.data(), input.size()); + return EVP_DigestVerify(ctx.get(), output.data(), output.size(), + input.data(), input.size()) && + EVP_DigestVerify(copy.get(), output.data(), output.size(), + input.data(), input.size()); } size_t len; @@ -321,6 +324,21 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { } actual.resize(len); EXPECT_EQ(Bytes(output), Bytes(actual)); + + // Repeat the test with |copy|, to check |EVP_MD_CTX_copy_ex| duplicated + // everything. + if (!EVP_DigestSign(copy.get(), nullptr, &len, input.data(), + input.size())) { + return false; + } + actual.resize(len); + if (!EVP_DigestSign(copy.get(), actual.data(), &len, input.data(), + input.size()) || + !t->GetBytes(&output, "Output")) { + return false; + } + actual.resize(len); + EXPECT_EQ(Bytes(output), Bytes(actual)); return true; } @@ -333,72 +351,78 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { return false; } - if (is_verify) { - return !!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), - input.data(), input.size()); - } - - size_t len; - if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) { - return false; - } - actual.resize(len); - if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) { + bssl::UniquePtr<EVP_PKEY_CTX> copy(EVP_PKEY_CTX_dup(ctx.get())); + if (!copy) { return false; } - // Encryption is non-deterministic, so we check by decrypting. - if (t->HasAttribute("CheckDecrypt")) { - size_t plaintext_len; - ctx.reset(EVP_PKEY_CTX_new(key, nullptr)); - if (!ctx || - !EVP_PKEY_decrypt_init(ctx.get()) || - (digest != nullptr && - !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || - !SetupContext(t, ctx.get()) || - !EVP_PKEY_decrypt(ctx.get(), nullptr, &plaintext_len, actual.data(), - actual.size())) { - return false; - } - output.resize(plaintext_len); - if (!EVP_PKEY_decrypt(ctx.get(), output.data(), &plaintext_len, - actual.data(), actual.size())) { - ADD_FAILURE() << "Could not decrypt result."; - return false; - } - output.resize(plaintext_len); - EXPECT_EQ(Bytes(input), Bytes(output)) << "Decrypted result mismatch."; - return true; + if (is_verify) { + return EVP_PKEY_verify(ctx.get(), output.data(), output.size(), + input.data(), input.size()) && + EVP_PKEY_verify(copy.get(), output.data(), output.size(), + input.data(), input.size()); } - // Some signature schemes are non-deterministic, so we check by verifying. - if (t->HasAttribute("CheckVerify")) { - ctx.reset(EVP_PKEY_CTX_new(key, nullptr)); - if (!ctx || - !EVP_PKEY_verify_init(ctx.get()) || - (digest != nullptr && - !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || - !SetupContext(t, ctx.get())) { + for (EVP_PKEY_CTX *pctx : {ctx.get(), copy.get()}) { + size_t len; + if (!key_op(pctx, nullptr, &len, input.data(), input.size())) { return false; } - if (t->HasAttribute("VerifyPSSSaltLength") && - !EVP_PKEY_CTX_set_rsa_pss_saltlen( - ctx.get(), - atoi(t->GetAttributeOrDie("VerifyPSSSaltLength").c_str()))) { + actual.resize(len); + if (!key_op(pctx, actual.data(), &len, input.data(), input.size())) { return false; } - EXPECT_TRUE(EVP_PKEY_verify(ctx.get(), actual.data(), actual.size(), - input.data(), input.size())) - << "Could not verify result."; - return true; - } - // By default, check by comparing the result against Output. - if (!t->GetBytes(&output, "Output")) { - return false; + if (t->HasAttribute("CheckDecrypt")) { + // Encryption is non-deterministic, so we check by decrypting. + size_t plaintext_len; + bssl::UniquePtr<EVP_PKEY_CTX> decrypt_ctx(EVP_PKEY_CTX_new(key, nullptr)); + if (!decrypt_ctx || + !EVP_PKEY_decrypt_init(decrypt_ctx.get()) || + (digest != nullptr && + !EVP_PKEY_CTX_set_signature_md(decrypt_ctx.get(), digest)) || + !SetupContext(t, decrypt_ctx.get()) || + !EVP_PKEY_decrypt(decrypt_ctx.get(), nullptr, &plaintext_len, + actual.data(), actual.size())) { + return false; + } + output.resize(plaintext_len); + if (!EVP_PKEY_decrypt(decrypt_ctx.get(), output.data(), &plaintext_len, + actual.data(), actual.size())) { + ADD_FAILURE() << "Could not decrypt result."; + return false; + } + output.resize(plaintext_len); + EXPECT_EQ(Bytes(input), Bytes(output)) << "Decrypted result mismatch."; + } else if (t->HasAttribute("CheckVerify")) { + // Some signature schemes are non-deterministic, so we check by verifying. + bssl::UniquePtr<EVP_PKEY_CTX> verify_ctx(EVP_PKEY_CTX_new(key, nullptr)); + if (!verify_ctx || + !EVP_PKEY_verify_init(verify_ctx.get()) || + (digest != nullptr && + !EVP_PKEY_CTX_set_signature_md(verify_ctx.get(), digest)) || + !SetupContext(t, verify_ctx.get())) { + return false; + } + if (t->HasAttribute("VerifyPSSSaltLength")) { + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen( + verify_ctx.get(), + atoi(t->GetAttributeOrDie("VerifyPSSSaltLength").c_str()))) { + return false; + } + } + EXPECT_TRUE(EVP_PKEY_verify(verify_ctx.get(), actual.data(), + actual.size(), input.data(), input.size())) + << "Could not verify result."; + } else { + // By default, check by comparing the result against Output. + if (!t->GetBytes(&output, "Output")) { + return false; + } + actual.resize(len); + EXPECT_EQ(Bytes(output), Bytes(actual)); + } } - actual.resize(len); - EXPECT_EQ(Bytes(output), Bytes(actual)); return true; } diff --git a/src/crypto/evp/evp_tests.txt b/src/crypto/evp/evp_tests.txt index ff08ee76..9dbe1cb7 100644 --- a/src/crypto/evp/evp_tests.txt +++ b/src/crypto/evp/evp_tests.txt @@ -274,6 +274,17 @@ Digest = SHA256 Input = "0123456789ABCDEF0123456789ABCDEF" CheckVerify +# Check a salt length with a non-standard digest length, to verify things are +# not just working due to defaults. (The current default is a maximum salt +# length, but the ecosystem has converged on matching the digest length, so we +# may change this in the future.) +Sign = RSA-2048 +RSAPadding = PSS +PSSSaltLength = 42 +Digest = SHA256 +Input = "0123456789ABCDEF0123456789ABCDEF" +CheckVerify + # Auto-detected salt length Verify = RSA-2048-SPKI RSAPadding = PSS diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c index eb59901e..865b36af 100644 --- a/src/crypto/evp/p_rsa.c +++ b/src/crypto/evp/p_rsa.c @@ -132,6 +132,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { dctx->pad_mode = sctx->pad_mode; dctx->md = sctx->md; dctx->mgf1md = sctx->mgf1md; + dctx->saltlen = sctx->saltlen; if (sctx->oaep_label) { OPENSSL_free(dctx->oaep_label); dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen); diff --git a/src/crypto/fipsmodule/aes/aes.c b/src/crypto/fipsmodule/aes/aes.c index 8a1ca31d..48d60eeb 100644 --- a/src/crypto/fipsmodule/aes/aes.c +++ b/src/crypto/fipsmodule/aes/aes.c @@ -834,6 +834,9 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { } int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { + if (bits != 128 && bits != 192 && bits != 256) { + return -2; + } if (hwaes_capable()) { return aes_hw_set_encrypt_key(key, bits, aeskey); } else if (vpaes_capable()) { @@ -844,6 +847,9 @@ int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { } int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { + if (bits != 128 && bits != 192 && bits != 256) { + return -2; + } if (hwaes_capable()) { return aes_hw_set_decrypt_key(key, bits, aeskey); } else if (vpaes_capable()) { diff --git a/src/crypto/fipsmodule/aes/aes_test.cc b/src/crypto/fipsmodule/aes/aes_test.cc index 2222b63d..1f9a4919 100644 --- a/src/crypto/fipsmodule/aes/aes_test.cc +++ b/src/crypto/fipsmodule/aes/aes_test.cc @@ -189,6 +189,13 @@ TEST(AESTest, WrapBadLengths) { } } +TEST(AESTest, InvalidKeySize) { + static const uint8_t kZero[8] = {0}; + AES_KEY key; + EXPECT_LT(AES_set_encrypt_key(kZero, 42, &key), 0); + EXPECT_LT(AES_set_decrypt_key(kZero, 42, &key), 0); +} + #if defined(SUPPORTS_ABI_TEST) TEST(AESTest, ABI) { for (int bits : {128, 192, 256}) { diff --git a/src/crypto/fipsmodule/cipher/e_aes.c b/src/crypto/fipsmodule/cipher/e_aes.c index dc94166c..1ea012dd 100644 --- a/src/crypto/fipsmodule/cipher/e_aes.c +++ b/src/crypto/fipsmodule/cipher/e_aes.c @@ -456,6 +456,9 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { case EVP_CTRL_COPY: { EVP_CIPHER_CTX *out = ptr; EVP_AES_GCM_CTX *gctx_out = aes_gcm_from_cipher_ctx(out); + // |EVP_CIPHER_CTX_copy| copies this generically, but we must redo it in + // case |out->cipher_data| and |in->cipher_data| are differently aligned. + OPENSSL_memcpy(gctx_out, gctx, sizeof(EVP_AES_GCM_CTX)); if (gctx->iv == c->iv) { gctx_out->iv = out->iv; } else { @@ -590,7 +593,7 @@ DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_gcm_generic) { out->key_len = 16; out->iv_len = 12; out->ctx_size = sizeof(EVP_AES_GCM_CTX) + EVP_AES_GCM_CTX_PADDING; - out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | + out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER; out->init = aes_gcm_init_key; @@ -658,7 +661,7 @@ DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_gcm_generic) { out->key_len = 24; out->iv_len = 12; out->ctx_size = sizeof(EVP_AES_GCM_CTX) + EVP_AES_GCM_CTX_PADDING; - out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | + out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER; out->init = aes_gcm_init_key; @@ -726,7 +729,7 @@ DEFINE_LOCAL_DATA(EVP_CIPHER, aes_256_gcm_generic) { out->key_len = 32; out->iv_len = 12; out->ctx_size = sizeof(EVP_AES_GCM_CTX) + EVP_AES_GCM_CTX_PADDING; - out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | + out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER; out->init = aes_gcm_init_key; diff --git a/src/crypto/fipsmodule/digest/digest.c b/src/crypto/fipsmodule/digest/digest.c index e49d552d..6705867c 100644 --- a/src/crypto/fipsmodule/digest/digest.c +++ b/src/crypto/fipsmodule/digest/digest.c @@ -116,7 +116,9 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { EVP_MD_CTX_free(ctx); } int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) { - if (in == NULL || in->digest == NULL) { + // |in->digest| may be NULL if this is a signing |EVP_MD_CTX| for, e.g., + // Ed25519 which does not hash with |EVP_MD_CTX|. + if (in == NULL || (in->pctx == NULL && in->digest == NULL)) { OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED); return 0; } @@ -131,29 +133,34 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) { } } - uint8_t *tmp_buf; - if (out->digest != in->digest) { - assert(in->digest->ctx_size != 0); - tmp_buf = OPENSSL_malloc(in->digest->ctx_size); - if (tmp_buf == NULL) { - if (pctx) { - in->pctx_ops->free(pctx); + uint8_t *tmp_buf = NULL; + if (in->digest != NULL) { + if (out->digest != in->digest) { + assert(in->digest->ctx_size != 0); + tmp_buf = OPENSSL_malloc(in->digest->ctx_size); + if (tmp_buf == NULL) { + if (pctx) { + in->pctx_ops->free(pctx); + } + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; } - OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); - return 0; + } else { + // |md_data| will be the correct size in this case. It's removed from + // |out| so that |EVP_MD_CTX_cleanup| doesn't free it, and then it's + // reused. + tmp_buf = out->md_data; + out->md_data = NULL; } - } else { - // |md_data| will be the correct size in this case. It's removed from |out| - // so that |EVP_MD_CTX_cleanup| doesn't free it, and then it's reused. - tmp_buf = out->md_data; - out->md_data = NULL; } EVP_MD_CTX_cleanup(out); out->digest = in->digest; out->md_data = tmp_buf; - OPENSSL_memcpy(out->md_data, in->md_data, in->digest->ctx_size); + if (in->digest != NULL) { + OPENSSL_memcpy(out->md_data, in->md_data, in->digest->ctx_size); + } out->pctx = pctx; out->pctx_ops = in->pctx_ops; assert(out->pctx == NULL || out->pctx_ops != NULL); diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc index dd4c75ae..1219e2b4 100644 --- a/src/crypto/fipsmodule/ec/ec_test.cc +++ b/src/crypto/fipsmodule/ec/ec_test.cc @@ -792,8 +792,8 @@ static std::string CurveToString( return OBJ_nid2sn(params.param.nid); } -INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()), - CurveToString); +INSTANTIATE_TEST_SUITE_P(, ECCurveTest, testing::ValuesIn(AllCurves()), + CurveToString); static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) { std::string curve_name; diff --git a/src/crypto/rsa_extra/rsa_test.cc b/src/crypto/rsa_extra/rsa_test.cc index 9bd47b1b..ed1630d9 100644 --- a/src/crypto/rsa_extra/rsa_test.cc +++ b/src/crypto/rsa_extra/rsa_test.cc @@ -461,7 +461,8 @@ TEST_P(RSAEncryptTest, TestKey) { } } -INSTANTIATE_TEST_CASE_P(, RSAEncryptTest, testing::ValuesIn(kRSAEncryptParams)); +INSTANTIATE_TEST_SUITE_P(, RSAEncryptTest, + testing::ValuesIn(kRSAEncryptParams)); TEST(RSATest, TestDecrypt) { bssl::UniquePtr<RSA> rsa( |