Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_protection.c @ 9177:22d110af473c
QUIC: removed key field from ngx_quic_secret_t.
It is made local as it is only needed now when creating crypto context.
BoringSSL lacks EVP interface for ChaCha20, providing instead
a function for one-shot encryption, thus hp is still preserved.
Based on a patch by Roman Arutyunyan.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Fri, 20 Oct 2023 18:05:07 +0400 |
parents | 8dacf87e4007 |
children | b74f891053c7 |
comparison
equal
deleted
inserted
replaced
9176:8dacf87e4007 | 9177:22d110af473c |
---|---|
115 size_t is_len; | 115 size_t is_len; |
116 uint8_t is[SHA256_DIGEST_LENGTH]; | 116 uint8_t is[SHA256_DIGEST_LENGTH]; |
117 ngx_str_t iss; | 117 ngx_str_t iss; |
118 ngx_uint_t i; | 118 ngx_uint_t i; |
119 const EVP_MD *digest; | 119 const EVP_MD *digest; |
120 ngx_quic_md_t client_key, server_key; | |
120 ngx_quic_hkdf_t seq[8]; | 121 ngx_quic_hkdf_t seq[8]; |
121 ngx_quic_secret_t *client, *server; | 122 ngx_quic_secret_t *client, *server; |
122 ngx_quic_ciphers_t ciphers; | 123 ngx_quic_ciphers_t ciphers; |
123 | 124 |
124 static const uint8_t salt[20] = | 125 static const uint8_t salt[20] = |
158 #endif | 159 #endif |
159 | 160 |
160 client->secret.len = SHA256_DIGEST_LENGTH; | 161 client->secret.len = SHA256_DIGEST_LENGTH; |
161 server->secret.len = SHA256_DIGEST_LENGTH; | 162 server->secret.len = SHA256_DIGEST_LENGTH; |
162 | 163 |
163 client->key.len = NGX_QUIC_AES_128_KEY_LEN; | 164 client_key.len = NGX_QUIC_AES_128_KEY_LEN; |
164 server->key.len = NGX_QUIC_AES_128_KEY_LEN; | 165 server_key.len = NGX_QUIC_AES_128_KEY_LEN; |
165 | 166 |
166 client->hp.len = NGX_QUIC_AES_128_KEY_LEN; | 167 client->hp.len = NGX_QUIC_AES_128_KEY_LEN; |
167 server->hp.len = NGX_QUIC_AES_128_KEY_LEN; | 168 server->hp.len = NGX_QUIC_AES_128_KEY_LEN; |
168 | 169 |
169 client->iv.len = NGX_QUIC_IV_LEN; | 170 client->iv.len = NGX_QUIC_IV_LEN; |
170 server->iv.len = NGX_QUIC_IV_LEN; | 171 server->iv.len = NGX_QUIC_IV_LEN; |
171 | 172 |
172 /* labels per RFC 9001, 5.1. Packet Protection Keys */ | 173 /* labels per RFC 9001, 5.1. Packet Protection Keys */ |
173 ngx_quic_hkdf_set(&seq[0], "tls13 client in", &client->secret, &iss); | 174 ngx_quic_hkdf_set(&seq[0], "tls13 client in", &client->secret, &iss); |
174 ngx_quic_hkdf_set(&seq[1], "tls13 quic key", &client->key, &client->secret); | 175 ngx_quic_hkdf_set(&seq[1], "tls13 quic key", &client_key, &client->secret); |
175 ngx_quic_hkdf_set(&seq[2], "tls13 quic iv", &client->iv, &client->secret); | 176 ngx_quic_hkdf_set(&seq[2], "tls13 quic iv", &client->iv, &client->secret); |
176 ngx_quic_hkdf_set(&seq[3], "tls13 quic hp", &client->hp, &client->secret); | 177 ngx_quic_hkdf_set(&seq[3], "tls13 quic hp", &client->hp, &client->secret); |
177 ngx_quic_hkdf_set(&seq[4], "tls13 server in", &server->secret, &iss); | 178 ngx_quic_hkdf_set(&seq[4], "tls13 server in", &server->secret, &iss); |
178 ngx_quic_hkdf_set(&seq[5], "tls13 quic key", &server->key, &server->secret); | 179 ngx_quic_hkdf_set(&seq[5], "tls13 quic key", &server_key, &server->secret); |
179 ngx_quic_hkdf_set(&seq[6], "tls13 quic iv", &server->iv, &server->secret); | 180 ngx_quic_hkdf_set(&seq[6], "tls13 quic iv", &server->iv, &server->secret); |
180 ngx_quic_hkdf_set(&seq[7], "tls13 quic hp", &server->hp, &server->secret); | 181 ngx_quic_hkdf_set(&seq[7], "tls13 quic hp", &server->hp, &server->secret); |
181 | 182 |
182 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { | 183 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { |
183 if (ngx_quic_hkdf_expand(&seq[i], digest, log) != NGX_OK) { | 184 if (ngx_quic_hkdf_expand(&seq[i], digest, log) != NGX_OK) { |
187 | 188 |
188 if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) { | 189 if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) { |
189 return NGX_ERROR; | 190 return NGX_ERROR; |
190 } | 191 } |
191 | 192 |
192 if (ngx_quic_crypto_init(ciphers.c, client, 0, log) == NGX_ERROR) { | 193 if (ngx_quic_crypto_init(ciphers.c, client, &client_key, 0, log) |
193 return NGX_ERROR; | 194 == NGX_ERROR) |
194 } | 195 { |
195 | 196 return NGX_ERROR; |
196 if (ngx_quic_crypto_init(ciphers.c, server, 1, log) == NGX_ERROR) { | 197 } |
198 | |
199 if (ngx_quic_crypto_init(ciphers.c, server, &server_key, 1, log) | |
200 == NGX_ERROR) | |
201 { | |
197 goto failed; | 202 goto failed; |
198 } | 203 } |
199 | 204 |
200 if (ngx_quic_crypto_hp_init(ciphers.hp, client, log) == NGX_ERROR) { | 205 if (ngx_quic_crypto_hp_init(ciphers.hp, client, log) == NGX_ERROR) { |
201 goto failed; | 206 goto failed; |
374 } | 379 } |
375 | 380 |
376 | 381 |
377 ngx_int_t | 382 ngx_int_t |
378 ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, | 383 ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, |
379 ngx_int_t enc, ngx_log_t *log) | 384 ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log) |
380 { | 385 { |
381 | 386 |
382 #ifdef OPENSSL_IS_BORINGSSL | 387 #ifdef OPENSSL_IS_BORINGSSL |
383 EVP_AEAD_CTX *ctx; | 388 EVP_AEAD_CTX *ctx; |
384 | 389 |
385 ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len, | 390 ctx = EVP_AEAD_CTX_new(cipher, key->data, key->len, |
386 EVP_AEAD_DEFAULT_TAG_LENGTH); | 391 EVP_AEAD_DEFAULT_TAG_LENGTH); |
387 if (ctx == NULL) { | 392 if (ctx == NULL) { |
388 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed"); | 393 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed"); |
389 return NGX_ERROR; | 394 return NGX_ERROR; |
390 } | 395 } |
421 ngx_ssl_error(NGX_LOG_INFO, log, 0, | 426 ngx_ssl_error(NGX_LOG_INFO, log, 0, |
422 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); | 427 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); |
423 return NGX_ERROR; | 428 return NGX_ERROR; |
424 } | 429 } |
425 | 430 |
426 if (EVP_CipherInit_ex(ctx, NULL, NULL, s->key.data, NULL, enc) != 1) { | 431 if (EVP_CipherInit_ex(ctx, NULL, NULL, key->data, NULL, enc) != 1) { |
427 EVP_CIPHER_CTX_free(ctx); | 432 EVP_CIPHER_CTX_free(ctx); |
428 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed"); | 433 ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed"); |
429 return NGX_ERROR; | 434 return NGX_ERROR; |
430 } | 435 } |
431 #endif | 436 #endif |
650 const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) | 655 const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) |
651 { | 656 { |
652 ngx_int_t key_len; | 657 ngx_int_t key_len; |
653 ngx_str_t secret_str; | 658 ngx_str_t secret_str; |
654 ngx_uint_t i; | 659 ngx_uint_t i; |
660 ngx_quic_md_t key; | |
655 ngx_quic_hkdf_t seq[3]; | 661 ngx_quic_hkdf_t seq[3]; |
656 ngx_quic_secret_t *peer_secret; | 662 ngx_quic_secret_t *peer_secret; |
657 ngx_quic_ciphers_t ciphers; | 663 ngx_quic_ciphers_t ciphers; |
658 | 664 |
659 peer_secret = is_write ? &keys->secrets[level].server | 665 peer_secret = is_write ? &keys->secrets[level].server |
675 } | 681 } |
676 | 682 |
677 peer_secret->secret.len = secret_len; | 683 peer_secret->secret.len = secret_len; |
678 ngx_memcpy(peer_secret->secret.data, secret, secret_len); | 684 ngx_memcpy(peer_secret->secret.data, secret, secret_len); |
679 | 685 |
680 peer_secret->key.len = key_len; | 686 key.len = key_len; |
681 peer_secret->iv.len = NGX_QUIC_IV_LEN; | 687 peer_secret->iv.len = NGX_QUIC_IV_LEN; |
682 peer_secret->hp.len = key_len; | 688 peer_secret->hp.len = key_len; |
683 | 689 |
684 secret_str.len = secret_len; | 690 secret_str.len = secret_len; |
685 secret_str.data = (u_char *) secret; | 691 secret_str.data = (u_char *) secret; |
686 | 692 |
687 ngx_quic_hkdf_set(&seq[0], "tls13 quic key", | 693 ngx_quic_hkdf_set(&seq[0], "tls13 quic key", &key, &secret_str); |
688 &peer_secret->key, &secret_str); | |
689 ngx_quic_hkdf_set(&seq[1], "tls13 quic iv", &peer_secret->iv, &secret_str); | 694 ngx_quic_hkdf_set(&seq[1], "tls13 quic iv", &peer_secret->iv, &secret_str); |
690 ngx_quic_hkdf_set(&seq[2], "tls13 quic hp", &peer_secret->hp, &secret_str); | 695 ngx_quic_hkdf_set(&seq[2], "tls13 quic hp", &peer_secret->hp, &secret_str); |
691 | 696 |
692 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { | 697 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { |
693 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, log) != NGX_OK) { | 698 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, log) != NGX_OK) { |
694 return NGX_ERROR; | 699 return NGX_ERROR; |
695 } | 700 } |
696 } | 701 } |
697 | 702 |
698 if (ngx_quic_crypto_init(ciphers.c, peer_secret, is_write, log) | 703 if (ngx_quic_crypto_init(ciphers.c, peer_secret, &key, is_write, log) |
699 == NGX_ERROR) | 704 == NGX_ERROR) |
700 { | 705 { |
701 return NGX_ERROR; | 706 return NGX_ERROR; |
702 } | 707 } |
703 | 708 |
756 | 761 |
757 | 762 |
758 void | 763 void |
759 ngx_quic_keys_update(ngx_event_t *ev) | 764 ngx_quic_keys_update(ngx_event_t *ev) |
760 { | 765 { |
766 ngx_int_t key_len; | |
761 ngx_uint_t i; | 767 ngx_uint_t i; |
768 ngx_quic_md_t client_key, server_key; | |
762 ngx_quic_hkdf_t seq[6]; | 769 ngx_quic_hkdf_t seq[6]; |
763 ngx_quic_keys_t *keys; | 770 ngx_quic_keys_t *keys; |
764 ngx_connection_t *c; | 771 ngx_connection_t *c; |
765 ngx_quic_ciphers_t ciphers; | 772 ngx_quic_ciphers_t ciphers; |
766 ngx_quic_secrets_t *current, *next; | 773 ngx_quic_secrets_t *current, *next; |
775 | 782 |
776 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update"); | 783 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update"); |
777 | 784 |
778 c->log->action = "updating keys"; | 785 c->log->action = "updating keys"; |
779 | 786 |
780 if (ngx_quic_ciphers(keys->cipher, &ciphers) == NGX_ERROR) { | 787 key_len = ngx_quic_ciphers(keys->cipher, &ciphers); |
781 goto failed; | 788 |
782 } | 789 if (key_len == NGX_ERROR) { |
790 goto failed; | |
791 } | |
792 | |
793 client_key.len = key_len; | |
794 server_key.len = key_len; | |
783 | 795 |
784 next->client.secret.len = current->client.secret.len; | 796 next->client.secret.len = current->client.secret.len; |
785 next->client.key.len = current->client.key.len; | |
786 next->client.iv.len = NGX_QUIC_IV_LEN; | 797 next->client.iv.len = NGX_QUIC_IV_LEN; |
787 next->client.hp = current->client.hp; | 798 next->client.hp = current->client.hp; |
788 next->client.hp_ctx = current->client.hp_ctx; | 799 next->client.hp_ctx = current->client.hp_ctx; |
789 | 800 |
790 next->server.secret.len = current->server.secret.len; | 801 next->server.secret.len = current->server.secret.len; |
791 next->server.key.len = current->server.key.len; | |
792 next->server.iv.len = NGX_QUIC_IV_LEN; | 802 next->server.iv.len = NGX_QUIC_IV_LEN; |
793 next->server.hp = current->server.hp; | 803 next->server.hp = current->server.hp; |
794 next->server.hp_ctx = current->server.hp_ctx; | 804 next->server.hp_ctx = current->server.hp_ctx; |
795 | 805 |
796 ngx_quic_hkdf_set(&seq[0], "tls13 quic ku", | 806 ngx_quic_hkdf_set(&seq[0], "tls13 quic ku", |
797 &next->client.secret, ¤t->client.secret); | 807 &next->client.secret, ¤t->client.secret); |
798 ngx_quic_hkdf_set(&seq[1], "tls13 quic key", | 808 ngx_quic_hkdf_set(&seq[1], "tls13 quic key", |
799 &next->client.key, &next->client.secret); | 809 &client_key, &next->client.secret); |
800 ngx_quic_hkdf_set(&seq[2], "tls13 quic iv", | 810 ngx_quic_hkdf_set(&seq[2], "tls13 quic iv", |
801 &next->client.iv, &next->client.secret); | 811 &next->client.iv, &next->client.secret); |
802 ngx_quic_hkdf_set(&seq[3], "tls13 quic ku", | 812 ngx_quic_hkdf_set(&seq[3], "tls13 quic ku", |
803 &next->server.secret, ¤t->server.secret); | 813 &next->server.secret, ¤t->server.secret); |
804 ngx_quic_hkdf_set(&seq[4], "tls13 quic key", | 814 ngx_quic_hkdf_set(&seq[4], "tls13 quic key", |
805 &next->server.key, &next->server.secret); | 815 &server_key, &next->server.secret); |
806 ngx_quic_hkdf_set(&seq[5], "tls13 quic iv", | 816 ngx_quic_hkdf_set(&seq[5], "tls13 quic iv", |
807 &next->server.iv, &next->server.secret); | 817 &next->server.iv, &next->server.secret); |
808 | 818 |
809 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { | 819 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { |
810 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) { | 820 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) { |
811 goto failed; | 821 goto failed; |
812 } | 822 } |
813 } | 823 } |
814 | 824 |
815 if (ngx_quic_crypto_init(ciphers.c, &next->client, 0, c->log) == NGX_ERROR) | 825 if (ngx_quic_crypto_init(ciphers.c, &next->client, &client_key, 0, c->log) |
816 { | 826 == NGX_ERROR) |
817 goto failed; | 827 { |
818 } | 828 goto failed; |
819 | 829 } |
820 if (ngx_quic_crypto_init(ciphers.c, &next->server, 1, c->log) == NGX_ERROR) | 830 |
831 if (ngx_quic_crypto_init(ciphers.c, &next->server, &server_key, 1, c->log) | |
832 == NGX_ERROR) | |
821 { | 833 { |
822 goto failed; | 834 goto failed; |
823 } | 835 } |
824 | 836 |
825 return; | 837 return; |
899 static ngx_int_t | 911 static ngx_int_t |
900 ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res) | 912 ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res) |
901 { | 913 { |
902 u_char *start; | 914 u_char *start; |
903 ngx_str_t ad, itag; | 915 ngx_str_t ad, itag; |
916 ngx_quic_md_t key; | |
904 ngx_quic_secret_t secret; | 917 ngx_quic_secret_t secret; |
905 ngx_quic_ciphers_t ciphers; | 918 ngx_quic_ciphers_t ciphers; |
906 | 919 |
907 /* 5.8. Retry Packet Integrity */ | 920 /* 5.8. Retry Packet Integrity */ |
908 static u_char key[16] = | 921 static u_char key_data[16] = |
909 "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"; | 922 "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"; |
910 static u_char nonce[NGX_QUIC_IV_LEN] = | 923 static u_char nonce[NGX_QUIC_IV_LEN] = |
911 "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; | 924 "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; |
912 static ngx_str_t in = ngx_string(""); | 925 static ngx_str_t in = ngx_string(""); |
913 | 926 |
924 | 937 |
925 if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) { | 938 if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) { |
926 return NGX_ERROR; | 939 return NGX_ERROR; |
927 } | 940 } |
928 | 941 |
929 secret.key.len = sizeof(key); | 942 key.len = sizeof(key_data); |
930 ngx_memcpy(secret.key.data, key, sizeof(key)); | 943 ngx_memcpy(key.data, key_data, sizeof(key_data)); |
931 secret.iv.len = NGX_QUIC_IV_LEN; | 944 secret.iv.len = NGX_QUIC_IV_LEN; |
932 | 945 |
933 if (ngx_quic_crypto_init(ciphers.c, &secret, 1, pkt->log) == NGX_ERROR) { | 946 if (ngx_quic_crypto_init(ciphers.c, &secret, &key, 1, pkt->log) |
947 == NGX_ERROR) | |
948 { | |
934 return NGX_ERROR; | 949 return NGX_ERROR; |
935 } | 950 } |
936 | 951 |
937 if (ngx_quic_crypto_seal(&secret, &itag, nonce, &in, &ad, pkt->log) | 952 if (ngx_quic_crypto_seal(&secret, &itag, nonce, &in, &ad, pkt->log) |
938 != NGX_OK) | 953 != NGX_OK) |