comparison src/event/ngx_event_quic.c @ 8304: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
8303:2ac03e80d013 8304: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);