Allow Ed25519 in TLS 1.2
authorDr. Stephen Henson <steve@openssl.org>
Fri, 16 Jun 2017 17:55:28 +0000 (18:55 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 21 Jun 2017 13:11:01 +0000 (14:11 +0100)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3585)

ssl/ssl_lib.c
ssl/statem/statem_clnt.c
ssl/statem/statem_srvr.c
ssl/t1_lib.c

index a535e13..a46ede1 100644 (file)
@@ -2969,6 +2969,11 @@ void ssl_set_masks(SSL *s)
         if (ecdsa_ok)
             mask_a |= SSL_aECDSA;
     }
+    /* Allow Ed25519 for TLS 1.2 if peer supports it */
+    if (!(mask_a & SSL_aECDSA) && ssl_has_cert(s, SSL_PKEY_ED25519)
+            && pvalid[SSL_PKEY_ED25519] & CERT_PKEY_EXPLICIT_SIGN
+            && TLS1_get_version(s) == TLS1_2_VERSION)
+            mask_a |= SSL_aECDSA;
 #endif
 
 #ifndef OPENSSL_NO_EC
index 4643935..711680e 100644 (file)
@@ -1790,9 +1790,10 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     if (!SSL_IS_TLS13(s)) {
         exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
         if (exp_idx >= 0 && i != exp_idx
-            && (exp_idx != SSL_PKEY_GOST_EC ||
-                (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256
-                 && i != SSL_PKEY_GOST01))) {
+                && (exp_idx != SSL_PKEY_ECC || i != SSL_PKEY_ED25519)
+                && (exp_idx != SSL_PKEY_GOST_EC ||
+                    (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256
+                    && i != SSL_PKEY_GOST01))) {
             x = NULL;
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
@@ -2210,7 +2211,10 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             goto err;
         }
 
-        md = ssl_md(s->s3->tmp.peer_sigalg->hash_idx);
+        if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
+            al = SSL_AD_INTERNAL_ERROR;
+            goto err;
+        }
 
         if (!PACKET_get_length_prefixed_2(pkt, &signature)
             || PACKET_remaining(pkt) != 0) {
@@ -3352,7 +3356,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 
 #ifndef OPENSSL_NO_EC
     idx = s->session->peer_type;
-    if (idx == SSL_PKEY_ECC) {
+    if (idx == SSL_PKEY_ECC || idx == SSL_PKEY_ED25519) {
         if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s) == 0) {
             /* check failed */
             SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
index 6168b98..05405b0 100644 (file)
@@ -2415,7 +2415,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
         size_t siglen, tbslen;
         int rv;
 
-        if (pkey == NULL || md == NULL) {
+        if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
             /* Should never happen */
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
index cf11921..0f1d95b 100644 (file)
@@ -1498,6 +1498,7 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
             break;
 #endif
 #ifndef OPENSSL_NO_EC
+        case NID_ED25519:
         case EVP_PKEY_EC:
             if (!have_ecdsa && tls12_sigalg_allowed(s, op, lu))
                 have_ecdsa = 1;
@@ -2380,11 +2381,16 @@ int tls_choose_sigalg(SSL *s, int *al)
                     return 0;
                 }
             } else if (!ssl_has_cert(s, idx)) {
-                if (al == NULL)
-                    return 1;
-                *al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
-                return 0;
+                /* Allow Ed25519 if no EC certificate */
+                if (idx == SSL_PKEY_ECC && ssl_has_cert(s, SSL_PKEY_ED25519)) {
+                    idx = SSL_PKEY_ED25519;
+                } else {
+                    if (al == NULL)
+                        return 1;
+                    *al = SSL_AD_INTERNAL_ERROR;
+                    SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+                    return 0;
+                }
             }
         } else {
             /* Find index for client certificate */
@@ -2421,6 +2427,10 @@ int tls_choose_sigalg(SSL *s, int *al)
                     if (lu->sig_idx == idx
                         && (curve == -1 || lu->curve == curve))
                         break;
+                    if (idx == SSL_PKEY_ECC && lu->sig == NID_ED25519) {
+                        idx = SSL_PKEY_ED25519;
+                        break;
+                    }
 #endif
                     if (idx == SSL_PKEY_RSA && lu->sig == EVP_PKEY_RSA_PSS)
                         break;