From e2b420fdd708e14a0b43a21cd2377cafb0d54c02 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Thu, 17 Dec 2015 00:05:26 +0000 Subject: [PATCH] Server side EVP_PKEY DH support Reviewed-by: Matt Caswell --- include/openssl/ssl.h | 2 +- ssl/s3_lib.c | 49 +++++++++++---------- ssl/ssl_cert.c | 25 ++--------- ssl/ssl_locl.h | 2 +- ssl/statem/statem_srvr.c | 95 +++++++++++++++++++++++----------------- 5 files changed, 85 insertions(+), 88 deletions(-) diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 307af48d64..0b9e5d7dff 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1836,7 +1836,7 @@ __owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c); /* Sanity check of curve server selects */ # define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE) /* Temporary DH key */ -# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_DH) +# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_PKEY) /* SSL/TLS version */ # define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE) /* Session tickets */ diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 30fcd393e6..848953a454 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3488,21 +3488,24 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) case SSL_CTRL_SET_TMP_DH: { DH *dh = (DH *)parg; + EVP_PKEY *pkdh = NULL; if (dh == NULL) { SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); return (ret); } + pkdh = ssl_dh_to_pkey(dh); + if (pkdh == NULL) { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } if (!ssl_security(s, SSL_SECOP_TMP_DH, - DH_security_bits(dh), 0, dh)) { + EVP_PKEY_security_bits(pkdh), 0, pkdh)) { SSLerr(SSL_F_SSL3_CTRL, SSL_R_DH_KEY_TOO_SMALL); - return (ret); + EVP_PKEY_free(pkdh); + return ret; } - if ((dh = DHparams_dup(dh)) == NULL) { - SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); - return (ret); - } - DH_free(s->cert->dh_tmp); - s->cert->dh_tmp = dh; + EVP_PKEY_free(s->cert->dh_tmp); + s->cert->dh_tmp = pkdh; ret = 1; } break; @@ -3851,27 +3854,25 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) #ifndef OPENSSL_NO_DH case SSL_CTRL_SET_TMP_DH: { - DH *new = NULL, *dh; - CERT *cert; - - cert = ctx->cert; - dh = (DH *)parg; - if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH, - DH_security_bits(dh), 0, dh)) { - SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL); + DH *dh = (DH *)parg; + EVP_PKEY *pkdh = NULL; + if (dh == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if ((new = DHparams_dup(dh)) == NULL) { - SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB); + pkdh = ssl_dh_to_pkey(dh); + if (pkdh == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE); return 0; } - if (!DH_generate_key(new)) { - SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB); - DH_free(new); - return 0; + if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH, + EVP_PKEY_security_bits(pkdh), 0, pkdh)) { + SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL); + EVP_PKEY_free(pkdh); + return 1; } - DH_free(cert->dh_tmp); - cert->dh_tmp = new; + EVP_PKEY_free(ctx->cert->dh_tmp); + ctx->cert->dh_tmp = pkdh; return 1; } /* diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 41e34ce1d8..f01d3a7835 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -197,27 +197,8 @@ CERT *ssl_cert_dup(CERT *cert) #ifndef OPENSSL_NO_DH if (cert->dh_tmp != NULL) { - ret->dh_tmp = DHparams_dup(cert->dh_tmp); - if (ret->dh_tmp == NULL) { - SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB); - goto err; - } - if (cert->dh_tmp->priv_key) { - BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); - if (!b) { - SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); - goto err; - } - ret->dh_tmp->priv_key = b; - } - if (cert->dh_tmp->pub_key) { - BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); - if (!b) { - SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); - goto err; - } - ret->dh_tmp->pub_key = b; - } + ret->dh_tmp = cert->dh_tmp; + EVP_PKEY_up_ref(ret->dh_tmp); } ret->dh_tmp_cb = cert->dh_tmp_cb; ret->dh_tmp_auto = cert->dh_tmp_auto; @@ -370,7 +351,7 @@ void ssl_cert_free(CERT *c) #endif #ifndef OPENSSL_NO_DH - DH_free(c->dh_tmp); + EVP_PKEY_free(c->dh_tmp); #endif ssl_cert_clear_certs(c); diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index bff20adc43..4afb0d45ee 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1489,7 +1489,7 @@ typedef struct cert_st { */ CERT_PKEY *key; # ifndef OPENSSL_NO_DH - DH *dh_tmp; + EVP_PKEY *dh_tmp; DH *(*dh_tmp_cb) (SSL *ssl, int is_export, int keysize); int dh_tmp_auto; # endif diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index abdff176f7..89f064c5f9 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1714,7 +1714,7 @@ int tls_construct_server_done(SSL *s) int tls_construct_server_key_exchange(SSL *s) { #ifndef OPENSSL_NO_DH - DH *dh = NULL, *dhp; + EVP_PKEY *pkdh = NULL; #endif #ifndef OPENSSL_NO_EC unsigned char *encodedPoint = NULL; @@ -1761,49 +1761,66 @@ int tls_construct_server_key_exchange(SSL *s) if (type & (SSL_kDHE | SSL_kDHEPSK)) { CERT *cert = s->cert; + EVP_PKEY *pkdhp = NULL; + DH *dh; + if (s->cert->dh_tmp_auto) { - dhp = ssl_get_auto_dh(s); - if (dhp == NULL) { + DH *dhp = ssl_get_auto_dh(s); + pkdh = EVP_PKEY_new(); + if (pkdh == NULL || dhp == NULL) { + DH_free(dhp); al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; } - } else - dhp = cert->dh_tmp; - if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) - dhp = s->cert->dh_tmp_cb(s, 0, 1024); - if (dhp == NULL) { + EVP_PKEY_assign_DH(pkdh, dhp); + pkdhp = pkdh; + } else { + pkdhp = cert->dh_tmp; + } + if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) { + DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024); + pkdh = ssl_dh_to_pkey(dhp); + if (pkdh == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + pkdhp = pkdh; + } + if (pkdhp == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, SSL_R_MISSING_TMP_DH_KEY); goto f_err; } if (!ssl_security(s, SSL_SECOP_TMP_DH, - DH_security_bits(dhp), 0, dhp)) { + EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL); goto f_err; } - if (s->s3->tmp.dh != NULL) { + if (s->s3->tmp.pkey != NULL) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - if (s->cert->dh_tmp_auto) - dh = dhp; - else if ((dh = DHparams_dup(dhp)) == NULL) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } + s->s3->tmp.pkey = ssl_generate_pkey(pkdhp, NID_undef); - s->s3->tmp.dh = dh; - if (!DH_generate_key(dh)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); + if (s->s3->tmp.pkey == NULL) { + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB); goto err; } + + dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey); + + EVP_PKEY_free(pkdh); + pkdh = NULL; + r[0] = dh->p; r[1] = dh->g; r[2] = dh->pub_key; @@ -2018,6 +2035,9 @@ int tls_construct_server_key_exchange(SSL *s) f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: +#ifndef OPENSSL_NO_DH + EVP_PKEY_free(pkdh); +#endif #ifndef OPENSSL_NO_EC OPENSSL_free(encodedPoint); #endif @@ -2107,10 +2127,6 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) RSA *rsa = NULL; EVP_PKEY *pkey = NULL; #endif -#ifndef OPENSSL_NO_DH - BIGNUM *pub = NULL; - DH *dh_srvr; -#endif #ifndef OPENSSL_NO_EC EVP_PKEY *ckey = NULL; #endif @@ -2334,7 +2350,8 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) #endif #ifndef OPENSSL_NO_DH if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { - unsigned char shared[(OPENSSL_DH_MAX_MODULUS_BITS + 7) / 8]; + EVP_PKEY *skey = NULL; + DH *cdh; if (!PACKET_get_net_2(pkt, &i)) { if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { @@ -2350,13 +2367,13 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); goto err; } - if (s->s3->tmp.dh == NULL) { + skey = s->s3->tmp.pkey; + if (skey == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, SSL_R_MISSING_TMP_DH_KEY); goto f_err; - } else - dh_srvr = s->s3->tmp.dh; + } if (PACKET_remaining(pkt) == 0L) { al = SSL_AD_HANDSHAKE_FAILURE; @@ -2371,29 +2388,27 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) ERR_R_INTERNAL_ERROR); goto f_err; } - pub = BN_bin2bn(data, i, NULL); - if (pub == NULL) { + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) { SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, SSL_R_BN_LIB); goto err; } - - i = DH_compute_key(shared, pub, dh_srvr); - - if (i <= 0) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - BN_clear_free(pub); + cdh = EVP_PKEY_get0_DH(ckey); + cdh->pub_key = BN_bin2bn(data, i, NULL); + if (cdh->pub_key == NULL) { + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, SSL_R_BN_LIB); goto err; } - DH_free(s->s3->tmp.dh); - s->s3->tmp.dh = NULL; - BN_clear_free(pub); - pub = NULL; - if (!ssl_generate_master_secret(s, shared, i, 0)) { + if (ssl_derive(s, skey, ckey) == 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; } + + EVP_PKEY_free(ckey); + ckey = NULL; + } else #endif -- 2.25.1