diff options
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 4 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.c | 121 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.h | 10 | ||||
-rw-r--r-- | src/lib/libssl/t1_lib.c | 76 | ||||
-rw-r--r-- | src/regress/lib/libssl/tlsext/tlsexttest.c | 338 |
5 files changed, 472 insertions, 77 deletions
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 84bb6879b0..52e4b6c5e9 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_locl.h,v 1.186 2017/08/11 17:54:41 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.187 2017/08/11 20:14:13 doug Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1382,6 +1382,8 @@ void SSL_error_internal(const SSL *s, int r, char *f, int l); | |||
1382 | 1382 | ||
1383 | void tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, | 1383 | void tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, |
1384 | size_t *pformatslen); | 1384 | size_t *pformatslen); |
1385 | void tls1_get_curvelist(SSL *s, int client_curves, const uint16_t **pcurves, | ||
1386 | size_t *pcurveslen); | ||
1385 | 1387 | ||
1386 | __END_HIDDEN_DECLS | 1388 | __END_HIDDEN_DECLS |
1387 | 1389 | ||
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c index ad30f43389..c050224c70 100644 --- a/src/lib/libssl/ssl_tlsext.c +++ b/src/lib/libssl/ssl_tlsext.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_tlsext.c,v 1.5 2017/08/11 06:30:41 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_tlsext.c,v 1.6 2017/08/11 20:14:13 doug Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> | 4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> |
@@ -21,6 +21,116 @@ | |||
21 | #include "bytestring.h" | 21 | #include "bytestring.h" |
22 | #include "ssl_tlsext.h" | 22 | #include "ssl_tlsext.h" |
23 | 23 | ||
24 | |||
25 | /* | ||
26 | * Supported Elliptic Curves - RFC 4492 section 5.1.1 | ||
27 | */ | ||
28 | int | ||
29 | tlsext_ec_clienthello_needs(SSL *s) | ||
30 | { | ||
31 | return ssl_has_ecc_ciphers(s); | ||
32 | } | ||
33 | |||
34 | int | ||
35 | tlsext_ec_clienthello_build(SSL *s, CBB *cbb) | ||
36 | { | ||
37 | CBB curvelist; | ||
38 | size_t curves_len; | ||
39 | int i; | ||
40 | const uint16_t *curves; | ||
41 | |||
42 | tls1_get_curvelist(s, 0, &curves, &curves_len); | ||
43 | |||
44 | if (curves_len == 0) { | ||
45 | SSLerror(s, ERR_R_INTERNAL_ERROR); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | if (!CBB_add_u16_length_prefixed(cbb, &curvelist)) | ||
50 | return 0; | ||
51 | |||
52 | for (i = 0; i < curves_len; i++) { | ||
53 | if (!CBB_add_u16(&curvelist, curves[i])) | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | if (!CBB_flush(cbb)) | ||
58 | return 0; | ||
59 | |||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | tlsext_ec_clienthello_parse(SSL *s, CBS *cbs, int *alert) | ||
65 | { | ||
66 | CBS curvelist; | ||
67 | size_t curves_len; | ||
68 | |||
69 | if (!CBS_get_u16_length_prefixed(cbs, &curvelist)) | ||
70 | goto err; | ||
71 | if (CBS_len(cbs) != 0) | ||
72 | goto err; | ||
73 | |||
74 | curves_len = CBS_len(&curvelist); | ||
75 | if (curves_len == 0 || curves_len % 2 != 0) | ||
76 | goto err; | ||
77 | curves_len /= 2; | ||
78 | |||
79 | if (!s->internal->hit) { | ||
80 | int i; | ||
81 | uint16_t *curves; | ||
82 | |||
83 | if (SSI(s)->tlsext_supportedgroups != NULL) | ||
84 | goto err; | ||
85 | |||
86 | if ((curves = reallocarray(NULL, curves_len, | ||
87 | sizeof(uint16_t))) == NULL) { | ||
88 | *alert = TLS1_AD_INTERNAL_ERROR; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | for (i = 0; i < curves_len; i++) { | ||
93 | if (!CBS_get_u16(&curvelist, &curves[i])) { | ||
94 | free(curves); | ||
95 | goto err; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | if (CBS_len(&curvelist) != 0) { | ||
100 | free(curves); | ||
101 | goto err; | ||
102 | } | ||
103 | |||
104 | SSI(s)->tlsext_supportedgroups = curves; | ||
105 | SSI(s)->tlsext_supportedgroups_length = curves_len; | ||
106 | } | ||
107 | |||
108 | return 1; | ||
109 | |||
110 | err: | ||
111 | *alert = TLS1_AD_DECODE_ERROR; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /* This extension is never used by the server. */ | ||
116 | int | ||
117 | tlsext_ec_serverhello_needs(SSL *s) | ||
118 | { | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | int | ||
123 | tlsext_ec_serverhello_build(SSL *s, CBB *cbb) | ||
124 | { | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | int | ||
129 | tlsext_ec_serverhello_parse(SSL *s, CBS *cbs, int *alert) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | |||
24 | /* | 134 | /* |
25 | * Supported Point Formats Extension - RFC 4492 section 5.1.2 | 135 | * Supported Point Formats Extension - RFC 4492 section 5.1.2 |
26 | */ | 136 | */ |
@@ -420,6 +530,15 @@ static struct tls_extension tls_extensions[] = { | |||
420 | .serverhello_build = tlsext_ecpf_serverhello_build, | 530 | .serverhello_build = tlsext_ecpf_serverhello_build, |
421 | .serverhello_parse = tlsext_ecpf_serverhello_parse, | 531 | .serverhello_parse = tlsext_ecpf_serverhello_parse, |
422 | }, | 532 | }, |
533 | { | ||
534 | .type = TLSEXT_TYPE_elliptic_curves, | ||
535 | .clienthello_needs = tlsext_ec_clienthello_needs, | ||
536 | .clienthello_build = tlsext_ec_clienthello_build, | ||
537 | .clienthello_parse = tlsext_ec_clienthello_parse, | ||
538 | .serverhello_needs = tlsext_ec_serverhello_needs, | ||
539 | .serverhello_build = tlsext_ec_serverhello_build, | ||
540 | .serverhello_parse = tlsext_ec_serverhello_parse, | ||
541 | }, | ||
423 | }; | 542 | }; |
424 | 543 | ||
425 | #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) | 544 | #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) |
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h index 6f79755f81..38f8ffaa65 100644 --- a/src/lib/libssl/ssl_tlsext.h +++ b/src/lib/libssl/ssl_tlsext.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_tlsext.h,v 1.4 2017/08/11 06:30:41 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_tlsext.h,v 1.5 2017/08/11 20:14:13 doug Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> | 4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> |
@@ -30,6 +30,13 @@ int tlsext_sni_serverhello_needs(SSL *s); | |||
30 | int tlsext_sni_serverhello_build(SSL *s, CBB *cbb); | 30 | int tlsext_sni_serverhello_build(SSL *s, CBB *cbb); |
31 | int tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert); | 31 | int tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert); |
32 | 32 | ||
33 | int tlsext_ec_clienthello_needs(SSL *s); | ||
34 | int tlsext_ec_clienthello_build(SSL *s, CBB *cbb); | ||
35 | int tlsext_ec_clienthello_parse(SSL *s, CBS *cbs, int *alert); | ||
36 | int tlsext_ec_serverhello_needs(SSL *s); | ||
37 | int tlsext_ec_serverhello_build(SSL *s, CBB *cbb); | ||
38 | int tlsext_ec_serverhello_parse(SSL *s, CBS *cbs, int *alert); | ||
39 | |||
33 | int tlsext_ecpf_clienthello_needs(SSL *s); | 40 | int tlsext_ecpf_clienthello_needs(SSL *s); |
34 | int tlsext_ecpf_clienthello_build(SSL *s, CBB *cbb); | 41 | int tlsext_ecpf_clienthello_build(SSL *s, CBB *cbb); |
35 | int tlsext_ecpf_clienthello_parse(SSL *s, CBS *cbs, int *alert); | 42 | int tlsext_ecpf_clienthello_parse(SSL *s, CBS *cbs, int *alert); |
@@ -37,6 +44,7 @@ int tlsext_ecpf_serverhello_needs(SSL *s); | |||
37 | int tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb); | 44 | int tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb); |
38 | int tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert); | 45 | int tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert); |
39 | 46 | ||
47 | |||
40 | int tlsext_clienthello_build(SSL *s, CBB *cbb); | 48 | int tlsext_clienthello_build(SSL *s, CBB *cbb); |
41 | int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, | 49 | int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, |
42 | int *alert); | 50 | int *alert); |
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c index 2e90d3e9df..4983ad27fa 100644 --- a/src/lib/libssl/t1_lib.c +++ b/src/lib/libssl/t1_lib.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: t1_lib.c,v 1.125 2017/08/11 05:06:34 doug Exp $ */ | 1 | /* $OpenBSD: t1_lib.c,v 1.126 2017/08/11 20:14:13 doug Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -365,7 +365,7 @@ tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, | |||
365 | * the client/session curves. Otherwise return the custom curve list if one | 365 | * the client/session curves. Otherwise return the custom curve list if one |
366 | * exists, or the default curves if a custom list has not been specified. | 366 | * exists, or the default curves if a custom list has not been specified. |
367 | */ | 367 | */ |
368 | static void | 368 | void |
369 | tls1_get_curvelist(SSL *s, int client_curves, const uint16_t **pcurves, | 369 | tls1_get_curvelist(SSL *s, int client_curves, const uint16_t **pcurves, |
370 | size_t *pcurveslen) | 370 | size_t *pcurveslen) |
371 | { | 371 | { |
@@ -674,12 +674,9 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) | |||
674 | { | 674 | { |
675 | int extdatalen = 0; | 675 | int extdatalen = 0; |
676 | unsigned char *ret = p; | 676 | unsigned char *ret = p; |
677 | int using_ecc; | ||
678 | size_t len; | 677 | size_t len; |
679 | CBB cbb; | 678 | CBB cbb; |
680 | 679 | ||
681 | using_ecc = ssl_has_ecc_ciphers(s); | ||
682 | |||
683 | ret += 2; | 680 | ret += 2; |
684 | if (ret >= limit) | 681 | if (ret >= limit) |
685 | return NULL; /* this really never occurs, but ... */ | 682 | return NULL; /* this really never occurs, but ... */ |
@@ -698,40 +695,6 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) | |||
698 | return NULL; | 695 | return NULL; |
699 | ret += len; | 696 | ret += len; |
700 | 697 | ||
701 | if (using_ecc) { | ||
702 | size_t curveslen, lenmax; | ||
703 | const uint16_t *curves; | ||
704 | int i; | ||
705 | |||
706 | /* | ||
707 | * Add TLS extension EllipticCurves to the ClientHello message. | ||
708 | */ | ||
709 | tls1_get_curvelist(s, 0, &curves, &curveslen); | ||
710 | |||
711 | if ((size_t)(limit - ret) < 6) | ||
712 | return NULL; | ||
713 | |||
714 | lenmax = limit - ret - 6; | ||
715 | if (curveslen * 2 > lenmax) | ||
716 | return NULL; | ||
717 | if (curveslen * 2 > 65532) { | ||
718 | SSLerror(s, ERR_R_INTERNAL_ERROR); | ||
719 | return NULL; | ||
720 | } | ||
721 | |||
722 | s2n(TLSEXT_TYPE_elliptic_curves, ret); | ||
723 | s2n((curveslen * 2) + 2, ret); | ||
724 | |||
725 | /* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for | ||
726 | * elliptic_curve_list, but the examples use two bytes. | ||
727 | * https://www1.ietf.org/mail-archive/web/tls/current/msg00538.html | ||
728 | * resolves this to two bytes. | ||
729 | */ | ||
730 | s2n(curveslen * 2, ret); | ||
731 | for (i = 0; i < curveslen; i++) | ||
732 | s2n(curves[i], ret); | ||
733 | } | ||
734 | |||
735 | if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { | 698 | if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { |
736 | int ticklen; | 699 | int ticklen; |
737 | if (!s->internal->new_session && s->session && s->session->tlsext_tick) | 700 | if (!s->internal->new_session && s->session && s->session->tlsext_tick) |
@@ -1142,40 +1105,7 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, | |||
1142 | if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) | 1105 | if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) |
1143 | return 0; | 1106 | return 0; |
1144 | 1107 | ||
1145 | if (type == TLSEXT_TYPE_elliptic_curves && | 1108 | if (type == TLSEXT_TYPE_session_ticket) { |
1146 | s->version != DTLS1_VERSION) { | ||
1147 | unsigned char *sdata = data; | ||
1148 | size_t curveslen, i; | ||
1149 | uint16_t *curves; | ||
1150 | |||
1151 | if (size < 2) { | ||
1152 | *al = TLS1_AD_DECODE_ERROR; | ||
1153 | return 0; | ||
1154 | } | ||
1155 | n2s(sdata, curveslen); | ||
1156 | if (curveslen != size - 2 || curveslen % 2 != 0) { | ||
1157 | *al = TLS1_AD_DECODE_ERROR; | ||
1158 | return 0; | ||
1159 | } | ||
1160 | curveslen /= 2; | ||
1161 | |||
1162 | if (!s->internal->hit) { | ||
1163 | if (SSI(s)->tlsext_supportedgroups) { | ||
1164 | *al = TLS1_AD_DECODE_ERROR; | ||
1165 | return 0; | ||
1166 | } | ||
1167 | SSI(s)->tlsext_supportedgroups_length = 0; | ||
1168 | if ((curves = reallocarray(NULL, curveslen, | ||
1169 | sizeof(uint16_t))) == NULL) { | ||
1170 | *al = TLS1_AD_INTERNAL_ERROR; | ||
1171 | return 0; | ||
1172 | } | ||
1173 | for (i = 0; i < curveslen; i++) | ||
1174 | n2s(sdata, curves[i]); | ||
1175 | SSI(s)->tlsext_supportedgroups = curves; | ||
1176 | SSI(s)->tlsext_supportedgroups_length = curveslen; | ||
1177 | } | ||
1178 | } else if (type == TLSEXT_TYPE_session_ticket) { | ||
1179 | if (s->internal->tls_session_ticket_ext_cb && | 1109 | if (s->internal->tls_session_ticket_ext_cb && |
1180 | !s->internal->tls_session_ticket_ext_cb(s, data, size, s->internal->tls_session_ticket_ext_cb_arg)) { | 1110 | !s->internal->tls_session_ticket_ext_cb(s, data, size, s->internal->tls_session_ticket_ext_cb_arg)) { |
1181 | *al = TLS1_AD_INTERNAL_ERROR; | 1111 | *al = TLS1_AD_INTERNAL_ERROR; |
diff --git a/src/regress/lib/libssl/tlsext/tlsexttest.c b/src/regress/lib/libssl/tlsext/tlsexttest.c index 5a7a34c56c..4f9e6e29e2 100644 --- a/src/regress/lib/libssl/tlsext/tlsexttest.c +++ b/src/regress/lib/libssl/tlsext/tlsexttest.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tlsexttest.c,v 1.4 2017/08/11 05:06:34 doug Exp $ */ | 1 | /* $OpenBSD: tlsexttest.c,v 1.5 2017/08/11 20:14:13 doug Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -34,6 +34,17 @@ hexdump(const unsigned char *buf, size_t len) | |||
34 | } | 34 | } |
35 | 35 | ||
36 | static void | 36 | static void |
37 | hexdump2(const uint16_t *buf, size_t len) | ||
38 | { | ||
39 | size_t i; | ||
40 | |||
41 | for (i = 1; i <= len / 2; i++) | ||
42 | fprintf(stderr, " 0x%04hx,%s", buf[i - 1], i % 8 ? "" : "\n"); | ||
43 | |||
44 | fprintf(stderr, "\n"); | ||
45 | } | ||
46 | |||
47 | static void | ||
37 | compare_data(const uint8_t *recv, size_t recv_len, const uint8_t *expect, | 48 | compare_data(const uint8_t *recv, size_t recv_len, const uint8_t *expect, |
38 | size_t expect_len) | 49 | size_t expect_len) |
39 | { | 50 | { |
@@ -44,6 +55,17 @@ compare_data(const uint8_t *recv, size_t recv_len, const uint8_t *expect, | |||
44 | hexdump(expect, expect_len); | 55 | hexdump(expect, expect_len); |
45 | } | 56 | } |
46 | 57 | ||
58 | static void | ||
59 | compare_data2(const uint16_t *recv, size_t recv_len, const uint16_t *expect, | ||
60 | size_t expect_len) | ||
61 | { | ||
62 | fprintf(stderr, "received:\n"); | ||
63 | hexdump2(recv, recv_len); | ||
64 | |||
65 | fprintf(stderr, "test data:\n"); | ||
66 | hexdump2(expect, expect_len); | ||
67 | } | ||
68 | |||
47 | #define FAIL(msg, ...) \ | 69 | #define FAIL(msg, ...) \ |
48 | do { \ | 70 | do { \ |
49 | fprintf(stderr, "[%s:%d] FAIL: ", __FILE__, __LINE__); \ | 71 | fprintf(stderr, "[%s:%d] FAIL: ", __FILE__, __LINE__); \ |
@@ -988,6 +1010,317 @@ test_tlsext_ecpf_serverhello(void) | |||
988 | return (failure); | 1010 | return (failure); |
989 | } | 1011 | } |
990 | 1012 | ||
1013 | /* | ||
1014 | * ellliptic_curves - RFC 4492 section 5.1.1 (Supported Elliptic Curves). | ||
1015 | * | ||
1016 | * This extension is only used by the client. | ||
1017 | */ | ||
1018 | |||
1019 | static uint8_t tlsext_ec_clienthello_default[] = { | ||
1020 | 0x00, 0x06, | ||
1021 | 0x00, 0x1d, /* X25519 (29) */ | ||
1022 | 0x00, 0x17, /* secp256r1 (23) */ | ||
1023 | 0x00, 0x18 /* secp384r1 (24) */ | ||
1024 | }; | ||
1025 | |||
1026 | static uint16_t tlsext_ec_clienthello_secp384r1_val[] = { | ||
1027 | 0x0018 /* tls1_ec_nid2curve_id(NID_secp384r1) */ | ||
1028 | }; | ||
1029 | static uint8_t tlsext_ec_clienthello_secp384r1[] = { | ||
1030 | 0x00, 0x02, | ||
1031 | 0x00, 0x18 /* secp384r1 (24) */ | ||
1032 | }; | ||
1033 | |||
1034 | /* Example from RFC 4492 section 5.1.1 */ | ||
1035 | static uint16_t tlsext_ec_clienthello_nistp192and224_val[] = { | ||
1036 | 0x0013, /* tls1_ec_nid2curve_id(NID_X9_62_prime192v1) */ | ||
1037 | 0x0015 /* tls1_ec_nid2curve_id(NID_secp224r1) */ | ||
1038 | }; | ||
1039 | static uint8_t tlsext_ec_clienthello_nistp192and224[] = { | ||
1040 | 0x00, 0x04, | ||
1041 | 0x00, 0x13, /* secp192r1 aka NIST P-192 */ | ||
1042 | 0x00, 0x15 /* secp224r1 aka NIST P-224 */ | ||
1043 | }; | ||
1044 | |||
1045 | static int | ||
1046 | test_tlsext_ec_clienthello(void) | ||
1047 | { | ||
1048 | unsigned char *data = NULL; | ||
1049 | SSL_CTX *ssl_ctx = NULL; | ||
1050 | SSL *ssl = NULL; | ||
1051 | size_t dlen; | ||
1052 | int failure, alert; | ||
1053 | CBB cbb; | ||
1054 | CBS cbs; | ||
1055 | |||
1056 | failure = 1; | ||
1057 | |||
1058 | CBB_init(&cbb, 0); | ||
1059 | |||
1060 | if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) | ||
1061 | errx(1, "failed to create SSL_CTX"); | ||
1062 | if ((ssl = SSL_new(ssl_ctx)) == NULL) | ||
1063 | errx(1, "failed to create SSL"); | ||
1064 | |||
1065 | /* | ||
1066 | * Default ciphers include EC so we need it by default. | ||
1067 | */ | ||
1068 | if (!tlsext_ec_clienthello_needs(ssl)) { | ||
1069 | FAIL("clienthello should need Ellipticcurves for default " | ||
1070 | "ciphers\n"); | ||
1071 | goto err; | ||
1072 | } | ||
1073 | |||
1074 | /* | ||
1075 | * Exclude cipher suites so we can test not including it. | ||
1076 | */ | ||
1077 | if (!SSL_set_cipher_list(ssl, "TLSv1.2:!ECDHE:!ECDSA")) { | ||
1078 | FAIL("clienthello should be able to set cipher list\n"); | ||
1079 | goto err; | ||
1080 | } | ||
1081 | if (tlsext_ec_clienthello_needs(ssl)) { | ||
1082 | FAIL("clienthello should not need Ellipticcurves\n"); | ||
1083 | goto err; | ||
1084 | } | ||
1085 | |||
1086 | /* | ||
1087 | * Use libtls default for the rest of the testing | ||
1088 | */ | ||
1089 | if (!SSL_set_cipher_list(ssl, "TLSv1.2+AEAD+ECDHE")) { | ||
1090 | FAIL("clienthello should be able to set cipher list\n"); | ||
1091 | goto err; | ||
1092 | } | ||
1093 | if (!tlsext_ec_clienthello_needs(ssl)) { | ||
1094 | FAIL("clienthello should need Ellipticcurves\n"); | ||
1095 | goto err; | ||
1096 | } | ||
1097 | |||
1098 | /* | ||
1099 | * Test with a session secp384r1. The default is used instead. | ||
1100 | */ | ||
1101 | if ((ssl->session = SSL_SESSION_new()) == NULL) | ||
1102 | errx(1, "failed to create session"); | ||
1103 | |||
1104 | if ((SSI(ssl)->tlsext_supportedgroups = malloc(sizeof(uint16_t))) | ||
1105 | == NULL) { | ||
1106 | FAIL("client could not malloc\n"); | ||
1107 | goto err; | ||
1108 | } | ||
1109 | SSI(ssl)->tlsext_supportedgroups[0] = tls1_ec_nid2curve_id(NID_secp384r1); | ||
1110 | SSI(ssl)->tlsext_supportedgroups_length = 1; | ||
1111 | |||
1112 | if (!tlsext_ec_clienthello_needs(ssl)) { | ||
1113 | FAIL("clienthello should need Ellipticcurves\n"); | ||
1114 | goto err; | ||
1115 | } | ||
1116 | |||
1117 | if (!tlsext_ec_clienthello_build(ssl, &cbb)) { | ||
1118 | FAIL("clienthello failed to build Ellipticcurves\n"); | ||
1119 | goto err; | ||
1120 | } | ||
1121 | |||
1122 | if (!CBB_finish(&cbb, &data, &dlen)) | ||
1123 | errx(1, "failed to finish CBB"); | ||
1124 | |||
1125 | if (dlen != sizeof(tlsext_ec_clienthello_default)) { | ||
1126 | FAIL("got clienthello Ellipticcurves with length %zu, " | ||
1127 | "want length %zu\n", dlen, | ||
1128 | sizeof(tlsext_ec_clienthello_default)); | ||
1129 | compare_data(data, dlen, tlsext_ec_clienthello_default, | ||
1130 | sizeof(tlsext_ec_clienthello_default)); | ||
1131 | goto err; | ||
1132 | } | ||
1133 | |||
1134 | if (memcmp(data, tlsext_ec_clienthello_default, dlen) != 0) { | ||
1135 | FAIL("clienthello Ellipticcurves differs:\n"); | ||
1136 | compare_data(data, dlen, tlsext_ec_clienthello_default, | ||
1137 | sizeof(tlsext_ec_clienthello_default)); | ||
1138 | goto err; | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * Test parsing secp384r1 | ||
1143 | */ | ||
1144 | CBB_cleanup(&cbb); | ||
1145 | CBB_init(&cbb, 0); | ||
1146 | free(data); | ||
1147 | data = NULL; | ||
1148 | |||
1149 | SSL_SESSION_free(ssl->session); | ||
1150 | if ((ssl->session = SSL_SESSION_new()) == NULL) | ||
1151 | errx(1, "failed to create session"); | ||
1152 | |||
1153 | CBS_init(&cbs, tlsext_ec_clienthello_secp384r1, | ||
1154 | sizeof(tlsext_ec_clienthello_secp384r1)); | ||
1155 | if (!tlsext_ec_clienthello_parse(ssl, &cbs, &alert)) { | ||
1156 | FAIL("failed to parse clienthello Ellipticcurves\n"); | ||
1157 | goto err; | ||
1158 | } | ||
1159 | |||
1160 | if (SSI(ssl)->tlsext_supportedgroups_length != | ||
1161 | sizeof(tlsext_ec_clienthello_secp384r1_val) / sizeof(uint16_t)) { | ||
1162 | FAIL("no tlsext_ellipticcurves from clienthello " | ||
1163 | "Ellipticcurves\n"); | ||
1164 | goto err; | ||
1165 | } | ||
1166 | |||
1167 | if (memcmp(SSI(ssl)->tlsext_supportedgroups, | ||
1168 | tlsext_ec_clienthello_secp384r1_val, | ||
1169 | sizeof(tlsext_ec_clienthello_secp384r1_val)) != 0) { | ||
1170 | FAIL("clienthello had an incorrect Ellipticcurves " | ||
1171 | "entry\n"); | ||
1172 | compare_data2(SSI(ssl)->tlsext_supportedgroups, | ||
1173 | SSI(ssl)->tlsext_supportedgroups_length * 2, | ||
1174 | tlsext_ec_clienthello_secp384r1_val, | ||
1175 | sizeof(tlsext_ec_clienthello_secp384r1_val)); | ||
1176 | goto err; | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1180 | * Use a custom order. | ||
1181 | */ | ||
1182 | CBB_cleanup(&cbb); | ||
1183 | CBB_init(&cbb, 0); | ||
1184 | |||
1185 | SSL_SESSION_free(ssl->session); | ||
1186 | if ((ssl->session = SSL_SESSION_new()) == NULL) | ||
1187 | errx(1, "failed to create session"); | ||
1188 | |||
1189 | if ((ssl->internal->tlsext_supportedgroups = malloc(sizeof(uint16_t) * 2)) == NULL) { | ||
1190 | FAIL("client could not malloc\n"); | ||
1191 | goto err; | ||
1192 | } | ||
1193 | ssl->internal->tlsext_supportedgroups[0] = tls1_ec_nid2curve_id(NID_X9_62_prime192v1); | ||
1194 | ssl->internal->tlsext_supportedgroups[1] = tls1_ec_nid2curve_id(NID_secp224r1); | ||
1195 | ssl->internal->tlsext_supportedgroups_length = 2; | ||
1196 | |||
1197 | if (!tlsext_ec_clienthello_needs(ssl)) { | ||
1198 | FAIL("clienthello should need Ellipticcurves\n"); | ||
1199 | goto err; | ||
1200 | } | ||
1201 | |||
1202 | if (!tlsext_ec_clienthello_build(ssl, &cbb)) { | ||
1203 | FAIL("clienthello failed to build Ellipticcurves\n"); | ||
1204 | goto err; | ||
1205 | } | ||
1206 | |||
1207 | if (!CBB_finish(&cbb, &data, &dlen)) | ||
1208 | errx(1, "failed to finish CBB"); | ||
1209 | |||
1210 | if (dlen != sizeof(tlsext_ec_clienthello_nistp192and224)) { | ||
1211 | FAIL("got clienthello Ellipticcurves with length %zu, " | ||
1212 | "want length %zu\n", dlen, | ||
1213 | sizeof(tlsext_ec_clienthello_nistp192and224)); | ||
1214 | fprintf(stderr, "received:\n"); | ||
1215 | hexdump(data, dlen); | ||
1216 | fprintf(stderr, "test data:\n"); | ||
1217 | hexdump(tlsext_ec_clienthello_nistp192and224, | ||
1218 | sizeof(tlsext_ec_clienthello_nistp192and224)); | ||
1219 | goto err; | ||
1220 | } | ||
1221 | |||
1222 | if (memcmp(data, tlsext_ec_clienthello_nistp192and224, dlen) != 0) { | ||
1223 | FAIL("clienthello Ellipticcurves differs:\n"); | ||
1224 | fprintf(stderr, "received:\n"); | ||
1225 | hexdump(data, dlen); | ||
1226 | fprintf(stderr, "test data:\n"); | ||
1227 | hexdump(tlsext_ec_clienthello_nistp192and224, | ||
1228 | sizeof(tlsext_ec_clienthello_nistp192and224)); | ||
1229 | goto err; | ||
1230 | } | ||
1231 | |||
1232 | /* | ||
1233 | * Parse non-default curves to session. | ||
1234 | */ | ||
1235 | CBB_cleanup(&cbb); | ||
1236 | CBB_init(&cbb, 0); | ||
1237 | free(data); | ||
1238 | data = NULL; | ||
1239 | |||
1240 | SSL_SESSION_free(ssl->session); | ||
1241 | if ((ssl->session = SSL_SESSION_new()) == NULL) | ||
1242 | errx(1, "failed to create session"); | ||
1243 | |||
1244 | /* Reset back to the default list. */ | ||
1245 | free(ssl->internal->tlsext_supportedgroups); | ||
1246 | ssl->internal->tlsext_supportedgroups = NULL; | ||
1247 | ssl->internal->tlsext_supportedgroups_length = 0; | ||
1248 | |||
1249 | CBS_init(&cbs, tlsext_ec_clienthello_nistp192and224, | ||
1250 | sizeof(tlsext_ec_clienthello_nistp192and224)); | ||
1251 | if (!tlsext_ec_clienthello_parse(ssl, &cbs, &alert)) { | ||
1252 | FAIL("failed to parse clienthello Ellipticcurves\n"); | ||
1253 | goto err; | ||
1254 | } | ||
1255 | |||
1256 | if (SSI(ssl)->tlsext_supportedgroups_length != | ||
1257 | sizeof(tlsext_ec_clienthello_nistp192and224_val) / sizeof(uint16_t)) { | ||
1258 | FAIL("no tlsext_ellipticcurves from clienthello " | ||
1259 | "Ellipticcurves\n"); | ||
1260 | goto err; | ||
1261 | } | ||
1262 | |||
1263 | if (memcmp(SSI(ssl)->tlsext_supportedgroups, | ||
1264 | tlsext_ec_clienthello_nistp192and224_val, | ||
1265 | sizeof(tlsext_ec_clienthello_nistp192and224_val)) != 0) { | ||
1266 | FAIL("clienthello had an incorrect Ellipticcurves entry\n"); | ||
1267 | compare_data2(SSI(ssl)->tlsext_supportedgroups, | ||
1268 | SSI(ssl)->tlsext_supportedgroups_length * 2, | ||
1269 | tlsext_ec_clienthello_nistp192and224_val, | ||
1270 | sizeof(tlsext_ec_clienthello_nistp192and224_val)); | ||
1271 | goto err; | ||
1272 | } | ||
1273 | |||
1274 | failure = 0; | ||
1275 | |||
1276 | err: | ||
1277 | CBB_cleanup(&cbb); | ||
1278 | SSL_CTX_free(ssl_ctx); | ||
1279 | SSL_free(ssl); | ||
1280 | free(data); | ||
1281 | |||
1282 | return (failure); | ||
1283 | } | ||
1284 | |||
1285 | |||
1286 | /* elliptic_curves is only used by the client so this doesn't test much. */ | ||
1287 | static int | ||
1288 | test_tlsext_ec_serverhello(void) | ||
1289 | { | ||
1290 | SSL_CTX *ssl_ctx = NULL; | ||
1291 | SSL *ssl = NULL; | ||
1292 | int failure; | ||
1293 | |||
1294 | failure = 1; | ||
1295 | |||
1296 | if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) | ||
1297 | errx(1, "failed to create SSL_CTX"); | ||
1298 | if ((ssl = SSL_new(ssl_ctx)) == NULL) | ||
1299 | errx(1, "failed to create SSL"); | ||
1300 | |||
1301 | if (tlsext_ec_serverhello_needs(ssl)) { | ||
1302 | FAIL("serverhello should not need elliptic_curves\n"); | ||
1303 | goto err; | ||
1304 | } | ||
1305 | |||
1306 | if ((ssl->session = SSL_SESSION_new()) == NULL) | ||
1307 | errx(1, "failed to create session"); | ||
1308 | |||
1309 | if (tlsext_ec_serverhello_needs(ssl)) { | ||
1310 | FAIL("serverhello should not need elliptic_curves\n"); | ||
1311 | goto err; | ||
1312 | } | ||
1313 | |||
1314 | failure = 0; | ||
1315 | |||
1316 | err: | ||
1317 | SSL_CTX_free(ssl_ctx); | ||
1318 | SSL_free(ssl); | ||
1319 | |||
1320 | return (failure); | ||
1321 | |||
1322 | } | ||
1323 | |||
991 | int | 1324 | int |
992 | main(int argc, char **argv) | 1325 | main(int argc, char **argv) |
993 | { | 1326 | { |
@@ -1004,5 +1337,8 @@ main(int argc, char **argv) | |||
1004 | failed |= test_tlsext_ecpf_clienthello(); | 1337 | failed |= test_tlsext_ecpf_clienthello(); |
1005 | failed |= test_tlsext_ecpf_serverhello(); | 1338 | failed |= test_tlsext_ecpf_serverhello(); |
1006 | 1339 | ||
1340 | failed |= test_tlsext_ec_clienthello(); | ||
1341 | failed |= test_tlsext_ec_serverhello(); | ||
1342 | |||
1007 | return (failed); | 1343 | return (failed); |
1008 | } | 1344 | } |