summaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorRobert Sloan <varomodt@google.com>2019-04-17 13:17:34 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-04-17 13:17:34 -0700
commit2669718082106ff65c13a73fc6f058e0713167b3 (patch)
tree5bfdfa9db8642d577ef86e52257844b934be87c4 /src/crypto
parent62c374e4170390cb3ca19cef283a8dc33c95211a (diff)
parentf63bd1f440905963647c68a896db0c85e8914d11 (diff)
downloadboringssl-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.cc2
-rw-r--r--src/crypto/bio/bio_test.cc4
-rw-r--r--src/crypto/bytestring/cbb.c17
-rw-r--r--src/crypto/cipher_extra/aead_test.cc143
-rw-r--r--src/crypto/cipher_extra/cipher_test.cc52
-rw-r--r--src/crypto/cipher_extra/e_aesgcmsiv.c5
-rw-r--r--src/crypto/digest_extra/digest_test.cc22
-rw-r--r--src/crypto/evp/evp_test.cc142
-rw-r--r--src/crypto/evp/evp_tests.txt11
-rw-r--r--src/crypto/evp/p_rsa.c1
-rw-r--r--src/crypto/fipsmodule/aes/aes.c6
-rw-r--r--src/crypto/fipsmodule/aes/aes_test.cc7
-rw-r--r--src/crypto/fipsmodule/cipher/e_aes.c9
-rw-r--r--src/crypto/fipsmodule/digest/digest.c39
-rw-r--r--src/crypto/fipsmodule/ec/ec_test.cc4
-rw-r--r--src/crypto/rsa_extra/rsa_test.cc3
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> &params)
- -> std::string { return params.param.name; });
+INSTANTIATE_TEST_SUITE_P(, PerAEADTest, testing::ValuesIn(kAEADs),
+ [](const testing::TestParamInfo<KnownAEAD> &params)
+ -> 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(