Skip to content

Commit

Permalink
Add AES128-SHA256 and ECDHE-RSA-AES128-SHA256 ciphers (#472)
Browse files Browse the repository at this point in the history
The change adds support for two ciphers:
  - AES128-SHA256 (TLS_RSA_WITH_AES_128_CBC_SHA256)
  - ECDHE-RSA-AES128-SHA256 (TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
  • Loading branch information
dkostic authored May 2, 2022
1 parent 5b74f41 commit f266226
Show file tree
Hide file tree
Showing 16 changed files with 10,270 additions and 800 deletions.
9 changes: 9 additions & 0 deletions crypto/cipher_extra/aead_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ static const struct KnownAEAD kAEADs[] = {
"aes_128_cbc_sha1_tls_implicit_iv_tests.txt",
kLimitedImplementation | RequiresADLength(11)},

{"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
"aes_128_cbc_sha256_tls_tests.txt",
kLimitedImplementation | RequiresADLength(11)},

{"AES_128_CBC_SHA256_TLSImplicitIV",
EVP_aead_aes_128_cbc_sha256_tls_implicit_iv,
"aes_128_cbc_sha256_tls_implicit_iv_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
51 changes: 49 additions & 2 deletions crypto/cipher_extra/cipher_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ TEST(CipherTest, SHA1WithSecretSuffix) {
// length wraps to the next block.
static_assert(kSkip < 8, "kSkip is too large");

// |EVP_sha1_final_with_secret_suffix| is sensitive to the public length of
// |EVP_final_with_secret_suffix_sha1| 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 < SHA_CBLOCK; prefix += kSkip) {
Expand All @@ -515,7 +515,54 @@ TEST(CipherTest, SHA1WithSecretSuffix) {
SHA1_Init(&ctx);
SHA1_Update(&ctx, buf, prefix);
uint8_t computed[SHA_DIGEST_LENGTH];
ASSERT_TRUE(EVP_sha1_final_with_secret_suffix(
ASSERT_TRUE(EVP_final_with_secret_suffix_sha1(
&ctx, computed, buf + prefix, secret_len, max_len));

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

TEST(CipherTest, SHA256WithSecretSuffix) {
uint8_t buf[SHA256_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 3-byte increments.
constexpr size_t kSkip = 3;
// This value should be less than 8 to test the edge case when the 8-byte
// length wraps to the next block.
static_assert(kSkip < 8, "kSkip is too large");

// |EVP_final_with_secret_suffix_sha256| 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 < SHA256_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 * SHA256_CBLOCK; max_len += kSkip) {
SCOPED_TRACE(max_len);
for (size_t len = 0; len <= max_len; len += kSkip) {
SCOPED_TRACE(len);

uint8_t expected[SHA256_DIGEST_LENGTH];
SHA256(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));

SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, buf, prefix);
uint8_t computed[SHA256_DIGEST_LENGTH];
ASSERT_TRUE(EVP_final_with_secret_suffix_sha256(
&ctx, computed, buf + prefix, secret_len, max_len));

CONSTTIME_DECLASSIFY(computed, sizeof(computed));
Expand Down
56 changes: 56 additions & 0 deletions crypto/cipher_extra/e_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,20 @@ static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(
EVP_sha1(), 1);
}

static int aead_aes_128_cbc_sha256_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_128_cbc(),
EVP_sha256(), 0);
}

static int aead_aes_128_cbc_sha256_tls_implicit_iv_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_128_cbc(),
EVP_sha256(), 1);
}

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 @@ -522,6 +536,40 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
aead_tls_tag_len,
};

static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
SHA256_DIGEST_LENGTH + 16, // key len (SHA256 + AES128)
16, // nonce len (IV)
16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256)
SHA256_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in

NULL, // init
aead_aes_128_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};

static const EVP_AEAD aead_aes_128_cbc_sha256_tls_implicit_iv = {
SHA256_DIGEST_LENGTH + 16 + 16, // key len (SHA256 + AES128 + IV)
0, // nonce len
16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256)
SHA256_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in

NULL, // init
aead_aes_128_cbc_sha256_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
aead_tls_get_iv, // get_iv
aead_tls_tag_len,
};

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 @@ -589,6 +637,14 @@ const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) {
return &aead_aes_256_cbc_sha1_tls_implicit_iv;
}

const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void) {
return &aead_aes_128_cbc_sha256_tls;
}

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_des_ede3_cbc_sha1_tls(void) {
return &aead_des_ede3_cbc_sha1_tls;
}
Expand Down
19 changes: 12 additions & 7 deletions crypto/cipher_extra/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,22 @@ 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_sha1_final_with_secret_suffix computes the result of hashing |len| bytes
// from |in| to |ctx| and writes 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 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.
//
// This function is exported for unit tests.
OPENSSL_EXPORT int EVP_sha1_final_with_secret_suffix(
// The functions are exported for unit tests.
OPENSSL_EXPORT int EVP_final_with_secret_suffix_sha1(
SHA_CTX *ctx, uint8_t out[SHA_DIGEST_LENGTH], const uint8_t *in, size_t len,
size_t max_len);

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);

// EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS
// record.
//
Expand Down
Loading

0 comments on commit f266226

Please sign in to comment.