diff options
author | jsing <> | 2018-01-27 15:30:05 +0000 |
---|---|---|
committer | jsing <> | 2018-01-27 15:30:05 +0000 |
commit | 7e9d176210d3d878a8e83ab3e422f4bf370711e6 (patch) | |
tree | 3d53d5ec7c827462ec31ee3156e980e4c951418a /src | |
parent | cccafe604becdfd2326c3f4d1c5664d824934cb4 (diff) | |
download | openbsd-7e9d176210d3d878a8e83ab3e422f4bf370711e6.tar.gz openbsd-7e9d176210d3d878a8e83ab3e422f4bf370711e6.tar.bz2 openbsd-7e9d176210d3d878a8e83ab3e422f4bf370711e6.zip |
Complete the TLS extension handling rewrite for the server-side.
This removes ssl_parse_clienthello_tlsext() and allows the CBS to be
passed all the way through from ssl3_get_client_hello(). The renegotation
check gets pulled up into ssl3_get_client_hello() which is where other
such checks exist.
The TLS extension parsing now also ensures that we do not get duplicates
of any known extensions (the old pre-rewrite code only did this for some
extensions).
ok inoguchi@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 7 | ||||
-rw-r--r-- | src/lib/libssl/ssl_srvr.c | 19 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.c | 82 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.h | 5 | ||||
-rw-r--r-- | src/lib/libssl/t1_lib.c | 71 |
5 files changed, 86 insertions, 98 deletions
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index f6e922e99c..d2a99afaa4 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.201 2017/10/12 16:06:32 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.202 2018/01/27 15:30:05 jsing 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 | * |
@@ -164,6 +164,9 @@ | |||
164 | 164 | ||
165 | __BEGIN_HIDDEN_DECLS | 165 | __BEGIN_HIDDEN_DECLS |
166 | 166 | ||
167 | #define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \ | ||
168 | __attribute__((__unused__)) | ||
169 | |||
167 | #define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ | 170 | #define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ |
168 | *((c)++)=(unsigned char)(((l)>>16)&0xff), \ | 171 | *((c)++)=(unsigned char)(((l)>>16)&0xff), \ |
169 | *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ | 172 | *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ |
@@ -1275,8 +1278,6 @@ uint16_t tls1_ec_nid2curve_id(const int nid); | |||
1275 | int tls1_check_curve(SSL *s, const uint16_t curve_id); | 1278 | int tls1_check_curve(SSL *s, const uint16_t curve_id); |
1276 | int tls1_get_shared_curve(SSL *s); | 1279 | int tls1_get_shared_curve(SSL *s); |
1277 | 1280 | ||
1278 | int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, | ||
1279 | unsigned char *d, int n, int *al); | ||
1280 | int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, | 1281 | int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, |
1281 | size_t n, int *al); | 1282 | size_t n, int *al); |
1282 | int ssl_check_clienthello_tlsext_early(SSL *s); | 1283 | int ssl_check_clienthello_tlsext_early(SSL *s); |
diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c index 5d741cdc81..6450623d4a 100644 --- a/src/lib/libssl/ssl_srvr.c +++ b/src/lib/libssl/ssl_srvr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_srvr.c,v 1.26 2017/10/12 15:52:50 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_srvr.c,v 1.27 2018/01/27 15:30:05 jsing 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 | * |
@@ -813,7 +813,6 @@ ssl3_get_client_hello(SSL *s) | |||
813 | int i, j, ok, al, ret = -1, cookie_valid = 0; | 813 | int i, j, ok, al, ret = -1, cookie_valid = 0; |
814 | long n; | 814 | long n; |
815 | unsigned long id; | 815 | unsigned long id; |
816 | unsigned char *p, *d; | ||
817 | SSL_CIPHER *c; | 816 | SSL_CIPHER *c; |
818 | STACK_OF(SSL_CIPHER) *ciphers = NULL; | 817 | STACK_OF(SSL_CIPHER) *ciphers = NULL; |
819 | unsigned long alg_k; | 818 | unsigned long alg_k; |
@@ -843,8 +842,7 @@ ssl3_get_client_hello(SSL *s) | |||
843 | if (n < 0) | 842 | if (n < 0) |
844 | goto err; | 843 | goto err; |
845 | 844 | ||
846 | d = p = (unsigned char *)s->internal->init_msg; | 845 | end = (unsigned char *)s->internal->init_msg + n; |
847 | end = d + n; | ||
848 | 846 | ||
849 | CBS_init(&cbs, s->internal->init_msg, n); | 847 | CBS_init(&cbs, s->internal->init_msg, n); |
850 | 848 | ||
@@ -1038,14 +1036,17 @@ ssl3_get_client_hello(SSL *s) | |||
1038 | goto f_err; | 1036 | goto f_err; |
1039 | } | 1037 | } |
1040 | 1038 | ||
1041 | p = (unsigned char *)CBS_data(&cbs); | 1039 | if (!tlsext_clienthello_parse(s, &cbs, &al)) { |
1042 | |||
1043 | /* TLS extensions*/ | ||
1044 | if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) { | ||
1045 | /* 'al' set by ssl_parse_clienthello_tlsext */ | ||
1046 | SSLerror(s, SSL_R_PARSE_TLSEXT); | 1040 | SSLerror(s, SSL_R_PARSE_TLSEXT); |
1047 | goto f_err; | 1041 | goto f_err; |
1048 | } | 1042 | } |
1043 | |||
1044 | if (!S3I(s)->renegotiate_seen && s->internal->renegotiate) { | ||
1045 | al = SSL_AD_HANDSHAKE_FAILURE; | ||
1046 | SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); | ||
1047 | goto f_err; | ||
1048 | } | ||
1049 | |||
1049 | if (ssl_check_clienthello_tlsext_early(s) <= 0) { | 1050 | if (ssl_check_clienthello_tlsext_early(s) <= 0) { |
1050 | SSLerror(s, SSL_R_CLIENTHELLO_TLSEXT); | 1051 | SSLerror(s, SSL_R_CLIENTHELLO_TLSEXT); |
1051 | goto err; | 1052 | goto err; |
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c index d0764af3c0..0e3ef7da15 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.19 2018/01/27 15:17:13 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_tlsext.c,v 1.20 2018/01/27 15:30:05 jsing 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> |
@@ -1292,6 +1292,35 @@ static struct tls_extension tls_extensions[] = { | |||
1292 | 1292 | ||
1293 | #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) | 1293 | #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) |
1294 | 1294 | ||
1295 | /* Ensure that extensions fit in a uint32_t bitmask. */ | ||
1296 | CTASSERT(N_TLS_EXTENSIONS <= (sizeof(uint32_t) * 8)); | ||
1297 | |||
1298 | static struct tls_extension * | ||
1299 | tls_extension_find(uint16_t type, size_t *tls_extensions_idx) | ||
1300 | { | ||
1301 | size_t i; | ||
1302 | |||
1303 | for (i = 0; i < N_TLS_EXTENSIONS; i++) { | ||
1304 | if (tls_extensions[i].type == type) { | ||
1305 | *tls_extensions_idx = i; | ||
1306 | return &tls_extensions[i]; | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | return NULL; | ||
1311 | } | ||
1312 | |||
1313 | static void | ||
1314 | tlsext_clienthello_reset_state(SSL *s) | ||
1315 | { | ||
1316 | s->internal->servername_done = 0; | ||
1317 | s->tlsext_status_type = -1; | ||
1318 | S3I(s)->renegotiate_seen = 0; | ||
1319 | free(S3I(s)->alpn_selected); | ||
1320 | S3I(s)->alpn_selected = NULL; | ||
1321 | s->internal->srtp_profile = NULL; | ||
1322 | } | ||
1323 | |||
1295 | int | 1324 | int |
1296 | tlsext_clienthello_build(SSL *s, CBB *cbb) | 1325 | tlsext_clienthello_build(SSL *s, CBB *cbb) |
1297 | { | 1326 | { |
@@ -1329,28 +1358,55 @@ tlsext_clienthello_build(SSL *s, CBB *cbb) | |||
1329 | } | 1358 | } |
1330 | 1359 | ||
1331 | int | 1360 | int |
1332 | tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t type, int *alert) | 1361 | tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert) |
1333 | { | 1362 | { |
1363 | CBS extensions, extension_data; | ||
1334 | struct tls_extension *tlsext; | 1364 | struct tls_extension *tlsext; |
1335 | size_t i; | 1365 | uint32_t extensions_seen = 0; |
1366 | uint16_t type; | ||
1367 | size_t idx; | ||
1336 | 1368 | ||
1337 | for (i = 0; i < N_TLS_EXTENSIONS; i++) { | 1369 | /* XXX - this possibly should be done by the caller... */ |
1338 | tlsext = &tls_extensions[i]; | 1370 | tlsext_clienthello_reset_state(s); |
1339 | 1371 | ||
1340 | if (tlsext->type != type) | 1372 | /* An empty extensions block is valid. */ |
1373 | if (CBS_len(cbs) == 0) | ||
1374 | return 1; | ||
1375 | |||
1376 | *alert = SSL_AD_DECODE_ERROR; | ||
1377 | |||
1378 | if (!CBS_get_u16_length_prefixed(cbs, &extensions)) | ||
1379 | return 0; | ||
1380 | |||
1381 | while (CBS_len(&extensions) > 0) { | ||
1382 | if (!CBS_get_u16(&extensions, &type)) | ||
1383 | return 0; | ||
1384 | if (!CBS_get_u16_length_prefixed(&extensions, &extension_data)) | ||
1385 | return 0; | ||
1386 | |||
1387 | if (s->internal->tlsext_debug_cb != NULL) | ||
1388 | s->internal->tlsext_debug_cb(s, 0, type, | ||
1389 | (unsigned char *)CBS_data(&extension_data), | ||
1390 | CBS_len(&extension_data), | ||
1391 | s->internal->tlsext_debug_arg); | ||
1392 | |||
1393 | /* Unknown extensions are ignored. */ | ||
1394 | if ((tlsext = tls_extension_find(type, &idx)) == NULL) | ||
1341 | continue; | 1395 | continue; |
1342 | if (!tlsext->clienthello_parse(s, cbs, alert)) | 1396 | |
1397 | /* Check for duplicate extensions. */ | ||
1398 | if ((extensions_seen & (1 << idx)) != 0) | ||
1343 | return 0; | 1399 | return 0; |
1344 | if (CBS_len(cbs) != 0) { | 1400 | extensions_seen |= (1 << idx); |
1345 | *alert = SSL_AD_DECODE_ERROR; | 1401 | |
1402 | if (!tlsext->clienthello_parse(s, &extension_data, alert)) | ||
1346 | return 0; | 1403 | return 0; |
1347 | } | ||
1348 | 1404 | ||
1349 | return 1; | 1405 | if (CBS_len(&extension_data) != 0) |
1406 | return 0; | ||
1350 | } | 1407 | } |
1351 | 1408 | ||
1352 | /* Not found. */ | 1409 | return 1; |
1353 | return 2; | ||
1354 | } | 1410 | } |
1355 | 1411 | ||
1356 | int | 1412 | int |
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h index 7c6250a7f7..1af2e6cb3b 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.10 2017/08/27 02:58:04 doug Exp $ */ | 1 | /* $OpenBSD: ssl_tlsext.h,v 1.11 2018/01/27 15:30:05 jsing 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> |
@@ -82,8 +82,7 @@ int tlsext_srtp_serverhello_parse(SSL *s, CBS *cbs, int *alert); | |||
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | int tlsext_clienthello_build(SSL *s, CBB *cbb); | 84 | int tlsext_clienthello_build(SSL *s, CBB *cbb); |
85 | int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, | 85 | int tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert); |
86 | int *alert); | ||
87 | 86 | ||
88 | int tlsext_serverhello_build(SSL *s, CBB *cbb); | 87 | int tlsext_serverhello_build(SSL *s, CBB *cbb); |
89 | int tlsext_serverhello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, | 88 | int tlsext_serverhello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, |
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c index 1cef08d094..fbd79431db 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.139 2017/10/11 17:35:00 jsing Exp $ */ | 1 | /* $OpenBSD: t1_lib.c,v 1.140 2018/01/27 15:30:05 jsing 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 | * |
@@ -662,75 +662,6 @@ tls12_get_req_sig_algs(SSL *s, unsigned char **sigalgs, size_t *sigalgs_len) | |||
662 | } | 662 | } |
663 | 663 | ||
664 | int | 664 | int |
665 | ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, | ||
666 | int n, int *al) | ||
667 | { | ||
668 | unsigned short type; | ||
669 | unsigned short size; | ||
670 | unsigned short len; | ||
671 | unsigned char *data = *p; | ||
672 | unsigned char *end = d + n; | ||
673 | CBS cbs; | ||
674 | |||
675 | s->internal->servername_done = 0; | ||
676 | s->tlsext_status_type = -1; | ||
677 | S3I(s)->renegotiate_seen = 0; | ||
678 | free(S3I(s)->alpn_selected); | ||
679 | S3I(s)->alpn_selected = NULL; | ||
680 | s->internal->srtp_profile = NULL; | ||
681 | |||
682 | if (data == end) | ||
683 | goto ri_check; | ||
684 | |||
685 | if (end - data < 2) | ||
686 | goto err; | ||
687 | n2s(data, len); | ||
688 | |||
689 | if (end - data != len) | ||
690 | goto err; | ||
691 | |||
692 | while (end - data >= 4) { | ||
693 | n2s(data, type); | ||
694 | n2s(data, size); | ||
695 | |||
696 | if (end - data < size) | ||
697 | goto err; | ||
698 | |||
699 | if (s->internal->tlsext_debug_cb) | ||
700 | s->internal->tlsext_debug_cb(s, 0, type, data, size, | ||
701 | s->internal->tlsext_debug_arg); | ||
702 | |||
703 | CBS_init(&cbs, data, size); | ||
704 | if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) | ||
705 | return 0; | ||
706 | |||
707 | data += size; | ||
708 | } | ||
709 | |||
710 | /* Spurious data on the end */ | ||
711 | if (data != end) | ||
712 | goto err; | ||
713 | |||
714 | *p = data; | ||
715 | |||
716 | ri_check: | ||
717 | |||
718 | /* Need RI if renegotiating */ | ||
719 | |||
720 | if (!S3I(s)->renegotiate_seen && s->internal->renegotiate) { | ||
721 | *al = SSL_AD_HANDSHAKE_FAILURE; | ||
722 | SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); | ||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | return 1; | ||
727 | |||
728 | err: | ||
729 | *al = SSL_AD_DECODE_ERROR; | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | int | ||
734 | ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al) | 665 | ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al) |
735 | { | 666 | { |
736 | unsigned short type; | 667 | unsigned short type; |