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

QUIC-TLS integration handler (RFC 9001) More...

#include <crypto.h>

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

Classes

struct  impl
 

Public Types

using session_ticket_callback_t
 Callback type for receiving session tickets.
 

Public Member Functions

 quic_crypto ()
 Default constructor.
 
 ~quic_crypto ()
 Destructor (cleans up OpenSSL resources)
 
 quic_crypto (const quic_crypto &)=delete
 
quic_cryptooperator= (const quic_crypto &)=delete
 
 quic_crypto (quic_crypto &&other) noexcept
 
quic_cryptooperator= (quic_crypto &&other) noexcept
 
auto init_client (const std::string &server_name) -> VoidResult
 Initialize as client.
 
auto init_server (const std::string &cert_file, const std::string &key_file) -> VoidResult
 Initialize as server.
 
auto derive_initial_secrets (const connection_id &dest_cid) -> VoidResult
 Derive initial secrets from destination connection ID.
 
auto process_crypto_data (encryption_level level, std::span< const uint8_t > data) -> Result< std::vector< uint8_t > >
 Process incoming CRYPTO frame data.
 
auto start_handshake () -> Result< std::vector< uint8_t > >
 Start the handshake (generate initial CRYPTO data)
 
auto is_handshake_complete () const noexcept -> bool
 Check if the handshake is complete.
 
auto current_level () const noexcept -> encryption_level
 Get current encryption level.
 
auto get_write_keys (encryption_level level) const -> Result< quic_keys >
 Get write keys for an encryption level.
 
auto get_read_keys (encryption_level level) const -> Result< quic_keys >
 Get read keys for an encryption level.
 
void set_keys (encryption_level level, const quic_keys &read_keys, const quic_keys &write_keys)
 Set keys for an encryption level (used during handshake)
 
auto update_keys () -> VoidResult
 Perform a key update (1-RTT only)
 
auto get_alpn () const -> std::string
 Get the negotiated ALPN protocol.
 
auto set_alpn (const std::vector< std::string > &protocols) -> VoidResult
 Set ALPN protocols to offer/accept.
 
auto is_server () const noexcept -> bool
 Check if this is a server instance.
 
auto key_phase () const noexcept -> uint8_t
 Get current key phase (for key updates)
 
void set_session_ticket_callback (session_ticket_callback_t cb)
 Set callback for receiving session tickets.
 
auto set_session_ticket (std::span< const uint8_t > ticket_data) -> VoidResult
 Set a session ticket for 0-RTT resumption.
 
auto enable_early_data (uint32_t max_early_data) -> VoidResult
 Enable 0-RTT early data.
 
auto is_early_data_accepted () const noexcept -> bool
 Check if 0-RTT early data was accepted by the server.
 
auto derive_zero_rtt_keys () -> VoidResult
 Derive 0-RTT keys from session ticket.
 
auto has_zero_rtt_keys () const noexcept -> bool
 Check if 0-RTT keys are available.
 

Private Attributes

std::unique_ptr< implimpl_
 

Detailed Description

QUIC-TLS integration handler (RFC 9001)

Manages the TLS 1.3 handshake for QUIC, handling:

  • Key derivation for each encryption level
  • CRYPTO frame data processing
  • Key updates after handshake

This class wraps OpenSSL for cryptographic operations.

Definition at line 244 of file crypto.h.

Member Typedef Documentation

◆ session_ticket_callback_t

Initial value:
std::function<void(
std::vector<uint8_t> ticket_data,
uint32_t lifetime_hint,
uint32_t ticket_age_add,
uint32_t max_early_data)>

Callback type for receiving session tickets.

This callback is invoked when a NewSessionTicket message is received from the server after handshake completion.

Parameters
ticket_dataRaw session ticket data
lifetime_hintTicket lifetime in seconds
ticket_age_addObfuscation value for ticket age
max_early_dataMaximum early data size (0 if early data not allowed)

Definition at line 390 of file crypto.h.

Constructor & Destructor Documentation

◆ quic_crypto() [1/3]

kcenon::network::protocols::quic::quic_crypto::quic_crypto ( )

Default constructor.

Definition at line 772 of file crypto.cpp.

773 : impl_(std::make_unique<impl>())
774{
775}

◆ ~quic_crypto()

kcenon::network::protocols::quic::quic_crypto::~quic_crypto ( )
default

Destructor (cleans up OpenSSL resources)

◆ quic_crypto() [2/3]

kcenon::network::protocols::quic::quic_crypto::quic_crypto ( const quic_crypto & )
delete

◆ quic_crypto() [3/3]

kcenon::network::protocols::quic::quic_crypto::quic_crypto ( quic_crypto && other)
defaultnoexcept

Member Function Documentation

◆ current_level()

auto kcenon::network::protocols::quic::quic_crypto::current_level ( ) const -> encryption_level
nodiscardnoexcept

Get current encryption level.

Returns
Current encryption level

Definition at line 1008 of file crypto.cpp.

1009{
1010 return impl_->current_level;
1011}

References kcenon::network::protocols::quic::quic_crypto::impl::current_level, and impl_.

◆ derive_initial_secrets()

auto kcenon::network::protocols::quic::quic_crypto::derive_initial_secrets ( const connection_id & dest_cid) -> VoidResult
nodiscard

Derive initial secrets from destination connection ID.

Parameters
dest_cidDestination Connection ID
Returns
Success or error

Definition at line 883 of file crypto.cpp.

885{
886 auto keys_result = initial_keys::derive(dest_cid);
887 if (keys_result.is_err())
888 {
889 return error_void(keys_result.error().code,
890 keys_result.error().message,
891 get_error_source(keys_result.error()));
892 }
893
894 auto& keys = keys_result.value();
895
896 if (impl_->is_server)
897 {
898 // Server: read with client keys, write with server keys
899 impl_->read_keys[encryption_level::initial] = keys.write; // Client's write = Server's read
900 impl_->write_keys[encryption_level::initial] = keys.read; // Server's write = Client's read
901 }
902 else
903 {
904 // Client: write with client keys, read with server keys
907 }
908
909 return ok();
910}
static auto derive(const connection_id &dest_cid, uint32_t version=0x00000001) -> Result< key_pair >
Derive client and server initial keys.
Definition crypto.cpp:237
@ initial
Initial encryption (derived from DCID)
const std::string & get_error_source(const simple_error &err)
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
VoidResult ok()
std::map< encryption_level, quic_keys > write_keys
Definition crypto.cpp:745
std::map< encryption_level, quic_keys > read_keys
Definition crypto.cpp:744

References kcenon::network::protocols::quic::initial_keys::derive(), kcenon::network::error_void(), kcenon::network::get_error_source(), kcenon::network::protocols::quic::initial, and kcenon::network::ok().

Here is the call graph for this function:

◆ derive_zero_rtt_keys()

auto kcenon::network::protocols::quic::quic_crypto::derive_zero_rtt_keys ( ) -> VoidResult
nodiscard

Derive 0-RTT keys from session ticket.

Returns
Success or error

Called internally when a valid session ticket is set.

Definition at line 1182 of file crypto.cpp.

1183{
1184 if (impl_->session_ticket_data.empty())
1185 {
1186 return error_void(-1, "No session ticket available", "quic::crypto");
1187 }
1188
1189 // Derive 0-RTT secret from the resumption secret in the ticket
1190 // The early data secret is derived using HKDF-Expand-Label with
1191 // the label "c e traffic" and the ClientHello transcript
1192 //
1193 // For simplicity in this implementation, we derive keys using a
1194 // deterministic derivation from the session ticket. A full implementation
1195 // would properly extract the resumption master secret from TLS.
1196
1197 // Use HKDF to derive a pseudo early secret from the ticket data
1198 // This is a simplified approach - full implementation needs proper TLS PSK handling
1199 auto early_secret_result = hkdf::extract(
1200 initial_salt_v1, // Use QUIC v1 salt as base
1202
1203 if (early_secret_result.is_err())
1204 {
1205 return error_void(early_secret_result.error().code,
1206 "Failed to derive early secret",
1207 "quic::crypto",
1208 early_secret_result.error().message);
1209 }
1210
1211 auto& early_secret = early_secret_result.value();
1212
1213 // Derive client early traffic secret
1214 auto client_early_secret_result = hkdf::expand_label(
1215 early_secret,
1216 "c e traffic",
1217 {},
1218 secret_size);
1219
1220 if (client_early_secret_result.is_err())
1221 {
1222 return error_void(client_early_secret_result.error().code,
1223 "Failed to derive client early secret",
1224 "quic::crypto",
1225 client_early_secret_result.error().message);
1226 }
1227
1228 // Derive 0-RTT keys from client early secret
1229 auto zero_rtt_keys_result = initial_keys::derive_keys(
1230 client_early_secret_result.value(),
1231 true);
1232
1233 if (zero_rtt_keys_result.is_err())
1234 {
1235 return error_void(zero_rtt_keys_result.error().code,
1236 "Failed to derive 0-RTT keys",
1237 "quic::crypto",
1238 zero_rtt_keys_result.error().message);
1239 }
1240
1241 auto& zero_rtt_keys = zero_rtt_keys_result.value();
1242
1243 // Copy the secret
1244 std::copy(client_early_secret_result.value().begin(),
1245 client_early_secret_result.value().end(),
1246 zero_rtt_keys.secret.begin());
1247
1248 // Store the 0-RTT keys
1249 // For client: 0-RTT is write-only (can't receive 0-RTT data)
1250 // For server: 0-RTT is read-only (can receive but not send 0-RTT)
1251 if (impl_->is_server)
1252 {
1253 impl_->read_keys[encryption_level::zero_rtt] = zero_rtt_keys;
1254 }
1255 else
1256 {
1258 }
1259
1260 impl_->has_zero_rtt_keys = true;
1261
1262 return ok();
1263}
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 std::array< uint8_t, 20 > initial_salt_v1
QUIC version 1 initial salt (RFC 9001 Section 5.2)
Definition crypto.h:36
constexpr size_t secret_size
Traffic secret size (SHA-256 output)
Definition keys.h:31

References kcenon::network::protocols::quic::initial_keys::derive_keys(), kcenon::network::error_void(), kcenon::network::protocols::quic::hkdf::expand_label(), kcenon::network::protocols::quic::hkdf::extract(), kcenon::network::protocols::quic::initial_salt_v1, kcenon::network::ok(), kcenon::network::protocols::quic::secret_size, and kcenon::network::protocols::quic::zero_rtt.

Here is the call graph for this function:

◆ enable_early_data()

auto kcenon::network::protocols::quic::quic_crypto::enable_early_data ( uint32_t max_early_data) -> VoidResult
nodiscard

Enable 0-RTT early data.

Parameters
max_early_dataMaximum bytes of early data to send
Returns
Success or error

Must be called after set_session_ticket() and before init_client().

Definition at line 1163 of file crypto.cpp.

1164{
1165 if (impl_->session_ticket_data.empty())
1166 {
1167 return error_void(-1, "Session ticket must be set before enabling early data",
1168 "quic::crypto");
1169 }
1170
1171 impl_->max_early_data_size = max_early_data;
1172 impl_->early_data_enabled = true;
1173
1174 return ok();
1175}

References kcenon::network::error_void(), and kcenon::network::ok().

Here is the call graph for this function:

◆ get_alpn()

auto kcenon::network::protocols::quic::quic_crypto::get_alpn ( ) const -> std::string
nodiscard

Get the negotiated ALPN protocol.

Returns
ALPN protocol string or empty if not negotiated

Definition at line 1097 of file crypto.cpp.

1098{
1099 return impl_->alpn;
1100}

References kcenon::network::protocols::quic::quic_crypto::impl::alpn, and impl_.

◆ get_read_keys()

auto kcenon::network::protocols::quic::quic_crypto::get_read_keys ( encryption_level level) const -> Result<quic_keys>
nodiscard

Get read keys for an encryption level.

Parameters
levelDesired encryption level
Returns
Keys or error if not available

Definition at line 1026 of file crypto.cpp.

1028{
1029 auto it = impl_->read_keys.find(level);
1030 if (it == impl_->read_keys.end())
1031 {
1032 return error<quic_keys>(
1033 -1, "Read keys not available for level", "quic::crypto",
1035 }
1036 return ok(quic_keys(it->second));
1037}
@ error
Black hole detected, reset to base.
auto encryption_level_to_string(encryption_level level) -> std::string
Convert encryption level to string for debugging.
Definition keys.cpp:13

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

Here is the call graph for this function:

◆ get_write_keys()

auto kcenon::network::protocols::quic::quic_crypto::get_write_keys ( encryption_level level) const -> Result<quic_keys>
nodiscard

Get write keys for an encryption level.

Parameters
levelDesired encryption level
Returns
Keys or error if not available

Definition at line 1013 of file crypto.cpp.

1015{
1016 auto it = impl_->write_keys.find(level);
1017 if (it == impl_->write_keys.end())
1018 {
1019 return error<quic_keys>(
1020 -1, "Write keys not available for level", "quic::crypto",
1022 }
1023 return ok(quic_keys(it->second));
1024}

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

Referenced by kcenon::network::protocols::quic::connection::generate_probe_packets().

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

◆ has_zero_rtt_keys()

auto kcenon::network::protocols::quic::quic_crypto::has_zero_rtt_keys ( ) const -> bool
nodiscardnoexcept

Check if 0-RTT keys are available.

Returns
true if 0-RTT keys have been derived

Definition at line 1265 of file crypto.cpp.

1266{
1267 return impl_->has_zero_rtt_keys;
1268}

References kcenon::network::protocols::quic::quic_crypto::impl::has_zero_rtt_keys, and impl_.

◆ init_client()

auto kcenon::network::protocols::quic::quic_crypto::init_client ( const std::string & server_name) -> VoidResult
nodiscard

Initialize as client.

Parameters
server_nameServer hostname (for SNI)
Returns
Success or error

Definition at line 782 of file crypto.cpp.

783{
784 impl_->is_server = false;
785
786 impl_->ssl_ctx = SSL_CTX_new(TLS_client_method());
787 if (!impl_->ssl_ctx)
788 {
789 return error_void(-1, "Failed to create SSL context", "quic::crypto",
790 get_openssl_error_string());
791 }
792
793 // Set TLS 1.3 only
794 SSL_CTX_set_min_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
795 SSL_CTX_set_max_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
796
797 impl_->ssl = SSL_new(impl_->ssl_ctx);
798 if (!impl_->ssl)
799 {
800 return error_void(-1, "Failed to create SSL object", "quic::crypto",
801 get_openssl_error_string());
802 }
803
804 // Set SNI
805 if (!server_name.empty())
806 {
807 SSL_set_tlsext_host_name(impl_->ssl, server_name.c_str());
808 }
809
810 // Create memory BIOs
811 impl_->rbio = BIO_new(BIO_s_mem());
812 impl_->wbio = BIO_new(BIO_s_mem());
813 if (!impl_->rbio || !impl_->wbio)
814 {
815 return error_void(-1, "Failed to create BIO objects", "quic::crypto");
816 }
817
818 BIO_set_nbio(impl_->rbio, 1);
819 BIO_set_nbio(impl_->wbio, 1);
820
821 SSL_set_bio(impl_->ssl, impl_->rbio, impl_->wbio);
822 SSL_set_connect_state(impl_->ssl);
823
824 return ok();
825}

References kcenon::network::error_void(), and kcenon::network::ok().

Here is the call graph for this function:

◆ init_server()

auto kcenon::network::protocols::quic::quic_crypto::init_server ( const std::string & cert_file,
const std::string & key_file ) -> VoidResult
nodiscard

Initialize as server.

Parameters
cert_filePath to certificate file (PEM format)
key_filePath to private key file (PEM format)
Returns
Success or error

Definition at line 827 of file crypto.cpp.

829{
830 impl_->is_server = true;
831
832 impl_->ssl_ctx = SSL_CTX_new(TLS_server_method());
833 if (!impl_->ssl_ctx)
834 {
835 return error_void(-1, "Failed to create SSL context", "quic::crypto",
836 get_openssl_error_string());
837 }
838
839 // Set TLS 1.3 only
840 SSL_CTX_set_min_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
841 SSL_CTX_set_max_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
842
843 // Load certificate
844 if (SSL_CTX_use_certificate_file(impl_->ssl_ctx, cert_file.c_str(),
845 SSL_FILETYPE_PEM) != 1)
846 {
847 return error_void(-1, "Failed to load certificate", "quic::crypto",
848 get_openssl_error_string());
849 }
850
851 // Load private key
852 if (SSL_CTX_use_PrivateKey_file(impl_->ssl_ctx, key_file.c_str(),
853 SSL_FILETYPE_PEM) != 1)
854 {
855 return error_void(-1, "Failed to load private key", "quic::crypto",
856 get_openssl_error_string());
857 }
858
859 impl_->ssl = SSL_new(impl_->ssl_ctx);
860 if (!impl_->ssl)
861 {
862 return error_void(-1, "Failed to create SSL object", "quic::crypto",
863 get_openssl_error_string());
864 }
865
866 // Create memory BIOs
867 impl_->rbio = BIO_new(BIO_s_mem());
868 impl_->wbio = BIO_new(BIO_s_mem());
869 if (!impl_->rbio || !impl_->wbio)
870 {
871 return error_void(-1, "Failed to create BIO objects", "quic::crypto");
872 }
873
874 BIO_set_nbio(impl_->rbio, 1);
875 BIO_set_nbio(impl_->wbio, 1);
876
877 SSL_set_bio(impl_->ssl, impl_->rbio, impl_->wbio);
878 SSL_set_accept_state(impl_->ssl);
879
880 return ok();
881}

References kcenon::network::error_void(), and kcenon::network::ok().

Here is the call graph for this function:

◆ is_early_data_accepted()

auto kcenon::network::protocols::quic::quic_crypto::is_early_data_accepted ( ) const -> bool
nodiscardnoexcept

Check if 0-RTT early data was accepted by the server.

Returns
true if server accepted early data, false otherwise

This value is only meaningful after handshake completion.

Definition at line 1177 of file crypto.cpp.

References kcenon::network::protocols::quic::quic_crypto::impl::early_data_accepted, and impl_.

◆ is_handshake_complete()

auto kcenon::network::protocols::quic::quic_crypto::is_handshake_complete ( ) const -> bool
nodiscardnoexcept

Check if the handshake is complete.

Returns
true if handshake has finished successfully

Definition at line 1003 of file crypto.cpp.

References kcenon::network::protocols::quic::quic_crypto::impl::handshake_complete, and impl_.

Referenced by kcenon::network::protocols::quic::connection::update_state().

Here is the caller graph for this function:

◆ is_server()

auto kcenon::network::protocols::quic::quic_crypto::is_server ( ) const -> bool
nodiscardnoexcept

Check if this is a server instance.

Returns
true if server, false if client

Definition at line 1132 of file crypto.cpp.

1133{
1134 return impl_->is_server;
1135}

References impl_, and kcenon::network::protocols::quic::quic_crypto::impl::is_server.

◆ key_phase()

auto kcenon::network::protocols::quic::quic_crypto::key_phase ( ) const -> uint8_t
nodiscardnoexcept

Get current key phase (for key updates)

Returns
Current key phase (0 or 1)

Definition at line 1137 of file crypto.cpp.

References impl_, and kcenon::network::protocols::quic::quic_crypto::impl::key_phase.

◆ operator=() [1/2]

quic_crypto & kcenon::network::protocols::quic::quic_crypto::operator= ( const quic_crypto & )
delete

◆ operator=() [2/2]

quic_crypto & kcenon::network::protocols::quic::quic_crypto::operator= ( quic_crypto && other)
defaultnoexcept

◆ process_crypto_data()

auto kcenon::network::protocols::quic::quic_crypto::process_crypto_data ( encryption_level level,
std::span< const uint8_t > data ) -> Result<std::vector<uint8_t>>
nodiscard

Process incoming CRYPTO frame data.

Parameters
levelEncryption level of the data
dataCRYPTO frame payload
Returns
Outgoing CRYPTO data to send (may be empty) or error

Definition at line 912 of file crypto.cpp.

915{
916 (void)level; // For now, we don't differentiate by level
917
918 // Write incoming data to read BIO
919 int written = BIO_write(impl_->rbio, data.data(),
920 static_cast<int>(data.size()));
921 if (written <= 0)
922 {
924 -1, "Failed to write to BIO", "quic::crypto");
925 }
926
927 // Continue handshake
928 int result = SSL_do_handshake(impl_->ssl);
929 if (result == 1)
930 {
933 }
934 else
935 {
936 int err = SSL_get_error(impl_->ssl, result);
937 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
938 {
940 -1, "SSL handshake failed", "quic::crypto",
941 get_openssl_error_string());
942 }
943 }
944
945 // Read any output data from write BIO
946 std::vector<uint8_t> output;
947 int pending = BIO_ctrl_pending(impl_->wbio);
948 if (pending > 0)
949 {
950 output.resize(static_cast<size_t>(pending));
951 int read = BIO_read(impl_->wbio, output.data(), pending);
952 if (read > 0)
953 {
954 output.resize(static_cast<size_t>(read));
955 }
956 else
957 {
958 output.clear();
959 }
960 }
961
962 return ok(std::move(output));
963}
@ application
1-RTT application data encryption

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

Here is the call graph for this function:

◆ set_alpn()

auto kcenon::network::protocols::quic::quic_crypto::set_alpn ( const std::vector< std::string > & protocols) -> VoidResult
nodiscard

Set ALPN protocols to offer/accept.

Parameters
protocolsList of protocol names (e.g., {"h3", "hq-interop"})
Returns
Success or error

Definition at line 1102 of file crypto.cpp.

1104{
1105 if (protocols.empty())
1106 {
1107 return ok();
1108 }
1109
1110 // Build ALPN wire format: length-prefixed strings
1111 impl_->alpn_data.clear();
1112 for (const auto& proto : protocols)
1113 {
1114 if (proto.size() > 255)
1115 {
1116 return error_void(-1, "ALPN protocol too long", "quic::crypto");
1117 }
1118 impl_->alpn_data.push_back(static_cast<uint8_t>(proto.size()));
1119 impl_->alpn_data.insert(impl_->alpn_data.end(), proto.begin(), proto.end());
1120 }
1121
1122 if (SSL_CTX_set_alpn_protos(impl_->ssl_ctx, impl_->alpn_data.data(),
1123 static_cast<unsigned int>(impl_->alpn_data.size())) != 0)
1124 {
1125 return error_void(-1, "Failed to set ALPN protocols", "quic::crypto",
1126 get_openssl_error_string());
1127 }
1128
1129 return ok();
1130}

References kcenon::network::error_void(), and kcenon::network::ok().

Here is the call graph for this function:

◆ set_keys()

void kcenon::network::protocols::quic::quic_crypto::set_keys ( encryption_level level,
const quic_keys & read_keys,
const quic_keys & write_keys )

Set keys for an encryption level (used during handshake)

Parameters
levelEncryption level
read_keysKeys for decryption
write_keysKeys for encryption

Definition at line 1039 of file crypto.cpp.

1042{
1043 impl_->read_keys[level] = read_keys;
1044 impl_->write_keys[level] = write_keys;
1045
1046 if (level > impl_->current_level)
1047 {
1048 impl_->current_level = level;
1049 }
1050}

References kcenon::network::protocols::quic::quic_crypto::impl::current_level, impl_, kcenon::network::protocols::quic::quic_crypto::impl::read_keys, and kcenon::network::protocols::quic::quic_crypto::impl::write_keys.

◆ set_session_ticket()

auto kcenon::network::protocols::quic::quic_crypto::set_session_ticket ( std::span< const uint8_t > ticket_data) -> VoidResult
nodiscard

Set a session ticket for 0-RTT resumption.

Parameters
ticket_dataSession ticket from previous connection
Returns
Success or error

Must be called before init_client() for the ticket to be used.

Definition at line 1151 of file crypto.cpp.

1153{
1154 if (ticket_data.empty())
1155 {
1156 return error_void(-1, "Empty session ticket", "quic::crypto");
1157 }
1158
1159 impl_->session_ticket_data.assign(ticket_data.begin(), ticket_data.end());
1160 return ok();
1161}

References kcenon::network::error_void(), and kcenon::network::ok().

Here is the call graph for this function:

◆ set_session_ticket_callback()

void kcenon::network::protocols::quic::quic_crypto::set_session_ticket_callback ( session_ticket_callback_t cb)

Set callback for receiving session tickets.

Parameters
cbCallback function

The callback will be invoked on the I/O thread when a NewSessionTicket message is received from the server.

Definition at line 1146 of file crypto.cpp.

1147{
1148 impl_->session_ticket_callback = std::move(cb);
1149}
session_ticket_callback_t session_ticket_callback
Definition crypto.cpp:751

References impl_, and kcenon::network::protocols::quic::quic_crypto::impl::session_ticket_callback.

◆ start_handshake()

auto kcenon::network::protocols::quic::quic_crypto::start_handshake ( ) -> Result<std::vector<uint8_t>>
nodiscard

Start the handshake (generate initial CRYPTO data)

Returns
Initial CRYPTO data to send or error

Definition at line 965 of file crypto.cpp.

966{
967 int result = SSL_do_handshake(impl_->ssl);
968 if (result == 1)
969 {
971 }
972 else
973 {
974 int err = SSL_get_error(impl_->ssl, result);
975 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
976 {
978 -1, "SSL handshake start failed", "quic::crypto",
979 get_openssl_error_string());
980 }
981 }
982
983 // Read output from write BIO
984 std::vector<uint8_t> output;
985 int pending = BIO_ctrl_pending(impl_->wbio);
986 if (pending > 0)
987 {
988 output.resize(static_cast<size_t>(pending));
989 int read = BIO_read(impl_->wbio, output.data(), pending);
990 if (read > 0)
991 {
992 output.resize(static_cast<size_t>(read));
993 }
994 else
995 {
996 output.clear();
997 }
998 }
999
1000 return ok(std::move(output));
1001}

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

Here is the call graph for this function:

◆ update_keys()

auto kcenon::network::protocols::quic::quic_crypto::update_keys ( ) -> VoidResult
nodiscard

Perform a key update (1-RTT only)

Returns
Success or error

Definition at line 1052 of file crypto.cpp.

1053{
1055 {
1056 return error_void(-1, "Handshake not complete", "quic::crypto");
1057 }
1058
1060 if (it == impl_->write_keys.end())
1061 {
1062 return error_void(-1, "Application keys not available", "quic::crypto");
1063 }
1064
1065 // Derive new secrets using "quic ku" label
1066 auto& old_secret = it->second.secret;
1067 auto new_secret_result = hkdf::expand_label(old_secret, "quic ku", {},
1068 secret_size);
1069 if (new_secret_result.is_err())
1070 {
1071 return error_void(new_secret_result.error().code,
1072 new_secret_result.error().message,
1073 get_error_source(new_secret_result.error()));
1074 }
1075
1076 // Derive new keys from new secret
1077 auto new_keys_result = initial_keys::derive_keys(new_secret_result.value(),
1078 true);
1079 if (new_keys_result.is_err())
1080 {
1081 return error_void(new_keys_result.error().code,
1082 new_keys_result.error().message,
1083 get_error_source(new_keys_result.error()));
1084 }
1085
1086 auto& new_keys = new_keys_result.value();
1087 std::copy(new_secret_result.value().begin(),
1088 new_secret_result.value().end(),
1089 new_keys.secret.begin());
1090
1093
1094 return ok();
1095}

References kcenon::network::protocols::quic::application, kcenon::network::protocols::quic::initial_keys::derive_keys(), kcenon::network::error_void(), kcenon::network::protocols::quic::hkdf::expand_label(), kcenon::network::get_error_source(), kcenon::network::ok(), and kcenon::network::protocols::quic::secret_size.

Here is the call graph for this function:

Member Data Documentation

◆ impl_

std::unique_ptr<impl> kcenon::network::protocols::quic::quic_crypto::impl_
private

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