src/event/quic/ngx_event_quic_protection.c - nginx source code

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. */


  4. #include <ngx_config.h>
  5. #include <ngx_core.h>
  6. #include <ngx_event.h>
  7. #include <ngx_event_quic_connection.h>


  8. /* RFC 9001, 5.4.1.  Header Protection Application: 5-byte mask */
  9. #define NGX_QUIC_HP_LEN               5

  10. #define NGX_QUIC_AES_128_KEY_LEN      16

  11. #define NGX_QUIC_INITIAL_CIPHER       TLS1_3_CK_AES_128_GCM_SHA256


  12. #define ngx_quic_md(str)     { sizeof(str) - 1, str }


  13. static ngx_int_t ngx_hkdf_expand(u_char *out_key, size_t out_len,
  14.     const EVP_MD *digest, const u_char *prk, size_t prk_len,
  15.     const u_char *info, size_t info_len);
  16. static ngx_int_t ngx_hkdf_extract(u_char *out_key, size_t *out_len,
  17.     const EVP_MD *digest, const u_char *secret, size_t secret_len,
  18.     const u_char *salt, size_t salt_len);

  19. static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
  20.     uint64_t *largest_pn);

  21. static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out,
  22.     const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
  23. #ifndef OPENSSL_IS_BORINGSSL
  24. static ngx_int_t ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
  25.     const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
  26. #endif

  27. static ngx_int_t ngx_quic_crypto_hp_init(const EVP_CIPHER *cipher,
  28.     ngx_quic_secret_t *s, ngx_log_t *log);
  29. static ngx_int_t ngx_quic_crypto_hp(ngx_quic_secret_t *s,
  30.     u_char *out, u_char *in, ngx_log_t *log);
  31. static void ngx_quic_crypto_hp_cleanup(ngx_quic_secret_t *s);

  32. static ngx_int_t ngx_quic_create_packet(ngx_quic_header_t *pkt,
  33.     ngx_str_t *res);
  34. static ngx_int_t ngx_quic_create_retry_packet(ngx_quic_header_t *pkt,
  35.     ngx_str_t *res);


  36. ngx_int_t
  37. ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
  38. {
  39.     ngx_int_t  len;

  40.     switch (id) {

  41.     case TLS1_3_CK_AES_128_GCM_SHA256:
  42. #ifdef OPENSSL_IS_BORINGSSL
  43.         ciphers->c = EVP_aead_aes_128_gcm();
  44. #else
  45.         ciphers->c = EVP_aes_128_gcm();
  46. #endif
  47.         ciphers->hp = EVP_aes_128_ctr();
  48.         ciphers->d = EVP_sha256();
  49.         len = 16;
  50.         break;

  51.     case TLS1_3_CK_AES_256_GCM_SHA384:
  52. #ifdef OPENSSL_IS_BORINGSSL
  53.         ciphers->c = EVP_aead_aes_256_gcm();
  54. #else
  55.         ciphers->c = EVP_aes_256_gcm();
  56. #endif
  57.         ciphers->hp = EVP_aes_256_ctr();
  58.         ciphers->d = EVP_sha384();
  59.         len = 32;
  60.         break;

  61.     case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
  62. #ifdef OPENSSL_IS_BORINGSSL
  63.         ciphers->c = EVP_aead_chacha20_poly1305();
  64. #else
  65.         ciphers->c = EVP_chacha20_poly1305();
  66. #endif
  67. #ifdef OPENSSL_IS_BORINGSSL
  68.         ciphers->hp = (const EVP_CIPHER *) EVP_aead_chacha20_poly1305();
  69. #else
  70.         ciphers->hp = EVP_chacha20();
  71. #endif
  72.         ciphers->d = EVP_sha256();
  73.         len = 32;
  74.         break;

  75. #ifndef OPENSSL_IS_BORINGSSL
  76.     case TLS1_3_CK_AES_128_CCM_SHA256:
  77.         ciphers->c = EVP_aes_128_ccm();
  78.         ciphers->hp = EVP_aes_128_ctr();
  79.         ciphers->d = EVP_sha256();
  80.         len = 16;
  81.         break;
  82. #endif

  83.     default:
  84.         return NGX_ERROR;
  85.     }

  86.     return len;
  87. }


  88. ngx_int_t
  89. ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,
  90.     ngx_log_t *log)
  91. {
  92.     size_t               is_len;
  93.     uint8_t              is[SHA256_DIGEST_LENGTH];
  94.     ngx_str_t            iss;
  95.     ngx_uint_t           i;
  96.     const EVP_MD        *digest;
  97.     ngx_quic_md_t        client_key, server_key;
  98.     ngx_quic_hkdf_t      seq[8];
  99.     ngx_quic_secret_t   *client, *server;
  100.     ngx_quic_ciphers_t   ciphers;

  101.     static const uint8_t salt[20] =
  102.         "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17"
  103.         "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a";

  104.     client = &keys->secrets[ssl_encryption_initial].client;
  105.     server = &keys->secrets[ssl_encryption_initial].server;

  106.     /*
  107.      * RFC 9001, section 5.  Packet Protection
  108.      *
  109.      * Initial packets use AEAD_AES_128_GCM.  The hash function
  110.      * for HKDF when deriving initial secrets and keys is SHA-256.
  111.      */

  112.     digest = EVP_sha256();
  113.     is_len = SHA256_DIGEST_LENGTH;

  114.     if (ngx_hkdf_extract(is, &is_len, digest, secret->data, secret->len,
  115.                          salt, sizeof(salt))
  116.         != NGX_OK)
  117.     {
  118.         return NGX_ERROR;
  119.     }

  120.     iss.len = is_len;
  121.     iss.data = is;

  122.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0,
  123.                    "quic ngx_quic_set_initial_secret");
  124. #ifdef NGX_QUIC_DEBUG_CRYPTO
  125.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
  126.                    "quic salt len:%uz %*xs", sizeof(salt), sizeof(salt), salt);
  127.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
  128.                    "quic initial secret len:%uz %*xs", is_len, is_len, is);
  129. #endif

  130.     client->secret.len = SHA256_DIGEST_LENGTH;
  131.     server->secret.len = SHA256_DIGEST_LENGTH;

  132.     client_key.len = NGX_QUIC_AES_128_KEY_LEN;
  133.     server_key.len = NGX_QUIC_AES_128_KEY_LEN;

  134.     client->hp.len = NGX_QUIC_AES_128_KEY_LEN;
  135.     server->hp.len = NGX_QUIC_AES_128_KEY_LEN;

  136.     client->iv.len = NGX_QUIC_IV_LEN;
  137.     server->iv.len = NGX_QUIC_IV_LEN;

  138.     /* labels per RFC 9001, 5.1. Packet Protection Keys */
  139.     ngx_quic_hkdf_set(&seq[0], "tls13 client in", &client->secret, &iss);
  140.     ngx_quic_hkdf_set(&seq[1], "tls13 quic key", &client_key, &client->secret);
  141.     ngx_quic_hkdf_set(&seq[2], "tls13 quic iv", &client->iv, &client->secret);
  142.     ngx_quic_hkdf_set(&seq[3], "tls13 quic hp", &client->hp, &client->secret);
  143.     ngx_quic_hkdf_set(&seq[4], "tls13 server in", &server->secret, &iss);
  144.     ngx_quic_hkdf_set(&seq[5], "tls13 quic key", &server_key, &server->secret);
  145.     ngx_quic_hkdf_set(&seq[6], "tls13 quic iv", &server->iv, &server->secret);
  146.     ngx_quic_hkdf_set(&seq[7], "tls13 quic hp", &server->hp, &server->secret);

  147.     for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
  148.         if (ngx_quic_hkdf_expand(&seq[i], digest, log) != NGX_OK) {
  149.             return NGX_ERROR;
  150.         }
  151.     }

  152.     if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) {
  153.         return NGX_ERROR;
  154.     }

  155.     if (ngx_quic_crypto_init(ciphers.c, client, &client_key, 0, log)
  156.         == NGX_ERROR)
  157.     {
  158.         return NGX_ERROR;
  159.     }

  160.     if (ngx_quic_crypto_init(ciphers.c, server, &server_key, 1, log)
  161.         == NGX_ERROR)
  162.     {
  163.         goto failed;
  164.     }

  165.     if (ngx_quic_crypto_hp_init(ciphers.hp, client, log) == NGX_ERROR) {
  166.         goto failed;
  167.     }

  168.     if (ngx_quic_crypto_hp_init(ciphers.hp, server, log) == NGX_ERROR) {
  169.         goto failed;
  170.     }

  171.     return NGX_OK;

  172. failed:

  173.     ngx_quic_keys_cleanup(keys);

  174.     return NGX_ERROR;
  175. }


  176. ngx_int_t
  177. ngx_quic_hkdf_expand(ngx_quic_hkdf_t *h, const EVP_MD *digest, ngx_log_t *log)
  178. {
  179.     size_t    info_len;
  180.     uint8_t  *p;
  181.     uint8_t   info[20];

  182.     info_len = 2 + 1 + h->label_len + 1;

  183.     info[0] = 0;
  184.     info[1] = h->out_len;
  185.     info[2] = h->label_len;

  186.     p = ngx_cpymem(&info[3], h->label, h->label_len);
  187.     *p = '\0';

  188.     if (ngx_hkdf_expand(h->out, h->out_len, digest,
  189.                         h->prk, h->prk_len, info, info_len)
  190.         != NGX_OK)
  191.     {
  192.         ngx_ssl_error(NGX_LOG_INFO, log, 0,
  193.                       "ngx_hkdf_expand(%*s) failed", h->label_len, h->label);
  194.         return NGX_ERROR;
  195.     }

  196. #ifdef NGX_QUIC_DEBUG_CRYPTO
  197.     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, log, 0,
  198.                    "quic expand \"%*s\" len:%uz %*xs",
  199.                    h->label_len, h->label, h->out_len, h->out_len, h->out);
  200. #endif

  201.     return NGX_OK;
  202. }


  203. static ngx_int_t
  204. ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest,
  205.     const uint8_t *prk, size_t prk_len, const u_char *info, size_t info_len)
  206. {
  207. #ifdef OPENSSL_IS_BORINGSSL

  208.     if (HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)
  209.         == 0)
  210.     {
  211.         return NGX_ERROR;
  212.     }

  213.     return NGX_OK;

  214. #else

  215.     EVP_PKEY_CTX  *pctx;

  216.     pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
  217.     if (pctx == NULL) {
  218.         return NGX_ERROR;
  219.     }

  220.     if (EVP_PKEY_derive_init(pctx) <= 0) {
  221.         goto failed;
  222.     }

  223.     if (EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) <= 0) {
  224.         goto failed;
  225.     }

  226.     if (EVP_PKEY_CTX_set_hkdf_md(pctx, digest) <= 0) {
  227.         goto failed;
  228.     }

  229.     if (EVP_PKEY_CTX_set1_hkdf_key(pctx, prk, prk_len) <= 0) {
  230.         goto failed;
  231.     }

  232.     if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len) <= 0) {
  233.         goto failed;
  234.     }

  235.     if (EVP_PKEY_derive(pctx, out_key, &out_len) <= 0) {
  236.         goto failed;
  237.     }

  238.     EVP_PKEY_CTX_free(pctx);

  239.     return NGX_OK;

  240. failed:

  241.     EVP_PKEY_CTX_free(pctx);

  242.     return NGX_ERROR;

  243. #endif
  244. }


  245. static ngx_int_t
  246. ngx_hkdf_extract(u_char *out_key, size_t *out_len, const EVP_MD *digest,
  247.     const u_char *secret, size_t secret_len, const u_char *salt,
  248.     size_t salt_len)
  249. {
  250. #ifdef OPENSSL_IS_BORINGSSL

  251.     if (HKDF_extract(out_key, out_len, digest, secret, secret_len, salt,
  252.                      salt_len)
  253.         == 0)
  254.     {
  255.         return NGX_ERROR;
  256.     }

  257.     return NGX_OK;

  258. #else

  259.     EVP_PKEY_CTX  *pctx;

  260.     pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
  261.     if (pctx == NULL) {
  262.         return NGX_ERROR;
  263.     }

  264.     if (EVP_PKEY_derive_init(pctx) <= 0) {
  265.         goto failed;
  266.     }

  267.     if (EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) <= 0) {
  268.         goto failed;
  269.     }

  270.     if (EVP_PKEY_CTX_set_hkdf_md(pctx, digest) <= 0) {
  271.         goto failed;
  272.     }

  273.     if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secret_len) <= 0) {
  274.         goto failed;
  275.     }

  276.     if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len) <= 0) {
  277.         goto failed;
  278.     }

  279.     if (EVP_PKEY_derive(pctx, out_key, out_len) <= 0) {
  280.         goto failed;
  281.     }

  282.     EVP_PKEY_CTX_free(pctx);

  283.     return NGX_OK;

  284. failed:

  285.     EVP_PKEY_CTX_free(pctx);

  286.     return NGX_ERROR;

  287. #endif
  288. }


  289. ngx_int_t
  290. ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
  291.     ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log)
  292. {

  293. #ifdef OPENSSL_IS_BORINGSSL
  294.     EVP_AEAD_CTX  *ctx;

  295.     ctx = EVP_AEAD_CTX_new(cipher, key->data, key->len,
  296.                            EVP_AEAD_DEFAULT_TAG_LENGTH);
  297.     if (ctx == NULL) {
  298.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed");
  299.         return NGX_ERROR;
  300.     }
  301. #else
  302.     EVP_CIPHER_CTX  *ctx;

  303.     ctx = EVP_CIPHER_CTX_new();
  304.     if (ctx == NULL) {
  305.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CIPHER_CTX_new() failed");
  306.         return NGX_ERROR;
  307.     }

  308.     if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc) != 1) {
  309.         EVP_CIPHER_CTX_free(ctx);
  310.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed");
  311.         return NGX_ERROR;
  312.     }

  313.     if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE
  314.         && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN,
  315.                                NULL)
  316.            == 0)
  317.     {
  318.         EVP_CIPHER_CTX_free(ctx);
  319.         ngx_ssl_error(NGX_LOG_INFO, log, 0,
  320.                       "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed");
  321.         return NGX_ERROR;
  322.     }

  323.     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL)
  324.         == 0)
  325.     {
  326.         EVP_CIPHER_CTX_free(ctx);
  327.         ngx_ssl_error(NGX_LOG_INFO, log, 0,
  328.                       "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed");
  329.         return NGX_ERROR;
  330.     }

  331.     if (EVP_CipherInit_ex(ctx, NULL, NULL, key->data, NULL, enc) != 1) {
  332.         EVP_CIPHER_CTX_free(ctx);
  333.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed");
  334.         return NGX_ERROR;
  335.     }
  336. #endif

  337.     s->ctx = ctx;
  338.     return NGX_OK;
  339. }


  340. static ngx_int_t
  341. ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
  342.     ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
  343. {
  344. #ifdef OPENSSL_IS_BORINGSSL
  345.     if (EVP_AEAD_CTX_open(s->ctx, out->data, &out->len, out->len, nonce,
  346.                           s->iv.len, in->data, in->len, ad->data, ad->len)
  347.         != 1)
  348.     {
  349.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_open() failed");
  350.         return NGX_ERROR;
  351.     }

  352.     return NGX_OK;
  353. #else
  354.     return ngx_quic_crypto_common(s, out, nonce, in, ad, log);
  355. #endif
  356. }


  357. ngx_int_t
  358. ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
  359.     ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
  360. {
  361. #ifdef OPENSSL_IS_BORINGSSL
  362.     if (EVP_AEAD_CTX_seal(s->ctx, out->data, &out->len, out->len, nonce,
  363.                           s->iv.len, in->data, in->len, ad->data, ad->len)
  364.         != 1)
  365.     {
  366.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_seal() failed");
  367.         return NGX_ERROR;
  368.     }

  369.     return NGX_OK;
  370. #else
  371.     return ngx_quic_crypto_common(s, out, nonce, in, ad, log);
  372. #endif
  373. }


  374. #ifndef OPENSSL_IS_BORINGSSL

  375. static ngx_int_t
  376. ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
  377.     const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
  378. {
  379.     int                     len, enc;
  380.     ngx_quic_crypto_ctx_t  *ctx;

  381.     ctx = s->ctx;
  382.     enc = EVP_CIPHER_CTX_encrypting(ctx);

  383.     if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, enc) != 1) {
  384.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed");
  385.         return NGX_ERROR;
  386.     }

  387.     if (enc == 0) {
  388.         in->len -= NGX_QUIC_TAG_LEN;

  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.             ngx_ssl_error(NGX_LOG_INFO, log, 0,
  394.                           "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed");
  395.             return NGX_ERROR;
  396.         }
  397.     }

  398.     if (EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(ctx)) == EVP_CIPH_CCM_MODE
  399.         && EVP_CipherUpdate(ctx, NULL, &len, NULL, in->len) != 1)
  400.     {
  401.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherUpdate() failed");
  402.         return NGX_ERROR;
  403.     }

  404.     if (EVP_CipherUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) {
  405.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherUpdate() failed");
  406.         return NGX_ERROR;
  407.     }

  408.     if (EVP_CipherUpdate(ctx, out->data, &len, in->data, in->len) != 1) {
  409.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherUpdate() failed");
  410.         return NGX_ERROR;
  411.     }

  412.     out->len = len;

  413.     if (EVP_CipherFinal_ex(ctx, out->data + out->len, &len) <= 0) {
  414.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherFinal_ex failed");
  415.         return NGX_ERROR;
  416.     }

  417.     out->len += len;

  418.     if (enc == 1) {
  419.         if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN,
  420.                                 out->data + out->len)
  421.             == 0)
  422.         {
  423.             ngx_ssl_error(NGX_LOG_INFO, log, 0,
  424.                           "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed");
  425.             return NGX_ERROR;
  426.         }

  427.         out->len += NGX_QUIC_TAG_LEN;
  428.     }

  429.     return NGX_OK;
  430. }

  431. #endif


  432. void
  433. ngx_quic_crypto_cleanup(ngx_quic_secret_t *s)
  434. {
  435.     if (s->ctx) {
  436. #ifdef OPENSSL_IS_BORINGSSL
  437.         EVP_AEAD_CTX_free(s->ctx);
  438. #else
  439.         EVP_CIPHER_CTX_free(s->ctx);
  440. #endif
  441.         s->ctx = NULL;
  442.     }
  443. }


  444. static ngx_int_t
  445. ngx_quic_crypto_hp_init(const EVP_CIPHER *cipher, ngx_quic_secret_t *s,
  446.     ngx_log_t *log)
  447. {
  448.     EVP_CIPHER_CTX  *ctx;

  449. #ifdef OPENSSL_IS_BORINGSSL
  450.     if (cipher == (EVP_CIPHER *) EVP_aead_chacha20_poly1305()) {
  451.         /* no EVP interface */
  452.         s->hp_ctx = NULL;
  453.         return NGX_OK;
  454.     }
  455. #endif

  456.     ctx = EVP_CIPHER_CTX_new();
  457.     if (ctx == NULL) {
  458.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CIPHER_CTX_new() failed");
  459.         return NGX_ERROR;
  460.     }

  461.     if (EVP_EncryptInit_ex(ctx, cipher, NULL, s->hp.data, NULL) != 1) {
  462.         EVP_CIPHER_CTX_free(ctx);
  463.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed");
  464.         return NGX_ERROR;
  465.     }

  466.     s->hp_ctx = ctx;
  467.     return NGX_OK;
  468. }


  469. static ngx_int_t
  470. ngx_quic_crypto_hp(ngx_quic_secret_t *s, u_char *out, u_char *in,
  471.     ngx_log_t *log)
  472. {
  473.     int              outlen;
  474.     EVP_CIPHER_CTX  *ctx;

  475.     static const u_char zero[NGX_QUIC_HP_LEN];

  476.     ctx = s->hp_ctx;

  477. #ifdef OPENSSL_IS_BORINGSSL
  478.     uint32_t         cnt;

  479.     if (ctx == NULL) {
  480.         ngx_memcpy(&cnt, in, sizeof(uint32_t));
  481.         CRYPTO_chacha_20(out, zero, NGX_QUIC_HP_LEN, s->hp.data, &in[4], cnt);
  482.         return NGX_OK;
  483.     }
  484. #endif

  485.     if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, in) != 1) {
  486.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed");
  487.         return NGX_ERROR;
  488.     }

  489.     if (!EVP_EncryptUpdate(ctx, out, &outlen, zero, NGX_QUIC_HP_LEN)) {
  490.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed");
  491.         return NGX_ERROR;
  492.     }

  493.     if (!EVP_EncryptFinal_ex(ctx, out + NGX_QUIC_HP_LEN, &outlen)) {
  494.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptFinal_Ex() failed");
  495.         return NGX_ERROR;
  496.     }

  497.     return NGX_OK;
  498. }


  499. static void
  500. ngx_quic_crypto_hp_cleanup(ngx_quic_secret_t *s)
  501. {
  502.     if (s->hp_ctx) {
  503.         EVP_CIPHER_CTX_free(s->hp_ctx);
  504.         s->hp_ctx = NULL;
  505.     }
  506. }


  507. ngx_int_t
  508. ngx_quic_keys_set_encryption_secret(ngx_log_t *log, ngx_uint_t is_write,
  509.     ngx_quic_keys_t *keys, enum ssl_encryption_level_t level,
  510.     const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len)
  511. {
  512.     ngx_int_t            key_len;
  513.     ngx_str_t            secret_str;
  514.     ngx_uint_t           i;
  515.     ngx_quic_md_t        key;
  516.     ngx_quic_hkdf_t      seq[3];
  517.     ngx_quic_secret_t   *peer_secret;
  518.     ngx_quic_ciphers_t   ciphers;

  519.     peer_secret = is_write ? &keys->secrets[level].server
  520.                            : &keys->secrets[level].client;

  521.     keys->cipher = SSL_CIPHER_get_id(cipher);

  522.     key_len = ngx_quic_ciphers(keys->cipher, &ciphers);

  523.     if (key_len == NGX_ERROR) {
  524.         ngx_ssl_error(NGX_LOG_INFO, log, 0, "unexpected cipher");
  525.         return NGX_ERROR;
  526.     }

  527.     if (sizeof(peer_secret->secret.data) < secret_len) {
  528.         ngx_log_error(NGX_LOG_ALERT, log, 0,
  529.                       "unexpected secret len: %uz", secret_len);
  530.         return NGX_ERROR;
  531.     }

  532.     peer_secret->secret.len = secret_len;
  533.     ngx_memcpy(peer_secret->secret.data, secret, secret_len);

  534.     key.len = key_len;
  535.     peer_secret->iv.len = NGX_QUIC_IV_LEN;
  536.     peer_secret->hp.len = key_len;

  537.     secret_str.len = secret_len;
  538.     secret_str.data = (u_char *) secret;

  539.     ngx_quic_hkdf_set(&seq[0], "tls13 quic key", &key, &secret_str);
  540.     ngx_quic_hkdf_set(&seq[1], "tls13 quic iv", &peer_secret->iv, &secret_str);
  541.     ngx_quic_hkdf_set(&seq[2], "tls13 quic hp", &peer_secret->hp, &secret_str);

  542.     for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
  543.         if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, log) != NGX_OK) {
  544.             return NGX_ERROR;
  545.         }
  546.     }

  547.     if (ngx_quic_crypto_init(ciphers.c, peer_secret, &key, is_write, log)
  548.         == NGX_ERROR)
  549.     {
  550.         return NGX_ERROR;
  551.     }

  552.     if (ngx_quic_crypto_hp_init(ciphers.hp, peer_secret, log) == NGX_ERROR) {
  553.         return NGX_ERROR;
  554.     }

  555.     ngx_explicit_memzero(key.data, key.len);

  556.     return NGX_OK;
  557. }


  558. ngx_uint_t
  559. ngx_quic_keys_available(ngx_quic_keys_t *keys,
  560.     enum ssl_encryption_level_t level, ngx_uint_t is_write)
  561. {
  562.     if (is_write == 0) {
  563.         return keys->secrets[level].client.ctx != NULL;
  564.     }

  565.     return keys->secrets[level].server.ctx != NULL;
  566. }


  567. void
  568. ngx_quic_keys_discard(ngx_quic_keys_t *keys,
  569.     enum ssl_encryption_level_t level)
  570. {
  571.     ngx_quic_secret_t  *client, *server;

  572.     client = &keys->secrets[level].client;
  573.     server = &keys->secrets[level].server;

  574.     ngx_quic_crypto_cleanup(client);
  575.     ngx_quic_crypto_cleanup(server);

  576.     ngx_quic_crypto_hp_cleanup(client);
  577.     ngx_quic_crypto_hp_cleanup(server);

  578.     if (client->secret.len) {
  579.         ngx_explicit_memzero(client->secret.data, client->secret.len);
  580.         client->secret.len = 0;
  581.     }

  582.     if (server->secret.len) {
  583.         ngx_explicit_memzero(server->secret.data, server->secret.len);
  584.         server->secret.len = 0;
  585.     }
  586. }


  587. void
  588. ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys)
  589. {
  590.     ngx_quic_secrets_t  *current, *next, tmp;

  591.     current = &keys->secrets[ssl_encryption_application];
  592.     next = &keys->next_key;

  593.     ngx_quic_crypto_cleanup(&current->client);
  594.     ngx_quic_crypto_cleanup(&current->server);

  595.     tmp = *current;
  596.     *current = *next;
  597.     *next = tmp;
  598. }


  599. void
  600. ngx_quic_keys_update(ngx_event_t *ev)
  601. {
  602.     ngx_int_t               key_len;
  603.     ngx_uint_t              i;
  604.     ngx_quic_md_t           client_key, server_key;
  605.     ngx_quic_hkdf_t         seq[6];
  606.     ngx_quic_keys_t        *keys;
  607.     ngx_connection_t       *c;
  608.     ngx_quic_ciphers_t      ciphers;
  609.     ngx_quic_secrets_t     *current, *next;
  610.     ngx_quic_connection_t  *qc;

  611.     c = ev->data;
  612.     qc = ngx_quic_get_connection(c);
  613.     keys = qc->keys;

  614.     current = &keys->secrets[ssl_encryption_application];
  615.     next = &keys->next_key;

  616.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update");

  617.     c->log->action = "updating keys";

  618.     key_len = ngx_quic_ciphers(keys->cipher, &ciphers);

  619.     if (key_len == NGX_ERROR) {
  620.         goto failed;
  621.     }

  622.     client_key.len = key_len;
  623.     server_key.len = key_len;

  624.     next->client.secret.len = current->client.secret.len;
  625.     next->client.iv.len = NGX_QUIC_IV_LEN;
  626.     next->client.hp = current->client.hp;
  627.     next->client.hp_ctx = current->client.hp_ctx;

  628.     next->server.secret.len = current->server.secret.len;
  629.     next->server.iv.len = NGX_QUIC_IV_LEN;
  630.     next->server.hp = current->server.hp;
  631.     next->server.hp_ctx = current->server.hp_ctx;

  632.     ngx_quic_hkdf_set(&seq[0], "tls13 quic ku",
  633.                       &next->client.secret, &current->client.secret);
  634.     ngx_quic_hkdf_set(&seq[1], "tls13 quic key",
  635.                       &client_key, &next->client.secret);
  636.     ngx_quic_hkdf_set(&seq[2], "tls13 quic iv",
  637.                       &next->client.iv, &next->client.secret);
  638.     ngx_quic_hkdf_set(&seq[3], "tls13 quic ku",
  639.                       &next->server.secret, &current->server.secret);
  640.     ngx_quic_hkdf_set(&seq[4], "tls13 quic key",
  641.                       &server_key, &next->server.secret);
  642.     ngx_quic_hkdf_set(&seq[5], "tls13 quic iv",
  643.                       &next->server.iv, &next->server.secret);

  644.     for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
  645.         if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) {
  646.             goto failed;
  647.         }
  648.     }

  649.     if (ngx_quic_crypto_init(ciphers.c, &next->client, &client_key, 0, c->log)
  650.         == NGX_ERROR)
  651.     {
  652.         goto failed;
  653.     }

  654.     if (ngx_quic_crypto_init(ciphers.c, &next->server, &server_key, 1, c->log)
  655.         == NGX_ERROR)
  656.     {
  657.         goto failed;
  658.     }

  659.     ngx_explicit_memzero(current->client.secret.data,
  660.                          current->client.secret.len);
  661.     ngx_explicit_memzero(current->server.secret.data,
  662.                          current->server.secret.len);

  663.     current->client.secret.len = 0;
  664.     current->server.secret.len = 0;

  665.     ngx_explicit_memzero(client_key.data, client_key.len);
  666.     ngx_explicit_memzero(server_key.data, server_key.len);

  667.     return;

  668. failed:

  669.     ngx_quic_close_connection(c, NGX_ERROR);
  670. }


  671. void
  672. ngx_quic_keys_cleanup(ngx_quic_keys_t *keys)
  673. {
  674.     ngx_uint_t           i;
  675.     ngx_quic_secrets_t  *next;

  676.     for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
  677.         ngx_quic_keys_discard(keys, i);
  678.     }

  679.     next = &keys->next_key;

  680.     ngx_quic_crypto_cleanup(&next->client);
  681.     ngx_quic_crypto_cleanup(&next->server);

  682.     if (next->client.secret.len) {
  683.         ngx_explicit_memzero(next->client.secret.data,
  684.                              next->client.secret.len);
  685.         next->client.secret.len = 0;
  686.     }

  687.     if (next->server.secret.len) {
  688.         ngx_explicit_memzero(next->server.secret.data,
  689.                              next->server.secret.len);
  690.         next->server.secret.len = 0;
  691.     }
  692. }


  693. static ngx_int_t
  694. ngx_quic_create_packet(ngx_quic_header_t *pkt, ngx_str_t *res)
  695. {
  696.     u_char             *pnp, *sample;
  697.     ngx_str_t           ad, out;
  698.     ngx_uint_t          i;
  699.     ngx_quic_secret_t  *secret;
  700.     u_char              nonce[NGX_QUIC_IV_LEN], mask[NGX_QUIC_HP_LEN];

  701.     ad.data = res->data;
  702.     ad.len = ngx_quic_create_header(pkt, ad.data, &pnp);

  703.     out.len = pkt->payload.len + NGX_QUIC_TAG_LEN;
  704.     out.data = res->data + ad.len;

  705. #ifdef NGX_QUIC_DEBUG_CRYPTO
  706.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  707.                    "quic ad len:%uz %xV", ad.len, &ad);
  708. #endif

  709.     secret = &pkt->keys->secrets[pkt->level].server;

  710.     ngx_memcpy(nonce, secret->iv.data, secret->iv.len);
  711.     ngx_quic_compute_nonce(nonce, sizeof(nonce), pkt->number);

  712.     if (ngx_quic_crypto_seal(secret, &out, nonce, &pkt->payload, &ad, pkt->log)
  713.         != NGX_OK)
  714.     {
  715.         return NGX_ERROR;
  716.     }

  717.     sample = &out.data[4 - pkt->num_len];
  718.     if (ngx_quic_crypto_hp(secret, mask, sample, pkt->log) != NGX_OK) {
  719.         return NGX_ERROR;
  720.     }

  721.     /* RFC 9001, 5.4.1.  Header Protection Application */
  722.     ad.data[0] ^= mask[0] & ngx_quic_pkt_hp_mask(pkt->flags);

  723.     for (i = 0; i < pkt->num_len; i++) {
  724.         pnp[i] ^= mask[i + 1];
  725.     }

  726.     res->len = ad.len + out.len;

  727.     return NGX_OK;
  728. }


  729. static ngx_int_t
  730. ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res)
  731. {
  732.     u_char              *start;
  733.     ngx_str_t            ad, itag;
  734.     ngx_quic_secret_t    secret;
  735.     ngx_quic_ciphers_t   ciphers;

  736.     /* 5.8.  Retry Packet Integrity */
  737.     static ngx_quic_md_t  key = ngx_quic_md(
  738.         "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e");
  739.     static const u_char   nonce[NGX_QUIC_IV_LEN] =
  740.         "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb";
  741.     static ngx_str_t      in = ngx_string("");

  742.     ad.data = res->data;
  743.     ad.len = ngx_quic_create_retry_itag(pkt, ad.data, &start);

  744.     itag.data = ad.data + ad.len;
  745.     itag.len = NGX_QUIC_TAG_LEN;

  746. #ifdef NGX_QUIC_DEBUG_CRYPTO
  747.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  748.                    "quic retry itag len:%uz %xV", ad.len, &ad);
  749. #endif

  750.     if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) {
  751.         return NGX_ERROR;
  752.     }

  753.     secret.iv.len = NGX_QUIC_IV_LEN;

  754.     if (ngx_quic_crypto_init(ciphers.c, &secret, &key, 1, pkt->log)
  755.         == NGX_ERROR)
  756.     {
  757.         return NGX_ERROR;
  758.     }

  759.     if (ngx_quic_crypto_seal(&secret, &itag, nonce, &in, &ad, pkt->log)
  760.         != NGX_OK)
  761.     {
  762.         ngx_quic_crypto_cleanup(&secret);
  763.         return NGX_ERROR;
  764.     }

  765.     ngx_quic_crypto_cleanup(&secret);

  766.     res->len = itag.data + itag.len - start;
  767.     res->data = start;

  768.     return NGX_OK;
  769. }


  770. ngx_int_t
  771. ngx_quic_derive_key(ngx_log_t *log, const char *label, ngx_str_t *secret,
  772.     ngx_str_t *salt, u_char *out, size_t len)
  773. {
  774.     size_t         is_len, info_len;
  775.     uint8_t       *p;
  776.     const EVP_MD  *digest;

  777.     uint8_t        is[SHA256_DIGEST_LENGTH];
  778.     uint8_t        info[20];

  779.     digest = EVP_sha256();
  780.     is_len = SHA256_DIGEST_LENGTH;

  781.     if (ngx_hkdf_extract(is, &is_len, digest, secret->data, secret->len,
  782.                          salt->data, salt->len)
  783.         != NGX_OK)
  784.     {
  785.         ngx_ssl_error(NGX_LOG_INFO, log, 0,
  786.                       "ngx_hkdf_extract(%s) failed", label);
  787.         return NGX_ERROR;
  788.     }

  789.     info[0] = 0;
  790.     info[1] = len;
  791.     info[2] = ngx_strlen(label);

  792.     info_len = 2 + 1 + info[2] + 1;

  793.     if (info_len >= 20) {
  794.         ngx_log_error(NGX_LOG_INFO, log, 0,
  795.                       "ngx_quic_create_key label \"%s\" too long", label);
  796.         return NGX_ERROR;
  797.     }

  798.     p = ngx_cpymem(&info[3], label, info[2]);
  799.     *p = '\0';

  800.     if (ngx_hkdf_expand(out, len, digest, is, is_len, info, info_len) != NGX_OK)
  801.     {
  802.         ngx_ssl_error(NGX_LOG_INFO, log, 0,
  803.                       "ngx_hkdf_expand(%s) failed", label);
  804.         return NGX_ERROR;
  805.     }

  806.     return NGX_OK;
  807. }


  808. static uint64_t
  809. ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
  810.     uint64_t *largest_pn)
  811. {
  812.     u_char    *p;
  813.     uint64_t   truncated_pn, expected_pn, candidate_pn;
  814.     uint64_t   pn_nbits, pn_win, pn_hwin, pn_mask;

  815.     pn_nbits = ngx_min(len * 8, 62);

  816.     p = *pos;
  817.     truncated_pn = *p++ ^ *mask++;

  818.     while (--len) {
  819.         truncated_pn = (truncated_pn << 8) + (*p++ ^ *mask++);
  820.     }

  821.     *pos = p;

  822.     expected_pn = *largest_pn + 1;
  823.     pn_win = 1ULL << pn_nbits;
  824.     pn_hwin = pn_win / 2;
  825.     pn_mask = pn_win - 1;

  826.     candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;

  827.     if ((int64_t) candidate_pn <= (int64_t) (expected_pn - pn_hwin)
  828.         && candidate_pn < (1ULL << 62) - pn_win)
  829.     {
  830.         candidate_pn += pn_win;

  831.     } else if (candidate_pn > expected_pn + pn_hwin
  832.                && candidate_pn >= pn_win)
  833.     {
  834.         candidate_pn -= pn_win;
  835.     }

  836.     *largest_pn = ngx_max((int64_t) *largest_pn, (int64_t) candidate_pn);

  837.     return candidate_pn;
  838. }


  839. void
  840. ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn)
  841. {
  842.     nonce[len - 8] ^= (pn >> 56) & 0x3f;
  843.     nonce[len - 7] ^= (pn >> 48) & 0xff;
  844.     nonce[len - 6] ^= (pn >> 40) & 0xff;
  845.     nonce[len - 5] ^= (pn >> 32) & 0xff;
  846.     nonce[len - 4] ^= (pn >> 24) & 0xff;
  847.     nonce[len - 3] ^= (pn >> 16) & 0xff;
  848.     nonce[len - 2] ^= (pn >> 8) & 0xff;
  849.     nonce[len - 1] ^= pn & 0xff;
  850. }


  851. ngx_int_t
  852. ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_str_t *res)
  853. {
  854.     if (ngx_quic_pkt_retry(pkt->flags)) {
  855.         return ngx_quic_create_retry_packet(pkt, res);
  856.     }

  857.     return ngx_quic_create_packet(pkt, res);
  858. }


  859. ngx_int_t
  860. ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn)
  861. {
  862.     u_char             *p, *sample;
  863.     size_t              len;
  864.     uint64_t            pn, lpn;
  865.     ngx_int_t           pnl;
  866.     ngx_str_t           in, ad;
  867.     ngx_uint_t          key_phase;
  868.     ngx_quic_secret_t  *secret;
  869.     uint8_t             nonce[NGX_QUIC_IV_LEN], mask[NGX_QUIC_HP_LEN];

  870.     secret = &pkt->keys->secrets[pkt->level].client;

  871.     p = pkt->raw->pos;
  872.     len = pkt->data + pkt->len - p;

  873.     /*
  874.      * RFC 9001, 5.4.2. Header Protection Sample
  875.      *           5.4.3. AES-Based Header Protection
  876.      *           5.4.4. ChaCha20-Based Header Protection
  877.      *
  878.      * the Packet Number field is assumed to be 4 bytes long
  879.      * AES and ChaCha20 algorithms sample 16 bytes
  880.      */

  881.     if (len < NGX_QUIC_TAG_LEN + 4) {
  882.         return NGX_DECLINED;
  883.     }

  884.     sample = p + 4;

  885.     /* header protection */

  886.     if (ngx_quic_crypto_hp(secret, mask, sample, pkt->log) != NGX_OK) {
  887.         return NGX_DECLINED;
  888.     }

  889.     pkt->flags ^= mask[0] & ngx_quic_pkt_hp_mask(pkt->flags);

  890.     if (ngx_quic_short_pkt(pkt->flags)) {
  891.         key_phase = (pkt->flags & NGX_QUIC_PKT_KPHASE) != 0;

  892.         if (key_phase != pkt->key_phase) {
  893.             if (pkt->keys->next_key.client.ctx != NULL) {
  894.                 secret = &pkt->keys->next_key.client;
  895.                 pkt->key_update = 1;

  896.             } else {
  897.                 /*
  898.                  * RFC 9001,  6.3. Timing of Receive Key Generation.
  899.                  *
  900.                  * Trial decryption to avoid timing side-channel.
  901.                  */
  902.                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  903.                                "quic next key missing");
  904.             }
  905.         }
  906.     }

  907.     lpn = *largest_pn;

  908.     pnl = (pkt->flags & 0x03) + 1;
  909.     pn = ngx_quic_parse_pn(&p, pnl, &mask[1], &lpn);

  910.     pkt->pn = pn;

  911.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  912.                    "quic packet rx clearflags:%xd", pkt->flags);
  913.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  914.                    "quic packet rx number:%uL len:%xi", pn, pnl);

  915.     /* packet protection */

  916.     in.data = p;
  917.     in.len = len - pnl;

  918.     ad.len = p - pkt->data;
  919.     ad.data = pkt->plaintext;

  920.     ngx_memcpy(ad.data, pkt->data, ad.len);
  921.     ad.data[0] = pkt->flags;

  922.     do {
  923.         ad.data[ad.len - pnl] = pn >> (8 * (pnl - 1)) % 256;
  924.     } while (--pnl);

  925.     ngx_memcpy(nonce, secret->iv.data, secret->iv.len);
  926.     ngx_quic_compute_nonce(nonce, sizeof(nonce), pn);

  927. #ifdef NGX_QUIC_DEBUG_CRYPTO
  928.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  929.                    "quic ad len:%uz %xV", ad.len, &ad);
  930. #endif

  931.     pkt->payload.len = in.len - NGX_QUIC_TAG_LEN;
  932.     pkt->payload.data = pkt->plaintext + ad.len;

  933.     if (ngx_quic_crypto_open(secret, &pkt->payload, nonce, &in, &ad, pkt->log)
  934.         != NGX_OK)
  935.     {
  936.         return NGX_DECLINED;
  937.     }

  938.     if (pkt->payload.len == 0) {
  939.         /*
  940.          * RFC 9000, 12.4.  Frames and Frame Types
  941.          *
  942.          * An endpoint MUST treat receipt of a packet containing no
  943.          * frames as a connection error of type PROTOCOL_VIOLATION.
  944.          */
  945.         ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic zero-length packet");
  946.         pkt->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
  947.         return NGX_ERROR;
  948.     }

  949.     if (pkt->flags & ngx_quic_pkt_rb_mask(pkt->flags)) {
  950.         /*
  951.          * RFC 9000, Reserved Bits
  952.          *
  953.          * An endpoint MUST treat receipt of a packet that has
  954.          * a non-zero value for these bits, after removing both
  955.          * packet and header protection, as a connection error
  956.          * of type PROTOCOL_VIOLATION.
  957.          */
  958.         ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
  959.                       "quic reserved bit set in packet");
  960.         pkt->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
  961.         return NGX_ERROR;
  962.     }

  963. #if defined(NGX_QUIC_DEBUG_CRYPTO) && defined(NGX_QUIC_DEBUG_PACKETS)
  964.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
  965.                    "quic packet payload len:%uz %xV",
  966.                    pkt->payload.len, &pkt->payload);
  967. #endif

  968.     *largest_pn = lpn;

  969.     return NGX_OK;
  970. }