Only support >= 256-bit elliptic curves with ecdh_auto (server) or by default (client).
[openssl.git] / ssl / t1_lib.c
index 67786a004181615a8416effd1afe5c038ff6a2df..8cde013138577f4b0f2cdc59312afdb0ad728247 100644 (file)
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
+#ifndef OPENSSL_NO_EC
 #ifdef OPENSSL_NO_EC2M
 # include <openssl/ec.h>
 #endif
+#endif
 #include <openssl/ocsp.h>
 #include <openssl/rand.h>
 #include "ssl_locl.h"
@@ -260,47 +262,68 @@ static const unsigned char ecformats_default[] = {
     TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
 };
 
-static const unsigned char eccurves_default[] = {
-# ifndef OPENSSL_NO_EC2M
-    0, 14,                      /* sect571r1 (14) */
-    0, 13,                      /* sect571k1 (13) */
-# endif
+/* The client's default curves / the server's 'auto' curves. */
+static const unsigned char eccurves_auto[] = {
+    /* Prefer P-256 which has the fastest and most secure implementations. */
+    0, 23,                      /* secp256r1 (23) */
+    /* Other >= 256-bit prime curves. */
     0, 25,                      /* secp521r1 (25) */
     0, 28,                      /* brainpool512r1 (28) */
+    0, 27,                      /* brainpoolP384r1 (27) */
+    0, 24,                      /* secp384r1 (24) */
+    0, 26,                      /* brainpoolP256r1 (26) */
+    0, 22,                      /* secp256k1 (22) */
 # ifndef OPENSSL_NO_EC2M
+    /* >= 256-bit binary curves. */
+    0, 14,                      /* sect571r1 (14) */
+    0, 13,                      /* sect571k1 (13) */
     0, 11,                      /* sect409k1 (11) */
     0, 12,                      /* sect409r1 (12) */
+    0, 9,                       /* sect283k1 (9) */
+    0, 10,                      /* sect283r1 (10) */
 # endif
+};
+
+static const unsigned char eccurves_all[] = {
+    /* Prefer P-256 which has the fastest and most secure implementations. */
+    0, 23,                      /* secp256r1 (23) */
+    /* Other >= 256-bit prime curves. */
+    0, 25,                      /* secp521r1 (25) */
+    0, 28,                      /* brainpool512r1 (28) */
     0, 27,                      /* brainpoolP384r1 (27) */
     0, 24,                      /* secp384r1 (24) */
+    0, 26,                      /* brainpoolP256r1 (26) */
+    0, 22,                      /* secp256k1 (22) */
 # ifndef OPENSSL_NO_EC2M
+    /* >= 256-bit binary curves. */
+    0, 14,                      /* sect571r1 (14) */
+    0, 13,                      /* sect571k1 (13) */
+    0, 11,                      /* sect409k1 (11) */
+    0, 12,                      /* sect409r1 (12) */
     0, 9,                       /* sect283k1 (9) */
     0, 10,                      /* sect283r1 (10) */
 # endif
-    0, 26,                      /* brainpoolP256r1 (26) */
-    0, 22,                      /* secp256k1 (22) */
-    0, 23,                      /* secp256r1 (23) */
+    /*
+     * Remaining curves disabled by default but still permitted if set
+     * via an explicit callback or parameters.
+     */
+    0, 20,                      /* secp224k1 (20) */
+    0, 21,                      /* secp224r1 (21) */
+    0, 18,                      /* secp192k1 (18) */
+    0, 19,                      /* secp192r1 (19) */
+    0, 15,                      /* secp160k1 (15) */
+    0, 16,                      /* secp160r1 (16) */
+    0, 17,                      /* secp160r2 (17) */
 # ifndef OPENSSL_NO_EC2M
     0, 8,                       /* sect239k1 (8) */
     0, 6,                       /* sect233k1 (6) */
     0, 7,                       /* sect233r1 (7) */
-# endif
-    0, 20,                      /* secp224k1 (20) */
-    0, 21,                      /* secp224r1 (21) */
-# ifndef OPENSSL_NO_EC2M
     0, 4,                       /* sect193r1 (4) */
     0, 5,                       /* sect193r2 (5) */
-# endif
-    0, 18,                      /* secp192k1 (18) */
-    0, 19,                      /* secp192r1 (19) */
-# ifndef OPENSSL_NO_EC2M
     0, 1,                       /* sect163k1 (1) */
     0, 2,                       /* sect163r1 (2) */
     0, 3,                       /* sect163r2 (3) */
 # endif
-    0, 15,                      /* secp160k1 (15) */
-    0, 16,                      /* secp160r1 (16) */
-    0, 17,                      /* secp160r2 (17) */
 };
 
 static const unsigned char suiteb_curves[] = {
@@ -470,12 +493,17 @@ static int tls1_get_curvelist(SSL *s, int sess,
 # ifdef OPENSSL_FIPS
             if (FIPS_mode()) {
                 *pcurves = fips_curves_default;
-                *pcurveslen = sizeof(fips_curves_default);
+                pcurveslen = sizeof(fips_curves_default);
             } else
 # endif
             {
-                *pcurves = eccurves_default;
-                pcurveslen = sizeof(eccurves_default);
+                if (!s->server || (s->cert && s->cert->ecdh_tmp_auto)) {
+                    *pcurves = eccurves_auto;
+                    pcurveslen = sizeof(eccurves_auto);
+                } else {
+                    *pcurves = eccurves_all;
+                    pcurveslen = sizeof(eccurves_all);
+                }
             }
         }
     }
@@ -651,6 +679,8 @@ static int nid_cb(const char *elem, int len, void *arg)
     size_t i;
     int nid;
     char etmp[20];
+    if (elem == NULL)
+        return 0;
     if (narg->nidcnt == MAX_CURVELIST)
         return 0;
     if (len > (int)(sizeof(etmp) - 1))
@@ -759,6 +789,16 @@ static int tls1_check_ec_key(SSL *s,
     for (j = 0; j <= 1; j++) {
         if (!tls1_get_curvelist(s, j, &pcurves, &num_curves))
             return 0;
+        if (j == 1 && num_curves == 0) {
+            /*
+             * If we've not received any curves then skip this check.
+             * RFC 4492 does not require the supported elliptic curves extension
+             * so if it is not sent we can just choose any curve.
+             * It is invalid to send an empty list in the elliptic curves
+             * extension, so num_curves == 0 always means no extension.
+             */
+            break;
+        }
         for (i = 0; i < num_curves; i++, pcurves += 2) {
             if (pcurves[0] == curve_id[0] && pcurves[1] == curve_id[1])
                 break;
@@ -1212,14 +1252,14 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
         unsigned long size_str;
         long lenmax;
 
-                /*-
-                 * check for enough space.
-                 * 4 for the servername type and entension length
-                 * 2 for servernamelist length
-                 * 1 for the hostname type
-                 * 2 for hostname length
-                 * + hostname length
-                 */
+        /*-
+         * check for enough space.
+         * 4 for the servername type and entension length
+         * 2 for servernamelist length
+         * 1 for the hostname type
+         * 2 for hostname length
+         * + hostname length
+         */
 
         if ((lenmax = limit - ret - 9) < 0
             || (size_str =
@@ -1273,12 +1313,12 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
             return NULL;
         }
 
-                /*-
-                 * check for enough space.
-                 * 4 for the srp type type and entension length
-                 * 1 for the srp user identity
-                 * + srp user identity length
-                 */
+        /*-
+         * check for enough space.
+         * 4 for the srp type type and entension length
+         * 1 for the srp user identity
+         * + srp user identity length
+         */
         if ((limit - ret - 5 - login_len) < 0)
             return NULL;
 
@@ -1453,11 +1493,11 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
         return NULL;
     s2n(TLSEXT_TYPE_heartbeat, ret);
     s2n(1, ret);
-        /*-
-         * Set mode:
-         * 1: peer may send requests
-         * 2: peer not allowed to send requests
-         */
+    /*-
+     * Set mode:
+     * 1: peer may send requests
+     * 2: peer not allowed to send requests
+     */
     if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
         *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
     else
@@ -1709,11 +1749,11 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
             return NULL;
         s2n(TLSEXT_TYPE_heartbeat, ret);
         s2n(1, ret);
-                /*-
-                 * Set mode:
-                 * 1: peer may send requests
-                 * 2: peer not allowed to send requests
-                 */
+        /*-
+         * Set mode:
+         * 1: peer may send requests
+         * 2: peer not allowed to send requests
+         */
         if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
             *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
         else
@@ -2344,23 +2384,23 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
         else if (type == TLSEXT_TYPE_next_proto_neg &&
                  s->s3->tmp.finish_md_len == 0 &&
                  s->s3->alpn_selected == NULL) {
-                        /*-
-                         * We shouldn't accept this extension on a
-                         * renegotiation.
-                         *
-                         * s->new_session will be set on renegotiation, but we
-                         * probably shouldn't rely that it couldn't be set on
-                         * the initial renegotation too in certain cases (when
-                         * there's some other reason to disallow resuming an
-                         * earlier session -- the current code won't be doing
-                         * anything like that, but this might change).
-                         *
-                         * A valid sign that there's been a previous handshake
-                         * in this connection is if s->s3->tmp.finish_md_len >
-                         * 0.  (We are talking about a check that will happen
-                         * in the Hello protocol round, well before a new
-                         * Finished message could have been computed.)
-                         */
+            /*-
+             * We shouldn't accept this extension on a
+             * renegotiation.
+             *
+             * s->new_session will be set on renegotiation, but we
+             * probably shouldn't rely that it couldn't be set on
+             * the initial renegotation too in certain cases (when
+             * there's some other reason to disallow resuming an
+             * earlier session -- the current code won't be doing
+             * anything like that, but this might change).
+             *
+             * A valid sign that there's been a previous handshake
+             * in this connection is if s->s3->tmp.finish_md_len >
+             * 0.  (We are talking about a check that will happen
+             * in the Hello protocol round, well before a new
+             * Finished message could have been computed.)
+             */
             s->s3->next_proto_neg_seen = 1;
         }
 # endif
@@ -2682,12 +2722,12 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p,
                 *al = TLS1_AD_DECODE_ERROR;
                 return 0;
             }
-                        /*-
-                         * The extension data consists of:
-                         *   uint16 list_length
-                         *   uint8 proto_length;
-                         *   uint8 proto[proto_length];
-                         */
+            /*-
+             * The extension data consists of:
+             *   uint16 list_length
+             *   uint8 proto_length;
+             *   uint8 proto[proto_length];
+             */
             len = data[0];
             len <<= 8;
             len |= data[1];
@@ -2965,6 +3005,7 @@ int tls1_set_server_sigalgs(SSL *s)
     if (s->cert->shared_sigalgs) {
         OPENSSL_free(s->cert->shared_sigalgs);
         s->cert->shared_sigalgs = NULL;
+        s->cert->shared_sigalgslen = 0;
     }
     /* Clear certificate digests and validity flags */
     for (i = 0; i < SSL_PKEY_NUM; i++) {
@@ -3618,6 +3659,7 @@ static int tls1_set_shared_sigalgs(SSL *s)
     if (c->shared_sigalgs) {
         OPENSSL_free(c->shared_sigalgs);
         c->shared_sigalgs = NULL;
+        c->shared_sigalgslen = 0;
     }
     /* If client use client signature algorithms if not NULL */
     if (!s->server && c->client_sigalgs && !is_suiteb) {
@@ -3640,12 +3682,14 @@ static int tls1_set_shared_sigalgs(SSL *s)
         preflen = c->peer_sigalgslen;
     }
     nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen);
-    if (!nmatch)
-        return 1;
-    salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
-    if (!salgs)
-        return 0;
-    nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen);
+    if (nmatch) {
+        salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
+        if (!salgs)
+            return 0;
+        nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen);
+    } else {
+        salgs = NULL;
+    }
     c->shared_sigalgs = salgs;
     c->shared_sigalgslen = nmatch;
     return 1;
@@ -3831,7 +3875,10 @@ int tls1_process_heartbeat(SSL *s)
         memcpy(bp, pl, payload);
         bp += payload;
         /* Random padding */
-        RAND_pseudo_bytes(bp, padding);
+        if (RAND_pseudo_bytes(bp, padding) < 0) {
+            OPENSSL_free(buffer);
+            return -1;
+        }
 
         r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer,
                              3 + payload + padding);
@@ -3866,7 +3913,7 @@ int tls1_process_heartbeat(SSL *s)
 int tls1_heartbeat(SSL *s)
 {
     unsigned char *buf, *p;
-    int ret;
+    int ret = -1;
     unsigned int payload = 18;  /* Sequence number + random bytes */
     unsigned int padding = 16;  /* Use minimum padding */
 
@@ -3895,16 +3942,16 @@ int tls1_heartbeat(SSL *s)
      */
     OPENSSL_assert(payload + padding <= 16381);
 
-        /*-
-         * Create HeartBeat message, we just use a sequence number
-         * as payload to distuingish different messages and add
-         * some random stuff.
-         *  - Message Type, 1 byte
-         *  - Payload Length, 2 bytes (unsigned int)
-         *  - Payload, the sequence number (2 bytes uint)
-         *  - Payload, random bytes (16 bytes uint)
-         *  - Padding
-         */
+    /*-
+     * Create HeartBeat message, we just use a sequence number
+     * as payload to distuingish different messages and add
+     * some random stuff.
+     *  - Message Type, 1 byte
+     *  - Payload Length, 2 bytes (unsigned int)
+     *  - Payload, the sequence number (2 bytes uint)
+     *  - Payload, random bytes (16 bytes uint)
+     *  - Padding
+     */
     buf = OPENSSL_malloc(1 + 2 + payload + padding);
     p = buf;
     /* Message Type */
@@ -3914,10 +3961,16 @@ int tls1_heartbeat(SSL *s)
     /* Sequence number */
     s2n(s->tlsext_hb_seq, p);
     /* 16 random bytes */
-    RAND_pseudo_bytes(p, 16);
+    if (RAND_pseudo_bytes(p, 16) < 0) {
+        SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
     p += 16;
     /* Random padding */
-    RAND_pseudo_bytes(p, padding);
+    if (RAND_pseudo_bytes(p, padding) < 0) {
+        SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
 
     ret = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
     if (ret >= 0) {
@@ -3929,6 +3982,7 @@ int tls1_heartbeat(SSL *s)
         s->tlsext_hb_pending = 1;
     }
 
+err:
     OPENSSL_free(buf);
 
     return ret;
@@ -3948,6 +4002,8 @@ static int sig_cb(const char *elem, int len, void *arg)
     size_t i;
     char etmp[20], *p;
     int sig_alg, hash_alg;
+    if (elem == NULL)
+        return 0;
     if (sarg->sigalgcnt == MAX_SIGALGLEN)
         return 0;
     if (len > (int)(sizeof(etmp) - 1))
@@ -4122,10 +4178,10 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
 # endif
     } else {
         if (!x || !pk)
-            goto end;
+            return 0;
         idx = ssl_cert_type(x, pk);
         if (idx == -1)
-            goto end;
+            return 0;
         cpk = c->pkeys + idx;
         if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
             check_flags = CERT_PKEY_STRICT_FLAGS;