Skip to content

Commit

Permalink
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 cipher suite support (#1455)
Browse files Browse the repository at this point in the history
Adds support for the TLS 1.2 cipher suite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ECDHE-RSA-AES256-SHA384).
  • Loading branch information
skmcgrail authored Mar 28, 2024
1 parent 7cad9e3 commit 2ce9017
Show file tree
Hide file tree
Showing 18 changed files with 6,477 additions and 925 deletions.
22 changes: 15 additions & 7 deletions crypto/cipher_extra/aead_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ static const struct KnownAEAD kAEADs[] = {
"aes_128_cbc_sha256_tls_implicit_iv_tests.txt",
kLimitedImplementation | RequiresADLength(11)},

{"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
"aes_256_cbc_sha384_tls_tests.txt",
kLimitedImplementation | RequiresADLength(11)},

{"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
"aes_256_cbc_sha1_tls_tests.txt",
kLimitedImplementation | RequiresADLength(11)},
Expand Down Expand Up @@ -1372,13 +1376,15 @@ struct EvpAeadCtxSerdeTestParams {
class EvpAeadCtxSerdeTest
: public testing::TestWithParam<EvpAeadCtxSerdeTestParams> {};

static const uint8_t kEvpAeadCtxKey[68] = {
0x49, 0xd4, 0x9f, 0x84, 0x62, 0xf1, 0xda, 0x3a, 0xe1, 0x60, 0x08, 0xf3,
0xcf, 0xf6, 0x01, 0x2d, 0x95, 0x90, 0x08, 0xfe, 0xad, 0x89, 0x31, 0x21,
0x1c, 0x84, 0xf0, 0x77, 0x57, 0x18, 0x94, 0x03, 0xe3, 0x85, 0x30, 0x32,
0xc3, 0x0f, 0xae, 0x54, 0x54, 0x8d, 0x21, 0x55, 0x68, 0xc9, 0x6f, 0xb9,
0x23, 0x4e, 0xbc, 0xba, 0x1a, 0x4c, 0x9a, 0xd8, 0x35, 0x96, 0xc2, 0xb3,
0x6e, 0x7a, 0x47, 0xa8, 0x8e, 0xdd, 0x6e, 0x1d};
static const uint8_t kEvpAeadCtxKey[80] = {
0x03, 0xeb, 0x1d, 0xb2, 0x2c, 0xa8, 0xc0, 0x3b, 0x29, 0x9c, 0x66, 0xe5,
0xdd, 0xb7, 0x70, 0x6c, 0x39, 0x86, 0x71, 0x94, 0x79, 0x5c, 0xf5, 0x88,
0xde, 0xd9, 0x05, 0x1f, 0x28, 0x96, 0x86, 0x28, 0x01, 0xb0, 0x59, 0x11,
0xb0, 0x3f, 0x35, 0xe6, 0xb5, 0x2f, 0x3b, 0xee, 0xbc, 0xf9, 0x11, 0xb1,
0x9e, 0x58, 0xf6, 0xb7, 0xf3, 0x3e, 0x5b, 0x66, 0x28, 0x85, 0x0c, 0x66,
0x2b, 0x75, 0xb7, 0x86, 0xfd, 0xa4, 0x2d, 0x4b, 0x8c, 0xe0, 0x9a, 0x58,
0xbf, 0xc6, 0x22, 0x4c, 0x39, 0x25, 0x66, 0xfd
};

static const EvpAeadCtxSerdeTestParams kEvpAeadCtxSerde[] = {
{"EVP_aead_aes_128_gcm", EVP_aead_aes_128_gcm(), kEvpAeadCtxKey, 16, 16,
Expand Down Expand Up @@ -1421,6 +1427,8 @@ static const EvpAeadCtxSerdeTestParams kEvpAeadCtxSerde[] = {
kEvpAeadCtxKey, 48, 32, 11},
{"EVP_aead_aes_128_cbc_sha256_tls_implicit_iv",
EVP_aead_aes_128_cbc_sha256_tls_implicit_iv(), kEvpAeadCtxKey, 64, 32, 12},
{"EVP_aead_aes_256_cbc_sha384_tls", EVP_aead_aes_256_cbc_sha384_tls(),
kEvpAeadCtxKey, 80, 48, 28},
{"EVP_aead_des_ede3_cbc_sha1_tls", EVP_aead_des_ede3_cbc_sha1_tls(),
kEvpAeadCtxKey, 44, 20, 13},
{"EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv",
Expand Down
48 changes: 48 additions & 0 deletions crypto/cipher_extra/cipher_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,54 @@ TEST(CipherTest, SHA256WithSecretSuffix) {
}
}

TEST(CipherTest, SHA384WithSecretSuffix) {
uint8_t buf[SHA384_CBLOCK * 4];
RAND_bytes(buf, sizeof(buf));
// Hashing should run in time independent of the bytes.
CONSTTIME_SECRET(buf, sizeof(buf));

// Exhaustively testing interesting cases in this function is cubic in the
// block size, so we test in 7-byte increments.
constexpr size_t kSkip = 7;
// This value should be less than 16 to test the edge case when the 16-byte
// length wraps to the next block.
static_assert(kSkip < 16, "kSkip is too large");

// |EVP_final_with_secret_suffix_sha384| is sensitive to the public length of
// the partial block previously hashed. In TLS, this is the HMAC prefix, the
// header, and the public minimum padding length.
for (size_t prefix = 0; prefix < SHA384_CBLOCK; prefix += kSkip) {
SCOPED_TRACE(prefix);
// The first block is treated differently, so we run with up to three
// blocks of length variability.
for (size_t max_len = 0; max_len < 3 * SHA384_CBLOCK; max_len += kSkip) {
SCOPED_TRACE(max_len);
for (size_t len = 0; len <= max_len; len += kSkip) {
SCOPED_TRACE(len);

uint8_t expected[SHA384_DIGEST_LENGTH];
SHA384(buf, prefix + len, expected);
CONSTTIME_DECLASSIFY(expected, sizeof(expected));

// Make a copy of the secret length to avoid interfering with the loop.
size_t secret_len = len;
CONSTTIME_SECRET(&secret_len, sizeof(secret_len));

SHA512_CTX ctx;
SHA384_Init(&ctx);
SHA384_Update(&ctx, buf, prefix);
uint8_t computed[SHA384_DIGEST_LENGTH];
ASSERT_TRUE(EVP_final_with_secret_suffix_sha384(
&ctx, computed, buf + prefix, secret_len, max_len));

CONSTTIME_DECLASSIFY(computed, sizeof(computed));
EXPECT_EQ(Bytes(expected), Bytes(computed));
}
}
}
}


TEST(CipherTest, GetCipher) {
const EVP_CIPHER *cipher = EVP_get_cipherbynid(NID_aes_128_gcm);
ASSERT_TRUE(cipher);
Expand Down
5 changes: 3 additions & 2 deletions crypto/cipher_extra/e_aes_cbc_hmac_sha256.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,9 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
size_t mac_len;
uint8_t record_mac_tmp[EVP_MAX_MD_SIZE];
uint8_t *record_mac;
if (!EVP_tls_cbc_digest_record_sha256(EVP_sha256(), mac, &mac_len, key->aux.tls_aad,
out, data_len, len, key->hmac_key, 64)) {
if (!EVP_tls_cbc_digest_record(EVP_sha256(), mac, &mac_len,
key->aux.tls_aad, out, data_len, len,
key->hmac_key, 64)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
Expand Down
32 changes: 32 additions & 0 deletions crypto/cipher_extra/e_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,14 @@ static int aead_aes_128_cbc_sha256_tls_implicit_iv_init(
EVP_sha256(), 1);
}

static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha384(), 0);
}

static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
Expand Down Expand Up @@ -589,6 +597,26 @@ static const EVP_AEAD aead_aes_128_cbc_sha256_tls_implicit_iv = {
NULL /* deserialize_state */,
};

static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
SHA384_DIGEST_LENGTH + 32, // key len (SHA384 + AES256)
16, // nonce len (IV)
16 + SHA384_DIGEST_LENGTH, // overhead (padding + SHA384)
SHA384_DIGEST_LENGTH, // max tag length
AEAD_AES_256_CBC_SHA384_TLS_ID, // evp_aead_id
0, // seal_scatter_supports_extra_in

NULL, // init
aead_aes_256_cbc_sha384_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
NULL /* serialize_state */,
NULL /* deserialize_state */,
};

static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
SHA_DIGEST_LENGTH + 24, // key len (SHA1 + 3DES)
8, // nonce len (IV)
Expand Down Expand Up @@ -673,6 +701,10 @@ const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls_implicit_iv(void) {
return &aead_aes_128_cbc_sha256_tls_implicit_iv;
}

const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) {
return &aead_aes_256_cbc_sha384_tls;
}

const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) {
return &aead_des_ede3_cbc_sha1_tls;
}
Expand Down
25 changes: 10 additions & 15 deletions crypto/cipher_extra/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
// which EVP_tls_cbc_digest_record supports.
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md);

// EVP_final_with_secret_suffix_sha1 and EVP_final_with_secret_suffix_sha256
// compute the result of hashing |len| bytes from |in| to |ctx| and write the
// resulting hash to |out|. |len| is treated as secret and must be at most
// |max_len|, which is treated as public. |in| must point to a buffer of at
// least |max_len| bytes. It returns one on success and zero if inputs are
// too long.
// EVP_final_with_secret_suffix_sha1, EVP_final_with_secret_suffix_sha256, and
// EVP_final_with_secret_suffix_sha384 compute the result of hashing |len|
// bytes from |in| to |ctx| and write the resulting hash to |out|.
// |len| is treated as secret and must be at most |max_len|, which is treated
// as public. |in| must point to a buffer of at least |max_len| bytes.
// It returns one on success and zero if inputs are too long.
//
// The functions are exported for unit tests.
OPENSSL_EXPORT int EVP_final_with_secret_suffix_sha1(
Expand All @@ -126,6 +126,10 @@ OPENSSL_EXPORT int EVP_final_with_secret_suffix_sha256(
SHA256_CTX *ctx, uint8_t out[SHA256_DIGEST_LENGTH], const uint8_t *in,
size_t len, size_t max_len);

OPENSSL_EXPORT int EVP_final_with_secret_suffix_sha384(
SHA512_CTX *ctx, uint8_t out[SHA384_DIGEST_LENGTH], const uint8_t *in,
size_t len, size_t max_len);

// EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS
// record.
//
Expand All @@ -151,15 +155,6 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
const uint8_t *mac_secret,
unsigned mac_secret_length);

// EVP_tls_cbc_digest_record_sha256 performs the same functionality of
// EVP_tls_cbc_digest_record except it internally calls SHA256 instead of SHA1.
int EVP_tls_cbc_digest_record_sha256(const EVP_MD *md, uint8_t *md_out,
size_t *md_out_size, const uint8_t header[13],
const uint8_t *data, size_t data_size,
size_t data_plus_mac_plus_padding_size,
const uint8_t *mac_secret,
unsigned mac_secret_length);

#define POLY1305_TAG_LEN 16

// For convenience (the x86_64 calling convention allows only six parameters in
Expand Down
Loading

0 comments on commit 2ce9017

Please sign in to comment.