diff options
author | Hugo Landau <hlandau@openssl.org> | 2022-05-23 10:42:03 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2022-05-27 08:00:52 +0200 |
commit | 416d0a638c1635a182e57fe80c7c065dd76818c0 (patch) | |
tree | aa70e7e9b9161ae2c30f7b6ed9bce6af66cace59 /crypto/packet.c | |
parent | 1aef2c10f10e0685298008be596c80e148c71a51 (diff) |
QUIC wire format support
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18382)
Diffstat (limited to 'crypto/packet.c')
-rw-r--r-- | crypto/packet.c | 76 |
1 files changed, 72 insertions, 4 deletions
diff --git a/crypto/packet.c b/crypto/packet.c index 09f6a9cea9..5123426d75 100644 --- a/crypto/packet.c +++ b/crypto/packet.c @@ -225,6 +225,18 @@ static int put_value(unsigned char *data, size_t value, size_t len) return 1; } +static int put_quic_value(unsigned char *data, size_t value, size_t len) +{ + if (data == NULL) + return 1; + + /* Value too large for field. */ + if (ossl_quic_vlint_encode_len(value) > len) + return 0; + + ossl_quic_vlint_encode_n(data, value, len); + return 1; +} /* * Internal helper function used by WPACKET_close(), WPACKET_finish() and @@ -261,10 +273,15 @@ static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose) if (sub->lenbytes > 0) { unsigned char *buf = GETBUF(pkt); - if (buf != NULL - && !put_value(&buf[sub->packet_len], packlen, - sub->lenbytes)) - return 0; + if (buf != NULL) { + if ((sub->flags & WPACKET_FLAGS_QUIC_VLINT) == 0) { + if (!put_value(&buf[sub->packet_len], packlen, sub->lenbytes)) + return 0; + } else { + if (!put_quic_value(&buf[sub->packet_len], packlen, sub->lenbytes)) + return 0; + } + } } else if (pkt->endfirst && sub->parent != NULL && (packlen != 0 || (sub->flags @@ -510,3 +527,54 @@ void WPACKET_cleanup(WPACKET *pkt) } pkt->subs = NULL; } + +int WPACKET_start_quic_sub_packet_bound(WPACKET *pkt, size_t max_len) +{ + size_t enclen = ossl_quic_vlint_encode_len(max_len); + + if (enclen == 0) + return 0; + + if (WPACKET_start_sub_packet_len__(pkt, enclen) == 0) + return 0; + + pkt->subs->flags |= WPACKET_FLAGS_QUIC_VLINT; + return 1; +} + +int WPACKET_start_quic_sub_packet(WPACKET *pkt) +{ + /* + * Assume no (sub)packet will exceed 4GiB, thus the 8-byte encoding need not + * be used. + */ + return WPACKET_start_quic_sub_packet_bound(pkt, OSSL_QUIC_VLINT_4B_MIN); +} + +int WPACKET_quic_sub_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) +{ + if (!WPACKET_start_quic_sub_packet_bound(pkt, len) + || !WPACKET_allocate_bytes(pkt, len, allocbytes) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +/* + * Write a QUIC variable-length integer to the packet. + */ +int WPACKET_quic_write_vlint(WPACKET *pkt, uint64_t v) +{ + unsigned char *b = NULL; + size_t enclen = ossl_quic_vlint_encode_len(v); + + if (enclen == 0) + return 0; + + if (WPACKET_allocate_bytes(pkt, enclen, &b) == 0) + return 0; + + ossl_quic_vlint_encode(b, v); + return 1; +} |