Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
kcenon::network::protocols::quic::hkdf Class Reference

HKDF (HMAC-based Key Derivation Function) utilities (RFC 5869) More...

#include <crypto.h>

Collaboration diagram for kcenon::network::protocols::quic::hkdf:
Collaboration graph

Static Public Member Functions

static auto extract (std::span< const uint8_t > salt, std::span< const uint8_t > ikm) -> Result< std::array< uint8_t, secret_size > >
 HKDF-Extract function.
 
static auto expand (std::span< const uint8_t > prk, std::span< const uint8_t > info, size_t length) -> Result< std::vector< uint8_t > >
 HKDF-Expand function.
 
static auto expand_label (std::span< const uint8_t > secret, const std::string &label, std::span< const uint8_t > context, size_t length) -> Result< std::vector< uint8_t > >
 HKDF-Expand-Label function (TLS 1.3 style)
 

Detailed Description

HKDF (HMAC-based Key Derivation Function) utilities (RFC 5869)

Used for deriving QUIC keys from secrets.

Definition at line 59 of file crypto.h.

Member Function Documentation

◆ expand()

auto kcenon::network::protocols::quic::hkdf::expand ( std::span< const uint8_t > prk,
std::span< const uint8_t > info,
size_t length ) -> Result<std::vector<uint8_t>>
staticnodiscard

HKDF-Expand function.

Parameters
prkPseudorandom key from Extract
infoContext and application specific information
lengthDesired output length
Returns
Output keying material (OKM) or error

Definition at line 124 of file crypto.cpp.

128{
129 std::vector<uint8_t> okm(length);
130
131 EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
132 if (!pctx)
133 {
135 -1, "Failed to create HKDF context", "quic::hkdf");
136 }
137
138 int ret = EVP_PKEY_derive_init(pctx);
139 if (ret <= 0)
140 {
141 EVP_PKEY_CTX_free(pctx);
143 -1, "HKDF derive init failed", "quic::hkdf", get_openssl_error_string());
144 }
145
146 ret = EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256());
147 if (ret <= 0)
148 {
149 EVP_PKEY_CTX_free(pctx);
151 -1, "HKDF set md failed", "quic::hkdf", get_openssl_error_string());
152 }
153
154 ret = EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
155 if (ret <= 0)
156 {
157 EVP_PKEY_CTX_free(pctx);
159 -1, "HKDF set mode failed", "quic::hkdf", get_openssl_error_string());
160 }
161
162 ret = EVP_PKEY_CTX_set1_hkdf_key(pctx, prk.data(),
163 static_cast<int>(prk.size()));
164 if (ret <= 0)
165 {
166 EVP_PKEY_CTX_free(pctx);
168 -1, "HKDF set key failed", "quic::hkdf", get_openssl_error_string());
169 }
170
171 ret = EVP_PKEY_CTX_add1_hkdf_info(pctx, info.data(),
172 static_cast<int>(info.size()));
173 if (ret <= 0)
174 {
175 EVP_PKEY_CTX_free(pctx);
177 -1, "HKDF set info failed", "quic::hkdf", get_openssl_error_string());
178 }
179
180 ret = EVP_PKEY_derive(pctx, okm.data(), &length);
181 EVP_PKEY_CTX_free(pctx);
182
183 if (ret <= 0)
184 {
186 -1, "HKDF expand failed", "quic::hkdf", get_openssl_error_string());
187 }
188
189 okm.resize(length);
190 return ok(std::move(okm));
191}
@ error
Black hole detected, reset to base.
VoidResult ok()

References kcenon::network::protocols::quic::error, and kcenon::network::ok().

Here is the call graph for this function:

◆ expand_label()

auto kcenon::network::protocols::quic::hkdf::expand_label ( std::span< const uint8_t > secret,
const std::string & label,
std::span< const uint8_t > context,
size_t length ) -> Result<std::vector<uint8_t>>
staticnodiscard

HKDF-Expand-Label function (TLS 1.3 style)

Parameters
secretSecret to expand
labelLabel string (without "tls13 " prefix)
contextContext data (usually empty for QUIC)
lengthDesired output length
Returns
Output keying material or error

Definition at line 193 of file crypto.cpp.

198{
199 // TLS 1.3 HKDF-Expand-Label structure:
200 // struct {
201 // uint16 length;
202 // opaque label<7..255> = "tls13 " + Label;
203 // opaque context<0..255>;
204 // } HkdfLabel;
205
206 const std::string prefix = "tls13 ";
207 std::vector<uint8_t> hkdf_label;
208 hkdf_label.reserve(2 + 1 + prefix.size() + label.size() + 1 + context.size());
209
210 // Length (2 bytes, big-endian)
211 hkdf_label.push_back(static_cast<uint8_t>((length >> 8) & 0xFF));
212 hkdf_label.push_back(static_cast<uint8_t>(length & 0xFF));
213
214 // Label length (1 byte) + "tls13 " + label
215 size_t label_len = prefix.size() + label.size();
216 hkdf_label.push_back(static_cast<uint8_t>(label_len));
217 for (char c : prefix)
218 {
219 hkdf_label.push_back(static_cast<uint8_t>(c));
220 }
221 for (char c : label)
222 {
223 hkdf_label.push_back(static_cast<uint8_t>(c));
224 }
225
226 // Context length (1 byte) + context
227 hkdf_label.push_back(static_cast<uint8_t>(context.size()));
228 hkdf_label.insert(hkdf_label.end(), context.begin(), context.end());
229
230 return expand(secret, hkdf_label, length);
231}
static auto expand(std::span< const uint8_t > prk, std::span< const uint8_t > info, size_t length) -> Result< std::vector< uint8_t > >
HKDF-Expand function.
Definition crypto.cpp:124

Referenced by kcenon::network::protocols::quic::initial_keys::derive(), kcenon::network::protocols::quic::initial_keys::derive_keys(), kcenon::network::protocols::quic::quic_crypto::derive_zero_rtt_keys(), and kcenon::network::protocols::quic::quic_crypto::update_keys().

Here is the caller graph for this function:

◆ extract()

auto kcenon::network::protocols::quic::hkdf::extract ( std::span< const uint8_t > salt,
std::span< const uint8_t > ikm ) -> Result<std::array<uint8_t, secret_size>>
staticnodiscard

HKDF-Extract function.

Parameters
saltSalt value (non-secret random value)
ikmInput keying material
Returns
Pseudorandom key (PRK) or error

Definition at line 56 of file crypto.cpp.

59{
60 std::array<uint8_t, secret_size> prk{};
61 size_t prk_len = prk.size();
62
63 EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
64 if (!pctx)
65 {
67 -1, "Failed to create HKDF context", "quic::hkdf");
68 }
69
70 int ret = EVP_PKEY_derive_init(pctx);
71 if (ret <= 0)
72 {
73 EVP_PKEY_CTX_free(pctx);
75 -1, "HKDF derive init failed", "quic::hkdf", get_openssl_error_string());
76 }
77
78 ret = EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256());
79 if (ret <= 0)
80 {
81 EVP_PKEY_CTX_free(pctx);
83 -1, "HKDF set md failed", "quic::hkdf", get_openssl_error_string());
84 }
85
86 ret = EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt.data(),
87 static_cast<int>(salt.size()));
88 if (ret <= 0)
89 {
90 EVP_PKEY_CTX_free(pctx);
92 -1, "HKDF set salt failed", "quic::hkdf", get_openssl_error_string());
93 }
94
95 ret = EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm.data(),
96 static_cast<int>(ikm.size()));
97 if (ret <= 0)
98 {
99 EVP_PKEY_CTX_free(pctx);
101 -1, "HKDF set key failed", "quic::hkdf", get_openssl_error_string());
102 }
103
104 ret = EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY);
105 if (ret <= 0)
106 {
107 EVP_PKEY_CTX_free(pctx);
109 -1, "HKDF set mode failed", "quic::hkdf", get_openssl_error_string());
110 }
111
112 ret = EVP_PKEY_derive(pctx, prk.data(), &prk_len);
113 EVP_PKEY_CTX_free(pctx);
114
115 if (ret <= 0)
116 {
118 -1, "HKDF extract failed", "quic::hkdf", get_openssl_error_string());
119 }
120
121 return ok(std::move(prk));
122}

References kcenon::network::protocols::quic::error, and kcenon::network::ok().

Referenced by kcenon::network::protocols::quic::initial_keys::derive(), and kcenon::network::protocols::quic::quic_crypto::derive_zero_rtt_keys().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: