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, &current->client.secret); 807 &next->client.secret, &current->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, &current->server.secret); 813 &next->server.secret, &current->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)