comparison src/event/ngx_event_quic.c @ 8182:b28ea685a56e quic

Moved all QUIC code into ngx_event_quic.c Introduced ngx_quic_input() and ngx_quic_output() as interface between nginx and protocol. They are the only functions that are exported. While there, added copyrights.
author Vladimir Homutov <vl@nginx.com>
date Fri, 28 Feb 2020 16:23:25 +0300
parents 01dc595de244
children 6091506af0f7
comparison
equal deleted inserted replaced
8181:3cb4f16426a5 8182:b28ea685a56e
1
2 /*
3 * Copyright (C) Nginx, Inc.
4 */
5
6
1 #include <ngx_config.h> 7 #include <ngx_config.h>
2 #include <ngx_core.h> 8 #include <ngx_core.h>
3 #include <ngx_event.h> 9
10
11 #define quic_version 0xff000018
12
13
14 #if (NGX_HAVE_NONALIGNED)
15
16 #define ngx_quic_parse_uint16(p) ntohs(*(uint16_t *) (p))
17 #define ngx_quic_parse_uint32(p) ntohl(*(uint32_t *) (p))
18
19 #define ngx_quic_write_uint16 ngx_quic_write_uint16_aligned
20 #define ngx_quic_write_uint32 ngx_quic_write_uint32_aligned
21
22 #else
23
24 #define ngx_quic_parse_uint16(p) ((p)[0] << 8 | (p)[1])
25 #define ngx_quic_parse_uint32(p) \
26 ((uint32_t) (p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3])
27
28 #define ngx_quic_write_uint16(p, s) \
29 ((p)[0] = (u_char) ((s) >> 8), \
30 (p)[1] = (u_char) (s), \
31 (p) + sizeof(uint16_t))
32
33 #define ngx_quic_write_uint32(p, s) \
34 ((p)[0] = (u_char) ((s) >> 24), \
35 (p)[1] = (u_char) ((s) >> 16), \
36 (p)[2] = (u_char) ((s) >> 8), \
37 (p)[3] = (u_char) (s), \
38 (p) + sizeof(uint32_t))
39
40 #endif
41
42
43 #define ngx_quic_write_uint16_aligned(p, s) \
44 (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t))
45
46 #define ngx_quic_write_uint32_aligned(p, s) \
47 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t))
48
49
50 /* TODO: real states, these are stubs */
51 typedef enum {
52 NGX_QUIC_ST_INITIAL,
53 NGX_QUIC_ST_HANDSHAKE,
54 NGX_QUIC_ST_APP_DATA
55 } ngx_quic_state_t;
56
57
58 typedef struct {
59 ngx_str_t secret;
60 ngx_str_t key;
61 ngx_str_t iv;
62 ngx_str_t hp;
63 } ngx_quic_secret_t;
64
65
66 struct ngx_quic_connection_s {
67
68 ngx_quic_state_t state;
69 ngx_ssl_t *ssl;
70
71 ngx_str_t out; // stub for some kind of output queue
72
73 ngx_str_t scid;
74 ngx_str_t dcid;
75 ngx_str_t token;
76
77 ngx_quic_secret_t client_in;
78 ngx_quic_secret_t client_hs;
79 ngx_quic_secret_t client_ad;
80 ngx_quic_secret_t server_in;
81 ngx_quic_secret_t server_hs;
82 ngx_quic_secret_t server_ad;
83 };
84
85
86 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
87 ngx_buf_t *b);
88 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *b);
89
90 static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
91 enum ssl_encryption_level_t level, const uint8_t *read_secret,
92 const uint8_t *write_secret, size_t secret_len);
93 static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
94 enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
95 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
96 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
97 enum ssl_encryption_level_t level, uint8_t alert);
98
99 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask);
100 static uint64_t ngx_quic_parse_int(u_char **pos);
101 static void ngx_quic_build_int(u_char **pos, uint64_t value);
102
103 static ngx_int_t ngx_hkdf_extract(u_char *out_key, size_t *out_len,
104 const EVP_MD *digest, const u_char *secret, size_t secret_len,
105 const u_char *salt, size_t salt_len);
106 static ngx_int_t ngx_hkdf_expand(u_char *out_key, size_t out_len,
107 const EVP_MD *digest, const u_char *prk, size_t prk_len,
108 const u_char *info, size_t info_len);
109
110 static ngx_int_t ngx_quic_hkdf_expand(ngx_connection_t *c, const EVP_MD *digest,
111 ngx_str_t *out, ngx_str_t *label, const uint8_t *prk, size_t prk_len);
112
113 static ngx_int_t ngx_quic_tls_open(ngx_connection_t *c,
114 const EVP_CIPHER *cipher, ngx_quic_secret_t *s, ngx_str_t *out,
115 u_char *nonce, ngx_str_t *in, ngx_str_t *ad);
116 static ngx_int_t ngx_quic_tls_seal(ngx_connection_t *c,
117 const EVP_CIPHER *cipher, ngx_quic_secret_t *s, ngx_str_t *out,
118 u_char *nonce, ngx_str_t *in, ngx_str_t *ad);
119
120 static ngx_int_t ngx_quic_tls_hp(ngx_connection_t *c, const EVP_CIPHER *cipher,
121 ngx_quic_secret_t *s, u_char *out, u_char *in);
122
123
124 static SSL_QUIC_METHOD quic_method = {
125 ngx_quic_set_encryption_secrets,
126 ngx_quic_add_handshake_data,
127 ngx_quic_flush_flight,
128 ngx_quic_send_alert,
129 };
130
131
132 void
133 ngx_quic_init_ssl_methods(SSL_CTX* ctx)
134 {
135 SSL_CTX_set_quic_method(ctx, &quic_method);
136 }
137
138
139 ngx_int_t
140 ngx_quic_input(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b)
141 {
142 if (c->quic == NULL) {
143 return ngx_quic_new_connection(c, ssl, b); //TODO: change state by results
144 }
145
146 switch (c->quic->state) {
147 case NGX_QUIC_ST_INITIAL:
148 case NGX_QUIC_ST_HANDSHAKE:
149 return ngx_quic_handshake_input(c, b);
150 default:
151 /* application data */
152 break;
153 }
154
155 return NGX_OK;
156 }
157
158
159 ngx_int_t
160 ngx_quic_output(ngx_connection_t *c)
161 {
162 /* stub for processing output queue */
163
164 if (c->quic->out.data) {
165 c->send(c, c->quic->out.data, c->quic->out.len);
166 c->quic->out.data = NULL;
167 }
168
169 return NGX_OK;
170 }
171
172
173 static int
174 ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
175 enum ssl_encryption_level_t level, const uint8_t *read_secret,
176 const uint8_t *write_secret, size_t secret_len)
177 {
178 u_char *name;
179 ngx_uint_t i;
180 const EVP_MD *digest;
181 const EVP_CIPHER *cipher;
182 ngx_connection_t *c;
183 ngx_quic_secret_t *client, *server;
184
185 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
186
187 //ngx_ssl_handshake_log(c); // TODO: enable again
188
189 #if (NGX_DEBUG)
190 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
191 u_char buf[64];
192 size_t m;
193
194 m = ngx_hex_dump(buf, (u_char *) read_secret, secret_len) - buf;
195 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
196 "set_encryption_secrets: read %*s, len: %uz, level:%d",
197 m, buf, secret_len, (int) level);
198
199 m = ngx_hex_dump(buf, (u_char *) write_secret, secret_len) - buf;
200 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
201 "set_encryption_secrets: write %*s, len: %uz, level:%d",
202 m, buf, secret_len, (int) level);
203 }
204 #endif
205
206 name = (u_char *) SSL_get_cipher(ssl_conn);
207
208 if (ngx_strcasecmp(name, (u_char *) "TLS_AES_128_GCM_SHA256") == 0
209 || ngx_strcasecmp(name, (u_char *) "(NONE)") == 0)
210 {
211 cipher = EVP_aes_128_gcm();
212 digest = EVP_sha256();
213
214 } else if (ngx_strcasecmp(name, (u_char *) "TLS_AES_256_GCM_SHA384") == 0) {
215 cipher = EVP_aes_256_gcm();
216 digest = EVP_sha384();
217
218 } else {
219 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "unexpected cipher");
220 return 0;
221 }
222
223 switch (level) {
224
225 case ssl_encryption_handshake:
226 client = &c->quic->client_hs;
227 server = &c->quic->server_hs;
228
229 break;
230
231 case ssl_encryption_application:
232 client = &c->quic->client_ad;
233 server = &c->quic->server_ad;
234
235 break;
236
237 default:
238 return 0;
239 }
240
241 client->key.len = EVP_CIPHER_key_length(cipher);
242 server->key.len = EVP_CIPHER_key_length(cipher);
243
244 client->iv.len = EVP_CIPHER_iv_length(cipher);
245 server->iv.len = EVP_CIPHER_iv_length(cipher);
246
247 client->hp.len = EVP_CIPHER_key_length(cipher);
248 server->hp.len = EVP_CIPHER_key_length(cipher);
249
250 struct {
251 ngx_str_t label;
252 ngx_str_t *key;
253 const uint8_t *secret;
254 } seq[] = {
255 { ngx_string("tls13 quic key"), &client->key, read_secret },
256 { ngx_string("tls13 quic iv"), &client->iv, read_secret },
257 { ngx_string("tls13 quic hp"), &client->hp, read_secret },
258 { ngx_string("tls13 quic key"), &server->key, write_secret },
259 { ngx_string("tls13 quic iv"), &server->iv, write_secret },
260 { ngx_string("tls13 quic hp"), &server->hp, write_secret },
261 };
262
263 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
264
265 if (ngx_quic_hkdf_expand(c, digest, seq[i].key, &seq[i].label,
266 seq[i].secret, secret_len)
267 != NGX_OK)
268 {
269 return 0;
270 }
271 }
272
273 return 1;
274 }
275
276
277 static int
278 ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
279 enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
280 {
281 u_char *p, *pnp, *name, *nonce, *sample;
282 ngx_int_t m;
283 ngx_str_t in, out, ad;
284 static int pn;
285 const EVP_CIPHER *cipher;
286 ngx_connection_t *c;
287 ngx_quic_secret_t *secret;
288 ngx_quic_connection_t *qc;
289 u_char buf[2048], mask[16];
290
291 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
292 qc = c->quic;
293
294 //ngx_ssl_handshake_log(c); // TODO: enable again
295
296 switch (level) {
297
298 case ssl_encryption_initial:
299 secret = &qc->server_in;
300 break;
301
302 case ssl_encryption_handshake:
303 secret = &qc->server_hs;
304 break;
305
306 default:
307 return 0;
308 }
309
310 m = ngx_hex_dump(buf, (u_char *) data, ngx_min(len, 1024)) - buf;
311 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
312 "ngx_quic_add_handshake_data: %*s%s, len: %uz, level:%d",
313 m, buf, len < 2048 ? "" : "...", len, (int) level);
314
315 in.data = ngx_alloc(4 + len + 5 /*minimal ACK*/, c->log);
316 if (in.data == 0) {
317 return 0;
318 }
319
320 p = in.data;
321 ngx_quic_build_int(&p, 6); // crypto frame
322 ngx_quic_build_int(&p, 0);
323 ngx_quic_build_int(&p, len);
324 p = ngx_cpymem(p, data, len);
325
326 if (level == ssl_encryption_initial) {
327 ngx_quic_build_int(&p, 2); // ack frame
328 ngx_quic_build_int(&p, 0);
329 ngx_quic_build_int(&p, 0);
330 ngx_quic_build_int(&p, 0);
331 ngx_quic_build_int(&p, 0);
332 }
333
334 in.len = p - in.data;
335 out.len = in.len + EVP_GCM_TLS_TAG_LEN;
336
337 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
338 "ngx_quic_add_handshake_data: clear_len:%uz, ciphertext_len:%uz",
339 in.len, out.len);
340
341 ad.data = ngx_alloc(346 /*max header*/, c->log);
342 if (ad.data == 0) {
343 return 0;
344 }
345
346 p = ad.data;
347 if (level == ssl_encryption_initial) {
348 *p++ = 0xc0; // initial, packet number len
349 } else if (level == ssl_encryption_handshake) {
350 *p++ = 0xe0; // handshake, packet number len
351 }
352 p = ngx_quic_write_uint32(p, quic_version);
353 *p++ = qc->scid.len;
354 p = ngx_cpymem(p, qc->scid.data, qc->scid.len);
355 *p++ = qc->dcid.len;
356 p = ngx_cpymem(p, qc->dcid.data, qc->dcid.len);
357 if (level == ssl_encryption_initial) {
358 ngx_quic_build_int(&p, 0); // token length
359 }
360 ngx_quic_build_int(&p, out.len + 1); // length (inc. pnl)
361 pnp = p;
362
363 if (level == ssl_encryption_initial) {
364 *p++ = 0; // packet number 0
365
366 } else if (level == ssl_encryption_handshake) {
367 *p++ = pn++;
368 }
369
370 ad.len = p - ad.data;
371
372 m = ngx_hex_dump(buf, ad.data, ad.len) - buf;
373 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
374 "ngx_quic_add_handshake_data ad: %*s, len: %uz",
375 m, buf, ad.len);
376
377
378 name = (u_char *) SSL_get_cipher(ssl_conn);
379
380 if (ngx_strcasecmp(name, (u_char *) "TLS_AES_128_GCM_SHA256") == 0
381 || ngx_strcasecmp(name, (u_char *) "(NONE)") == 0)
382 {
383 cipher = EVP_aes_128_gcm();
384
385 } else if (ngx_strcasecmp(name, (u_char *) "TLS_AES_256_GCM_SHA384") == 0) {
386 cipher = EVP_aes_256_gcm();
387
388 } else {
389 return 0;
390 }
391
392 nonce = ngx_pstrdup(c->pool, &secret->iv);
393 if (level == ssl_encryption_handshake) {
394 nonce[11] ^= (pn - 1);
395 }
396
397 m = ngx_hex_dump(buf, (u_char *) secret->iv.data, 12) - buf;
398 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
399 "ngx_quic_add_handshake_data sample: server_iv %*s",
400 m, buf);
401 m = ngx_hex_dump(buf, (u_char *) nonce, 12) - buf;
402 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
403 "ngx_quic_add_handshake_data sample: n=%d nonce %*s",
404 pn - 1, m, buf);
405
406 if (ngx_quic_tls_seal(c, cipher, secret, &out, nonce, &in, &ad) != NGX_OK)
407 {
408 return 0;
409 }
410
411 sample = &out.data[3]; // pnl=0
412 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), secret, mask, sample) != NGX_OK) {
413 return 0;
414 }
415
416 m = ngx_hex_dump(buf, (u_char *) sample, 16) - buf;
417 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
418 "ngx_quic_add_handshake_data sample: %*s, len: %uz",
419 m, buf, 16);
420
421 m = ngx_hex_dump(buf, (u_char *) mask, 16) - buf;
422 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
423 "ngx_quic_add_handshake_data mask: %*s, len: %uz",
424 m, buf, 16);
425
426 m = ngx_hex_dump(buf, (u_char *) secret->hp.data, 16) - buf;
427 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
428 "ngx_quic_add_handshake_data hp_key: %*s, len: %uz",
429 m, buf, 16);
430
431 // header protection, pnl = 0
432 ad.data[0] ^= mask[0] & 0x0f;
433 *pnp ^= mask[1];
434
435 u_char *packet = ngx_alloc(ad.len + out.len, c->log);
436 if (packet == 0) {
437 return 0;
438 }
439
440 p = ngx_cpymem(packet, ad.data, ad.len);
441 p = ngx_cpymem(p, out.data, out.len);
442
443 m = ngx_hex_dump(buf, (u_char *) packet, ngx_min(1024, p - packet)) - buf;
444 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
445 "ngx_quic_add_handshake_data packet: %*s%s, len: %uz",
446 m, buf, len < 2048 ? "" : "...", p - packet);
447
448 // TODO: save state of data to send into qc (push into queue)
449
450 qc->out.data = packet;
451 qc->out.len = p - packet;
452
453 if (ngx_quic_output(c) != NGX_OK) {
454 return 0;
455 }
456
457 return 1;
458 }
459
460
461 static int
462 ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
463 {
464 ngx_connection_t *c;
465
466 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
467
468 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ngx_quic_flush_flight()");
469
470 return 1;
471 }
472
473
474 static int
475 ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
476 uint8_t alert)
477 {
478 ngx_connection_t *c;
479
480 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
481
482 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
483 "ngx_quic_send_alert(), lvl=%d, alert=%d",
484 (int) level, (int) alert);
485
486 return 1;
487 }
488
489
490 static ngx_int_t
491 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b)
492 {
493 int n, sslerr;
494 #if (NGX_DEBUG)
495 u_char buf[512];
496 size_t m;
497 #endif
498
499 ngx_quic_connection_t *qc;
500
501 if ((b->pos[0] & 0xf0) != 0xc0) {
502 ngx_log_error(NGX_LOG_INFO, c->log, 0, "invalid initial packet");
503 return NGX_ERROR;
504 }
505
506 if (ngx_buf_size(b) < 1200) {
507 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
508 return NGX_ERROR;
509 }
510
511 ngx_int_t flags = *b->pos++;
512 uint32_t version = ngx_quic_parse_uint32(b->pos);
513 b->pos += sizeof(uint32_t);
514
515 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
516 "quic flags:%xi version:%xD", flags, version);
517
518 if (version != quic_version) {
519 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unsupported quic version");
520 return NGX_ERROR;
521 }
522
523 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
524 if (qc == NULL) {
525 return NGX_ERROR;
526 }
527
528 c->quic = qc;
529
530 qc->dcid.len = *b->pos++;
531 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len);
532 if (qc->dcid.data == NULL) {
533 return NGX_ERROR;
534 }
535
536 ngx_memcpy(qc->dcid.data, b->pos, qc->dcid.len);
537 b->pos += qc->dcid.len;
538
539 qc->scid.len = *b->pos++;
540 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len);
541 if (qc->scid.data == NULL) {
542 return NGX_ERROR;
543 }
544
545 ngx_memcpy(qc->scid.data, b->pos, qc->scid.len);
546 b->pos += qc->scid.len;
547
548 qc->token.len = ngx_quic_parse_int(&b->pos);
549 qc->token.data = ngx_pnalloc(c->pool, qc->token.len);
550 if (qc->token.data == NULL) {
551 return NGX_ERROR;
552 }
553
554 ngx_memcpy(qc->token.data, b->pos, qc->token.len);
555 b->pos += qc->token.len;
556
557 ngx_int_t plen = ngx_quic_parse_int(&b->pos);
558
559 if (plen > b->last - b->pos) {
560 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet");
561 return NGX_ERROR;
562 }
563
564 /* draft-ietf-quic-tls-23#section-5.4.2:
565 * the Packet Number field is assumed to be 4 bytes long
566 * draft-ietf-quic-tls-23#section-5.4.[34]:
567 * AES-Based and ChaCha20-Based header protections sample 16 bytes
568 */
569 u_char *sample = b->pos + 4;
570
571 #if (NGX_DEBUG)
572 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
573 m = ngx_hex_dump(buf, qc->dcid.data, qc->dcid.len) - buf;
574 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
575 "quic DCID: %*s, len: %uz", m, buf, qc->dcid.len);
576
577 m = ngx_hex_dump(buf, qc->scid.data, qc->scid.len) - buf;
578 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
579 "quic SCID: %*s, len: %uz", m, buf, qc->scid.len);
580
581 m = ngx_hex_dump(buf, qc->token.data, qc->token.len) - buf;
582 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
583 "quic token: %*s, len: %uz", m, buf, qc->token.len);
584
585 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
586 "quic packet length: %d", plen);
587
588 m = ngx_hex_dump(buf, sample, 16) - buf;
589 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
590 "quic sample: %*s", m, buf);
591 }
592 #endif
593
594 // initial secret
595
596 size_t is_len;
597 uint8_t is[SHA256_DIGEST_LENGTH];
598 ngx_uint_t i;
599 const EVP_MD *digest;
600 const EVP_CIPHER *cipher;
601 static const uint8_t salt[20] =
602 "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7"
603 "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02";
604
605 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */
606
607 cipher = EVP_aes_128_gcm();
608 digest = EVP_sha256();
609
610 if (ngx_hkdf_extract(is, &is_len, digest, qc->dcid.data, qc->dcid.len,
611 salt, sizeof(salt))
612 != NGX_OK)
613 {
614 return NGX_ERROR;
615 }
616
617 ngx_str_t iss = {
618 .data = is,
619 .len = is_len
620 };
621
622 #if (NGX_DEBUG)
623 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
624 m = ngx_hex_dump(buf, (uint8_t *) salt, sizeof(salt)) - buf;
625 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
626 "quic salt: %*s, len: %uz", m, buf, sizeof(salt));
627
628 m = ngx_hex_dump(buf, is, is_len) - buf;
629 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
630 "quic initial secret: %*s, len: %uz", m, buf, is_len);
631 }
632 #endif
633
634 /* draft-ietf-quic-tls-23#section-5.2 */
635 qc->client_in.secret.len = SHA256_DIGEST_LENGTH;
636 qc->server_in.secret.len = SHA256_DIGEST_LENGTH;
637
638 qc->client_in.key.len = EVP_CIPHER_key_length(cipher);
639 qc->server_in.key.len = EVP_CIPHER_key_length(cipher);
640
641 qc->client_in.hp.len = EVP_CIPHER_key_length(cipher);
642 qc->server_in.hp.len = EVP_CIPHER_key_length(cipher);
643
644 qc->client_in.iv.len = EVP_CIPHER_iv_length(cipher);
645 qc->server_in.iv.len = EVP_CIPHER_iv_length(cipher);
646
647 struct {
648 ngx_str_t label;
649 ngx_str_t *key;
650 ngx_str_t *prk;
651 } seq[] = {
652
653 /* draft-ietf-quic-tls-23#section-5.2 */
654 { ngx_string("tls13 client in"), &qc->client_in.secret, &iss },
655 {
656 ngx_string("tls13 quic key"),
657 &qc->client_in.key,
658 &qc->client_in.secret,
659 },
660 {
661 ngx_string("tls13 quic iv"),
662 &qc->client_in.iv,
663 &qc->client_in.secret,
664 },
665 {
666 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.4.1 */
667 ngx_string("tls13 quic hp"),
668 &qc->client_in.hp,
669 &qc->client_in.secret,
670 },
671 { ngx_string("tls13 server in"), &qc->server_in.secret, &iss },
672 {
673 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */
674 ngx_string("tls13 quic key"),
675 &qc->server_in.key,
676 &qc->server_in.secret,
677 },
678 {
679 ngx_string("tls13 quic iv"),
680 &qc->server_in.iv,
681 &qc->server_in.secret,
682 },
683 {
684 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.4.1 */
685 ngx_string("tls13 quic hp"),
686 &qc->server_in.hp,
687 &qc->server_in.secret,
688 },
689
690 };
691
692 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
693
694 if (ngx_quic_hkdf_expand(c, digest, seq[i].key, &seq[i].label,
695 seq[i].prk->data, seq[i].prk->len)
696 != NGX_OK)
697 {
698 return NGX_ERROR;
699 }
700 }
701
702 // header protection
703
704 uint8_t mask[16];
705 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), &qc->client_in, mask, sample)
706 != NGX_OK)
707 {
708 return NGX_ERROR;
709 }
710
711 u_char clearflags = flags ^ (mask[0] & 0x0f);
712 ngx_int_t pnl = (clearflags & 0x03) + 1;
713 uint64_t pn = ngx_quic_parse_pn(&b->pos, pnl, &mask[1]);
714
715 #if (NGX_DEBUG)
716 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
717 m = ngx_hex_dump(buf, sample, 16) - buf;
718 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
719 "quic sample: %*s", m, buf);
720
721 m = ngx_hex_dump(buf, mask, 5) - buf;
722 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
723 "quic mask: %*s", m, buf);
724
725 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
726 "quic packet number: %uL, len: %xi", pn, pnl);
727 }
728 #endif
729
730 // packet protection
731
732 ngx_str_t in;
733 in.data = b->pos;
734 in.len = plen - pnl;
735
736 ngx_str_t ad;
737 ad.len = b->pos - b->start;
738 ad.data = ngx_pnalloc(c->pool, ad.len);
739 if (ad.data == NULL) {
740 return NGX_ERROR;
741 }
742
743 ngx_memcpy(ad.data, b->start, ad.len);
744 ad.data[0] = clearflags;
745 ad.data[ad.len - pnl] = (u_char)pn;
746
747 uint8_t *nonce = ngx_pstrdup(c->pool, &qc->client_in.iv);
748 nonce[11] ^= pn;
749
750 #if (NGX_DEBUG)
751 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
752 m = ngx_hex_dump(buf, nonce, 12) - buf;
753 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
754 "quic nonce: %*s, len: %uz", m, buf, 12);
755
756 m = ngx_hex_dump(buf, ad.data, ad.len) - buf;
757 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
758 "quic ad: %*s, len: %uz", m, buf, ad.len);
759 }
760 #endif
761
762 ngx_str_t out;
763
764 if (ngx_quic_tls_open(c, EVP_aes_128_gcm(), &qc->client_in, &out, nonce,
765 &in, &ad)
766 != NGX_OK)
767 {
768 return NGX_ERROR;
769 }
770
771 #if (NGX_DEBUG)
772 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
773 m = ngx_hex_dump(buf, out.data, ngx_min(out.len, 256)) - buf;
774 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
775 "quic packet payload: %*s%s, len: %uz",
776 m, buf, m < 512 ? "" : "...", out.len);
777 }
778 #endif
779
780 if (out.data[0] != 0x06) {
781 ngx_log_error(NGX_LOG_INFO, c->log, 0,
782 "unexpected frame in initial packet");
783 return NGX_ERROR;
784 }
785
786 if (out.data[1] != 0x00) {
787 ngx_log_error(NGX_LOG_INFO, c->log, 0,
788 "unexpected CRYPTO offset in initial packet");
789 return NGX_ERROR;
790 }
791
792 uint8_t *crypto = &out.data[2];
793 uint64_t crypto_len = ngx_quic_parse_int(&crypto);
794
795 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
796 "quic initial packet CRYPTO length: %uL pp:%p:%p",
797 crypto_len, out.data, crypto);
798
799 if (ngx_ssl_create_connection(ssl, c, NGX_SSL_BUFFER) != NGX_OK) {
800 return NGX_ERROR;
801 }
802
803 static const uint8_t params[12] = "\x00\x0a\x00\x3a\x00\x01\x00\x00\x09\x00\x01\x03";
804
805 if (SSL_set_quic_transport_params(c->ssl->connection, params,
806 sizeof(params)) == 0)
807 {
808 ngx_log_error(NGX_LOG_INFO, c->log, 0,
809 "SSL_set_quic_transport_params() failed");
810 return NGX_ERROR;
811 }
812
813 n = SSL_do_handshake(c->ssl->connection);
814
815 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
816
817 if (n == -1) {
818 sslerr = SSL_get_error(c->ssl->connection, n);
819
820 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
821 sslerr);
822 }
823
824 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
825 "SSL_quic_read_level: %d, SSL_quic_write_level: %d",
826 (int) SSL_quic_read_level(c->ssl->connection),
827 (int) SSL_quic_write_level(c->ssl->connection));
828
829 if (!SSL_provide_quic_data(c->ssl->connection,
830 SSL_quic_read_level(c->ssl->connection),
831 crypto, crypto_len))
832 {
833 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
834 "SSL_provide_quic_data() failed");
835 return NGX_ERROR;
836 }
837
838 n = SSL_do_handshake(c->ssl->connection);
839
840 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
841
842 if (n == -1) {
843 sslerr = SSL_get_error(c->ssl->connection, n);
844
845 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
846 sslerr);
847
848 if (sslerr == SSL_ERROR_SSL) {
849 ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
850 }
851 }
852
853 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
854 "SSL_quic_read_level: %d, SSL_quic_write_level: %d",
855 (int) SSL_quic_read_level(c->ssl->connection),
856 (int) SSL_quic_write_level(c->ssl->connection));
857
858 return NGX_OK;
859 }
860
861
862 static ngx_int_t
863 ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *bb)
864 {
865 size_t m;
866 ssize_t n;
867 ngx_str_t out;
868 const EVP_CIPHER *cipher;
869 ngx_quic_connection_t *qc;
870 u_char buf[4096], *p, *b;
871
872 qc = c->quic;
873
874 n = bb->last - bb->pos;
875 p = bb->pos;
876 b = bb->start;
877
878 m = ngx_hex_dump(buf, b, n) - buf;
879 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
880 "quic handshake handler: %*s, len: %uz", m, buf, n);
881
882 if ((p[0] & 0xf0) != 0xe0) {
883 ngx_log_error(NGX_LOG_INFO, c->log, 0, "invalid packet type");
884 return NGX_ERROR;
885 }
886
887 ngx_int_t flags = *p++;
888 uint32_t version = ngx_quic_parse_uint32(p);
889 p += sizeof(uint32_t);
890
891 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
892 "quic flags:%xi version:%xD", flags, version);
893
894 if (version != quic_version) {
895 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unsupported quic version");
896 return NGX_ERROR;
897 }
898
899 if (*p++ != qc->dcid.len) {
900 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl");
901 return NGX_ERROR;
902 }
903
904 if (ngx_memcmp(p, qc->dcid.data, qc->dcid.len) != 0) {
905 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid");
906 return NGX_ERROR;
907 }
908
909 p += qc->dcid.len;
910
911 if (*p++ != qc->scid.len) {
912 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl");
913 return NGX_ERROR;
914 }
915
916 if (ngx_memcmp(p, qc->scid.data, qc->scid.len) != 0) {
917 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid");
918 return NGX_ERROR;
919 }
920
921 p += qc->scid.len;
922
923 ngx_int_t plen = ngx_quic_parse_int(&p);
924
925 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
926 "quic packet length: %d", plen);
927
928 if (plen > b + n - p) {
929 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet");
930 return NGX_ERROR;
931 }
932
933 u_char *sample = p + 4;
934
935 m = ngx_hex_dump(buf, sample, 16) - buf;
936 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic sample: %*s", m, buf);
937
938 // header protection
939
940 uint8_t mask[16];
941 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), &qc->client_hs, mask, sample)
942 != NGX_OK)
943 {
944 return NGX_ERROR;
945 }
946
947 u_char clearflags = flags ^ (mask[0] & 0x0f);
948 ngx_int_t pnl = (clearflags & 0x03) + 1;
949 uint64_t pn = ngx_quic_parse_pn(&p, pnl, &mask[1]);
950
951 #if (NGX_DEBUG)
952 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
953 m = ngx_hex_dump(buf, mask, 5) - buf;
954 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
955 "quic mask: %*s", m, buf);
956 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
957 "quic clear flags: %xi", clearflags);
958 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
959 "quic packet number: %uL, len: %xi", pn, pnl);
960 }
961 #endif
962
963 // packet protection
964
965 ngx_str_t in;
966 in.data = p;
967 in.len = plen - pnl;
968
969 ngx_str_t ad;
970 ad.len = p - b;
971 ad.data = ngx_pnalloc(c->pool, ad.len);
972 if (ad.data == NULL) {
973 return NGX_ERROR;
974 }
975
976 ngx_memcpy(ad.data, b, ad.len);
977 ad.data[0] = clearflags;
978 ad.data[ad.len - pnl] = (u_char)pn;
979
980 uint8_t *nonce = ngx_pstrdup(c->pool, &qc->client_hs.iv);
981 nonce[11] ^= pn;
982
983 #if (NGX_DEBUG)
984 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
985 m = ngx_hex_dump(buf, nonce, 12) - buf;
986 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
987 "quic nonce: %*s, len: %uz", m, buf, 12);
988
989 m = ngx_hex_dump(buf, ad.data, ad.len) - buf;
990 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
991 "quic ad: %*s, len: %uz", m, buf, ad.len);
992 }
993 #endif
994
995 u_char *name = (u_char *) SSL_get_cipher(c->ssl->connection);
996 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
997 "quic ssl cipher: %s", name);
998
999 if (ngx_strcasecmp(name, (u_char *) "TLS_AES_128_GCM_SHA256") == 0
1000 || ngx_strcasecmp(name, (u_char *) "(NONE)") == 0)
1001 {
1002 cipher = EVP_aes_128_gcm();
1003
1004 } else if (ngx_strcasecmp(name, (u_char *) "TLS_AES_256_GCM_SHA384") == 0) {
1005 cipher = EVP_aes_256_gcm();
1006
1007 } else {
1008 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "unexpected cipher");
1009 return NGX_ERROR;
1010 }
1011
1012 if (ngx_quic_tls_open(c, cipher, &qc->client_hs, &out, nonce, &in, &ad)
1013 != NGX_OK)
1014 {
1015 return NGX_ERROR;
1016 }
1017
1018 #if (NGX_DEBUG)
1019 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
1020 m = ngx_hex_dump(buf, out.data, ngx_min(out.len, 256)) - buf;
1021 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
1022 "quic packet payload: %*s%s, len: %uz",
1023 m, buf, m < 512 ? "" : "...", out.len);
1024 }
1025 #endif
1026
1027 return NGX_OK;
1028 }
4 1029
5 1030
6 uint64_t 1031 uint64_t
7 ngx_quic_parse_int(u_char **pos) 1032 ngx_quic_parse_int(u_char **pos)
8 { 1033 {
51 *pos = p; 1076 *pos = p;
52 // return len2; 1077 // return len2;
53 } 1078 }
54 1079
55 1080
56 uint64_t 1081 static uint64_t
57 ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask) 1082 ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask)
58 { 1083 {
59 u_char *p; 1084 u_char *p;
60 uint64_t value; 1085 uint64_t value;
61 1086
69 *pos = p; 1094 *pos = p;
70 return value; 1095 return value;
71 } 1096 }
72 1097
73 1098
74 ngx_int_t 1099 static ngx_int_t
75 ngx_hkdf_extract(u_char *out_key, size_t *out_len, const EVP_MD *digest, 1100 ngx_hkdf_extract(u_char *out_key, size_t *out_len, const EVP_MD *digest,
76 const u_char *secret, size_t secret_len, const u_char *salt, 1101 const u_char *secret, size_t secret_len, const u_char *salt,
77 size_t salt_len) 1102 size_t salt_len)
78 { 1103 {
79 #ifdef OPENSSL_IS_BORINGSSL 1104 #ifdef OPENSSL_IS_BORINGSSL
117 1142
118 return NGX_OK; 1143 return NGX_OK;
119 } 1144 }
120 1145
121 1146
122 ngx_int_t 1147 static ngx_int_t
123 ngx_quic_hkdf_expand(ngx_connection_t *c, const EVP_MD *digest, ngx_str_t *out, 1148 ngx_quic_hkdf_expand(ngx_connection_t *c, const EVP_MD *digest, ngx_str_t *out,
124 ngx_str_t *label, const uint8_t *prk, size_t prk_len) 1149 ngx_str_t *label, const uint8_t *prk, size_t prk_len)
125 { 1150 {
126 uint8_t *p; 1151 uint8_t *p;
127 size_t info_len; 1152 size_t info_len;
166 1191
167 return NGX_OK; 1192 return NGX_OK;
168 } 1193 }
169 1194
170 1195
171 ngx_int_t 1196 static ngx_int_t
172 ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest, 1197 ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest,
173 const uint8_t *prk, size_t prk_len, const u_char *info, size_t info_len) 1198 const uint8_t *prk, size_t prk_len, const u_char *info, size_t info_len)
174 { 1199 {
175 #ifdef OPENSSL_IS_BORINGSSL 1200 #ifdef OPENSSL_IS_BORINGSSL
176 if (HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len) 1201 if (HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)
212 1237
213 return NGX_OK; 1238 return NGX_OK;
214 } 1239 }
215 1240
216 1241
217 ngx_int_t 1242 static ngx_int_t
218 ngx_quic_tls_open(ngx_connection_t *c, const EVP_CIPHER *cipher, 1243 ngx_quic_tls_open(ngx_connection_t *c, const EVP_CIPHER *cipher,
219 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in, 1244 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
220 ngx_str_t *ad) 1245 ngx_str_t *ad)
221 { 1246 {
222 out->len = in->len - EVP_GCM_TLS_TAG_LEN; 1247 out->len = in->len - EVP_GCM_TLS_TAG_LEN;
317 1342
318 return NGX_OK; 1343 return NGX_OK;
319 } 1344 }
320 1345
321 1346
322 ngx_int_t 1347 static ngx_int_t
323 ngx_quic_tls_seal(ngx_connection_t *c, const EVP_CIPHER *cipher, 1348 ngx_quic_tls_seal(ngx_connection_t *c, const EVP_CIPHER *cipher,
324 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in, 1349 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
325 ngx_str_t *ad) 1350 ngx_str_t *ad)
326 { 1351 {
327 out->len = in->len + EVP_GCM_TLS_TAG_LEN; 1352 out->len = in->len + EVP_GCM_TLS_TAG_LEN;
420 1445
421 return NGX_OK; 1446 return NGX_OK;
422 } 1447 }
423 1448
424 1449
425 ngx_int_t 1450 static ngx_int_t
426 ngx_quic_tls_hp(ngx_connection_t *c, const EVP_CIPHER *cipher, 1451 ngx_quic_tls_hp(ngx_connection_t *c, const EVP_CIPHER *cipher,
427 ngx_quic_secret_t *s, u_char *out, u_char *in) 1452 ngx_quic_secret_t *s, u_char *out, u_char *in)
428 { 1453 {
429 int outlen; 1454 int outlen;
430 EVP_CIPHER_CTX *ctx; 1455 EVP_CIPHER_CTX *ctx;