aboutsummaryrefslogtreecommitdiff
path: root/crypto/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/packet.c')
-rw-r--r--crypto/packet.c100
1 files changed, 89 insertions, 11 deletions
diff --git a/crypto/packet.c b/crypto/packet.c
index 927bb3f80f6c..6a43b35655fb 100644
--- a/crypto/packet.c
+++ b/crypto/packet.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -9,6 +9,9 @@
#include "internal/cryptlib.h"
#include "internal/packet.h"
+#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
+# include "internal/packet_quic.h"
+#endif
#include <openssl/err.h>
#define DEFAULT_BUF_SIZE 256
@@ -104,10 +107,8 @@ static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
pkt->curr = 0;
pkt->written = 0;
- if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) {
- ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL)
return 0;
- }
if (lenbytes == 0)
return 1;
@@ -225,6 +226,20 @@ static int put_value(unsigned char *data, uint64_t value, size_t len)
return 1;
}
+#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
+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;
+}
+#endif
/*
* Internal helper function used by WPACKET_close(), WPACKET_finish() and
@@ -261,10 +276,20 @@ 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 !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
+ 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 (!put_value(&buf[sub->packet_len], packlen, sub->lenbytes))
+ return 0;
+#endif
+ }
} else if (pkt->endfirst && sub->parent != NULL
&& (packlen != 0
|| (sub->flags
@@ -351,10 +376,8 @@ int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
if (lenbytes > 0 && pkt->endfirst)
return 0;
- if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) {
- ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL)
return 0;
- }
sub->parent = pkt->subs;
pkt->subs = sub;
@@ -510,3 +533,58 @@ void WPACKET_cleanup(WPACKET *pkt)
}
pkt->subs = NULL;
}
+
+#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
+
+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;
+}
+
+#endif