diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index e14b448609..f1363ca3b6 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3090,7 +3090,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) unsigned int cid, nid; for (i = 0; i < clistlen; i++) { n2s(clist, cid); - nid = tls1_ec_curve_id2nid(cid); + nid = tls1_ec_curve_id2nid(cid, NULL); if (nid != 0) cptr[i] = nid; else @@ -3982,27 +3982,38 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen, return s->session->master_key_length >= 0; } -/* Generate a private key from parameters or a curve NID */ -EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm, int nid) +/* Generate a private key from parameters or a curve ID */ +EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm, int id) { EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; + int nid; if (pm != NULL) { pctx = EVP_PKEY_CTX_new(pm, NULL); + nid = 0; } else { + unsigned int curve_flags; + nid = tls1_ec_curve_id2nid(id, &curve_flags); + if (nid == 0) + goto err; /* * Generate a new key for this curve. * Should not be called if EC is disabled: if it is it will * fail with an unknown algorithm error. */ - pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { + pctx = EVP_PKEY_CTX_new_id(nid, NULL); + nid = 0; + } else { + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + } } if (pctx == NULL) goto err; if (EVP_PKEY_keygen_init(pctx) <= 0) goto err; #ifndef OPENSSL_NO_EC - if (pm == NULL && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0) + if (nid != 0 && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0) goto err; #endif diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index f502cadb1d..3c230d14d6 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1987,7 +1987,13 @@ __owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s); SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); # ifndef OPENSSL_NO_EC -__owur int tls1_ec_curve_id2nid(int curve_id); +/* Flags values from tls1_ec_curve_id2nid() */ +/* Mask for curve type */ +# define TLS_CURVE_TYPE 0x3 +# define TLS_CURVE_PRIME 0x0 +# define TLS_CURVE_CHAR2 0x1 +# define TLS_CURVE_CUSTOM 0x2 +__owur int tls1_ec_curve_id2nid(int curve_id, unsigned int *pflags); __owur int tls1_ec_nid2curve_id(int nid); __owur int tls1_check_curve(SSL *s, const unsigned char *p, size_t len); __owur int tls1_shared_curve(SSL *s, int nmatch); diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index df19211b55..6f4c8ff2bf 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1497,6 +1497,7 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) PACKET encoded_pt; const unsigned char *ecparams; int curve_nid; + unsigned int curve_flags; EVP_PKEY_CTX *pctx = NULL; /* @@ -1519,7 +1520,8 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) return 0; } - curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2)); + curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2), &curve_flags); + if (curve_nid == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, @@ -1527,19 +1529,31 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) return 0; } - /* Set up EVP_PKEY with named curve as parameters */ - pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); - if (pctx == NULL - || EVP_PKEY_paramgen_init(pctx) <= 0 - || 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_SKE_ECDHE, ERR_R_EVP_LIB); + if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { + EVP_PKEY *key = EVP_PKEY_new(); + + if (key == NULL || !EVP_PKEY_set_type(key, curve_nid)) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_EVP_LIB); + EVP_PKEY_free(key); + return 0; + } + s->s3->peer_tmp = key; + } else { + /* Set up EVP_PKEY with named curve as parameters */ + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (pctx == NULL + || EVP_PKEY_paramgen_init(pctx) <= 0 + || 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_SKE_ECDHE, ERR_R_EVP_LIB); + EVP_PKEY_CTX_free(pctx); + return 0; + } EVP_PKEY_CTX_free(pctx); - return 0; + pctx = NULL; } - EVP_PKEY_CTX_free(pctx); - pctx = NULL; if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) { *al = SSL_AD_DECODE_ERROR; @@ -1547,9 +1561,9 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) return 0; } - if (EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(s->s3->peer_tmp), - PACKET_data(&encoded_pt), - PACKET_remaining(&encoded_pt), NULL) == 0) { + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_BAD_ECPOINT); return 0; @@ -2269,7 +2283,7 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al) EVP_PKEY *ckey = NULL, *skey = NULL; skey = s->s3->peer_tmp; - if ((skey == NULL) || EVP_PKEY_get0_EC_KEY(skey) == NULL) { + if (skey == NULL) { SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR); return 0; } @@ -2282,9 +2296,7 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al) } /* Generate encoding of client key */ - encoded_pt_len = EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(ckey), - POINT_CONVERSION_UNCOMPRESSED, - &encodedPoint, NULL); + encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint); if (encoded_pt_len == 0) { SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EC_LIB); diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 602336acd9..a5fe75216b 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1737,7 +1737,7 @@ int tls_construct_server_key_exchange(SSL *s) SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); goto err; } - s->s3->tmp.pkey = ssl_generate_pkey(NULL, nid); + s->s3->tmp.pkey = ssl_generate_pkey(NULL, curve_id); /* Generate a new key for this curve */ if (s->s3->tmp.pkey == NULL) { al = SSL_AD_INTERNAL_ERROR; @@ -1746,10 +1746,8 @@ int tls_construct_server_key_exchange(SSL *s) } /* Encode the public key. */ - encodedlen = EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(s->s3->tmp.pkey), - POINT_CONVERSION_UNCOMPRESSED, - &encodedPoint, NULL); - + encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey, + &encodedPoint); if (encodedlen == 0) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; @@ -2386,8 +2384,7 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al) SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EVP_LIB); goto err; } - if (EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(ckey), data, i, - NULL) == 0) { + if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EC_LIB); goto err; diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 2418c65862..ca4e7d6956 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -121,12 +121,6 @@ typedef struct { unsigned int flags; /* Flags: currently just field type */ } tls_curve_info; -/* Mask for curve type */ -# define TLS_CURVE_TYPE 0x3 -# define TLS_CURVE_PRIME 0x0 -# define TLS_CURVE_CHAR2 0x1 -# define TLS_CURVE_CUSTOM 0x2 - /* * Table of curve information. * Do not delete entries or reorder this array! It is used as a lookup @@ -161,8 +155,7 @@ static const tls_curve_info nid_list[] = { {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */ {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */ {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */ - /* X25519 (29) */ - {NID_X25519, 128, TLS_CURVE_CUSTOM}, + {NID_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */ }; static const unsigned char ecformats_default[] = { @@ -222,12 +215,16 @@ static const unsigned char suiteb_curves[] = { 0, TLSEXT_curve_P_384 }; -int tls1_ec_curve_id2nid(int curve_id) +int tls1_ec_curve_id2nid(int curve_id, unsigned int *pflags) { + const tls_curve_info *cinfo; /* ECC curves from RFC 4492 and RFC 7027 */ if ((curve_id < 1) || ((unsigned int)curve_id > OSSL_NELEM(nid_list))) return 0; - return nid_list[curve_id - 1].nid; + cinfo = nid_list + curve_id - 1; + if (pflags) + *pflags = cinfo->flags; + return cinfo->nid; } int tls1_ec_nid2curve_id(int nid) @@ -413,7 +410,7 @@ int tls1_shared_curve(SSL *s, int nmatch) continue; if (nmatch == k) { int id = (pref[0] << 8) | pref[1]; - return tls1_ec_curve_id2nid(id); + return tls1_ec_curve_id2nid(id, NULL); } k++; }