Use EVP_PKEY for client side EC.
Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
parent
880d9d8609
commit
61dd9f7a22
3 changed files with 52 additions and 90 deletions
16
ssl/s3_lib.c
16
ssl/s3_lib.c
|
@ -3762,7 +3762,8 @@ void ssl3_free(SSL *s)
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
EVP_PKEY_free(s->s3->tmp.pkey);
|
EVP_PKEY_free(s->s3->tmp.pkey);
|
||||||
s->s3->tmp.pkey = NULL;
|
s->s3->tmp.pkey = NULL;
|
||||||
EC_KEY_free(s->s3->peer_ecdh_tmp);
|
EVP_PKEY_free(s->s3->peer_tmp);
|
||||||
|
s->s3->peer_tmp = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
|
sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
|
||||||
|
@ -3801,8 +3802,8 @@ void ssl3_clear(SSL *s)
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
EVP_PKEY_free(s->s3->tmp.pkey);
|
EVP_PKEY_free(s->s3->tmp.pkey);
|
||||||
s->s3->tmp.pkey = NULL;
|
s->s3->tmp.pkey = NULL;
|
||||||
EC_KEY_free(s->s3->peer_ecdh_tmp);
|
EVP_PKEY_free(s->s3->peer_tmp);
|
||||||
s->s3->peer_ecdh_tmp = NULL;
|
s->s3->peer_tmp = NULL;
|
||||||
s->s3->is_probably_safari = 0;
|
s->s3->is_probably_safari = 0;
|
||||||
#endif /* !OPENSSL_NO_EC */
|
#endif /* !OPENSSL_NO_EC */
|
||||||
|
|
||||||
|
@ -4155,19 +4156,20 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
|
||||||
EVP_PKEY *ptmp;
|
EVP_PKEY *ptmp;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC)
|
#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC)
|
||||||
if (!s->s3->peer_dh_tmp && !s->s3->peer_ecdh_tmp)
|
if (s->s3->peer_dh_tmp == NULL && s->s3->peer_tmp == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
ptmp = EVP_PKEY_new();
|
ptmp = EVP_PKEY_new();
|
||||||
if (ptmp == NULL)
|
if (ptmp == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
else if (s->s3->peer_dh_tmp)
|
else if (s->s3->peer_dh_tmp != NULL)
|
||||||
rv = EVP_PKEY_set1_DH(ptmp, s->s3->peer_dh_tmp);
|
rv = EVP_PKEY_set1_DH(ptmp, s->s3->peer_dh_tmp);
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
else if (s->s3->peer_ecdh_tmp)
|
else if (s->s3->peer_tmp != NULL)
|
||||||
rv = EVP_PKEY_set1_EC_KEY(ptmp, s->s3->peer_ecdh_tmp);
|
rv = EVP_PKEY_set1_EC_KEY(ptmp,
|
||||||
|
EVP_PKEY_get0_EC_KEY(s->s3->peer_tmp));
|
||||||
#endif
|
#endif
|
||||||
if (rv) {
|
if (rv) {
|
||||||
*(EVP_PKEY **)parg = ptmp;
|
*(EVP_PKEY **)parg = ptmp;
|
||||||
|
|
|
@ -1341,7 +1341,7 @@ typedef struct ssl3_state_st {
|
||||||
DH *peer_dh_tmp;
|
DH *peer_dh_tmp;
|
||||||
# endif
|
# endif
|
||||||
# ifndef OPENSSL_NO_EC
|
# ifndef OPENSSL_NO_EC
|
||||||
EC_KEY *peer_ecdh_tmp;
|
EVP_PKEY *peer_tmp;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
} SSL3_STATE;
|
} SSL3_STATE;
|
||||||
|
|
|
@ -1585,8 +1585,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||||
DH *dh = NULL;
|
DH *dh = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
EC_KEY *ecdh = NULL;
|
EVP_PKEY_CTX *pctx = NULL;
|
||||||
int curve_nid = 0;
|
|
||||||
#endif
|
#endif
|
||||||
PACKET save_param_start, signature;
|
PACKET save_param_start, signature;
|
||||||
|
|
||||||
|
@ -1606,8 +1605,8 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||||
s->s3->peer_dh_tmp = NULL;
|
s->s3->peer_dh_tmp = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
EC_KEY_free(s->s3->peer_ecdh_tmp);
|
EVP_PKEY_free(s->s3->peer_tmp);
|
||||||
s->s3->peer_ecdh_tmp = NULL;
|
s->s3->peer_tmp = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
||||||
|
@ -1742,6 +1741,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||||
else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
||||||
PACKET encoded_pt;
|
PACKET encoded_pt;
|
||||||
unsigned char *ecparams;
|
unsigned char *ecparams;
|
||||||
|
int curve_nid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract elliptic curve parameters and the server's ephemeral ECDH
|
* Extract elliptic curve parameters and the server's ephemeral ECDH
|
||||||
|
@ -1761,26 +1761,34 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2))) == 0) {
|
curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2));
|
||||||
|
if (curve_nid == 0) {
|
||||||
al = SSL_AD_INTERNAL_ERROR;
|
al = SSL_AD_INTERNAL_ERROR;
|
||||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||||
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
|
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecdh = EC_KEY_new_by_curve_name(curve_nid);
|
/* Set up EVP_PKEY with named curve as parameters */
|
||||||
|
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
|
||||||
if (ecdh == NULL) {
|
if (pctx == NULL
|
||||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EC_LIB);
|
|| EVP_PKEY_paramgen_init(pctx) <= 0
|
||||||
goto err;
|
|| EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, curve_nid) <= 0
|
||||||
|
|| EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
|
||||||
|
al = SSL_AD_INTERNAL_ERROR;
|
||||||
|
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
|
||||||
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
pctx = NULL;
|
||||||
|
|
||||||
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
|
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
|
||||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
|
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EC_KEY_oct2key(ecdh, PACKET_data(&encoded_pt),
|
if (EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(s->s3->peer_tmp),
|
||||||
|
PACKET_data(&encoded_pt),
|
||||||
PACKET_remaining(&encoded_pt), NULL) == 0) {
|
PACKET_remaining(&encoded_pt), NULL) == 0) {
|
||||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
|
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
|
@ -1801,8 +1809,6 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||||
pkey = X509_get_pubkey(s->session->peer);
|
pkey = X509_get_pubkey(s->session->peer);
|
||||||
# endif
|
# endif
|
||||||
/* else anonymous ECDH, so no certificate or pkey. */
|
/* else anonymous ECDH, so no certificate or pkey. */
|
||||||
s->s3->peer_ecdh_tmp = ecdh;
|
|
||||||
ecdh = NULL;
|
|
||||||
} else if (alg_k) {
|
} else if (alg_k) {
|
||||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
|
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
|
||||||
|
@ -1913,7 +1919,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||||
DH_free(dh);
|
DH_free(dh);
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
EC_KEY_free(ecdh);
|
EVP_PKEY_CTX_free(pctx);
|
||||||
#endif
|
#endif
|
||||||
EVP_MD_CTX_free(md_ctx);
|
EVP_MD_CTX_free(md_ctx);
|
||||||
ossl_statem_set_error(s);
|
ossl_statem_set_error(s);
|
||||||
|
@ -2238,9 +2244,7 @@ int tls_construct_client_key_exchange(SSL *s)
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
EC_KEY *clnt_ecdh = NULL;
|
EVP_PKEY *ckey = NULL, *skey = NULL;
|
||||||
const EC_POINT *srvr_ecpoint = NULL;
|
|
||||||
EVP_PKEY *srvr_pub_pkey = NULL;
|
|
||||||
unsigned char *encodedPoint = NULL;
|
unsigned char *encodedPoint = NULL;
|
||||||
int encoded_pt_len = 0;
|
int encoded_pt_len = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2468,84 +2472,41 @@ psk_err:
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
|
else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
|
||||||
const EC_GROUP *srvr_group = NULL;
|
|
||||||
EC_KEY *tkey;
|
|
||||||
int field_size = 0;
|
|
||||||
|
|
||||||
if (s->s3->peer_ecdh_tmp != NULL) {
|
if (s->s3->peer_tmp != NULL) {
|
||||||
tkey = s->s3->peer_ecdh_tmp;
|
skey = s->s3->peer_tmp;
|
||||||
} else {
|
} else {
|
||||||
/* Get the Server Public Key from Cert */
|
/* Get the Server Public Key from Cert */
|
||||||
srvr_pub_pkey = X509_get_pubkey(s->session->peer);
|
skey = X509_get0_pubkey(s->session->peer);
|
||||||
if ((srvr_pub_pkey == NULL)
|
if ((skey == NULL)
|
||||||
|| (srvr_pub_pkey->type != EVP_PKEY_EC)
|
|| (skey->type != EVP_PKEY_EC)
|
||||||
|| (srvr_pub_pkey->pkey.ec == NULL)) {
|
|| (skey->pkey.ec == NULL)) {
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
|
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
|
||||||
ERR_R_INTERNAL_ERROR);
|
ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
tkey = srvr_pub_pkey->pkey.ec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
srvr_group = EC_KEY_get0_group(tkey);
|
ckey = ssl_generate_pkey(skey, NID_undef);
|
||||||
srvr_ecpoint = EC_KEY_get0_public_key(tkey);
|
|
||||||
|
|
||||||
if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) {
|
if (ssl_derive(s, ckey, skey) == 0) {
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
|
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EVP_LIB);
|
||||||
ERR_R_INTERNAL_ERROR);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((clnt_ecdh = EC_KEY_new()) == NULL) {
|
/* Generate encoding of client key */
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
|
encoded_pt_len = EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(ckey),
|
||||||
ERR_R_MALLOC_FAILURE);
|
POINT_CONVERSION_UNCOMPRESSED,
|
||||||
goto err;
|
&encodedPoint, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) {
|
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
/* Generate a new ECDH key pair */
|
|
||||||
if (!(EC_KEY_generate_key(clnt_ecdh))) {
|
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* use the 'p' output buffer for the ECDH key, but make sure to
|
|
||||||
* clear it out afterwards
|
|
||||||
*/
|
|
||||||
|
|
||||||
field_size = EC_GROUP_get_degree(srvr_group);
|
|
||||||
if (field_size <= 0) {
|
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pmslen = (field_size + 7) / 8;
|
|
||||||
pms = OPENSSL_malloc(pmslen);
|
|
||||||
if (pms == NULL)
|
|
||||||
goto memerr;
|
|
||||||
n = ECDH_compute_key(pms, pmslen, srvr_ecpoint, clnt_ecdh, NULL);
|
|
||||||
if (n <= 0 || pmslen != (size_t)n) {
|
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First check the size of encoding and allocate memory
|
|
||||||
* accordingly.
|
|
||||||
*/
|
|
||||||
encoded_pt_len =
|
|
||||||
EC_KEY_key2buf(clnt_ecdh, POINT_CONVERSION_UNCOMPRESSED,
|
|
||||||
&encodedPoint, NULL);
|
|
||||||
|
|
||||||
if (encoded_pt_len == 0) {
|
if (encoded_pt_len == 0) {
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
|
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_free(ckey);
|
||||||
|
ckey = NULL;
|
||||||
|
|
||||||
n = encoded_pt_len;
|
n = encoded_pt_len;
|
||||||
|
|
||||||
*p = n; /* length of encoded point */
|
*p = n; /* length of encoded point */
|
||||||
|
@ -2558,8 +2519,6 @@ psk_err:
|
||||||
|
|
||||||
/* Free allocated memory */
|
/* Free allocated memory */
|
||||||
OPENSSL_free(encodedPoint);
|
OPENSSL_free(encodedPoint);
|
||||||
EC_KEY_free(clnt_ecdh);
|
|
||||||
EVP_PKEY_free(srvr_pub_pkey);
|
|
||||||
}
|
}
|
||||||
#endif /* !OPENSSL_NO_EC */
|
#endif /* !OPENSSL_NO_EC */
|
||||||
#ifndef OPENSSL_NO_GOST
|
#ifndef OPENSSL_NO_GOST
|
||||||
|
@ -2723,8 +2682,10 @@ psk_err:
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->s3->tmp.pms = pms;
|
if (pms != NULL) {
|
||||||
s->s3->tmp.pmslen = pmslen;
|
s->s3->tmp.pms = pms;
|
||||||
|
s->s3->tmp.pmslen = pmslen;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
memerr:
|
memerr:
|
||||||
|
@ -2735,8 +2696,7 @@ psk_err:
|
||||||
s->s3->tmp.pms = NULL;
|
s->s3->tmp.pms = NULL;
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
OPENSSL_free(encodedPoint);
|
OPENSSL_free(encodedPoint);
|
||||||
EC_KEY_free(clnt_ecdh);
|
EVP_PKEY_free(ckey);
|
||||||
EVP_PKEY_free(srvr_pub_pkey);
|
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_PSK
|
#ifndef OPENSSL_NO_PSK
|
||||||
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
|
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
|
||||||
|
|
Loading…
Reference in a new issue