summaryrefslogtreecommitdiff
path: root/src
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
parent62c374e4170390cb3ca19cef283a8dc33c95211a (diff)
parentf63bd1f440905963647c68a896db0c85e8914d11 (diff)
downloadboringssl-2669718082106ff65c13a73fc6f058e0713167b3.tar.gz
external/boringssl: Sync to c9827e073f64e353c4891ecc2c73721882543ee0.
am: f63bd1f440 Change-Id: I3b6a5db1dab391cd490dd40dfba716bd48359b39
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-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
-rw-r--r--src/include/openssl/aes.h12
-rw-r--r--src/include/openssl/bytestring.h4
-rw-r--r--src/include/openssl/ssl.h3
-rw-r--r--src/ssl/d1_both.cc2
-rw-r--r--src/ssl/handoff.cc8
-rw-r--r--src/ssl/handshake_server.cc8
-rw-r--r--src/ssl/internal.h10
-rw-r--r--src/ssl/s3_both.cc2
-rw-r--r--src/ssl/ssl_lib.cc6
-rw-r--r--src/ssl/ssl_test.cc18
-rw-r--r--src/ssl/t1_lib.cc4
-rw-r--r--src/ssl/test/handshake_util.cc3
29 files changed, 335 insertions, 213 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fd353266..4cfbcc55 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -204,6 +204,7 @@ elseif(MSVC)
# copy constructor is inaccessible or deleted
"C4626" # assignment operator could not be generated because a base class
# assignment operator is inaccessible or deleted
+ "C4628" # digraphs not supported with -Ze
"C4668" # 'symbol' is not defined as a preprocessor macro, replacing with
# '0' for 'directives'
# Disable this because GTest uses it everywhere.
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(
diff --git a/src/include/openssl/aes.h b/src/include/openssl/aes.h
index 11565854..3606bfc4 100644
--- a/src/include/openssl/aes.h
+++ b/src/include/openssl/aes.h
@@ -76,18 +76,18 @@ struct aes_key_st {
typedef struct aes_key_st AES_KEY;
// AES_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit key,
-// |key|.
+// |key|. |key| must point to |bits|/8 bytes. It returns zero on success and a
+// negative number if |bits| is an invalid AES key size.
//
-// WARNING: unlike other OpenSSL functions, this returns zero on success and a
-// negative number on error.
+// WARNING: this function breaks the usual return value convention.
OPENSSL_EXPORT int AES_set_encrypt_key(const uint8_t *key, unsigned bits,
AES_KEY *aeskey);
// AES_set_decrypt_key configures |aeskey| to decrypt with the |bits|-bit key,
-// |key|.
+// |key|. |key| must point to |bits|/8 bytes. It returns zero on success and a
+// negative number if |bits| is an invalid AES key size.
//
-// WARNING: unlike other OpenSSL functions, this returns zero on success and a
-// negative number on error.
+// WARNING: this function breaks the usual return value convention.
OPENSSL_EXPORT int AES_set_decrypt_key(const uint8_t *key, unsigned bits,
AES_KEY *aeskey);
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
index 75b84341..029c2be2 100644
--- a/src/include/openssl/bytestring.h
+++ b/src/include/openssl/bytestring.h
@@ -345,9 +345,9 @@ struct cbb_st {
// length-prefix, or zero if no length-prefix is pending.
uint8_t pending_len_len;
char pending_is_asn1;
- // is_top_level is true iff this is a top-level |CBB| (as opposed to a child
+ // is_child is true iff this is a child |CBB| (as opposed to a top-level
// |CBB|). Top-level objects are valid arguments for |CBB_finish|.
- char is_top_level;
+ char is_child;
};
// CBB_zero sets an uninitialised |cbb| to the zero state. It must be
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 629f0063..4240c29a 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -4757,7 +4757,8 @@ OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span<uint8_t> out_prefix,
OPENSSL_EXPORT void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on);
OPENSSL_EXPORT void SSL_set_handoff_mode(SSL *SSL, bool on);
-OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out);
+OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out,
+ SSL_CLIENT_HELLO *out_hello);
OPENSSL_EXPORT bool SSL_decline_handoff(SSL *ssl);
OPENSSL_EXPORT bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff);
OPENSSL_EXPORT bool SSL_serialize_handback(const SSL *ssl, CBB *out);
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index d82852d7..f68cd1c4 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -405,7 +405,7 @@ ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed,
return ssl_open_record_success;
}
-bool dtls1_get_message(SSL *ssl, SSLMessage *out) {
+bool dtls1_get_message(const SSL *ssl, SSLMessage *out) {
if (!dtls1_is_current_message_complete(ssl)) {
return false;
}
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
index f9dbd135..0928015d 100644
--- a/src/ssl/handoff.cc
+++ b/src/ssl/handoff.cc
@@ -49,7 +49,8 @@ static bool serialize_features(CBB *out) {
return CBB_flush(out);
}
-bool SSL_serialize_handoff(const SSL *ssl, CBB *out) {
+bool SSL_serialize_handoff(const SSL *ssl, CBB *out,
+ SSL_CLIENT_HELLO *out_hello) {
const SSL3_STATE *const s3 = ssl->s3;
if (!ssl->server ||
s3->hs == nullptr ||
@@ -58,6 +59,7 @@ bool SSL_serialize_handoff(const SSL *ssl, CBB *out) {
}
CBB seq;
+ SSLMessage msg;
Span<const uint8_t> transcript = s3->hs->transcript.buffer();
if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&seq, kHandoffVersion) ||
@@ -66,7 +68,9 @@ bool SSL_serialize_handoff(const SSL *ssl, CBB *out) {
reinterpret_cast<uint8_t *>(s3->hs_buf->data),
s3->hs_buf->length) ||
!serialize_features(&seq) ||
- !CBB_flush(out)) {
+ !CBB_flush(out) ||
+ !ssl->method->get_message(ssl, &msg) ||
+ !ssl_client_hello_init(ssl, out_hello, msg)) {
return false;
}
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index cb4e9d1f..4622ad08 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -515,10 +515,6 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- if (hs->config->handoff) {
- return ssl_hs_handoff;
- }
-
SSL_CLIENT_HELLO client_hello;
if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
@@ -526,6 +522,10 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
+ if (hs->config->handoff) {
+ return ssl_hs_handoff;
+ }
+
// Run the early callback.
if (ssl->ctx->select_certificate_cb != NULL) {
switch (ssl->ctx->select_certificate_cb(&client_hello)) {
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 16b2866f..ee2952a4 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -1081,7 +1081,7 @@ void dtls_clear_outgoing_messages(SSL *ssl);
void ssl_do_info_callback(const SSL *ssl, int type, int value);
// ssl_do_msg_callback calls |ssl|'s message callback, if set.
-void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+void ssl_do_msg_callback(const SSL *ssl, int is_write, int content_type,
Span<const uint8_t> in);
@@ -1798,7 +1798,7 @@ int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
// ClientHello functions.
-bool ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
const SSLMessage &msg);
bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
@@ -1958,7 +1958,7 @@ struct SSL_PROTOCOL_METHOD {
void (*ssl_free)(SSL *ssl);
// get_message sets |*out| to the current handshake message and returns true
// if one has been received. It returns false if more input is needed.
- bool (*get_message)(SSL *ssl, SSLMessage *out);
+ bool (*get_message)(const SSL *ssl, SSLMessage *out);
// next_message is called to release the current handshake message.
void (*next_message)(SSL *ssl);
// Use the |ssl_open_handshake| wrapper.
@@ -2675,7 +2675,7 @@ void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
void ssl_update_cache(SSL_HANDSHAKE *hs, int mode);
int ssl_send_alert(SSL *ssl, int level, int desc);
-bool ssl3_get_message(SSL *ssl, SSLMessage *out);
+bool ssl3_get_message(const SSL *ssl, SSLMessage *out);
ssl_open_record_t ssl3_open_handshake(SSL *ssl, size_t *out_consumed,
uint8_t *out_alert, Span<uint8_t> in);
void ssl3_next_message(SSL *ssl);
@@ -2741,7 +2741,7 @@ unsigned int dtls1_min_mtu(void);
bool dtls1_new(SSL *ssl);
void dtls1_free(SSL *ssl);
-bool dtls1_get_message(SSL *ssl, SSLMessage *out);
+bool dtls1_get_message(const SSL *ssl, SSLMessage *out);
ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed,
uint8_t *out_alert, Span<uint8_t> in);
void dtls1_next_message(SSL *ssl);
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index aec6cae3..27e9454f 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -494,7 +494,7 @@ static bool parse_message(const SSL *ssl, SSLMessage *out,
return true;
}
-bool ssl3_get_message(SSL *ssl, SSLMessage *out) {
+bool ssl3_get_message(const SSL *ssl, SSLMessage *out) {
size_t unused;
if (!parse_message(ssl, out, &unused)) {
return false;
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index d3e76d0f..f9910f70 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -378,7 +378,7 @@ void ssl_do_info_callback(const SSL *ssl, int type, int value) {
}
}
-void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+void ssl_do_msg_callback(const SSL *ssl, int is_write, int content_type,
Span<const uint8_t> in) {
if (ssl->msg_callback == NULL) {
return;
@@ -399,8 +399,8 @@ void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
version = SSL_version(ssl);
}
- ssl->msg_callback(is_write, version, content_type, in.data(), in.size(), ssl,
- ssl->msg_callback_arg);
+ ssl->msg_callback(is_write, version, content_type, in.data(), in.size(),
+ const_cast<SSL *>(ssl), ssl->msg_callback_arg);
}
void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index af5d7952..d01b6495 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1650,11 +1650,11 @@ class SSLVersionTest : public ::testing::TestWithParam<VersionParam> {
bssl::UniquePtr<EVP_PKEY> key_;
};
-INSTANTIATE_TEST_CASE_P(WithVersion, SSLVersionTest,
- testing::ValuesIn(kAllVersions),
- [](const testing::TestParamInfo<VersionParam> &i) {
- return i.param.name;
- });
+INSTANTIATE_TEST_SUITE_P(WithVersion, SSLVersionTest,
+ testing::ValuesIn(kAllVersions),
+ [](const testing::TestParamInfo<VersionParam> &i) {
+ return i.param.name;
+ });
TEST_P(SSLVersionTest, SequenceNumber) {
ASSERT_TRUE(Connect());
@@ -3574,7 +3574,7 @@ std::string TicketAEADMethodParamToString(
return ret;
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
TicketAEADMethodTests, TicketAEADMethodTest,
testing::Combine(testing::Values(TLS1_2_VERSION, TLS1_3_VERSION),
testing::Values(0, 1, 2),
@@ -4050,8 +4050,9 @@ TEST(SSLTest, Handoff) {
ScopedCBB cbb;
Array<uint8_t> handoff;
+ SSL_CLIENT_HELLO hello;
ASSERT_TRUE(CBB_init(cbb.get(), 256));
- ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get()));
+ ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get(), &hello));
ASSERT_TRUE(CBBFinishArray(cbb.get(), &handoff));
bssl::UniquePtr<SSL> handshaker(SSL_new(handshaker_ctx.get()));
@@ -4122,8 +4123,9 @@ TEST(SSLTest, HandoffDeclined) {
ASSERT_EQ(server_err, SSL_ERROR_HANDOFF);
ScopedCBB cbb;
+ SSL_CLIENT_HELLO hello;
ASSERT_TRUE(CBB_init(cbb.get(), 256));
- ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get()));
+ ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get(), &hello));
ASSERT_TRUE(SSL_decline_handoff(server.get()));
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index c0452dc7..87f18889 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -199,10 +199,10 @@ static bool tls1_check_duplicate_extensions(const CBS *cbs) {
return true;
}
-bool ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
const SSLMessage &msg) {
OPENSSL_memset(out, 0, sizeof(*out));
- out->ssl = ssl;
+ out->ssl = const_cast<SSL *>(ssl);
out->client_hello = CBS_data(&msg.body);
out->client_hello_len = CBS_len(&msg.body);
diff --git a/src/ssl/test/handshake_util.cc b/src/ssl/test/handshake_util.cc
index a36b41a8..afead7f8 100644
--- a/src/ssl/test/handshake_util.cc
+++ b/src/ssl/test/handshake_util.cc
@@ -413,8 +413,9 @@ static bool PrepareHandoff(SSL *ssl, SettingsWriter *writer,
}
ScopedCBB cbb;
+ SSL_CLIENT_HELLO hello;
if (!CBB_init(cbb.get(), 512) ||
- !SSL_serialize_handoff(ssl, cbb.get()) ||
+ !SSL_serialize_handoff(ssl, cbb.get(), &hello) ||
!writer->WriteHandoff({CBB_data(cbb.get()), CBB_len(cbb.get())}) ||
!SerializeContextState(ssl->ctx.get(), cbb.get()) ||
!GetTestState(ssl)->Serialize(cbb.get())) {