diff --git a/ssl/record/methods/tls13_meth.c b/ssl/record/methods/tls13_meth.c index f5b028d61ac8f5..8e2719ef8c39fc 100644 --- a/ssl/record/methods/tls13_meth.c +++ b/ssl/record/methods/tls13_meth.c @@ -29,6 +29,8 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, OSSL_PARAM params[2], *p = params; int mode; int enc = (rl->direction == OSSL_RECORD_DIRECTION_WRITE) ? 1 : 0; + int only_mac = EVP_CIPHER_is_a(ciph, "NULL") && mactype == NID_hmac + && md != NULL; rl->iv = OPENSSL_zalloc(ivlen); if (rl->iv == NULL) @@ -51,21 +53,8 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, return OSSL_RECORD_RETURN_FATAL; } - mode = EVP_CIPHER_get_mode(ciph); - - if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, enc) <= 0 - || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, - NULL) <= 0 - || (mode == EVP_CIPH_CCM_MODE - && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, - NULL) <= 0) - || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, enc) <= 0) { - ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); - return OSSL_RECORD_RETURN_FATAL; - } - - /* Integrity only SSL cipher */ - if (md != NULL) { + /* Integrity only */ + if (only_mac) { mac = EVP_MAC_fetch(rl->libctx, "HMAC", rl->propq); if (mac == NULL || (mac_ctx = rl->mac_ctx = EVP_MAC_CTX_new(mac)) == NULL) { @@ -73,18 +62,31 @@ 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; } - + 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)){ - EVP_MAC_free(mac); + if (!EVP_MAC_init(mac_ctx, key, keylen, params)) { ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); return OSSL_RECORD_RETURN_FATAL; } - EVP_MAC_free(mac); + goto end; } + mode = EVP_CIPHER_get_mode(ciph); + + if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, enc) <= 0 + || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, + NULL) <= 0 + || (mode == EVP_CIPH_CCM_MODE + && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, + NULL) <= 0) + || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, enc) <= 0) { + ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); + return OSSL_RECORD_RETURN_FATAL; + } + + end: return OSSL_RECORD_RETURN_SUCCESS; } @@ -104,8 +106,7 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs, WPACKET wpkt; const EVP_CIPHER *cipher; EVP_MAC_CTX *mac_ctx = NULL; - int mode; - int ret = 0, only_mac = 0; /* set for MAC only, no encryption */ + int mode, ret = 0, only_mac = 0; /* set for MAC only, no encryption */ if (n_recs != 1) { /* Should not happen */ @@ -123,7 +124,7 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs, return 0; } mode = EVP_CIPHER_get_mode(cipher); - only_mac = EVP_CIPHER_is_a(cipher, "NULL"); + only_mac = EVP_CIPHER_is_a(cipher, "NULL") && rl->mac_ctx != NULL; /* * If we're sending an alert and ctx != NULL then we must be forcing @@ -137,8 +138,7 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs, return 1; } - if (only_mac) - { + if (only_mac) { if ((mac_ctx = EVP_MAC_CTX_dup(rl->mac_ctx)) == NULL) { RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); @@ -175,24 +175,6 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs, goto end; } - if (only_mac) { - if (!EVP_MAC_update(mac_ctx, nonce, ivlen)) - { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto end; - } - } else { - if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, 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); - goto end; - } - } - /* Set up the AAD */ if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) || !WPACKET_put_bytes_u8(&wpkt, rec->type) @@ -206,48 +188,56 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs, goto end; } + if (only_mac) { + if (!EVP_MAC_update(mac_ctx, nonce, ivlen) + || !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; + } + 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; + } + ret = 1; + goto end; + } + + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, 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; + } + /* * For CCM we must explicitly set the total plaintext length before we add * any AAD. */ - if (only_mac && (!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; - } - if ((mode == EVP_CIPH_CCM_MODE && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) || - EVP_CipherUpdate(ctx, NULL, &lenu, recheader, - sizeof(recheader)) <= 0 || - EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 || - EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 || - (size_t)(lenu + lenf) != rec->length) - { - goto end; + if ((mode == EVP_CIPH_CCM_MODE + && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, + (unsigned int)rec->length) <= 0) + || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, + sizeof(recheader)) <= 0 + || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, + (unsigned int)rec->length) <= 0 + || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 + || (size_t)(lenu + lenf) != rec->length) { + return 0; } if (sending) { /* Add the tag */ - if (only_mac) { - memcpy(rec->data + rec->length, tag, rl->taglen); - } else { - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen, - rec->data + rec->length) <= 0) - { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto end; - } + if (EVP_CIPHER_CTX_ctrl(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; } rec->length += rl->taglen; - } else if (only_mac - && CRYPTO_memcmp(tag, rec->data + rec->length, rl->taglen) != 0) { - goto end; - } - - + } ret = 1; end: EVP_MAC_CTX_free(mac_ctx); diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c index 058a8b0c41bdbc..2fc4b67a191d8c 100644 --- a/ssl/tls13_enc.c +++ b/ssl/tls13_enc.c @@ -720,8 +720,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, - mac_md, NULL, md)) { + ivlen, NULL, 0, cipher, taglen, + mac_pkey_type, mac_md, NULL, md)) { /* SSLfatal already called */ goto err; }