summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libssl/ssl_locl.h5
-rw-r--r--src/lib/libssl/ssl_tlsext.c108
-rw-r--r--src/lib/libssl/ssl_tlsext.h9
-rw-r--r--src/lib/libssl/t1_lib.c150
-rw-r--r--src/regress/lib/libssl/tlsext/tlsexttest.c471
5 files changed, 595 insertions, 148 deletions
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h
index 8ef2d01402..c11c5899e3 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.184 2017/08/10 17:18:38 jsing Exp $ */ 1/* $OpenBSD: ssl_locl.h,v 1.185 2017/08/11 05:06:34 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 *
@@ -1380,6 +1380,9 @@ int SSL_state_func_code(int _state);
1380#define SSLerrorx(r) ERR_PUT_error(ERR_LIB_SSL,(0xfff),(r),__FILE__,__LINE__) 1380#define SSLerrorx(r) ERR_PUT_error(ERR_LIB_SSL,(0xfff),(r),__FILE__,__LINE__)
1381void SSL_error_internal(const SSL *s, int r, char *f, int l); 1381void SSL_error_internal(const SSL *s, int r, char *f, int l);
1382 1382
1383void tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats,
1384 size_t *pformatslen);
1385
1383__END_HIDDEN_DECLS 1386__END_HIDDEN_DECLS
1384 1387
1385#endif 1388#endif
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index 400c69fa87..e8723b502c 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.3 2017/07/24 17:39:43 jsing Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.4 2017/08/11 05:06:34 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 * 4 *
@@ -21,6 +21,103 @@
21#include "ssl_tlsext.h" 21#include "ssl_tlsext.h"
22 22
23/* 23/*
24 * Supported Point Formats Extension - RFC 4492 section 5.1.2
25 */
26static int
27tlsext_ecpf_build(SSL *s, CBB *cbb)
28{
29 CBB ecpf;
30 size_t formats_len;
31 const uint8_t *formats;
32
33 tls1_get_formatlist(s, 0, &formats, &formats_len);
34
35 if (formats_len == 0) {
36 SSLerror(s, ERR_R_INTERNAL_ERROR);
37 return 0;
38 }
39
40 if (!CBB_add_u8_length_prefixed(cbb, &ecpf))
41 return 0;
42 if (!CBB_add_bytes(&ecpf, formats, formats_len))
43 return 0;
44 if (!CBB_flush(cbb))
45 return 0;
46
47 return 1;
48}
49
50static int
51tlsext_ecpf_parse(SSL *s, CBS *cbs, int *alert)
52{
53 CBS ecpf;
54
55 if (!CBS_get_u8_length_prefixed(cbs, &ecpf))
56 goto err;
57 if (CBS_len(&ecpf) == 0)
58 goto err;
59 if (CBS_len(cbs) != 0)
60 goto err;
61
62 /* Must contain uncompressed (0) */
63 if (!CBS_contains_zero_byte(&ecpf)) {
64 SSLerror(s, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
65 goto err;
66 }
67
68 if (!s->internal->hit) {
69 if (!CBS_stow(&ecpf, &(SSI(s)->tlsext_ecpointformatlist),
70 &(SSI(s)->tlsext_ecpointformatlist_length)))
71 goto err;
72 }
73
74 return 1;
75
76 err:
77 *alert = TLS1_AD_INTERNAL_ERROR;
78 return 0;
79}
80
81int
82tlsext_ecpf_clienthello_needs(SSL *s)
83{
84 return ssl_has_ecc_ciphers(s);
85}
86
87int
88tlsext_ecpf_clienthello_build(SSL *s, CBB *cbb)
89{
90 return tlsext_ecpf_build(s, cbb);
91}
92
93int
94tlsext_ecpf_clienthello_parse(SSL *s, CBS *cbs, int *alert)
95{
96 return tlsext_ecpf_parse(s, cbs, alert);
97}
98
99int
100tlsext_ecpf_serverhello_needs(SSL *s)
101{
102 if (s->version == DTLS1_VERSION)
103 return 0;
104
105 return ssl_using_ecc_cipher(s);
106}
107
108int
109tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb)
110{
111 return tlsext_ecpf_build(s, cbb);
112}
113
114int
115tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert)
116{
117 return tlsext_ecpf_parse(s, cbs, alert);
118}
119
120/*
24 * Renegotiation Indication - RFC 5746. 121 * Renegotiation Indication - RFC 5746.
25 */ 122 */
26int 123int
@@ -313,6 +410,15 @@ static struct tls_extension tls_extensions[] = {
313 .serverhello_build = tlsext_ri_serverhello_build, 410 .serverhello_build = tlsext_ri_serverhello_build,
314 .serverhello_parse = tlsext_ri_serverhello_parse, 411 .serverhello_parse = tlsext_ri_serverhello_parse,
315 }, 412 },
413 {
414 .type = TLSEXT_TYPE_ec_point_formats,
415 .clienthello_needs = tlsext_ecpf_clienthello_needs,
416 .clienthello_build = tlsext_ecpf_clienthello_build,
417 .clienthello_parse = tlsext_ecpf_clienthello_parse,
418 .serverhello_needs = tlsext_ecpf_serverhello_needs,
419 .serverhello_build = tlsext_ecpf_serverhello_build,
420 .serverhello_parse = tlsext_ecpf_serverhello_parse,
421 },
316}; 422};
317 423
318#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) 424#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 4b0194861a..67a9cfb688 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.2 2017/07/24 17:10:31 jsing Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.3 2017/08/11 05:06:34 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 * 4 *
@@ -29,6 +29,13 @@ int tlsext_sni_serverhello_needs(SSL *s);
29int tlsext_sni_serverhello_build(SSL *s, CBB *cbb); 29int tlsext_sni_serverhello_build(SSL *s, CBB *cbb);
30int tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert); 30int tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert);
31 31
32int tlsext_ecpf_clienthello_needs(SSL *s);
33int tlsext_ecpf_clienthello_build(SSL *s, CBB *cbb);
34int tlsext_ecpf_clienthello_parse(SSL *s, CBS *cbs, int *alert);
35int tlsext_ecpf_serverhello_needs(SSL *s);
36int tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb);
37int tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert);
38
32int tlsext_clienthello_build(SSL *s, CBB *cbb); 39int tlsext_clienthello_build(SSL *s, CBB *cbb);
33int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, 40int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type,
34 int *alert); 41 int *alert);
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c
index 42fd18fe2d..2e90d3e9df 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.124 2017/08/10 17:18:38 jsing Exp $ */ 1/* $OpenBSD: t1_lib.c,v 1.125 2017/08/11 05:06:34 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 *
@@ -342,7 +342,7 @@ tls1_ec_nid2curve_id(int nid)
342 * the client/session formats. Otherwise return the custom format list if one 342 * the client/session formats. Otherwise return the custom format list if one
343 * exists, or the default formats if a custom list has not been specified. 343 * exists, or the default formats if a custom list has not been specified.
344 */ 344 */
345static void 345void
346tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, 346tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats,
347 size_t *pformatslen) 347 size_t *pformatslen)
348{ 348{
@@ -699,34 +699,11 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
699 ret += len; 699 ret += len;
700 700
701 if (using_ecc) { 701 if (using_ecc) {
702 size_t curveslen, formatslen, lenmax; 702 size_t curveslen, lenmax;
703 const uint16_t *curves; 703 const uint16_t *curves;
704 const uint8_t *formats;
705 int i; 704 int i;
706 705
707 /* 706 /*
708 * Add TLS extension ECPointFormats to the ClientHello message.
709 */
710 tls1_get_formatlist(s, 0, &formats, &formatslen);
711
712 if ((size_t)(limit - ret) < 5)
713 return NULL;
714
715 lenmax = limit - ret - 5;
716 if (formatslen > lenmax)
717 return NULL;
718 if (formatslen > 255) {
719 SSLerror(s, ERR_R_INTERNAL_ERROR);
720 return NULL;
721 }
722
723 s2n(TLSEXT_TYPE_ec_point_formats, ret);
724 s2n(formatslen + 1, ret);
725 *(ret++) = (unsigned char)formatslen;
726 memcpy(ret, formats, formatslen);
727 ret += formatslen;
728
729 /*
730 * Add TLS extension EllipticCurves to the ClientHello message. 707 * Add TLS extension EllipticCurves to the ClientHello message.
731 */ 708 */
732 tls1_get_curvelist(s, 0, &curves, &curveslen); 709 tls1_get_curvelist(s, 0, &curves, &curveslen);
@@ -931,14 +908,12 @@ skip_ext:
931unsigned char * 908unsigned char *
932ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) 909ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
933{ 910{
934 int using_ecc, extdatalen = 0; 911 int extdatalen = 0;
935 unsigned char *ret = p; 912 unsigned char *ret = p;
936 int next_proto_neg_seen; 913 int next_proto_neg_seen;
937 size_t len; 914 size_t len;
938 CBB cbb; 915 CBB cbb;
939 916
940 using_ecc = ssl_using_ecc_cipher(s);
941
942 ret += 2; 917 ret += 2;
943 if (ret >= limit) 918 if (ret >= limit)
944 return NULL; /* this really never occurs, but ... */ 919 return NULL; /* this really never occurs, but ... */
@@ -957,33 +932,6 @@ ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
957 return NULL; 932 return NULL;
958 ret += len; 933 ret += len;
959 934
960 if (using_ecc && s->version != DTLS1_VERSION) {
961 const unsigned char *formats;
962 size_t formatslen, lenmax;
963
964 /*
965 * Add TLS extension ECPointFormats to the ServerHello message.
966 */
967 tls1_get_formatlist(s, 0, &formats, &formatslen);
968
969 if ((size_t)(limit - ret) < 5)
970 return NULL;
971
972 lenmax = limit - ret - 5;
973 if (formatslen > lenmax)
974 return NULL;
975 if (formatslen > 255) {
976 SSLerror(s, ERR_R_INTERNAL_ERROR);
977 return NULL;
978 }
979
980 s2n(TLSEXT_TYPE_ec_point_formats, ret);
981 s2n(formatslen + 1, ret);
982 *(ret++) = (unsigned char)formatslen;
983 memcpy(ret, formats, formatslen);
984 ret += formatslen;
985 }
986
987 /* 935 /*
988 * Currently the server should not respond with a SupportedCurves 936 * Currently the server should not respond with a SupportedCurves
989 * extension. 937 * extension.
@@ -1194,38 +1142,7 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
1194 if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) 1142 if (!tlsext_clienthello_parse_one(s, &cbs, type, al))
1195 return 0; 1143 return 0;
1196 1144
1197 if (type == TLSEXT_TYPE_ec_point_formats && 1145 if (type == TLSEXT_TYPE_elliptic_curves &&
1198 s->version != DTLS1_VERSION) {
1199 unsigned char *sdata = data;
1200 size_t formatslen;
1201 uint8_t *formats;
1202
1203 if (size < 1) {
1204 *al = TLS1_AD_DECODE_ERROR;
1205 return 0;
1206 }
1207 formatslen = *(sdata++);
1208 if (formatslen != size - 1) {
1209 *al = TLS1_AD_DECODE_ERROR;
1210 return 0;
1211 }
1212
1213 if (!s->internal->hit) {
1214 free(SSI(s)->tlsext_ecpointformatlist);
1215 SSI(s)->tlsext_ecpointformatlist = NULL;
1216 SSI(s)->tlsext_ecpointformatlist_length = 0;
1217
1218 if ((formats = reallocarray(NULL, formatslen,
1219 sizeof(uint8_t))) == NULL) {
1220 *al = TLS1_AD_INTERNAL_ERROR;
1221 return 0;
1222 }
1223 memcpy(formats, sdata, formatslen);
1224 SSI(s)->tlsext_ecpointformatlist = formats;
1225 SSI(s)->tlsext_ecpointformatlist_length =
1226 formatslen;
1227 }
1228 } else if (type == TLSEXT_TYPE_elliptic_curves &&
1229 s->version != DTLS1_VERSION) { 1146 s->version != DTLS1_VERSION) {
1230 unsigned char *sdata = data; 1147 unsigned char *sdata = data;
1231 size_t curveslen, i; 1148 size_t curveslen, i;
@@ -1510,39 +1427,7 @@ ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al)
1510 if (!tlsext_serverhello_parse_one(s, &cbs, type, al)) 1427 if (!tlsext_serverhello_parse_one(s, &cbs, type, al))
1511 return 0; 1428 return 0;
1512 1429
1513 if (type == TLSEXT_TYPE_ec_point_formats && 1430 if (type == TLSEXT_TYPE_session_ticket) {
1514 s->version != DTLS1_VERSION) {
1515 unsigned char *sdata = data;
1516 size_t formatslen;
1517 uint8_t *formats;
1518
1519 if (size < 1) {
1520 *al = TLS1_AD_DECODE_ERROR;
1521 return 0;
1522 }
1523 formatslen = *(sdata++);
1524 if (formatslen != size - 1) {
1525 *al = TLS1_AD_DECODE_ERROR;
1526 return 0;
1527 }
1528
1529 if (!s->internal->hit) {
1530 free(SSI(s)->tlsext_ecpointformatlist);
1531 SSI(s)->tlsext_ecpointformatlist = NULL;
1532 SSI(s)->tlsext_ecpointformatlist_length = 0;
1533
1534 if ((formats = reallocarray(NULL, formatslen,
1535 sizeof(uint8_t))) == NULL) {
1536 *al = TLS1_AD_INTERNAL_ERROR;
1537 return 0;
1538 }
1539 memcpy(formats, sdata, formatslen);
1540 SSI(s)->tlsext_ecpointformatlist = formats;
1541 SSI(s)->tlsext_ecpointformatlist_length =
1542 formatslen;
1543 }
1544 }
1545 else if (type == TLSEXT_TYPE_session_ticket) {
1546 if (s->internal->tls_session_ticket_ext_cb && 1431 if (s->internal->tls_session_ticket_ext_cb &&
1547 !s->internal->tls_session_ticket_ext_cb(s, data, size, s->internal->tls_session_ticket_ext_cb_arg)) { 1432 !s->internal->tls_session_ticket_ext_cb(s, data, size, s->internal->tls_session_ticket_ext_cb_arg)) {
1548 *al = TLS1_AD_INTERNAL_ERROR; 1433 *al = TLS1_AD_INTERNAL_ERROR;
@@ -1779,29 +1664,6 @@ ssl_check_serverhello_tlsext(SSL *s)
1779 int ret = SSL_TLSEXT_ERR_NOACK; 1664 int ret = SSL_TLSEXT_ERR_NOACK;
1780 int al = SSL_AD_UNRECOGNIZED_NAME; 1665 int al = SSL_AD_UNRECOGNIZED_NAME;
1781 1666
1782 /* If we are client and using an elliptic curve cryptography cipher
1783 * suite, then if server returns an EC point formats lists extension
1784 * it must contain uncompressed.
1785 */
1786 if (ssl_using_ecc_cipher(s) &&
1787 s->internal->tlsext_ecpointformatlist != NULL &&
1788 s->internal->tlsext_ecpointformatlist_length > 0) {
1789 /* we are using an ECC cipher */
1790 size_t i;
1791 unsigned char *list;
1792 int found_uncompressed = 0;
1793 list = SSI(s)->tlsext_ecpointformatlist;
1794 for (i = 0; i < SSI(s)->tlsext_ecpointformatlist_length; i++) {
1795 if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed) {
1796 found_uncompressed = 1;
1797 break;
1798 }
1799 }
1800 if (!found_uncompressed) {
1801 SSLerror(s, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
1802 return -1;
1803 }
1804 }
1805 ret = SSL_TLSEXT_ERR_OK; 1667 ret = SSL_TLSEXT_ERR_OK;
1806 1668
1807 if (s->ctx != NULL && s->ctx->internal->tlsext_servername_callback != 0) 1669 if (s->ctx != NULL && s->ctx->internal->tlsext_servername_callback != 0)
diff --git a/src/regress/lib/libssl/tlsext/tlsexttest.c b/src/regress/lib/libssl/tlsext/tlsexttest.c
index 792ccfe706..5a7a34c56c 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.3 2017/07/24 17:42:14 jsing Exp $ */ 1/* $OpenBSD: tlsexttest.c,v 1.4 2017/08/11 05:06:34 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -33,6 +33,23 @@ hexdump(const unsigned char *buf, size_t len)
33 fprintf(stderr, "\n"); 33 fprintf(stderr, "\n");
34} 34}
35 35
36static void
37compare_data(const uint8_t *recv, size_t recv_len, const uint8_t *expect,
38 size_t expect_len)
39{
40 fprintf(stderr, "received:\n");
41 hexdump(recv, recv_len);
42
43 fprintf(stderr, "test data:\n");
44 hexdump(expect, expect_len);
45}
46
47#define FAIL(msg, ...) \
48do { \
49 fprintf(stderr, "[%s:%d] FAIL: ", __FILE__, __LINE__); \
50 fprintf(stderr, msg, ##__VA_ARGS__); \
51} while(0)
52
36/* 53/*
37 * Renegotiation Indication - RFC 5746. 54 * Renegotiation Indication - RFC 5746.
38 */ 55 */
@@ -522,6 +539,455 @@ test_tlsext_sni_serverhello(void)
522 return (failure); 539 return (failure);
523} 540}
524 541
542/*
543 * ECPointFormats - RFC 4492 section 5.1.2 (Supported Point Formats).
544 *
545 * Examples are from the RFC. Both client and server have the same build and
546 * parse but the needs differ.
547 */
548
549static uint8_t tlsext_ecpf_hello_uncompressed_val[] = {
550 TLSEXT_ECPOINTFORMAT_uncompressed
551};
552static uint8_t tlsext_ecpf_hello_uncompressed[] = {
553 0x01,
554 0x00 /* TLSEXT_ECPOINTFORMAT_uncompressed */
555};
556
557static uint8_t tlsext_ecpf_hello_prime[] = {
558 0x01,
559 0x01 /* TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime */
560};
561
562static uint8_t tlsext_ecpf_hello_prefer_order_val[] = {
563 TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime,
564 TLSEXT_ECPOINTFORMAT_uncompressed,
565 TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
566};
567static uint8_t tlsext_ecpf_hello_prefer_order[] = {
568 0x03,
569 0x01, /* TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime */
570 0x00, /* TLSEXT_ECPOINTFORMAT_uncompressed */
571 0x02 /* TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 */
572};
573
574static int
575test_tlsext_ecpf_clienthello(void)
576{
577 uint8_t *data = NULL;
578 SSL_CTX *ssl_ctx = NULL;
579 SSL *ssl = NULL;
580 size_t dlen;
581 int failure, alert;
582 CBB cbb;
583 CBS cbs;
584
585 failure = 1;
586
587 CBB_init(&cbb, 0);
588
589 if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL)
590 errx(1, "failed to create SSL_CTX");
591 if ((ssl = SSL_new(ssl_ctx)) == NULL)
592 errx(1, "failed to create SSL");
593
594 /*
595 * Default ciphers include EC so we need it by default.
596 */
597 if (!tlsext_ecpf_clienthello_needs(ssl)) {
598 FAIL("clienthello should need ECPointFormats for default "
599 "ciphers\n");
600 goto err;
601 }
602
603 /*
604 * Exclude EC cipher suites so we can test not including it.
605 */
606 if (!SSL_set_cipher_list(ssl, "ALL:!ECDHE:!ECDH")) {
607 FAIL("clienthello should be able to set cipher list\n");
608 goto err;
609 }
610 if (tlsext_ecpf_clienthello_needs(ssl)) {
611 FAIL("clienthello should not need ECPointFormats\n");
612 goto err;
613 }
614
615 /*
616 * Use libtls default for the rest of the testing
617 */
618 if (!SSL_set_cipher_list(ssl, "TLSv1.2+AEAD+ECDHE")) {
619 FAIL("clienthello should be able to set cipher list\n");
620 goto err;
621 }
622 if (!tlsext_ecpf_clienthello_needs(ssl)) {
623 FAIL("clienthello should need ECPointFormats\n");
624 goto err;
625 }
626
627 /*
628 * The default ECPointFormats should only have uncompressed
629 */
630 if ((ssl->session = SSL_SESSION_new()) == NULL)
631 errx(1, "failed to create session");
632
633 if (!tlsext_ecpf_clienthello_build(ssl, &cbb)) {
634 FAIL("clienthello failed to build ECPointFormats\n");
635 goto err;
636 }
637
638 if (!CBB_finish(&cbb, &data, &dlen))
639 errx(1, "failed to finish CBB");
640
641 if (dlen != sizeof(tlsext_ecpf_hello_uncompressed)) {
642 FAIL("got clienthello ECPointFormats with length %zu, "
643 "want length %zu\n", dlen,
644 sizeof(tlsext_ecpf_hello_uncompressed));
645 compare_data(data, dlen, tlsext_ecpf_hello_uncompressed,
646 sizeof(tlsext_ecpf_hello_uncompressed));
647 goto err;
648 }
649
650 if (memcmp(data, tlsext_ecpf_hello_uncompressed, dlen) != 0) {
651 FAIL("clienthello ECPointFormats differs:\n");
652 compare_data(data, dlen, tlsext_ecpf_hello_uncompressed,
653 sizeof(tlsext_ecpf_hello_uncompressed));
654 goto err;
655 }
656
657 /*
658 * Make sure we can parse the default.
659 */
660 CBB_cleanup(&cbb);
661 CBB_init(&cbb, 0);
662 free(data);
663 data = NULL;
664
665 SSL_SESSION_free(ssl->session);
666 if ((ssl->session = SSL_SESSION_new()) == NULL)
667 errx(1, "failed to create session");
668
669 CBS_init(&cbs, tlsext_ecpf_hello_uncompressed,
670 sizeof(tlsext_ecpf_hello_uncompressed));
671 if (!tlsext_ecpf_clienthello_parse(ssl, &cbs, &alert)) {
672 FAIL("failed to parse clienthello ECPointFormats\n");
673 goto err;
674 }
675
676 if (SSI(ssl)->tlsext_ecpointformatlist_length !=
677 sizeof(tlsext_ecpf_hello_uncompressed_val)) {
678 FAIL("no tlsext_ecpointformats from clienthello "
679 "ECPointFormats\n");
680 goto err;
681 }
682
683 if (memcmp(SSI(ssl)->tlsext_ecpointformatlist,
684 tlsext_ecpf_hello_uncompressed_val,
685 sizeof(tlsext_ecpf_hello_uncompressed_val)) != 0) {
686 FAIL("clienthello had an incorrect ECPointFormats entry\n");
687 goto err;
688 }
689
690 /*
691 * Test with a custom order.
692 */
693 CBB_cleanup(&cbb);
694 CBB_init(&cbb, 0);
695 free(data);
696 data = NULL;
697
698 SSL_SESSION_free(ssl->session);
699 if ((ssl->session = SSL_SESSION_new()) == NULL)
700 errx(1, "failed to create session");
701
702 if ((ssl->internal->tlsext_ecpointformatlist = malloc(sizeof(uint8_t) * 3)) == NULL) {
703 FAIL("client could not malloc\n");
704 goto err;
705 }
706 ssl->internal->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
707 ssl->internal->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_uncompressed;
708 ssl->internal->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
709 ssl->internal->tlsext_ecpointformatlist_length = 3;
710
711 if (!tlsext_ecpf_clienthello_needs(ssl)) {
712 FAIL("clienthello should need ECPointFormats with a custom "
713 "format\n");
714 goto err;
715 }
716
717 if (!tlsext_ecpf_clienthello_build(ssl, &cbb)) {
718 FAIL("clienthello failed to build ECPointFormats\n");
719 goto err;
720 }
721
722 if (!CBB_finish(&cbb, &data, &dlen))
723 errx(1, "failed to finish CBB");
724
725 if (dlen != sizeof(tlsext_ecpf_hello_prefer_order)) {
726 FAIL("got clienthello ECPointFormats with length %zu, "
727 "want length %zu\n", dlen,
728 sizeof(tlsext_ecpf_hello_prefer_order));
729 compare_data(data, dlen, tlsext_ecpf_hello_prefer_order,
730 sizeof(tlsext_ecpf_hello_prefer_order));
731 goto err;
732 }
733
734 if (memcmp(data, tlsext_ecpf_hello_prefer_order, dlen) != 0) {
735 FAIL("clienthello ECPointFormats differs:\n");
736 compare_data(data, dlen, tlsext_ecpf_hello_prefer_order,
737 sizeof(tlsext_ecpf_hello_prefer_order));
738 goto err;
739 }
740
741 /*
742 * Make sure that we can parse this custom order.
743 */
744 CBB_cleanup(&cbb);
745 CBB_init(&cbb, 0);
746 free(data);
747 data = NULL;
748
749 SSL_SESSION_free(ssl->session);
750 if ((ssl->session = SSL_SESSION_new()) == NULL)
751 errx(1, "failed to create session");
752
753 /* Reset the custom list so we go back to the default uncompressed. */
754 free(ssl->internal->tlsext_ecpointformatlist);
755 ssl->internal->tlsext_ecpointformatlist = NULL;
756 ssl->internal->tlsext_ecpointformatlist_length = 0;
757
758 CBS_init(&cbs, tlsext_ecpf_hello_prefer_order,
759 sizeof(tlsext_ecpf_hello_prefer_order));
760 if (!tlsext_ecpf_clienthello_parse(ssl, &cbs, &alert)) {
761 FAIL("failed to parse clienthello ECPointFormats\n");
762 goto err;
763 }
764
765 if (SSI(ssl)->tlsext_ecpointformatlist_length !=
766 sizeof(tlsext_ecpf_hello_prefer_order_val)) {
767 FAIL("no tlsext_ecpointformats from clienthello "
768 "ECPointFormats\n");
769 goto err;
770 }
771
772 if (memcmp(SSI(ssl)->tlsext_ecpointformatlist,
773 tlsext_ecpf_hello_prefer_order_val,
774 sizeof(tlsext_ecpf_hello_prefer_order_val)) != 0) {
775 FAIL("clienthello had an incorrect ECPointFormats entry\n");
776 goto err;
777 }
778
779
780 failure = 0;
781
782 err:
783 CBB_cleanup(&cbb);
784 SSL_CTX_free(ssl_ctx);
785 SSL_free(ssl);
786 free(data);
787
788 return (failure);
789}
790
791
792static int
793test_tlsext_ecpf_serverhello(void)
794{
795 uint8_t *data = NULL;
796 SSL_CTX *ssl_ctx = NULL;
797 SSL *ssl = NULL;
798 size_t dlen;
799 int failure, alert;
800 CBB cbb;
801 CBS cbs;
802
803 failure = 1;
804
805 CBB_init(&cbb, 0);
806
807 if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL)
808 errx(1, "failed to create SSL_CTX");
809 if ((ssl = SSL_new(ssl_ctx)) == NULL)
810 errx(1, "failed to create SSL");
811
812 if ((ssl->session = SSL_SESSION_new()) == NULL)
813 errx(1, "failed to create session");
814
815 /* Setup the state so we can call needs. */
816 if ((S3I(ssl)->hs.new_cipher =
817 ssl3_get_cipher_by_id(TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305))
818 == NULL) {
819 FAIL("serverhello cannot find cipher\n");
820 goto err;
821 }
822 if ((SSI(ssl)->tlsext_ecpointformatlist = malloc(sizeof(uint8_t)))
823 == NULL) {
824 FAIL("server could not malloc\n");
825 goto err;
826 }
827 SSI(ssl)->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
828 SSI(ssl)->tlsext_ecpointformatlist_length = 1;
829
830 if (!tlsext_ecpf_serverhello_needs(ssl)) {
831 FAIL("serverhello should need ECPointFormats now\n");
832 goto err;
833 }
834
835 /*
836 * The server will ignore the session list and use either a custom
837 * list or the default (uncompressed).
838 */
839 if (!tlsext_ecpf_serverhello_build(ssl, &cbb)) {
840 FAIL("serverhello failed to build ECPointFormats\n");
841 goto err;
842 }
843
844 if (!CBB_finish(&cbb, &data, &dlen))
845 errx(1, "failed to finish CBB");
846
847 if (dlen != sizeof(tlsext_ecpf_hello_uncompressed)) {
848 FAIL("got serverhello ECPointFormats with length %zu, "
849 "want length %zu\n", dlen,
850 sizeof(tlsext_ecpf_hello_uncompressed));
851 compare_data(data, dlen, tlsext_ecpf_hello_uncompressed,
852 sizeof(tlsext_ecpf_hello_uncompressed));
853 goto err;
854 }
855
856 if (memcmp(data, tlsext_ecpf_hello_uncompressed, dlen) != 0) {
857 FAIL("serverhello ECPointFormats differs:\n");
858 compare_data(data, dlen, tlsext_ecpf_hello_uncompressed,
859 sizeof(tlsext_ecpf_hello_uncompressed));
860 goto err;
861 }
862
863 /*
864 * Cannot parse a non-default list without at least uncompressed.
865 */
866 CBB_cleanup(&cbb);
867 CBB_init(&cbb, 0);
868 free(data);
869 data = NULL;
870
871 SSL_SESSION_free(ssl->session);
872 if ((ssl->session = SSL_SESSION_new()) == NULL)
873 errx(1, "failed to create session");
874
875 CBS_init(&cbs, tlsext_ecpf_hello_prime,
876 sizeof(tlsext_ecpf_hello_prime));
877 if (tlsext_ecpf_serverhello_parse(ssl, &cbs, &alert)) {
878 FAIL("must include uncompressed in serverhello ECPointFormats\n");
879 goto err;
880 }
881
882 /*
883 * Test with a custom order that replaces the default uncompressed.
884 */
885 CBB_cleanup(&cbb);
886 CBB_init(&cbb, 0);
887 free(data);
888 data = NULL;
889
890 SSL_SESSION_free(ssl->session);
891 if ((ssl->session = SSL_SESSION_new()) == NULL)
892 errx(1, "failed to create session");
893
894 /* Add a session list even though it will be ignored. */
895 if ((SSI(ssl)->tlsext_ecpointformatlist = malloc(sizeof(uint8_t)))
896 == NULL) {
897 FAIL("server could not malloc\n");
898 goto err;
899 }
900 SSI(ssl)->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
901 SSI(ssl)->tlsext_ecpointformatlist_length = 1;
902
903 /* Replace the default list with a custom one. */
904 if ((ssl->internal->tlsext_ecpointformatlist = malloc(sizeof(uint8_t) * 3)) == NULL) {
905 FAIL("server could not malloc\n");
906 goto err;
907 }
908 ssl->internal->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
909 ssl->internal->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_uncompressed;
910 ssl->internal->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
911 ssl->internal->tlsext_ecpointformatlist_length = 3;
912
913 if (!tlsext_ecpf_serverhello_needs(ssl)) {
914 FAIL("serverhello should need ECPointFormats\n");
915 goto err;
916 }
917
918 if (!tlsext_ecpf_serverhello_build(ssl, &cbb)) {
919 FAIL("serverhello failed to build ECPointFormats\n");
920 goto err;
921 }
922
923 if (!CBB_finish(&cbb, &data, &dlen))
924 errx(1, "failed to finish CBB");
925
926 if (dlen != sizeof(tlsext_ecpf_hello_prefer_order)) {
927 FAIL("got serverhello ECPointFormats with length %zu, "
928 "want length %zu\n", dlen,
929 sizeof(tlsext_ecpf_hello_prefer_order));
930 compare_data(data, dlen, tlsext_ecpf_hello_prefer_order,
931 sizeof(tlsext_ecpf_hello_prefer_order));
932 goto err;
933 }
934
935 if (memcmp(data, tlsext_ecpf_hello_prefer_order, dlen) != 0) {
936 FAIL("serverhello ECPointFormats differs:\n");
937 compare_data(data, dlen, tlsext_ecpf_hello_prefer_order,
938 sizeof(tlsext_ecpf_hello_prefer_order));
939 goto err;
940 }
941
942 /*
943 * Should be able to parse the custom list into a session list.
944 */
945 CBB_cleanup(&cbb);
946 CBB_init(&cbb, 0);
947 free(data);
948 data = NULL;
949
950 SSL_SESSION_free(ssl->session);
951 if ((ssl->session = SSL_SESSION_new()) == NULL)
952 errx(1, "failed to create session");
953
954 /* Reset back to the default (uncompressed) */
955 free(ssl->internal->tlsext_ecpointformatlist);
956 ssl->internal->tlsext_ecpointformatlist = NULL;
957 ssl->internal->tlsext_ecpointformatlist_length = 0;
958
959 CBS_init(&cbs, tlsext_ecpf_hello_prefer_order,
960 sizeof(tlsext_ecpf_hello_prefer_order));
961 if (!tlsext_ecpf_serverhello_parse(ssl, &cbs, &alert)) {
962 FAIL("failed to parse serverhello ECPointFormats\n");
963 goto err;
964 }
965
966 if (SSI(ssl)->tlsext_ecpointformatlist_length !=
967 sizeof(tlsext_ecpf_hello_prefer_order_val)) {
968 FAIL("no tlsext_ecpointformats from serverhello "
969 "ECPointFormats\n");
970 goto err;
971 }
972
973 if (memcmp(SSI(ssl)->tlsext_ecpointformatlist,
974 tlsext_ecpf_hello_prefer_order_val,
975 sizeof(tlsext_ecpf_hello_prefer_order_val)) != 0) {
976 FAIL("serverhello had an incorrect ECPointFormats entry\n");
977 goto err;
978 }
979
980 failure = 0;
981
982 err:
983 CBB_cleanup(&cbb);
984 SSL_CTX_free(ssl_ctx);
985 SSL_free(ssl);
986 free(data);
987
988 return (failure);
989}
990
525int 991int
526main(int argc, char **argv) 992main(int argc, char **argv)
527{ 993{
@@ -535,5 +1001,8 @@ main(int argc, char **argv)
535 failed |= test_tlsext_sni_clienthello(); 1001 failed |= test_tlsext_sni_clienthello();
536 failed |= test_tlsext_sni_serverhello(); 1002 failed |= test_tlsext_sni_serverhello();
537 1003
1004 failed |= test_tlsext_ecpf_clienthello();
1005 failed |= test_tlsext_ecpf_serverhello();
1006
538 return (failed); 1007 return (failed);
539} 1008}