Make EVP_MD_CTX_ctrl() work for legacy use cases (ssl3).
[openssl.git] / ssl / s3_enc.c
index 966d498e612288a61deb84bd87f21b4ea04b701b..6c3b7110723e010f65f61bc722dd489c9eb113ac 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright 2005 Nokia. All rights reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
@@ -12,6 +12,7 @@
 #include "ssl_locl.h"
 #include <openssl/evp.h>
 #include <openssl/md5.h>
+#include <openssl/core_names.h>
 #include "internal/cryptlib.h"
 
 static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
@@ -51,8 +52,8 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
             || !EVP_DigestUpdate(s1, buf, k)
             || !EVP_DigestUpdate(s1, s->session->master_key,
                                  s->session->master_key_length)
-            || !EVP_DigestUpdate(s1, s->s3->server_random, SSL3_RANDOM_SIZE)
-            || !EVP_DigestUpdate(s1, s->s3->client_random, SSL3_RANDOM_SIZE)
+            || !EVP_DigestUpdate(s1, s->s3.server_random, SSL3_RANDOM_SIZE)
+            || !EVP_DigestUpdate(s1, s->s3.client_random, SSL3_RANDOM_SIZE)
             || !EVP_DigestFinal_ex(s1, smd, NULL)
             || !EVP_DigestInit_ex(m5, EVP_md5(), NULL)
             || !EVP_DigestUpdate(m5, s->session->master_key,
@@ -90,8 +91,6 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
 int ssl3_change_cipher_state(SSL *s, int which)
 {
     unsigned char *p, *mac_secret;
-    unsigned char exp_key[EVP_MAX_KEY_LENGTH];
-    unsigned char exp_iv[EVP_MAX_IV_LENGTH];
     unsigned char *ms, *key, *iv;
     EVP_CIPHER_CTX *dd;
     const EVP_CIPHER *c;
@@ -103,8 +102,8 @@ int ssl3_change_cipher_state(SSL *s, int which)
     size_t n, i, j, k, cl;
     int reuse_dd = 0;
 
-    c = s->s3->tmp.new_sym_enc;
-    m = s->s3->tmp.new_hash;
+    c = s->s3.tmp.new_sym_enc;
+    m = s->s3.tmp.new_hash;
     /* m == NULL will lead to a crash later */
     if (!ossl_assert(m != NULL)) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
@@ -112,10 +111,10 @@ int ssl3_change_cipher_state(SSL *s, int which)
         goto err;
     }
 #ifndef OPENSSL_NO_COMP
-    if (s->s3->tmp.new_compression == NULL)
+    if (s->s3.tmp.new_compression == NULL)
         comp = NULL;
     else
-        comp = s->s3->tmp.new_compression->method;
+        comp = s->s3.tmp.new_compression->method;
 #endif
 
     if (which & SSL3_CC_READ) {
@@ -153,9 +152,9 @@ int ssl3_change_cipher_state(SSL *s, int which)
         }
 #endif
         RECORD_LAYER_reset_read_sequence(&s->rlayer);
-        mac_secret = &(s->s3->read_mac_secret[0]);
+        mac_secret = &(s->s3.read_mac_secret[0]);
     } else {
-        s->statem.invalid_enc_write_ctx = 1;
+        s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
         if (s->enc_write_ctx != NULL) {
             reuse_dd = 1;
         } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
@@ -168,7 +167,6 @@ int ssl3_change_cipher_state(SSL *s, int which)
              */
             EVP_CIPHER_CTX_reset(s->enc_write_ctx);
         }
-        EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, EVP_CTRL_SET_DRBG, 0, s->drbg);
         dd = s->enc_write_ctx;
         if (ssl_replace_hash(&s->write_hash, m) == NULL) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
@@ -190,13 +188,13 @@ int ssl3_change_cipher_state(SSL *s, int which)
         }
 #endif
         RECORD_LAYER_reset_write_sequence(&s->rlayer);
-        mac_secret = &(s->s3->write_mac_secret[0]);
+        mac_secret = &(s->s3.write_mac_secret[0]);
     }
 
     if (reuse_dd)
         EVP_CIPHER_CTX_reset(dd);
 
-    p = s->s3->tmp.key_block;
+    p = s->s3.tmp.key_block;
     mdi = EVP_MD_size(m);
     if (mdi < 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
@@ -225,7 +223,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
         n += k;
     }
 
-    if (n > s->s3->tmp.key_block_length) {
+    if (n > s->s3.tmp.key_block_length) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
                  ERR_R_INTERNAL_ERROR);
         goto err;
@@ -239,13 +237,9 @@ int ssl3_change_cipher_state(SSL *s, int which)
         goto err;
     }
 
-    s->statem.invalid_enc_write_ctx = 0;
-    OPENSSL_cleanse(exp_key, sizeof(exp_key));
-    OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
+    s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
     return 1;
  err:
-    OPENSSL_cleanse(exp_key, sizeof(exp_key));
-    OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
     return 0;
 }
 
@@ -258,7 +252,7 @@ int ssl3_setup_key_block(SSL *s)
     int ret = 0;
     SSL_COMP *comp;
 
-    if (s->s3->tmp.key_block_length != 0)
+    if (s->s3.tmp.key_block_length != 0)
         return 1;
 
     if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) {
@@ -267,12 +261,12 @@ int ssl3_setup_key_block(SSL *s)
         return 0;
     }
 
-    s->s3->tmp.new_sym_enc = c;
-    s->s3->tmp.new_hash = hash;
+    s->s3.tmp.new_sym_enc = c;
+    s->s3.tmp.new_hash = hash;
 #ifdef OPENSSL_NO_COMP
-    s->s3->tmp.new_compression = NULL;
+    s->s3.tmp.new_compression = NULL;
 #else
-    s->s3->tmp.new_compression = comp;
+    s->s3.tmp.new_compression = comp;
 #endif
 
     num = EVP_MD_size(hash);
@@ -290,8 +284,8 @@ int ssl3_setup_key_block(SSL *s)
         return 0;
     }
 
-    s->s3->tmp.key_block_length = num;
-    s->s3->tmp.key_block = p;
+    s->s3.tmp.key_block_length = num;
+    s->s3.tmp.key_block = p;
 
     /* Calls SSLfatal() as required */
     ret = ssl3_generate_key_block(s, p, num);
@@ -301,15 +295,15 @@ int ssl3_setup_key_block(SSL *s)
          * enable vulnerability countermeasure for CBC ciphers with known-IV
          * problem (http://www.openssl.org/~bodo/tls-cbc.txt)
          */
-        s->s3->need_empty_fragments = 1;
+        s->s3.need_empty_fragments = 1;
 
         if (s->session->cipher != NULL) {
             if (s->session->cipher->algorithm_enc == SSL_eNULL)
-                s->s3->need_empty_fragments = 0;
+                s->s3.need_empty_fragments = 0;
 
 #ifndef OPENSSL_NO_RC4
             if (s->session->cipher->algorithm_enc == SSL_RC4)
-                s->s3->need_empty_fragments = 0;
+                s->s3.need_empty_fragments = 0;
 #endif
         }
     }
@@ -319,9 +313,9 @@ int ssl3_setup_key_block(SSL *s)
 
 void ssl3_cleanup_key_block(SSL *s)
 {
-    OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length);
-    s->s3->tmp.key_block = NULL;
-    s->s3->tmp.key_block_length = 0;
+    OPENSSL_clear_free(s->s3.tmp.key_block, s->s3.tmp.key_block_length);
+    s->s3.tmp.key_block = NULL;
+    s->s3.tmp.key_block_length = 0;
 }
 
 int ssl3_init_finished_mac(SSL *s)
@@ -334,8 +328,8 @@ int ssl3_init_finished_mac(SSL *s)
         return 0;
     }
     ssl3_free_digest_list(s);
-    s->s3->handshake_buffer = buf;
-    (void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
+    s->s3.handshake_buffer = buf;
+    (void)BIO_set_close(s->s3.handshake_buffer, BIO_CLOSE);
     return 1;
 }
 
@@ -346,31 +340,31 @@ int ssl3_init_finished_mac(SSL *s)
 
 void ssl3_free_digest_list(SSL *s)
 {
-    BIO_free(s->s3->handshake_buffer);
-    s->s3->handshake_buffer = NULL;
-    EVP_MD_CTX_free(s->s3->handshake_dgst);
-    s->s3->handshake_dgst = NULL;
+    BIO_free(s->s3.handshake_buffer);
+    s->s3.handshake_buffer = NULL;
+    EVP_MD_CTX_free(s->s3.handshake_dgst);
+    s->s3.handshake_dgst = NULL;
 }
 
 int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len)
 {
     int ret;
 
-    if (s->s3->handshake_dgst == NULL) {
+    if (s->s3.handshake_dgst == NULL) {
         /* Note: this writes to a memory BIO so a failure is a fatal error */
         if (len > INT_MAX) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
                      SSL_R_OVERFLOW_ERROR);
             return 0;
         }
-        ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len);
+        ret = BIO_write(s->s3.handshake_buffer, (void *)buf, (int)len);
         if (ret <= 0 || ret != (int)len) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
                      ERR_R_INTERNAL_ERROR);
             return 0;
         }
     } else {
-        ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
+        ret = EVP_DigestUpdate(s->s3.handshake_dgst, buf, len);
         if (!ret) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
                      ERR_R_INTERNAL_ERROR);
@@ -386,37 +380,48 @@ int ssl3_digest_cached_records(SSL *s, int keep)
     long hdatalen;
     void *hdata;
 
-    if (s->s3->handshake_dgst == NULL) {
-        hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+    if (s->s3.handshake_dgst == NULL) {
+        hdatalen = BIO_get_mem_data(s->s3.handshake_buffer, &hdata);
         if (hdatalen <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
                      SSL_R_BAD_HANDSHAKE_LENGTH);
             return 0;
         }
 
-        s->s3->handshake_dgst = EVP_MD_CTX_new();
-        if (s->s3->handshake_dgst == NULL) {
+        s->s3.handshake_dgst = EVP_MD_CTX_new();
+        if (s->s3.handshake_dgst == NULL) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
                      ERR_R_MALLOC_FAILURE);
             return 0;
         }
 
         md = ssl_handshake_md(s);
-        if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL)
-            || !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) {
+        if (md == NULL || !EVP_DigestInit_ex(s->s3.handshake_dgst, md, NULL)
+            || !EVP_DigestUpdate(s->s3.handshake_dgst, hdata, hdatalen)) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
                      ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
     if (keep == 0) {
-        BIO_free(s->s3->handshake_buffer);
-        s->s3->handshake_buffer = NULL;
+        BIO_free(s->s3.handshake_buffer);
+        s->s3.handshake_buffer = NULL;
     }
 
     return 1;
 }
 
+void ssl3_digest_master_key_set_params(const SSL_SESSION *session,
+                                       OSSL_PARAM params[])
+{
+    int n = 0;
+    params[n++] = OSSL_PARAM_construct_octet_string(OSSL_DIGEST_PARAM_SSL3_MS,
+                                                    (void *)session->master_key,
+                                                    session->master_key_length,
+                                                    NULL);
+    params[n++] = OSSL_PARAM_construct_end();
+}
+
 size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
                              unsigned char *p)
 {
@@ -428,7 +433,7 @@ size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
         return 0;
     }
 
-    if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) {
+    if (EVP_MD_CTX_type(s->s3.handshake_dgst) != NID_md5_sha1) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
                  SSL_R_NO_REQUIRED_DIGEST);
         return 0;
@@ -440,30 +445,36 @@ size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
                  ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) {
+    if (!EVP_MD_CTX_copy_ex(ctx, s->s3.handshake_dgst)) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
                  ERR_R_INTERNAL_ERROR);
-        return 0;
+        ret = 0;
+        goto err;
     }
 
     ret = EVP_MD_CTX_size(ctx);
     if (ret < 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
                  ERR_R_INTERNAL_ERROR);
-        EVP_MD_CTX_reset(ctx);
-        return 0;
+        ret = 0;
+        goto err;
     }
 
-    if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0)
-        || EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
-                           (int)s->session->master_key_length,
-                           s->session->master_key) <= 0
-        || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
-                 ERR_R_INTERNAL_ERROR);
-        ret = 0;
+    if (sender != NULL) {
+        OSSL_PARAM digest_cmd_params[3];
+
+        ssl3_digest_master_key_set_params(s->session, digest_cmd_params);
+
+        if (EVP_DigestUpdate(ctx, sender, len) <= 0
+            || EVP_MD_CTX_set_params(ctx, digest_cmd_params) <= 0
+            || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
+                         ERR_R_INTERNAL_ERROR);
+                ret = 0;
+        }
     }
 
+ err:
     EVP_MD_CTX_free(ctx);
 
     return ret;
@@ -499,9 +510,9 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
             || EVP_DigestUpdate(ctx, salt[i],
                                 strlen((const char *)salt[i])) <= 0
             || EVP_DigestUpdate(ctx, p, len) <= 0
-            || EVP_DigestUpdate(ctx, &(s->s3->client_random[0]),
+            || EVP_DigestUpdate(ctx, &(s->s3.client_random[0]),
                                 SSL3_RANDOM_SIZE) <= 0
-            || EVP_DigestUpdate(ctx, &(s->s3->server_random[0]),
+            || EVP_DigestUpdate(ctx, &(s->s3.server_random[0]),
                                 SSL3_RANDOM_SIZE) <= 0
                /* TODO(size_t) : convert me */
             || EVP_DigestFinal_ex(ctx, buf, &n) <= 0