summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-06-17 18:16:22 +0200
committerMatt Caswell <matt@openssl.org>2020-07-06 10:26:09 +0200
commit524cb684ac00922c4a21235a8ae2c66596893437 (patch)
tree8573cd013ac83ce9b4ba788d1c8abaf414e10b3a /ssl
parentAdd provider support for TLS CBC padding and MAC removal (diff)
downloadopenssl-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.c159
-rw-r--r--ssl/t1_enc.c32
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;