Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_protection.c @ 9172:4ccb0d973206
QUIC: reusing crypto contexts for packet protection.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Fri, 20 Oct 2023 18:05:07 +0400 |
parents | f98636db77ef |
children | 904a54092d5b |
comparison
equal
deleted
inserted
replaced
9171:f98636db77ef | 9172:4ccb0d973206 |
---|---|
24 const u_char *salt, size_t salt_len); | 24 const u_char *salt, size_t salt_len); |
25 | 25 |
26 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask, | 26 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask, |
27 uint64_t *largest_pn); | 27 uint64_t *largest_pn); |
28 | 28 |
29 static ngx_int_t ngx_quic_crypto_open(const ngx_quic_cipher_t *cipher, | 29 static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, |
30 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in, | 30 u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log); |
31 ngx_str_t *ad, ngx_log_t *log); | |
32 static ngx_int_t ngx_quic_crypto_hp(ngx_log_t *log, const EVP_CIPHER *cipher, | 31 static ngx_int_t ngx_quic_crypto_hp(ngx_log_t *log, const EVP_CIPHER *cipher, |
33 ngx_quic_secret_t *s, u_char *out, u_char *in); | 32 ngx_quic_secret_t *s, u_char *out, u_char *in); |
34 | 33 |
35 static ngx_int_t ngx_quic_create_packet(ngx_quic_header_t *pkt, | 34 static ngx_int_t ngx_quic_create_packet(ngx_quic_header_t *pkt, |
36 ngx_str_t *res); | 35 ngx_str_t *res); |
106 | 105 |
107 ngx_int_t | 106 ngx_int_t |
108 ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret, | 107 ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret, |
109 ngx_log_t *log) | 108 ngx_log_t *log) |
110 { | 109 { |
111 size_t is_len; | 110 size_t is_len; |
112 uint8_t is[SHA256_DIGEST_LENGTH]; | 111 uint8_t is[SHA256_DIGEST_LENGTH]; |
113 ngx_str_t iss; | 112 ngx_str_t iss; |
114 ngx_uint_t i; | 113 ngx_uint_t i; |
115 const EVP_MD *digest; | 114 const EVP_MD *digest; |
116 ngx_quic_hkdf_t seq[8]; | 115 ngx_quic_hkdf_t seq[8]; |
117 ngx_quic_secret_t *client, *server; | 116 ngx_quic_secret_t *client, *server; |
117 ngx_quic_ciphers_t ciphers; | |
118 | 118 |
119 static const uint8_t salt[20] = | 119 static const uint8_t salt[20] = |
120 "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" | 120 "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" |
121 "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; | 121 "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; |
122 | 122 |
178 if (ngx_quic_hkdf_expand(&seq[i], digest, log) != NGX_OK) { | 178 if (ngx_quic_hkdf_expand(&seq[i], digest, log) != NGX_OK) { |
179 return NGX_ERROR; | 179 return NGX_ERROR; |
180 } | 180 } |
181 } | 181 } |
182 | 182 |
183 return NGX_OK; | 183 if (ngx_quic_ciphers(0, &ciphers, ssl_encryption_initial) == NGX_ERROR) { |
184 return NGX_ERROR; | |
185 } | |
186 | |
187 if (ngx_quic_crypto_init(ciphers.c, client, 0, log) == NGX_ERROR) { | |
188 return NGX_ERROR; | |
189 } | |
190 | |
191 if (ngx_quic_crypto_init(ciphers.c, server, 1, log) == NGX_ERROR) { | |
192 goto failed; | |
193 } | |
194 | |
195 return NGX_OK; | |
196 | |
197 failed: | |
198 | |
199 ngx_quic_keys_cleanup(keys); | |
200 | |
201 return NGX_ERROR; | |
184 } | 202 } |
185 | 203 |
186 | 204 |
187 ngx_int_t | 205 ngx_int_t |
188 ngx_quic_hkdf_expand(ngx_quic_hkdf_t *h, const EVP_MD *digest, ngx_log_t *log) | 206 ngx_quic_hkdf_expand(ngx_quic_hkdf_t *h, const EVP_MD *digest, ngx_log_t *log) |
341 | 359 |
342 #endif | 360 #endif |
343 } | 361 } |
344 | 362 |
345 | 363 |
346 static ngx_int_t | 364 ngx_int_t |
347 ngx_quic_crypto_open(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, | 365 ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, |
348 ngx_str_t *out, u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) | 366 ngx_int_t enc, ngx_log_t *log) |
349 { | 367 { |
350 | 368 |
351 #ifdef OPENSSL_IS_BORINGSSL | 369 #ifdef OPENSSL_IS_BORINGSSL |
352 EVP_AEAD_CTX *ctx; | 370 EVP_AEAD_CTX *ctx; |
353 | 371 |
355 EVP_AEAD_DEFAULT_TAG_LENGTH); | 373 EVP_AEAD_DEFAULT_TAG_LENGTH); |
356 if (ctx == NULL) { | 374 if (ctx == NULL) { |
357 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed"); | 375 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed"); |
358 return NGX_ERROR; | 376 return NGX_ERROR; |
359 } | 377 } |
360 | |
361 if (EVP_AEAD_CTX_open(ctx, out->data, &out->len, out->len, nonce, s->iv.len, | |
362 in->data, in->len, ad->data, ad->len) | |
363 != 1) | |
364 { | |
365 EVP_AEAD_CTX_free(ctx); | |
366 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_open() failed"); | |
367 return NGX_ERROR; | |
368 } | |
369 | |
370 EVP_AEAD_CTX_free(ctx); | |
371 #else | 378 #else |
372 int len; | |
373 EVP_CIPHER_CTX *ctx; | 379 EVP_CIPHER_CTX *ctx; |
374 | 380 |
375 ctx = EVP_CIPHER_CTX_new(); | 381 ctx = EVP_CIPHER_CTX_new(); |
376 if (ctx == NULL) { | 382 if (ctx == NULL) { |
377 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CIPHER_CTX_new() failed"); | 383 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CIPHER_CTX_new() failed"); |
378 return NGX_ERROR; | 384 return NGX_ERROR; |
379 } | 385 } |
380 | 386 |
381 if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) { | 387 if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc) != 1) { |
382 EVP_CIPHER_CTX_free(ctx); | 388 EVP_CIPHER_CTX_free(ctx); |
383 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed"); | 389 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed"); |
384 return NGX_ERROR; | |
385 } | |
386 | |
387 in->len -= NGX_QUIC_TAG_LEN; | |
388 | |
389 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, | |
390 in->data + in->len) | |
391 == 0) | |
392 { | |
393 EVP_CIPHER_CTX_free(ctx); | |
394 ngx_ssl_error(NGX_LOG_INFO, log, 0, | |
395 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); | |
396 return NGX_ERROR; | |
397 } | |
398 | |
399 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) | |
400 == 0) | |
401 { | |
402 EVP_CIPHER_CTX_free(ctx); | |
403 ngx_ssl_error(NGX_LOG_INFO, log, 0, | |
404 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); | |
405 return NGX_ERROR; | |
406 } | |
407 | |
408 if (EVP_DecryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { | |
409 EVP_CIPHER_CTX_free(ctx); | |
410 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed"); | |
411 return NGX_ERROR; | |
412 } | |
413 | |
414 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE | |
415 && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) | |
416 { | |
417 EVP_CIPHER_CTX_free(ctx); | |
418 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); | |
419 return NGX_ERROR; | |
420 } | |
421 | |
422 if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { | |
423 EVP_CIPHER_CTX_free(ctx); | |
424 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); | |
425 return NGX_ERROR; | |
426 } | |
427 | |
428 if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { | |
429 EVP_CIPHER_CTX_free(ctx); | |
430 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); | |
431 return NGX_ERROR; | |
432 } | |
433 | |
434 out->len = len; | |
435 | |
436 if (EVP_DecryptFinal_ex(ctx, out->data + out->len, &len) <= 0) { | |
437 EVP_CIPHER_CTX_free(ctx); | |
438 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptFinal_ex failed"); | |
439 return NGX_ERROR; | |
440 } | |
441 | |
442 out->len += len; | |
443 | |
444 EVP_CIPHER_CTX_free(ctx); | |
445 #endif | |
446 | |
447 return NGX_OK; | |
448 } | |
449 | |
450 | |
451 ngx_int_t | |
452 ngx_quic_crypto_seal(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, | |
453 ngx_str_t *out, u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) | |
454 { | |
455 | |
456 #ifdef OPENSSL_IS_BORINGSSL | |
457 EVP_AEAD_CTX *ctx; | |
458 | |
459 ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len, | |
460 EVP_AEAD_DEFAULT_TAG_LENGTH); | |
461 if (ctx == NULL) { | |
462 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed"); | |
463 return NGX_ERROR; | |
464 } | |
465 | |
466 if (EVP_AEAD_CTX_seal(ctx, out->data, &out->len, out->len, nonce, s->iv.len, | |
467 in->data, in->len, ad->data, ad->len) | |
468 != 1) | |
469 { | |
470 EVP_AEAD_CTX_free(ctx); | |
471 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_seal() failed"); | |
472 return NGX_ERROR; | |
473 } | |
474 | |
475 EVP_AEAD_CTX_free(ctx); | |
476 #else | |
477 int len; | |
478 EVP_CIPHER_CTX *ctx; | |
479 | |
480 ctx = EVP_CIPHER_CTX_new(); | |
481 if (ctx == NULL) { | |
482 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CIPHER_CTX_new() failed"); | |
483 return NGX_ERROR; | |
484 } | |
485 | |
486 if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) { | |
487 EVP_CIPHER_CTX_free(ctx); | |
488 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); | |
489 return NGX_ERROR; | 390 return NGX_ERROR; |
490 } | 391 } |
491 | 392 |
492 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE | 393 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE |
493 && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, | 394 && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, |
507 ngx_ssl_error(NGX_LOG_INFO, log, 0, | 408 ngx_ssl_error(NGX_LOG_INFO, log, 0, |
508 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); | 409 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); |
509 return NGX_ERROR; | 410 return NGX_ERROR; |
510 } | 411 } |
511 | 412 |
512 if (EVP_EncryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { | 413 if (EVP_CipherInit_ex(ctx, NULL, NULL, s->key.data, NULL, enc) != 1) { |
513 EVP_CIPHER_CTX_free(ctx); | 414 EVP_CIPHER_CTX_free(ctx); |
415 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed"); | |
416 return NGX_ERROR; | |
417 } | |
418 #endif | |
419 | |
420 s->ctx = ctx; | |
421 return NGX_OK; | |
422 } | |
423 | |
424 | |
425 static ngx_int_t | |
426 ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, | |
427 ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) | |
428 { | |
429 ngx_quic_crypto_ctx_t *ctx; | |
430 | |
431 ctx = s->ctx; | |
432 | |
433 #ifdef OPENSSL_IS_BORINGSSL | |
434 if (EVP_AEAD_CTX_open(ctx, out->data, &out->len, out->len, nonce, s->iv.len, | |
435 in->data, in->len, ad->data, ad->len) | |
436 != 1) | |
437 { | |
438 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_open() failed"); | |
439 return NGX_ERROR; | |
440 } | |
441 #else | |
442 int len; | |
443 | |
444 if (EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce) != 1) { | |
445 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed"); | |
446 return NGX_ERROR; | |
447 } | |
448 | |
449 in->len -= NGX_QUIC_TAG_LEN; | |
450 | |
451 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, | |
452 in->data + in->len) | |
453 == 0) | |
454 { | |
455 ngx_ssl_error(NGX_LOG_INFO, log, 0, | |
456 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); | |
457 return NGX_ERROR; | |
458 } | |
459 | |
460 if (EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(ctx)) == EVP_CIPH_CCM_MODE | |
461 && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) | |
462 { | |
463 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); | |
464 return NGX_ERROR; | |
465 } | |
466 | |
467 if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { | |
468 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); | |
469 return NGX_ERROR; | |
470 } | |
471 | |
472 if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { | |
473 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); | |
474 return NGX_ERROR; | |
475 } | |
476 | |
477 out->len = len; | |
478 | |
479 if (EVP_DecryptFinal_ex(ctx, out->data + out->len, &len) <= 0) { | |
480 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptFinal_ex failed"); | |
481 return NGX_ERROR; | |
482 } | |
483 | |
484 out->len += len; | |
485 #endif | |
486 | |
487 return NGX_OK; | |
488 } | |
489 | |
490 | |
491 ngx_int_t | |
492 ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, | |
493 ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) | |
494 { | |
495 ngx_quic_crypto_ctx_t *ctx; | |
496 | |
497 ctx = s->ctx; | |
498 | |
499 #ifdef OPENSSL_IS_BORINGSSL | |
500 if (EVP_AEAD_CTX_seal(ctx, out->data, &out->len, out->len, nonce, s->iv.len, | |
501 in->data, in->len, ad->data, ad->len) | |
502 != 1) | |
503 { | |
504 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_seal() failed"); | |
505 return NGX_ERROR; | |
506 } | |
507 #else | |
508 int len; | |
509 | |
510 if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce) != 1) { | |
514 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); | 511 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); |
515 return NGX_ERROR; | 512 return NGX_ERROR; |
516 } | 513 } |
517 | 514 |
518 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE | 515 if (EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(ctx)) == EVP_CIPH_CCM_MODE |
519 && EVP_EncryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) | 516 && EVP_EncryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) |
520 { | 517 { |
521 EVP_CIPHER_CTX_free(ctx); | |
522 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); | 518 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); |
523 return NGX_ERROR; | 519 return NGX_ERROR; |
524 } | 520 } |
525 | 521 |
526 if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { | 522 if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { |
527 EVP_CIPHER_CTX_free(ctx); | |
528 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); | 523 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); |
529 return NGX_ERROR; | 524 return NGX_ERROR; |
530 } | 525 } |
531 | 526 |
532 if (EVP_EncryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { | 527 if (EVP_EncryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { |
533 EVP_CIPHER_CTX_free(ctx); | |
534 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); | 528 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); |
535 return NGX_ERROR; | 529 return NGX_ERROR; |
536 } | 530 } |
537 | 531 |
538 out->len = len; | 532 out->len = len; |
539 | 533 |
540 if (EVP_EncryptFinal_ex(ctx, out->data + out->len, &len) <= 0) { | 534 if (EVP_EncryptFinal_ex(ctx, out->data + out->len, &len) <= 0) { |
541 EVP_CIPHER_CTX_free(ctx); | |
542 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptFinal_ex failed"); | 535 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptFinal_ex failed"); |
543 return NGX_ERROR; | 536 return NGX_ERROR; |
544 } | 537 } |
545 | 538 |
546 out->len += len; | 539 out->len += len; |
547 | 540 |
548 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, | 541 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, |
549 out->data + out->len) | 542 out->data + out->len) |
550 == 0) | 543 == 0) |
551 { | 544 { |
552 EVP_CIPHER_CTX_free(ctx); | |
553 ngx_ssl_error(NGX_LOG_INFO, log, 0, | 545 ngx_ssl_error(NGX_LOG_INFO, log, 0, |
554 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed"); | 546 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed"); |
555 return NGX_ERROR; | 547 return NGX_ERROR; |
556 } | 548 } |
557 | 549 |
558 out->len += NGX_QUIC_TAG_LEN; | 550 out->len += NGX_QUIC_TAG_LEN; |
559 | 551 #endif |
560 EVP_CIPHER_CTX_free(ctx); | 552 |
561 #endif | 553 return NGX_OK; |
562 | 554 } |
563 return NGX_OK; | 555 |
556 | |
557 void | |
558 ngx_quic_crypto_cleanup(ngx_quic_secret_t *s) | |
559 { | |
560 if (s->ctx) { | |
561 #ifdef OPENSSL_IS_BORINGSSL | |
562 EVP_AEAD_CTX_free(s->ctx); | |
563 #else | |
564 EVP_CIPHER_CTX_free(s->ctx); | |
565 #endif | |
566 s->ctx = NULL; | |
567 } | |
564 } | 568 } |
565 | 569 |
566 | 570 |
567 static ngx_int_t | 571 static ngx_int_t |
568 ngx_quic_crypto_hp(ngx_log_t *log, const EVP_CIPHER *cipher, | 572 ngx_quic_crypto_hp(ngx_log_t *log, const EVP_CIPHER *cipher, |
664 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, log) != NGX_OK) { | 668 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, log) != NGX_OK) { |
665 return NGX_ERROR; | 669 return NGX_ERROR; |
666 } | 670 } |
667 } | 671 } |
668 | 672 |
673 if (ngx_quic_crypto_init(ciphers.c, peer_secret, is_write, log) | |
674 == NGX_ERROR) | |
675 { | |
676 return NGX_ERROR; | |
677 } | |
678 | |
669 return NGX_OK; | 679 return NGX_OK; |
670 } | 680 } |
671 | 681 |
672 | 682 |
673 ngx_uint_t | 683 ngx_uint_t |
674 ngx_quic_keys_available(ngx_quic_keys_t *keys, | 684 ngx_quic_keys_available(ngx_quic_keys_t *keys, |
675 enum ssl_encryption_level_t level, ngx_uint_t is_write) | 685 enum ssl_encryption_level_t level, ngx_uint_t is_write) |
676 { | 686 { |
677 if (is_write == 0) { | 687 if (is_write == 0) { |
678 return keys->secrets[level].client.key.len != 0; | 688 return keys->secrets[level].client.ctx != NULL; |
679 } | 689 } |
680 | 690 |
681 return keys->secrets[level].server.key.len != 0; | 691 return keys->secrets[level].server.ctx != NULL; |
682 } | 692 } |
683 | 693 |
684 | 694 |
685 void | 695 void |
686 ngx_quic_keys_discard(ngx_quic_keys_t *keys, | 696 ngx_quic_keys_discard(ngx_quic_keys_t *keys, |
687 enum ssl_encryption_level_t level) | 697 enum ssl_encryption_level_t level) |
688 { | 698 { |
689 keys->secrets[level].client.key.len = 0; | 699 ngx_quic_secret_t *client, *server; |
690 keys->secrets[level].server.key.len = 0; | 700 |
701 client = &keys->secrets[level].client; | |
702 server = &keys->secrets[level].server; | |
703 | |
704 ngx_quic_crypto_cleanup(client); | |
705 ngx_quic_crypto_cleanup(server); | |
691 } | 706 } |
692 | 707 |
693 | 708 |
694 void | 709 void |
695 ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys) | 710 ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys) |
696 { | 711 { |
697 ngx_quic_secrets_t *current, *next, tmp; | 712 ngx_quic_secrets_t *current, *next, tmp; |
698 | 713 |
699 current = &keys->secrets[ssl_encryption_application]; | 714 current = &keys->secrets[ssl_encryption_application]; |
700 next = &keys->next_key; | 715 next = &keys->next_key; |
716 | |
717 ngx_quic_crypto_cleanup(¤t->client); | |
718 ngx_quic_crypto_cleanup(¤t->server); | |
701 | 719 |
702 tmp = *current; | 720 tmp = *current; |
703 *current = *next; | 721 *current = *next; |
704 *next = tmp; | 722 *next = tmp; |
705 } | 723 } |
760 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) { | 778 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) { |
761 goto failed; | 779 goto failed; |
762 } | 780 } |
763 } | 781 } |
764 | 782 |
783 if (ngx_quic_crypto_init(ciphers.c, &next->client, 0, c->log) == NGX_ERROR) | |
784 { | |
785 goto failed; | |
786 } | |
787 | |
788 if (ngx_quic_crypto_init(ciphers.c, &next->server, 1, c->log) == NGX_ERROR) | |
789 { | |
790 goto failed; | |
791 } | |
792 | |
765 return; | 793 return; |
766 | 794 |
767 failed: | 795 failed: |
768 | 796 |
769 ngx_quic_close_connection(c, NGX_ERROR); | 797 ngx_quic_close_connection(c, NGX_ERROR); |
798 } | |
799 | |
800 | |
801 void | |
802 ngx_quic_keys_cleanup(ngx_quic_keys_t *keys) | |
803 { | |
804 ngx_uint_t i; | |
805 ngx_quic_secrets_t *next; | |
806 | |
807 for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) { | |
808 ngx_quic_keys_discard(keys, i); | |
809 } | |
810 | |
811 next = &keys->next_key; | |
812 | |
813 ngx_quic_crypto_cleanup(&next->client); | |
814 ngx_quic_crypto_cleanup(&next->server); | |
770 } | 815 } |
771 | 816 |
772 | 817 |
773 static ngx_int_t | 818 static ngx_int_t |
774 ngx_quic_create_packet(ngx_quic_header_t *pkt, ngx_str_t *res) | 819 ngx_quic_create_packet(ngx_quic_header_t *pkt, ngx_str_t *res) |
799 secret = &pkt->keys->secrets[pkt->level].server; | 844 secret = &pkt->keys->secrets[pkt->level].server; |
800 | 845 |
801 ngx_memcpy(nonce, secret->iv.data, secret->iv.len); | 846 ngx_memcpy(nonce, secret->iv.data, secret->iv.len); |
802 ngx_quic_compute_nonce(nonce, sizeof(nonce), pkt->number); | 847 ngx_quic_compute_nonce(nonce, sizeof(nonce), pkt->number); |
803 | 848 |
804 if (ngx_quic_crypto_seal(ciphers.c, secret, &out, | 849 if (ngx_quic_crypto_seal(secret, &out, nonce, &pkt->payload, &ad, pkt->log) |
805 nonce, &pkt->payload, &ad, pkt->log) | |
806 != NGX_OK) | 850 != NGX_OK) |
807 { | 851 { |
808 return NGX_ERROR; | 852 return NGX_ERROR; |
809 } | 853 } |
810 | 854 |
860 | 904 |
861 secret.key.len = sizeof(key); | 905 secret.key.len = sizeof(key); |
862 ngx_memcpy(secret.key.data, key, sizeof(key)); | 906 ngx_memcpy(secret.key.data, key, sizeof(key)); |
863 secret.iv.len = NGX_QUIC_IV_LEN; | 907 secret.iv.len = NGX_QUIC_IV_LEN; |
864 | 908 |
865 if (ngx_quic_crypto_seal(ciphers.c, &secret, &itag, nonce, &in, &ad, | 909 if (ngx_quic_crypto_init(ciphers.c, &secret, 1, pkt->log) == NGX_ERROR) { |
866 pkt->log) | 910 return NGX_ERROR; |
911 } | |
912 | |
913 if (ngx_quic_crypto_seal(&secret, &itag, nonce, &in, &ad, pkt->log) | |
867 != NGX_OK) | 914 != NGX_OK) |
868 { | 915 { |
869 return NGX_ERROR; | 916 ngx_quic_crypto_cleanup(&secret); |
870 } | 917 return NGX_ERROR; |
918 } | |
919 | |
920 ngx_quic_crypto_cleanup(&secret); | |
871 | 921 |
872 res->len = itag.data + itag.len - start; | 922 res->len = itag.data + itag.len - start; |
873 res->data = start; | 923 res->data = start; |
874 | 924 |
875 return NGX_OK; | 925 return NGX_OK; |
997 ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn) | 1047 ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn) |
998 { | 1048 { |
999 u_char *p, *sample; | 1049 u_char *p, *sample; |
1000 size_t len; | 1050 size_t len; |
1001 uint64_t pn, lpn; | 1051 uint64_t pn, lpn; |
1002 ngx_int_t pnl, rc; | 1052 ngx_int_t pnl; |
1003 ngx_str_t in, ad; | 1053 ngx_str_t in, ad; |
1004 ngx_uint_t key_phase; | 1054 ngx_uint_t key_phase; |
1005 ngx_quic_secret_t *secret; | 1055 ngx_quic_secret_t *secret; |
1006 ngx_quic_ciphers_t ciphers; | 1056 ngx_quic_ciphers_t ciphers; |
1007 uint8_t nonce[NGX_QUIC_IV_LEN], mask[NGX_QUIC_HP_LEN]; | 1057 uint8_t nonce[NGX_QUIC_IV_LEN], mask[NGX_QUIC_HP_LEN]; |
1086 #endif | 1136 #endif |
1087 | 1137 |
1088 pkt->payload.len = in.len - NGX_QUIC_TAG_LEN; | 1138 pkt->payload.len = in.len - NGX_QUIC_TAG_LEN; |
1089 pkt->payload.data = pkt->plaintext + ad.len; | 1139 pkt->payload.data = pkt->plaintext + ad.len; |
1090 | 1140 |
1091 rc = ngx_quic_crypto_open(ciphers.c, secret, &pkt->payload, | 1141 if (ngx_quic_crypto_open(secret, &pkt->payload, nonce, &in, &ad, pkt->log) |
1092 nonce, &in, &ad, pkt->log); | 1142 != NGX_OK) |
1093 if (rc != NGX_OK) { | 1143 { |
1094 return NGX_DECLINED; | 1144 return NGX_DECLINED; |
1095 } | 1145 } |
1096 | 1146 |
1097 if (pkt->payload.len == 0) { | 1147 if (pkt->payload.len == 0) { |
1098 /* | 1148 /* |