diff options
author | doug <> | 2017-08-11 05:06:34 +0000 |
---|---|---|
committer | doug <> | 2017-08-11 05:06:34 +0000 |
commit | 2c7289aaf0a5e656e3db4ad3e101b1dd3e2dc610 (patch) | |
tree | cf9f734a8e9d38d5af29ff18c56720f241220b61 /src/lib | |
parent | ae58363a3ade3f9016687060c0c4efe3702141f8 (diff) | |
download | openbsd-2c7289aaf0a5e656e3db4ad3e101b1dd3e2dc610.tar.gz openbsd-2c7289aaf0a5e656e3db4ad3e101b1dd3e2dc610.tar.bz2 openbsd-2c7289aaf0a5e656e3db4ad3e101b1dd3e2dc610.zip |
Rewrite the ECPointFormats TLS extension handling using CBB/CBS and the
new extension framework.
input + ok jsing@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 5 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.c | 108 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.h | 9 | ||||
-rw-r--r-- | src/lib/libssl/t1_lib.c | 150 |
4 files changed, 125 insertions, 147 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__) |
1381 | void SSL_error_internal(const SSL *s, int r, char *f, int l); | 1381 | 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, | ||
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 | */ | ||
26 | static int | ||
27 | tlsext_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 | |||
50 | static int | ||
51 | tlsext_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 | |||
81 | int | ||
82 | tlsext_ecpf_clienthello_needs(SSL *s) | ||
83 | { | ||
84 | return ssl_has_ecc_ciphers(s); | ||
85 | } | ||
86 | |||
87 | int | ||
88 | tlsext_ecpf_clienthello_build(SSL *s, CBB *cbb) | ||
89 | { | ||
90 | return tlsext_ecpf_build(s, cbb); | ||
91 | } | ||
92 | |||
93 | int | ||
94 | tlsext_ecpf_clienthello_parse(SSL *s, CBS *cbs, int *alert) | ||
95 | { | ||
96 | return tlsext_ecpf_parse(s, cbs, alert); | ||
97 | } | ||
98 | |||
99 | int | ||
100 | tlsext_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 | |||
108 | int | ||
109 | tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb) | ||
110 | { | ||
111 | return tlsext_ecpf_build(s, cbb); | ||
112 | } | ||
113 | |||
114 | int | ||
115 | tlsext_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 | */ |
26 | int | 123 | int |
@@ -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); | |||
29 | int tlsext_sni_serverhello_build(SSL *s, CBB *cbb); | 29 | int tlsext_sni_serverhello_build(SSL *s, CBB *cbb); |
30 | int tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert); | 30 | int tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert); |
31 | 31 | ||
32 | int tlsext_ecpf_clienthello_needs(SSL *s); | ||
33 | int tlsext_ecpf_clienthello_build(SSL *s, CBB *cbb); | ||
34 | int tlsext_ecpf_clienthello_parse(SSL *s, CBS *cbs, int *alert); | ||
35 | int tlsext_ecpf_serverhello_needs(SSL *s); | ||
36 | int tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb); | ||
37 | int tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert); | ||
38 | |||
32 | int tlsext_clienthello_build(SSL *s, CBB *cbb); | 39 | int tlsext_clienthello_build(SSL *s, CBB *cbb); |
33 | int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, | 40 | int 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 | */ |
345 | static void | 345 | void |
346 | tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, | 346 | tls1_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: | |||
931 | unsigned char * | 908 | unsigned char * |
932 | ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) | 909 | ssl_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) |