summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorRajeev Ranjan <ranjan.rajeev@siemens.com>2023-12-01 12:47:07 +0100
committerTomas Mraz <tomas@openssl.org>2024-05-14 15:39:15 +0200
commitb6a5e801679663c13875cf6e18f475f8700d72a9 (patch)
tree437ddfdbc1fbcf49974cc2daa89bfeadd68876ae /ssl
parent61f32392dd67d47018ce46f427339e7191426e45 (diff)
Add support for integrity-only cipher suites for TLS v1.3
- add test vectors for tls1_3 integrity-only ciphers - recmethod_local.h: add new member for MAC - tls13_meth.c: add MAC only to tls 1.3 - tls13_enc.c: extend function to add MAC only - ssl_local.h: add ssl_cipher_get_evp_md_mac() - s3_lib.c: add the new ciphers and add #ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS - ssl_ciph.c : add ssl_cipher_get_evp_md_mac() and use it - tls13secretstest.c: add dummy test function - Configure: add integrity-only-ciphers option - document the new ciphers Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22903)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/record/methods/recmethod_local.h7
-rw-r--r--ssl/record/methods/tls13_meth.c127
-rw-r--r--ssl/record/methods/tls_common.c4
-rw-r--r--ssl/s3_lib.c60
-rw-r--r--ssl/ssl_ciph.c61
-rw-r--r--ssl/ssl_local.h3
-rw-r--r--ssl/t1_trce.c2
-rw-r--r--ssl/tls13_enc.c162
8 files changed, 308 insertions, 118 deletions
diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h
index fe9dce1535..5a3d010503 100644
--- a/ssl/record/methods/recmethod_local.h
+++ b/ssl/record/methods/recmethod_local.h
@@ -295,6 +295,9 @@ struct ossl_record_layer_st
/* cryptographic state */
EVP_CIPHER_CTX *enc_ctx;
+ /* TLSv1.3 MAC ctx, only used with integrity-only cipher */
+ EVP_MAC_CTX *mac_ctx;
+
/* Explicit IV length */
size_t eivlen;
@@ -333,8 +336,8 @@ struct ossl_record_layer_st
int tlstree;
/* TLSv1.3 fields */
- /* static IV */
- unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char *iv; /* static IV */
+ unsigned char *nonce; /* part of static IV followed by sequence number */
int allow_plain_alerts;
/* TLS "any" fields */
diff --git a/ssl/record/methods/tls13_meth.c b/ssl/record/methods/tls13_meth.c
index d782c327ec..afae14ad22 100644
--- a/ssl/record/methods/tls13_meth.c
+++ b/ssl/record/methods/tls13_meth.c
@@ -24,15 +24,42 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
COMP_METHOD *comp)
{
EVP_CIPHER_CTX *ciph_ctx;
+ EVP_MAC_CTX *mac_ctx;
+ EVP_MAC *mac;
+ OSSL_PARAM params[2], *p = params;
int mode;
int enc = (rl->direction == OSSL_RECORD_DIRECTION_WRITE) ? 1 : 0;
- if (ivlen > sizeof(rl->iv)) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ rl->iv = OPENSSL_malloc(ivlen);
+ if (rl->iv == NULL)
return OSSL_RECORD_RETURN_FATAL;
- }
+
+ rl->nonce = OPENSSL_malloc(ivlen);
+ if (rl->nonce == NULL)
+ return OSSL_RECORD_RETURN_FATAL;
+
memcpy(rl->iv, iv, ivlen);
+ /* Integrity only */
+ if (EVP_CIPHER_is_a(ciph, "NULL") && mactype == NID_hmac && md != NULL) {
+ mac = EVP_MAC_fetch(rl->libctx, "HMAC", rl->propq);
+ if (mac == NULL
+ || (mac_ctx = rl->mac_ctx = EVP_MAC_CTX_new(mac)) == NULL) {
+ EVP_MAC_free(mac);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ EVP_MAC_free(mac);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ (char *)EVP_MD_name(md), 0);
+ *p = OSSL_PARAM_construct_end();
+ if (!EVP_MAC_init(mac_ctx, key, keylen, params)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ goto end;
+ }
+
ciph_ctx = rl->enc_ctx = EVP_CIPHER_CTX_new();
if (ciph_ctx == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
@@ -51,7 +78,7 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
-
+ end:
return OSSL_RECORD_RETURN_SUCCESS;
}
@@ -59,15 +86,18 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
size_t n_recs, int sending, SSL_MAC_BUF *mac,
size_t macsize)
{
- EVP_CIPHER_CTX *ctx;
- unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH];
- size_t ivlen, offset, loop, hdrlen;
+ EVP_CIPHER_CTX *enc_ctx;
+ unsigned char recheader[SSL3_RT_HEADER_LENGTH];
+ unsigned char tag[EVP_MAX_MD_SIZE];
+ size_t nonce_len, offset, loop, hdrlen, taglen;
unsigned char *staticiv;
+ unsigned char *nonce;
unsigned char *seq = rl->sequence;
int lenu, lenf;
TLS_RL_RECORD *rec = &recs[0];
WPACKET wpkt;
const EVP_CIPHER *cipher;
+ EVP_MAC_CTX *mac_ctx = NULL;
int mode;
if (n_recs != 1) {
@@ -76,15 +106,14 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
return 0;
}
- ctx = rl->enc_ctx;
+ enc_ctx = rl->enc_ctx; /* enc_ctx is ignored when rl->mac_ctx != NULL */
staticiv = rl->iv;
+ nonce = rl->nonce;
- cipher = EVP_CIPHER_CTX_get0_cipher(ctx);
- if (cipher == NULL) {
+ if (enc_ctx == NULL && rl->mac_ctx == NULL) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- mode = EVP_CIPHER_get_mode(cipher);
/*
* If we're sending an alert and ctx != NULL then we must be forcing
@@ -92,13 +121,17 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
* plaintext alerts at certain points in the handshake. If we've got this
* far then we have already validated that a plaintext alert is ok here.
*/
- if (ctx == NULL || rec->type == SSL3_RT_ALERT) {
+ if (rec->type == SSL3_RT_ALERT) {
memmove(rec->data, rec->input, rec->length);
rec->input = rec->data;
return 1;
}
- ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ /* For integrity-only ciphers, nonce_len is same as MAC size */
+ if (rl->mac_ctx != NULL)
+ nonce_len = EVP_MAC_CTX_get_mac_size(rl->mac_ctx);
+ else
+ nonce_len = EVP_CIPHER_CTX_get_iv_length(enc_ctx);
if (!sending) {
/*
@@ -110,30 +143,22 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
rec->length -= rl->taglen;
}
- /* Set up IV */
- if (ivlen < SEQ_NUM_SIZE) {
+ /* Set up nonce: part of static IV followed by sequence number */
+ if (nonce_len < SEQ_NUM_SIZE) {
/* Should not happen */
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- offset = ivlen - SEQ_NUM_SIZE;
- memcpy(iv, staticiv, offset);
+ offset = nonce_len - SEQ_NUM_SIZE;
+ memcpy(nonce, staticiv, offset);
for (loop = 0; loop < SEQ_NUM_SIZE; loop++)
- iv[offset + loop] = staticiv[offset + loop] ^ seq[loop];
+ nonce[offset + loop] = staticiv[offset + loop] ^ seq[loop];
if (!tls_increment_sequence_ctr(rl)) {
/* RLAYERfatal already called */
return 0;
}
- if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0
- || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
- rl->taglen,
- rec->data + rec->length) <= 0)) {
- RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
/* Set up the AAD */
if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
|| !WPACKET_put_bytes_u8(&wpkt, rec->type)
@@ -147,24 +172,64 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
return 0;
}
+ if (rl->mac_ctx != NULL) {
+ int ret = 0;
+
+ if ((mac_ctx = EVP_MAC_CTX_dup(rl->mac_ctx)) == NULL
+ || !EVP_MAC_update(mac_ctx, nonce, nonce_len)
+ || !EVP_MAC_update(mac_ctx, recheader, sizeof(recheader))
+ || !EVP_MAC_update(mac_ctx, rec->input, rec->length)
+ || !EVP_MAC_final(mac_ctx, tag, &taglen, rl->taglen)) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto end_mac;
+ }
+
+ if (sending) {
+ memcpy(rec->data + rec->length, tag, rl->taglen);
+ rec->length += rl->taglen;
+ } else if (CRYPTO_memcmp(tag, rec->data + rec->length,
+ rl->taglen) != 0) {
+ goto end_mac;
+ }
+ ret = 1;
+ end_mac:
+ EVP_MAC_CTX_free(mac_ctx);
+ return ret;
+ }
+
+ cipher = EVP_CIPHER_CTX_get0_cipher(enc_ctx);
+ if (cipher == NULL) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ mode = EVP_CIPHER_get_mode(cipher);
+
+ if (EVP_CipherInit_ex(enc_ctx, NULL, NULL, NULL, nonce, sending) <= 0
+ || (!sending && EVP_CIPHER_CTX_ctrl(enc_ctx, EVP_CTRL_AEAD_SET_TAG,
+ rl->taglen,
+ rec->data + rec->length) <= 0)) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
/*
* For CCM we must explicitly set the total plaintext length before we add
* any AAD.
*/
if ((mode == EVP_CIPH_CCM_MODE
- && EVP_CipherUpdate(ctx, NULL, &lenu, NULL,
+ && EVP_CipherUpdate(enc_ctx, NULL, &lenu, NULL,
(unsigned int)rec->length) <= 0)
- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader,
+ || EVP_CipherUpdate(enc_ctx, NULL, &lenu, recheader,
sizeof(recheader)) <= 0
- || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,
+ || EVP_CipherUpdate(enc_ctx, rec->data, &lenu, rec->input,
(unsigned int)rec->length) <= 0
- || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
+ || EVP_CipherFinal_ex(enc_ctx, rec->data + lenu, &lenf) <= 0
|| (size_t)(lenu + lenf) != rec->length) {
return 0;
}
if (sending) {
/* Add the tag */
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen,
+ if (EVP_CIPHER_CTX_ctrl(enc_ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen,
rec->data + rec->length) <= 0) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c
index d9e017d254..bf6dc0d1f5 100644
--- a/ssl/record/methods/tls_common.c
+++ b/ssl/record/methods/tls_common.c
@@ -1434,11 +1434,13 @@ static void tls_int_free(OSSL_RECORD_LAYER *rl)
tls_release_write_buffer(rl);
EVP_CIPHER_CTX_free(rl->enc_ctx);
+ EVP_MAC_CTX_free(rl->mac_ctx);
EVP_MD_CTX_free(rl->md_ctx);
#ifndef OPENSSL_NO_COMP
COMP_CTX_free(rl->compctx);
#endif
-
+ OPENSSL_free(rl->iv);
+ OPENSSL_free(rl->nonce);
if (rl->version == SSL3_VERSION)
OPENSSL_cleanse(rl->mac_secret, sizeof(rl->mac_secret));
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 2bc5e79fd1..5c7f338c65 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -112,7 +112,40 @@ static SSL_CIPHER tls13_ciphers[] = {
SSL_HANDSHAKE_MAC_SHA256,
64, /* CCM8 uses a short tag, so we have a low security strength */
128,
- }
+ },
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
+ {
+ 1,
+ TLS1_3_RFC_SHA256_SHA256,
+ TLS1_3_RFC_SHA256_SHA256,
+ TLS1_3_CK_SHA256_SHA256,
+ SSL_kANY,
+ SSL_aANY,
+ SSL_eNULL,
+ SSL_SHA256,
+ TLS1_3_VERSION, TLS1_3_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_STRONG_NONE,
+ SSL_HANDSHAKE_MAC_SHA256,
+ 0,
+ 256,
+ }, {
+ 1,
+ TLS1_3_RFC_SHA384_SHA384,
+ TLS1_3_RFC_SHA384_SHA384,
+ TLS1_3_CK_SHA384_SHA384,
+ SSL_kANY,
+ SSL_aANY,
+ SSL_eNULL,
+ SSL_SHA384,
+ TLS1_3_VERSION, TLS1_3_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_STRONG_NONE,
+ SSL_HANDSHAKE_MAC_SHA384,
+ 0,
+ 384,
+ },
+#endif
};
/*
@@ -126,6 +159,7 @@ static SSL_CIPHER tls13_ciphers[] = {
* Weak ciphers
*/
static SSL_CIPHER ssl3_ciphers[] = {
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
SSL3_TXT_RSA_NULL_MD5,
@@ -158,6 +192,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -352,6 +387,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_RSA_WITH_NULL_SHA256,
@@ -368,6 +404,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
{
1,
TLS1_TXT_RSA_WITH_AES_128_SHA256,
@@ -944,6 +981,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
64, /* CCM8 uses a short tag, so we have a low security strength */
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA,
@@ -960,6 +998,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -1010,6 +1049,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA,
@@ -1026,6 +1066,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -1076,6 +1117,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_ECDH_anon_WITH_NULL_SHA,
@@ -1092,6 +1134,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -1270,6 +1313,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_PSK_WITH_NULL_SHA,
@@ -1318,6 +1362,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -1596,6 +1641,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_PSK_WITH_NULL_SHA256,
@@ -1628,6 +1674,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256,
@@ -1660,6 +1707,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_DHE_PSK_WITH_NULL_SHA256,
@@ -1692,6 +1740,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256,
@@ -1724,6 +1773,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_RSA_PSK_WITH_NULL_SHA256,
@@ -1756,6 +1806,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+#endif
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -1838,6 +1889,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+#ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA,
@@ -1886,7 +1938,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
-
+#endif
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
@@ -2613,6 +2665,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+# ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
"GOST2001-NULL-GOST94",
@@ -2629,6 +2682,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+# endif
{
1,
"IANA-GOST2012-GOST8912-GOST8912",
@@ -2661,6 +2715,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
+# ifndef OPENSSL_NO_INTEGRITY_ONLY_CIPHERS
{
1,
"GOST2012-NULL-GOST12",
@@ -2677,6 +2732,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+# endif
{
1,
"GOST2012-KUZNYECHIK-KUZNYECHIKOMAC",
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index a9cf6416b1..e70b800a5c 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -482,7 +482,8 @@ static int load_builtin_compressions(void)
int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
const EVP_CIPHER **enc)
{
- int i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, sslc->algorithm_enc);
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_cipher,
+ sslc->algorithm_enc);
if (i == -1) {
*enc = NULL;
@@ -508,6 +509,33 @@ int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
return 1;
}
+int ssl_cipher_get_evp_md_mac(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_MD **md,
+ int *mac_pkey_type, size_t *mac_secret_size)
+{
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_mac, sslc->algorithm_mac);
+
+ if (i == -1) {
+ *md = NULL;
+ if (mac_pkey_type != NULL)
+ *mac_pkey_type = NID_undef;
+ if (mac_secret_size != NULL)
+ *mac_secret_size = 0;
+ } else {
+ const EVP_MD *digest = ctx->ssl_digest_methods[i];
+
+ if (digest == NULL || !ssl_evp_md_up_ref(digest))
+ return 0;
+
+ *md = digest;
+ if (mac_pkey_type != NULL)
+ *mac_pkey_type = ctx->ssl_mac_pkey_id[i];
+ if (mac_secret_size != NULL)
+ *mac_secret_size = ctx->ssl_mac_secret_size[i];
+ }
+ return 1;
+}
+
int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
const EVP_CIPHER **enc, const EVP_MD **md,
int *mac_pkey_type, size_t *mac_secret_size,
@@ -547,34 +575,17 @@ int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
if (!ssl_cipher_get_evp_cipher(ctx, c, enc))
return 0;
- i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac);
- if (i == -1) {
- *md = NULL;
- if (mac_pkey_type != NULL)
- *mac_pkey_type = NID_undef;
- if (mac_secret_size != NULL)
- *mac_secret_size = 0;
- if (c->algorithm_mac == SSL_AEAD)
- mac_pkey_type = NULL;
- } else {
- const EVP_MD *digest = ctx->ssl_digest_methods[i];
-
- if (digest == NULL
- || !ssl_evp_md_up_ref(digest)) {
- ssl_evp_cipher_free(*enc);
- return 0;
- }
- *md = digest;
- if (mac_pkey_type != NULL)
- *mac_pkey_type = ctx->ssl_mac_pkey_id[i];
- if (mac_secret_size != NULL)
- *mac_secret_size = ctx->ssl_mac_secret_size[i];
+ if (!ssl_cipher_get_evp_md_mac(ctx, c, md, mac_pkey_type,
+ mac_secret_size)) {
+ ssl_evp_cipher_free(*enc);
+ return 0;
}
if ((*enc != NULL)
- && (*md != NULL
+ && (*md != NULL
|| (EVP_CIPHER_get_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER))
- && (!mac_pkey_type || *mac_pkey_type != NID_undef)) {
+ && (c->algorithm_mac == SSL_AEAD
+ || mac_pkey_type == NULL || *mac_pkey_type != NID_undef)) {
const EVP_CIPHER *evp = NULL;
if (use_etm
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 49a514fee4..2d827d8bb9 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -2495,6 +2495,9 @@ __owur int ossl_bytes_to_cipher_list(SSL_CONNECTION *s, PACKET *cipher_suites,
void ssl_update_cache(SSL_CONNECTION *s, int mode);
__owur int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
const EVP_CIPHER **enc);
+__owur int ssl_cipher_get_evp_md_mac(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_MD **md,
+ int *mac_pkey_type, size_t *mac_secret_size);
__owur int ssl_cipher_get_evp(SSL_CTX *ctxc, const SSL_SESSION *s,
const EVP_CIPHER **enc, const EVP_MD **md,
int *mac_pkey_type, size_t *mac_secret_size,
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 29dce65e4f..9c811c5ee6 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -446,6 +446,8 @@ static const ssl_trace_tbl ssl_ciphers_tbl[] = {
{0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
{0xFF85, "LEGACY-GOST2012-GOST8912-GOST8912"},
{0xFF87, "GOST2012-NULL-GOST12"},
+ {0xC0B4, "TLS_SHA256_SHA256"},
+ {0xC0B5, "TLS_SHA384_SHA384"},
{0xC100, "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC"},
{0xC101, "GOST2012-MAGMA-MAGMAOMAC"},
{0xC102, "GOST2012-GOST8912-IANA"},
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 56f100371d..f6b4b9f4c2 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -323,10 +323,12 @@ int tls13_setup_key_block(SSL_CONNECTION *s)
{
const EVP_CIPHER *c;
const EVP_MD *hash;
+ int mac_type = NID_undef;
+ size_t mac_secret_size = 0;
s->session->cipher = s->s3.tmp.new_cipher;
if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, &c, &hash,
- NULL, NULL, NULL, 0)) {
+ &mac_type, &mac_secret_size, NULL, 0)) {
/* Error is already recorded */
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
return 0;
@@ -336,23 +338,27 @@ int tls13_setup_key_block(SSL_CONNECTION *s)
s->s3.tmp.new_sym_enc = c;
ssl_evp_md_free(s->s3.tmp.new_hash);
s->s3.tmp.new_hash = hash;
+ s->s3.tmp.new_mac_pkey_type = mac_type;
+ s->s3.tmp.new_mac_secret_size = mac_secret_size;
return 1;
}
static int derive_secret_key_and_iv(SSL_CONNECTION *s, const EVP_MD *md,
const EVP_CIPHER *ciph,
+ int mac_type,
+ const EVP_MD *mac_md,
const unsigned char *insecret,
const unsigned char *hash,
const unsigned char *label,
size_t labellen, unsigned char *secret,
unsigned char *key, size_t *keylen,
- unsigned char *iv, size_t *ivlen,
+ unsigned char **iv, size_t *ivlen,
size_t *taglen)
{
int hashleni = EVP_MD_get_size(md);
size_t hashlen;
- int mode;
+ int mode, mac_mdleni;
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
@@ -367,48 +373,71 @@ static int derive_secret_key_and_iv(SSL_CONNECTION *s, const EVP_MD *md,
return 0;
}
- *keylen = EVP_CIPHER_get_key_length(ciph);
-
- mode = EVP_CIPHER_get_mode(ciph);
- if (mode == EVP_CIPH_CCM_MODE) {
- uint32_t algenc;
-
- *ivlen = EVP_CCM_TLS_IV_LEN;
- if (s->s3.tmp.new_cipher != NULL) {
- algenc = s->s3.tmp.new_cipher->algorithm_enc;
- } else if (s->session->cipher != NULL) {
- /* We've not selected a cipher yet - we must be doing early data */
- algenc = s->session->cipher->algorithm_enc;
- } else if (s->psksession != NULL && s->psksession->cipher != NULL) {
- /* We must be doing early data with out-of-band PSK */
- algenc = s->psksession->cipher->algorithm_enc;
- } else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ /* if ciph is NULL cipher, then use new_hash to calculate keylen */
+ if (EVP_CIPHER_is_a(ciph, "NULL")
+ && mac_md != NULL
+ && mac_type == NID_hmac) {
+ mac_mdleni = EVP_MD_get_size(mac_md);
+
+ if (mac_mdleni < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
- *taglen = EVP_CCM8_TLS_TAG_LEN;
- else
- *taglen = EVP_CCM_TLS_TAG_LEN;
+ *ivlen = *taglen = (size_t)mac_mdleni;
+ *keylen = s->s3.tmp.new_mac_secret_size;
} else {
- int iivlen;
- if (mode == EVP_CIPH_GCM_MODE) {
- *taglen = EVP_GCM_TLS_TAG_LEN;
+ *keylen = EVP_CIPHER_get_key_length(ciph);
+
+ mode = EVP_CIPHER_get_mode(ciph);
+ if (mode == EVP_CIPH_CCM_MODE) {
+ uint32_t algenc;
+
+ *ivlen = EVP_CCM_TLS_IV_LEN;
+ if (s->s3.tmp.new_cipher != NULL) {
+ algenc = s->s3.tmp.new_cipher->algorithm_enc;
+ } else if (s->session->cipher != NULL) {
+ /* We've not selected a cipher yet - we must be doing early data */
+ algenc = s->session->cipher->algorithm_enc;
+ } else if (s->psksession != NULL && s->psksession->cipher != NULL) {
+ /* We must be doing early data with out-of-band PSK */
+ algenc = s->psksession->cipher->algorithm_enc;
+ } else {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
+ if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
+ *taglen = EVP_CCM8_TLS_TAG_LEN;
+ else
+ *taglen = EVP_CCM_TLS_TAG_LEN;
} else {
- /* CHACHA20P-POLY1305 */
- *taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
+ int iivlen;
+
+ if (mode == EVP_CIPH_GCM_MODE) {
+ *taglen = EVP_GCM_TLS_TAG_LEN;
+ } else {
+ /* CHACHA20P-POLY1305 */
+ *taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
+ }
+ iivlen = EVP_CIPHER_get_iv_length(ciph);
+ if (iivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
+ *ivlen = iivlen;
}
- iivlen = EVP_CIPHER_get_iv_length(ciph);
- if (iivlen < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ }
+
+ if (*ivlen > EVP_MAX_IV_LENGTH) {
+ *iv = OPENSSL_malloc(*ivlen);
+ if (*iv == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- *ivlen = iivlen;
}
if (!tls13_derive_key(s, md, secret, key, *keylen)
- || !tls13_derive_iv(s, md, secret, iv, *ivlen)) {
+ || !tls13_derive_iv(s, md, secret, *iv, *ivlen)) {
/* SSLfatal() already called */
return 0;
}
@@ -434,7 +463,8 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
static const unsigned char resumption_master_secret[] = "\x72\x65\x73\x20\x6D\x61\x73\x74\x65\x72";
/* ASCII: "e exp master", in hex for EBCDIC compatibility */
static const unsigned char early_exporter_master_secret[] = "\x65\x20\x65\x78\x70\x20\x6D\x61\x73\x74\x65\x72";
- unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char iv_intern[EVP_MAX_IV_LENGTH];
+ unsigned char *iv = iv_intern;
unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
@@ -446,17 +476,18 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
const unsigned char *label;
size_t labellen, hashlen = 0;
int ret = 0;
- const EVP_MD *md = NULL;
+ const EVP_MD *md = NULL, *mac_md = NULL;
const EVP_CIPHER *cipher = NULL;
+ int mac_pkey_type = NID_undef;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
- size_t keylen, ivlen, taglen;
+ size_t keylen, ivlen = EVP_MAX_IV_LENGTH, taglen;
int level;
int direction = (which & SSL3_CC_READ) != 0 ? OSSL_RECORD_DIRECTION_READ
: OSSL_RECORD_DIRECTION_WRITE;
if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
|| ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
- if (which & SSL3_CC_EARLY) {
+ if ((which & SSL3_CC_EARLY) != 0) {
EVP_MD_CTX *mdctx = NULL;
long handlen;
void *hdata;
@@ -496,6 +527,23 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
}
/*
+ * This ups the ref count on cipher so we better make sure we free
+ * it again
+ */
+ if (!ssl_cipher_get_evp_cipher(sctx, sslcipher, &cipher)) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
+ && (!ssl_cipher_get_evp_md_mac(sctx, sslcipher, &mac_md,
+ &mac_pkey_type, NULL))) {
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
* We need to calculate the handshake digest using the digest from
* the session. We haven't yet selected our ciphersuite so we can't
* use ssl_handshake_md().
@@ -506,17 +554,6 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
goto err;
}
- /*
- * This ups the ref count on cipher so we better make sure we free
- * it again
- */
- if (!ssl_cipher_get_evp_cipher(sctx, sslcipher, &cipher)) {
- /* Error is already recorded */
- SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
- EVP_MD_CTX_free(mdctx);
- goto err;
- }
-
md = ssl_md(sctx, sslcipher->algorithm2);
if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
|| !EVP_DigestUpdate(mdctx, hdata, handlen)
@@ -598,9 +635,11 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
}
}
- if (!(which & SSL3_CC_EARLY)) {
+ if ((which & SSL3_CC_EARLY) == 0) {
md = ssl_handshake_md(s);
cipher = s->s3.tmp.new_sym_enc;
+ mac_md = s->s3.tmp.new_hash;
+ mac_pkey_type = s->s3.tmp.new_mac_pkey_type;
if (!ssl3_digest_cached_records(s, 1)
|| !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
/* SSLfatal() already called */;
@@ -637,9 +676,9 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
if (!ossl_assert(cipher != NULL))
goto err;
- if (!derive_secret_key_and_iv(s, md, cipher,
+ if (!derive_secret_key_and_iv(s, md, cipher, mac_pkey_type, mac_md,
insecret, hash, label, labellen, secret, key,
- &keylen, iv, &ivlen, &taglen)) {
+ &keylen, &iv, &ivlen, &taglen)) {
/* SSLfatal() already called */
goto err;
}
@@ -692,8 +731,8 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
if (!ssl_set_new_record_layer(s, s->version,
direction,
level, secret, hashlen, key, keylen, iv,
- ivlen, NULL, 0, cipher, taglen, NID_undef,
- NULL, NULL, md)) {
+ ivlen, NULL, 0, cipher, taglen,
+ mac_pkey_type, mac_md, NULL, md)) {
/* SSLfatal already called */
goto err;
}
@@ -702,10 +741,14 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
err:
if ((which & SSL3_CC_EARLY) != 0) {
/* We up-refed this so now we need to down ref */
+ if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
+ ssl_evp_md_free(mac_md);
ssl_evp_cipher_free(cipher);
}
OPENSSL_cleanse(key, sizeof(key));
OPENSSL_cleanse(secret, sizeof(secret));
+ if (iv != iv_intern)
+ OPENSSL_free(iv);
return ret;
}
@@ -723,7 +766,8 @@ int tls13_update_key(SSL_CONNECTION *s, int sending)
int ret = 0, l;
int direction = sending ? OSSL_RECORD_DIRECTION_WRITE
: OSSL_RECORD_DIRECTION_READ;
- unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char iv_intern[EVP_MAX_IV_LENGTH];
+ unsigned char *iv = iv_intern;
if ((l = EVP_MD_get_size(md)) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
@@ -737,10 +781,12 @@ int tls13_update_key(SSL_CONNECTION *s, int sending)
insecret = s->client_app_traffic_secret;
if (!derive_secret_key_and_iv(s, md,
- s->s3.tmp.new_sym_enc, insecret, NULL,
+ s->s3.tmp.new_sym_enc,
+ s->s3.t