|
1 | 1 | /* Copyright (C) CZ.NIC, z.s.p.o. <[email protected]> |
2 | 2 | * SPDX-License-Identifier: GPL-3.0-or-later |
3 | 3 | */ |
| 4 | +#include <ngtcp2/ngtcp2.h> |
| 5 | +#include "contrib/openbsd/siphash.h" |
4 | 6 | #include "quic_common.h" |
5 | 7 | #include "libdnssec/random.h" |
6 | 8 | #include "session2.h" |
7 | | -#include <ngtcp2/ngtcp2.h> |
| 9 | +#include "quic_conn.h" |
8 | 10 |
|
9 | 11 | uint64_t quic_timestamp(void) |
10 | 12 | { |
@@ -35,18 +37,83 @@ void init_random_cid(ngtcp2_cid *cid, size_t len) |
35 | 37 | /* DNSSEC_EOK */0 ? len : 0; |
36 | 38 | } |
37 | 39 |
|
38 | | -ssize_t send_version_negotiation(struct wire_buf *dest, ngtcp2_version_cid dec_cids, |
39 | | - ngtcp2_cid dcid, ngtcp2_cid scid) |
| 40 | +uint64_t cid2hash(const ngtcp2_cid *cid, kr_quic_table_t *table) |
| 41 | +{ |
| 42 | + SIPHASH_CTX ctx; |
| 43 | + SipHash24_Init(&ctx, (const SIPHASH_KEY *)(table->hash_secret)); |
| 44 | + SipHash24_Update(&ctx, cid->data, MIN(cid->datalen, 8)); |
| 45 | + uint64_t ret = SipHash24_End(&ctx); |
| 46 | + |
| 47 | + return ret; |
| 48 | +} |
| 49 | + |
| 50 | +kr_quic_cid_t **kr_quic_table_lookup2(const ngtcp2_cid *cid, kr_quic_table_t *table) |
40 | 51 | { |
41 | | - uint8_t rnd = 0; |
42 | | - dnssec_random_buffer(&rnd, sizeof(rnd)); |
43 | | - uint32_t supported_quic[1] = { NGTCP2_PROTO_VER_V1 }; |
44 | | - int ret = ngtcp2_pkt_write_version_negotiation( |
| 52 | + uint64_t hash = cid2hash(cid, table); |
| 53 | + |
| 54 | + kr_quic_cid_t **res = table->conns + (hash % table->size); |
| 55 | + while (*res != NULL && !ngtcp2_cid_eq(cid, (const ngtcp2_cid *)(*res)->cid_placeholder)) { |
| 56 | + res = &(*res)->next; |
| 57 | + } |
| 58 | + |
| 59 | + return res; |
| 60 | +} |
| 61 | + |
| 62 | +struct pl_quic_conn_sess_data *kr_quic_table_lookup(const ngtcp2_cid *cid, kr_quic_table_t *table) |
| 63 | +{ |
| 64 | + kr_quic_cid_t **pcid = kr_quic_table_lookup2(cid, table); |
| 65 | + return *pcid == NULL ? NULL : (*pcid)->conn_sess; |
| 66 | +} |
| 67 | + |
| 68 | +bool init_unique_cid(ngtcp2_cid *cid, size_t len, kr_quic_table_t *table) |
| 69 | +{ |
| 70 | + do { |
| 71 | + if (init_random_cid(cid, len), cid->datalen == 0) |
| 72 | + return false; |
| 73 | + |
| 74 | + } while (kr_quic_table_lookup(cid, table) != NULL); |
| 75 | + |
| 76 | + return true; |
| 77 | +} |
| 78 | + |
| 79 | +int write_retry_packet(struct wire_buf *dest, kr_quic_table_t *table, |
| 80 | + ngtcp2_version_cid *dec_cids, |
| 81 | + const struct sockaddr *src_addr, |
| 82 | + uint8_t *secret, size_t secret_len) |
| 83 | +{ |
| 84 | + ngtcp2_cid dcid; |
| 85 | + ngtcp2_cid scid; |
| 86 | + ngtcp2_cid new_dcid; |
| 87 | + |
| 88 | + ngtcp2_cid_init(&dcid, dec_cids->dcid, dec_cids->dcidlen); |
| 89 | + ngtcp2_cid_init(&scid, dec_cids->scid, dec_cids->scidlen); |
| 90 | + |
| 91 | + init_random_cid(&new_dcid, 0); |
| 92 | + if (!init_unique_cid(&new_dcid, 0, table)) { |
| 93 | + kr_log_debug(DOQ, "Failed to initialize unique cid for Retry packet\n"); |
| 94 | + return -1; |
| 95 | + } |
| 96 | + |
| 97 | + uint8_t retry_token[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN2]; |
| 98 | + uint64_t now = quic_timestamp(); |
| 99 | + |
| 100 | + int ret = ngtcp2_crypto_generate_retry_token2( |
| 101 | + retry_token, (const uint8_t *)secret, |
| 102 | + secret_len, dec_cids->version, |
| 103 | + src_addr, kr_sockaddr_len(src_addr), |
| 104 | + &new_dcid, &dcid, now); |
| 105 | + |
| 106 | + if (ret < 0) { |
| 107 | + kr_log_debug(DOQ, "Failed to generate retry token\n"); |
| 108 | + return ret; |
| 109 | + } |
| 110 | + |
| 111 | + ret = ngtcp2_crypto_write_retry( |
45 | 112 | wire_buf_free_space(dest), |
46 | 113 | wire_buf_free_space_length(dest), |
47 | | - rnd, dec_cids.scid, dec_cids.scidlen, |
48 | | - dec_cids.dcid, dec_cids.dcidlen, supported_quic, |
49 | | - sizeof(supported_quic) / sizeof(*supported_quic) |
| 114 | + dec_cids->version, &scid, |
| 115 | + &new_dcid, &dcid, |
| 116 | + retry_token, ret |
50 | 117 | ); |
51 | 118 |
|
52 | 119 | return ret; |
|
0 commit comments