summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2018-02-08 11:30:30 +0000
committerjsing <>2018-02-08 11:30:30 +0000
commit229ae49ead0f79b4527f210ea8576c4bd87866e0 (patch)
tree9e5cad14fc7d443c7ddd3a3abf5efddfc0546802
parentfc0438989e1c41cdad9328de2e6d0856c7e42063 (diff)
downloadopenbsd-229ae49ead0f79b4527f210ea8576c4bd87866e0.tar.gz
openbsd-229ae49ead0f79b4527f210ea8576c4bd87866e0.tar.bz2
openbsd-229ae49ead0f79b4527f210ea8576c4bd87866e0.zip
Complete the TLS extension rewrite on the client-side.
The RI logic gets pulled up into ssl3_get_server_hello() and ssl_parse_serverhello_tlsext() gets replaced by tlsext_client_parse(), which allows a CBS to be passed all the way down. This also deduplicates the tlsext_client_build() and tlsext_server_build() code. ok beck@
-rw-r--r--src/lib/libssl/ssl_clnt.c28
-rw-r--r--src/lib/libssl/ssl_tlsext.c141
-rw-r--r--src/lib/libssl/ssl_tlsext.h5
-rw-r--r--src/lib/libssl/t1_lib.c75
4 files changed, 93 insertions, 156 deletions
diff --git a/src/lib/libssl/ssl_clnt.c b/src/lib/libssl/ssl_clnt.c
index 56ea99d82e..10dbe83cd5 100644
--- a/src/lib/libssl/ssl_clnt.c
+++ b/src/lib/libssl/ssl_clnt.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_clnt.c,v 1.22 2017/10/12 16:06:32 jsing Exp $ */ 1/* $OpenBSD: ssl_clnt.c,v 1.23 2018/02/08 11:30:30 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_server_hello(SSL *s)
813 STACK_OF(SSL_CIPHER) *sk; 813 STACK_OF(SSL_CIPHER) *sk;
814 const SSL_CIPHER *cipher; 814 const SSL_CIPHER *cipher;
815 const SSL_METHOD *method; 815 const SSL_METHOD *method;
816 unsigned char *p;
817 unsigned long alg_k; 816 unsigned long alg_k;
818 size_t outlen; 817 size_t outlen;
819 int i, al, ok; 818 int i, al, ok;
@@ -1011,22 +1010,31 @@ ssl3_get_server_hello(SSL *s)
1011 goto f_err; 1010 goto f_err;
1012 } 1011 }
1013 1012
1014 /* TLS extensions. */ 1013 if (!tlsext_serverhello_parse(s, &cbs, &al)) {
1015 p = (unsigned char *)CBS_data(&cbs);
1016 if (!ssl_parse_serverhello_tlsext(s, &p, CBS_len(&cbs), &al)) {
1017 /* 'al' set by ssl_parse_serverhello_tlsext */
1018 SSLerror(s, SSL_R_PARSE_TLSEXT); 1014 SSLerror(s, SSL_R_PARSE_TLSEXT);
1019 goto f_err; 1015 goto f_err;
1020 } 1016 }
1017
1018 /*
1019 * Determine if we need to see RI. Strictly speaking if we want to
1020 * avoid an attack we should *always* see RI even on initial server
1021 * hello because the client doesn't see any renegotiation during an
1022 * attack. However this would mean we could not connect to any server
1023 * which doesn't support RI so for the immediate future tolerate RI
1024 * absence on initial connect only.
1025 */
1026 if (!S3I(s)->renegotiate_seen &&
1027 !(s->internal->options & SSL_OP_LEGACY_SERVER_CONNECT)) {
1028 al = SSL_AD_HANDSHAKE_FAILURE;
1029 SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
1030 goto f_err;
1031 }
1032
1021 if (ssl_check_serverhello_tlsext(s) <= 0) { 1033 if (ssl_check_serverhello_tlsext(s) <= 0) {
1022 SSLerror(s, SSL_R_SERVERHELLO_TLSEXT); 1034 SSLerror(s, SSL_R_SERVERHELLO_TLSEXT);
1023 goto err; 1035 goto err;
1024 } 1036 }
1025 1037
1026 /* See if any data remains... */
1027 if (p - CBS_data(&cbs) != CBS_len(&cbs))
1028 goto truncated;
1029
1030 return (1); 1038 return (1);
1031 1039
1032truncated: 1040truncated:
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index 0e3ef7da15..3735b719db 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.20 2018/01/27 15:30:05 jsing Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.21 2018/02/08 11:30:30 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>
@@ -1310,19 +1310,34 @@ tls_extension_find(uint16_t type, size_t *tls_extensions_idx)
1310 return NULL; 1310 return NULL;
1311} 1311}
1312 1312
1313static void 1313static int
1314tlsext_clienthello_reset_state(SSL *s) 1314tls_extension_needs(struct tls_extension *tlsext, int is_serverhello, SSL *s)
1315{ 1315{
1316 s->internal->servername_done = 0; 1316 if (is_serverhello)
1317 s->tlsext_status_type = -1; 1317 return tlsext->serverhello_needs(s);
1318 S3I(s)->renegotiate_seen = 0; 1318 return tlsext->clienthello_needs(s);
1319 free(S3I(s)->alpn_selected);
1320 S3I(s)->alpn_selected = NULL;
1321 s->internal->srtp_profile = NULL;
1322} 1319}
1323 1320
1324int 1321static int
1325tlsext_clienthello_build(SSL *s, CBB *cbb) 1322tls_extension_build(struct tls_extension *tlsext, int is_serverhello, SSL *s,
1323 CBB *cbb)
1324{
1325 if (is_serverhello)
1326 return tlsext->serverhello_build(s, cbb);
1327 return tlsext->clienthello_build(s, cbb);
1328}
1329
1330static int
1331tls_extension_parse(struct tls_extension *tlsext, int is_serverhello, SSL *s,
1332 CBS *cbs, int *alert)
1333{
1334 if (is_serverhello)
1335 return tlsext->serverhello_parse(s, cbs, alert);
1336 return tlsext->clienthello_parse(s, cbs, alert);
1337}
1338
1339static int
1340tlsext_build(SSL *s, CBB *cbb, int is_serverhello)
1326{ 1341{
1327 CBB extensions, extension_data; 1342 CBB extensions, extension_data;
1328 struct tls_extension *tlsext; 1343 struct tls_extension *tlsext;
@@ -1335,14 +1350,16 @@ tlsext_clienthello_build(SSL *s, CBB *cbb)
1335 for (i = 0; i < N_TLS_EXTENSIONS; i++) { 1350 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
1336 tlsext = &tls_extensions[i]; 1351 tlsext = &tls_extensions[i];
1337 1352
1338 if (!tlsext->clienthello_needs(s)) 1353 if (!tls_extension_needs(tlsext, is_serverhello, s))
1339 continue; 1354 continue;
1340 1355
1341 if (!CBB_add_u16(&extensions, tlsext->type)) 1356 if (!CBB_add_u16(&extensions, tlsext->type))
1342 return 0; 1357 return 0;
1343 if (!CBB_add_u16_length_prefixed(&extensions, &extension_data)) 1358 if (!CBB_add_u16_length_prefixed(&extensions, &extension_data))
1344 return 0; 1359 return 0;
1345 if (!tls_extensions[i].clienthello_build(s, &extension_data)) 1360
1361 if (!tls_extension_build(tlsext, is_serverhello, s,
1362 &extension_data))
1346 return 0; 1363 return 0;
1347 1364
1348 extensions_present = 1; 1365 extensions_present = 1;
@@ -1357,8 +1374,8 @@ tlsext_clienthello_build(SSL *s, CBB *cbb)
1357 return 1; 1374 return 1;
1358} 1375}
1359 1376
1360int 1377static int
1361tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert) 1378tlsext_parse(SSL *s, CBS *cbs, int *alert, int is_serverhello)
1362{ 1379{
1363 CBS extensions, extension_data; 1380 CBS extensions, extension_data;
1364 struct tls_extension *tlsext; 1381 struct tls_extension *tlsext;
@@ -1366,9 +1383,6 @@ tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert)
1366 uint16_t type; 1383 uint16_t type;
1367 size_t idx; 1384 size_t idx;
1368 1385
1369 /* XXX - this possibly should be done by the caller... */
1370 tlsext_clienthello_reset_state(s);
1371
1372 /* An empty extensions block is valid. */ 1386 /* An empty extensions block is valid. */
1373 if (CBS_len(cbs) == 0) 1387 if (CBS_len(cbs) == 0)
1374 return 1; 1388 return 1;
@@ -1385,7 +1399,7 @@ tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert)
1385 return 0; 1399 return 0;
1386 1400
1387 if (s->internal->tlsext_debug_cb != NULL) 1401 if (s->internal->tlsext_debug_cb != NULL)
1388 s->internal->tlsext_debug_cb(s, 0, type, 1402 s->internal->tlsext_debug_cb(s, is_serverhello, type,
1389 (unsigned char *)CBS_data(&extension_data), 1403 (unsigned char *)CBS_data(&extension_data),
1390 CBS_len(&extension_data), 1404 CBS_len(&extension_data),
1391 s->internal->tlsext_debug_arg); 1405 s->internal->tlsext_debug_arg);
@@ -1394,12 +1408,13 @@ tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert)
1394 if ((tlsext = tls_extension_find(type, &idx)) == NULL) 1408 if ((tlsext = tls_extension_find(type, &idx)) == NULL)
1395 continue; 1409 continue;
1396 1410
1397 /* Check for duplicate extensions. */ 1411 /* Check for duplicate known extensions. */
1398 if ((extensions_seen & (1 << idx)) != 0) 1412 if ((extensions_seen & (1 << idx)) != 0)
1399 return 0; 1413 return 0;
1400 extensions_seen |= (1 << idx); 1414 extensions_seen |= (1 << idx);
1401 1415
1402 if (!tlsext->clienthello_parse(s, &extension_data, alert)) 1416 if (!tls_extension_parse(tlsext, is_serverhello, s,
1417 &extension_data, alert))
1403 return 0; 1418 return 0;
1404 1419
1405 if (CBS_len(&extension_data) != 0) 1420 if (CBS_len(&extension_data) != 0)
@@ -1409,63 +1424,51 @@ tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert)
1409 return 1; 1424 return 1;
1410} 1425}
1411 1426
1412int 1427static void
1413tlsext_serverhello_build(SSL *s, CBB *cbb) 1428tlsext_clienthello_reset_state(SSL *s)
1414{ 1429{
1415 CBB extensions, extension_data; 1430 s->internal->servername_done = 0;
1416 struct tls_extension *tlsext; 1431 s->tlsext_status_type = -1;
1417 int extensions_present = 0; 1432 S3I(s)->renegotiate_seen = 0;
1418 size_t i; 1433 free(S3I(s)->alpn_selected);
1419 1434 S3I(s)->alpn_selected = NULL;
1420 if (!CBB_add_u16_length_prefixed(cbb, &extensions)) 1435 s->internal->srtp_profile = NULL;
1421 return 0; 1436}
1422
1423 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
1424 tlsext = &tls_extensions[i];
1425
1426 if (!tlsext->serverhello_needs(s))
1427 continue;
1428
1429 if (!CBB_add_u16(&extensions, tlsext->type))
1430 return 0;
1431 if (!CBB_add_u16_length_prefixed(&extensions, &extension_data))
1432 return 0;
1433 if (!tlsext->serverhello_build(s, &extension_data))
1434 return 0;
1435 1437
1436 extensions_present = 1; 1438int
1437 } 1439tlsext_clienthello_build(SSL *s, CBB *cbb)
1440{
1441 return tlsext_build(s, cbb, 0);
1442}
1438 1443
1439 if (!extensions_present) 1444int
1440 CBB_discard_child(cbb); 1445tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert)
1446{
1447 /* XXX - this possibly should be done by the caller... */
1448 tlsext_clienthello_reset_state(s);
1441 1449
1442 if (!CBB_flush(cbb)) 1450 return tlsext_parse(s, cbs, alert, 0);
1443 return 0; 1451}
1444 1452
1445 return 1; 1453static void
1454tlsext_serverhello_reset_state(SSL *s)
1455{
1456 S3I(s)->renegotiate_seen = 0;
1457 free(S3I(s)->alpn_selected);
1458 S3I(s)->alpn_selected = NULL;
1446} 1459}
1447 1460
1448int 1461int
1449tlsext_serverhello_parse_one(SSL *s, CBS *cbs, uint16_t type, int *alert) 1462tlsext_serverhello_build(SSL *s, CBB *cbb)
1450{ 1463{
1451 struct tls_extension *tlsext; 1464 return tlsext_build(s, cbb, 1);
1452 size_t i; 1465}
1453
1454 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
1455 tlsext = &tls_extensions[i];
1456
1457 if (tlsext->type != type)
1458 continue;
1459 if (!tlsext->serverhello_parse(s, cbs, alert))
1460 return 0;
1461 if (CBS_len(cbs) != 0) {
1462 *alert = SSL_AD_DECODE_ERROR;
1463 return 0;
1464 }
1465 1466
1466 return 1; 1467int
1467 } 1468tlsext_serverhello_parse(SSL *s, CBS *cbs, int *alert)
1469{
1470 /* XXX - this possibly should be done by the caller... */
1471 tlsext_serverhello_reset_state(s);
1468 1472
1469 /* Not found. */ 1473 return tlsext_parse(s, cbs, alert, 1);
1470 return 2;
1471} 1474}
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h
index 1af2e6cb3b..4248932fb2 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.11 2018/01/27 15:30:05 jsing Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.12 2018/02/08 11:30:30 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>
@@ -85,5 +85,4 @@ int tlsext_clienthello_build(SSL *s, CBB *cbb);
85int tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert); 85int tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert);
86 86
87int tlsext_serverhello_build(SSL *s, CBB *cbb); 87int tlsext_serverhello_build(SSL *s, CBB *cbb);
88int tlsext_serverhello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, 88int tlsext_serverhello_parse(SSL *s, CBS *cbs, int *alert);
89 int *alert);
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c
index fbd79431db..d92fd70f5b 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.140 2018/01/27 15:30:05 jsing Exp $ */ 1/* $OpenBSD: t1_lib.c,v 1.141 2018/02/08 11:30:30 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,79 +662,6 @@ tls12_get_req_sig_algs(SSL *s, unsigned char **sigalgs, size_t *sigalgs_len)
662} 662}
663 663
664int 664int
665ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al)
666{
667 unsigned short type;
668 unsigned short size;
669 unsigned short len;
670 unsigned char *data = *p;
671 unsigned char *end = *p + n;
672 CBS cbs;
673
674 S3I(s)->renegotiate_seen = 0;
675 free(S3I(s)->alpn_selected);
676 S3I(s)->alpn_selected = NULL;
677
678 if (data == end)
679 goto ri_check;
680
681 if (end - data < 2)
682 goto err;
683 n2s(data, len);
684
685 if (end - data != len)
686 goto err;
687
688 while (end - data >= 4) {
689 n2s(data, type);
690 n2s(data, size);
691
692 if (end - data < size)
693 goto err;
694
695 if (s->internal->tlsext_debug_cb)
696 s->internal->tlsext_debug_cb(s, 1, type, data, size,
697 s->internal->tlsext_debug_arg);
698
699 CBS_init(&cbs, data, size);
700 if (!tlsext_serverhello_parse_one(s, &cbs, type, al))
701 return 0;
702
703 data += size;
704
705 }
706
707 if (data != end) {
708 *al = SSL_AD_DECODE_ERROR;
709 return 0;
710 }
711
712 *p = data;
713
714ri_check:
715
716 /* Determine if we need to see RI. Strictly speaking if we want to
717 * avoid an attack we should *always* see RI even on initial server
718 * hello because the client doesn't see any renegotiation during an
719 * attack. However this would mean we could not connect to any server
720 * which doesn't support RI so for the immediate future tolerate RI
721 * absence on initial connect only.
722 */
723 if (!S3I(s)->renegotiate_seen &&
724 !(s->internal->options & SSL_OP_LEGACY_SERVER_CONNECT)) {
725 *al = SSL_AD_HANDSHAKE_FAILURE;
726 SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
727 return 0;
728 }
729
730 return 1;
731
732err:
733 *al = SSL_AD_DECODE_ERROR;
734 return 0;
735}
736
737int
738ssl_check_clienthello_tlsext_early(SSL *s) 665ssl_check_clienthello_tlsext_early(SSL *s)
739{ 666{
740 int ret = SSL_TLSEXT_ERR_NOACK; 667 int ret = SSL_TLSEXT_ERR_NOACK;