12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2021 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#include "shrpx_quic.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#include <sys/types.h>
282c593315Sopenharmony_ci#include <sys/socket.h>
292c593315Sopenharmony_ci#include <netdb.h>
302c593315Sopenharmony_ci#include <netinet/udp.h>
312c593315Sopenharmony_ci
322c593315Sopenharmony_ci#include <array>
332c593315Sopenharmony_ci#include <chrono>
342c593315Sopenharmony_ci
352c593315Sopenharmony_ci#include <ngtcp2/ngtcp2_crypto.h>
362c593315Sopenharmony_ci
372c593315Sopenharmony_ci#include <nghttp3/nghttp3.h>
382c593315Sopenharmony_ci
392c593315Sopenharmony_ci#include <openssl/rand.h>
402c593315Sopenharmony_ci
412c593315Sopenharmony_ci#include "shrpx_config.h"
422c593315Sopenharmony_ci#include "shrpx_log.h"
432c593315Sopenharmony_ci#include "util.h"
442c593315Sopenharmony_ci#include "xsi_strerror.h"
452c593315Sopenharmony_ci
462c593315Sopenharmony_cibool operator==(const ngtcp2_cid &lhs, const ngtcp2_cid &rhs) {
472c593315Sopenharmony_ci  return ngtcp2_cid_eq(&lhs, &rhs);
482c593315Sopenharmony_ci}
492c593315Sopenharmony_ci
502c593315Sopenharmony_cinamespace shrpx {
512c593315Sopenharmony_ci
522c593315Sopenharmony_cingtcp2_tstamp quic_timestamp() {
532c593315Sopenharmony_ci  return std::chrono::duration_cast<std::chrono::nanoseconds>(
542c593315Sopenharmony_ci             std::chrono::steady_clock::now().time_since_epoch())
552c593315Sopenharmony_ci      .count();
562c593315Sopenharmony_ci}
572c593315Sopenharmony_ci
582c593315Sopenharmony_ciint quic_send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa,
592c593315Sopenharmony_ci                     size_t remote_salen, const sockaddr *local_sa,
602c593315Sopenharmony_ci                     size_t local_salen, const ngtcp2_pkt_info &pi,
612c593315Sopenharmony_ci                     const uint8_t *data, size_t datalen, size_t gso_size) {
622c593315Sopenharmony_ci  iovec msg_iov = {const_cast<uint8_t *>(data), datalen};
632c593315Sopenharmony_ci  msghdr msg{};
642c593315Sopenharmony_ci  msg.msg_name = const_cast<sockaddr *>(remote_sa);
652c593315Sopenharmony_ci  msg.msg_namelen = remote_salen;
662c593315Sopenharmony_ci  msg.msg_iov = &msg_iov;
672c593315Sopenharmony_ci  msg.msg_iovlen = 1;
682c593315Sopenharmony_ci
692c593315Sopenharmony_ci  uint8_t msg_ctrl[CMSG_SPACE(sizeof(int)) +
702c593315Sopenharmony_ci#ifdef UDP_SEGMENT
712c593315Sopenharmony_ci                   CMSG_SPACE(sizeof(uint16_t)) +
722c593315Sopenharmony_ci#endif // UDP_SEGMENT
732c593315Sopenharmony_ci                   CMSG_SPACE(sizeof(in6_pktinfo))];
742c593315Sopenharmony_ci
752c593315Sopenharmony_ci  memset(msg_ctrl, 0, sizeof(msg_ctrl));
762c593315Sopenharmony_ci
772c593315Sopenharmony_ci  msg.msg_control = msg_ctrl;
782c593315Sopenharmony_ci  msg.msg_controllen = sizeof(msg_ctrl);
792c593315Sopenharmony_ci
802c593315Sopenharmony_ci  size_t controllen = 0;
812c593315Sopenharmony_ci
822c593315Sopenharmony_ci  auto cm = CMSG_FIRSTHDR(&msg);
832c593315Sopenharmony_ci
842c593315Sopenharmony_ci  switch (local_sa->sa_family) {
852c593315Sopenharmony_ci  case AF_INET: {
862c593315Sopenharmony_ci    controllen += CMSG_SPACE(sizeof(in_pktinfo));
872c593315Sopenharmony_ci    cm->cmsg_level = IPPROTO_IP;
882c593315Sopenharmony_ci    cm->cmsg_type = IP_PKTINFO;
892c593315Sopenharmony_ci    cm->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
902c593315Sopenharmony_ci    in_pktinfo pktinfo{};
912c593315Sopenharmony_ci    auto addrin =
922c593315Sopenharmony_ci        reinterpret_cast<sockaddr_in *>(const_cast<sockaddr *>(local_sa));
932c593315Sopenharmony_ci    pktinfo.ipi_spec_dst = addrin->sin_addr;
942c593315Sopenharmony_ci    memcpy(CMSG_DATA(cm), &pktinfo, sizeof(pktinfo));
952c593315Sopenharmony_ci
962c593315Sopenharmony_ci    break;
972c593315Sopenharmony_ci  }
982c593315Sopenharmony_ci  case AF_INET6: {
992c593315Sopenharmony_ci    controllen += CMSG_SPACE(sizeof(in6_pktinfo));
1002c593315Sopenharmony_ci    cm->cmsg_level = IPPROTO_IPV6;
1012c593315Sopenharmony_ci    cm->cmsg_type = IPV6_PKTINFO;
1022c593315Sopenharmony_ci    cm->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
1032c593315Sopenharmony_ci    in6_pktinfo pktinfo{};
1042c593315Sopenharmony_ci    auto addrin =
1052c593315Sopenharmony_ci        reinterpret_cast<sockaddr_in6 *>(const_cast<sockaddr *>(local_sa));
1062c593315Sopenharmony_ci    pktinfo.ipi6_addr = addrin->sin6_addr;
1072c593315Sopenharmony_ci    memcpy(CMSG_DATA(cm), &pktinfo, sizeof(pktinfo));
1082c593315Sopenharmony_ci
1092c593315Sopenharmony_ci    break;
1102c593315Sopenharmony_ci  }
1112c593315Sopenharmony_ci  default:
1122c593315Sopenharmony_ci    assert(0);
1132c593315Sopenharmony_ci  }
1142c593315Sopenharmony_ci
1152c593315Sopenharmony_ci#ifdef UDP_SEGMENT
1162c593315Sopenharmony_ci  if (gso_size && datalen > gso_size) {
1172c593315Sopenharmony_ci    controllen += CMSG_SPACE(sizeof(uint16_t));
1182c593315Sopenharmony_ci    cm = CMSG_NXTHDR(&msg, cm);
1192c593315Sopenharmony_ci    cm->cmsg_level = SOL_UDP;
1202c593315Sopenharmony_ci    cm->cmsg_type = UDP_SEGMENT;
1212c593315Sopenharmony_ci    cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
1222c593315Sopenharmony_ci    uint16_t n = gso_size;
1232c593315Sopenharmony_ci    memcpy(CMSG_DATA(cm), &n, sizeof(n));
1242c593315Sopenharmony_ci  }
1252c593315Sopenharmony_ci#endif // UDP_SEGMENT
1262c593315Sopenharmony_ci
1272c593315Sopenharmony_ci  controllen += CMSG_SPACE(sizeof(int));
1282c593315Sopenharmony_ci  cm = CMSG_NXTHDR(&msg, cm);
1292c593315Sopenharmony_ci  cm->cmsg_len = CMSG_LEN(sizeof(int));
1302c593315Sopenharmony_ci  unsigned int tos = pi.ecn;
1312c593315Sopenharmony_ci  memcpy(CMSG_DATA(cm), &tos, sizeof(tos));
1322c593315Sopenharmony_ci
1332c593315Sopenharmony_ci  switch (local_sa->sa_family) {
1342c593315Sopenharmony_ci  case AF_INET:
1352c593315Sopenharmony_ci    cm->cmsg_level = IPPROTO_IP;
1362c593315Sopenharmony_ci    cm->cmsg_type = IP_TOS;
1372c593315Sopenharmony_ci
1382c593315Sopenharmony_ci    break;
1392c593315Sopenharmony_ci  case AF_INET6:
1402c593315Sopenharmony_ci    cm->cmsg_level = IPPROTO_IPV6;
1412c593315Sopenharmony_ci    cm->cmsg_type = IPV6_TCLASS;
1422c593315Sopenharmony_ci
1432c593315Sopenharmony_ci    break;
1442c593315Sopenharmony_ci  default:
1452c593315Sopenharmony_ci    assert(0);
1462c593315Sopenharmony_ci  }
1472c593315Sopenharmony_ci
1482c593315Sopenharmony_ci  msg.msg_controllen = controllen;
1492c593315Sopenharmony_ci
1502c593315Sopenharmony_ci  ssize_t nwrite;
1512c593315Sopenharmony_ci
1522c593315Sopenharmony_ci  do {
1532c593315Sopenharmony_ci    nwrite = sendmsg(faddr->fd, &msg, 0);
1542c593315Sopenharmony_ci  } while (nwrite == -1 && errno == EINTR);
1552c593315Sopenharmony_ci
1562c593315Sopenharmony_ci  if (nwrite == -1) {
1572c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
1582c593315Sopenharmony_ci      auto error = errno;
1592c593315Sopenharmony_ci      LOG(INFO) << "sendmsg failed: errno=" << error;
1602c593315Sopenharmony_ci    }
1612c593315Sopenharmony_ci
1622c593315Sopenharmony_ci    return -errno;
1632c593315Sopenharmony_ci  }
1642c593315Sopenharmony_ci
1652c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
1662c593315Sopenharmony_ci    LOG(INFO) << "QUIC sent packet: local="
1672c593315Sopenharmony_ci              << util::to_numeric_addr(local_sa, local_salen)
1682c593315Sopenharmony_ci              << " remote=" << util::to_numeric_addr(remote_sa, remote_salen)
1692c593315Sopenharmony_ci              << " ecn=" << log::hex << pi.ecn << log::dec << " " << nwrite
1702c593315Sopenharmony_ci              << " bytes";
1712c593315Sopenharmony_ci  }
1722c593315Sopenharmony_ci
1732c593315Sopenharmony_ci  return 0;
1742c593315Sopenharmony_ci}
1752c593315Sopenharmony_ci
1762c593315Sopenharmony_ciint generate_quic_retry_connection_id(ngtcp2_cid &cid, size_t cidlen,
1772c593315Sopenharmony_ci                                      const uint8_t *server_id, uint8_t km_id,
1782c593315Sopenharmony_ci                                      const uint8_t *key) {
1792c593315Sopenharmony_ci  assert(cidlen == SHRPX_QUIC_SCIDLEN);
1802c593315Sopenharmony_ci
1812c593315Sopenharmony_ci  if (RAND_bytes(cid.data, cidlen) != 1) {
1822c593315Sopenharmony_ci    return -1;
1832c593315Sopenharmony_ci  }
1842c593315Sopenharmony_ci
1852c593315Sopenharmony_ci  cid.datalen = cidlen;
1862c593315Sopenharmony_ci
1872c593315Sopenharmony_ci  cid.data[0] = (cid.data[0] & 0x3f) | km_id;
1882c593315Sopenharmony_ci
1892c593315Sopenharmony_ci  auto p = cid.data + SHRPX_QUIC_CID_PREFIX_OFFSET;
1902c593315Sopenharmony_ci
1912c593315Sopenharmony_ci  std::copy_n(server_id, SHRPX_QUIC_SERVER_IDLEN, p);
1922c593315Sopenharmony_ci
1932c593315Sopenharmony_ci  return encrypt_quic_connection_id(p, p, key);
1942c593315Sopenharmony_ci}
1952c593315Sopenharmony_ci
1962c593315Sopenharmony_ciint generate_quic_connection_id(ngtcp2_cid &cid, size_t cidlen,
1972c593315Sopenharmony_ci                                const uint8_t *cid_prefix, uint8_t km_id,
1982c593315Sopenharmony_ci                                const uint8_t *key) {
1992c593315Sopenharmony_ci  assert(cidlen == SHRPX_QUIC_SCIDLEN);
2002c593315Sopenharmony_ci
2012c593315Sopenharmony_ci  if (RAND_bytes(cid.data, cidlen) != 1) {
2022c593315Sopenharmony_ci    return -1;
2032c593315Sopenharmony_ci  }
2042c593315Sopenharmony_ci
2052c593315Sopenharmony_ci  cid.datalen = cidlen;
2062c593315Sopenharmony_ci
2072c593315Sopenharmony_ci  cid.data[0] = (cid.data[0] & 0x3f) | km_id;
2082c593315Sopenharmony_ci
2092c593315Sopenharmony_ci  auto p = cid.data + SHRPX_QUIC_CID_PREFIX_OFFSET;
2102c593315Sopenharmony_ci
2112c593315Sopenharmony_ci  std::copy_n(cid_prefix, SHRPX_QUIC_CID_PREFIXLEN, p);
2122c593315Sopenharmony_ci
2132c593315Sopenharmony_ci  return encrypt_quic_connection_id(p, p, key);
2142c593315Sopenharmony_ci}
2152c593315Sopenharmony_ci
2162c593315Sopenharmony_ciint encrypt_quic_connection_id(uint8_t *dest, const uint8_t *src,
2172c593315Sopenharmony_ci                               const uint8_t *key) {
2182c593315Sopenharmony_ci  auto ctx = EVP_CIPHER_CTX_new();
2192c593315Sopenharmony_ci  auto d = defer(EVP_CIPHER_CTX_free, ctx);
2202c593315Sopenharmony_ci
2212c593315Sopenharmony_ci  if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key, nullptr)) {
2222c593315Sopenharmony_ci    return -1;
2232c593315Sopenharmony_ci  }
2242c593315Sopenharmony_ci
2252c593315Sopenharmony_ci  EVP_CIPHER_CTX_set_padding(ctx, 0);
2262c593315Sopenharmony_ci
2272c593315Sopenharmony_ci  int len;
2282c593315Sopenharmony_ci
2292c593315Sopenharmony_ci  if (!EVP_EncryptUpdate(ctx, dest, &len, src, SHRPX_QUIC_DECRYPTED_DCIDLEN) ||
2302c593315Sopenharmony_ci      !EVP_EncryptFinal_ex(ctx, dest + len, &len)) {
2312c593315Sopenharmony_ci    return -1;
2322c593315Sopenharmony_ci  }
2332c593315Sopenharmony_ci
2342c593315Sopenharmony_ci  return 0;
2352c593315Sopenharmony_ci}
2362c593315Sopenharmony_ci
2372c593315Sopenharmony_ciint decrypt_quic_connection_id(uint8_t *dest, const uint8_t *src,
2382c593315Sopenharmony_ci                               const uint8_t *key) {
2392c593315Sopenharmony_ci  auto ctx = EVP_CIPHER_CTX_new();
2402c593315Sopenharmony_ci  auto d = defer(EVP_CIPHER_CTX_free, ctx);
2412c593315Sopenharmony_ci
2422c593315Sopenharmony_ci  if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key, nullptr)) {
2432c593315Sopenharmony_ci    return -1;
2442c593315Sopenharmony_ci  }
2452c593315Sopenharmony_ci
2462c593315Sopenharmony_ci  EVP_CIPHER_CTX_set_padding(ctx, 0);
2472c593315Sopenharmony_ci
2482c593315Sopenharmony_ci  int len;
2492c593315Sopenharmony_ci
2502c593315Sopenharmony_ci  if (!EVP_DecryptUpdate(ctx, dest, &len, src, SHRPX_QUIC_DECRYPTED_DCIDLEN) ||
2512c593315Sopenharmony_ci      !EVP_DecryptFinal_ex(ctx, dest + len, &len)) {
2522c593315Sopenharmony_ci    return -1;
2532c593315Sopenharmony_ci  }
2542c593315Sopenharmony_ci
2552c593315Sopenharmony_ci  return 0;
2562c593315Sopenharmony_ci}
2572c593315Sopenharmony_ci
2582c593315Sopenharmony_ciint generate_quic_hashed_connection_id(ngtcp2_cid &dest,
2592c593315Sopenharmony_ci                                       const Address &remote_addr,
2602c593315Sopenharmony_ci                                       const Address &local_addr,
2612c593315Sopenharmony_ci                                       const ngtcp2_cid &cid) {
2622c593315Sopenharmony_ci  auto ctx = EVP_MD_CTX_new();
2632c593315Sopenharmony_ci  auto d = defer(EVP_MD_CTX_free, ctx);
2642c593315Sopenharmony_ci
2652c593315Sopenharmony_ci  std::array<uint8_t, 32> h;
2662c593315Sopenharmony_ci  unsigned int hlen = EVP_MD_size(EVP_sha256());
2672c593315Sopenharmony_ci
2682c593315Sopenharmony_ci  if (!EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) ||
2692c593315Sopenharmony_ci      !EVP_DigestUpdate(ctx, &remote_addr.su.sa, remote_addr.len) ||
2702c593315Sopenharmony_ci      !EVP_DigestUpdate(ctx, &local_addr.su.sa, local_addr.len) ||
2712c593315Sopenharmony_ci      !EVP_DigestUpdate(ctx, cid.data, cid.datalen) ||
2722c593315Sopenharmony_ci      !EVP_DigestFinal_ex(ctx, h.data(), &hlen)) {
2732c593315Sopenharmony_ci    return -1;
2742c593315Sopenharmony_ci  }
2752c593315Sopenharmony_ci
2762c593315Sopenharmony_ci  assert(hlen == h.size());
2772c593315Sopenharmony_ci
2782c593315Sopenharmony_ci  std::copy_n(std::begin(h), sizeof(dest.data), std::begin(dest.data));
2792c593315Sopenharmony_ci  dest.datalen = sizeof(dest.data);
2802c593315Sopenharmony_ci
2812c593315Sopenharmony_ci  return 0;
2822c593315Sopenharmony_ci}
2832c593315Sopenharmony_ci
2842c593315Sopenharmony_ciint generate_quic_stateless_reset_token(uint8_t *token, const ngtcp2_cid &cid,
2852c593315Sopenharmony_ci                                        const uint8_t *secret,
2862c593315Sopenharmony_ci                                        size_t secretlen) {
2872c593315Sopenharmony_ci  if (ngtcp2_crypto_generate_stateless_reset_token(token, secret, secretlen,
2882c593315Sopenharmony_ci                                                   &cid) != 0) {
2892c593315Sopenharmony_ci    return -1;
2902c593315Sopenharmony_ci  }
2912c593315Sopenharmony_ci
2922c593315Sopenharmony_ci  return 0;
2932c593315Sopenharmony_ci}
2942c593315Sopenharmony_ci
2952c593315Sopenharmony_ciint generate_retry_token(uint8_t *token, size_t &tokenlen, uint32_t version,
2962c593315Sopenharmony_ci                         const sockaddr *sa, socklen_t salen,
2972c593315Sopenharmony_ci                         const ngtcp2_cid &retry_scid, const ngtcp2_cid &odcid,
2982c593315Sopenharmony_ci                         const uint8_t *secret, size_t secretlen) {
2992c593315Sopenharmony_ci  auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
3002c593315Sopenharmony_ci               std::chrono::system_clock::now().time_since_epoch())
3012c593315Sopenharmony_ci               .count();
3022c593315Sopenharmony_ci
3032c593315Sopenharmony_ci  auto stokenlen = ngtcp2_crypto_generate_retry_token(
3042c593315Sopenharmony_ci      token, secret, secretlen, version, sa, salen, &retry_scid, &odcid, t);
3052c593315Sopenharmony_ci  if (stokenlen < 0) {
3062c593315Sopenharmony_ci    return -1;
3072c593315Sopenharmony_ci  }
3082c593315Sopenharmony_ci
3092c593315Sopenharmony_ci  tokenlen = stokenlen;
3102c593315Sopenharmony_ci
3112c593315Sopenharmony_ci  return 0;
3122c593315Sopenharmony_ci}
3132c593315Sopenharmony_ci
3142c593315Sopenharmony_ciint verify_retry_token(ngtcp2_cid &odcid, const uint8_t *token, size_t tokenlen,
3152c593315Sopenharmony_ci                       uint32_t version, const ngtcp2_cid &dcid,
3162c593315Sopenharmony_ci                       const sockaddr *sa, socklen_t salen,
3172c593315Sopenharmony_ci                       const uint8_t *secret, size_t secretlen) {
3182c593315Sopenharmony_ci
3192c593315Sopenharmony_ci  auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
3202c593315Sopenharmony_ci               std::chrono::system_clock::now().time_since_epoch())
3212c593315Sopenharmony_ci               .count();
3222c593315Sopenharmony_ci
3232c593315Sopenharmony_ci  if (ngtcp2_crypto_verify_retry_token(&odcid, token, tokenlen, secret,
3242c593315Sopenharmony_ci                                       secretlen, version, sa, salen, &dcid,
3252c593315Sopenharmony_ci                                       10 * NGTCP2_SECONDS, t) != 0) {
3262c593315Sopenharmony_ci    return -1;
3272c593315Sopenharmony_ci  }
3282c593315Sopenharmony_ci
3292c593315Sopenharmony_ci  return 0;
3302c593315Sopenharmony_ci}
3312c593315Sopenharmony_ci
3322c593315Sopenharmony_ciint generate_token(uint8_t *token, size_t &tokenlen, const sockaddr *sa,
3332c593315Sopenharmony_ci                   size_t salen, const uint8_t *secret, size_t secretlen) {
3342c593315Sopenharmony_ci  auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
3352c593315Sopenharmony_ci               std::chrono::system_clock::now().time_since_epoch())
3362c593315Sopenharmony_ci               .count();
3372c593315Sopenharmony_ci
3382c593315Sopenharmony_ci  auto stokenlen = ngtcp2_crypto_generate_regular_token(
3392c593315Sopenharmony_ci      token, secret, secretlen, sa, salen, t);
3402c593315Sopenharmony_ci  if (stokenlen < 0) {
3412c593315Sopenharmony_ci    return -1;
3422c593315Sopenharmony_ci  }
3432c593315Sopenharmony_ci
3442c593315Sopenharmony_ci  tokenlen = stokenlen;
3452c593315Sopenharmony_ci
3462c593315Sopenharmony_ci  return 0;
3472c593315Sopenharmony_ci}
3482c593315Sopenharmony_ci
3492c593315Sopenharmony_ciint verify_token(const uint8_t *token, size_t tokenlen, const sockaddr *sa,
3502c593315Sopenharmony_ci                 socklen_t salen, const uint8_t *secret, size_t secretlen) {
3512c593315Sopenharmony_ci  auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
3522c593315Sopenharmony_ci               std::chrono::system_clock::now().time_since_epoch())
3532c593315Sopenharmony_ci               .count();
3542c593315Sopenharmony_ci
3552c593315Sopenharmony_ci  if (ngtcp2_crypto_verify_regular_token(token, tokenlen, secret, secretlen, sa,
3562c593315Sopenharmony_ci                                         salen, 3600 * NGTCP2_SECONDS,
3572c593315Sopenharmony_ci                                         t) != 0) {
3582c593315Sopenharmony_ci    return -1;
3592c593315Sopenharmony_ci  }
3602c593315Sopenharmony_ci
3612c593315Sopenharmony_ci  return 0;
3622c593315Sopenharmony_ci}
3632c593315Sopenharmony_ci
3642c593315Sopenharmony_ciint generate_quic_connection_id_encryption_key(uint8_t *key, size_t keylen,
3652c593315Sopenharmony_ci                                               const uint8_t *secret,
3662c593315Sopenharmony_ci                                               size_t secretlen,
3672c593315Sopenharmony_ci                                               const uint8_t *salt,
3682c593315Sopenharmony_ci                                               size_t saltlen) {
3692c593315Sopenharmony_ci  constexpr uint8_t info[] = "connection id encryption key";
3702c593315Sopenharmony_ci  ngtcp2_crypto_md sha256;
3712c593315Sopenharmony_ci  ngtcp2_crypto_md_init(
3722c593315Sopenharmony_ci      &sha256, reinterpret_cast<void *>(const_cast<EVP_MD *>(EVP_sha256())));
3732c593315Sopenharmony_ci
3742c593315Sopenharmony_ci  if (ngtcp2_crypto_hkdf(key, keylen, &sha256, secret, secretlen, salt, saltlen,
3752c593315Sopenharmony_ci                         info, str_size(info)) != 0) {
3762c593315Sopenharmony_ci    return -1;
3772c593315Sopenharmony_ci  }
3782c593315Sopenharmony_ci
3792c593315Sopenharmony_ci  return 0;
3802c593315Sopenharmony_ci}
3812c593315Sopenharmony_ci
3822c593315Sopenharmony_ciconst QUICKeyingMaterial *
3832c593315Sopenharmony_ciselect_quic_keying_material(const QUICKeyingMaterials &qkms, uint8_t km_id) {
3842c593315Sopenharmony_ci  for (auto &qkm : qkms.keying_materials) {
3852c593315Sopenharmony_ci    if (km_id == qkm.id) {
3862c593315Sopenharmony_ci      return &qkm;
3872c593315Sopenharmony_ci    }
3882c593315Sopenharmony_ci  }
3892c593315Sopenharmony_ci
3902c593315Sopenharmony_ci  return &qkms.keying_materials.front();
3912c593315Sopenharmony_ci}
3922c593315Sopenharmony_ci
3932c593315Sopenharmony_ci} // namespace shrpx
394