Skip to content

Commit

Permalink
QUIC Frame Encoding and Decoding Functions
Browse files Browse the repository at this point in the history
This adds functions for encoding and decoding QUIC frames.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from #18795)
  • Loading branch information
hlandau authored and paulidale committed Jul 29, 2022
1 parent 2059574 commit dffafaf
Show file tree
Hide file tree
Showing 10 changed files with 3,067 additions and 7 deletions.
6 changes: 3 additions & 3 deletions crypto/packet.c
Expand Up @@ -207,7 +207,7 @@ int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
}

/* Store the |value| of length |len| at location |data| */
static int put_value(unsigned char *data, size_t value, size_t len)
static int put_value(unsigned char *data, uint64_t value, size_t len)
{
if (data == NULL)
return 1;
Expand Down Expand Up @@ -396,12 +396,12 @@ int WPACKET_start_sub_packet(WPACKET *pkt)
return WPACKET_start_sub_packet_len__(pkt, 0);
}

int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size)
int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size)
{
unsigned char *data;

/* Internal API, so should not fail */
if (!ossl_assert(size <= sizeof(unsigned int))
if (!ossl_assert(size <= sizeof(uint64_t))
|| !WPACKET_allocate_bytes(pkt, size, &data)
|| !put_value(data, val, size))
return 0;
Expand Down
78 changes: 77 additions & 1 deletion include/internal/packet.h
Expand Up @@ -229,6 +229,28 @@ __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt,
return 1;
}

/*
* Peek ahead at 8 bytes in network order from |pkt| and store the value in
* |*data|
*/
__owur static ossl_inline int PACKET_peek_net_8(const PACKET *pkt,
uint64_t *data)
{
if (PACKET_remaining(pkt) < 8)
return 0;

*data = ((uint64_t)(*pkt->curr)) << 56;
*data |= ((uint64_t)(*(pkt->curr + 1))) << 48;
*data |= ((uint64_t)(*(pkt->curr + 2))) << 40;
*data |= ((uint64_t)(*(pkt->curr + 3))) << 32;
*data |= ((uint64_t)(*(pkt->curr + 4))) << 24;
*data |= ((uint64_t)(*(pkt->curr + 5))) << 16;
*data |= ((uint64_t)(*(pkt->curr + 6))) << 8;
*data |= *(pkt->curr + 7);

return 1;
}

/*
* Decodes a QUIC variable-length integer in |pkt| and stores the result in
* |data|.
Expand All @@ -251,6 +273,47 @@ __owur static ossl_inline int PACKET_get_quic_vlint(PACKET *pkt,
return 1;
}

/*
* Decodes a QUIC variable-length integer in |pkt| and stores the result in
* |data|. Unlike PACKET_get_quic_vlint, this does not advance the current
* position.
*/
__owur static ossl_inline int PACKET_peek_quic_vlint(PACKET *pkt,
uint64_t *data)
{
size_t enclen;

if (PACKET_remaining(pkt) < 1)
return 0;

enclen = ossl_quic_vlint_decode_len(*pkt->curr);

if (PACKET_remaining(pkt) < enclen)
return 0;

*data = ossl_quic_vlint_decode_unchecked(pkt->curr);
return 1;
}

/*
* Skips over a QUIC variable-length integer in |pkt| without decoding it.
*/
__owur static ossl_inline int PACKET_skip_quic_vlint(PACKET *pkt)
{
size_t enclen;

if (PACKET_remaining(pkt) < 1)
return 0;

enclen = ossl_quic_vlint_decode_len(*pkt->curr);

if (PACKET_remaining(pkt) < enclen)
return 0;

packet_forward(pkt, enclen);
return 1;
}

/* Equivalent of n2l */
/* Get 4 bytes in network order from |pkt| and store the value in |*data| */
__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
Expand All @@ -275,6 +338,17 @@ __owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data)
return ret;
}

/* Get 8 bytes in network order from |pkt| and store the value in |*data| */
__owur static ossl_inline int PACKET_get_net_8(PACKET *pkt, uint64_t *data)
{
if (!PACKET_peek_net_8(pkt, data))
return 0;

packet_forward(pkt, 8);

return 1;
}

/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt,
unsigned int *data)
Expand Down Expand Up @@ -885,7 +959,7 @@ int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
* 1 byte will fail. Don't call this directly. Use the convenience macros below
* instead.
*/
int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes);
int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t bytes);

/*
* Convenience macros for calling WPACKET_put_bytes with different
Expand All @@ -899,6 +973,8 @@ int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes);
WPACKET_put_bytes__((pkt), (val), 3)
#define WPACKET_put_bytes_u32(pkt, val) \
WPACKET_put_bytes__((pkt), (val), 4)
#define WPACKET_put_bytes_u64(pkt, val) \
WPACKET_put_bytes__((pkt), (val), 8)

/* Set a maximum size that we will not allow the WPACKET to grow beyond */
int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize);
Expand Down
29 changes: 29 additions & 0 deletions include/internal/quic_types.h
@@ -0,0 +1,29 @@
/*
* Copyright 2022 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/

#ifndef OSSL_QUIC_TYPES_H
# define OSSL_QUIC_TYPES_H

# include <openssl/ssl.h>

/* QUIC packet number representation. */
typedef uint64_t QUIC_PN;
# define QUIC_PN_INVALID UINT64_MAX

static ossl_unused ossl_inline QUIC_PN ossl_quic_pn_max(QUIC_PN a, QUIC_PN b)
{
return a > b ? a : b;
}

static ossl_unused ossl_inline QUIC_PN ossl_quic_pn_min(QUIC_PN a, QUIC_PN b)
{
return a < b ? a : b;
}

#endif

0 comments on commit dffafaf

Please sign in to comment.