comparison src/event/ngx_event_quic.c @ 8191:9c3be23ddbe7 quic

QUIC: refactored key handling. All key handling functionality is moved into ngx_quic_protection.c. Public structures from ngx_quic_protection.h are now private and new methods are available to manipulate keys. A negotiated cipher is cached in QUIC connection from the set secret callback to avoid calling SSL_get_current_cipher() on each encrypt/decrypt operation. This also reduces the number of unwanted c->ssl->connection occurrences.
author Sergey Kandaurov <pluknet@nginx.com>
date Mon, 02 Nov 2020 18:21:34 +0300
parents d10118e38943
children 183275308d9a
comparison
equal deleted inserted replaced
8190:d10118e38943 8191:9c3be23ddbe7
92 * can be processed and acknowledged. Initial packets can only be sent 92 * can be processed and acknowledged. Initial packets can only be sent
93 * with Initial packet protection keys and acknowledged in packets which 93 * with Initial packet protection keys and acknowledged in packets which
94 * are also Initial packets. 94 * are also Initial packets.
95 */ 95 */
96 typedef struct { 96 typedef struct {
97 ngx_quic_secret_t client_secret;
98 ngx_quic_secret_t server_secret;
99
100 enum ssl_encryption_level_t level; 97 enum ssl_encryption_level_t level;
101 98
102 uint64_t pnum; /* to be sent */ 99 uint64_t pnum; /* to be sent */
103 uint64_t largest_ack; /* received from peer */ 100 uint64_t largest_ack; /* received from peer */
104 uint64_t largest_pn; /* received from peer */ 101 uint64_t largest_pn; /* received from peer */
132 ngx_uint_t client_tp_done; 129 ngx_uint_t client_tp_done;
133 ngx_quic_tp_t tp; 130 ngx_quic_tp_t tp;
134 ngx_quic_tp_t ctp; 131 ngx_quic_tp_t ctp;
135 132
136 ngx_quic_send_ctx_t send_ctx[NGX_QUIC_SEND_CTX_LAST]; 133 ngx_quic_send_ctx_t send_ctx[NGX_QUIC_SEND_CTX_LAST];
137 ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; 134
138 ngx_quic_secrets_t next_key;
139 ngx_quic_frames_stream_t crypto[NGX_QUIC_ENCRYPTION_LAST]; 135 ngx_quic_frames_stream_t crypto[NGX_QUIC_ENCRYPTION_LAST];
136
137 ngx_quic_keys_t *keys;
140 138
141 ngx_quic_conf_t *conf; 139 ngx_quic_conf_t *conf;
142 140
143 ngx_event_t push; 141 ngx_event_t push;
144 ngx_event_t pto; 142 ngx_event_t pto;
641 static int 639 static int
642 ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, 640 ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
643 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, 641 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
644 const uint8_t *rsecret, size_t secret_len) 642 const uint8_t *rsecret, size_t secret_len)
645 { 643 {
646 ngx_connection_t *c; 644 ngx_connection_t *c;
647 ngx_quic_secrets_t *keys;
648 645
649 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); 646 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
650 647
651 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 648 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
652 "quic ngx_quic_set_read_secret() level:%d", level); 649 "quic ngx_quic_set_read_secret() level:%d", level);
653 #ifdef NGX_QUIC_DEBUG_CRYPTO 650 #ifdef NGX_QUIC_DEBUG_CRYPTO
654 ngx_quic_hexdump(c->log, "quic read secret", rsecret, secret_len); 651 ngx_quic_hexdump(c->log, "quic read secret", rsecret, secret_len);
655 #endif 652 #endif
656 653
657 keys = &c->quic->keys[level]; 654 return ngx_quic_keys_set_encryption_secret(c->pool, 0, c->quic->keys, level,
658 655 cipher, rsecret, secret_len);
659 return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level,
660 rsecret, secret_len,
661 &keys->client);
662 } 656 }
663 657
664 658
665 static int 659 static int
666 ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn, 660 ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
667 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, 661 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
668 const uint8_t *wsecret, size_t secret_len) 662 const uint8_t *wsecret, size_t secret_len)
669 { 663 {
670 ngx_connection_t *c; 664 ngx_connection_t *c;
671 ngx_quic_secrets_t *keys;
672 665
673 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); 666 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
674 667
675 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 668 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
676 "quic ngx_quic_set_write_secret() level:%d", level); 669 "quic ngx_quic_set_write_secret() level:%d", level);
677 #ifdef NGX_QUIC_DEBUG_CRYPTO 670 #ifdef NGX_QUIC_DEBUG_CRYPTO
678 ngx_quic_hexdump(c->log, "quic write secret", wsecret, secret_len); 671 ngx_quic_hexdump(c->log, "quic write secret", wsecret, secret_len);
679 #endif 672 #endif
680 673
681 keys = &c->quic->keys[level]; 674 return ngx_quic_keys_set_encryption_secret(c->pool, 1, c->quic->keys, level,
682 675 cipher, wsecret, secret_len);
683 return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level,
684 wsecret, secret_len,
685 &keys->server);
686 } 676 }
687 677
688 #else 678 #else
689 679
690 static int 680 static int
691 ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn, 681 ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
692 enum ssl_encryption_level_t level, const uint8_t *rsecret, 682 enum ssl_encryption_level_t level, const uint8_t *rsecret,
693 const uint8_t *wsecret, size_t secret_len) 683 const uint8_t *wsecret, size_t secret_len)
694 { 684 {
695 ngx_int_t rc; 685 ngx_connection_t *c;
696 ngx_connection_t *c; 686 const SSL_CIPHER *cipher;
697 ngx_quic_secrets_t *keys;
698 687
699 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); 688 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
700 689
701 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 690 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
702 "quic ngx_quic_set_encryption_secrets() level:%d", level); 691 "quic ngx_quic_set_encryption_secrets() level:%d", level);
703 #ifdef NGX_QUIC_DEBUG_CRYPTO 692 #ifdef NGX_QUIC_DEBUG_CRYPTO
704 ngx_quic_hexdump(c->log, "quic read", rsecret, secret_len); 693 ngx_quic_hexdump(c->log, "quic read secret", rsecret, secret_len);
705 #endif 694 #endif
706 695
707 keys = &c->quic->keys[level]; 696 cipher = SSL_get_current_cipher(ssl_conn);
708 697
709 rc = ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, 698 if (ngx_quic_keys_set_encryption_secret(c->pool, 0, c->quic->keys, level,
710 rsecret, secret_len, 699 cipher, rsecret, secret_len)
711 &keys->client); 700 != 1)
712 if (rc != 1) { 701 {
713 return rc; 702 return 0;
714 } 703 }
715 704
716 if (level == ssl_encryption_early_data) { 705 if (level == ssl_encryption_early_data) {
717 return 1; 706 return 1;
718 } 707 }
719 708
720 #ifdef NGX_QUIC_DEBUG_CRYPTO 709 #ifdef NGX_QUIC_DEBUG_CRYPTO
721 ngx_quic_hexdump(c->log, "quic write", wsecret, secret_len); 710 ngx_quic_hexdump(c->log, "quic write secret", wsecret, secret_len);
722 #endif 711 #endif
723 712
724 return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, 713 return ngx_quic_keys_set_encryption_secret(c->pool, 1, c->quic->keys, level,
725 wsecret, secret_len, 714 cipher, wsecret, secret_len);
726 &keys->server);
727 } 715 }
728 716
729 #endif 717 #endif
730 718
731 719
963 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); 951 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
964 if (qc == NULL) { 952 if (qc == NULL) {
965 return NULL; 953 return NULL;
966 } 954 }
967 955
956 qc->keys = ngx_quic_keys_new(c->pool);
957 if (qc->keys == NULL) {
958 return NULL;
959 }
960
968 ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel, 961 ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel,
969 ngx_quic_rbtree_insert_stream); 962 ngx_quic_rbtree_insert_stream);
970 963
971 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { 964 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
972 ngx_queue_init(&qc->send_ctx[i].frames); 965 ngx_queue_init(&qc->send_ctx[i].frames);
1237 pkt.scid = c->quic->dcid; 1230 pkt.scid = c->quic->dcid;
1238 pkt.token = token; 1231 pkt.token = token;
1239 1232
1240 res.data = buf; 1233 res.data = buf;
1241 1234
1242 if (ngx_quic_encrypt(&pkt, NULL, &res) != NGX_OK) { 1235 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
1243 return NGX_ERROR; 1236 return NGX_ERROR;
1244 } 1237 }
1245 1238
1246 #ifdef NGX_QUIC_DEBUG_PACKETS 1239 #ifdef NGX_QUIC_DEBUG_PACKETS
1247 ngx_quic_hexdump(c->log, "quic packet to send", res.data, res.len); 1240 ngx_quic_hexdump(c->log, "quic packet to send", res.data, res.len);
1988 static ngx_int_t 1981 static ngx_int_t
1989 ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf, 1982 ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
1990 ngx_quic_header_t *pkt) 1983 ngx_quic_header_t *pkt)
1991 { 1984 {
1992 ngx_int_t rc; 1985 ngx_int_t rc;
1993 ngx_ssl_conn_t *ssl_conn;
1994 ngx_quic_secrets_t *keys, *next, tmp;
1995 ngx_quic_send_ctx_t *ctx; 1986 ngx_quic_send_ctx_t *ctx;
1996 ngx_quic_connection_t *qc; 1987 ngx_quic_connection_t *qc;
1997 1988
1998 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 1989 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
1999 1990
2133 } 2124 }
2134 } 2125 }
2135 2126
2136 c->log->action = "decrypting packet"; 2127 c->log->action = "decrypting packet";
2137 2128
2138 keys = &qc->keys[pkt->level]; 2129 if (!ngx_quic_keys_available(qc->keys, pkt->level)) {
2139
2140 if (keys->client.key.len == 0) {
2141 ngx_log_error(NGX_LOG_INFO, c->log, 0, 2130 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2142 "quic no level %d keys yet, ignoring packet", pkt->level); 2131 "quic no level %d keys yet, ignoring packet", pkt->level);
2143 return NGX_DECLINED; 2132 return NGX_DECLINED;
2144 } 2133 }
2145 2134
2146 next = &qc->next_key; 2135 pkt->keys = qc->keys;
2147
2148 pkt->secret = &keys->client;
2149 pkt->next = &next->client;
2150 pkt->key_phase = qc->key_phase; 2136 pkt->key_phase = qc->key_phase;
2151 pkt->plaintext = buf; 2137 pkt->plaintext = buf;
2152 2138
2153 ctx = ngx_quic_get_send_ctx(qc, pkt->level); 2139 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
2154 2140
2155 ssl_conn = c->ssl ? c->ssl->connection : NULL; 2141 rc = ngx_quic_decrypt(pkt, &ctx->largest_pn);
2156
2157 rc = ngx_quic_decrypt(pkt, ssl_conn, &ctx->largest_pn);
2158 if (rc != NGX_OK) { 2142 if (rc != NGX_OK) {
2159 qc->error = pkt->error; 2143 qc->error = pkt->error;
2160 qc->error_reason = "failed to decrypt packet"; 2144 qc->error_reason = "failed to decrypt packet";
2161 return rc; 2145 return rc;
2162 } 2146 }
2188 2172
2189 if (pkt->level != ssl_encryption_application) { 2173 if (pkt->level != ssl_encryption_application) {
2190 return ngx_quic_payload_handler(c, pkt); 2174 return ngx_quic_payload_handler(c, pkt);
2191 } 2175 }
2192 2176
2193 /* switch keys on Key Phase change */ 2177 if (!pkt->key_update) {
2194 2178 return ngx_quic_payload_handler(c, pkt);
2195 if (pkt->key_update) { 2179 }
2196 qc->key_phase ^= 1; 2180
2197 2181 /* switch keys and generate next on Key Phase change */
2198 tmp = *keys; 2182
2199 *keys = *next; 2183 qc->key_phase ^= 1;
2200 *next = tmp; 2184 ngx_quic_keys_switch(c, qc->keys);
2201 }
2202 2185
2203 rc = ngx_quic_payload_handler(c, pkt); 2186 rc = ngx_quic_payload_handler(c, pkt);
2204 if (rc != NGX_OK) { 2187 if (rc != NGX_OK) {
2205 return rc; 2188 return rc;
2206 } 2189 }
2207 2190
2208 /* generate next keys */ 2191 return ngx_quic_keys_update(c, qc->keys);
2209
2210 if (pkt->key_update) {
2211 if (ngx_quic_key_update(c, keys, next) != NGX_OK) {
2212 return NGX_ERROR;
2213 }
2214 }
2215
2216 return NGX_OK;
2217 } 2192 }
2218 2193
2219 2194
2220 static ngx_int_t 2195 static ngx_int_t
2221 ngx_quic_init_secrets(ngx_connection_t *c) 2196 ngx_quic_init_secrets(ngx_connection_t *c)
2222 { 2197 {
2223 ngx_quic_secrets_t *keys;
2224 ngx_quic_connection_t *qc; 2198 ngx_quic_connection_t *qc;
2225 2199
2226 qc =c->quic; 2200 qc = c->quic;
2227 keys = &qc->keys[ssl_encryption_initial]; 2201
2228 2202 if (ngx_quic_keys_set_initial_secret(c->pool, qc->keys, &qc->odcid)
2229 if (ngx_quic_set_initial_secret(c->pool, &keys->client, &keys->server,
2230 &qc->odcid)
2231 != NGX_OK) 2203 != NGX_OK)
2232 { 2204 {
2233 return NGX_ERROR; 2205 return NGX_ERROR;
2234 } 2206 }
2235 2207
2247 ngx_quic_send_ctx_t *ctx; 2219 ngx_quic_send_ctx_t *ctx;
2248 ngx_quic_connection_t *qc; 2220 ngx_quic_connection_t *qc;
2249 2221
2250 qc = c->quic; 2222 qc = c->quic;
2251 2223
2252 if (qc->keys[level].client.key.len == 0) { 2224 if (!ngx_quic_keys_available(qc->keys, level)) {
2253 return; 2225 return;
2254 } 2226 }
2255 2227
2256 qc->keys[level].client.key.len = 0; 2228 ngx_quic_keys_discard(qc->keys, level);
2229
2257 qc->pto_count = 0; 2230 qc->pto_count = 0;
2258 2231
2259 ctx = ngx_quic_get_send_ctx(qc, level); 2232 ctx = ngx_quic_get_send_ctx(qc, level);
2260 2233
2261 while (!ngx_queue_empty(&ctx->sent)) { 2234 while (!ngx_queue_empty(&ctx->sent)) {
3632 /* 3605 /*
3633 * Generating next keys before a key update is received. 3606 * Generating next keys before a key update is received.
3634 * See quic-tls 9.4 Header Protection Timing Side-Channels. 3607 * See quic-tls 9.4 Header Protection Timing Side-Channels.
3635 */ 3608 */
3636 3609
3637 if (ngx_quic_key_update(c, &c->quic->keys[ssl_encryption_application], 3610 if (ngx_quic_keys_update(c, c->quic->keys) != NGX_OK) {
3638 &c->quic->next_key)
3639 != NGX_OK)
3640 {
3641 return NGX_ERROR; 3611 return NGX_ERROR;
3642 } 3612 }
3643 3613
3644 /* 3614 /*
3645 * 4.10.2 An endpoint MUST discard its handshake keys 3615 * 4.10.2 An endpoint MUST discard its handshake keys
4501 size_t pad_len; 4471 size_t pad_len;
4502 ssize_t len; 4472 ssize_t len;
4503 ngx_str_t out, res; 4473 ngx_str_t out, res;
4504 ngx_msec_t now; 4474 ngx_msec_t now;
4505 ngx_queue_t *q; 4475 ngx_queue_t *q;
4506 ngx_ssl_conn_t *ssl_conn;
4507 ngx_quic_frame_t *f, *start; 4476 ngx_quic_frame_t *f, *start;
4508 ngx_quic_header_t pkt; 4477 ngx_quic_header_t pkt;
4509 ngx_quic_secrets_t *keys;
4510 ngx_quic_connection_t *qc; 4478 ngx_quic_connection_t *qc;
4511 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 4479 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
4512 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 4480 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
4513 4481
4514 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, 4482 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4515 "quic ngx_quic_send_frames"); 4483 "quic ngx_quic_send_frames");
4516
4517 ssl_conn = c->ssl ? c->ssl->connection : NULL;
4518 4484
4519 q = ngx_queue_head(frames); 4485 q = ngx_queue_head(frames);
4520 start = ngx_queue_data(q, ngx_quic_frame_t, queue); 4486 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
4521 4487
4522 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); 4488 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
4552 4518
4553 out.len = p - out.data; 4519 out.len = p - out.data;
4554 4520
4555 qc = c->quic; 4521 qc = c->quic;
4556 4522
4557 keys = &c->quic->keys[start->level]; 4523 pkt.keys = qc->keys;
4558
4559 pkt.secret = &keys->server;
4560 4524
4561 pkt.flags = NGX_QUIC_PKT_FIXED_BIT; 4525 pkt.flags = NGX_QUIC_PKT_FIXED_BIT;
4562 4526
4563 if (start->level == ssl_encryption_initial) { 4527 if (start->level == ssl_encryption_initial) {
4564 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL; 4528 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL;
4601 "quic packet tx %s bytes:%ui" 4565 "quic packet tx %s bytes:%ui"
4602 " need_ack:%d number:%L encoded nl:%d trunc:0x%xD", 4566 " need_ack:%d number:%L encoded nl:%d trunc:0x%xD",
4603 ngx_quic_level_name(start->level), out.len, pkt.need_ack, 4567 ngx_quic_level_name(start->level), out.len, pkt.need_ack,
4604 pkt.number, pkt.num_len, pkt.trunc); 4568 pkt.number, pkt.num_len, pkt.trunc);
4605 4569
4606 if (ngx_quic_encrypt(&pkt, ssl_conn, &res) != NGX_OK) { 4570 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
4607 ngx_quic_free_frames(c, frames); 4571 ngx_quic_free_frames(c, frames);
4608 return NGX_ERROR; 4572 return NGX_ERROR;
4609 } 4573 }
4610 4574
4611 len = c->send(c, res.data, res.len); 4575 len = c->send(c, res.data, res.len);