diff options
Diffstat (limited to 'src/regress/lib/libssl/tlsext/tlsexttest.c')
| -rw-r--r-- | src/regress/lib/libssl/tlsext/tlsexttest.c | 303 |
1 files changed, 302 insertions, 1 deletions
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 | */ | ||
| 1308 | static uint8_t tlsext_sessionticket_hello_min[1]; | ||
| 1309 | static uint8_t tlsext_sessionticket_hello_max[65535]; | ||
| 1310 | |||
| 1311 | static int | ||
| 1312 | test_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 | |||
| 1521 | static int | ||
| 1522 | test_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 | |||
| 1301 | int | 1599 | int |
| 1302 | main(int argc, char **argv) | 1600 | main(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 | } |
