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