diff options
author | Matt Caswell <matt@openssl.org> | 2020-06-17 18:16:22 +0200 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2020-07-06 10:26:09 +0200 |
commit | 524cb684ac00922c4a21235a8ae2c66596893437 (patch) | |
tree | 8573cd013ac83ce9b4ba788d1c8abaf414e10b3a /ssl | |
parent | Add provider support for TLS CBC padding and MAC removal (diff) | |
download | openssl-524cb684ac00922c4a21235a8ae2c66596893437.tar.xz openssl-524cb684ac00922c4a21235a8ae2c66596893437.zip |
Make libssl start using the TLS provider CBC support
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12288)
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/record/ssl3_record.c | 159 | ||||
-rw-r--r-- | ssl/t1_enc.c | 32 |
2 files changed, 141 insertions, 50 deletions
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index 5efa77a5b3..0c5ecae1a2 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -10,6 +10,7 @@ #include "../ssl_local.h" #include <openssl/trace.h> #include <openssl/rand.h> +#include <openssl/core_names.h> #include "record_local.h" #include "internal/cryptlib.h" @@ -1140,63 +1141,121 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, } } - /* TODO(size_t): Convert this call */ - tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input, - (unsigned int)reclen[0]); - if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) - & EVP_CIPH_FLAG_CUSTOM_CIPHER) - ? (tmpr < 0) - : (tmpr == 0)) { - /* AEAD can fail to verify MAC */ - return 0; - } + if (EVP_CIPHER_provider(enc) != NULL) { + int outlen; - if (sending == 0) { - if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) { - for (ctr = 0; ctr < n_recs; ctr++) { - recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN; - recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN; - recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + /* Provided cipher - we do not support pipelining on this path */ + if (n_recs > 1) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!EVP_CipherUpdate(ds, recs[0].data, &outlen, recs[0].input, + (unsigned int)reclen[0])) + return 0; + recs[0].length = outlen; + + /* + * The length returned from EVP_CipherUpdate above is the actual + * payload length. We need to adjust the data/input ptr to skip over + * any explicit IV + */ + if (!sending) { + if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) { + recs[0].data += EVP_GCM_TLS_EXPLICIT_IV_LEN; + recs[0].input += EVP_GCM_TLS_EXPLICIT_IV_LEN; + } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) { + recs[0].data += EVP_CCM_TLS_EXPLICIT_IV_LEN; + recs[0].input += EVP_CCM_TLS_EXPLICIT_IV_LEN; + } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) { + recs[0].data += bs; + recs[0].input += bs; + recs[0].orig_len -= bs; } - } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) { - for (ctr = 0; ctr < n_recs; ctr++) { - recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN; - recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN; - recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + + /* Now get a pointer to the MAC (if applicable) */ + if (macs != NULL) { + OSSL_PARAM params[2], *p = params; + + /* Get the MAC */ + macs[0].alloced = 0; + + *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC, + (void **)&macs[0].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, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return 0; + } } } - } + } else { + /* Legacy cipher */ + + /* TODO(size_t): Convert this call */ + tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input, + (unsigned int)reclen[0]); + if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) + & EVP_CIPH_FLAG_CUSTOM_CIPHER) + ? (tmpr < 0) + : (tmpr == 0)) { + /* AEAD can fail to verify MAC */ + return 0; + } - if (!sending) { - for (ctr = 0; ctr < n_recs; ctr++) { - if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) { - if (recs[ctr].length < bs) + if (!sending) { + /* Adjust the record to remove the explicit IV/MAC/Tag */ + if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) { + for (ctr = 0; ctr < n_recs; ctr++) { + recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + } + } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) { + for (ctr = 0; ctr < n_recs; ctr++) { + recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + } + } + + for (ctr = 0; ctr < n_recs; ctr++) { + if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) { + if (recs[ctr].length < bs) + return 0; + recs[ctr].data += bs; + recs[ctr].input += bs; + recs[ctr].length -= bs; + recs[ctr].orig_len -= bs; + } + + /* + * If using Mac-then-encrypt, then this will succeed but + * with a random MAC if padding is invalid + */ + if (!tls1_cbc_remove_padding_and_mac(&recs[ctr].length, + recs[ctr].orig_len, + recs[ctr].data, + (macs != NULL) ? &macs[ctr].mac : NULL, + (macs != NULL) ? &macs[ctr].alloced + : NULL, + bs, + macsize, + (EVP_CIPHER_CTX_flags(s->enc_read_ctx) + & EVP_CIPH_FLAG_AEAD_CIPHER) != 0, + s->ctx->libctx)) return 0; - recs[ctr].data += bs; - recs[ctr].input += bs; - recs[ctr].length -= bs; - recs[ctr].orig_len -= bs; } - /* - * If using Mac-then-encrypt, then this will succeed but with a - * random MAC if padding is invalid - */ - if (!tls1_cbc_remove_padding_and_mac(&recs[ctr].length, - recs[ctr].orig_len, - recs[ctr].data, - (macs != NULL) ? &macs[ctr].mac : NULL, - (macs != NULL) ? &macs[ctr].alloced : NULL, - bs, - macsize, - (EVP_CIPHER_CTX_flags(s->enc_read_ctx) - & EVP_CIPH_FLAG_AEAD_CIPHER) != 0, - s->ctx->libctx)) - return 0; - } - } - if (pad && !sending) { - for (ctr = 0; ctr < n_recs; ctr++) { - recs[ctr].length -= pad; + if (pad) { + for (ctr = 0; ctr < n_recs; ctr++) { + recs[ctr].length -= pad; + } + } } } } diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index e929121cd2..9a6c1799f7 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -396,6 +396,38 @@ 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; + } + } #ifndef OPENSSL_NO_KTLS if (s->compress) goto skip_ktls; |