summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordoug <>2017-08-12 21:17:03 +0000
committerdoug <>2017-08-12 21:17:03 +0000
commit7b1e2bed428777bb9ee601d6775aa91efdc80340 (patch)
treea6945bbfcf083598e38feabf2ece8ed3cbfaed2b /src
parent8bf5f970305d128e9bff3306420305d1a510a83f (diff)
downloadopenbsd-7b1e2bed428777bb9ee601d6775aa91efdc80340.tar.gz
openbsd-7b1e2bed428777bb9ee601d6775aa91efdc80340.tar.bz2
openbsd-7b1e2bed428777bb9ee601d6775aa91efdc80340.zip
Rewrite session ticket TLS extension handling using CBB/CBS and the new
extension framework. ok jsing@ beck@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libssl/ssl_tlsext.c136
-rw-r--r--src/lib/libssl/ssl_tlsext.h8
-rw-r--r--src/lib/libssl/t1_lib.c66
-rw-r--r--src/regress/lib/libssl/tlsext/tlsexttest.c303
4 files changed, 447 insertions, 66 deletions
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index c050224c70..1813d46f41 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.6 2017/08/11 20:14:13 doug Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.7 2017/08/12 21:17:03 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>
@@ -492,6 +492,131 @@ tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert)
492 return 1; 492 return 1;
493} 493}
494 494
495/*
496 * SessionTicket extension - RFC 5077 section 3.2
497 */
498int
499tlsext_sessionticket_clienthello_needs(SSL *s)
500{
501 /*
502 * Send session ticket extension when enabled and not overridden.
503 *
504 * When renegotiating, send an empty session ticket to indicate support.
505 */
506 if ((SSL_get_options(s) & SSL_OP_NO_TICKET) != 0)
507 return 0;
508
509 if (s->internal->new_session)
510 return 1;
511
512 if (s->internal->tlsext_session_ticket != NULL &&
513 s->internal->tlsext_session_ticket->data == NULL)
514 return 0;
515
516 return 1;
517}
518
519int
520tlsext_sessionticket_clienthello_build(SSL *s, CBB *cbb)
521{
522 /*
523 * Signal that we support session tickets by sending an empty
524 * extension when renegotiating or no session found.
525 */
526 if (s->internal->new_session || s->session == NULL)
527 return 1;
528
529 if (s->session->tlsext_tick != NULL) {
530 /* Attempt to resume with an existing session ticket */
531 if (!CBB_add_bytes(cbb, s->session->tlsext_tick,
532 s->session->tlsext_ticklen))
533 return 0;
534
535 } else if (s->internal->tlsext_session_ticket != NULL) {
536 /*
537 * Attempt to resume with a custom provided session ticket set
538 * by SSL_set_session_ticket_ext().
539 */
540 if (s->internal->tlsext_session_ticket->length > 0) {
541 size_t ticklen = s->internal->tlsext_session_ticket->length;
542
543 if ((s->session->tlsext_tick = malloc(ticklen)) == NULL)
544 return 0;
545 memcpy(s->session->tlsext_tick,
546 s->internal->tlsext_session_ticket->data,
547 ticklen);
548 s->session->tlsext_ticklen = ticklen;
549
550 if (!CBB_add_bytes(cbb, s->session->tlsext_tick,
551 s->session->tlsext_ticklen))
552 return 0;
553 }
554 }
555
556 if (!CBB_flush(cbb))
557 return 0;
558
559 return 1;
560}
561
562int
563tlsext_sessionticket_clienthello_parse(SSL *s, CBS *cbs, int *alert)
564{
565 if (s->internal->tls_session_ticket_ext_cb) {
566 if (!s->internal->tls_session_ticket_ext_cb(s, CBS_data(cbs),
567 (int)CBS_len(cbs),
568 s->internal->tls_session_ticket_ext_cb_arg)) {
569 *alert = TLS1_AD_INTERNAL_ERROR;
570 return 0;
571 }
572 }
573
574 /* We need to signal that this was processed fully */
575 if (!CBS_skip(cbs, CBS_len(cbs))) {
576 *alert = TLS1_AD_INTERNAL_ERROR;
577 return 0;
578 }
579
580 return 1;
581}
582
583int
584tlsext_sessionticket_serverhello_needs(SSL *s)
585{
586 return (s->internal->tlsext_ticket_expected &&
587 !(SSL_get_options(s) & SSL_OP_NO_TICKET));
588}
589
590int
591tlsext_sessionticket_serverhello_build(SSL *s, CBB *cbb)
592{
593 /* Empty ticket */
594
595 return 1;
596}
597
598int
599tlsext_sessionticket_serverhello_parse(SSL *s, CBS *cbs, int *alert)
600{
601 if (s->internal->tls_session_ticket_ext_cb) {
602 if (!s->internal->tls_session_ticket_ext_cb(s, CBS_data(cbs),
603 (int)CBS_len(cbs),
604 s->internal->tls_session_ticket_ext_cb_arg)) {
605 *alert = TLS1_AD_INTERNAL_ERROR;
606 return 0;
607 }
608 }
609
610 if ((SSL_get_options(s) & SSL_OP_NO_TICKET) != 0 || CBS_len(cbs) > 0) {
611 *alert = TLS1_AD_UNSUPPORTED_EXTENSION;
612 return 0;
613 }
614
615 s->internal->tlsext_ticket_expected = 1;
616
617 return 1;
618}
619
495struct tls_extension { 620struct tls_extension {
496 uint16_t type; 621 uint16_t type;
497 int (*clienthello_needs)(SSL *s); 622 int (*clienthello_needs)(SSL *s);
@@ -539,6 +664,15 @@ static struct tls_extension tls_extensions[] = {
539 .serverhello_build = tlsext_ec_serverhello_build, 664 .serverhello_build = tlsext_ec_serverhello_build,
540 .serverhello_parse = tlsext_ec_serverhello_parse, 665 .serverhello_parse = tlsext_ec_serverhello_parse,
541 }, 666 },
667 {
668 .type = TLSEXT_TYPE_session_ticket,
669 .clienthello_needs = tlsext_sessionticket_clienthello_needs,
670 .clienthello_build = tlsext_sessionticket_clienthello_build,
671 .clienthello_parse = tlsext_sessionticket_clienthello_parse,
672 .serverhello_needs = tlsext_sessionticket_serverhello_needs,
673 .serverhello_build = tlsext_sessionticket_serverhello_build,
674 .serverhello_parse = tlsext_sessionticket_serverhello_parse,
675 },
542}; 676};
543 677
544#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) 678#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 38f8ffaa65..1e701e941a 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.5 2017/08/11 20:14:13 doug Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.6 2017/08/12 21:17:03 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>
@@ -44,6 +44,12 @@ int tlsext_ecpf_serverhello_needs(SSL *s);
44int tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb); 44int tlsext_ecpf_serverhello_build(SSL *s, CBB *cbb);
45int tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert); 45int tlsext_ecpf_serverhello_parse(SSL *s, CBS *cbs, int *alert);
46 46
47int tlsext_sessionticket_clienthello_needs(SSL *s);
48int tlsext_sessionticket_clienthello_build(SSL *s, CBB *cbb);
49int tlsext_sessionticket_clienthello_parse(SSL *s, CBS *cbs, int *alert);
50int tlsext_sessionticket_serverhello_needs(SSL *s);
51int tlsext_sessionticket_serverhello_build(SSL *s, CBB *cbb);
52int tlsext_sessionticket_serverhello_parse(SSL *s, CBS *cbs, int *alert);
47 53
48int tlsext_clienthello_build(SSL *s, CBB *cbb); 54int tlsext_clienthello_build(SSL *s, CBB *cbb);
49int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type, 55int tlsext_clienthello_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 911e8d3f4e..63d401c337 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.128 2017/08/12 21:03:08 jsing Exp $ */ 1/* $OpenBSD: t1_lib.c,v 1.129 2017/08/12 21:17:03 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 *
@@ -690,39 +690,6 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
690 return NULL; 690 return NULL;
691 ret += len; 691 ret += len;
692 692
693 if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
694 int ticklen;
695 if (!s->internal->new_session && s->session && s->session->tlsext_tick)
696 ticklen = s->session->tlsext_ticklen;
697 else if (s->session && s->internal->tlsext_session_ticket &&
698 s->internal->tlsext_session_ticket->data) {
699 ticklen = s->internal->tlsext_session_ticket->length;
700 s->session->tlsext_tick = malloc(ticklen);
701 if (!s->session->tlsext_tick)
702 return NULL;
703 memcpy(s->session->tlsext_tick,
704 s->internal->tlsext_session_ticket->data, ticklen);
705 s->session->tlsext_ticklen = ticklen;
706 } else
707 ticklen = 0;
708 if (ticklen == 0 && s->internal->tlsext_session_ticket &&
709 s->internal->tlsext_session_ticket->data == NULL)
710 goto skip_ext;
711 /* Check for enough room 2 for extension type, 2 for len
712 * rest for ticket
713 */
714 if ((size_t)(limit - ret) < 4 + ticklen)
715 return NULL;
716 s2n(TLSEXT_TYPE_session_ticket, ret);
717
718 s2n(ticklen, ret);
719 if (ticklen) {
720 memcpy(ret, s->session->tlsext_tick, ticklen);
721 ret += ticklen;
722 }
723 }
724skip_ext:
725
726 if (TLS1_get_client_version(s) >= TLS1_2_VERSION) { 693 if (TLS1_get_client_version(s) >= TLS1_2_VERSION) {
727 if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6) 694 if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6)
728 return NULL; 695 return NULL;
@@ -884,15 +851,6 @@ ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
884 * extension. 851 * extension.
885 */ 852 */
886 853
887 if (s->internal->tlsext_ticket_expected &&
888 !(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
889 if ((size_t)(limit - ret) < 4)
890 return NULL;
891
892 s2n(TLSEXT_TYPE_session_ticket, ret);
893 s2n(0, ret);
894 }
895
896 if (s->internal->tlsext_status_expected) { 854 if (s->internal->tlsext_status_expected) {
897 if ((size_t)(limit - ret) < 4) 855 if ((size_t)(limit - ret) < 4)
898 return NULL; 856 return NULL;
@@ -1068,13 +1026,7 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
1068 if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) 1026 if (!tlsext_clienthello_parse_one(s, &cbs, type, al))
1069 return 0; 1027 return 0;
1070 1028
1071 if (type == TLSEXT_TYPE_session_ticket) { 1029 if (type == TLSEXT_TYPE_signature_algorithms) {
1072 if (s->internal->tls_session_ticket_ext_cb &&
1073 !s->internal->tls_session_ticket_ext_cb(s, data, size, s->internal->tls_session_ticket_ext_cb_arg)) {
1074 *al = TLS1_AD_INTERNAL_ERROR;
1075 return 0;
1076 }
1077 } else if (type == TLSEXT_TYPE_signature_algorithms) {
1078 int dsize; 1030 int dsize;
1079 if (sigalg_seen || size < 2) { 1031 if (sigalg_seen || size < 2) {
1080 *al = SSL_AD_DECODE_ERROR; 1032 *al = SSL_AD_DECODE_ERROR;
@@ -1277,19 +1229,7 @@ ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al)
1277 if (!tlsext_serverhello_parse_one(s, &cbs, type, al)) 1229 if (!tlsext_serverhello_parse_one(s, &cbs, type, al))
1278 return 0; 1230 return 0;
1279 1231
1280 if (type == TLSEXT_TYPE_session_ticket) { 1232 if (type == TLSEXT_TYPE_status_request &&
1281 if (s->internal->tls_session_ticket_ext_cb &&
1282 !s->internal->tls_session_ticket_ext_cb(s, data, size, s->internal->tls_session_ticket_ext_cb_arg)) {
1283 *al = TLS1_AD_INTERNAL_ERROR;
1284 return 0;
1285 }
1286 if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || (size > 0)) {
1287 *al = TLS1_AD_UNSUPPORTED_EXTENSION;
1288 return 0;
1289 }
1290 s->internal->tlsext_ticket_expected = 1;
1291 }
1292 else if (type == TLSEXT_TYPE_status_request &&
1293 s->version != DTLS1_VERSION) { 1233 s->version != DTLS1_VERSION) {
1294 /* MUST be empty and only sent if we've requested 1234 /* MUST be empty and only sent if we've requested
1295 * a status request message. 1235 * a status request message.
diff --git a/src/regress/lib/libssl/tlsext/tlsexttest.c b/src/regress/lib/libssl/tlsext/tlsexttest.c
index 880142202e..1267f50a49 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.9 2017/08/12 19:09:37 beck Exp $ */ 1/* $OpenBSD: tlsexttest.c,v 1.10 2017/08/12 21:17:03 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -1298,6 +1298,304 @@ test_tlsext_sni_serverhello(void)
1298 return (failure); 1298 return (failure);
1299} 1299}
1300 1300
1301/*
1302 * Session ticket - RFC 5077 since no known implementations use 4507.
1303 *
1304 * Session tickets can be length 0 (special case) to 2^16-1.
1305 *
1306 * The state is encrypted by the server so it is opaque to the client.
1307 */
1308static uint8_t tlsext_sessionticket_hello_min[1];
1309static uint8_t tlsext_sessionticket_hello_max[65535];
1310
1311static int
1312test_tlsext_sessionticket_clienthello(void)
1313{
1314 unsigned char *data = NULL;
1315 SSL_CTX *ssl_ctx = NULL;
1316 SSL *ssl = NULL;
1317 int failure;
1318 CBB cbb;
1319 size_t dlen;
1320 uint8_t dummy[1234];
1321
1322 failure = 1;
1323
1324 CBB_init(&cbb, 0);
1325
1326 /* Create fake session tickets with random data. */
1327 arc4random_buf(tlsext_sessionticket_hello_min,
1328 sizeof(tlsext_sessionticket_hello_min));
1329 arc4random_buf(tlsext_sessionticket_hello_max,
1330 sizeof(tlsext_sessionticket_hello_max));
1331
1332 if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL)
1333 errx(1, "failed to create SSL_CTX");
1334 if ((ssl = SSL_new(ssl_ctx)) == NULL)
1335 errx(1, "failed to create SSL");
1336
1337 /* Should need a ticket by default. */
1338 if (!tlsext_sessionticket_clienthello_needs(ssl)) {
1339 FAIL("clienthello should need Sessionticket for default "
1340 "ciphers\n");
1341 goto err;
1342 }
1343
1344 /* Test disabling tickets. */
1345 if ((SSL_set_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) == 0) {
1346 FAIL("Cannot disable tickets in the TLS connection");
1347 return 0;
1348 }
1349 if (tlsext_sessionticket_clienthello_needs(ssl)) {
1350 FAIL("clienthello should not need SessionTicket if it was disabled");
1351 goto err;
1352 }
1353
1354 /* Test re-enabling tickets. */
1355 if ((SSL_clear_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) != 0) {
1356 FAIL("Cannot re-enable tickets in the TLS connection");
1357 return 0;
1358 }
1359 if (!tlsext_sessionticket_clienthello_needs(ssl)) {
1360 FAIL("clienthello should need SessionTicket if it was disabled");
1361 goto err;
1362 }
1363
1364 /* Since we don't have a session, we should build an empty ticket. */
1365 if (!tlsext_sessionticket_clienthello_build(ssl, &cbb)) {
1366 FAIL("Cannot build a ticket");
1367 goto err;
1368 }
1369 if (!CBB_finish(&cbb, &data, &dlen)) {
1370 FAIL("Cannot finish CBB");
1371 goto err;
1372 }
1373 if (dlen != 0) {
1374 FAIL("Expected 0 length but found %zu\n", dlen);
1375 goto err;
1376 }
1377
1378 CBB_cleanup(&cbb);
1379 CBB_init(&cbb, 0);
1380 free(data);
1381 data = NULL;
1382
1383 /* With a new session (but no ticket), we should still have 0 length */
1384 if ((ssl->session = SSL_SESSION_new()) == NULL)
1385 errx(1, "failed to create session");
1386 if (!tlsext_sessionticket_clienthello_needs(ssl)) {
1387 FAIL("Should still want a session ticket with a new session");
1388 goto err;
1389 }
1390 if (!tlsext_sessionticket_clienthello_build(ssl, &cbb)) {
1391 FAIL("Cannot build a ticket");
1392 goto err;
1393 }
1394 if (!CBB_finish(&cbb, &data, &dlen)) {
1395 FAIL("Cannot finish CBB");
1396 goto err;
1397 }
1398 if (dlen != 0) {
1399 FAIL("Expected 0 length but found %zu\n", dlen);
1400 goto err;
1401 }
1402
1403 CBB_cleanup(&cbb);
1404 CBB_init(&cbb, 0);
1405 free(data);
1406 data = NULL;
1407
1408 /* With a new session (and ticket), we should use that ticket */
1409 SSL_SESSION_free(ssl->session);
1410 if ((ssl->session = SSL_SESSION_new()) == NULL)
1411 errx(1, "failed to create session");
1412
1413 arc4random_buf(&dummy, sizeof(dummy));
1414 if ((ssl->session->tlsext_tick = malloc(sizeof(dummy))) == NULL) {
1415 errx(1, "failed to malloc");
1416 }
1417 memcpy(ssl->session->tlsext_tick, dummy, sizeof(dummy));
1418 ssl->session->tlsext_ticklen = sizeof(dummy);
1419
1420 if (!tlsext_sessionticket_clienthello_needs(ssl)) {
1421 FAIL("Should still want a session ticket with a new session");
1422 goto err;
1423 }
1424 if (!tlsext_sessionticket_clienthello_build(ssl, &cbb)) {
1425 FAIL("Cannot build a ticket");
1426 goto err;
1427 }
1428 if (!CBB_finish(&cbb, &data, &dlen)) {
1429 FAIL("Cannot finish CBB");
1430 goto err;
1431 }
1432 if (dlen != sizeof(dummy)) {
1433 FAIL("Expected %zu length but found %zu\n", sizeof(dummy), dlen);
1434 goto err;
1435 }
1436 if (memcmp(data, dummy, dlen) != 0) {
1437 FAIL("serverhello SNI differs:\n");
1438 compare_data(data, dlen,
1439 dummy, sizeof(dummy));
1440 goto err;
1441 }
1442
1443 CBB_cleanup(&cbb);
1444 CBB_init(&cbb, 0);
1445 free(data);
1446 data = NULL;
1447 free(ssl->session->tlsext_tick);
1448 ssl->session->tlsext_tick = NULL;
1449 ssl->session->tlsext_ticklen = 0;
1450
1451 /*
1452 * Send in NULL to disable session tickets at runtime without going
1453 * through SSL_set_options().
1454 */
1455 if (!SSL_set_session_ticket_ext(ssl, NULL, 0)) {
1456 FAIL("Could not set a NULL custom ticket");
1457 goto err;
1458 }
1459 /* Should not need a ticket in this case */
1460 if (tlsext_sessionticket_clienthello_needs(ssl)) {
1461 FAIL("Should not want to use session tickets with a NULL custom");
1462 goto err;
1463 }
1464
1465 /*
1466 * If you want to remove the tlsext_session_ticket behavior, you have
1467 * to do it manually.
1468 */
1469 free(ssl->internal->tlsext_session_ticket);
1470 ssl->internal->tlsext_session_ticket = NULL;
1471
1472 if (!tlsext_sessionticket_clienthello_needs(ssl)) {
1473 FAIL("Should need a session ticket again when the custom one is removed");
1474 goto err;
1475 }
1476
1477 /* Test a custom session ticket (not recommended in practice) */
1478 if (!SSL_set_session_ticket_ext(ssl, tlsext_sessionticket_hello_max,
1479 sizeof(tlsext_sessionticket_hello_max))) {
1480 FAIL("Should be able to set a custom ticket");
1481 goto err;
1482 }
1483 if (!tlsext_sessionticket_clienthello_needs(ssl)) {
1484 FAIL("Should need a session ticket again when the custom one is not empty");
1485 goto err;
1486 }
1487 if (!tlsext_sessionticket_clienthello_build(ssl, &cbb)) {
1488 FAIL("Cannot build a ticket with a max length random payload");
1489 goto err;
1490 }
1491 if (!CBB_finish(&cbb, &data, &dlen)) {
1492 FAIL("Cannot finish CBB");
1493 goto err;
1494 }
1495 if (dlen != sizeof(tlsext_sessionticket_hello_max)) {
1496 FAIL("Expected %zu length but found %zu\n",
1497 sizeof(tlsext_sessionticket_hello_max), dlen);
1498 goto err;
1499 }
1500 if (memcmp(data, tlsext_sessionticket_hello_max,
1501 sizeof(tlsext_sessionticket_hello_max)) != 0) {
1502 FAIL("Expected to get what we passed in");
1503 compare_data(data, dlen,
1504 tlsext_sessionticket_hello_max,
1505 sizeof(tlsext_sessionticket_hello_max));
1506 goto err;
1507 }
1508
1509 failure = 0;
1510
1511 err:
1512 CBB_cleanup(&cbb);
1513 SSL_CTX_free(ssl_ctx);
1514 SSL_free(ssl);
1515 free(data);
1516
1517 return (failure);
1518}
1519
1520
1521static int
1522test_tlsext_sessionticket_serverhello(void)
1523{
1524 SSL_CTX *ssl_ctx = NULL;
1525 SSL *ssl = NULL;
1526 int failure;
1527 uint8_t *data;
1528 size_t dlen;
1529 CBB cbb;
1530
1531 CBB_init(&cbb, 0);
1532
1533 failure = 1;
1534
1535 if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL)
1536 errx(1, "failed to create SSL_CTX");
1537 if ((ssl = SSL_new(ssl_ctx)) == NULL)
1538 errx(1, "failed to create SSL");
1539
1540 /*
1541 * By default, should not need a session ticket since the ticket
1542 * is not yet expected.
1543 */
1544 if (tlsext_sessionticket_serverhello_needs(ssl)) {
1545 FAIL("serverhello should not need SessionTicket by default\n");
1546 goto err;
1547 }
1548
1549 /* Test disabling tickets. */
1550 if ((SSL_set_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) == 0) {
1551 FAIL("Cannot disable tickets in the TLS connection");
1552 return 0;
1553 }
1554 if (tlsext_sessionticket_serverhello_needs(ssl)) {
1555 FAIL("serverhello should not need SessionTicket if it was disabled");
1556 goto err;
1557 }
1558
1559 /* Test re-enabling tickets. */
1560 if ((SSL_clear_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) != 0) {
1561 FAIL("Cannot re-enable tickets in the TLS connection");
1562 return 0;
1563 }
1564 if (tlsext_sessionticket_serverhello_needs(ssl)) {
1565 FAIL("serverhello should not need SessionTicket yet");
1566 goto err;
1567 }
1568
1569 /* Set expected to require it. */
1570 ssl->internal->tlsext_ticket_expected = 1;
1571 if (!tlsext_sessionticket_serverhello_needs(ssl)) {
1572 FAIL("serverhello should now be required for SessionTicket");
1573 goto err;
1574 }
1575
1576 /* server hello's session ticket should always be 0 length payload. */
1577 if (!tlsext_sessionticket_serverhello_build(ssl, &cbb)) {
1578 FAIL("Cannot build a ticket with a max length random payload");
1579 goto err;
1580 }
1581 if (!CBB_finish(&cbb, &data, &dlen)) {
1582 FAIL("Cannot finish CBB");
1583 goto err;
1584 }
1585 if (dlen != 0) {
1586 FAIL("Expected 0 length but found %zu\n", dlen);
1587 goto err;
1588 }
1589
1590 failure = 0;
1591
1592 err:
1593 SSL_CTX_free(ssl_ctx);
1594 SSL_free(ssl);
1595
1596 return (failure);
1597}
1598
1301int 1599int
1302main(int argc, char **argv) 1600main(int argc, char **argv)
1303{ 1601{
@@ -1317,5 +1615,8 @@ main(int argc, char **argv)
1317 failed |= test_tlsext_sni_clienthello(); 1615 failed |= test_tlsext_sni_clienthello();
1318 failed |= test_tlsext_sni_serverhello(); 1616 failed |= test_tlsext_sni_serverhello();
1319 1617
1618 failed |= test_tlsext_sessionticket_clienthello();
1619 failed |= test_tlsext_sessionticket_serverhello();
1620
1320 return (failed); 1621 return (failed);
1321} 1622}