]> git.ipfire.org Git - thirdparty/openssl.git/blame - ssl/quic/quic_record_util.c
QUIC Record Layer (Refactor and TX Side)
[thirdparty/openssl.git] / ssl / quic / quic_record_util.c
CommitLineData
ec279ac2
HL
1/*
2 * Copyright 2022 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#include "internal/quic_record_util.h"
19571483
HL
11#include "internal/quic_record_rx.h"
12#include "internal/quic_record_tx.h"
ec279ac2 13#include "internal/quic_wire_pkt.h"
19571483 14#include "../ssl_local.h"
ec279ac2
HL
15#include <openssl/kdf.h>
16#include <openssl/core_names.h>
17
18/*
19 * QUIC Key Derivation Utilities
20 * =============================
21 */
22int ossl_quic_hkdf_extract(OSSL_LIB_CTX *libctx,
23 const char *propq,
24 const EVP_MD *md,
25 const unsigned char *salt, size_t salt_len,
26 const unsigned char *ikm, size_t ikm_len,
27 unsigned char *out, size_t out_len)
28{
29 int ret = 0;
30 EVP_KDF *kdf = NULL;
31 EVP_KDF_CTX *kctx = NULL;
32 OSSL_PARAM params[7], *p = params;
33 int mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
34 const char *md_name;
35
36 if ((md_name = EVP_MD_get0_name(md)) == NULL
37 || (kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_HKDF, propq)) == NULL
38 || (kctx = EVP_KDF_CTX_new(kdf)) == NULL)
39 goto err;
40
41 *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
42 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
43 (char *)md_name, 0);
44 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
45 (unsigned char *)salt, salt_len);
46 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
47 (unsigned char *)ikm, ikm_len);
48 *p++ = OSSL_PARAM_construct_end();
49
50 ret = EVP_KDF_derive(kctx, out, out_len, params);
51
52err:
53 EVP_KDF_CTX_free(kctx);
54 EVP_KDF_free(kdf);
55 return ret;
56}
57
19571483
HL
58/* Constants used for key derivation in QUIC v1. */
59static const unsigned char quic_client_in_label[] = {
60 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e /* "client in" */
61};
62static const unsigned char quic_server_in_label[] = {
63 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x69, 0x6e /* "server in" */
64};
65
66/* Salt used to derive Initial packet protection keys (RFC 9001 Section 5.2). */
67static const unsigned char quic_v1_initial_salt[] = {
68 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
69 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
70};
71
72int ossl_quic_provide_initial_secret(OSSL_LIB_CTX *libctx,
73 const char *propq,
74 const QUIC_CONN_ID *dst_conn_id,
75 int is_server,
76 struct ossl_qrx_st *qrx,
77 struct ossl_qtx_st *qtx)
78{
79 unsigned char initial_secret[32];
80 unsigned char client_initial_secret[32], server_initial_secret[32];
81 unsigned char *rx_secret, *tx_secret;
82 EVP_MD *sha256;
83
84 if (qrx == NULL && qtx == NULL)
85 return 1;
86
87 /* Initial encryption always uses SHA-256. */
88 if ((sha256 = EVP_MD_fetch(libctx, "SHA256", propq)) == NULL)
89 return 0;
90
91 if (is_server) {
92 rx_secret = client_initial_secret;
93 tx_secret = server_initial_secret;
94 } else {
95 rx_secret = server_initial_secret;
96 tx_secret = client_initial_secret;
97 }
98
99 /* Derive initial secret from destination connection ID. */
100 if (!ossl_quic_hkdf_extract(libctx, propq,
101 sha256,
102 quic_v1_initial_salt,
103 sizeof(quic_v1_initial_salt),
104 dst_conn_id->id,
105 dst_conn_id->id_len,
106 initial_secret,
107 sizeof(initial_secret)))
108 goto err;
109
110 /* Derive "client in" secret. */
111 if (((qtx != NULL && tx_secret == client_initial_secret)
112 || (qrx != NULL && rx_secret == client_initial_secret))
113 && !tls13_hkdf_expand_ex(libctx, propq,
114 sha256,
115 initial_secret,
116 quic_client_in_label,
117 sizeof(quic_client_in_label),
118 NULL, 0,
119 client_initial_secret,
120 sizeof(client_initial_secret), 0))
121 goto err;
122
123 /* Derive "server in" secret. */
124 if (((qtx != NULL && tx_secret == server_initial_secret)
125 || (qrx != NULL && rx_secret == server_initial_secret))
126 && !tls13_hkdf_expand_ex(libctx, propq,
127 sha256,
128 initial_secret,
129 quic_server_in_label,
130 sizeof(quic_server_in_label),
131 NULL, 0,
132 server_initial_secret,
133 sizeof(server_initial_secret), 0))
134 goto err;
135
136 /* Setup RX EL. Initial encryption always uses AES-128-GCM. */
137 if (qrx != NULL
138 && !ossl_qrx_provide_secret(qrx, QUIC_ENC_LEVEL_INITIAL,
139 QRL_SUITE_AES128GCM,
140 sha256,
141 rx_secret,
142 sizeof(server_initial_secret)))
143 goto err;
144
145 /*
146 * ossl_qrx_provide_secret takes ownership of our ref to SHA256, so if we
147 * are initialising both sides, get a new ref for the following call for the
148 * TX side.
149 */
150 if (qrx != NULL && qtx != NULL && !EVP_MD_up_ref(sha256)) {
151 sha256 = NULL;
152 goto err;
153 }
154
155 /* Setup TX cipher. */
156 if (qtx != NULL
157 && !ossl_qtx_provide_secret(qtx, QUIC_ENC_LEVEL_INITIAL,
158 QRL_SUITE_AES128GCM,
159 sha256,
160 tx_secret,
161 sizeof(server_initial_secret)))
162 goto err;
163
164 return 1;
165
166err:
167 EVP_MD_free(sha256);
168 return 0;
169}
170
ec279ac2
HL
171/*
172 * QUIC Record Layer Ciphersuite Info
173 * ==================================
174 */
175
176struct suite_info {
177 const char *cipher_name, *md_name;
178 uint32_t secret_len, cipher_key_len, cipher_iv_len, cipher_tag_len;
179 uint32_t hdr_prot_key_len, hdr_prot_cipher_id;
19571483 180 uint64_t max_pkt, max_forged_pkt;
ec279ac2
HL
181};
182
183static const struct suite_info suite_aes128gcm = {
184 "AES-128-GCM", "SHA256", 32, 16, 12, 16, 16,
19571483
HL
185 QUIC_HDR_PROT_CIPHER_AES_128,
186 ((uint64_t)1) << 23, /* Limits as prescribed by RFC 9001 */
187 ((uint64_t)1) << 52,
ec279ac2
HL
188};
189
190static const struct suite_info suite_aes256gcm = {
191 "AES-256-GCM", "SHA384", 48, 32, 12, 16, 32,
19571483
HL
192 QUIC_HDR_PROT_CIPHER_AES_256,
193 ((uint64_t)1) << 23, /* Limits as prescribed by RFC 9001 */
194 ((uint64_t)1) << 52,
ec279ac2
HL
195};
196
197static const struct suite_info suite_chacha20poly1305 = {
198 "ChaCha20-Poly1305", "SHA256", 32, 32, 12, 16, 32,
19571483
HL
199 QUIC_HDR_PROT_CIPHER_CHACHA,
200 /* Do not use UINT64_MAX here as this represents an invalid value */
201 UINT64_MAX - 1, /* No applicable limit for this suite (RFC 9001) */
202 ((uint64_t)1) << 36, /* Limit as prescribed by RFC 9001 */
ec279ac2
HL
203};
204
205static const struct suite_info *get_suite(uint32_t suite_id)
206{
207 switch (suite_id) {
208 case QRL_SUITE_AES128GCM:
209 return &suite_aes128gcm;
210 case QRL_SUITE_AES256GCM:
211 return &suite_aes256gcm;
212 case QRL_SUITE_CHACHA20POLY1305:
213 return &suite_chacha20poly1305;
214 default:
215 return NULL;
216 }
217}
218
219const char *ossl_qrl_get_suite_cipher_name(uint32_t suite_id)
220{
221 const struct suite_info *c = get_suite(suite_id);
222 return c != NULL ? c->cipher_name : NULL;
223}
224
225const char *ossl_qrl_get_suite_md_name(uint32_t suite_id)
226{
227 const struct suite_info *c = get_suite(suite_id);
228 return c != NULL ? c->md_name : NULL;
229}
230
231uint32_t ossl_qrl_get_suite_secret_len(uint32_t suite_id)
232{
233 const struct suite_info *c = get_suite(suite_id);
234 return c != NULL ? c->secret_len : 0;
235}
236
237uint32_t ossl_qrl_get_suite_cipher_key_len(uint32_t suite_id)
238{
239 const struct suite_info *c = get_suite(suite_id);
240 return c != NULL ? c->cipher_key_len : 0;
241}
242
243uint32_t ossl_qrl_get_suite_cipher_iv_len(uint32_t suite_id)
244{
245 const struct suite_info *c = get_suite(suite_id);
246 return c != NULL ? c->cipher_iv_len : 0;
247}
248
249uint32_t ossl_qrl_get_suite_cipher_tag_len(uint32_t suite_id)
250{
251 const struct suite_info *c = get_suite(suite_id);
252 return c != NULL ? c->cipher_tag_len : 0;
253}
254
255uint32_t ossl_qrl_get_suite_hdr_prot_cipher_id(uint32_t suite_id)
256{
257 const struct suite_info *c = get_suite(suite_id);
258 return c != NULL ? c->hdr_prot_cipher_id : 0;
259}
260
261uint32_t ossl_qrl_get_suite_hdr_prot_key_len(uint32_t suite_id)
262{
263 const struct suite_info *c = get_suite(suite_id);
264 return c != NULL ? c->hdr_prot_key_len : 0;
265}
19571483
HL
266
267uint64_t ossl_qrl_get_suite_max_pkt(uint32_t suite_id)
268{
269 const struct suite_info *c = get_suite(suite_id);
270 return c != NULL ? c->max_pkt : UINT64_MAX;
271}
272
273uint64_t ossl_qrl_get_suite_max_forged_pkt(uint32_t suite_id)
274{
275 const struct suite_info *c = get_suite(suite_id);
276 return c != NULL ? c->max_forged_pkt : UINT64_MAX;
277}