From: Matt Caswell Date: Fri, 26 Jun 2020 12:05:18 +0000 (+0100) Subject: Convert SSLv3 handling to use provider side CBC/MAC removal X-Git-Tag: openssl-3.0.0-alpha5~68 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=b5588178232f5cbf32662dfa173c72a001d54aeb Convert SSLv3 handling to use provider side CBC/MAC removal Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/12288) --- diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index 0c5ecae1a2..6359c79bb1 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -897,22 +897,51 @@ int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending, /* otherwise, rec->length >= bs */ } - /* TODO(size_t): Convert this call */ - if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) { - /* Shouldn't happen */ - SSLfatal(s, SSL_AD_BAD_RECORD_MAC, 0, ERR_R_INTERNAL_ERROR); - return 0; - } + if (EVP_CIPHER_provider(enc) != NULL) { + int outlen; + + if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input, + (unsigned int)l)) + return 0; + rec->length = outlen; + + if (!sending && mac != NULL) { + /* Now get a pointer to the MAC */ + OSSL_PARAM params[2], *p = params; + + /* Get the MAC */ + mac->alloced = 0; + + *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC, + (void **)&mac->mac, + macsize); + *p = OSSL_PARAM_construct_end(); - if (!sending) - return ssl3_cbc_remove_padding_and_mac(&rec->length, - rec->orig_len, - rec->data, - (mac != NULL) ? &mac->mac : NULL, - (mac != NULL) ? &mac->alloced : NULL, - bs, - macsize, - s->ctx->libctx); + if (!EVP_CIPHER_CTX_get_params(ds, params)) { + /* Shouldn't normally happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, 0, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } else { + /* TODO(size_t): Convert this call */ + if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) { + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_BAD_RECORD_MAC, 0, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!sending) + return ssl3_cbc_remove_padding_and_mac(&rec->length, + rec->orig_len, + rec->data, + (mac != NULL) ? &mac->mac : NULL, + (mac != NULL) ? &mac->alloced : NULL, + bs, + macsize, + s->ctx->libctx); + } } return 1; } diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 5a807d6d57..36b7c7616e 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -241,6 +241,12 @@ int ssl3_change_cipher_state(SSL *s, int which) goto err; } + if (EVP_CIPHER_provider(c) != NULL + && !tls_provider_set_tls_params(s, dd, c, m)) { + /* SSLfatal already called */ + goto err; + } + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; return 1; err: diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 17b856fabc..250098600f 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -2804,6 +2804,9 @@ const EVP_MD *ssl_evp_md_fetch(OPENSSL_CTX *libctx, int ssl_evp_md_up_ref(const EVP_MD *md); void ssl_evp_md_free(const EVP_MD *md); +int tls_provider_set_tls_params(SSL *s, EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *ciph, + const EVP_MD *md); # else /* OPENSSL_UNIT_TEST */ diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 9a6c1799f7..7c0b3e9d65 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -136,6 +136,45 @@ static int count_unprocessed_records(SSL *s) # endif #endif + +int tls_provider_set_tls_params(SSL *s, EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *ciph, + const EVP_MD *md) +{ + /* + * Provided cipher, the TLS padding/MAC removal is performed provider + * side so we need to tell the ctx about our TLS version and mac size + */ + OSSL_PARAM params[3], *pprm = params; + size_t macsize = 0; + int imacsize = -1; + + if ((EVP_CIPHER_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER) == 0 + /* + * We look at s->ext.use_etm instead of SSL_READ_ETM() or + * SSL_WRITE_ETM() because this test applies to both reading + * and writing. + */ + && !s->ext.use_etm) + imacsize = EVP_MD_size(md); + if (imacsize >= 0) + macsize = (size_t)imacsize; + + *pprm++ = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_TLS_VERSION, + &s->version); + *pprm++ = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_TLS_MAC_SIZE, + &macsize); + *pprm = OSSL_PARAM_construct_end(); + + if (!EVP_CIPHER_CTX_set_params(ctx, params)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + int tls1_change_cipher_state(SSL *s, int which) { unsigned char *p, *mac_secret; @@ -396,38 +435,12 @@ int tls1_change_cipher_state(SSL *s, int which) ERR_R_INTERNAL_ERROR); goto err; } - if (EVP_CIPHER_provider(c) != NULL) { - /* - * Provided cipher, the TLS padding/MAC removal is performed provider - * side so we need to tell the ctx about our TLS version and mac size - */ - OSSL_PARAM params[3], *pprm = params; - size_t macsize = 0; - int imacsize = -1; - - if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) == 0 - /* - * We look at s->ext.use_etm instead of SSL_READ_ETM() or - * SSL_WRITE_ETM() because this test applies to both reading - * and writing. - */ - && !s->ext.use_etm) - imacsize = EVP_MD_size(m); - if (imacsize >= 0) - macsize = (size_t)imacsize; - - *pprm++ = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_TLS_VERSION, - &s->version); - *pprm++ = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_TLS_MAC_SIZE, - &macsize); - *pprm = OSSL_PARAM_construct_end(); - - if (!EVP_CIPHER_CTX_set_params(dd, params)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, - ERR_R_INTERNAL_ERROR); - goto err; - } + if (EVP_CIPHER_provider(c) != NULL + && !tls_provider_set_tls_params(s, dd, c, m)) { + /* SSLfatal already called */ + goto err; } + #ifndef OPENSSL_NO_KTLS if (s->compress) goto skip_ktls;