Klaus Demo nginx / ab9038a
SSL: support for TLSv1.3 early data with OpenSSL. In collaboration with Maxim Dounin. Sergey Kandaurov 3 years ago
2 changed file(s) with 451 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
2525 static void ngx_ssl_passwords_cleanup(void *data);
2626 static int ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn,
2727 ngx_ssl_session_t *sess);
28 #ifdef SSL_READ_EARLY_DATA_SUCCESS
29 static ngx_int_t ngx_ssl_try_early_data(ngx_connection_t *c);
30 #endif
31 #if (NGX_DEBUG)
32 static void ngx_ssl_handshake_log(ngx_connection_t *c);
33 #endif
2834 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
35 #ifdef SSL_READ_EARLY_DATA_SUCCESS
36 static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf,
37 size_t size);
38 #endif
2939 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
3040 static void ngx_ssl_write_handler(ngx_event_t *wev);
41 #ifdef SSL_READ_EARLY_DATA_SUCCESS
42 static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data,
43 size_t size);
44 #endif
3145 static void ngx_ssl_read_handler(ngx_event_t *rev);
3246 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
3347 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
339353 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
340354 #endif
341355
356 #ifdef SSL_OP_NO_ANTI_REPLAY
357 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY);
358 #endif
359
342360 #ifdef SSL_MODE_RELEASE_BUFFERS
343361 SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
344362 #endif
11841202
11851203 SSL_CTX_set_early_data_enabled(ssl->ctx, 1);
11861204
1205 #elif defined SSL_READ_EARLY_DATA_SUCCESS
1206
1207 /* OpenSSL */
1208
1209 SSL_CTX_set_max_early_data(ssl->ctx, NGX_SSL_BUFSIZE);
1210
11871211 #else
11881212 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
11891213 "\"ssl_early_data\" is not supported on this platform, "
12451269
12461270 sc->session_ctx = ssl->ctx;
12471271
1272 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1273 if (SSL_CTX_get_max_early_data(ssl->ctx)) {
1274 sc->try_early_data = 1;
1275 }
1276 #endif
1277
12481278 sc->connection = SSL_new(ssl->ctx);
12491279
12501280 if (sc->connection == NULL) {
13241354 int n, sslerr;
13251355 ngx_err_t err;
13261356
1357 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1358 if (c->ssl->try_early_data) {
1359 return ngx_ssl_try_early_data(c);
1360 }
1361 #endif
1362
13271363 ngx_ssl_clear_error(c->log);
13281364
13291365 n = SSL_do_handshake(c->ssl->connection);
13411377 }
13421378
13431379 #if (NGX_DEBUG)
1344 {
1345 char buf[129], *s, *d;
1346 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1347 const
1348 #endif
1349 SSL_CIPHER *cipher;
1350
1351 cipher = SSL_get_current_cipher(c->ssl->connection);
1352
1353 if (cipher) {
1354 SSL_CIPHER_description(cipher, &buf[1], 128);
1355
1356 for (s = &buf[1], d = buf; *s; s++) {
1357 if (*s == ' ' && *d == ' ') {
1358 continue;
1359 }
1360
1361 if (*s == LF || *s == CR) {
1362 continue;
1363 }
1364
1365 *++d = *s;
1366 }
1367
1368 if (*d != ' ') {
1369 d++;
1370 }
1371
1372 *d = '\0';
1373
1374 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1375 "SSL: %s, cipher: \"%s\"",
1376 SSL_get_version(c->ssl->connection), &buf[1]);
1377
1378 if (SSL_session_reused(c->ssl->connection)) {
1379 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1380 "SSL reused session");
1381 }
1382
1383 } else {
1384 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1385 "SSL no shared ciphers");
1386 }
1387 }
1380 ngx_ssl_handshake_log(c);
13881381 #endif
13891382
13901383 c->ssl->handshaked = 1;
14671460 }
14681461
14691462
1463 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1464
1465 static ngx_int_t
1466 ngx_ssl_try_early_data(ngx_connection_t *c)
1467 {
1468 int n, sslerr;
1469 u_char buf;
1470 size_t readbytes;
1471 ngx_err_t err;
1472
1473 ngx_ssl_clear_error(c->log);
1474
1475 readbytes = 0;
1476
1477 n = SSL_read_early_data(c->ssl->connection, &buf, 1, &readbytes);
1478
1479 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1480 "SSL_read_early_data: %d, %uz", n, readbytes);
1481
1482 if (n == SSL_READ_EARLY_DATA_FINISH) {
1483 c->ssl->try_early_data = 0;
1484 return ngx_ssl_handshake(c);
1485 }
1486
1487 if (n == SSL_READ_EARLY_DATA_SUCCESS) {
1488
1489 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1490 return NGX_ERROR;
1491 }
1492
1493 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1494 return NGX_ERROR;
1495 }
1496
1497 #if (NGX_DEBUG)
1498 ngx_ssl_handshake_log(c);
1499 #endif
1500
1501 c->ssl->try_early_data = 0;
1502
1503 c->ssl->early_buf = buf;
1504 c->ssl->early_preread = 1;
1505
1506 c->ssl->handshaked = 1;
1507 c->ssl->in_early = 1;
1508
1509 c->recv = ngx_ssl_recv;
1510 c->send = ngx_ssl_write;
1511 c->recv_chain = ngx_ssl_recv_chain;
1512 c->send_chain = ngx_ssl_send_chain;
1513
1514 return NGX_OK;
1515 }
1516
1517 /* SSL_READ_EARLY_DATA_ERROR */
1518
1519 sslerr = SSL_get_error(c->ssl->connection, n);
1520
1521 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1522
1523 if (sslerr == SSL_ERROR_WANT_READ) {
1524 c->read->ready = 0;
1525 c->read->handler = ngx_ssl_handshake_handler;
1526 c->write->handler = ngx_ssl_handshake_handler;
1527
1528 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1529 return NGX_ERROR;
1530 }
1531
1532 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1533 return NGX_ERROR;
1534 }
1535
1536 return NGX_AGAIN;
1537 }
1538
1539 if (sslerr == SSL_ERROR_WANT_WRITE) {
1540 c->write->ready = 0;
1541 c->read->handler = ngx_ssl_handshake_handler;
1542 c->write->handler = ngx_ssl_handshake_handler;
1543
1544 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1545 return NGX_ERROR;
1546 }
1547
1548 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1549 return NGX_ERROR;
1550 }
1551
1552 return NGX_AGAIN;
1553 }
1554
1555 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1556
1557 c->ssl->no_wait_shutdown = 1;
1558 c->ssl->no_send_shutdown = 1;
1559 c->read->eof = 1;
1560
1561 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
1562 ngx_connection_error(c, err,
1563 "peer closed connection in SSL handshake");
1564
1565 return NGX_ERROR;
1566 }
1567
1568 c->read->error = 1;
1569
1570 ngx_ssl_connection_error(c, sslerr, err, "SSL_read_early_data() failed");
1571
1572 return NGX_ERROR;
1573 }
1574
1575 #endif
1576
1577
1578 #if (NGX_DEBUG)
1579
1580 static void
1581 ngx_ssl_handshake_log(ngx_connection_t *c)
1582 {
1583 char buf[129], *s, *d;
1584 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1585 const
1586 #endif
1587 SSL_CIPHER *cipher;
1588
1589 cipher = SSL_get_current_cipher(c->ssl->connection);
1590
1591 if (cipher) {
1592 SSL_CIPHER_description(cipher, &buf[1], 128);
1593
1594 for (s = &buf[1], d = buf; *s; s++) {
1595 if (*s == ' ' && *d == ' ') {
1596 continue;
1597 }
1598
1599 if (*s == LF || *s == CR) {
1600 continue;
1601 }
1602
1603 *++d = *s;
1604 }
1605
1606 if (*d != ' ') {
1607 d++;
1608 }
1609
1610 *d = '\0';
1611
1612 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1613 "SSL: %s, cipher: \"%s\"",
1614 SSL_get_version(c->ssl->connection), &buf[1]);
1615
1616 if (SSL_session_reused(c->ssl->connection)) {
1617 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1618 "SSL reused session");
1619 }
1620
1621 } else {
1622 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1623 "SSL no shared ciphers");
1624 }
1625 }
1626
1627 #endif
1628
1629
14701630 static void
14711631 ngx_ssl_handshake_handler(ngx_event_t *ev)
14721632 {
15541714 {
15551715 int n, bytes;
15561716
1717 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1718 if (c->ssl->in_early) {
1719 return ngx_ssl_recv_early(c, buf, size);
1720 }
1721 #endif
1722
15571723 if (c->ssl->last == NGX_ERROR) {
15581724 c->read->error = 1;
15591725 return NGX_ERROR;
16251791 }
16261792 }
16271793 }
1794
1795
1796 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1797
1798 static ssize_t
1799 ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
1800 {
1801 int n, bytes;
1802 size_t readbytes;
1803
1804 if (c->ssl->last == NGX_ERROR) {
1805 c->read->error = 1;
1806 return NGX_ERROR;
1807 }
1808
1809 if (c->ssl->last == NGX_DONE) {
1810 c->read->ready = 0;
1811 c->read->eof = 1;
1812 return 0;
1813 }
1814
1815 bytes = 0;
1816
1817 ngx_ssl_clear_error(c->log);
1818
1819 if (c->ssl->early_preread) {
1820
1821 if (size == 0) {
1822 c->read->ready = 0;
1823 c->read->eof = 1;
1824 return 0;
1825 }
1826
1827 *buf = c->ssl->early_buf;
1828
1829 c->ssl->early_preread = 0;
1830
1831 bytes = 1;
1832 size -= 1;
1833 buf += 1;
1834 }
1835
1836 /*
1837 * SSL_read_early_data() may return data in parts, so try to read
1838 * until SSL_read_early_data() would return no data
1839 */
1840
1841 for ( ;; ) {
1842
1843 readbytes = 0;
1844
1845 n = SSL_read_early_data(c->ssl->connection, buf, size, &readbytes);
1846
1847 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1848 "SSL_read_early_data: %d, %uz", n, readbytes);
1849
1850 if (n == SSL_READ_EARLY_DATA_SUCCESS) {
1851
1852 c->ssl->last = ngx_ssl_handle_recv(c, 1);
1853
1854 bytes += readbytes;
1855 size -= readbytes;
1856
1857 if (size == 0) {
1858 c->read->ready = 1;
1859 return bytes;
1860 }
1861
1862 buf += readbytes;
1863
1864 continue;
1865 }
1866
1867 if (n == SSL_READ_EARLY_DATA_FINISH) {
1868
1869 c->ssl->last = ngx_ssl_handle_recv(c, 1);
1870 c->ssl->in_early = 0;
1871
1872 if (bytes) {
1873 c->read->ready = 1;
1874 return bytes;
1875 }
1876
1877 return ngx_ssl_recv(c, buf, size);
1878 }
1879
1880 /* SSL_READ_EARLY_DATA_ERROR */
1881
1882 c->ssl->last = ngx_ssl_handle_recv(c, 0);
1883
1884 if (bytes) {
1885 if (c->ssl->last != NGX_AGAIN) {
1886 c->read->ready = 1;
1887 }
1888
1889 return bytes;
1890 }
1891
1892 switch (c->ssl->last) {
1893
1894 case NGX_DONE:
1895 c->read->ready = 0;
1896 c->read->eof = 1;
1897 return 0;
1898
1899 case NGX_ERROR:
1900 c->read->error = 1;
1901
1902 /* fall through */
1903
1904 case NGX_AGAIN:
1905 return c->ssl->last;
1906 }
1907 }
1908 }
1909
1910 #endif
16281911
16291912
16301913 static ngx_int_t
19222205 int n, sslerr;
19232206 ngx_err_t err;
19242207
2208 #ifdef SSL_READ_EARLY_DATA_SUCCESS
2209 if (c->ssl->in_early) {
2210 return ngx_ssl_write_early(c, data, size);
2211 }
2212 #endif
2213
19252214 ngx_ssl_clear_error(c->log);
19262215
19272216 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size);
20072296
20082297 return NGX_ERROR;
20092298 }
2299
2300
2301 #ifdef SSL_READ_EARLY_DATA_SUCCESS
2302
2303 ssize_t
2304 ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
2305 {
2306 int n, sslerr;
2307 size_t written;
2308 ngx_err_t err;
2309
2310 ngx_ssl_clear_error(c->log);
2311
2312 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size);
2313
2314 written = 0;
2315
2316 n = SSL_write_early_data(c->ssl->connection, data, size, &written);
2317
2318 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2319 "SSL_write_early_data: %d, %uz", n, written);
2320
2321 if (n > 0) {
2322
2323 if (c->ssl->saved_read_handler) {
2324
2325 c->read->handler = c->ssl->saved_read_handler;
2326 c->ssl->saved_read_handler = NULL;
2327 c->read->ready = 1;
2328
2329 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2330 return NGX_ERROR;
2331 }
2332
2333 ngx_post_event(c->read, &ngx_posted_events);
2334 }
2335
2336 c->sent += written;
2337
2338 return written;
2339 }
2340
2341 sslerr = SSL_get_error(c->ssl->connection, n);
2342
2343 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
2344
2345 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
2346
2347 if (sslerr == SSL_ERROR_WANT_WRITE) {
2348
2349 if (c->ssl->saved_read_handler) {
2350
2351 c->read->handler = c->ssl->saved_read_handler;
2352 c->ssl->saved_read_handler = NULL;
2353 c->read->ready = 1;
2354
2355 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2356 return NGX_ERROR;
2357 }
2358
2359 ngx_post_event(c->read, &ngx_posted_events);
2360 }
2361
2362 c->write->ready = 0;
2363 return NGX_AGAIN;
2364 }
2365
2366 if (sslerr == SSL_ERROR_WANT_READ) {
2367
2368 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2369 "SSL_write_early_data: want read");
2370
2371 c->read->ready = 0;
2372
2373 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2374 return NGX_ERROR;
2375 }
2376
2377 /*
2378 * we do not set the timer because there is already
2379 * the write event timer
2380 */
2381
2382 if (c->ssl->saved_read_handler == NULL) {
2383 c->ssl->saved_read_handler = c->read->handler;
2384 c->read->handler = ngx_ssl_read_handler;
2385 }
2386
2387 return NGX_AGAIN;
2388 }
2389
2390 c->ssl->no_wait_shutdown = 1;
2391 c->ssl->no_send_shutdown = 1;
2392 c->write->error = 1;
2393
2394 ngx_ssl_connection_error(c, sslerr, err, "SSL_write_early_data() failed");
2395
2396 return NGX_ERROR;
2397 }
2398
2399 #endif
20102400
20112401
20122402 static void
36934083 s->len = 0;
36944084
36954085 #ifdef SSL_ERROR_EARLY_DATA_REJECTED
4086
4087 /* BoringSSL */
4088
36964089 if (SSL_in_early_data(c->ssl->connection)) {
36974090 ngx_str_set(s, "1");
36984091 }
4092
4093 #elif defined SSL_READ_EARLY_DATA_SUCCESS
4094
4095 /* OpenSSL */
4096
4097 if (!SSL_is_init_finished(c->ssl->connection)) {
4098 ngx_str_set(s, "1");
4099 }
4100
36994101 #endif
37004102
37014103 return NGX_OK;
8686 ngx_event_handler_pt saved_read_handler;
8787 ngx_event_handler_pt saved_write_handler;
8888
89 u_char early_buf;
90
8991 unsigned handshaked:1;
9092 unsigned renegotiation:1;
9193 unsigned buffer:1;
9294 unsigned no_wait_shutdown:1;
9395 unsigned no_send_shutdown:1;
9496 unsigned handshake_buffer_set:1;
97 unsigned try_early_data:1;
98 unsigned in_early:1;
99 unsigned early_preread:1;
95100 };
96101
97102