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

Derives initial encryption keys from Destination Connection ID. More...

#include <crypto.h>

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

Static Public Member Functions

static auto derive (const connection_id &dest_cid, uint32_t version=0x00000001) -> Result< key_pair >
 Derive client and server initial keys.
 
static auto derive_keys (std::span< const uint8_t > initial_secret, bool is_client_keys) -> Result< quic_keys >
 Derive keys from an initial secret.
 

Detailed Description

Derives initial encryption keys from Destination Connection ID.

Initial keys are derived deterministically from the Destination Connection ID, allowing peers to decrypt Initial packets without a prior handshake.

Definition at line 110 of file crypto.h.

Member Function Documentation

◆ derive()

auto kcenon::network::protocols::quic::initial_keys::derive ( const connection_id & dest_cid,
uint32_t version = 0x00000001 ) -> Result<key_pair>
staticnodiscard

Derive client and server initial keys.

Parameters
dest_cidDestination Connection ID (from client's perspective)
versionQUIC version (affects salt selection)
Returns
Key pair for initial encryption level or error

Definition at line 237 of file crypto.cpp.

239{
240 // Select salt based on version
241 std::span<const uint8_t> salt;
243 {
244 salt = initial_salt_v2;
245 }
246 else
247 {
248 salt = initial_salt_v1;
249 }
250
251 // Extract initial secret from destination connection ID
252 auto initial_secret_result = hkdf::extract(salt, dest_cid.data());
253 if (initial_secret_result.is_err())
254 {
255 return error<key_pair>(
256 initial_secret_result.error().code,
257 "Failed to derive initial secret",
258 "quic::initial_keys",
259 initial_secret_result.error().message);
260 }
261
262 auto& initial_secret = initial_secret_result.value();
263
264 // Derive client initial secret
265 auto client_secret_result = hkdf::expand_label(
266 initial_secret,
267 std::string(reinterpret_cast<const char*>(client_initial_label.data()),
268 client_initial_label.size()),
269 {},
271 if (client_secret_result.is_err())
272 {
273 return error<key_pair>(
274 client_secret_result.error().code,
275 "Failed to derive client initial secret",
276 "quic::initial_keys",
277 client_secret_result.error().message);
278 }
279
280 // Derive server initial secret
281 auto server_secret_result = hkdf::expand_label(
282 initial_secret,
283 std::string(reinterpret_cast<const char*>(server_initial_label.data()),
284 server_initial_label.size()),
285 {},
287 if (server_secret_result.is_err())
288 {
289 return error<key_pair>(
290 server_secret_result.error().code,
291 "Failed to derive server initial secret",
292 "quic::initial_keys",
293 server_secret_result.error().message);
294 }
295
296 // Derive client keys
297 auto client_keys_result = derive_keys(client_secret_result.value(), true);
298 if (client_keys_result.is_err())
299 {
300 return error<key_pair>(
301 client_keys_result.error().code,
302 "Failed to derive client keys",
303 "quic::initial_keys",
304 client_keys_result.error().message);
305 }
306
307 // Derive server keys
308 auto server_keys_result = derive_keys(server_secret_result.value(), false);
309 if (server_keys_result.is_err())
310 {
311 return error<key_pair>(
312 server_keys_result.error().code,
313 "Failed to derive server keys",
314 "quic::initial_keys",
315 server_keys_result.error().message);
316 }
317
318 // Copy secrets into keys
319 auto& client_keys = client_keys_result.value();
320 auto& server_keys = server_keys_result.value();
321
322 std::copy(client_secret_result.value().begin(),
323 client_secret_result.value().end(),
324 client_keys.secret.begin());
325 std::copy(server_secret_result.value().begin(),
326 server_secret_result.value().end(),
327 server_keys.secret.begin());
328
329 // For a client: write = client keys, read = server keys
330 // For a server: write = server keys, read = client keys
331 // This function returns from client's perspective
332 key_pair result;
333 result.write = std::move(client_keys);
334 result.read = std::move(server_keys);
335
336 return ok(std::move(result));
337}
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)
Definition crypto.cpp:193
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.
Definition crypto.cpp:56
static auto derive_keys(std::span< const uint8_t > initial_secret, bool is_client_keys) -> Result< quic_keys >
Derive keys from an initial secret.
Definition crypto.cpp:339
constexpr uint32_t version_2
QUIC version 2 (RFC 9369)
Definition packet.h:32
@ error
Black hole detected, reset to base.
constexpr std::array< uint8_t, 20 > initial_salt_v1
QUIC version 1 initial salt (RFC 9001 Section 5.2)
Definition crypto.h:36
constexpr std::array< uint8_t, 20 > initial_salt_v2
QUIC version 2 initial salt (RFC 9369)
Definition crypto.h:44
constexpr size_t secret_size
Traffic secret size (SHA-256 output)
Definition keys.h:31
constexpr const char * version() noexcept
Get the network system version string.
Definition network.cppm:111
VoidResult ok()

References kcenon::network::protocols::quic::error, kcenon::network::protocols::quic::hkdf::expand_label(), kcenon::network::protocols::quic::hkdf::extract(), kcenon::network::protocols::quic::initial_salt_v1, kcenon::network::protocols::quic::initial_salt_v2, kcenon::network::ok(), kcenon::network::protocols::quic::key_pair::read, kcenon::network::protocols::quic::secret_size, kcenon::network::version(), kcenon::network::protocols::quic::quic_version::version_2, and kcenon::network::protocols::quic::key_pair::write.

Referenced by kcenon::network::protocols::quic::quic_crypto::derive_initial_secrets().

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

◆ derive_keys()

auto kcenon::network::protocols::quic::initial_keys::derive_keys ( std::span< const uint8_t > initial_secret,
bool is_client_keys ) -> Result<quic_keys>
staticnodiscard

Derive keys from an initial secret.

Parameters
initial_secretThe initial secret
is_client_keystrue for client keys, false for server keys
Returns
QUIC keys or error

Definition at line 339 of file crypto.cpp.

342{
343 (void)is_client_keys; // Not used but kept for API clarity
344
345 quic_keys keys;
346
347 // Derive AEAD key
348 auto key_result = hkdf::expand_label(
349 initial_secret,
350 std::string(reinterpret_cast<const char*>(quic_key_label.data()),
351 quic_key_label.size()),
352 {},
354 if (key_result.is_err())
355 {
356 return error<quic_keys>(
357 key_result.error().code,
358 "Failed to derive AEAD key",
359 "quic::initial_keys",
360 key_result.error().message);
361 }
362 std::copy(key_result.value().begin(), key_result.value().end(),
363 keys.key.begin());
364
365 // Derive IV
366 auto iv_result = hkdf::expand_label(
367 initial_secret,
368 std::string(reinterpret_cast<const char*>(quic_iv_label.data()),
369 quic_iv_label.size()),
370 {},
372 if (iv_result.is_err())
373 {
374 return error<quic_keys>(
375 iv_result.error().code,
376 "Failed to derive IV",
377 "quic::initial_keys",
378 iv_result.error().message);
379 }
380 std::copy(iv_result.value().begin(), iv_result.value().end(),
381 keys.iv.begin());
382
383 // Derive header protection key
384 auto hp_result = hkdf::expand_label(
385 initial_secret,
386 std::string(reinterpret_cast<const char*>(quic_hp_label.data()),
387 quic_hp_label.size()),
388 {},
390 if (hp_result.is_err())
391 {
392 return error<quic_keys>(
393 hp_result.error().code,
394 "Failed to derive HP key",
395 "quic::initial_keys",
396 hp_result.error().message);
397 }
398 std::copy(hp_result.value().begin(), hp_result.value().end(),
399 keys.hp_key.begin());
400
401 return ok(std::move(keys));
402}
constexpr size_t aes_128_key_size
AES-128-GCM key size in bytes.
Definition keys.h:19
constexpr size_t aead_iv_size
AEAD IV/nonce size in bytes.
Definition keys.h:25
constexpr size_t hp_key_size
Header protection key size for AES-128.
Definition keys.h:34

References kcenon::network::protocols::quic::aead_iv_size, kcenon::network::protocols::quic::aes_128_key_size, kcenon::network::protocols::quic::error, kcenon::network::protocols::quic::hkdf::expand_label(), kcenon::network::protocols::quic::quic_keys::hp_key, kcenon::network::protocols::quic::hp_key_size, kcenon::network::protocols::quic::quic_keys::iv, kcenon::network::protocols::quic::quic_keys::key, and kcenon::network::ok().

Referenced by kcenon::network::protocols::quic::quic_crypto::derive_zero_rtt_keys(), and kcenon::network::protocols::quic::quic_crypto::update_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: