1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2021 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "shrpx_quic.h"
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netdb.h>
30 #include <netinet/udp.h>
31
32 #include <array>
33 #include <chrono>
34
35 #include <ngtcp2/ngtcp2_crypto.h>
36
37 #include <nghttp3/nghttp3.h>
38
39 #include <openssl/rand.h>
40
41 #include "shrpx_config.h"
42 #include "shrpx_log.h"
43 #include "util.h"
44 #include "xsi_strerror.h"
45
operator ==(const ngtcp2_cid & lhs,const ngtcp2_cid & rhs)46 bool operator==(const ngtcp2_cid &lhs, const ngtcp2_cid &rhs) {
47 return ngtcp2_cid_eq(&lhs, &rhs);
48 }
49
50 namespace shrpx {
51
quic_timestamp()52 ngtcp2_tstamp quic_timestamp() {
53 return std::chrono::duration_cast<std::chrono::nanoseconds>(
54 std::chrono::steady_clock::now().time_since_epoch())
55 .count();
56 }
57
quic_send_packet(const UpstreamAddr * faddr,const sockaddr * remote_sa,size_t remote_salen,const sockaddr * local_sa,size_t local_salen,const ngtcp2_pkt_info & pi,const uint8_t * data,size_t datalen,size_t gso_size)58 int quic_send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa,
59 size_t remote_salen, const sockaddr *local_sa,
60 size_t local_salen, const ngtcp2_pkt_info &pi,
61 const uint8_t *data, size_t datalen, size_t gso_size) {
62 iovec msg_iov = {const_cast<uint8_t *>(data), datalen};
63 msghdr msg{};
64 msg.msg_name = const_cast<sockaddr *>(remote_sa);
65 msg.msg_namelen = remote_salen;
66 msg.msg_iov = &msg_iov;
67 msg.msg_iovlen = 1;
68
69 uint8_t msg_ctrl[CMSG_SPACE(sizeof(int)) +
70 #ifdef UDP_SEGMENT
71 CMSG_SPACE(sizeof(uint16_t)) +
72 #endif // UDP_SEGMENT
73 CMSG_SPACE(sizeof(in6_pktinfo))];
74
75 memset(msg_ctrl, 0, sizeof(msg_ctrl));
76
77 msg.msg_control = msg_ctrl;
78 msg.msg_controllen = sizeof(msg_ctrl);
79
80 size_t controllen = 0;
81
82 auto cm = CMSG_FIRSTHDR(&msg);
83
84 switch (local_sa->sa_family) {
85 case AF_INET: {
86 controllen += CMSG_SPACE(sizeof(in_pktinfo));
87 cm->cmsg_level = IPPROTO_IP;
88 cm->cmsg_type = IP_PKTINFO;
89 cm->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
90 in_pktinfo pktinfo{};
91 auto addrin =
92 reinterpret_cast<sockaddr_in *>(const_cast<sockaddr *>(local_sa));
93 pktinfo.ipi_spec_dst = addrin->sin_addr;
94 memcpy(CMSG_DATA(cm), &pktinfo, sizeof(pktinfo));
95
96 break;
97 }
98 case AF_INET6: {
99 controllen += CMSG_SPACE(sizeof(in6_pktinfo));
100 cm->cmsg_level = IPPROTO_IPV6;
101 cm->cmsg_type = IPV6_PKTINFO;
102 cm->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
103 in6_pktinfo pktinfo{};
104 auto addrin =
105 reinterpret_cast<sockaddr_in6 *>(const_cast<sockaddr *>(local_sa));
106 pktinfo.ipi6_addr = addrin->sin6_addr;
107 memcpy(CMSG_DATA(cm), &pktinfo, sizeof(pktinfo));
108
109 break;
110 }
111 default:
112 assert(0);
113 }
114
115 #ifdef UDP_SEGMENT
116 if (gso_size && datalen > gso_size) {
117 controllen += CMSG_SPACE(sizeof(uint16_t));
118 cm = CMSG_NXTHDR(&msg, cm);
119 cm->cmsg_level = SOL_UDP;
120 cm->cmsg_type = UDP_SEGMENT;
121 cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
122 uint16_t n = gso_size;
123 memcpy(CMSG_DATA(cm), &n, sizeof(n));
124 }
125 #endif // UDP_SEGMENT
126
127 controllen += CMSG_SPACE(sizeof(int));
128 cm = CMSG_NXTHDR(&msg, cm);
129 cm->cmsg_len = CMSG_LEN(sizeof(int));
130 unsigned int tos = pi.ecn;
131 memcpy(CMSG_DATA(cm), &tos, sizeof(tos));
132
133 switch (local_sa->sa_family) {
134 case AF_INET:
135 cm->cmsg_level = IPPROTO_IP;
136 cm->cmsg_type = IP_TOS;
137
138 break;
139 case AF_INET6:
140 cm->cmsg_level = IPPROTO_IPV6;
141 cm->cmsg_type = IPV6_TCLASS;
142
143 break;
144 default:
145 assert(0);
146 }
147
148 msg.msg_controllen = controllen;
149
150 ssize_t nwrite;
151
152 do {
153 nwrite = sendmsg(faddr->fd, &msg, 0);
154 } while (nwrite == -1 && errno == EINTR);
155
156 if (nwrite == -1) {
157 if (LOG_ENABLED(INFO)) {
158 auto error = errno;
159 LOG(INFO) << "sendmsg failed: errno=" << error;
160 }
161
162 return -errno;
163 }
164
165 if (LOG_ENABLED(INFO)) {
166 LOG(INFO) << "QUIC sent packet: local="
167 << util::to_numeric_addr(local_sa, local_salen)
168 << " remote=" << util::to_numeric_addr(remote_sa, remote_salen)
169 << " ecn=" << log::hex << pi.ecn << log::dec << " " << nwrite
170 << " bytes";
171 }
172
173 return 0;
174 }
175
generate_quic_retry_connection_id(ngtcp2_cid & cid,size_t cidlen,const uint8_t * server_id,uint8_t km_id,const uint8_t * key)176 int generate_quic_retry_connection_id(ngtcp2_cid &cid, size_t cidlen,
177 const uint8_t *server_id, uint8_t km_id,
178 const uint8_t *key) {
179 assert(cidlen == SHRPX_QUIC_SCIDLEN);
180
181 if (RAND_bytes(cid.data, cidlen) != 1) {
182 return -1;
183 }
184
185 cid.datalen = cidlen;
186
187 cid.data[0] = (cid.data[0] & 0x3f) | km_id;
188
189 auto p = cid.data + SHRPX_QUIC_CID_PREFIX_OFFSET;
190
191 std::copy_n(server_id, SHRPX_QUIC_SERVER_IDLEN, p);
192
193 return encrypt_quic_connection_id(p, p, key);
194 }
195
generate_quic_connection_id(ngtcp2_cid & cid,size_t cidlen,const uint8_t * cid_prefix,uint8_t km_id,const uint8_t * key)196 int generate_quic_connection_id(ngtcp2_cid &cid, size_t cidlen,
197 const uint8_t *cid_prefix, uint8_t km_id,
198 const uint8_t *key) {
199 assert(cidlen == SHRPX_QUIC_SCIDLEN);
200
201 if (RAND_bytes(cid.data, cidlen) != 1) {
202 return -1;
203 }
204
205 cid.datalen = cidlen;
206
207 cid.data[0] = (cid.data[0] & 0x3f) | km_id;
208
209 auto p = cid.data + SHRPX_QUIC_CID_PREFIX_OFFSET;
210
211 std::copy_n(cid_prefix, SHRPX_QUIC_CID_PREFIXLEN, p);
212
213 return encrypt_quic_connection_id(p, p, key);
214 }
215
encrypt_quic_connection_id(uint8_t * dest,const uint8_t * src,const uint8_t * key)216 int encrypt_quic_connection_id(uint8_t *dest, const uint8_t *src,
217 const uint8_t *key) {
218 auto ctx = EVP_CIPHER_CTX_new();
219 auto d = defer(EVP_CIPHER_CTX_free, ctx);
220
221 if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key, nullptr)) {
222 return -1;
223 }
224
225 EVP_CIPHER_CTX_set_padding(ctx, 0);
226
227 int len;
228
229 if (!EVP_EncryptUpdate(ctx, dest, &len, src, SHRPX_QUIC_DECRYPTED_DCIDLEN) ||
230 !EVP_EncryptFinal_ex(ctx, dest + len, &len)) {
231 return -1;
232 }
233
234 return 0;
235 }
236
decrypt_quic_connection_id(uint8_t * dest,const uint8_t * src,const uint8_t * key)237 int decrypt_quic_connection_id(uint8_t *dest, const uint8_t *src,
238 const uint8_t *key) {
239 auto ctx = EVP_CIPHER_CTX_new();
240 auto d = defer(EVP_CIPHER_CTX_free, ctx);
241
242 if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key, nullptr)) {
243 return -1;
244 }
245
246 EVP_CIPHER_CTX_set_padding(ctx, 0);
247
248 int len;
249
250 if (!EVP_DecryptUpdate(ctx, dest, &len, src, SHRPX_QUIC_DECRYPTED_DCIDLEN) ||
251 !EVP_DecryptFinal_ex(ctx, dest + len, &len)) {
252 return -1;
253 }
254
255 return 0;
256 }
257
generate_quic_hashed_connection_id(ngtcp2_cid & dest,const Address & remote_addr,const Address & local_addr,const ngtcp2_cid & cid)258 int generate_quic_hashed_connection_id(ngtcp2_cid &dest,
259 const Address &remote_addr,
260 const Address &local_addr,
261 const ngtcp2_cid &cid) {
262 auto ctx = EVP_MD_CTX_new();
263 auto d = defer(EVP_MD_CTX_free, ctx);
264
265 std::array<uint8_t, 32> h;
266 unsigned int hlen = EVP_MD_size(EVP_sha256());
267
268 if (!EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) ||
269 !EVP_DigestUpdate(ctx, &remote_addr.su.sa, remote_addr.len) ||
270 !EVP_DigestUpdate(ctx, &local_addr.su.sa, local_addr.len) ||
271 !EVP_DigestUpdate(ctx, cid.data, cid.datalen) ||
272 !EVP_DigestFinal_ex(ctx, h.data(), &hlen)) {
273 return -1;
274 }
275
276 assert(hlen == h.size());
277
278 std::copy_n(std::begin(h), sizeof(dest.data), std::begin(dest.data));
279 dest.datalen = sizeof(dest.data);
280
281 return 0;
282 }
283
generate_quic_stateless_reset_token(uint8_t * token,const ngtcp2_cid & cid,const uint8_t * secret,size_t secretlen)284 int generate_quic_stateless_reset_token(uint8_t *token, const ngtcp2_cid &cid,
285 const uint8_t *secret,
286 size_t secretlen) {
287 if (ngtcp2_crypto_generate_stateless_reset_token(token, secret, secretlen,
288 &cid) != 0) {
289 return -1;
290 }
291
292 return 0;
293 }
294
generate_retry_token(uint8_t * token,size_t & tokenlen,uint32_t version,const sockaddr * sa,socklen_t salen,const ngtcp2_cid & retry_scid,const ngtcp2_cid & odcid,const uint8_t * secret,size_t secretlen)295 int generate_retry_token(uint8_t *token, size_t &tokenlen, uint32_t version,
296 const sockaddr *sa, socklen_t salen,
297 const ngtcp2_cid &retry_scid, const ngtcp2_cid &odcid,
298 const uint8_t *secret, size_t secretlen) {
299 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
300 std::chrono::system_clock::now().time_since_epoch())
301 .count();
302
303 auto stokenlen = ngtcp2_crypto_generate_retry_token(
304 token, secret, secretlen, version, sa, salen, &retry_scid, &odcid, t);
305 if (stokenlen < 0) {
306 return -1;
307 }
308
309 tokenlen = stokenlen;
310
311 return 0;
312 }
313
verify_retry_token(ngtcp2_cid & odcid,const uint8_t * token,size_t tokenlen,uint32_t version,const ngtcp2_cid & dcid,const sockaddr * sa,socklen_t salen,const uint8_t * secret,size_t secretlen)314 int verify_retry_token(ngtcp2_cid &odcid, const uint8_t *token, size_t tokenlen,
315 uint32_t version, const ngtcp2_cid &dcid,
316 const sockaddr *sa, socklen_t salen,
317 const uint8_t *secret, size_t secretlen) {
318
319 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
320 std::chrono::system_clock::now().time_since_epoch())
321 .count();
322
323 if (ngtcp2_crypto_verify_retry_token(&odcid, token, tokenlen, secret,
324 secretlen, version, sa, salen, &dcid,
325 10 * NGTCP2_SECONDS, t) != 0) {
326 return -1;
327 }
328
329 return 0;
330 }
331
generate_token(uint8_t * token,size_t & tokenlen,const sockaddr * sa,size_t salen,const uint8_t * secret,size_t secretlen)332 int generate_token(uint8_t *token, size_t &tokenlen, const sockaddr *sa,
333 size_t salen, const uint8_t *secret, size_t secretlen) {
334 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
335 std::chrono::system_clock::now().time_since_epoch())
336 .count();
337
338 auto stokenlen = ngtcp2_crypto_generate_regular_token(
339 token, secret, secretlen, sa, salen, t);
340 if (stokenlen < 0) {
341 return -1;
342 }
343
344 tokenlen = stokenlen;
345
346 return 0;
347 }
348
verify_token(const uint8_t * token,size_t tokenlen,const sockaddr * sa,socklen_t salen,const uint8_t * secret,size_t secretlen)349 int verify_token(const uint8_t *token, size_t tokenlen, const sockaddr *sa,
350 socklen_t salen, const uint8_t *secret, size_t secretlen) {
351 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
352 std::chrono::system_clock::now().time_since_epoch())
353 .count();
354
355 if (ngtcp2_crypto_verify_regular_token(token, tokenlen, secret, secretlen, sa,
356 salen, 3600 * NGTCP2_SECONDS,
357 t) != 0) {
358 return -1;
359 }
360
361 return 0;
362 }
363
generate_quic_connection_id_encryption_key(uint8_t * key,size_t keylen,const uint8_t * secret,size_t secretlen,const uint8_t * salt,size_t saltlen)364 int generate_quic_connection_id_encryption_key(uint8_t *key, size_t keylen,
365 const uint8_t *secret,
366 size_t secretlen,
367 const uint8_t *salt,
368 size_t saltlen) {
369 constexpr uint8_t info[] = "connection id encryption key";
370 ngtcp2_crypto_md sha256;
371 ngtcp2_crypto_md_init(
372 &sha256, reinterpret_cast<void *>(const_cast<EVP_MD *>(EVP_sha256())));
373
374 if (ngtcp2_crypto_hkdf(key, keylen, &sha256, secret, secretlen, salt, saltlen,
375 info, str_size(info)) != 0) {
376 return -1;
377 }
378
379 return 0;
380 }
381
382 const QUICKeyingMaterial *
select_quic_keying_material(const QUICKeyingMaterials & qkms,uint8_t km_id)383 select_quic_keying_material(const QUICKeyingMaterials &qkms, uint8_t km_id) {
384 for (auto &qkm : qkms.keying_materials) {
385 if (km_id == qkm.id) {
386 return &qkm;
387 }
388 }
389
390 return &qkms.keying_materials.front();
391 }
392
393 } // namespace shrpx
394