Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7770:90f94413177e quic
TLS Early Data support.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Wed, 01 Apr 2020 13:27:42 +0300 |
parents | 2ac03e80d013 |
children | e35f824f644d |
comparison
equal
deleted
inserted
replaced
7769:2ac03e80d013 | 7770:90f94413177e |
---|---|
10 | 10 |
11 | 11 |
12 typedef enum { | 12 typedef enum { |
13 NGX_QUIC_ST_INITIAL, /* connection just created */ | 13 NGX_QUIC_ST_INITIAL, /* connection just created */ |
14 NGX_QUIC_ST_HANDSHAKE, /* handshake started */ | 14 NGX_QUIC_ST_HANDSHAKE, /* handshake started */ |
15 NGX_QUIC_ST_EARLY_DATA, /* handshake in progress */ | |
15 NGX_QUIC_ST_APPLICATION /* handshake complete */ | 16 NGX_QUIC_ST_APPLICATION /* handshake complete */ |
16 } ngx_quic_state_t; | 17 } ngx_quic_state_t; |
17 | 18 |
18 | 19 |
19 typedef struct { | 20 typedef struct { |
80 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, | 81 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, |
81 enum ssl_encryption_level_t level, uint8_t alert); | 82 enum ssl_encryption_level_t level, uint8_t alert); |
82 | 83 |
83 | 84 |
84 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, | 85 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, |
85 ngx_quic_tp_t *tp, ngx_quic_header_t *pkt); | 86 ngx_quic_tp_t *tp, ngx_quic_header_t *pkt, |
87 ngx_connection_handler_pt handler); | |
86 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c); | 88 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c); |
87 static void ngx_quic_input_handler(ngx_event_t *rev); | 89 static void ngx_quic_input_handler(ngx_event_t *rev); |
88 static void ngx_quic_close_connection(ngx_connection_t *c); | 90 static void ngx_quic_close_connection(ngx_connection_t *c); |
89 | 91 |
90 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b); | 92 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b); |
91 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c, | 93 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c, |
92 ngx_quic_header_t *pkt); | 94 ngx_quic_header_t *pkt); |
93 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, | 95 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, |
96 ngx_quic_header_t *pkt); | |
97 static ngx_int_t ngx_quic_early_input(ngx_connection_t *c, | |
94 ngx_quic_header_t *pkt); | 98 ngx_quic_header_t *pkt); |
95 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, | 99 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, |
96 ngx_quic_header_t *pkt); | 100 ngx_quic_header_t *pkt); |
97 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, | 101 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, |
98 ngx_quic_header_t *pkt); | 102 ngx_quic_header_t *pkt); |
157 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); | 161 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); |
158 | 162 |
159 ngx_quic_hexdump(c->log, "level:%d read secret", | 163 ngx_quic_hexdump(c->log, "level:%d read secret", |
160 rsecret, secret_len, level); | 164 rsecret, secret_len, level); |
161 | 165 |
166 if (level == ssl_encryption_early_data) { | |
167 c->quic->state = NGX_QUIC_ST_EARLY_DATA; | |
168 } | |
169 | |
162 return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, | 170 return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, |
163 rsecret, secret_len, | 171 rsecret, secret_len, |
164 &c->quic->secrets.client); | 172 &c->quic->secrets.client); |
165 } | 173 } |
166 | 174 |
202 if (rc != 1) { | 210 if (rc != 1) { |
203 return rc; | 211 return rc; |
204 } | 212 } |
205 | 213 |
206 if (level == ssl_encryption_early_data) { | 214 if (level == ssl_encryption_early_data) { |
215 c->quic->state = NGX_QUIC_ST_EARLY_DATA; | |
207 return 1; | 216 return 1; |
208 } | 217 } |
209 | 218 |
210 ngx_quic_hexdump(c->log, "level:%d write", wsecret, secret_len, level); | 219 ngx_quic_hexdump(c->log, "level:%d write", wsecret, secret_len, level); |
211 | 220 |
350 pkt.log = c->log; | 359 pkt.log = c->log; |
351 pkt.raw = b; | 360 pkt.raw = b; |
352 pkt.data = b->start; | 361 pkt.data = b->start; |
353 pkt.len = b->last - b->start; | 362 pkt.len = b->last - b->start; |
354 | 363 |
355 if (ngx_quic_new_connection(c, ssl, tp, &pkt) != NGX_OK) { | 364 if (ngx_quic_new_connection(c, ssl, tp, &pkt, handler) != NGX_OK) { |
356 ngx_quic_close_connection(c); | 365 ngx_quic_close_connection(c); |
357 return; | 366 return; |
358 } | 367 } |
359 | 368 |
360 // we don't need stream handler for initial packet processing | |
361 c->quic->streams.handler = handler; | |
362 | |
363 ngx_add_timer(c->read, c->quic->tp.max_idle_timeout); | 369 ngx_add_timer(c->read, c->quic->tp.max_idle_timeout); |
364 | 370 |
365 c->read->handler = ngx_quic_input_handler; | 371 c->read->handler = ngx_quic_input_handler; |
366 | 372 |
367 return; | 373 return; |
368 } | 374 } |
369 | 375 |
370 | 376 |
371 static ngx_int_t | 377 static ngx_int_t |
372 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp, | 378 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp, |
373 ngx_quic_header_t *pkt) | 379 ngx_quic_header_t *pkt, ngx_connection_handler_pt handler) |
374 { | 380 { |
375 ngx_quic_tp_t *ctp; | 381 ngx_quic_tp_t *ctp; |
376 ngx_quic_connection_t *qc; | 382 ngx_quic_connection_t *qc; |
377 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; | 383 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; |
378 | 384 |
408 ngx_quic_rbtree_insert_stream); | 414 ngx_quic_rbtree_insert_stream); |
409 | 415 |
410 c->quic = qc; | 416 c->quic = qc; |
411 qc->ssl = ssl; | 417 qc->ssl = ssl; |
412 qc->tp = *tp; | 418 qc->tp = *tp; |
419 qc->streams.handler = handler; | |
413 | 420 |
414 ctp = &qc->ctp; | 421 ctp = &qc->ctp; |
415 ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE; | 422 ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE; |
416 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; | 423 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; |
417 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; | 424 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; |
454 | 461 |
455 if (ngx_quic_init_connection(c) != NGX_OK) { | 462 if (ngx_quic_init_connection(c) != NGX_OK) { |
456 return NGX_ERROR; | 463 return NGX_ERROR; |
457 } | 464 } |
458 | 465 |
459 return ngx_quic_payload_handler(c, pkt); | 466 if (ngx_quic_payload_handler(c, pkt) != NGX_OK) { |
467 return NGX_ERROR; | |
468 } | |
469 | |
470 /* pos is at header end, adjust by actual packet length */ | |
471 pkt->raw->pos += pkt->len; | |
472 | |
473 return ngx_quic_input(c, pkt->raw); | |
460 } | 474 } |
461 | 475 |
462 | 476 |
463 static ngx_int_t | 477 static ngx_int_t |
464 ngx_quic_init_connection(ngx_connection_t *c) | 478 ngx_quic_init_connection(ngx_connection_t *c) |
480 if (SSL_set_quic_method(ssl_conn, &quic_method) == 0) { | 494 if (SSL_set_quic_method(ssl_conn, &quic_method) == 0) { |
481 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 495 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
482 "SSL_set_quic_method() failed"); | 496 "SSL_set_quic_method() failed"); |
483 return NGX_ERROR; | 497 return NGX_ERROR; |
484 } | 498 } |
499 | |
500 #ifdef SSL_READ_EARLY_DATA_SUCCESS | |
501 if (SSL_CTX_get_max_early_data(qc->ssl->ctx)) { | |
502 SSL_set_quic_early_data_enabled(ssl_conn, 1); | |
503 } | |
504 #endif | |
485 | 505 |
486 len = ngx_quic_create_transport_params(NULL, NULL, &qc->tp); | 506 len = ngx_quic_create_transport_params(NULL, NULL, &qc->tp); |
487 /* always succeeds */ | 507 /* always succeeds */ |
488 | 508 |
489 p = ngx_pnalloc(c->pool, len); | 509 p = ngx_pnalloc(c->pool, len); |
664 { | 684 { |
665 u_char *p; | 685 u_char *p; |
666 ngx_int_t rc; | 686 ngx_int_t rc; |
667 ngx_quic_header_t pkt; | 687 ngx_quic_header_t pkt; |
668 | 688 |
669 p = b->start; | 689 p = b->pos; |
670 | 690 |
671 do { | 691 while (p < b->last) { |
672 c->log->action = "processing quic packet"; | 692 c->log->action = "processing quic packet"; |
673 | 693 |
674 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | 694 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); |
675 pkt.raw = b; | 695 pkt.raw = b; |
676 pkt.data = p; | 696 pkt.data = p; |
691 rc = ngx_quic_initial_input(c, &pkt); | 711 rc = ngx_quic_initial_input(c, &pkt); |
692 | 712 |
693 } else if (ngx_quic_pkt_hs(pkt.flags)) { | 713 } else if (ngx_quic_pkt_hs(pkt.flags)) { |
694 rc = ngx_quic_handshake_input(c, &pkt); | 714 rc = ngx_quic_handshake_input(c, &pkt); |
695 | 715 |
716 } else if (ngx_quic_pkt_zrtt(pkt.flags)) { | |
717 rc = ngx_quic_early_input(c, &pkt); | |
718 | |
696 } else { | 719 } else { |
697 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 720 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
698 "BUG: unknown quic state"); | 721 "BUG: unknown quic state"); |
699 return NGX_ERROR; | 722 return NGX_ERROR; |
700 } | 723 } |
708 } | 731 } |
709 | 732 |
710 /* b->pos is at header end, adjust by actual packet length */ | 733 /* b->pos is at header end, adjust by actual packet length */ |
711 p = b->pos + pkt.len; | 734 p = b->pos + pkt.len; |
712 b->pos = p; /* reset b->pos to the next packet start */ | 735 b->pos = p; /* reset b->pos to the next packet start */ |
713 | 736 } |
714 } while (p < b->last); | |
715 | 737 |
716 return NGX_OK; | 738 return NGX_OK; |
717 } | 739 } |
718 | 740 |
719 | 741 |
794 return NGX_ERROR; | 816 return NGX_ERROR; |
795 } | 817 } |
796 | 818 |
797 pkt->secret = &qc->secrets.client.hs; | 819 pkt->secret = &qc->secrets.client.hs; |
798 pkt->level = ssl_encryption_handshake; | 820 pkt->level = ssl_encryption_handshake; |
821 pkt->plaintext = buf; | |
822 | |
823 if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) { | |
824 return NGX_ERROR; | |
825 } | |
826 | |
827 return ngx_quic_payload_handler(c, pkt); | |
828 } | |
829 | |
830 | |
831 static ngx_int_t | |
832 ngx_quic_early_input(ngx_connection_t *c, ngx_quic_header_t *pkt) | |
833 { | |
834 ngx_quic_connection_t *qc; | |
835 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; | |
836 | |
837 c->log->action = "processing early data quic packet"; | |
838 | |
839 qc = c->quic; | |
840 | |
841 /* extract cleartext data into pkt */ | |
842 if (ngx_quic_parse_long_header(pkt) != NGX_OK) { | |
843 return NGX_ERROR; | |
844 } | |
845 | |
846 if (pkt->dcid.len != qc->dcid.len) { | |
847 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); | |
848 return NGX_ERROR; | |
849 } | |
850 | |
851 if (ngx_memcmp(pkt->dcid.data, qc->dcid.data, qc->dcid.len) != 0) { | |
852 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); | |
853 return NGX_ERROR; | |
854 } | |
855 | |
856 if (pkt->scid.len != qc->scid.len) { | |
857 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl"); | |
858 return NGX_ERROR; | |
859 } | |
860 | |
861 if (ngx_memcmp(pkt->scid.data, qc->scid.data, qc->scid.len) != 0) { | |
862 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid"); | |
863 return NGX_ERROR; | |
864 } | |
865 | |
866 if (!ngx_quic_pkt_zrtt(pkt->flags)) { | |
867 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
868 "invalid packet type: 0x%xi", pkt->flags); | |
869 return NGX_ERROR; | |
870 } | |
871 | |
872 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) { | |
873 return NGX_ERROR; | |
874 } | |
875 | |
876 if (c->quic->state != NGX_QUIC_ST_EARLY_DATA) { | |
877 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected 0-RTT packet"); | |
878 return NGX_OK; | |
879 } | |
880 | |
881 pkt->secret = &qc->secrets.client.ed; | |
882 pkt->level = ssl_encryption_early_data; | |
799 pkt->plaintext = buf; | 883 pkt->plaintext = buf; |
800 | 884 |
801 if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) { | 885 if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) { |
802 return NGX_ERROR; | 886 return NGX_ERROR; |
803 } | 887 } |
998 ack_frame = ngx_quic_alloc_frame(c, 0); | 1082 ack_frame = ngx_quic_alloc_frame(c, 0); |
999 if (ack_frame == NULL) { | 1083 if (ack_frame == NULL) { |
1000 return NGX_ERROR; | 1084 return NGX_ERROR; |
1001 } | 1085 } |
1002 | 1086 |
1003 ack_frame->level = pkt->level; | 1087 ack_frame->level = (pkt->level == ssl_encryption_early_data) |
1088 ? ssl_encryption_application | |
1089 : pkt->level; | |
1004 ack_frame->type = NGX_QUIC_FT_ACK; | 1090 ack_frame->type = NGX_QUIC_FT_ACK; |
1005 ack_frame->u.ack.pn = pkt->pn; | 1091 ack_frame->u.ack.pn = pkt->pn; |
1006 | 1092 |
1007 ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, pkt->level); | 1093 ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, pkt->level); |
1008 ngx_quic_queue_frame(qc, ack_frame); | 1094 ngx_quic_queue_frame(qc, ack_frame); |