Modify TLS support for new X25519 API.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 11 Aug 2016 14:41:49 +0000 (15:41 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Sat, 13 Aug 2016 13:11:05 +0000 (14:11 +0100)
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>
ssl/s3_lib.c
ssl/ssl_locl.h
ssl/statem/statem_clnt.c
ssl/statem/statem_srvr.c
ssl/t1_lib.c

index e14b448..f1363ca 100644 (file)
@@ -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
 
index f502cad..3c230d1 100644 (file)
@@ -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);
index df19211..6f4c8ff 100644 (file)
@@ -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);
index 602336a..a5fe752 100644 (file)
@@ -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;
index 2418c65..ca4e7d6 100644 (file)
@@ -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++;
             }