Convert SSLv3 handling to use provider side CBC/MAC removal

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12288)
This commit is contained in:
Matt Caswell 2020-06-26 13:05:18 +01:00
parent 63ee6ec177
commit b558817823
4 changed files with 97 additions and 46 deletions

View File

@ -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 (!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_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 (!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;
}

View File

@ -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:

View File

@ -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 */

View File

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