Modify TLS support for new X25519 API.
When handling ECDH check to see if the curve is "custom" (X25519 is
currently the only curve of this type) and instead of setting a curve
NID just allocate a key of appropriate type.
Reviewed-by: Rich Salz <rsalz@openssl.org>
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index e14b448..f1363ca 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3090,7 +3090,7 @@
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 @@
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 f502cad..3c230d1 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1987,7 +1987,13 @@
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 df19211..6f4c8ff 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1497,6 +1497,7 @@
PACKET encoded_pt;
const unsigned char *ecparams;
int curve_nid;
+ unsigned int curve_flags;
EVP_PKEY_CTX *pctx = NULL;
/*
@@ -1519,7 +1520,8 @@
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 @@
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 @@
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 @@
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 @@
}
/* 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 602336a..a5fe752 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1737,7 +1737,7 @@
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 @@
}
/* 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 @@
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 2418c65..ca4e7d6 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -121,12 +121,6 @@
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 @@
{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 @@
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 @@
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++;
}