Add support for automatic ECDH temporary key parameter selection. When enabled instead of requiring an application to hard code a (possibly inappropriate) parameter set and delve into EC internals we just automatically use the preferred curve.
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index ffc78c9..7392439 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c
@@ -332,33 +332,24 @@ } } -/* Return any common values from two lists. One list is used as a - * preference list where we return the most preferred match. +/* Return nth shared curve. If nmatch == -1 return number of + * matches. */ -int tls1_shared_list(SSL *s, - const unsigned char *l1, size_t l1len, - const unsigned char *l2, size_t l2len, - int nmatch) + +int tls1_shared_curve(SSL *s, int nmatch) { const unsigned char *pref, *supp; size_t preflen, supplen, i, j; int k; - l1len /= 2; - l2len /= 2; - if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) - { - pref = l1; - preflen = l1len; - supp = l2; - supplen = l2len; - } - else - { - supp = l1; - supplen = l1len; - pref = l2; - preflen = l2len; - } + /* Can't do anything on client side */ + if (s->server == 0) + return -1; + tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), + &supp, &supplen); + tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), + &pref, &preflen); + preflen /= 2; + supplen /= 2; k = 0; for (i = 0; i < preflen; i++, pref+=2) { @@ -368,32 +359,17 @@ if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) { if (nmatch == k) - return (pref[0] << 8) | pref[1]; + { + int id = (pref[0] << 8) | pref[1]; + return tls1_ec_curve_id2nid(id); + } k++; } } } - if (nmatch == -1 && k > 0) - return k; - return -1; - } - -int tls1_shared_curve(SSL *s, int nmatch) - { - const unsigned char *l1, *l2; - size_t l1len, l2len; - int id; - /* Can't do anything on client side */ - if (s->server == 0) - return -1; - /* Get supported curves */ - tls1_get_curvelist(s, 0, &l1, &l1len); - tls1_get_curvelist(s, 1, &l2, &l2len); - - id = tls1_shared_list(s, l1, l1len, l2, l2len, nmatch); if (nmatch == -1) - return id; - return tls1_ec_curve_id2nid(id); + return k; + return 0; } int tls1_set_curves(unsigned char **pext, size_t *pextlen, @@ -531,6 +507,7 @@ { const unsigned char *p; size_t plen, i; + int j; /* If point formats extension present check it, otherwise everything * is supported (see RFC4492). */ @@ -546,19 +523,17 @@ if (i == plen) return 0; } - /* If curve list present check it, otherwise everything is - * supported. - */ - if (s->session->tlsext_ellipticcurvelist) + /* Check curve is consistent with client and server preferences */ + for (j = 0; j <= 1; j++) { - p = s->session->tlsext_ellipticcurvelist; - plen = s->session->tlsext_ellipticcurvelist_length; + tls1_get_curvelist(s, j, &p, &plen); for (i = 0; i < plen; i+=2, p+=2) { if (p[0] == curve_id[0] && p[1] == curve_id[1]) - return 1; + break; } - return 0; + if (i == plen) + return 0; } return 1; } @@ -585,6 +560,13 @@ { unsigned char curve_id[2]; EC_KEY *ec = s->cert->ecdh_tmp; + if (s->cert->ecdh_tmp_auto) + { + /* Need a shared curve */ + if (tls1_shared_curve(s, 0)) + return 1; + else return 0; + } if (!ec) { if (s->cert->ecdh_tmp_cb)