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 241 of file crypto.cpp.

243{
244 // Select salt based on version
245 std::span<const uint8_t> salt;
247 {
248 salt = initial_salt_v2;
249 }
250 else
251 {
252 salt = initial_salt_v1;
253 }
254
255 // Extract initial secret from destination connection ID
256 auto initial_secret_result = hkdf::extract(salt, dest_cid.data());
257 if (initial_secret_result.is_err())
258 {
259 return error<key_pair>(
260 initial_secret_result.error().code,
261 "Failed to derive initial secret",
262 "quic::initial_keys",
263 initial_secret_result.error().message);
264 }
265
266 auto& initial_secret = initial_secret_result.value();
267
268 // Derive client initial secret
269 auto client_secret_result = hkdf::expand_label(
270 initial_secret,
271 std::string(reinterpret_cast<const char*>(client_initial_label.data()),
272 client_initial_label.size()),
273 {},
275 if (client_secret_result.is_err())
276 {
277 return error<key_pair>(
278 client_secret_result.error().code,
279 "Failed to derive client initial secret",
280 "quic::initial_keys",
281 client_secret_result.error().message);
282 }
283
284 // Derive server initial secret
285 auto server_secret_result = hkdf::expand_label(
286 initial_secret,
287 std::string(reinterpret_cast<const char*>(server_initial_label.data()),
288 server_initial_label.size()),
289 {},
291 if (server_secret_result.is_err())
292 {
293 return error<key_pair>(
294 server_secret_result.error().code,
295 "Failed to derive server initial secret",
296 "quic::initial_keys",
297 server_secret_result.error().message);
298 }
299
300 // Derive client keys
301 auto client_keys_result = derive_keys(client_secret_result.value(), true);
302 if (client_keys_result.is_err())
303 {
304 return error<key_pair>(
305 client_keys_result.error().code,
306 "Failed to derive client keys",
307 "quic::initial_keys",
308 client_keys_result.error().message);
309 }
310
311 // Derive server keys
312 auto server_keys_result = derive_keys(server_secret_result.value(), false);
313 if (server_keys_result.is_err())
314 {
315 return error<key_pair>(
316 server_keys_result.error().code,
317 "Failed to derive server keys",
318 "quic::initial_keys",
319 server_keys_result.error().message);
320 }
321
322 // Copy secrets into keys
323 auto& client_keys = client_keys_result.value();
324 auto& server_keys = server_keys_result.value();
325
326 std::copy(client_secret_result.value().begin(),
327 client_secret_result.value().end(),
328 client_keys.secret.begin());
329 std::copy(server_secret_result.value().begin(),
330 server_secret_result.value().end(),
331 server_keys.secret.begin());
332
333 // For a client: write = client keys, read = server keys
334 // For a server: write = server keys, read = client keys
335 // This function returns from client's perspective
336 key_pair result;
337 result.write = std::move(client_keys);
338 result.read = std::move(server_keys);
339
340 return ok(std::move(result));
341}
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:197
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:343
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 343 of file crypto.cpp.

346{
347 (void)is_client_keys; // Not used but kept for API clarity
348
349 quic_keys keys;
350
351 // Derive AEAD key
352 auto key_result = hkdf::expand_label(
353 initial_secret,
354 std::string(reinterpret_cast<const char*>(quic_key_label.data()),
355 quic_key_label.size()),
356 {},
358 if (key_result.is_err())
359 {
360 return error<quic_keys>(
361 key_result.error().code,
362 "Failed to derive AEAD key",
363 "quic::initial_keys",
364 key_result.error().message);
365 }
366 std::copy(key_result.value().begin(), key_result.value().end(),
367 keys.key.begin());
368
369 // Derive IV
370 auto iv_result = hkdf::expand_label(
371 initial_secret,
372 std::string(reinterpret_cast<const char*>(quic_iv_label.data()),
373 quic_iv_label.size()),
374 {},
376 if (iv_result.is_err())
377 {
378 return error<quic_keys>(
379 iv_result.error().code,
380 "Failed to derive IV",
381 "quic::initial_keys",
382 iv_result.error().message);
383 }
384 std::copy(iv_result.value().begin(), iv_result.value().end(),
385 keys.iv.begin());
386
387 // Derive header protection key
388 auto hp_result = hkdf::expand_label(
389 initial_secret,
390 std::string(reinterpret_cast<const char*>(quic_hp_label.data()),
391 quic_hp_label.size()),
392 {},
394 if (hp_result.is_err())
395 {
396 return error<quic_keys>(
397 hp_result.error().code,
398 "Failed to derive HP key",
399 "quic::initial_keys",
400 hp_result.error().message);
401 }
402 std::copy(hp_result.value().begin(), hp_result.value().end(),
403 keys.hp_key.begin());
404
405 return ok(std::move(keys));
406}
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: