Convert SSLv3 handling to use provider side CBC/MAC removal
authorMatt Caswell <matt@openssl.org>
Fri, 26 Jun 2020 12:05:18 +0000 (13:05 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 6 Jul 2020 08:26:09 +0000 (09:26 +0100)
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12288)

ssl/record/ssl3_record.c
ssl/s3_enc.c
ssl/ssl_local.h
ssl/t1_enc.c

index 0c5ecae1a2afa69dc58c64075424879777fb64dc..6359c79bb167332627f318cb4fb21ad3a9f3d97d 100644 (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 (!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;
 }
index 5a807d6d5752647811f27e568b73da6265e40cf0..36b7c7616ee707900bb1d7f1581838c760797b0b 100644 (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:
index 17b856fabc4f47e34c01974fa6ea367f950cfac0..250098600f117258911f983d8cf9638974fe51e2 100644 (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 */
 
index 9a6c1799f75daa327ee57850094ba33353699a19..7c0b3e9d6503ee4bfe16cd601193852727aff2d3 100644 (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;