Implement a replacement for SSL_set_tmp_dh()
authorMatt Caswell <matt@openssl.org>
Thu, 15 Oct 2020 15:45:54 +0000 (16:45 +0100)
committerMatt Caswell <matt@openssl.org>
Wed, 18 Nov 2020 14:14:52 +0000 (14:14 +0000)
The old function took a DH as a parameter. In the new version we pass
an EVP_PKEY instead. Similarly for the SSL_CTX version of this function.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13368)

apps/s_server.c
include/openssl/ssl.h.in
ssl/s3_lib.c
ssl/ssl_conf.c
ssl/ssl_lib.c
ssl/tls_depr.c
util/libssl.num

index 18d0fad174144df6421776b9e194410ba224e58a..839d9320ff1d7036093fc4a41b51615667e206e4 100644 (file)
@@ -21,6 +21,7 @@
 #include <openssl/e_os2.h>
 #include <openssl/async.h>
 #include <openssl/ssl.h>
+#include <openssl/decoder.h>
 
 #ifndef OPENSSL_NO_SOCK
 
@@ -71,9 +72,6 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
                                unsigned int *id_len);
 static void init_session_cache_ctx(SSL_CTX *sctx);
 static void free_sessions(void);
-#ifndef OPENSSL_NO_DH
-static DH *load_dh_param(const char *dhfile);
-#endif
 static void print_connection_info(SSL *con);
 
 static const int bufsize = 16 * 1024;
@@ -2030,62 +2028,67 @@ int s_server_main(int argc, char *argv[])
     if (alpn_ctx.data)
         SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
 
-#ifndef OPENSSL_NO_DH
     if (!no_dhe) {
-        DH *dh = NULL;
+        EVP_PKEY *dhpkey = NULL;
 
         if (dhfile != NULL)
-            dh = load_dh_param(dhfile);
+            dhpkey = load_keyparams(dhfile, 0, "DH", "DH parameters");
         else if (s_cert_file != NULL)
-            dh = load_dh_param(s_cert_file);
+            dhpkey = load_keyparams(s_cert_file, 0, "DH", "DH parameters");
 
-        if (dh != NULL) {
+        if (dhpkey != NULL) {
             BIO_printf(bio_s_out, "Setting temp DH parameters\n");
         } else {
             BIO_printf(bio_s_out, "Using default temp DH parameters\n");
         }
         (void)BIO_flush(bio_s_out);
 
-        if (dh == NULL) {
+        if (dhpkey == NULL) {
             SSL_CTX_set_dh_auto(ctx, 1);
+        } else {
+            /*
+             * We need 2 references: one for use by ctx and one for use by
+             * ctx2
+             */
+            if (!EVP_PKEY_up_ref(dhpkey)) {
+                EVP_PKEY_free(dhpkey);
+                goto end;
+            }
+            if (!SSL_CTX_set0_tmp_dh_pkey(ctx, dhpkey)) {
+                BIO_puts(bio_err, "Error setting temp DH parameters\n");
+                ERR_print_errors(bio_err);
+                /* Free 2 references */
+                EVP_PKEY_free(dhpkey);
+                EVP_PKEY_free(dhpkey);
+                goto end;
+            }
         }
-# ifndef OPENSSL_NO_DEPRECATED_3_0
-        /* TODO(3.0): We need a 3.0 friendly way of doing this */
-        else if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
-            BIO_puts(bio_err, "Error setting temp DH parameters\n");
-            ERR_print_errors(bio_err);
-            DH_free(dh);
-            goto end;
-        }
-# endif
 
         if (ctx2 != NULL) {
-            if (!dhfile) {
-                DH *dh2 = load_dh_param(s_cert_file2);
-                if (dh2 != NULL) {
+            if (dhfile != NULL) {
+                EVP_PKEY *dhpkey2 = load_keyparams(s_cert_file2, 0, "DH",
+                                                   "DH parameters");
+
+                if (dhpkey2 != NULL) {
                     BIO_printf(bio_s_out, "Setting temp DH parameters\n");
                     (void)BIO_flush(bio_s_out);
 
-                    DH_free(dh);
-                    dh = dh2;
+                    EVP_PKEY_free(dhpkey);
+                    dhpkey = dhpkey2;
                 }
             }
-            if (dh == NULL) {
+            if (dhpkey == NULL) {
                 SSL_CTX_set_dh_auto(ctx2, 1);
-            }
-# ifndef OPENSSL_NO_DEPRECATED_3_0
-          /* TODO(3.0): We need a 3.0 friendly way of doing this */
-            else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
+            } else if (!SSL_CTX_set0_tmp_dh_pkey(ctx2, dhpkey)) {
                 BIO_puts(bio_err, "Error setting temp DH parameters\n");
                 ERR_print_errors(bio_err);
-                DH_free(dh);
+                EVP_PKEY_free(dhpkey);
                 goto end;
             }
-# endif
+            dhpkey = NULL;
         }
-        DH_free(dh);
+        EVP_PKEY_free(dhpkey);
     }
-#endif
 
     if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
         goto end;
@@ -3011,26 +3014,6 @@ static void print_connection_info(SSL *con)
     (void)BIO_flush(bio_s_out);
 }
 
-#ifndef OPENSSL_NO_DH
-static DH *load_dh_param(const char *dhfile)
-{
-# ifndef OPENSSL_NO_DEPRECATED_3_0
-    /* TODO(3.0): Use a decoder for this */
-    DH *ret = NULL;
-    BIO *bio;
-
-    if ((bio = BIO_new_file(dhfile, "r")) == NULL)
-        goto err;
-    ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- err:
-    BIO_free(bio);
-    return ret;
-# else
-    return NULL;
-# endif
-}
-#endif
-
 static int www_body(int s, int stype, int prot, unsigned char *context)
 {
     char *buf = NULL;
index cd3abd8c2688cf29f42d788f8865a488ebf7c34b..a02227be0cdbc8ade4dfd844075e030c0360f536 100644 (file)
@@ -1505,6 +1505,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 # define SSL_get_server_tmp_key(s, pk) \
          SSL_get_peer_tmp_key(s, pk)
 
+int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
+int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);
+
 /*
  * The following symbol names are old and obsolete. They are kept
  * for compatibility reasons only and should not be used anymore.
index 664844302a45c06622744a03193d42fa8b01685f..8a572b8dd37d4c2cbdcb7e8c9ad4f7dbe79a33ec 100644 (file)
@@ -3465,15 +3465,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
                 ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
                 return 0;
             }
-            if (!ssl_security(s, SSL_SECOP_TMP_DH,
-                              EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
-                ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
-                EVP_PKEY_free(pkdh);
-                return 0;
-            }
-            EVP_PKEY_free(s->cert->dh_tmp);
-            s->cert->dh_tmp = pkdh;
-            return 1;
+            return SSL_set0_tmp_dh_pkey(s, pkdh);
         }
         break;
     case SSL_CTRL_SET_TMP_DH_CB:
@@ -3816,15 +3808,7 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
                 ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
                 return 0;
             }
-            if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
-                                  EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
-                ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
-                EVP_PKEY_free(pkdh);
-                return 0;
-            }
-            EVP_PKEY_free(ctx->cert->dh_tmp);
-            ctx->cert->dh_tmp = pkdh;
-            return 1;
+            return SSL_CTX_set0_tmp_dh_pkey(ctx, pkdh);
         }
     case SSL_CTRL_SET_TMP_DH_CB:
         {
index 2311df5d84d8ed4d49a5c291e2942e6001b9bb2f..2e8240c73b820ce6e2b7c1574976219bfa1d7383 100644 (file)
@@ -11,7 +11,8 @@
 #include "ssl_local.h"
 #include <openssl/conf.h>
 #include <openssl/objects.h>
-#include <openssl/dh.h>
+#include <openssl/decoder.h>
+#include <openssl/core_dispatch.h>
 #include "internal/nelem.h"
 
 /*
@@ -574,34 +575,51 @@ static int cmd_ClientCAStore(SSL_CONF_CTX *cctx, const char *value)
     return cmd_RequestCAStore(cctx, value);
 }
 
-#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
-/* TODO(3.0): We need a 3.0 friendly way of doing this */
 static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
 {
     int rv = 0;
-    DH *dh = NULL;
+    EVP_PKEY *dhpkey = NULL;
     BIO *in = NULL;
-    if (cctx->ctx || cctx->ssl) {
+    SSL_CTX *sslctx = (cctx->ssl != NULL) ? cctx->ssl->ctx : cctx->ctx;
+    OSSL_DECODER_CTX *decoderctx = NULL;
+
+    if (cctx->ctx != NULL || cctx->ssl != NULL) {
         in = BIO_new(BIO_s_file());
         if (in == NULL)
             goto end;
         if (BIO_read_filename(in, value) <= 0)
             goto end;
-        dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
-        if (dh == NULL)
+
+        decoderctx
+            = OSSL_DECODER_CTX_new_by_EVP_PKEY(&dhpkey, "PEM", NULL, "DH",
+                                               OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+                                               sslctx->libctx, sslctx->propq);
+        if (decoderctx == NULL
+                || !OSSL_DECODER_from_bio(decoderctx, in)) {
+            OSSL_DECODER_CTX_free(decoderctx);
+            goto end;
+        }
+        OSSL_DECODER_CTX_free(decoderctx);
+
+        if (dhpkey == NULL)
             goto end;
-    } else
+    } else {
         return 1;
-    if (cctx->ctx)
-        rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
-    if (cctx->ssl)
-        rv = SSL_set_tmp_dh(cctx->ssl, dh);
+    }
+
+    if (cctx->ctx != NULL) {
+        if ((rv = SSL_CTX_set0_tmp_dh_pkey(cctx->ctx, dhpkey)) > 0)
+            dhpkey = NULL;
+    }
+    if (cctx->ssl != NULL) {
+        if ((rv = SSL_set0_tmp_dh_pkey(cctx->ssl, dhpkey)) > 0)
+            dhpkey = NULL;
+    }
  end:
-    DH_free(dh);
+    EVP_PKEY_free(dhpkey);
     BIO_free(in);
     return rv > 0;
 }
-#endif
 
 static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
 {
@@ -727,11 +745,9 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
     SSL_CONF_CMD(ClientCAStore, NULL,
                  SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
                  SSL_CONF_TYPE_STORE),
-#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
     SSL_CONF_CMD(DHParameters, "dhparam",
                  SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
                  SSL_CONF_TYPE_FILE),
-#endif
     SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0),
     SSL_CONF_CMD_STRING(NumTickets, "num_tickets", SSL_CONF_FLAG_SERVER),
 };
index bd7b83825091a71e2e955b4abe24499db2cfbe39..8f6771da3dddaf5f36b0d68398d750aefc11db6d 100644 (file)
@@ -5955,3 +5955,29 @@ void ssl_evp_md_free(const EVP_MD *md)
         EVP_MD_free((EVP_MD *)md);
     }
 }
+
+int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey)
+{
+    if (!ssl_security(s, SSL_SECOP_TMP_DH,
+                      EVP_PKEY_security_bits(dhpkey), 0, dhpkey)) {
+        SSLerr(0, SSL_R_DH_KEY_TOO_SMALL);
+        EVP_PKEY_free(dhpkey);
+        return 0;
+    }
+    EVP_PKEY_free(s->cert->dh_tmp);
+    s->cert->dh_tmp = dhpkey;
+    return 1;
+}
+
+int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey)
+{
+    if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
+                          EVP_PKEY_security_bits(dhpkey), 0, dhpkey)) {
+        SSLerr(0, SSL_R_DH_KEY_TOO_SMALL);
+        EVP_PKEY_free(dhpkey);
+        return 0;
+    }
+    EVP_PKEY_free(ctx->cert->dh_tmp);
+    ctx->cert->dh_tmp = dhpkey;
+    return 1;
+}
index 1ed47dd8ded93f0d97b1f976fce046e9c890651f..6f2103ad91ab7cb201213e33d86ed2b921f1b30c 100644 (file)
@@ -144,7 +144,7 @@ HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx)
 }
 
 /* Some deprecated public APIs pass DH objects */
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
 EVP_PKEY *ssl_dh_to_pkey(DH *dh)
 {
     EVP_PKEY *ret;
@@ -158,6 +158,6 @@ EVP_PKEY *ssl_dh_to_pkey(DH *dh)
     }
     return ret;
 }
-#endif
+# endif
 #endif
 
index 8b22c719e6910872fb26480e160306cfc8f6bb27..75e45bb17f35a0037f4124df3440bd7404480411 100644 (file)
@@ -517,3 +517,5 @@ SSL_new_session_ticket                  ?   3_0_0   EXIST::FUNCTION:
 SSL_get0_peer_certificate               ?      3_0_0   EXIST::FUNCTION:
 SSL_get1_peer_certificate               ?      3_0_0   EXIST::FUNCTION:
 SSL_load_client_CA_file_ex              ?      3_0_0   EXIST::FUNCTION:
+SSL_set0_tmp_dh_pkey                    ?      3_0_0   EXIST::FUNCTION:
+SSL_CTX_set0_tmp_dh_pkey                ?      3_0_0   EXIST::FUNCTION: