summaryrefslogtreecommitdiffstats
path: root/ssl/s3_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/s3_lib.c')
-rw-r--r--ssl/s3_lib.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 248bb94df8..e9addc4e58 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3391,6 +3391,94 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return (int)clistlen;
}
+ case SSL_CTRL_SET_CURVELIST:
+ {
+ int *nid_list = parg;
+ size_t nid_listlen = larg, i;
+ unsigned char *clist, *p;
+ /* Bitmap of curves included to detect duplicates: only works
+ * while curve ids < 32
+ */
+ unsigned long dup_list = 0;
+ clist = OPENSSL_malloc(nid_listlen * 2);
+ for (i = 0, p = clist; i < nid_listlen; i++)
+ {
+ unsigned long idmask;
+ int id;
+ id = tls1_ec_nid2curve_id(nid_list[i]);
+ idmask = 1L << id;
+ if (!id || (dup_list & idmask))
+ {
+ OPENSSL_free(clist);
+ return 0;
+ }
+ dup_list |= idmask;
+ s2n(id, p);
+ }
+ if (s->tlsext_ellipticcurvelist)
+ OPENSSL_free(s->tlsext_ellipticcurvelist);
+ s->tlsext_ellipticcurvelist = clist;
+ s->tlsext_ellipticcurvelist_length = nid_listlen * 2;
+ return 1;
+ }
+
+ case SSL_CTRL_SHARED_CURVES:
+ {
+ unsigned long mask = 0;
+ unsigned char *pmask, *pref;
+ size_t pmasklen, preflen, i;
+ int nmatch = 0;
+ /* Must be server */
+ if (!s->server)
+ return 0;
+ /* No curves if client didn't sent supported curves extension */
+ if (!s->session->tlsext_ellipticcurvelist)
+ return 0;
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+ {
+ pref = s->tlsext_ellipticcurvelist;
+ preflen = s->tlsext_ellipticcurvelist_length;
+ pmask = s->session->tlsext_ellipticcurvelist;
+ pmasklen = s->session->tlsext_ellipticcurvelist_length;
+ }
+ else
+ {
+ pref = s->session->tlsext_ellipticcurvelist;
+ preflen = s->session->tlsext_ellipticcurvelist_length;
+ pmask = s->tlsext_ellipticcurvelist;
+ pmasklen = s->tlsext_ellipticcurvelist_length;
+ }
+ /* Build a mask of supported curves */
+ for (i = 0; i < pmasklen; i+=2, pmask+=2)
+ {
+ /* Skip any curves that wont fit in mask */
+ if (pmask[0] || (pmask[1] > 31))
+ continue;
+ mask |= 1L << pmask[1];
+ }
+ /* Check preference order against mask */
+ for (i = 0; i < preflen; i+=2, pref+=2)
+ {
+ if (pref[0] || (pref[1] > 30))
+ continue;
+ /* Search for matching curves in preference order */
+ if (mask & (1L << pref[1]))
+ {
+ int id = tls1_ec_curve_id2nid(pref[1]);
+ if (id && parg && nmatch == larg)
+ {
+ *((int *)parg) = id;
+ return 1;
+ }
+ nmatch++;
+ }
+ }
+ if (parg)
+ return 0;
+ return nmatch;
+
+ }
+
default:
break;
}