From 17e81f2cd1843f01838245eae7b5ed5edf83d6be Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 09:30:55 +0200 Subject: Adding upstream version 0.12.1+dfsg. Signed-off-by: Daniel Baumann --- tests/ngtcp2_test_helper.c | 404 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 tests/ngtcp2_test_helper.c (limited to 'tests/ngtcp2_test_helper.c') diff --git a/tests/ngtcp2_test_helper.c b/tests/ngtcp2_test_helper.c new file mode 100644 index 0000000..a29a943 --- /dev/null +++ b/tests/ngtcp2_test_helper.c @@ -0,0 +1,404 @@ +/* + * ngtcp2 + * + * Copyright (c) 2017 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_test_helper.h" + +#include +#include + +#include "ngtcp2_conv.h" +#include "ngtcp2_pkt.h" +#include "ngtcp2_ppe.h" +#include "ngtcp2_vec.h" +#include "ngtcp2_net.h" + +size_t ngtcp2_t_encode_stream_frame(uint8_t *out, uint8_t flags, + uint64_t stream_id, uint64_t offset, + uint16_t datalen) { + uint8_t *p = out; + + if (offset) { + flags |= NGTCP2_STREAM_OFF_BIT; + } + *p++ = NGTCP2_FRAME_STREAM | flags; + + p = ngtcp2_put_uvarint(p, stream_id); + + if (offset) { + p = ngtcp2_put_uvarint(p, offset); + } + + if (flags & NGTCP2_STREAM_LEN_BIT) { + p = ngtcp2_put_uvarint(p, datalen); + } + + memset(p, 0, datalen); + p += datalen; + + return (size_t)(p - out); +} + +size_t ngtcp2_t_encode_ack_frame(uint8_t *out, uint64_t largest_ack, + uint64_t first_ack_blklen, uint64_t gap, + uint64_t ack_blklen) { + uint8_t *p = out; + + p = out; + + *p++ = NGTCP2_FRAME_ACK; + /* Largest Acknowledged */ + p = ngtcp2_put_uvarint(p, largest_ack); + /* ACK Delay */ + p = ngtcp2_put_uvarint(p, 0); + /* ACK Block Count */ + p = ngtcp2_put_uvarint(p, 1); + /* First ACK Block */ + p = ngtcp2_put_uvarint(p, first_ack_blklen); + /* Gap (1) */ + p = ngtcp2_put_uvarint(p, gap); + /* Additional ACK Block (1) */ + p = ngtcp2_put_uvarint(p, ack_blklen); + + return (size_t)(p - out); +} + +static int null_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, + const uint8_t *plaintext, size_t plaintextlen, + const uint8_t *nonce, size_t noncelen, + const uint8_t *aad, size_t aadlen) { + (void)dest; + (void)aead; + (void)aead_ctx; + (void)plaintext; + (void)plaintextlen; + (void)nonce; + (void)noncelen; + (void)aad; + (void)aadlen; + memset(dest + plaintextlen, 0, NGTCP2_FAKE_AEAD_OVERHEAD); + return 0; +} + +static int null_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, + const ngtcp2_crypto_cipher_ctx *hp_ctx, + const uint8_t *sample) { + (void)hp; + (void)hp_ctx; + (void)sample; + memcpy(dest, NGTCP2_FAKE_HP_MASK, sizeof(NGTCP2_FAKE_HP_MASK) - 1); + return 0; +} + +size_t write_pkt(uint8_t *out, size_t outlen, const ngtcp2_cid *dcid, + int64_t pkt_num, ngtcp2_frame *fr, size_t frlen, + ngtcp2_crypto_km *ckm) { + return write_pkt_flags(out, outlen, NGTCP2_PKT_FLAG_NONE, dcid, pkt_num, fr, + frlen, ckm); +} + +size_t write_pkt_flags(uint8_t *out, size_t outlen, uint8_t flags, + const ngtcp2_cid *dcid, int64_t pkt_num, + ngtcp2_frame *fr, size_t frlen, ngtcp2_crypto_km *ckm) { + ngtcp2_crypto_cc cc; + ngtcp2_ppe ppe; + ngtcp2_pkt_hd hd; + int rv; + ngtcp2_ssize n; + size_t i; + + memset(&cc, 0, sizeof(cc)); + cc.encrypt = null_encrypt; + cc.hp_mask = null_hp_mask; + cc.ckm = ckm; + cc.aead.max_overhead = NGTCP2_FAKE_AEAD_OVERHEAD; + + ngtcp2_pkt_hd_init(&hd, flags, NGTCP2_PKT_1RTT, dcid, NULL, pkt_num, 4, + NGTCP2_PROTO_VER_V1, 0); + + ngtcp2_ppe_init(&ppe, out, outlen, &cc); + rv = ngtcp2_ppe_encode_hd(&ppe, &hd); + assert(0 == rv); + + for (i = 0; i < frlen; ++i, ++fr) { + rv = ngtcp2_ppe_encode_frame(&ppe, fr); + assert(0 == rv); + } + + n = ngtcp2_ppe_final(&ppe, NULL); + assert(n > 0); + + return (size_t)n; +} + +static size_t write_long_header_pkt_generic( + uint8_t *out, size_t outlen, uint8_t pkt_type, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, int64_t pkt_num, uint32_t version, + const uint8_t *token, size_t tokenlen, ngtcp2_frame *fr, size_t frlen, + ngtcp2_crypto_km *ckm) { + ngtcp2_crypto_cc cc; + ngtcp2_ppe ppe; + ngtcp2_pkt_hd hd; + int rv; + ngtcp2_ssize n; + size_t i; + + memset(&cc, 0, sizeof(cc)); + cc.encrypt = null_encrypt; + cc.hp_mask = null_hp_mask; + cc.ckm = ckm; + switch (pkt_type) { + case NGTCP2_PKT_INITIAL: + cc.aead.max_overhead = NGTCP2_INITIAL_AEAD_OVERHEAD; + break; + case NGTCP2_PKT_HANDSHAKE: + case NGTCP2_PKT_0RTT: + cc.aead.max_overhead = NGTCP2_FAKE_AEAD_OVERHEAD; + break; + default: + assert(0); + } + + /* ngtcp2_pkt_encode_hd_long requires known QUIC version. If we + need to write unsupported version for testing purpose, just + pretend that it is QUIC v1 here and rewrite the version field + later. */ + ngtcp2_pkt_hd_init( + &hd, NGTCP2_PKT_FLAG_LONG_FORM, pkt_type, dcid, scid, pkt_num, 4, + version != NGTCP2_PROTO_VER_V1 && version != NGTCP2_PROTO_VER_V2_DRAFT + ? NGTCP2_PROTO_VER_V1 + : version, + 0); + + hd.token.base = (uint8_t *)token; + hd.token.len = tokenlen; + + ngtcp2_ppe_init(&ppe, out, outlen, &cc); + rv = ngtcp2_ppe_encode_hd(&ppe, &hd); + assert(0 == rv); + ngtcp2_put_uint32be(&out[1], version); + + for (i = 0; i < frlen; ++i, ++fr) { + rv = ngtcp2_ppe_encode_frame(&ppe, fr); + assert(0 == rv); + } + + n = ngtcp2_ppe_final(&ppe, NULL); + assert(n > 0); + return (size_t)n; +} + +size_t write_initial_pkt(uint8_t *out, size_t outlen, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, int64_t pkt_num, + uint32_t version, const uint8_t *token, + size_t tokenlen, ngtcp2_frame *fr, size_t frlen, + ngtcp2_crypto_km *ckm) { + return write_long_header_pkt_generic(out, outlen, NGTCP2_PKT_INITIAL, dcid, + scid, pkt_num, version, token, tokenlen, + fr, frlen, ckm); +} + +size_t write_handshake_pkt(uint8_t *out, size_t outlen, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, int64_t pkt_num, + uint32_t version, ngtcp2_frame *fr, size_t frlen, + ngtcp2_crypto_km *ckm) { + return write_long_header_pkt_generic(out, outlen, NGTCP2_PKT_HANDSHAKE, dcid, + scid, pkt_num, version, NULL, 0, fr, + frlen, ckm); +} + +size_t write_0rtt_pkt(uint8_t *out, size_t outlen, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, int64_t pkt_num, uint32_t version, + ngtcp2_frame *fr, size_t frlen, ngtcp2_crypto_km *ckm) { + return write_long_header_pkt_generic(out, outlen, NGTCP2_PKT_0RTT, dcid, scid, + pkt_num, version, NULL, 0, fr, frlen, + ckm); +} + +ngtcp2_strm *open_stream(ngtcp2_conn *conn, int64_t stream_id) { + ngtcp2_strm *strm; + int rv; + (void)rv; + + strm = ngtcp2_objalloc_strm_get(&conn->strm_objalloc); + assert(strm); + + rv = ngtcp2_conn_init_stream(conn, strm, stream_id, NULL); + assert(0 == rv); + + return strm; +} + +size_t rtb_entry_length(const ngtcp2_rtb_entry *ent) { + size_t len = 0; + + for (; ent; ent = ent->next) { + ++len; + } + + return len; +} + +void dcid_init(ngtcp2_cid *cid) { + static const uint8_t id[] = "\xff\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xff"; + ngtcp2_cid_init(cid, id, sizeof(id) - 1); +} + +void scid_init(ngtcp2_cid *cid) { + static const uint8_t id[] = "\xee\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xee"; + ngtcp2_cid_init(cid, id, sizeof(id) - 1); +} + +void rcid_init(ngtcp2_cid *cid) { + static const uint8_t id[] = "\xdd\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xdd"; + ngtcp2_cid_init(cid, id, sizeof(id) - 1); +} + +uint64_t read_pkt_payloadlen(const uint8_t *pkt, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid) { + uint64_t len; + + ngtcp2_get_uvarint(&len, &pkt[1 + 4 + 1 + dcid->datalen + 1 + scid->datalen]); + + return len; +} + +void write_pkt_payloadlen(uint8_t *pkt, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, uint64_t payloadlen) { + assert(payloadlen < 1073741824); + ngtcp2_put_uvarint30(&pkt[1 + 4 + 1 + dcid->datalen + 1 + scid->datalen], + (uint32_t)payloadlen); +} + +ngtcp2_ssize pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, + size_t pktlen) { + const uint8_t *p; + ngtcp2_ssize nread; + + nread = ngtcp2_pkt_decode_hd_long(dest, pkt, pktlen); + if (nread < 0 || (!(dest->flags & NGTCP2_PKT_FLAG_LONG_FORM) && + dest->type == NGTCP2_PKT_VERSION_NEGOTIATION)) { + return nread; + } + + if ((size_t)nread == pktlen) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + p = pkt + nread; + + dest->pkt_numlen = (size_t)(pkt[0] & NGTCP2_PKT_NUMLEN_MASK) + 1; + if (pktlen < (size_t)nread + dest->pkt_numlen) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + dest->pkt_num = ngtcp2_get_pkt_num(p, dest->pkt_numlen); + + return nread + (ngtcp2_ssize)dest->pkt_numlen; +} + +ngtcp2_ssize pkt_decode_hd_short(ngtcp2_pkt_hd *dest, const uint8_t *pkt, + size_t pktlen, size_t dcidlen) { + const uint8_t *p; + ngtcp2_ssize nread; + + nread = ngtcp2_pkt_decode_hd_short(dest, pkt, pktlen, dcidlen); + if (nread < 0) { + return nread; + } + + if ((size_t)nread == pktlen) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + p = pkt + nread; + + dest->pkt_numlen = (size_t)(pkt[0] & NGTCP2_PKT_NUMLEN_MASK) + 1; + if (pktlen < (size_t)nread + dest->pkt_numlen) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + dest->pkt_num = ngtcp2_get_pkt_num(p, dest->pkt_numlen); + + return nread + (ngtcp2_ssize)dest->pkt_numlen; +} + +ngtcp2_ssize pkt_decode_hd_short_mask(ngtcp2_pkt_hd *dest, const uint8_t *pkt, + size_t pktlen, size_t dcidlen) { + static const uint8_t mask[] = NGTCP2_FAKE_HP_MASK; + const uint8_t *p; + ngtcp2_ssize nread; + uint8_t hb; + uint8_t pkt_numbuf[4]; + size_t i; + + nread = ngtcp2_pkt_decode_hd_short(dest, pkt, pktlen, dcidlen); + if (nread < 0) { + return nread; + } + + if ((size_t)nread == pktlen) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + p = pkt + nread; + + hb = (uint8_t)(pkt[0] ^ (mask[0] & 0x1f)); + + dest->pkt_numlen = (size_t)(hb & NGTCP2_PKT_NUMLEN_MASK) + 1; + if (pktlen < (size_t)nread + dest->pkt_numlen) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + for (i = 0; i < dest->pkt_numlen; ++i) { + pkt_numbuf[i] = *(p + i) ^ mask[i + 1]; + } + + dest->pkt_num = ngtcp2_get_pkt_num(pkt_numbuf, dest->pkt_numlen); + + return nread + (ngtcp2_ssize)dest->pkt_numlen; +} + +static void addr_init(ngtcp2_sockaddr_in *dest, uint32_t addr, uint16_t port) { + memset(dest, 0, sizeof(*dest)); + + dest->sin_family = AF_INET; + dest->sin_port = ngtcp2_htons(port); + dest->sin_addr.s_addr = ngtcp2_htonl(addr); +} + +void path_init(ngtcp2_path_storage *path, uint32_t local_addr, + uint16_t local_port, uint32_t remote_addr, + uint16_t remote_port) { + ngtcp2_sockaddr_in la, ra; + + addr_init(&la, local_addr, local_port); + addr_init(&ra, remote_addr, remote_port); + + ngtcp2_path_storage_init(path, (ngtcp2_sockaddr *)&la, sizeof(la), + (ngtcp2_sockaddr *)&ra, sizeof(ra), NULL); +} -- cgit v1.2.3