Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 cipher suite support #1455

Merged
merged 14 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
dkostic marked this conversation as resolved.
Show resolved Hide resolved
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
Loading