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_crypto & operator= (const quic_crypto &)=delete
 
 quic_crypto (quic_crypto &&other) noexcept
 
quic_crypto & operator= (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< impl > impl_
 

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

783 : impl_(std::make_unique<impl>())
784{
785}

◆ ~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 1030 of file crypto.cpp.

1031{
1032 return impl_->current_level;
1033}

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

907{
908 auto keys_result = initial_keys::derive(dest_cid);
909 if (keys_result.is_err())
910 {
911 return error_void(keys_result.error().code,
912 keys_result.error().message,
913 get_error_source(keys_result.error()));
914 }
915
916 auto& keys = keys_result.value();
917
918 if (impl_->is_server)
919 {
920 // Server: read with client keys, write with server keys
921 impl_->read_keys[encryption_level::initial] = keys.write; // Client's write = Server's read
922 impl_->write_keys[encryption_level::initial] = keys.read; // Server's write = Client's read
923 }
924 else
925 {
926 // Client: write with client keys, read with server keys
929 }
930
931 return ok();
932}
static auto derive(const connection_id &dest_cid, uint32_t version=0x00000001) -> Result< key_pair >
Derive client and server initial keys.
Definition crypto.cpp:241
@ 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:749
std::map< encryption_level, quic_keys > read_keys
Definition crypto.cpp:748

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

1205{
1206 if (impl_->session_ticket_data.empty())
1207 {
1208 return error_void(-1, "No session ticket available", "quic::crypto");
1209 }
1210
1211 // Derive 0-RTT secret from the resumption secret in the ticket
1212 // The early data secret is derived using HKDF-Expand-Label with
1213 // the label "c e traffic" and the ClientHello transcript
1214 //
1215 // For simplicity in this implementation, we derive keys using a
1216 // deterministic derivation from the session ticket. A full implementation
1217 // would properly extract the resumption master secret from TLS.
1218
1219 // Use HKDF to derive a pseudo early secret from the ticket data
1220 // This is a simplified approach - full implementation needs proper TLS PSK handling
1221 auto early_secret_result = hkdf::extract(
1222 initial_salt_v1, // Use QUIC v1 salt as base
1224
1225 if (early_secret_result.is_err())
1226 {
1227 return error_void(early_secret_result.error().code,
1228 "Failed to derive early secret",
1229 "quic::crypto",
1230 early_secret_result.error().message);
1231 }
1232
1233 auto& early_secret = early_secret_result.value();
1234
1235 // Derive client early traffic secret
1236 auto client_early_secret_result = hkdf::expand_label(
1237 early_secret,
1238 "c e traffic",
1239 {},
1240 secret_size);
1241
1242 if (client_early_secret_result.is_err())
1243 {
1244 return error_void(client_early_secret_result.error().code,
1245 "Failed to derive client early secret",
1246 "quic::crypto",
1247 client_early_secret_result.error().message);
1248 }
1249
1250 // Derive 0-RTT keys from client early secret
1251 auto zero_rtt_keys_result = initial_keys::derive_keys(
1252 client_early_secret_result.value(),
1253 true);
1254
1255 if (zero_rtt_keys_result.is_err())
1256 {
1257 return error_void(zero_rtt_keys_result.error().code,
1258 "Failed to derive 0-RTT keys",
1259 "quic::crypto",
1260 zero_rtt_keys_result.error().message);
1261 }
1262
1263 auto& zero_rtt_keys = zero_rtt_keys_result.value();
1264
1265 // Copy the secret
1266 std::copy(client_early_secret_result.value().begin(),
1267 client_early_secret_result.value().end(),
1268 zero_rtt_keys.secret.begin());
1269
1270 // Store the 0-RTT keys
1271 // For client: 0-RTT is write-only (can't receive 0-RTT data)
1272 // For server: 0-RTT is read-only (can receive but not send 0-RTT)
1273 if (impl_->is_server)
1274 {
1275 impl_->read_keys[encryption_level::zero_rtt] = zero_rtt_keys;
1276 }
1277 else
1278 {
1280 }
1281
1282 impl_->has_zero_rtt_keys = true;
1283
1284 return ok();
1285}
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 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 1185 of file crypto.cpp.

1186{
1187 if (impl_->session_ticket_data.empty())
1188 {
1189 return error_void(-1, "Session ticket must be set before enabling early data",
1190 "quic::crypto");
1191 }
1192
1193 impl_->max_early_data_size = max_early_data;
1194 impl_->early_data_enabled = true;
1195
1196 return ok();
1197}

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

1120{
1121 return impl_->alpn;
1122}

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

Referenced by kcenon::network::internal::quic_socket::negotiated_alpn().

Here is the caller graph for this function:

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

1050{
1051 auto it = impl_->read_keys.find(level);
1052 if (it == impl_->read_keys.end())
1053 {
1054 return error<quic_keys>(
1055 -1, "Read keys not available for level", "quic::crypto",
1057 }
1058 return ok(quic_keys(it->second));
1059}
@ 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 1035 of file crypto.cpp.

1037{
1038 auto it = impl_->write_keys.find(level);
1039 if (it == impl_->write_keys.end())
1040 {
1041 return error<quic_keys>(
1042 -1, "Write keys not available for level", "quic::crypto",
1044 }
1045 return ok(quic_keys(it->second));
1046}

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

1288{
1289 return impl_->has_zero_rtt_keys;
1290}

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

793{
794 impl_->reset_tls();
795 impl_->is_server = false;
796
797 impl_->ssl_ctx = SSL_CTX_new(TLS_client_method());
798 if (!impl_->ssl_ctx)
799 {
800 return error_void(-1, "Failed to create SSL context", "quic::crypto",
801 get_openssl_error_string());
802 }
803
804 // Set TLS 1.3 only
805 SSL_CTX_set_min_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
806 SSL_CTX_set_max_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
807
808 impl_->ssl = SSL_new(impl_->ssl_ctx);
809 if (!impl_->ssl)
810 {
811 return error_void(-1, "Failed to create SSL object", "quic::crypto",
812 get_openssl_error_string());
813 }
814
815 // Set SNI
816 if (!server_name.empty())
817 {
818 SSL_set_tlsext_host_name(impl_->ssl, server_name.c_str());
819 }
820
821 // Create memory BIOs
822 impl_->rbio = BIO_new(BIO_s_mem());
823 impl_->wbio = BIO_new(BIO_s_mem());
824 if (!impl_->rbio || !impl_->wbio)
825 {
826 // Ownership has not been transferred to SSL_set_bio yet.
827 BIO_free(impl_->rbio);
828 BIO_free(impl_->wbio);
829 impl_->rbio = nullptr;
830 impl_->wbio = nullptr;
831 return error_void(-1, "Failed to create BIO objects", "quic::crypto");
832 }
833
834 BIO_set_nbio(impl_->rbio, 1);
835 BIO_set_nbio(impl_->wbio, 1);
836
837 SSL_set_bio(impl_->ssl, impl_->rbio, impl_->wbio);
838 SSL_set_connect_state(impl_->ssl);
839
840 return ok();
841}

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

845{
846 impl_->reset_tls();
847 impl_->is_server = true;
848
849 impl_->ssl_ctx = SSL_CTX_new(TLS_server_method());
850 if (!impl_->ssl_ctx)
851 {
852 return error_void(-1, "Failed to create SSL context", "quic::crypto",
853 get_openssl_error_string());
854 }
855
856 // Set TLS 1.3 only
857 SSL_CTX_set_min_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
858 SSL_CTX_set_max_proto_version(impl_->ssl_ctx, TLS1_3_VERSION);
859
860 // Load certificate
861 if (SSL_CTX_use_certificate_file(impl_->ssl_ctx, cert_file.c_str(),
862 SSL_FILETYPE_PEM) != 1)
863 {
864 return error_void(-1, "Failed to load certificate", "quic::crypto",
865 get_openssl_error_string());
866 }
867
868 // Load private key
869 if (SSL_CTX_use_PrivateKey_file(impl_->ssl_ctx, key_file.c_str(),
870 SSL_FILETYPE_PEM) != 1)
871 {
872 return error_void(-1, "Failed to load private key", "quic::crypto",
873 get_openssl_error_string());
874 }
875
876 impl_->ssl = SSL_new(impl_->ssl_ctx);
877 if (!impl_->ssl)
878 {
879 return error_void(-1, "Failed to create SSL object", "quic::crypto",
880 get_openssl_error_string());
881 }
882
883 // Create memory BIOs
884 impl_->rbio = BIO_new(BIO_s_mem());
885 impl_->wbio = BIO_new(BIO_s_mem());
886 if (!impl_->rbio || !impl_->wbio)
887 {
888 // Ownership has not been transferred to SSL_set_bio yet.
889 BIO_free(impl_->rbio);
890 BIO_free(impl_->wbio);
891 impl_->rbio = nullptr;
892 impl_->wbio = nullptr;
893 return error_void(-1, "Failed to create BIO objects", "quic::crypto");
894 }
895
896 BIO_set_nbio(impl_->rbio, 1);
897 BIO_set_nbio(impl_->wbio, 1);
898
899 SSL_set_bio(impl_->ssl, impl_->rbio, impl_->wbio);
900 SSL_set_accept_state(impl_->ssl);
901
902 return ok();
903}

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 1199 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 1025 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 1154 of file crypto.cpp.

1155{
1156 return impl_->is_server;
1157}

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

937{
938 (void)level; // For now, we don't differentiate by level
939
940 // Write incoming data to read BIO
941 int written = BIO_write(impl_->rbio, data.data(),
942 static_cast<int>(data.size()));
943 if (written <= 0)
944 {
946 -1, "Failed to write to BIO", "quic::crypto");
947 }
948
949 // Continue handshake
950 int result = SSL_do_handshake(impl_->ssl);
951 if (result == 1)
952 {
955 }
956 else
957 {
958 int err = SSL_get_error(impl_->ssl, result);
959 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
960 {
962 -1, "SSL handshake failed", "quic::crypto",
963 get_openssl_error_string());
964 }
965 }
966
967 // Read any output data from write BIO
968 std::vector<uint8_t> output;
969 int pending = BIO_ctrl_pending(impl_->wbio);
970 if (pending > 0)
971 {
972 output.resize(static_cast<size_t>(pending));
973 int read = BIO_read(impl_->wbio, output.data(), pending);
974 if (read > 0)
975 {
976 output.resize(static_cast<size_t>(read));
977 }
978 else
979 {
980 output.clear();
981 }
982 }
983
984 return ok(std::move(output));
985}
@ 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 1124 of file crypto.cpp.

1126{
1127 if (protocols.empty())
1128 {
1129 return ok();
1130 }
1131
1132 // Build ALPN wire format: length-prefixed strings
1133 impl_->alpn_data.clear();
1134 for (const auto& proto : protocols)
1135 {
1136 if (proto.size() > 255)
1137 {
1138 return error_void(-1, "ALPN protocol too long", "quic::crypto");
1139 }
1140 impl_->alpn_data.push_back(static_cast<uint8_t>(proto.size()));
1141 impl_->alpn_data.insert(impl_->alpn_data.end(), proto.begin(), proto.end());
1142 }
1143
1144 if (SSL_CTX_set_alpn_protos(impl_->ssl_ctx, impl_->alpn_data.data(),
1145 static_cast<unsigned int>(impl_->alpn_data.size())) != 0)
1146 {
1147 return error_void(-1, "Failed to set ALPN protocols", "quic::crypto",
1148 get_openssl_error_string());
1149 }
1150
1151 return ok();
1152}

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

1064{
1065 impl_->read_keys[level] = read_keys;
1066 impl_->write_keys[level] = write_keys;
1067
1068 if (level > impl_->current_level)
1069 {
1070 impl_->current_level = level;
1071 }
1072}

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

1175{
1176 if (ticket_data.empty())
1177 {
1178 return error_void(-1, "Empty session ticket", "quic::crypto");
1179 }
1180
1181 impl_->session_ticket_data.assign(ticket_data.begin(), ticket_data.end());
1182 return ok();
1183}

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

1169{
1170 impl_->session_ticket_callback = std::move(cb);
1171}
session_ticket_callback_t session_ticket_callback
Definition crypto.cpp:755

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

988{
989 int result = SSL_do_handshake(impl_->ssl);
990 if (result == 1)
991 {
993 }
994 else
995 {
996 int err = SSL_get_error(impl_->ssl, result);
997 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
998 {
1000 -1, "SSL handshake start failed", "quic::crypto",
1001 get_openssl_error_string());
1002 }
1003 }
1004
1005 // Read output from write BIO
1006 std::vector<uint8_t> output;
1007 int pending = BIO_ctrl_pending(impl_->wbio);
1008 if (pending > 0)
1009 {
1010 output.resize(static_cast<size_t>(pending));
1011 int read = BIO_read(impl_->wbio, output.data(), pending);
1012 if (read > 0)
1013 {
1014 output.resize(static_cast<size_t>(read));
1015 }
1016 else
1017 {
1018 output.clear();
1019 }
1020 }
1021
1022 return ok(std::move(output));
1023}

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

1075{
1077 {
1078 return error_void(-1, "Handshake not complete", "quic::crypto");
1079 }
1080
1082 if (it == impl_->write_keys.end())
1083 {
1084 return error_void(-1, "Application keys not available", "quic::crypto");
1085 }
1086
1087 // Derive new secrets using "quic ku" label
1088 auto& old_secret = it->second.secret;
1089 auto new_secret_result = hkdf::expand_label(old_secret, "quic ku", {},
1090 secret_size);
1091 if (new_secret_result.is_err())
1092 {
1093 return error_void(new_secret_result.error().code,
1094 new_secret_result.error().message,
1095 get_error_source(new_secret_result.error()));
1096 }
1097
1098 // Derive new keys from new secret
1099 auto new_keys_result = initial_keys::derive_keys(new_secret_result.value(),
1100 true);
1101 if (new_keys_result.is_err())
1102 {
1103 return error_void(new_keys_result.error().code,
1104 new_keys_result.error().message,
1105 get_error_source(new_keys_result.error()));
1106 }
1107
1108 auto& new_keys = new_keys_result.value();
1109 std::copy(new_secret_result.value().begin(),
1110 new_secret_result.value().end(),
1111 new_keys.secret.begin());
1112
1115
1116 return ok();
1117}

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: