src/event/quic/ngx_event_quic_ssl.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. #if defined OPENSSL_IS_BORINGSSL                                              \
  9.     || defined LIBRESSL_VERSION_NUMBER                                        \
  10.     || NGX_QUIC_OPENSSL_COMPAT
  11. #define NGX_QUIC_BORINGSSL_API   1
  12. #endif


  13. /*
  14. * RFC 9000, 7.5.  Cryptographic Message Buffering
  15. *
  16. * Implementations MUST support buffering at least 4096 bytes of data
  17. */
  18. #define NGX_QUIC_MAX_BUFFERED    65535


  19. #if (NGX_QUIC_BORINGSSL_API)
  20. static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
  21.     enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
  22.     const uint8_t *secret, size_t secret_len);
  23. static int ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
  24.     enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
  25.     const uint8_t *secret, size_t secret_len);
  26. #else
  27. static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
  28.     enum ssl_encryption_level_t level, const uint8_t *read_secret,
  29.     const uint8_t *write_secret, size_t secret_len);
  30. #endif

  31. static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
  32.     enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
  33. static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
  34. static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
  35.     enum ssl_encryption_level_t level, uint8_t alert);
  36. static ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
  37.     enum ssl_encryption_level_t level);


  38. #if (NGX_QUIC_BORINGSSL_API)

  39. static int
  40. ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
  41.     enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
  42.     const uint8_t *rsecret, size_t secret_len)
  43. {
  44.     ngx_connection_t       *c;
  45.     ngx_quic_connection_t  *qc;

  46.     c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
  47.     qc = ngx_quic_get_connection(c);

  48.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  49.                    "quic ngx_quic_set_read_secret() level:%d", level);
  50. #ifdef NGX_QUIC_DEBUG_CRYPTO
  51.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  52.                    "quic read secret len:%uz %*xs", secret_len,
  53.                    secret_len, rsecret);
  54. #endif

  55.     if (ngx_quic_keys_set_encryption_secret(c->log, 0, qc->keys, level,
  56.                                             cipher, rsecret, secret_len)
  57.         != NGX_OK)
  58.     {
  59.         return 0;
  60.     }

  61.     return 1;
  62. }


  63. static int
  64. ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
  65.     enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
  66.     const uint8_t *wsecret, size_t secret_len)
  67. {
  68.     ngx_connection_t       *c;
  69.     ngx_quic_connection_t  *qc;

  70.     c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
  71.     qc = ngx_quic_get_connection(c);

  72.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  73.                    "quic ngx_quic_set_write_secret() level:%d", level);
  74. #ifdef NGX_QUIC_DEBUG_CRYPTO
  75.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  76.                    "quic write secret len:%uz %*xs", secret_len,
  77.                    secret_len, wsecret);
  78. #endif

  79.     if (ngx_quic_keys_set_encryption_secret(c->log, 1, qc->keys, level,
  80.                                             cipher, wsecret, secret_len)
  81.         != NGX_OK)
  82.     {
  83.         return 0;
  84.     }

  85.     return 1;
  86. }

  87. #else

  88. static int
  89. ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
  90.     enum ssl_encryption_level_t level, const uint8_t *rsecret,
  91.     const uint8_t *wsecret, size_t secret_len)
  92. {
  93.     ngx_connection_t       *c;
  94.     const SSL_CIPHER       *cipher;
  95.     ngx_quic_connection_t  *qc;

  96.     c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
  97.     qc = ngx_quic_get_connection(c);

  98.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  99.                    "quic ngx_quic_set_encryption_secrets() level:%d", level);
  100. #ifdef NGX_QUIC_DEBUG_CRYPTO
  101.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  102.                    "quic read secret len:%uz %*xs", secret_len,
  103.                    secret_len, rsecret);
  104. #endif

  105.     cipher = SSL_get_current_cipher(ssl_conn);

  106.     if (ngx_quic_keys_set_encryption_secret(c->log, 0, qc->keys, level,
  107.                                             cipher, rsecret, secret_len)
  108.         != NGX_OK)
  109.     {
  110.         return 0;
  111.     }

  112.     if (level == ssl_encryption_early_data) {
  113.         return 1;
  114.     }

  115. #ifdef NGX_QUIC_DEBUG_CRYPTO
  116.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  117.                    "quic write secret len:%uz %*xs", secret_len,
  118.                    secret_len, wsecret);
  119. #endif

  120.     if (ngx_quic_keys_set_encryption_secret(c->log, 1, qc->keys, level,
  121.                                             cipher, wsecret, secret_len)
  122.         != NGX_OK)
  123.     {
  124.         return 0;
  125.     }

  126.     return 1;
  127. }

  128. #endif


  129. static int
  130. ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
  131.     enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
  132. {
  133.     u_char                 *p, *end;
  134.     size_t                  client_params_len;
  135.     ngx_chain_t            *out;
  136.     const uint8_t          *client_params;
  137.     ngx_quic_tp_t           ctp;
  138.     ngx_quic_frame_t       *frame;
  139.     ngx_connection_t       *c;
  140.     ngx_quic_send_ctx_t    *ctx;
  141.     ngx_quic_connection_t  *qc;
  142. #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
  143.     unsigned int            alpn_len;
  144.     const unsigned char    *alpn_data;
  145. #endif

  146.     c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
  147.     qc = ngx_quic_get_connection(c);

  148.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  149.                    "quic ngx_quic_add_handshake_data");

  150.     if (!qc->client_tp_done) {
  151.         /*
  152.          * things to do once during handshake: check ALPN and transport
  153.          * parameters; we want to break handshake if something is wrong
  154.          * here;
  155.          */

  156. #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)

  157.         SSL_get0_alpn_selected(ssl_conn, &alpn_data, &alpn_len);

  158.         if (alpn_len == 0) {
  159.             qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
  160.             qc->error_reason = "unsupported protocol in ALPN extension";

  161.             ngx_log_error(NGX_LOG_INFO, c->log, 0,
  162.                           "quic unsupported protocol in ALPN extension");
  163.             return 0;
  164.         }

  165. #endif

  166.         SSL_get_peer_quic_transport_params(ssl_conn, &client_params,
  167.                                            &client_params_len);

  168.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  169.                        "quic SSL_get_peer_quic_transport_params():"
  170.                        " params_len:%ui", client_params_len);

  171.         if (client_params_len == 0) {
  172.             /* RFC 9001, 8.2.  QUIC Transport Parameters Extension */
  173.             qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
  174.             qc->error_reason = "missing transport parameters";

  175.             ngx_log_error(NGX_LOG_INFO, c->log, 0,
  176.                           "missing transport parameters");
  177.             return 0;
  178.         }

  179.         p = (u_char *) client_params;
  180.         end = p + client_params_len;

  181.         /* defaults for parameters not sent by client */
  182.         ngx_memcpy(&ctp, &qc->ctp, sizeof(ngx_quic_tp_t));

  183.         if (ngx_quic_parse_transport_params(p, end, &ctp, c->log)
  184.             != NGX_OK)
  185.         {
  186.             qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
  187.             qc->error_reason = "failed to process transport parameters";

  188.             return 0;
  189.         }

  190.         if (ngx_quic_apply_transport_params(c, &ctp) != NGX_OK) {
  191.             return 0;
  192.         }

  193.         qc->client_tp_done = 1;
  194.     }

  195.     ctx = ngx_quic_get_send_ctx(qc, level);

  196.     out = ngx_quic_copy_buffer(c, (u_char *) data, len);
  197.     if (out == NGX_CHAIN_ERROR) {
  198.         return 0;
  199.     }

  200.     frame = ngx_quic_alloc_frame(c);
  201.     if (frame == NULL) {
  202.         return 0;
  203.     }

  204.     frame->data = out;
  205.     frame->level = level;
  206.     frame->type = NGX_QUIC_FT_CRYPTO;
  207.     frame->u.crypto.offset = ctx->crypto_sent;
  208.     frame->u.crypto.length = len;

  209.     ctx->crypto_sent += len;

  210.     ngx_quic_queue_frame(qc, frame);

  211.     return 1;
  212. }


  213. static int
  214. ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
  215. {
  216. #if (NGX_DEBUG)
  217.     ngx_connection_t  *c;

  218.     c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);

  219.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  220.                    "quic ngx_quic_flush_flight()");
  221. #endif
  222.     return 1;
  223. }


  224. static int
  225. ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
  226.     uint8_t alert)
  227. {
  228.     ngx_connection_t       *c;
  229.     ngx_quic_connection_t  *qc;

  230.     c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);

  231.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  232.                    "quic ngx_quic_send_alert() level:%s alert:%d",
  233.                    ngx_quic_level_name(level), (int) alert);

  234.     /* already closed on regular shutdown */

  235.     qc = ngx_quic_get_connection(c);
  236.     if (qc == NULL) {
  237.         return 1;
  238.     }

  239.     qc->error = NGX_QUIC_ERR_CRYPTO(alert);
  240.     qc->error_reason = "handshake failed";

  241.     return 1;
  242. }


  243. ngx_int_t
  244. ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
  245.     ngx_quic_frame_t *frame)
  246. {
  247.     uint64_t                  last;
  248.     ngx_chain_t              *cl;
  249.     ngx_quic_send_ctx_t      *ctx;
  250.     ngx_quic_connection_t    *qc;
  251.     ngx_quic_crypto_frame_t  *f;

  252.     qc = ngx_quic_get_connection(c);

  253.     if (!ngx_quic_keys_available(qc->keys, pkt->level, 0)) {
  254.         return NGX_OK;
  255.     }

  256.     ctx = ngx_quic_get_send_ctx(qc, pkt->level);
  257.     f = &frame->u.crypto;

  258.     /* no overflow since both values are 62-bit */
  259.     last = f->offset + f->length;

  260.     if (last > ctx->crypto.offset + NGX_QUIC_MAX_BUFFERED) {
  261.         qc->error = NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED;
  262.         return NGX_ERROR;
  263.     }

  264.     if (last <= ctx->crypto.offset) {
  265.         if (pkt->level == ssl_encryption_initial) {
  266.             /* speeding up handshake completion */

  267.             if (!ngx_queue_empty(&ctx->sent)) {
  268.                 ngx_quic_resend_frames(c, ctx);

  269.                 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
  270.                 while (!ngx_queue_empty(&ctx->sent)) {
  271.                     ngx_quic_resend_frames(c, ctx);
  272.                 }
  273.             }
  274.         }

  275.         return NGX_OK;
  276.     }

  277.     if (f->offset == ctx->crypto.offset) {
  278.         if (ngx_quic_crypto_input(c, frame->data, pkt->level) != NGX_OK) {
  279.             return NGX_ERROR;
  280.         }

  281.         ngx_quic_skip_buffer(c, &ctx->crypto, last);

  282.     } else {
  283.         if (ngx_quic_write_buffer(c, &ctx->crypto, frame->data, f->length,
  284.                                   f->offset)
  285.             == NGX_CHAIN_ERROR)
  286.         {
  287.             return NGX_ERROR;
  288.         }
  289.     }

  290.     cl = ngx_quic_read_buffer(c, &ctx->crypto, (uint64_t) -1);

  291.     if (cl) {
  292.         if (ngx_quic_crypto_input(c, cl, pkt->level) != NGX_OK) {
  293.             return NGX_ERROR;
  294.         }

  295.         ngx_quic_free_chain(c, cl);
  296.     }

  297.     return NGX_OK;
  298. }


  299. static ngx_int_t
  300. ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
  301.     enum ssl_encryption_level_t level)
  302. {
  303.     int                     n, sslerr;
  304.     ngx_buf_t              *b;
  305.     ngx_chain_t            *cl;
  306.     ngx_ssl_conn_t         *ssl_conn;
  307.     ngx_quic_frame_t       *frame;
  308.     ngx_quic_connection_t  *qc;

  309.     qc = ngx_quic_get_connection(c);

  310.     ssl_conn = c->ssl->connection;

  311.     for (cl = data; cl; cl = cl->next) {
  312.         b = cl->buf;

  313.         if (!SSL_provide_quic_data(ssl_conn, level, b->pos, b->last - b->pos)) {
  314.             ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
  315.                           "SSL_provide_quic_data() failed");
  316.             return NGX_ERROR;
  317.         }
  318.     }

  319.     n = SSL_do_handshake(ssl_conn);

  320.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);

  321.     if (n <= 0) {
  322.         sslerr = SSL_get_error(ssl_conn, n);

  323.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
  324.                        sslerr);

  325.         if (sslerr != SSL_ERROR_WANT_READ) {

  326.             if (c->ssl->handshake_rejected) {
  327.                 ngx_connection_error(c, 0, "handshake rejected");
  328.                 ERR_clear_error();

  329.                 return NGX_ERROR;
  330.             }

  331.             ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
  332.             return NGX_ERROR;
  333.         }
  334.     }

  335.     if (n <= 0 || SSL_in_init(ssl_conn)) {
  336.         if (ngx_quic_keys_available(qc->keys, ssl_encryption_early_data, 0)
  337.             && qc->client_tp_done)
  338.         {
  339.             if (ngx_quic_init_streams(c) != NGX_OK) {
  340.                 return NGX_ERROR;
  341.             }
  342.         }

  343.         return NGX_OK;
  344.     }

  345. #if (NGX_DEBUG)
  346.     ngx_ssl_handshake_log(c);
  347. #endif

  348.     c->ssl->handshaked = 1;

  349.     frame = ngx_quic_alloc_frame(c);
  350.     if (frame == NULL) {
  351.         return NGX_ERROR;
  352.     }

  353.     frame->level = ssl_encryption_application;
  354.     frame->type = NGX_QUIC_FT_HANDSHAKE_DONE;
  355.     ngx_quic_queue_frame(qc, frame);

  356.     if (qc->conf->retry) {
  357.         if (ngx_quic_send_new_token(c, qc->path) != NGX_OK) {
  358.             return NGX_ERROR;
  359.         }
  360.     }

  361.     /*
  362.      * RFC 9001, 9.5.  Header Protection Timing Side Channels
  363.      *
  364.      * Generating next keys before a key update is received.
  365.      */

  366.     ngx_post_event(&qc->key_update, &ngx_posted_events);

  367.     /*
  368.      * RFC 9001, 4.9.2.  Discarding Handshake Keys
  369.      *
  370.      * An endpoint MUST discard its Handshake keys
  371.      * when the TLS handshake is confirmed.
  372.      */
  373.     ngx_quic_discard_ctx(c, ssl_encryption_handshake);

  374.     ngx_quic_discover_path_mtu(c, qc->path);

  375.     /* start accepting clients on negotiated number of server ids */
  376.     if (ngx_quic_create_sockets(c) != NGX_OK) {
  377.         return NGX_ERROR;
  378.     }

  379.     if (ngx_quic_init_streams(c) != NGX_OK) {
  380.         return NGX_ERROR;
  381.     }

  382.     return NGX_OK;
  383. }


  384. ngx_int_t
  385. ngx_quic_init_connection(ngx_connection_t *c)
  386. {
  387.     u_char                  *p;
  388.     size_t                   clen;
  389.     ssize_t                  len;
  390.     ngx_str_t                dcid;
  391.     ngx_ssl_conn_t          *ssl_conn;
  392.     ngx_quic_socket_t       *qsock;
  393.     ngx_quic_connection_t   *qc;
  394.     static SSL_QUIC_METHOD   quic_method;

  395.     qc = ngx_quic_get_connection(c);

  396.     if (ngx_ssl_create_connection(qc->conf->ssl, c, 0) != NGX_OK) {
  397.         return NGX_ERROR;
  398.     }

  399.     c->ssl->no_wait_shutdown = 1;

  400.     ssl_conn = c->ssl->connection;

  401.     if (!quic_method.send_alert) {
  402. #if (NGX_QUIC_BORINGSSL_API)
  403.         quic_method.set_read_secret = ngx_quic_set_read_secret;
  404.         quic_method.set_write_secret = ngx_quic_set_write_secret;
  405. #else
  406.         quic_method.set_encryption_secrets = ngx_quic_set_encryption_secrets;
  407. #endif
  408.         quic_method.add_handshake_data = ngx_quic_add_handshake_data;
  409.         quic_method.flush_flight = ngx_quic_flush_flight;
  410.         quic_method.send_alert = ngx_quic_send_alert;
  411.     }

  412.     if (SSL_set_quic_method(ssl_conn, &quic_method) == 0) {
  413.         ngx_log_error(NGX_LOG_INFO, c->log, 0,
  414.                       "quic SSL_set_quic_method() failed");
  415.         return NGX_ERROR;
  416.     }

  417. #ifdef OPENSSL_INFO_QUIC
  418.     if (SSL_CTX_get_max_early_data(qc->conf->ssl->ctx)) {
  419.         SSL_set_quic_early_data_enabled(ssl_conn, 1);
  420.     }
  421. #endif

  422.     qsock = ngx_quic_get_socket(c);

  423.     dcid.data = qsock->sid.id;
  424.     dcid.len = qsock->sid.len;

  425.     if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key, qc->tp.sr_token)
  426.         != NGX_OK)
  427.     {
  428.         return NGX_ERROR;
  429.     }

  430.     len = ngx_quic_create_transport_params(NULL, NULL, &qc->tp, &clen);
  431.     /* always succeeds */

  432.     p = ngx_pnalloc(c->pool, len);
  433.     if (p == NULL) {
  434.         return NGX_ERROR;
  435.     }

  436.     len = ngx_quic_create_transport_params(p, p + len, &qc->tp, NULL);
  437.     if (len < 0) {
  438.         return NGX_ERROR;
  439.     }

  440. #ifdef NGX_QUIC_DEBUG_PACKETS
  441.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  442.                    "quic transport parameters len:%uz %*xs", len, len, p);
  443. #endif

  444.     if (SSL_set_quic_transport_params(ssl_conn, p, len) == 0) {
  445.         ngx_log_error(NGX_LOG_INFO, c->log, 0,
  446.                       "quic SSL_set_quic_transport_params() failed");
  447.         return NGX_ERROR;
  448.     }

  449. #ifdef OPENSSL_IS_BORINGSSL
  450.     if (SSL_set_quic_early_data_context(ssl_conn, p, clen) == 0) {
  451.         ngx_log_error(NGX_LOG_INFO, c->log, 0,
  452.                       "quic SSL_set_quic_early_data_context() failed");
  453.         return NGX_ERROR;
  454.     }
  455. #endif

  456.     return NGX_OK;
  457. }