Mercurial > hg > nginx
comparison src/event/ngx_event_quic.c @ 8319:29354c6fc5f2 quic
TLS Key Update in QUIC.
Old keys retention is yet to be implemented.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Mon, 06 Apr 2020 14:54:08 +0300 |
parents | 0dc0552335bd |
children | 6e1213ef469a |
comparison
equal
deleted
inserted
replaced
8318:1bb5e8538d0c | 8319:29354c6fc5f2 |
---|---|
66 | 66 |
67 ngx_quic_state_t state; | 67 ngx_quic_state_t state; |
68 | 68 |
69 ngx_quic_namespace_t ns[NGX_QUIC_NAMESPACE_LAST]; | 69 ngx_quic_namespace_t ns[NGX_QUIC_NAMESPACE_LAST]; |
70 ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; | 70 ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; |
71 ngx_quic_secrets_t next_key; | |
71 uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; | 72 uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; |
72 | 73 |
73 ngx_ssl_t *ssl; | 74 ngx_ssl_t *ssl; |
74 | 75 |
75 ngx_event_t push; | 76 ngx_event_t push; |
86 uint64_t cur_streams; | 87 uint64_t cur_streams; |
87 uint64_t max_streams; | 88 uint64_t max_streams; |
88 | 89 |
89 unsigned send_timer_set:1; | 90 unsigned send_timer_set:1; |
90 unsigned closing:1; | 91 unsigned closing:1; |
92 unsigned key_phase:1; | |
91 }; | 93 }; |
92 | 94 |
93 | 95 |
94 #if BORINGSSL_API_VERSION >= 10 | 96 #if BORINGSSL_API_VERSION >= 10 |
95 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, | 97 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, |
977 | 979 |
978 | 980 |
979 static ngx_int_t | 981 static ngx_int_t |
980 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt) | 982 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt) |
981 { | 983 { |
982 ngx_quic_secrets_t *keys; | 984 ngx_int_t rc; |
985 ngx_quic_secrets_t *keys, *next, tmp; | |
983 ngx_quic_connection_t *qc; | 986 ngx_quic_connection_t *qc; |
984 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; | 987 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; |
985 | 988 |
986 c->log->action = "processing application data quic packet"; | 989 c->log->action = "processing application data quic packet"; |
987 | 990 |
988 qc = c->quic; | 991 qc = c->quic; |
989 | 992 |
990 keys = &c->quic->keys[ssl_encryption_application]; | 993 keys = &c->quic->keys[ssl_encryption_application]; |
994 next = &c->quic->next_key; | |
991 | 995 |
992 if (keys->client.key.len == 0) { | 996 if (keys->client.key.len == 0) { |
993 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 997 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
994 "no read keys yet, packet ignored"); | 998 "no read keys yet, packet ignored"); |
995 return NGX_DECLINED; | 999 return NGX_DECLINED; |
998 if (ngx_quic_parse_short_header(pkt, &qc->dcid) != NGX_OK) { | 1002 if (ngx_quic_parse_short_header(pkt, &qc->dcid) != NGX_OK) { |
999 return NGX_ERROR; | 1003 return NGX_ERROR; |
1000 } | 1004 } |
1001 | 1005 |
1002 pkt->secret = &keys->client; | 1006 pkt->secret = &keys->client; |
1007 pkt->next = &next->client; | |
1008 pkt->key_phase = c->quic->key_phase; | |
1003 pkt->level = ssl_encryption_application; | 1009 pkt->level = ssl_encryption_application; |
1004 pkt->plaintext = buf; | 1010 pkt->plaintext = buf; |
1005 | 1011 |
1006 if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) { | 1012 if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) { |
1007 return NGX_ERROR; | 1013 return NGX_ERROR; |
1008 } | 1014 } |
1009 | 1015 |
1010 return ngx_quic_payload_handler(c, pkt); | 1016 /* switch keys on Key Phase change */ |
1017 | |
1018 if (pkt->key_update) { | |
1019 c->quic->key_phase ^= 1; | |
1020 | |
1021 tmp = *keys; | |
1022 *keys = *next; | |
1023 *next = tmp; | |
1024 } | |
1025 | |
1026 rc = ngx_quic_payload_handler(c, pkt); | |
1027 | |
1028 if (rc == NGX_ERROR) { | |
1029 return NGX_ERROR; | |
1030 } | |
1031 | |
1032 /* generate next keys */ | |
1033 | |
1034 if (pkt->key_update) { | |
1035 if (ngx_quic_key_update(c, keys, next) != NGX_OK) { | |
1036 return NGX_ERROR; | |
1037 } | |
1038 } | |
1039 | |
1040 return rc; | |
1011 } | 1041 } |
1012 | 1042 |
1013 | 1043 |
1014 static ngx_int_t | 1044 static ngx_int_t |
1015 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1045 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1328 frame->type = NGX_QUIC_FT_HANDSHAKE_DONE; | 1358 frame->type = NGX_QUIC_FT_HANDSHAKE_DONE; |
1329 ngx_sprintf(frame->info, "HANDSHAKE DONE on handshake completed"); | 1359 ngx_sprintf(frame->info, "HANDSHAKE DONE on handshake completed"); |
1330 ngx_quic_queue_frame(c->quic, frame); | 1360 ngx_quic_queue_frame(c->quic, frame); |
1331 } | 1361 } |
1332 #endif | 1362 #endif |
1363 | |
1364 /* | |
1365 * Generating next keys before a key update is received. | |
1366 * See quic-tls 9.4 Header Protection Timing Side-Channels. | |
1367 */ | |
1368 | |
1369 if (ngx_quic_key_update(c, &c->quic->keys[ssl_encryption_application], | |
1370 &c->quic->next_key) | |
1371 != NGX_OK) | |
1372 { | |
1373 return NGX_ERROR; | |
1374 } | |
1333 } | 1375 } |
1334 | 1376 |
1335 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1377 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1336 "SSL_quic_read_level: %d, SSL_quic_write_level: %d", | 1378 "SSL_quic_read_level: %d, SSL_quic_write_level: %d", |
1337 (int) SSL_quic_read_level(ssl_conn), | 1379 (int) SSL_quic_read_level(ssl_conn), |
1754 | 1796 |
1755 } else if (start->level == ssl_encryption_handshake) { | 1797 } else if (start->level == ssl_encryption_handshake) { |
1756 pkt.flags = NGX_QUIC_PKT_HANDSHAKE; | 1798 pkt.flags = NGX_QUIC_PKT_HANDSHAKE; |
1757 | 1799 |
1758 } else { | 1800 } else { |
1759 pkt.flags = 0x40; // TODO: macro, set FIXED bit | 1801 // TODO: macro, set FIXED bit |
1802 pkt.flags = 0x40 | (c->quic->key_phase ? NGX_QUIC_PKT_KPHASE : 0); | |
1760 } | 1803 } |
1761 | 1804 |
1762 ngx_quic_set_packet_number(&pkt, ns); | 1805 ngx_quic_set_packet_number(&pkt, ns); |
1763 | 1806 |
1764 pkt.log = c->log; | 1807 pkt.log = c->log; |