Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/ssl/quic/quic_wire_pkt.c
48261 views
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
#include <openssl/err.h>
11
#include "internal/common.h"
12
#include "internal/quic_wire_pkt.h"
13
14
int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
15
OSSL_LIB_CTX *libctx,
16
const char *propq,
17
uint32_t cipher_id,
18
const unsigned char *quic_hp_key,
19
size_t quic_hp_key_len)
20
{
21
const char *cipher_name = NULL;
22
23
switch (cipher_id) {
24
case QUIC_HDR_PROT_CIPHER_AES_128:
25
cipher_name = "AES-128-ECB";
26
break;
27
case QUIC_HDR_PROT_CIPHER_AES_256:
28
cipher_name = "AES-256-ECB";
29
break;
30
case QUIC_HDR_PROT_CIPHER_CHACHA:
31
cipher_name = "ChaCha20";
32
break;
33
default:
34
ERR_raise(ERR_LIB_SSL, ERR_R_UNSUPPORTED);
35
return 0;
36
}
37
38
hpr->cipher_ctx = EVP_CIPHER_CTX_new();
39
if (hpr->cipher_ctx == NULL) {
40
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
41
return 0;
42
}
43
44
hpr->cipher = EVP_CIPHER_fetch(libctx, cipher_name, propq);
45
if (hpr->cipher == NULL
46
|| quic_hp_key_len != (size_t)EVP_CIPHER_get_key_length(hpr->cipher)) {
47
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
48
goto err;
49
}
50
51
if (!EVP_CipherInit_ex(hpr->cipher_ctx, hpr->cipher, NULL,
52
quic_hp_key, NULL, 1)) {
53
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
54
goto err;
55
}
56
57
hpr->libctx = libctx;
58
hpr->propq = propq;
59
hpr->cipher_id = cipher_id;
60
return 1;
61
62
err:
63
ossl_quic_hdr_protector_cleanup(hpr);
64
return 0;
65
}
66
67
void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr)
68
{
69
EVP_CIPHER_CTX_free(hpr->cipher_ctx);
70
hpr->cipher_ctx = NULL;
71
72
EVP_CIPHER_free(hpr->cipher);
73
hpr->cipher = NULL;
74
}
75
76
static int hdr_generate_mask(QUIC_HDR_PROTECTOR *hpr,
77
const unsigned char *sample, size_t sample_len,
78
unsigned char *mask)
79
{
80
int l = 0;
81
unsigned char dst[16];
82
static const unsigned char zeroes[5] = {0};
83
size_t i;
84
85
if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_128
86
|| hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_256) {
87
if (sample_len < 16) {
88
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
89
return 0;
90
}
91
92
if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, NULL, 1)
93
|| !EVP_CipherUpdate(hpr->cipher_ctx, dst, &l, sample, 16)) {
94
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
95
return 0;
96
}
97
98
for (i = 0; i < 5; ++i)
99
mask[i] = dst[i];
100
} else if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_CHACHA) {
101
if (sample_len < 16) {
102
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
103
return 0;
104
}
105
106
if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, sample, 1)
107
|| !EVP_CipherUpdate(hpr->cipher_ctx, mask, &l,
108
zeroes, sizeof(zeroes))) {
109
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
110
return 0;
111
}
112
} else {
113
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
114
assert(0);
115
return 0;
116
}
117
118
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
119
/* No matter what we did above we use the same mask in fuzzing mode */
120
memset(mask, 0, 5);
121
#endif
122
123
return 1;
124
}
125
126
int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
127
QUIC_PKT_HDR_PTRS *ptrs)
128
{
129
return ossl_quic_hdr_protector_decrypt_fields(hpr,
130
ptrs->raw_sample,
131
ptrs->raw_sample_len,
132
ptrs->raw_start,
133
ptrs->raw_pn);
134
}
135
136
int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
137
const unsigned char *sample,
138
size_t sample_len,
139
unsigned char *first_byte,
140
unsigned char *pn_bytes)
141
{
142
unsigned char mask[5], pn_len, i;
143
144
if (!hdr_generate_mask(hpr, sample, sample_len, mask))
145
return 0;
146
147
*first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
148
pn_len = (*first_byte & 0x3) + 1;
149
150
for (i = 0; i < pn_len; ++i)
151
pn_bytes[i] ^= mask[i + 1];
152
153
return 1;
154
}
155
156
int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
157
QUIC_PKT_HDR_PTRS *ptrs)
158
{
159
return ossl_quic_hdr_protector_encrypt_fields(hpr,
160
ptrs->raw_sample,
161
ptrs->raw_sample_len,
162
ptrs->raw_start,
163
ptrs->raw_pn);
164
}
165
166
int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
167
const unsigned char *sample,
168
size_t sample_len,
169
unsigned char *first_byte,
170
unsigned char *pn_bytes)
171
{
172
unsigned char mask[5], pn_len, i;
173
174
if (!hdr_generate_mask(hpr, sample, sample_len, mask))
175
return 0;
176
177
pn_len = (*first_byte & 0x3) + 1;
178
for (i = 0; i < pn_len; ++i)
179
pn_bytes[i] ^= mask[i + 1];
180
181
*first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
182
return 1;
183
}
184
185
int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
186
size_t short_conn_id_len,
187
int partial,
188
int nodata,
189
QUIC_PKT_HDR *hdr,
190
QUIC_PKT_HDR_PTRS *ptrs,
191
uint64_t *fail_cause)
192
{
193
unsigned int b0;
194
unsigned char *pn = NULL;
195
size_t l = PACKET_remaining(pkt);
196
197
if (fail_cause != NULL)
198
*fail_cause = QUIC_PKT_HDR_DECODE_DECODE_ERR;
199
200
if (ptrs != NULL) {
201
ptrs->raw_start = (unsigned char *)PACKET_data(pkt);
202
ptrs->raw_sample = NULL;
203
ptrs->raw_sample_len = 0;
204
ptrs->raw_pn = NULL;
205
}
206
207
if (l < QUIC_MIN_VALID_PKT_LEN
208
|| !PACKET_get_1(pkt, &b0))
209
return 0;
210
211
hdr->partial = partial;
212
hdr->unused = 0;
213
hdr->reserved = 0;
214
215
if ((b0 & 0x80) == 0) {
216
/* Short header. */
217
if (short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
218
return 0;
219
220
if ((b0 & 0x40) == 0 /* fixed bit not set? */
221
|| l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
222
return 0;
223
224
hdr->type = QUIC_PKT_TYPE_1RTT;
225
hdr->fixed = 1;
226
hdr->spin_bit = (b0 & 0x20) != 0;
227
if (partial) {
228
hdr->key_phase = 0; /* protected, zero for now */
229
hdr->pn_len = 0; /* protected, zero for now */
230
hdr->reserved = 0; /* protected, zero for now */
231
} else {
232
hdr->key_phase = (b0 & 0x04) != 0;
233
hdr->pn_len = (b0 & 0x03) + 1;
234
hdr->reserved = (b0 & 0x18) >> 3;
235
}
236
237
/* Copy destination connection ID field to header structure. */
238
if (!PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, short_conn_id_len))
239
return 0;
240
241
hdr->dst_conn_id.id_len = (unsigned char)short_conn_id_len;
242
243
/*
244
* Skip over the PN. If this is a partial decode, the PN length field
245
* currently has header protection applied. Thus we do not know the
246
* length of the PN but we are allowed to assume it is 4 bytes long at
247
* this stage.
248
*/
249
memset(hdr->pn, 0, sizeof(hdr->pn));
250
pn = (unsigned char *)PACKET_data(pkt);
251
if (partial) {
252
if (!PACKET_forward(pkt, sizeof(hdr->pn)))
253
return 0;
254
} else {
255
if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
256
return 0;
257
}
258
259
/* Fields not used in short-header packets. */
260
hdr->version = 0;
261
hdr->src_conn_id.id_len = 0;
262
hdr->token = NULL;
263
hdr->token_len = 0;
264
265
/*
266
* Short-header packets always come last in a datagram, the length
267
* is the remainder of the buffer.
268
*/
269
hdr->len = PACKET_remaining(pkt);
270
hdr->data = PACKET_data(pkt);
271
272
/*
273
* Skip over payload. Since this is a short header packet, which cannot
274
* be followed by any other kind of packet, this advances us to the end
275
* of the datagram.
276
*/
277
if (!PACKET_forward(pkt, hdr->len))
278
return 0;
279
} else {
280
/* Long header. */
281
unsigned long version;
282
unsigned int dst_conn_id_len, src_conn_id_len, raw_type;
283
284
if (!PACKET_get_net_4(pkt, &version))
285
return 0;
286
287
/*
288
* All QUIC packets must have the fixed bit set, except exceptionally
289
* for Version Negotiation packets.
290
*/
291
if (version != 0 && (b0 & 0x40) == 0)
292
return 0;
293
294
if (!PACKET_get_1(pkt, &dst_conn_id_len)
295
|| dst_conn_id_len > QUIC_MAX_CONN_ID_LEN
296
|| !PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, dst_conn_id_len)
297
|| !PACKET_get_1(pkt, &src_conn_id_len)
298
|| src_conn_id_len > QUIC_MAX_CONN_ID_LEN
299
|| !PACKET_copy_bytes(pkt, hdr->src_conn_id.id, src_conn_id_len))
300
return 0;
301
302
hdr->version = (uint32_t)version;
303
hdr->dst_conn_id.id_len = (unsigned char)dst_conn_id_len;
304
hdr->src_conn_id.id_len = (unsigned char)src_conn_id_len;
305
306
if (version == 0) {
307
/*
308
* Version negotiation packet. Version negotiation packets are
309
* identified by a version field of 0 and the type bits in the first
310
* byte are ignored (they may take any value, and we ignore them).
311
*/
312
hdr->type = QUIC_PKT_TYPE_VERSION_NEG;
313
hdr->fixed = (b0 & 0x40) != 0;
314
315
hdr->data = PACKET_data(pkt);
316
hdr->len = PACKET_remaining(pkt);
317
318
/*
319
* Version negotiation packets must contain an array of u32s, so it
320
* is invalid for their payload length to not be divisible by 4.
321
*/
322
if ((hdr->len % 4) != 0)
323
return 0;
324
325
/* Version negotiation packets are always fully decoded. */
326
hdr->partial = 0;
327
328
/* Fields not used in version negotiation packets. */
329
hdr->pn_len = 0;
330
hdr->spin_bit = 0;
331
hdr->key_phase = 0;
332
hdr->token = NULL;
333
hdr->token_len = 0;
334
memset(hdr->pn, 0, sizeof(hdr->pn));
335
336
if (!PACKET_forward(pkt, hdr->len))
337
return 0;
338
} else if (version != QUIC_VERSION_1) {
339
if (fail_cause != NULL)
340
*fail_cause |= QUIC_PKT_HDR_DECODE_BAD_VERSION;
341
/* Unknown version, do not decode. */
342
return 0;
343
} else {
344
if (l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
345
return 0;
346
347
/* Get long packet type and decode to QUIC_PKT_TYPE_*. */
348
raw_type = ((b0 >> 4) & 0x3);
349
350
switch (raw_type) {
351
case 0:
352
hdr->type = QUIC_PKT_TYPE_INITIAL;
353
break;
354
case 1:
355
hdr->type = QUIC_PKT_TYPE_0RTT;
356
break;
357
case 2:
358
hdr->type = QUIC_PKT_TYPE_HANDSHAKE;
359
break;
360
case 3:
361
hdr->type = QUIC_PKT_TYPE_RETRY;
362
break;
363
}
364
365
hdr->pn_len = 0;
366
hdr->fixed = 1;
367
368
/* Fields not used in long-header packets. */
369
hdr->spin_bit = 0;
370
hdr->key_phase = 0;
371
372
if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
373
/* Initial packet. */
374
uint64_t token_len;
375
376
if (!PACKET_get_quic_vlint(pkt, &token_len)
377
|| token_len > SIZE_MAX
378
|| !PACKET_get_bytes(pkt, &hdr->token, (size_t)token_len))
379
return 0;
380
381
hdr->token_len = (size_t)token_len;
382
if (token_len == 0)
383
hdr->token = NULL;
384
} else {
385
hdr->token = NULL;
386
hdr->token_len = 0;
387
}
388
389
if (hdr->type == QUIC_PKT_TYPE_RETRY) {
390
/* Retry packet. */
391
hdr->data = PACKET_data(pkt);
392
hdr->len = PACKET_remaining(pkt);
393
394
/* Retry packets are always fully decoded. */
395
hdr->partial = 0;
396
397
/* Unused bits in Retry header. */
398
hdr->unused = b0 & 0x0f;
399
400
/* Fields not used in Retry packets. */
401
memset(hdr->pn, 0, sizeof(hdr->pn));
402
403
if (!PACKET_forward(pkt, hdr->len))
404
return 0;
405
} else {
406
/* Initial, 0-RTT or Handshake packet. */
407
uint64_t len;
408
409
hdr->pn_len = partial ? 0 : ((b0 & 0x03) + 1);
410
hdr->reserved = partial ? 0 : ((b0 & 0x0C) >> 2);
411
412
if (!PACKET_get_quic_vlint(pkt, &len)
413
|| len < sizeof(hdr->pn))
414
return 0;
415
416
if (!nodata && len > PACKET_remaining(pkt))
417
return 0;
418
419
/*
420
* Skip over the PN. If this is a partial decode, the PN length
421
* field currently has header protection applied. Thus we do not
422
* know the length of the PN but we are allowed to assume it is
423
* 4 bytes long at this stage.
424
*/
425
pn = (unsigned char *)PACKET_data(pkt);
426
memset(hdr->pn, 0, sizeof(hdr->pn));
427
if (partial) {
428
if (!PACKET_forward(pkt, sizeof(hdr->pn)))
429
return 0;
430
431
hdr->len = (size_t)(len - sizeof(hdr->pn));
432
} else {
433
if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
434
return 0;
435
436
hdr->len = (size_t)(len - hdr->pn_len);
437
}
438
439
if (nodata) {
440
hdr->data = NULL;
441
} else {
442
hdr->data = PACKET_data(pkt);
443
444
/* Skip over packet body. */
445
if (!PACKET_forward(pkt, hdr->len))
446
return 0;
447
}
448
}
449
}
450
}
451
452
if (ptrs != NULL) {
453
ptrs->raw_pn = pn;
454
if (pn != NULL) {
455
ptrs->raw_sample = pn + 4;
456
ptrs->raw_sample_len = PACKET_end(pkt) - ptrs->raw_sample;
457
}
458
}
459
460
/*
461
* Good decode, clear the generic DECODE_ERR flag
462
*/
463
if (fail_cause != NULL)
464
*fail_cause &= ~QUIC_PKT_HDR_DECODE_DECODE_ERR;
465
466
return 1;
467
}
468
469
int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
470
size_t short_conn_id_len,
471
const QUIC_PKT_HDR *hdr,
472
QUIC_PKT_HDR_PTRS *ptrs)
473
{
474
unsigned char b0;
475
size_t off_start, off_sample, off_pn;
476
unsigned char *start = WPACKET_get_curr(pkt);
477
478
if (!WPACKET_get_total_written(pkt, &off_start))
479
return 0;
480
481
if (ptrs != NULL) {
482
/* ptrs would not be stable on non-static WPACKET */
483
if (!ossl_assert(pkt->staticbuf != NULL))
484
return 0;
485
ptrs->raw_start = NULL;
486
ptrs->raw_sample = NULL;
487
ptrs->raw_sample_len = 0;
488
ptrs->raw_pn = 0;
489
}
490
491
/* Cannot serialize a partial header, or one whose DCID length is wrong. */
492
if (hdr->partial
493
|| (hdr->type == QUIC_PKT_TYPE_1RTT
494
&& hdr->dst_conn_id.id_len != short_conn_id_len))
495
return 0;
496
497
if (hdr->type == QUIC_PKT_TYPE_1RTT) {
498
/* Short header. */
499
500
/*
501
* Cannot serialize a header whose DCID length is wrong, or with an
502
* invalid PN length.
503
*/
504
if (hdr->dst_conn_id.id_len != short_conn_id_len
505
|| short_conn_id_len > QUIC_MAX_CONN_ID_LEN
506
|| hdr->pn_len < 1 || hdr->pn_len > 4)
507
return 0;
508
509
b0 = (hdr->spin_bit << 5)
510
| (hdr->key_phase << 2)
511
| (hdr->pn_len - 1)
512
| (hdr->reserved << 3)
513
| 0x40; /* fixed bit */
514
515
if (!WPACKET_put_bytes_u8(pkt, b0)
516
|| !WPACKET_memcpy(pkt, hdr->dst_conn_id.id, short_conn_id_len)
517
|| !WPACKET_get_total_written(pkt, &off_pn)
518
|| !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
519
return 0;
520
} else {
521
/* Long header. */
522
unsigned int raw_type;
523
524
if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
525
|| hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
526
return 0;
527
528
if (ossl_quic_pkt_type_has_pn(hdr->type)
529
&& (hdr->pn_len < 1 || hdr->pn_len > 4))
530
return 0;
531
532
switch (hdr->type) {
533
case QUIC_PKT_TYPE_VERSION_NEG:
534
if (hdr->version != 0)
535
return 0;
536
537
/* Version negotiation packets use zero for the type bits */
538
raw_type = 0;
539
break;
540
541
case QUIC_PKT_TYPE_INITIAL: raw_type = 0; break;
542
case QUIC_PKT_TYPE_0RTT: raw_type = 1; break;
543
case QUIC_PKT_TYPE_HANDSHAKE: raw_type = 2; break;
544
case QUIC_PKT_TYPE_RETRY: raw_type = 3; break;
545
default:
546
return 0;
547
}
548
549
b0 = (raw_type << 4) | 0x80; /* long */
550
if (hdr->type != QUIC_PKT_TYPE_VERSION_NEG || hdr->fixed)
551
b0 |= 0x40; /* fixed */
552
if (ossl_quic_pkt_type_has_pn(hdr->type)) {
553
b0 |= hdr->pn_len - 1;
554
b0 |= (hdr->reserved << 2);
555
}
556
if (hdr->type == QUIC_PKT_TYPE_RETRY)
557
b0 |= hdr->unused;
558
559
if (!WPACKET_put_bytes_u8(pkt, b0)
560
|| !WPACKET_put_bytes_u32(pkt, hdr->version)
561
|| !WPACKET_put_bytes_u8(pkt, hdr->dst_conn_id.id_len)
562
|| !WPACKET_memcpy(pkt, hdr->dst_conn_id.id,
563
hdr->dst_conn_id.id_len)
564
|| !WPACKET_put_bytes_u8(pkt, hdr->src_conn_id.id_len)
565
|| !WPACKET_memcpy(pkt, hdr->src_conn_id.id,
566
hdr->src_conn_id.id_len))
567
return 0;
568
569
if (hdr->type == QUIC_PKT_TYPE_VERSION_NEG) {
570
if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
571
return 0;
572
573
return 1;
574
}
575
576
if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
577
if (!WPACKET_quic_write_vlint(pkt, hdr->token_len)
578
|| !WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
579
return 0;
580
}
581
582
if (hdr->type == QUIC_PKT_TYPE_RETRY) {
583
if (!WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
584
return 0;
585
return 1;
586
}
587
588
if (!WPACKET_quic_write_vlint(pkt, hdr->len + hdr->pn_len)
589
|| !WPACKET_get_total_written(pkt, &off_pn)
590
|| !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
591
return 0;
592
}
593
594
if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
595
return 0;
596
597
off_sample = off_pn + 4;
598
599
if (ptrs != NULL) {
600
ptrs->raw_start = start;
601
ptrs->raw_sample = start + (off_sample - off_start);
602
ptrs->raw_sample_len
603
= WPACKET_get_curr(pkt) + hdr->len - ptrs->raw_sample;
604
ptrs->raw_pn = start + (off_pn - off_start);
605
}
606
607
return 1;
608
}
609
610
int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
611
const QUIC_PKT_HDR *hdr)
612
{
613
size_t len = 0, enclen;
614
615
/* Cannot serialize a partial header, or one whose DCID length is wrong. */
616
if (hdr->partial
617
|| (hdr->type == QUIC_PKT_TYPE_1RTT
618
&& hdr->dst_conn_id.id_len != short_conn_id_len))
619
return 0;
620
621
if (hdr->type == QUIC_PKT_TYPE_1RTT) {
622
/* Short header. */
623
624
/*
625
* Cannot serialize a header whose DCID length is wrong, or with an
626
* invalid PN length.
627
*/
628
if (hdr->dst_conn_id.id_len != short_conn_id_len
629
|| short_conn_id_len > QUIC_MAX_CONN_ID_LEN
630
|| hdr->pn_len < 1 || hdr->pn_len > 4)
631
return 0;
632
633
return 1 + short_conn_id_len + hdr->pn_len;
634
} else {
635
/* Long header. */
636
if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
637
|| hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
638
return 0;
639
640
len += 1 /* Initial byte */ + 4 /* Version */
641
+ 1 + hdr->dst_conn_id.id_len /* DCID Len, DCID */
642
+ 1 + hdr->src_conn_id.id_len /* SCID Len, SCID */
643
;
644
645
if (ossl_quic_pkt_type_has_pn(hdr->type)) {
646
if (hdr->pn_len < 1 || hdr->pn_len > 4)
647
return 0;
648
649
len += hdr->pn_len;
650
}
651
652
if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
653
enclen = ossl_quic_vlint_encode_len(hdr->token_len);
654
if (!enclen)
655
return 0;
656
657
len += enclen + hdr->token_len;
658
}
659
660
if (!ossl_quic_pkt_type_must_be_last(hdr->type)) {
661
enclen = ossl_quic_vlint_encode_len(hdr->len + hdr->pn_len);
662
if (!enclen)
663
return 0;
664
665
len += enclen;
666
}
667
668
return len;
669
}
670
}
671
672
int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
673
size_t buf_len,
674
size_t short_conn_id_len,
675
QUIC_CONN_ID *dst_conn_id)
676
{
677
unsigned char b0;
678
size_t blen;
679
680
if (buf_len < QUIC_MIN_VALID_PKT_LEN
681
|| short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
682
return 0;
683
684
b0 = buf[0];
685
if ((b0 & 0x80) != 0) {
686
/*
687
* Long header. We need 6 bytes (initial byte, 4 version bytes, DCID
688
* length byte to begin with). This is covered by the buf_len test
689
* above.
690
*/
691
692
/*
693
* If the version field is non-zero (meaning that this is not a Version
694
* Negotiation packet), the fixed bit must be set.
695
*/
696
if ((buf[1] || buf[2] || buf[3] || buf[4]) && (b0 & 0x40) == 0)
697
return 0;
698
699
blen = (size_t)buf[5]; /* DCID Length */
700
if (blen > QUIC_MAX_CONN_ID_LEN
701
|| buf_len < QUIC_MIN_VALID_PKT_LEN + blen)
702
return 0;
703
704
dst_conn_id->id_len = (unsigned char)blen;
705
memcpy(dst_conn_id->id, buf + 6, blen);
706
return 1;
707
} else {
708
/* Short header. */
709
if ((b0 & 0x40) == 0)
710
/* Fixed bit not set, not a valid QUIC packet header. */
711
return 0;
712
713
if (buf_len < QUIC_MIN_VALID_PKT_LEN_CRYPTO + short_conn_id_len)
714
return 0;
715
716
dst_conn_id->id_len = (unsigned char)short_conn_id_len;
717
memcpy(dst_conn_id->id, buf + 1, short_conn_id_len);
718
return 1;
719
}
720
}
721
722
int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
723
size_t enc_pn_len,
724
QUIC_PN largest_pn,
725
QUIC_PN *res_pn)
726
{
727
int64_t expected_pn, truncated_pn, candidate_pn, pn_win, pn_hwin, pn_mask;
728
729
switch (enc_pn_len) {
730
case 1:
731
truncated_pn = enc_pn[0];
732
break;
733
case 2:
734
truncated_pn = ((QUIC_PN)enc_pn[0] << 8)
735
| (QUIC_PN)enc_pn[1];
736
break;
737
case 3:
738
truncated_pn = ((QUIC_PN)enc_pn[0] << 16)
739
| ((QUIC_PN)enc_pn[1] << 8)
740
| (QUIC_PN)enc_pn[2];
741
break;
742
case 4:
743
truncated_pn = ((QUIC_PN)enc_pn[0] << 24)
744
| ((QUIC_PN)enc_pn[1] << 16)
745
| ((QUIC_PN)enc_pn[2] << 8)
746
| (QUIC_PN)enc_pn[3];
747
break;
748
default:
749
return 0;
750
}
751
752
/* Implemented as per RFC 9000 Section A.3. */
753
expected_pn = largest_pn + 1;
754
pn_win = ((int64_t)1) << (enc_pn_len * 8);
755
pn_hwin = pn_win / 2;
756
pn_mask = pn_win - 1;
757
candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
758
if (candidate_pn <= expected_pn - pn_hwin
759
&& candidate_pn < (((int64_t)1) << 62) - pn_win)
760
*res_pn = candidate_pn + pn_win;
761
else if (candidate_pn > expected_pn + pn_hwin
762
&& candidate_pn >= pn_win)
763
*res_pn = candidate_pn - pn_win;
764
else
765
*res_pn = candidate_pn;
766
return 1;
767
}
768
769
/* From RFC 9000 Section A.2. Simplified implementation. */
770
int ossl_quic_wire_determine_pn_len(QUIC_PN pn,
771
QUIC_PN largest_acked)
772
{
773
uint64_t num_unacked
774
= (largest_acked == QUIC_PN_INVALID) ? pn + 1 : pn - largest_acked;
775
776
/*
777
* num_unacked \in [ 0, 2** 7] -> 1 byte
778
* num_unacked \in (2** 7, 2**15] -> 2 bytes
779
* num_unacked \in (2**15, 2**23] -> 3 bytes
780
* num_unacked \in (2**23, ] -> 4 bytes
781
*/
782
783
if (num_unacked <= (1U<<7)) return 1;
784
if (num_unacked <= (1U<<15)) return 2;
785
if (num_unacked <= (1U<<23)) return 3;
786
return 4;
787
}
788
789
int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
790
unsigned char *enc_pn,
791
size_t enc_pn_len)
792
{
793
switch (enc_pn_len) {
794
case 1:
795
enc_pn[0] = (unsigned char)pn;
796
break;
797
case 2:
798
enc_pn[1] = (unsigned char)pn;
799
enc_pn[0] = (unsigned char)(pn >> 8);
800
break;
801
case 3:
802
enc_pn[2] = (unsigned char)pn;
803
enc_pn[1] = (unsigned char)(pn >> 8);
804
enc_pn[0] = (unsigned char)(pn >> 16);
805
break;
806
case 4:
807
enc_pn[3] = (unsigned char)pn;
808
enc_pn[2] = (unsigned char)(pn >> 8);
809
enc_pn[1] = (unsigned char)(pn >> 16);
810
enc_pn[0] = (unsigned char)(pn >> 24);
811
break;
812
default:
813
return 0;
814
}
815
816
return 1;
817
}
818
819
int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
820
const char *propq,
821
const QUIC_PKT_HDR *hdr,
822
const QUIC_CONN_ID *client_initial_dcid)
823
{
824
unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
825
const unsigned char *actual_tag;
826
827
if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
828
return 0;
829
830
if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
831
hdr, client_initial_dcid,
832
expected_tag))
833
return 0;
834
835
actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
836
837
return !CRYPTO_memcmp(expected_tag, actual_tag,
838
QUIC_RETRY_INTEGRITY_TAG_LEN);
839
}
840
841
/* RFC 9001 s. 5.8 */
842
static const unsigned char retry_integrity_key[] = {
843
0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
844
0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
845
};
846
847
static const unsigned char retry_integrity_nonce[] = {
848
0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2,
849
0x23, 0x98, 0x25, 0xbb
850
};
851
852
int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
853
const char *propq,
854
const QUIC_PKT_HDR *hdr,
855
const QUIC_CONN_ID *client_initial_dcid,
856
unsigned char *tag)
857
{
858
EVP_CIPHER *cipher = NULL;
859
EVP_CIPHER_CTX *cctx = NULL;
860
int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
861
WPACKET wpkt;
862
/* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
863
unsigned char buf[128];
864
QUIC_PKT_HDR hdr2;
865
size_t hdr_enc_len = 0;
866
867
if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
868
|| hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
869
|| hdr->data == NULL
870
|| client_initial_dcid == NULL || tag == NULL
871
|| client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN) {
872
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
873
goto err;
874
}
875
876
/*
877
* Do not reserve packet body in WPACKET. Retry packet header
878
* does not contain a Length field so this does not affect
879
* the serialized packet header.
880
*/
881
hdr2 = *hdr;
882
hdr2.len = 0;
883
884
/* Assemble retry psuedo-packet. */
885
if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0)) {
886
ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
887
goto err;
888
}
889
890
wpkt_valid = 1;
891
892
/* Prepend original DCID to the packet. */
893
if (!WPACKET_put_bytes_u8(&wpkt, client_initial_dcid->id_len)
894
|| !WPACKET_memcpy(&wpkt, client_initial_dcid->id,
895
client_initial_dcid->id_len)) {
896
ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
897
goto err;
898
}
899
900
/* Encode main retry header. */
901
if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
902
&hdr2, NULL))
903
goto err;
904
905
if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len)) {
906
ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
907
goto err;
908
}
909
910
/* Create and initialise cipher context. */
911
/* TODO(QUIC FUTURE): Cipher fetch caching. */
912
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL) {
913
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
914
goto err;
915
}
916
917
if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
918
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
919
goto err;
920
}
921
922
if (!EVP_CipherInit_ex(cctx, cipher, NULL,
923
retry_integrity_key, retry_integrity_nonce, /*enc=*/1)) {
924
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
925
goto err;
926
}
927
928
/* Feed packet header as AAD data. */
929
if (EVP_CipherUpdate(cctx, NULL, &l, buf, hdr_enc_len) != 1) {
930
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
931
goto err;
932
}
933
934
/* Feed packet body as AAD data. */
935
if (EVP_CipherUpdate(cctx, NULL, &l, hdr->data,
936
hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) != 1) {
937
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
938
goto err;
939
}
940
941
/* Finalise and get tag. */
942
if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1) {
943
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
944
goto err;
945
}
946
947
if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
948
QUIC_RETRY_INTEGRITY_TAG_LEN,
949
tag) != 1) {
950
ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
951
goto err;
952
}
953
954
ok = 1;
955
err:
956
EVP_CIPHER_free(cipher);
957
EVP_CIPHER_CTX_free(cctx);
958
if (wpkt_valid)
959
WPACKET_finish(&wpkt);
960
961
return ok;
962
}
963
964