diff options
-rw-r--r-- | .github/workflows/run-checker-merge.yml | 1 | ||||
-rw-r--r-- | CHANGES.md | 7 | ||||
-rwxr-xr-x | Configure | 1 | ||||
-rw-r--r-- | INSTALL.md | 4 | ||||
-rw-r--r-- | doc/man1/openssl-ciphers.pod.in | 11 | ||||
-rw-r--r-- | doc/man3/SSL_CTX_set_cipher_list.pod | 4 | ||||
-rw-r--r-- | include/openssl/tls1.h | 6 | ||||
-rw-r--r-- | ssl/record/methods/recmethod_local.h | 7 | ||||
-rw-r--r-- | ssl/record/methods/tls13_meth.c | 127 | ||||
-rw-r--r-- | ssl/record/methods/tls_common.c | 4 | ||||
-rw-r--r-- | ssl/s3_lib.c | 60 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 61 | ||||
-rw-r--r-- | ssl/ssl_local.h | 3 | ||||
-rw-r--r-- | ssl/t1_trce.c | 2 | ||||
-rw-r--r-- | ssl/tls13_enc.c | 162 | ||||
-rw-r--r-- | test/ciphername_test.c | 2 | ||||
-rw-r--r-- | test/evp_libctx_test.c | 12 | ||||
-rw-r--r-- | test/evp_test.c | 2 | ||||
-rw-r--r-- | test/helpers/ssltestlib.h | 2 | ||||
-rw-r--r-- | test/quicapitest.c | 10 | ||||
-rw-r--r-- | test/sslapitest.c | 65 | ||||
-rw-r--r-- | test/tls13secretstest.c | 7 |
22 files changed, 423 insertions, 137 deletions
diff --git a/.github/workflows/run-checker-merge.yml b/.github/workflows/run-checker-merge.yml index 8a1da0c2f2..98dcde18b9 100644 --- a/.github/workflows/run-checker-merge.yml +++ b/.github/workflows/run-checker-merge.yml @@ -33,6 +33,7 @@ jobs: no-srp, no-srtp, no-ts, + no-integrity-only-ciphers, enable-weak-ssl-ciphers, enable-zlib, enable-pie, diff --git a/CHANGES.md b/CHANGES.md index 9211c30be3..cf0efe31ba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -53,6 +53,13 @@ OpenSSL 3.4 *Tim Perry* + * Added support for integrity-only cipher suites TLS_SHA256_SHA256 and + TLS_SHA384_SHA384 in TLS 1.3, as defined in RFC 9150. + + This work was sponsored by Siemens AG. + + *Rajeev Ranjan* + * Added support for requesting CRL in CMP. This work was sponsored by Siemens AG. @@ -529,6 +529,7 @@ my @disablables = ( "thread-pool", "threads", "tls", + "integrity-only-ciphers", "trace", "ts", "ubsan", diff --git a/INSTALL.md b/INSTALL.md index a34de9bbf8..6073979bc0 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1117,6 +1117,10 @@ synonymous with `no-ssl3`. Note this only affects version negotiation. OpenSSL will still provide the methods for applications to explicitly select the individual protocol versions. +### no-integrity-only-ciphers + +Don't build support for integrity only ciphers in tls. + ### no-{protocol}-method no-{ssl3|tls1|tls1_1|tls1_2|dtls1|dtls1_2}-method diff --git a/doc/man1/openssl-ciphers.pod.in b/doc/man1/openssl-ciphers.pod.in index a84d2daff5..5239beca1d 100644 --- a/doc/man1/openssl-ciphers.pod.in +++ b/doc/man1/openssl-ciphers.pod.in @@ -738,6 +738,15 @@ Note: the CBC modes mentioned in this RFC are not supported. TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_8_SHA256 TLS_AES_128_CCM_8_SHA256 +=head2 TLS v1.3 integrity-only cipher suites according to RFC 9150 + + TLS_SHA256_SHA256 TLS_SHA256_SHA256 + TLS_SHA384_SHA384 TLS_SHA384_SHA384 + +Note: these ciphers are purely HMAC based and do not provide any confidentiality +and thus are disabled by default. +These ciphers are only available at security level 0. + =head2 Older names used by OpenSSL The following names are accepted by older releases: @@ -802,6 +811,8 @@ The B<-convert> option was added in OpenSSL 1.1.1. Support for standard IANA names in cipher lists was added in OpenSSL 3.2.0. +The support for TLS v1.3 integrity-only cipher suites was added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/SSL_CTX_set_cipher_list.pod b/doc/man3/SSL_CTX_set_cipher_list.pod index 71f399400c..0fe8be8094 100644 --- a/doc/man3/SSL_CTX_set_cipher_list.pod +++ b/doc/man3/SSL_CTX_set_cipher_list.pod @@ -50,6 +50,10 @@ ciphersuite names in order of preference. Valid TLSv1.3 ciphersuite names are: =item TLS_AES_128_CCM_8_SHA256 +=item TLS_SHA384_SHA384 - integrity-only + +=item TLS_SHA256_SHA256 - integrity-only + =back An empty list is permissible. The default value for the this setting is: diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 7e3d1a725b..8ff39e3956 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -622,6 +622,10 @@ int SSL_CTX_set_tlsext_ticket_key_evp_cb # define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304 # define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305 +/* Integrity-only ciphersuites from RFC 9150 */ +# define TLS1_3_CK_SHA256_SHA256 0x0300C0B4 +# define TLS1_3_CK_SHA384_SHA384 0x0300C0B5 + /* Aria ciphersuites from RFC6209 */ # define TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C050 # define TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C051 @@ -699,6 +703,8 @@ int SSL_CTX_set_tlsext_ticket_key_evp_cb # define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256" # define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" # define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" +# define TLS1_3_RFC_SHA256_SHA256 "TLS_SHA256_SHA256" +# define TLS1_3_RFC_SHA384_SHA384 "TLS_SHA384_SHA384" # define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256" # define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256" # define TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA "TLS_ECDHE_ECDSA_WITH_NULL_SHA" 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); + retur |