summaryrefslogtreecommitdiffstats
path: root/crypto/packet.c
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2022-05-23 10:42:03 +0100
committerTomas Mraz <tomas@openssl.org>2022-05-27 08:00:52 +0200
commit416d0a638c1635a182e57fe80c7c065dd76818c0 (patch)
treeaa70e7e9b9161ae2c30f7b6ed9bce6af66cace59 /crypto/packet.c
parent1aef2c10f10e0685298008be596c80e148c71a51 (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.c76
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;
+}