Coverage Report

Created: 2025-06-13 06:56

/src/openssl/include/internal/quic_wire_pkt.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#ifndef OSSL_QUIC_WIRE_PKT_H
11
# define OSSL_QUIC_WIRE_PKT_H
12
13
# include <openssl/ssl.h>
14
# include "internal/packet_quic.h"
15
# include "internal/quic_types.h"
16
17
# ifndef OPENSSL_NO_QUIC
18
19
0
#  define QUIC_VERSION_NONE   ((uint32_t)0)   /* Used for version negotiation */
20
0
#  define QUIC_VERSION_1      ((uint32_t)1)   /* QUIC v1 */
21
22
/* QUIC logical packet type. These do not match wire values. */
23
0
#  define QUIC_PKT_TYPE_INITIAL        1
24
0
#  define QUIC_PKT_TYPE_0RTT           2
25
0
#  define QUIC_PKT_TYPE_HANDSHAKE      3
26
0
#  define QUIC_PKT_TYPE_RETRY          4
27
0
#  define QUIC_PKT_TYPE_1RTT           5
28
0
#  define QUIC_PKT_TYPE_VERSION_NEG    6
29
30
/*
31
 * Determine encryption level from packet type. Returns QUIC_ENC_LEVEL_NUM if
32
 * the packet is not of a type which is encrypted.
33
 */
34
static ossl_inline ossl_unused uint32_t
35
ossl_quic_pkt_type_to_enc_level(uint32_t pkt_type)
36
0
{
37
0
    switch (pkt_type) {
38
0
        case QUIC_PKT_TYPE_INITIAL:
39
0
            return QUIC_ENC_LEVEL_INITIAL;
40
0
        case QUIC_PKT_TYPE_HANDSHAKE:
41
0
            return QUIC_ENC_LEVEL_HANDSHAKE;
42
0
        case QUIC_PKT_TYPE_0RTT:
43
0
            return QUIC_ENC_LEVEL_0RTT;
44
0
        case QUIC_PKT_TYPE_1RTT:
45
0
            return QUIC_ENC_LEVEL_1RTT;
46
0
        default:
47
0
            return QUIC_ENC_LEVEL_NUM;
48
0
    }
49
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_to_enc_level
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_to_enc_level
50
51
static ossl_inline ossl_unused uint32_t
52
ossl_quic_enc_level_to_pkt_type(uint32_t enc_level)
53
0
{
54
0
    switch (enc_level) {
55
0
        case QUIC_ENC_LEVEL_INITIAL:
56
0
            return QUIC_PKT_TYPE_INITIAL;
57
0
        case QUIC_ENC_LEVEL_HANDSHAKE:
58
0
            return QUIC_PKT_TYPE_HANDSHAKE;
59
0
        case QUIC_ENC_LEVEL_0RTT:
60
0
            return QUIC_PKT_TYPE_0RTT;
61
0
        case QUIC_ENC_LEVEL_1RTT:
62
0
            return QUIC_PKT_TYPE_1RTT;
63
0
        default:
64
0
            return UINT32_MAX;
65
0
    }
66
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: t1_lib.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_impl.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_method.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_obj.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_port.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_record_rx.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_record_shared.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_record_tx.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_record_util.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_rstream.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_sf_list.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_sstream.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_stream_map.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_txp.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_wire.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_channel.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_demux.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_fifd.c:ossl_quic_enc_level_to_pkt_type
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_enc_level_to_pkt_type
67
68
/* Determine if a packet type contains an encrypted payload. */
69
static ossl_inline ossl_unused int
70
ossl_quic_pkt_type_is_encrypted(uint32_t pkt_type)
71
0
{
72
0
    switch (pkt_type) {
73
0
        case QUIC_PKT_TYPE_RETRY:
74
0
        case QUIC_PKT_TYPE_VERSION_NEG:
75
0
            return 0;
76
0
        default:
77
0
            return 1;
78
0
    }
79
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_is_encrypted
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_is_encrypted
80
81
/* Determine if a packet type contains a PN field. */
82
static ossl_inline ossl_unused int
83
ossl_quic_pkt_type_has_pn(uint32_t pkt_type)
84
0
{
85
    /*
86
     * Currently a packet has a PN iff it is encrypted. This could change
87
     * someday.
88
     */
89
0
    return ossl_quic_pkt_type_is_encrypted(pkt_type);
90
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_has_pn
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_has_pn
91
92
/*
93
 * Determine if a packet type can appear with other packets in a datagram. Some
94
 * packet types must be the sole packet in a datagram.
95
 */
96
static ossl_inline ossl_unused int
97
ossl_quic_pkt_type_can_share_dgram(uint32_t pkt_type)
98
0
{
99
    /*
100
     * Currently only the encrypted packet types can share a datagram. This
101
     * could change someday.
102
     */
103
0
    return ossl_quic_pkt_type_is_encrypted(pkt_type);
104
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_can_share_dgram
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_can_share_dgram
105
106
/*
107
 * Determine if the packet type must come at the end of the datagram (due to the
108
 * lack of a length field).
109
 */
110
static ossl_inline ossl_unused int
111
ossl_quic_pkt_type_must_be_last(uint32_t pkt_type)
112
0
{
113
    /*
114
     * Any packet type which cannot share a datagram obviously must come last.
115
     * 1-RTT also must come last as it lacks a length field.
116
     */
117
0
    return !ossl_quic_pkt_type_can_share_dgram(pkt_type)
118
0
        || pkt_type == QUIC_PKT_TYPE_1RTT;
119
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_must_be_last
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_must_be_last
120
121
/*
122
 * Determine if the packet type has a version field.
123
 */
124
static ossl_inline ossl_unused int
125
ossl_quic_pkt_type_has_version(uint32_t pkt_type)
126
0
{
127
0
    return pkt_type != QUIC_PKT_TYPE_1RTT && pkt_type != QUIC_PKT_TYPE_VERSION_NEG;
128
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_has_version
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_has_version
129
130
/*
131
 * Determine if the packet type has a SCID field.
132
 */
133
static ossl_inline ossl_unused int
134
ossl_quic_pkt_type_has_scid(uint32_t pkt_type)
135
0
{
136
0
    return pkt_type != QUIC_PKT_TYPE_1RTT;
137
0
}
Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_has_scid
Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_has_scid
138
139
/*
140
 * Smallest possible QUIC packet size as per RFC (aside from version negotiation
141
 * packets).
142
 */
143
0
#  define QUIC_MIN_VALID_PKT_LEN_CRYPTO      21
144
0
#  define QUIC_MIN_VALID_PKT_LEN_VERSION_NEG  7
145
0
#  define QUIC_MIN_VALID_PKT_LEN              QUIC_MIN_VALID_PKT_LEN_VERSION_NEG
146
147
typedef struct quic_pkt_hdr_ptrs_st QUIC_PKT_HDR_PTRS;
148
149
/*
150
 * QUIC Packet Header Protection
151
 * =============================
152
 *
153
 * Functions to apply and remove QUIC packet header protection. A header
154
 * protector is initialised using ossl_quic_hdr_protector_init and must be
155
 * destroyed using ossl_quic_hdr_protector_cleanup when no longer needed.
156
 */
157
typedef struct quic_hdr_protector_st {
158
    OSSL_LIB_CTX       *libctx;
159
    const char         *propq;
160
    EVP_CIPHER_CTX     *cipher_ctx;
161
    EVP_CIPHER         *cipher;
162
    uint32_t            cipher_id;
163
} QUIC_HDR_PROTECTOR;
164
165
0
#  define QUIC_HDR_PROT_CIPHER_AES_128    1
166
0
#  define QUIC_HDR_PROT_CIPHER_AES_256    2
167
0
#  define QUIC_HDR_PROT_CIPHER_CHACHA     3
168
169
/*
170
 * Initialises a header protector.
171
 *
172
 *   cipher_id:
173
 *      The header protection cipher method to use. One of
174
 *      QUIC_HDR_PROT_CIPHER_*. Must be chosen based on negotiated TLS cipher
175
 *      suite.
176
 *
177
 *   quic_hp_key:
178
 *      This must be the "quic hp" key derived from a traffic secret.
179
 *
180
 *      The length of the quic_hp_key must correspond to that expected for the
181
 *      given cipher ID.
182
 *
183
 * The header protector performs amortisable initialisation in this function,
184
 * therefore a header protector should be used for as long as possible.
185
 *
186
 * Returns 1 on success and 0 on failure.
187
 */
188
int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
189
                                 OSSL_LIB_CTX *libctx,
190
                                 const char *propq,
191
                                 uint32_t cipher_id,
192
                                 const unsigned char *quic_hp_key,
193
                                 size_t quic_hp_key_len);
194
195
/*
196
 * Destroys a header protector. This is also safe to call on a zero-initialized
197
 * OSSL_QUIC_HDR_PROTECTOR structure which has not been initialized, or which
198
 * has already been destroyed.
199
 */
200
void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr);
201
202
/*
203
 * Removes header protection from a packet. The packet payload must currently be
204
 * encrypted (i.e., you must remove header protection before decrypting packets
205
 * received). The function examines the header buffer to determine which bytes
206
 * of the header need to be decrypted.
207
 *
208
 * If this function fails, no data is modified.
209
 *
210
 * This is implemented as a call to ossl_quic_hdr_protector_decrypt_fields().
211
 *
212
 * Returns 1 on success and 0 on failure.
213
 */
214
int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
215
                                    QUIC_PKT_HDR_PTRS *ptrs);
216
217
/*
218
 * Applies header protection to a packet. The packet payload must already have
219
 * been encrypted (i.e., you must apply header protection after encrypting
220
 * a packet). The function examines the header buffer to determine which bytes
221
 * of the header need to be encrypted.
222
 *
223
 * This is implemented as a call to ossl_quic_hdr_protector_encrypt_fields().
224
 *
225
 * Returns 1 on success and 0 on failure.
226
 */
227
int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
228
                                    QUIC_PKT_HDR_PTRS *ptrs);
229
230
/*
231
 * Removes header protection from a packet. The packet payload must currently
232
 * be encrypted. This is a low-level function which assumes you have already
233
 * determined which parts of the packet header need to be decrypted.
234
 *
235
 * sample:
236
 *   The range of bytes in the packet to be used to generate the header
237
 *   protection mask. It is permissible to set sample_len to the size of the
238
 *   remainder of the packet; this function will only use as many bytes as
239
 *   needed. If not enough sample bytes are provided, this function fails.
240
 *
241
 * first_byte:
242
 *   The first byte of the QUIC packet header to be decrypted.
243
 *
244
 * pn:
245
 *   Pointer to the start of the PN field. The caller is responsible
246
 *   for ensuring at least four bytes follow this pointer.
247
 *
248
 * Returns 1 on success and 0 on failure.
249
 */
250
int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
251
                                           const unsigned char *sample,
252
                                           size_t sample_len,
253
                                           unsigned char *first_byte,
254
                                           unsigned char *pn_bytes);
255
256
/*
257
 * Works analogously to ossl_hdr_protector_decrypt_fields, but applies header
258
 * protection instead of removing it.
259
 */
260
int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
261
                                           const unsigned char *sample,
262
                                           size_t sample_len,
263
                                           unsigned char *first_byte,
264
                                           unsigned char *pn_bytes);
265
266
/*
267
 * QUIC Packet Header
268
 * ==================
269
 *
270
 * This structure provides a logical representation of a QUIC packet header.
271
 *
272
 * QUIC packet formats fall into the following categories:
273
 *
274
 *   Long Packets, which is subdivided into five possible packet types:
275
 *     Version Negotiation (a special case);
276
 *     Initial;
277
 *     0-RTT;
278
 *     Handshake; and
279
 *     Retry
280
 *
281
 *   Short Packets, which comprises only a single packet type (1-RTT).
282
 *
283
 * The packet formats vary and common fields are found in some packets but
284
 * not others. The below table indicates which fields are present in which
285
 * kinds of packet. * indicates header protection is applied.
286
 *
287
 *   SLLLLL         Legend: 1=1-RTT, i=Initial, 0=0-RTT, h=Handshake
288
 *   1i0hrv                 r=Retry, v=Version Negotiation
289
 *   ------
290
 *   1i0hrv         Header Form (0=Short, 1=Long)
291
 *   1i0hr          Fixed Bit (always 1)
292
 *   1              Spin Bit
293
 *   1       *      Reserved Bits
294
 *   1       *      Key Phase
295
 *   1i0h    *      Packet Number Length
296
 *    i0hr?         Long Packet Type
297
 *    i0h           Type-Specific Bits
298
 *    i0hr          Version (note: always 0 for Version Negotiation packets)
299
 *   1i0hrv         Destination Connection ID
300
 *    i0hrv         Source Connection ID
301
 *   1i0h    *      Packet Number
302
 *    i             Token
303
 *    i0h           Length
304
 *       r          Retry Token
305
 *       r          Retry Integrity Tag
306
 *
307
 * For each field below, the conditions under which the field is valid are
308
 * specified. If a field is not currently valid, it is initialized to a zero or
309
 * NULL value.
310
 */
311
typedef struct quic_pkt_hdr_st {
312
    /* [ALL] A QUIC_PKT_TYPE_* value. Always valid. */
313
    unsigned int    type        :8;
314
315
    /* [S] Value of the spin bit. Valid if (type == 1RTT). */
316
    unsigned int    spin_bit    :1;
317
318
    /*
319
     * [S] Value of the Key Phase bit in the short packet.
320
     * Valid if (type == 1RTT && !partial).
321
     */
322
    unsigned int    key_phase   :1;
323
324
    /*
325
     * [1i0h] Length of packet number in bytes. This is the decoded value.
326
     * Valid if ((type == 1RTT || (version && type != RETRY)) && !partial).
327
     */
328
    unsigned int    pn_len      :4;
329
330
    /*
331
     * [ALL] Set to 1 if this is a partial decode because the packet header
332
     * has not yet been deprotected. pn_len, pn and key_phase are not valid if
333
     * this is set.
334
     */
335
    unsigned int    partial     :1;
336
337
    /*
338
     * [ALL] Whether the fixed bit was set. Note that only Version Negotiation
339
     * packets are allowed to have this unset, so this will always be 1 for all
340
     * other packet types (decode will fail if it is not set). Ignored when
341
     * encoding unless encoding a Version Negotiation packet.
342
     */
343
    unsigned int    fixed       :1;
344
345
    /*
346
     * The unused bits in the low 4 bits of a Retry packet header's first byte.
347
     * This is used to ensure that Retry packets have the same bit-for-bit
348
     * representation in their header when decoding and encoding them again.
349
     * This is necessary to validate Retry packet headers.
350
     */
351
    unsigned int    unused      :4;
352
353
    /*
354
     * The 'Reserved' bits in an Initial, Handshake, 0-RTT or 1-RTT packet
355
     * header's first byte. These are provided so that the caller can validate
356
     * that they are zero, as this must be done after packet protection is
357
     * successfully removed to avoid creating a timing channel.
358
     */
359
    unsigned int    reserved    :2;
360
361
    /* [L] Version field. Valid if (type != 1RTT). */
362
    uint32_t        version;
363
364
    /* [ALL] The destination connection ID. Always valid. */
365
    QUIC_CONN_ID    dst_conn_id;
366
367
    /*
368
     * [L] The source connection ID.
369
     * Valid if (type != 1RTT).
370
     */
371
    QUIC_CONN_ID    src_conn_id;
372
373
    /*
374
     * [1i0h] Relatively-encoded packet number in raw, encoded form. The correct
375
     * decoding of this value is context-dependent. The number of bytes valid in
376
     * this buffer is determined by pn_len above. If the decode was partial,
377
     * this field is not valid.
378
     *
379
     * Valid if ((type == 1RTT || (version && type != RETRY)) && !partial).
380
     */
381
    unsigned char           pn[4];
382
383
    /*
384
     * [i] Token field in Initial packet. Points to memory inside the decoded
385
     * PACKET, and therefore is valid for as long as the PACKET's buffer is
386
     * valid. token_len is the length of the token in bytes.
387
     *
388
     * Valid if (type == INITIAL).
389
     */
390
    const unsigned char    *token;
391
    size_t                  token_len;
392
393
    /*
394
     * [ALL] Payload length in bytes.
395
     *
396
     * Though 1-RTT, Retry and Version Negotiation packets do not contain an
397
     * explicit length field, this field is always valid and is used by the
398
     * packet header encoding and decoding routines to describe the payload
399
     * length, regardless of whether the packet type encoded or decoded uses an
400
     * explicit length indication.
401
     */
402
    size_t                  len;
403
404
    /*
405
     * Pointer to start of payload data in the packet. Points to memory inside
406
     * the decoded PACKET, and therefore is valid for as long as the PACKET'S
407
     * buffer is valid. The length of the buffer in bytes is in len above.
408
     *
409
     * For Version Negotiation packets, points to the array of supported
410
     * versions.
411
     *
412
     * For Retry packets, points to the Retry packet payload, which comprises
413
     * the Retry Token followed by a 16-byte Retry Integrity Tag.
414
     *
415
     * Regardless of whether a packet is a Version Negotiation packet (where the
416
     * payload contains a list of supported versions), a Retry packet (where the
417
     * payload contains a Retry Token and Retry Integrity Tag), or any other
418
     * packet type (where the payload contains frames), the payload is not
419
     * validated and the user must parse the payload bearing this in mind.
420
     *
421
     * If the decode was partial (partial is set), this points to the start of
422
     * the packet number field, rather than the protected payload, as the length
423
     * of the packet number field is unknown. The len field reflects this in
424
     * this case (i.e., the len field is the number of payload bytes plus the
425
     * number of bytes comprising the PN).
426
     */
427
    const unsigned char    *data;
428
} QUIC_PKT_HDR;
429
430
/*
431
 * Extra information which can be output by the packet header decode functions
432
 * for the assistance of the header protector. This avoids the header protector
433
 * needing to partially re-decode the packet header.
434
 */
435
struct quic_pkt_hdr_ptrs_st {
436
    unsigned char    *raw_start;        /* start of packet */
437
    unsigned char    *raw_sample;       /* start of sampling range */
438
    size_t            raw_sample_len;   /* maximum length of sampling range */
439
440
    /*
441
     * Start of PN field. Guaranteed to be NULL unless at least four bytes are
442
     * available via this pointer.
443
     */
444
    unsigned char    *raw_pn;
445
};
446
447
/*
448
 * If partial is 1, reads the unprotected parts of a protected packet header
449
 * from a PACKET, performing a partial decode.
450
 *
451
 * If partial is 0, the input is assumed to have already had header protection
452
 * removed, and all header fields are decoded.
453
 *
454
 * If nodata is 1, the input is assumed to have no payload data in it. Otherwise
455
 * payload data must be present.
456
 *
457
 * On success, the logical decode of the packet header is written to *hdr.
458
 * hdr->partial is set or cleared according to whether a partial decode was
459
 * performed. *ptrs is filled with pointers to various parts of the packet
460
 * buffer.
461
 *
462
 * In order to decode short packets, the connection ID length being used must be
463
 * known contextually, and should be passed as short_conn_id_len. If
464
 * short_conn_id_len is set to an invalid value (a value greater than
465
 * QUIC_MAX_CONN_ID_LEN), this function fails when trying to decode a short
466
 * packet, but succeeds for long packets.
467
 *
468
 * fail_cause is a bitmask of the reasons decode might have failed
469
 * as defined below, useful when you need to interrogate parts of
470
 * a header even if its otherwise undecodeable.  May be NULL.
471
 *
472
 * Returns 1 on success and 0 on failure.
473
 */
474
475
0
#  define QUIC_PKT_HDR_DECODE_DECODE_ERR  (1 << 0)
476
0
#  define QUIC_PKT_HDR_DECODE_BAD_VERSION (1 << 1)
477
478
int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
479
                                  size_t short_conn_id_len,
480
                                  int partial,
481
                                  int nodata,
482
                                  QUIC_PKT_HDR *hdr,
483
                                  QUIC_PKT_HDR_PTRS *ptrs,
484
                                  uint64_t *fail_cause);
485
486
/*
487
 * Encodes a packet header. The packet is written to pkt.
488
 *
489
 * The length of the (encrypted) packet payload should be written to hdr->len
490
 * and will be placed in the serialized packet header. The payload data itself
491
 * is not copied; the caller should write hdr->len bytes of encrypted payload to
492
 * the WPACKET immediately after the call to this function. However,
493
 * WPACKET_reserve_bytes is called for the payload size.
494
 *
495
 * This function does not apply header protection. You must apply header
496
 * protection yourself after calling this function. *ptrs is filled with
497
 * pointers which can be passed to a header protector, but this must be
498
 * performed after the encrypted payload is written.
499
 *
500
 * The pointers in *ptrs are direct pointers into the WPACKET buffer. If more
501
 * data is written to the WPACKET buffer, WPACKET buffer reallocations may
502
 * occur, causing these pointers to become invalid. Therefore, you must not call
503
 * any write WPACKET function between this call and the call to
504
 * ossl_quic_hdr_protector_encrypt. This function calls WPACKET_reserve_bytes
505
 * for the payload length, so you may assume hdr->len bytes are already free to
506
 * write at the WPACKET cursor location once this function returns successfully.
507
 * It is recommended that you call this function, write the encrypted payload,
508
 * call ossl_quic_hdr_protector_encrypt, and then call
509
 * WPACKET_allocate_bytes(hdr->len).
510
 *
511
 * Version Negotiation and Retry packets do not use header protection; for these
512
 * header types, the fields in *ptrs are all written as zero. Version
513
 * Negotiation, Retry and 1-RTT packets do not contain a Length field, but
514
 * hdr->len bytes of data are still reserved in the WPACKET.
515
 *
516
 * If serializing a short packet and short_conn_id_len does not match the DCID
517
 * specified in hdr, the function fails.
518
 *
519
 * Returns 1 on success and 0 on failure.
520
 */
521
int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
522
                                  size_t short_conn_id_len,
523
                                  const QUIC_PKT_HDR *hdr,
524
                                  QUIC_PKT_HDR_PTRS *ptrs);
525
526
/*
527
 * Retrieves only the DCID from a packet header. This is intended for demuxer
528
 * use. It avoids the need to parse the rest of the packet header twice.
529
 *
530
 * Information on packet length is not decoded, as this only needs to be used on
531
 * the first packet in a datagram, therefore this takes a buffer and not a
532
 * PACKET.
533
 *
534
 * Returns 1 on success and 0 on failure.
535
 */
536
int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
537
                                           size_t buf_len,
538
                                           size_t short_conn_id_len,
539
                                           QUIC_CONN_ID *dst_conn_id);
540
541
/*
542
 * Precisely predicts the encoded length of a packet header structure.
543
 *
544
 * May return 0 if the packet header is not valid, but the fact that this
545
 * function returns non-zero does not guarantee that
546
 * ossl_quic_wire_encode_pkt_hdr() will succeed.
547
 */
548
int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
549
                                           const QUIC_PKT_HDR *hdr);
550
551
/*
552
 * Packet Number Encoding
553
 * ======================
554
 */
555
556
/*
557
 * Decode an encoded packet header QUIC PN.
558
 *
559
 * enc_pn is the raw encoded PN to decode. enc_pn_len is its length in bytes as
560
 * indicated by packet headers. largest_pn is the largest PN successfully
561
 * processed in the relevant PN space.
562
 *
563
 * The resulting PN is written to *res_pn.
564
 *
565
 * Returns 1 on success or 0 on failure.
566
 */
567
int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
568
                                     size_t enc_pn_len,
569
                                     QUIC_PN largest_pn,
570
                                     QUIC_PN *res_pn);
571
572
/*
573
 * Determine how many bytes should be used to encode a PN. Returns the number of
574
 * bytes (which will be in range [1, 4]).
575
 */
576
int ossl_quic_wire_determine_pn_len(QUIC_PN pn, QUIC_PN largest_acked);
577
578
/*
579
 * Encode a PN for a packet header using the specified number of bytes, which
580
 * should have been determined by calling ossl_quic_wire_determine_pn_len. The
581
 * PN encoding process is done in two parts to allow the caller to override PN
582
 * encoding length if it wishes.
583
 *
584
 * Returns 1 on success and 0 on failure.
585
 */
586
int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
587
                                     unsigned char *enc_pn,
588
                                     size_t enc_pn_len);
589
590
/*
591
 * Retry Integrity Tags
592
 * ====================
593
 */
594
595
0
#  define QUIC_RETRY_INTEGRITY_TAG_LEN    16
596
597
/*
598
 * Validate a retry integrity tag. Returns 1 if the tag is valid.
599
 *
600
 * Must be called on a hdr with a type of QUIC_PKT_TYPE_RETRY with a valid data
601
 * pointer.
602
 *
603
 * client_initial_dcid must be the original DCID used by the client in its first
604
 * Initial packet, as this is used to calculate the Retry Integrity Tag.
605
 *
606
 * Returns 0 if the tag is invalid, if called on any other type of packet or if
607
 * the body is too short.
608
 */
609
int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
610
                                           const char *propq,
611
                                           const QUIC_PKT_HDR *hdr,
612
                                           const QUIC_CONN_ID *client_initial_dcid);
613
614
/*
615
 * Calculates a retry integrity tag. Returns 0 on error, for example if hdr does
616
 * not have a type of QUIC_PKT_TYPE_RETRY.
617
 *
618
 * client_initial_dcid must be the original DCID used by the client in its first
619
 * Initial packet, as this is used to calculate the Retry Integrity Tag.
620
 *
621
 * tag must point to a buffer of QUIC_RETRY_INTEGRITY_TAG_LEN bytes in size.
622
 *
623
 * Note that hdr->data must point to the Retry packet body, and hdr->len must
624
 * include the space for the Retry Integrity Tag. (This means that you can
625
 * easily fill in a tag in a Retry packet you are generating by calling this
626
 * function and passing (hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) as
627
 * the tag argument.) This function fails if hdr->len is too short to contain a
628
 * Retry Integrity Tag.
629
 */
630
int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
631
                                            const char *propq,
632
                                            const QUIC_PKT_HDR *hdr,
633
                                            const QUIC_CONN_ID *client_initial_dcid,
634
                                            unsigned char *tag);
635
636
# endif
637
638
#endif