DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
quic_hkdf.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file quic_hkdf.h
6 * @brief HKDF-SHA256 (RFC 5869) and TLS 1.3 HKDF-Expand-Label (RFC 8446 sec 7.1).
7 *
8 * QUIC packet protection keys are derived with the TLS 1.3 key schedule (RFC 9001 sec 5.2):
9 * an Initial secret is HKDF-Extract'd from a fixed salt and the client's Destination Connection
10 * ID, and every packet-protection value (key / iv / hp) is an HKDF-Expand-Label of a traffic
11 * secret. This is the same HMAC-SHA256 the SSH transport already ships, so these two routines are
12 * a thin layer over ssh_hmac_sha256 rather than a second HMAC.
13 *
14 * Pure, zero heap, host-tested against the RFC 9001 Appendix A worked examples (the HkdfLabel
15 * byte strings and the derived client/server secrets).
16 *
17 * @author Douglas Quigg (dstroy0)
18 * @date 2026
19 */
20
21#ifndef DETERMINISTICESPASYNCWEBSERVER_QUIC_HKDF_H
22#define DETERMINISTICESPASYNCWEBSERVER_QUIC_HKDF_H
23
24#include "ServerConfig.h"
25
26// Shared by the HTTP/3 (QUIC) key schedule and the DTLS 1.3 record layer.
27#if (DETWS_ENABLE_HTTP3 || DETWS_ENABLE_DTLS)
28
29#include <stddef.h>
30#include <stdint.h>
31
32/** @brief HKDF-SHA256 output block length (== SHA-256 digest length). */
33#define QUIC_HKDF_HASH_LEN 32
34
35/**
36 * @brief HKDF-Extract (RFC 5869 sec 2.2): PRK = HMAC-SHA256(salt, ikm).
37 *
38 * @param salt Optional salt (may be NULL only when @p salt_len is 0).
39 * @param salt_len Salt length in bytes.
40 * @param ikm Input keying material.
41 * @param ikm_len Input keying material length.
42 * @param prk Output pseudo-random key, must be QUIC_HKDF_HASH_LEN bytes.
43 */
44void quic_hkdf_extract(const uint8_t *salt, size_t salt_len, const uint8_t *ikm, size_t ikm_len,
45 uint8_t prk[QUIC_HKDF_HASH_LEN]);
46
47/** @brief The RFC 8446 sec 7.1 HKDF-Expand-Label prefix used by TLS 1.3 and QUIC. DTLS 1.3 overrides
48 * it with "dtls13" (RFC 9147 sec 5.9); callers that need it pass it explicitly. */
49static constexpr char QUIC_HKDF_LABEL_PREFIX[] = "tls13 ";
50
51/**
52 * @brief HKDF-Expand-Label (RFC 8446 sec 7.1) with the QUIC/TLS 1.3 "tls13 " label prefix.
53 *
54 * Builds the HkdfLabel structure
55 * struct { uint16 length; opaque label<7..255> = "tls13 " + label; opaque context<0..255>; }
56 * and runs HKDF-Expand (RFC 5869 sec 2.3) with an empty context (all QUIC packet-protection uses of
57 * this function pass an empty context). @p out_len must not exceed 255*32 bytes; QUIC only ever asks
58 * for <= 32, which is a single HMAC block.
59 *
60 * @param secret Traffic secret (HKDF PRK), QUIC_HKDF_HASH_LEN bytes.
61 * @param label Short ASCII label, e.g. "quic key" (without the prefix), <= 249 bytes.
62 * @param out Output keying material.
63 * @param out_len Number of output bytes requested.
64 * @param label_prefix HkdfLabel prefix; defaults to the TLS 1.3 "tls13 " prefix. DTLS 1.3 passes "dtls13".
65 */
66void quic_hkdf_expand_label(const uint8_t secret[QUIC_HKDF_HASH_LEN], const char *label, uint8_t *out, size_t out_len,
67 const char *label_prefix = QUIC_HKDF_LABEL_PREFIX);
68
69/**
70 * @brief HKDF-Expand-Label with an explicit context (RFC 8446 sec 7.1, the general form).
71 *
72 * Identical to quic_hkdf_expand_label() but the HkdfLabel context is @p context (0..255 bytes)
73 * instead of empty. The TLS 1.3 key schedule's Derive-Secret (sec 7.1) is exactly this with the
74 * context set to a Transcript-Hash, so the whole handshake key schedule layers on this one routine.
75 *
76 * @param secret PRK, QUIC_HKDF_HASH_LEN bytes.
77 * @param label Short ASCII label without the "tls13 " prefix, <= 249 bytes.
78 * @param context Context bytes (may be NULL only when @p context_len is 0), <= 255 bytes.
79 * @param context_len Context length.
80 * @param out Output keying material.
81 * @param out_len Number of output bytes requested.
82 * @param label_prefix HkdfLabel prefix; defaults to the TLS 1.3 "tls13 " prefix. DTLS 1.3 passes "dtls13".
83 */
84void quic_hkdf_expand_label_ctx(const uint8_t secret[QUIC_HKDF_HASH_LEN], const char *label, const uint8_t *context,
85 size_t context_len, uint8_t *out, size_t out_len,
86 const char *label_prefix = QUIC_HKDF_LABEL_PREFIX);
87
88#endif // DETWS_ENABLE_HTTP3 || DETWS_ENABLE_DTLS
89#endif // DETERMINISTICESPASYNCWEBSERVER_QUIC_HKDF_H
User-facing configuration for DeterministicESPAsyncWebServer.