ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
common.c File Reference

Common handshake functions: initialization, cleanup, encryption, rekeying. More...

Go to the source code of this file.

Functions

asciichat_error_t crypto_handshake_init (crypto_handshake_context_t *ctx, bool is_server)
 Initialize crypto handshake context.
 
asciichat_error_t crypto_handshake_set_parameters (crypto_handshake_context_t *ctx, const crypto_parameters_packet_t *params)
 Set crypto parameters from crypto_parameters_packet_t.
 
asciichat_error_t crypto_handshake_validate_packet_size (const crypto_handshake_context_t *ctx, uint16_t packet_type, size_t packet_size)
 Validate crypto packet size based on session parameters.
 
asciichat_error_t crypto_handshake_init_with_password (crypto_handshake_context_t *ctx, bool is_server, const char *password)
 Initialize crypto handshake context with password authentication.
 
void crypto_handshake_cleanup (crypto_handshake_context_t *ctx)
 Cleanup crypto handshake context with secure memory wiping.
 
bool crypto_handshake_is_ready (const crypto_handshake_context_t *ctx)
 Check if handshake is complete and encryption is ready.
 
const crypto_context_tcrypto_handshake_get_context (const crypto_handshake_context_t *ctx)
 Get the crypto context for encryption/decryption.
 
asciichat_error_t crypto_handshake_encrypt_packet (const crypto_handshake_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_len)
 Encrypt a packet using the established crypto context.
 
asciichat_error_t crypto_handshake_decrypt_packet (const crypto_handshake_context_t *ctx, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_len)
 Decrypt a packet using the established crypto context.
 
asciichat_error_t crypto_encrypt_packet_or_passthrough (const crypto_handshake_context_t *ctx, bool crypto_ready, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_len)
 Encrypt with automatic passthrough if crypto not ready.
 
asciichat_error_t crypto_decrypt_packet_or_passthrough (const crypto_handshake_context_t *ctx, bool crypto_ready, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_len)
 Decrypt with automatic passthrough if crypto not ready.
 
asciichat_error_t crypto_handshake_rekey_request (crypto_handshake_context_t *ctx, socket_t socket)
 Send REKEY_REQUEST packet (initiator side)
 
asciichat_error_t crypto_handshake_rekey_response (crypto_handshake_context_t *ctx, socket_t socket)
 Send REKEY_RESPONSE packet (responder side)
 
asciichat_error_t crypto_handshake_rekey_complete (crypto_handshake_context_t *ctx, socket_t socket)
 Send REKEY_COMPLETE packet (initiator side)
 
asciichat_error_t crypto_handshake_process_rekey_request (crypto_handshake_context_t *ctx, const uint8_t *packet, size_t packet_len)
 Process received REKEY_REQUEST packet (responder side)
 
asciichat_error_t crypto_handshake_process_rekey_response (crypto_handshake_context_t *ctx, const uint8_t *packet, size_t packet_len)
 Process received REKEY_RESPONSE packet (initiator side)
 
asciichat_error_t crypto_handshake_process_rekey_complete (crypto_handshake_context_t *ctx, const uint8_t *packet, size_t packet_len)
 Process received REKEY_COMPLETE packet (responder side)
 
bool crypto_handshake_should_rekey (const crypto_handshake_context_t *ctx)
 Check if rekeying should be triggered for this handshake context.
 

Detailed Description

Common handshake functions: initialization, cleanup, encryption, rekeying.

Definition in file crypto/handshake/common.c.

Function Documentation

◆ crypto_decrypt_packet_or_passthrough()

asciichat_error_t crypto_decrypt_packet_or_passthrough ( const crypto_handshake_context_t ctx,
bool  crypto_ready,
const uint8_t ciphertext,
size_t  ciphertext_len,
uint8_t plaintext,
size_t  plaintext_size,
size_t *  plaintext_len 
)

Decrypt with automatic passthrough if crypto not ready.

Parameters
ctxHandshake context
crypto_readyTrue if crypto is ready, false to passthrough
ciphertextCiphertext or plaintext data to decrypt
ciphertext_lenLength of ciphertext/plaintext data
plaintextOutput buffer for plaintext
plaintext_sizeSize of output buffer
plaintext_lenOutput parameter for actual plaintext length
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 340 of file crypto/handshake/common.c.

343 {
344 if (!crypto_ready) {
345 // No encryption - just copy data
346 if (ciphertext_len > plaintext_size) {
347 SET_ERRNO(ERROR_BUFFER, "Ciphertext too large for plaintext buffer: %zu > %zu", ciphertext_len, plaintext_size);
348 return ERROR_BUFFER;
349 }
350 memcpy(plaintext, ciphertext, ciphertext_len);
351 *plaintext_len = ciphertext_len;
352 return ASCIICHAT_OK;
353 }
354
355 return crypto_handshake_decrypt_packet(ctx, ciphertext, ciphertext_len, plaintext, plaintext_size, plaintext_len);
356}
asciichat_error_t crypto_handshake_decrypt_packet(const crypto_handshake_context_t *ctx, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_len)
Decrypt a packet using the established crypto context.
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
@ ASCIICHAT_OK
Definition error_codes.h:48
@ ERROR_BUFFER
Definition error_codes.h:96

References ASCIICHAT_OK, crypto_handshake_decrypt_packet(), ERROR_BUFFER, and SET_ERRNO.

Referenced by crypto_client_decrypt_packet(), and crypto_server_decrypt_packet().

◆ crypto_encrypt_packet_or_passthrough()

asciichat_error_t crypto_encrypt_packet_or_passthrough ( const crypto_handshake_context_t ctx,
bool  crypto_ready,
const uint8_t plaintext,
size_t  plaintext_len,
uint8_t ciphertext,
size_t  ciphertext_size,
size_t *  ciphertext_len 
)

Encrypt with automatic passthrough if crypto not ready.

Parameters
ctxHandshake context
crypto_readyTrue if crypto is ready, false to passthrough
plaintextPlaintext data to encrypt
plaintext_lenLength of plaintext data
ciphertextOutput buffer for ciphertext or plaintext (if passthrough)
ciphertext_sizeSize of output buffer
ciphertext_lenOutput parameter for actual length
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 321 of file crypto/handshake/common.c.

324 {
325 if (!crypto_ready) {
326 // No encryption - just copy data
327 if (plaintext_len > ciphertext_size) {
328 SET_ERRNO(ERROR_BUFFER, "Plaintext too large for ciphertext buffer: %zu > %zu", plaintext_len, ciphertext_size);
329 return ERROR_BUFFER;
330 }
331 memcpy(ciphertext, plaintext, plaintext_len);
332 *ciphertext_len = plaintext_len;
333 return ASCIICHAT_OK;
334 }
335
336 return crypto_handshake_encrypt_packet(ctx, plaintext, plaintext_len, ciphertext, ciphertext_size, ciphertext_len);
337}
asciichat_error_t crypto_handshake_encrypt_packet(const crypto_handshake_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_len)
Encrypt a packet using the established crypto context.

References ASCIICHAT_OK, crypto_handshake_encrypt_packet(), ERROR_BUFFER, and SET_ERRNO.

Referenced by crypto_client_encrypt_packet(), and crypto_server_encrypt_packet().

◆ crypto_handshake_cleanup()

void crypto_handshake_cleanup ( crypto_handshake_context_t ctx)

Cleanup crypto handshake context with secure memory wiping.

Parameters
ctxHandshake context to cleanup

Definition at line 259 of file crypto/handshake/common.c.

259 {
260 if (!ctx)
261 return;
262
263 // Cleanup core crypto context
265
266 // Zero out sensitive data
267 sodium_memzero(ctx, sizeof(crypto_handshake_context_t));
268}
void crypto_cleanup(crypto_context_t *ctx)
Cleanup crypto context with secure memory wiping.
Cryptographic handshake context structure.

References crypto_cleanup(), and crypto_handshake_context_t::crypto_ctx.

Referenced by client_crypto_init(), crypto_client_cleanup(), crypto_server_cleanup_client(), and server_connection_close().

◆ crypto_handshake_decrypt_packet()

asciichat_error_t crypto_handshake_decrypt_packet ( const crypto_handshake_context_t ctx,
const uint8_t ciphertext,
size_t  ciphertext_len,
uint8_t plaintext,
size_t  plaintext_size,
size_t *  plaintext_len 
)

Decrypt a packet using the established crypto context.

Parameters
ctxHandshake context (must be ready)
ciphertextCiphertext data to decrypt
ciphertext_lenLength of ciphertext data
plaintextOutput buffer for plaintext
plaintext_sizeSize of output buffer
plaintext_lenOutput parameter for actual plaintext length
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 303 of file crypto/handshake/common.c.

305 {
306 if (!ctx || !crypto_handshake_is_ready(ctx)) {
307 SET_ERRNO(ERROR_INVALID_STATE, "Invalid state: ctx=%p, ready=%d", ctx, ctx ? crypto_handshake_is_ready(ctx) : 0);
308 return ERROR_INVALID_STATE;
309 }
310
311 crypto_result_t result = crypto_decrypt((crypto_context_t *)&ctx->crypto_ctx, ciphertext, ciphertext_len, plaintext,
312 plaintext_size, plaintext_len);
313 if (result != CRYPTO_OK) {
314 return SET_ERRNO(ERROR_NETWORK, "Failed to decrypt packet: %s", crypto_result_to_string(result));
315 }
316
317 return ASCIICHAT_OK;
318}
bool crypto_handshake_is_ready(const crypto_handshake_context_t *ctx)
Check if handshake is complete and encryption is ready.
const char * crypto_result_to_string(crypto_result_t result)
Convert crypto result to human-readable string.
crypto_result_t
Cryptographic operation result codes.
crypto_result_t crypto_decrypt(crypto_context_t *ctx, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext_out, size_t plaintext_out_size, size_t *plaintext_len_out)
Decrypt data using XSalsa20-Poly1305.
@ CRYPTO_OK
@ ERROR_INVALID_STATE
@ ERROR_NETWORK
Definition error_codes.h:69
Cryptographic context structure.

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_decrypt(), crypto_handshake_is_ready(), CRYPTO_OK, crypto_result_to_string(), ERROR_INVALID_STATE, ERROR_NETWORK, and SET_ERRNO.

Referenced by crypto_decrypt_packet_or_passthrough().

◆ crypto_handshake_encrypt_packet()

asciichat_error_t crypto_handshake_encrypt_packet ( const crypto_handshake_context_t ctx,
const uint8_t plaintext,
size_t  plaintext_len,
uint8_t ciphertext,
size_t  ciphertext_size,
size_t *  ciphertext_len 
)

Encrypt a packet using the established crypto context.

Parameters
ctxHandshake context (must be ready)
plaintextPlaintext data to encrypt
plaintext_lenLength of plaintext data
ciphertextOutput buffer for ciphertext
ciphertext_sizeSize of output buffer
ciphertext_lenOutput parameter for actual ciphertext length
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 285 of file crypto/handshake/common.c.

287 {
288 if (!ctx || !crypto_handshake_is_ready(ctx)) {
289 SET_ERRNO(ERROR_INVALID_STATE, "Invalid state: ctx=%p, ready=%d", ctx, ctx ? crypto_handshake_is_ready(ctx) : 0);
290 return ERROR_INVALID_STATE;
291 }
292
293 crypto_result_t result = crypto_encrypt((crypto_context_t *)&ctx->crypto_ctx, plaintext, plaintext_len, ciphertext,
294 ciphertext_size, ciphertext_len);
295 if (result != CRYPTO_OK) {
296 return SET_ERRNO(ERROR_NETWORK, "Failed to encrypt packet: %s", crypto_result_to_string(result));
297 }
298
299 return ASCIICHAT_OK;
300}
crypto_result_t crypto_encrypt(crypto_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext_out, size_t ciphertext_out_size, size_t *ciphertext_len_out)
Encrypt data using XSalsa20-Poly1305.

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_encrypt(), crypto_handshake_is_ready(), CRYPTO_OK, crypto_result_to_string(), ERROR_INVALID_STATE, ERROR_NETWORK, and SET_ERRNO.

Referenced by crypto_encrypt_packet_or_passthrough().

◆ crypto_handshake_get_context()

const crypto_context_t * crypto_handshake_get_context ( const crypto_handshake_context_t ctx)

Get the crypto context for encryption/decryption.

Parameters
ctxHandshake context
Returns
Pointer to crypto context, or NULL if ctx is NULL

Definition at line 278 of file crypto/handshake/common.c.

278 {
279 if (!ctx || !crypto_handshake_is_ready(ctx))
280 return NULL;
281 return &ctx->crypto_ctx;
282}

References crypto_handshake_context_t::crypto_ctx, and crypto_handshake_is_ready().

Referenced by broadcast_server_state_to_all_clients(), client_send_thread_func(), crypto_client_get_context(), crypto_server_get_context(), disconnect_client_for_bad_data(), tcp_client_send_audio_batch(), tcp_client_send_audio_opus(), tcp_client_send_audio_opus_batch(), tcp_client_send_join(), and tcp_client_send_packet().

◆ crypto_handshake_init()

asciichat_error_t crypto_handshake_init ( crypto_handshake_context_t ctx,
bool  is_server 
)

Initialize crypto handshake context.

Parameters
ctxHandshake context to initialize (must not be NULL)
is_serverTrue if this is the server side, false for client
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 17 of file crypto/handshake/common.c.

17 {
18 if (!ctx) {
19 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters: ctx=%p", ctx);
20 }
21
22 // Zero out the context
23 memset(ctx, 0, sizeof(crypto_handshake_context_t));
24
25 // Initialize core crypto context
27 if (result != CRYPTO_OK) {
28 return SET_ERRNO(ERROR_CRYPTO, "Failed to initialize crypto context: %s", crypto_result_to_string(result));
29 }
30
32 ctx->is_server = is_server;
33 ctx->verify_server_key = false;
34 ctx->require_client_auth = false;
35 ctx->server_uses_client_auth = false; // Set to true only if authenticated packet received
36
37 // Load server keys if this is a server
38 if (is_server) {
39 log_info("Server crypto handshake initialized (ephemeral keys)");
40 } else {
41 log_info("Client crypto handshake initialized");
42 }
43
44 return ASCIICHAT_OK;
45}
crypto_result_t crypto_init(crypto_context_t *ctx)
Initialize libsodium and crypto context.
@ ERROR_CRYPTO
Definition error_codes.h:88
@ ERROR_INVALID_PARAM
@ CRYPTO_HANDSHAKE_INIT
#define log_info(...)
Log an INFO message.
crypto_handshake_state_t state

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, CRYPTO_HANDSHAKE_INIT, crypto_init(), CRYPTO_OK, crypto_result_to_string(), ERROR_CRYPTO, ERROR_INVALID_PARAM, crypto_handshake_context_t::is_server, log_info, crypto_handshake_context_t::require_client_auth, crypto_handshake_context_t::server_uses_client_auth, SET_ERRNO, crypto_handshake_context_t::state, and crypto_handshake_context_t::verify_server_key.

Referenced by client_crypto_init(), and server_crypto_handshake().

◆ crypto_handshake_init_with_password()

asciichat_error_t crypto_handshake_init_with_password ( crypto_handshake_context_t ctx,
bool  is_server,
const char *  password 
)

Initialize crypto handshake context with password authentication.

Parameters
ctxHandshake context to initialize (must not be NULL)
is_serverTrue if this is the server side, false for client
passwordPassword for authentication (must meet length requirements)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 229 of file crypto/handshake/common.c.

230 {
231 if (!ctx || !password) {
232 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters: ctx=%p, password=%p", ctx, password);
233 }
234
235 // Zero out the context
236 memset(ctx, 0, sizeof(crypto_handshake_context_t));
237
238 // Initialize core crypto context with password
239 crypto_result_t result = crypto_init_with_password(&ctx->crypto_ctx, password);
240 if (result != CRYPTO_OK) {
241 return SET_ERRNO(ERROR_CRYPTO, "Failed to initialize crypto context with password: %s",
243 }
244
246 ctx->is_server = is_server;
247 ctx->verify_server_key = false;
248 ctx->require_client_auth = false;
249 ctx->server_uses_client_auth = false; // Set to true only if authenticated packet received
250 ctx->has_password = true;
251
252 // Store password temporarily (will be cleared after key derivation)
253 SAFE_STRNCPY(ctx->password, password, sizeof(ctx->password) - 1);
254
255 return ASCIICHAT_OK;
256}
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:358
crypto_result_t crypto_init_with_password(crypto_context_t *ctx, const char *password)
Initialize with password-based encryption.

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, CRYPTO_HANDSHAKE_INIT, crypto_init_with_password(), CRYPTO_OK, crypto_result_to_string(), ERROR_CRYPTO, ERROR_INVALID_PARAM, crypto_handshake_context_t::has_password, crypto_handshake_context_t::is_server, crypto_handshake_context_t::password, crypto_handshake_context_t::require_client_auth, SAFE_STRNCPY, crypto_handshake_context_t::server_uses_client_auth, SET_ERRNO, crypto_handshake_context_t::state, and crypto_handshake_context_t::verify_server_key.

Referenced by client_crypto_init(), and server_crypto_handshake().

◆ crypto_handshake_is_ready()

◆ crypto_handshake_process_rekey_complete()

asciichat_error_t crypto_handshake_process_rekey_complete ( crypto_handshake_context_t ctx,
const uint8_t packet,
size_t  packet_len 
)

Process received REKEY_COMPLETE packet (responder side)

Process received REKEY_COMPLETE packet (responder side). Verifies that the packet decrypts with the new shared secret. If successful, commits to the new key.

Definition at line 563 of file crypto/handshake/common.c.

564 {
565 if (!ctx || !crypto_handshake_is_ready(ctx)) {
566 return SET_ERRNO(ERROR_INVALID_STATE, "Handshake not ready for rekeying: ctx=%p, ready=%d", ctx,
567 ctx ? crypto_handshake_is_ready(ctx) : 0);
568 }
569
571 return SET_ERRNO(ERROR_INVALID_STATE, "No rekey in progress or temp key missing");
572 }
573
574 log_info("Received REKEY_COMPLETE packet (%zu bytes), verifying with NEW key", packet_len);
575
576 // Temporarily swap keys to decrypt with NEW key
577 uint8_t old_shared_key[CRYPTO_SHARED_KEY_SIZE];
578 memcpy(old_shared_key, ctx->crypto_ctx.shared_key, CRYPTO_SHARED_KEY_SIZE);
580
581 // Attempt to decrypt with NEW key
582 uint8_t plaintext[256];
583 size_t plaintext_len = 0;
584 crypto_result_t result =
585 crypto_decrypt(&ctx->crypto_ctx, packet, packet_len, plaintext, sizeof(plaintext), &plaintext_len);
586
587 // Restore old key immediately
588 memcpy(ctx->crypto_ctx.shared_key, old_shared_key, CRYPTO_SHARED_KEY_SIZE);
589 sodium_memzero(old_shared_key, sizeof(old_shared_key));
590
591 if (result != CRYPTO_OK) {
593 return SET_ERRNO(ERROR_CRYPTO, "REKEY_COMPLETE decryption failed (key mismatch): %s",
595 }
596
597 log_info("REKEY_COMPLETE verified successfully, committing to new key");
598
599 // Commit to new key (atomic switch)
600 result = crypto_rekey_commit(&ctx->crypto_ctx);
601 if (result != CRYPTO_OK) {
602 return SET_ERRNO(ERROR_CRYPTO, "Failed to commit rekey: %s", crypto_result_to_string(result));
603 }
604
605 log_info("Session rekeying completed successfully (responder side)");
606 return ASCIICHAT_OK;
607}
unsigned char uint8_t
Definition common.h:56
crypto_result_t crypto_rekey_commit(crypto_context_t *ctx)
Commit to new keys after successful REKEY_COMPLETE.
#define CRYPTO_SHARED_KEY_SIZE
Shared key size (X25519)
void crypto_rekey_abort(crypto_context_t *ctx)
Abort rekeying and fallback to old keys.
uint8_t temp_shared_key[32]

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_decrypt(), crypto_handshake_is_ready(), CRYPTO_OK, crypto_rekey_abort(), crypto_rekey_commit(), crypto_result_to_string(), CRYPTO_SHARED_KEY_SIZE, ERROR_CRYPTO, ERROR_INVALID_STATE, crypto_context_t::has_temp_key, log_info, crypto_context_t::rekey_in_progress, SET_ERRNO, crypto_context_t::shared_key, and crypto_context_t::temp_shared_key.

◆ crypto_handshake_process_rekey_request()

asciichat_error_t crypto_handshake_process_rekey_request ( crypto_handshake_context_t ctx,
const uint8_t packet,
size_t  packet_len 
)

Process received REKEY_REQUEST packet (responder side)

Process received REKEY_REQUEST packet (responder side). Extracts peer's new ephemeral public key and computes new shared secret.

Definition at line 478 of file crypto/handshake/common.c.

479 {
480 if (!ctx || !crypto_handshake_is_ready(ctx)) {
481 return SET_ERRNO(ERROR_INVALID_STATE, "Handshake not ready for rekeying: ctx=%p, ready=%d", ctx,
482 ctx ? crypto_handshake_is_ready(ctx) : 0);
483 }
484
485 // DDoS PROTECTION: Rate limit rekey requests
486 time_t now = time(NULL);
487 if (ctx->crypto_ctx.rekey_last_request_time > 0) {
488 time_t elapsed = now - ctx->crypto_ctx.rekey_last_request_time;
489 if (elapsed < REKEY_MIN_REQUEST_INTERVAL) {
490 return SET_ERRNO(ERROR_CRYPTO,
491 "SECURITY: Rekey request rejected - too frequent (%ld sec since last, minimum %d sec required)",
492 (long)elapsed, REKEY_MIN_REQUEST_INTERVAL);
493 }
494 }
495
496 // Update last request time
498
499 // Validate packet size (should be 32 bytes for X25519 public key)
500 if (packet_len != CRYPTO_PUBLIC_KEY_SIZE) {
501 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid REKEY_REQUEST packet size: %zu (expected %d)", packet_len,
503 }
504
505 log_info("Received REKEY_REQUEST with peer's new ephemeral public key (32 bytes)");
506
507 // Initialize our rekey process (generates our new ephemeral keypair)
509 if (result != CRYPTO_OK) {
510 return SET_ERRNO(ERROR_CRYPTO, "Failed to initialize rekey: %s", crypto_result_to_string(result));
511 }
512
513 // Process peer's public key and compute new shared secret
514 result = crypto_rekey_process_request(&ctx->crypto_ctx, packet);
515 if (result != CRYPTO_OK) {
517 return SET_ERRNO(ERROR_CRYPTO, "Failed to process REKEY_REQUEST: %s", crypto_result_to_string(result));
518 }
519
520 log_debug("REKEY_REQUEST processed successfully, new shared secret computed (responder side)");
521 return ASCIICHAT_OK;
522}
crypto_result_t crypto_rekey_process_request(crypto_context_t *ctx, const uint8_t *peer_new_public_key)
Process REKEY_REQUEST from peer (responder side)
#define CRYPTO_PUBLIC_KEY_SIZE
Public key size (X25519)
#define REKEY_MIN_REQUEST_INTERVAL
Minimum interval between rekey requests (60 seconds, DDoS protection)
crypto_result_t crypto_rekey_init(crypto_context_t *ctx)
Initiate rekeying by generating new ephemeral keys.
#define log_debug(...)
Log a DEBUG message.

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_handshake_is_ready(), CRYPTO_OK, CRYPTO_PUBLIC_KEY_SIZE, crypto_rekey_abort(), crypto_rekey_init(), crypto_rekey_process_request(), crypto_result_to_string(), ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, log_debug, log_info, crypto_context_t::rekey_last_request_time, REKEY_MIN_REQUEST_INTERVAL, and SET_ERRNO.

Referenced by crypto_client_process_rekey_request().

◆ crypto_handshake_process_rekey_response()

asciichat_error_t crypto_handshake_process_rekey_response ( crypto_handshake_context_t ctx,
const uint8_t packet,
size_t  packet_len 
)

Process received REKEY_RESPONSE packet (initiator side)

Process received REKEY_RESPONSE packet (initiator side). Extracts peer's new ephemeral public key and computes new shared secret.

Definition at line 528 of file crypto/handshake/common.c.

529 {
530 if (!ctx || !crypto_handshake_is_ready(ctx)) {
531 return SET_ERRNO(ERROR_INVALID_STATE, "Handshake not ready for rekeying: ctx=%p, ready=%d", ctx,
532 ctx ? crypto_handshake_is_ready(ctx) : 0);
533 }
534
535 // Validate packet size (should be 32 bytes for X25519 public key)
536 if (packet_len != CRYPTO_PUBLIC_KEY_SIZE) {
537 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid REKEY_RESPONSE packet size: %zu (expected %d)", packet_len,
539 }
540
542 return SET_ERRNO(ERROR_INVALID_STATE, "No rekey in progress or temp key missing");
543 }
544
545 log_info("Received REKEY_RESPONSE with peer's new ephemeral public key (32 bytes)");
546
547 // Process peer's public key and compute new shared secret
549 if (result != CRYPTO_OK) {
551 return SET_ERRNO(ERROR_CRYPTO, "Failed to process REKEY_RESPONSE: %s", crypto_result_to_string(result));
552 }
553
554 log_debug("REKEY_RESPONSE processed successfully, new shared secret computed (initiator side)");
555 return ASCIICHAT_OK;
556}
crypto_result_t crypto_rekey_process_response(crypto_context_t *ctx, const uint8_t *peer_new_public_key)
Process REKEY_RESPONSE from peer (initiator side)

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_handshake_is_ready(), CRYPTO_OK, CRYPTO_PUBLIC_KEY_SIZE, crypto_rekey_abort(), crypto_rekey_process_response(), crypto_result_to_string(), ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, crypto_context_t::has_temp_key, log_debug, log_info, crypto_context_t::rekey_in_progress, and SET_ERRNO.

Referenced by crypto_client_process_rekey_response().

◆ crypto_handshake_rekey_complete()

asciichat_error_t crypto_handshake_rekey_complete ( crypto_handshake_context_t ctx,
socket_t  socket 
)

Send REKEY_COMPLETE packet (initiator side)

Send REKEY_COMPLETE packet (initiator side). CRITICAL: This packet is encrypted with the NEW shared secret. It proves that both sides have computed the same shared secret.

Definition at line 423 of file crypto/handshake/common.c.

423 {
424 if (!ctx || !crypto_handshake_is_ready(ctx)) {
425 return SET_ERRNO(ERROR_INVALID_STATE, "Handshake not ready for rekeying: ctx=%p, ready=%d", ctx,
426 ctx ? crypto_handshake_is_ready(ctx) : 0);
427 }
428
430 return SET_ERRNO(ERROR_INVALID_STATE, "No rekey in progress or temp key missing");
431 }
432
433 // Encrypt empty payload with NEW key to prove possession
434 uint8_t plaintext[1] = {0}; // Minimal payload
435 uint8_t ciphertext[256]; // Sufficient for nonce + MAC + minimal payload
436 size_t ciphertext_len = 0;
437
438 // Temporarily swap keys to encrypt with NEW key
439 uint8_t old_shared_key[CRYPTO_SHARED_KEY_SIZE];
440 memcpy(old_shared_key, ctx->crypto_ctx.shared_key, CRYPTO_SHARED_KEY_SIZE);
442
443 // Encrypt with NEW key
444 crypto_result_t result =
445 crypto_encrypt(&ctx->crypto_ctx, plaintext, sizeof(plaintext), ciphertext, sizeof(ciphertext), &ciphertext_len);
446
447 // Restore old key immediately (commit will happen after successful send)
448 memcpy(ctx->crypto_ctx.shared_key, old_shared_key, CRYPTO_SHARED_KEY_SIZE);
449 sodium_memzero(old_shared_key, sizeof(old_shared_key));
450
451 if (result != CRYPTO_OK) {
453 return SET_ERRNO(ERROR_CRYPTO, "Failed to encrypt REKEY_COMPLETE: %s", crypto_result_to_string(result));
454 }
455
456 // Send encrypted REKEY_COMPLETE
457 log_info("Sending REKEY_COMPLETE (encrypted with NEW key, %zu bytes)", ciphertext_len);
458 int send_result = send_packet(socket, PACKET_TYPE_CRYPTO_REKEY_COMPLETE, ciphertext, ciphertext_len);
459 if (send_result != 0) {
461 return SET_ERRNO(ERROR_NETWORK, "Failed to send REKEY_COMPLETE packet");
462 }
463
464 // Commit to new key (atomic switch)
465 result = crypto_rekey_commit(&ctx->crypto_ctx);
466 if (result != CRYPTO_OK) {
467 return SET_ERRNO(ERROR_CRYPTO, "Failed to commit rekey: %s", crypto_result_to_string(result));
468 }
469
470 log_info("Session rekeying completed successfully (initiator side)");
471 return ASCIICHAT_OK;
472}
int send_packet(socket_t sockfd, packet_type_t type, const void *data, size_t len)
Send a basic packet without encryption.
Definition packet.c:754
@ PACKET_TYPE_CRYPTO_REKEY_COMPLETE
Initiator -> Responder: Empty (encrypted with NEW key, but still handshake)
Definition packet.h:340

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_encrypt(), crypto_handshake_is_ready(), CRYPTO_OK, crypto_rekey_abort(), crypto_rekey_commit(), crypto_result_to_string(), CRYPTO_SHARED_KEY_SIZE, ERROR_CRYPTO, ERROR_INVALID_STATE, ERROR_NETWORK, crypto_context_t::has_temp_key, log_info, PACKET_TYPE_CRYPTO_REKEY_COMPLETE, crypto_context_t::rekey_in_progress, send_packet(), SET_ERRNO, crypto_context_t::shared_key, and crypto_context_t::temp_shared_key.

Referenced by crypto_client_send_rekey_complete().

◆ crypto_handshake_rekey_request()

asciichat_error_t crypto_handshake_rekey_request ( crypto_handshake_context_t ctx,
socket_t  socket 
)

Send REKEY_REQUEST packet (initiator side)

Send REKEY_REQUEST packet (initiator side). Sends the initiator's new ephemeral public key to the peer.

Definition at line 366 of file crypto/handshake/common.c.

366 {
367 if (!ctx || !crypto_handshake_is_ready(ctx)) {
368 return SET_ERRNO(ERROR_INVALID_STATE, "Handshake not ready for rekeying: ctx=%p, ready=%d", ctx,
369 ctx ? crypto_handshake_is_ready(ctx) : 0);
370 }
371
372 // Initialize rekey process (generates new ephemeral keypair)
374 if (result != CRYPTO_OK) {
375 return SET_ERRNO(ERROR_CRYPTO, "Failed to initialize rekey: %s", crypto_result_to_string(result));
376 }
377
378 // Send REKEY_REQUEST with new ephemeral public key (32 bytes)
379 log_info("Sending REKEY_REQUEST with new ephemeral X25519 public key (32 bytes)");
380 int send_result =
382 if (send_result != 0) {
383 crypto_rekey_abort(&ctx->crypto_ctx); // Clean up temp keys on failure
384 return SET_ERRNO(ERROR_NETWORK, "Failed to send REKEY_REQUEST packet");
385 }
386
387 log_debug("REKEY_REQUEST sent successfully, awaiting REKEY_RESPONSE");
388 return ASCIICHAT_OK;
389}
@ PACKET_TYPE_CRYPTO_REKEY_REQUEST
Initiator -> Responder: {new_ephemeral_pk[32]} (UNENCRYPTED during rekey)
Definition packet.h:336
uint8_t temp_public_key[32]

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_handshake_is_ready(), CRYPTO_OK, CRYPTO_PUBLIC_KEY_SIZE, crypto_rekey_abort(), crypto_rekey_init(), crypto_result_to_string(), ERROR_CRYPTO, ERROR_INVALID_STATE, ERROR_NETWORK, log_debug, log_info, PACKET_TYPE_CRYPTO_REKEY_REQUEST, send_packet(), SET_ERRNO, and crypto_context_t::temp_public_key.

Referenced by client_send_thread_func(), and crypto_client_initiate_rekey().

◆ crypto_handshake_rekey_response()

asciichat_error_t crypto_handshake_rekey_response ( crypto_handshake_context_t ctx,
socket_t  socket 
)

Send REKEY_RESPONSE packet (responder side)

Send REKEY_RESPONSE packet (responder side). Sends the responder's new ephemeral public key to the peer.

Definition at line 395 of file crypto/handshake/common.c.

395 {
396 if (!ctx || !crypto_handshake_is_ready(ctx)) {
397 return SET_ERRNO(ERROR_INVALID_STATE, "Handshake not ready for rekeying: ctx=%p, ready=%d", ctx,
398 ctx ? crypto_handshake_is_ready(ctx) : 0);
399 }
400
402 return SET_ERRNO(ERROR_INVALID_STATE, "No rekey in progress or temp key missing");
403 }
404
405 // Send REKEY_RESPONSE with new ephemeral public key (32 bytes)
406 log_info("Sending REKEY_RESPONSE with new ephemeral X25519 public key (32 bytes)");
407 int send_result =
409 if (send_result != 0) {
410 crypto_rekey_abort(&ctx->crypto_ctx); // Clean up temp keys on failure
411 return SET_ERRNO(ERROR_NETWORK, "Failed to send REKEY_RESPONSE packet");
412 }
413
414 log_debug("REKEY_RESPONSE sent successfully, awaiting REKEY_COMPLETE");
415 return ASCIICHAT_OK;
416}
@ PACKET_TYPE_CRYPTO_REKEY_RESPONSE
Responder -> Initiator: {new_ephemeral_pk[32]} (UNENCRYPTED during rekey)
Definition packet.h:338

References ASCIICHAT_OK, crypto_handshake_context_t::crypto_ctx, crypto_handshake_is_ready(), CRYPTO_PUBLIC_KEY_SIZE, crypto_rekey_abort(), ERROR_INVALID_STATE, ERROR_NETWORK, crypto_context_t::has_temp_key, log_debug, log_info, PACKET_TYPE_CRYPTO_REKEY_RESPONSE, crypto_context_t::rekey_in_progress, send_packet(), SET_ERRNO, and crypto_context_t::temp_public_key.

Referenced by crypto_client_send_rekey_response().

◆ crypto_handshake_set_parameters()

asciichat_error_t crypto_handshake_set_parameters ( crypto_handshake_context_t ctx,
const crypto_parameters_packet_t params 
)

Set crypto parameters from crypto_parameters_packet_t.

Parameters
ctxHandshake context
paramsNegotiated crypto parameters (from capabilities negotiation)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 48 of file crypto/handshake/common.c.

49 {
50 if (!ctx || !params) {
51 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters: ctx=%p, params=%p", ctx, params);
52 }
53
54 // Client receives network byte order and must convert
55 // Server uses host byte order and must NOT convert
56 if (ctx->is_server) {
57 // Server: values are already in host byte order
58 // Update crypto context with negotiated parameters directly
63 } else {
64 // Client: convert from network byte order
65 // Update crypto context with negotiated parameters directly
70 }
71 // Update crypto context with negotiated parameters directly
72 ctx->crypto_ctx.nonce_size = params->nonce_size;
73 ctx->crypto_ctx.mac_size = params->mac_size;
74 ctx->crypto_ctx.hmac_size = params->hmac_size;
76 AUTH_CHALLENGE_SIZE; // Auth challenge size is fixed for now, could be negotiated later
78 (uint8_t)ctx->crypto_ctx.shared_key_size; // Use shared key size as encryption key size
79 ctx->crypto_ctx.private_key_size = ctx->crypto_ctx.public_key_size; // Same as public key for X25519
80 ctx->crypto_ctx.salt_size = ARGON2ID_SALT_SIZE; // Salt size doesn't change
81
82 log_debug("Crypto parameters set: kex_key=%u, auth_key=%u, sig=%u, "
83 "secret=%u, nonce=%u, mac=%u, hmac=%u",
87
88 return ASCIICHAT_OK;
89}
#define NET_TO_HOST_U16(val)
Definition endian.h:116
#define AUTH_CHALLENGE_SIZE
Challenge nonce size (32 bytes)
#define ARGON2ID_SALT_SIZE
Argon2id salt size in bytes.
uint8_t hmac_size
HMAC size in bytes (e.g., 32 for HMAC-SHA256)
Definition packet.h:895
uint16_t auth_public_key_size
Authentication public key size in bytes (e.g., 32 for Ed25519, 1952 for Dilithium3)
Definition packet.h:885
uint16_t signature_size
Signature size in bytes (e.g., 64 for Ed25519, 3309 for Dilithium3)
Definition packet.h:887
uint8_t nonce_size
Nonce size in bytes (e.g., 24 for XSalsa20)
Definition packet.h:891
uint8_t mac_size
MAC size in bytes (e.g., 16 for Poly1305)
Definition packet.h:893
uint16_t shared_secret_size
Shared secret size in bytes (e.g., 32 for X25519)
Definition packet.h:889
uint16_t kex_public_key_size
Key exchange public key size in bytes (e.g., 32 for X25519, 1568 for Kyber1024)
Definition packet.h:883

References ARGON2ID_SALT_SIZE, ASCIICHAT_OK, AUTH_CHALLENGE_SIZE, crypto_context_t::auth_challenge_size, crypto_context_t::auth_public_key_size, crypto_parameters_packet_t::auth_public_key_size, crypto_handshake_context_t::crypto_ctx, crypto_context_t::encryption_key_size, ERROR_INVALID_PARAM, crypto_context_t::hmac_size, crypto_parameters_packet_t::hmac_size, crypto_handshake_context_t::is_server, crypto_parameters_packet_t::kex_public_key_size, log_debug, crypto_context_t::mac_size, crypto_parameters_packet_t::mac_size, NET_TO_HOST_U16, crypto_context_t::nonce_size, crypto_parameters_packet_t::nonce_size, crypto_context_t::private_key_size, crypto_context_t::public_key_size, crypto_context_t::salt_size, SET_ERRNO, crypto_context_t::shared_key_size, crypto_parameters_packet_t::shared_secret_size, crypto_context_t::signature_size, and crypto_parameters_packet_t::signature_size.

Referenced by client_crypto_handshake(), and server_crypto_handshake().

◆ crypto_handshake_should_rekey()

bool crypto_handshake_should_rekey ( const crypto_handshake_context_t ctx)

Check if rekeying should be triggered for this handshake context.

Check if rekeying should be triggered for this handshake context. Wrapper around crypto_should_rekey() for handshake context.

Definition at line 613 of file crypto/handshake/common.c.

613 {
614 if (!ctx || !crypto_handshake_is_ready(ctx)) {
615 return false;
616 }
617 return crypto_should_rekey(&ctx->crypto_ctx);
618}
bool crypto_should_rekey(const crypto_context_t *ctx)
Check if rekeying should be triggered based on time or packet count thresholds.

References crypto_handshake_context_t::crypto_ctx, crypto_handshake_is_ready(), and crypto_should_rekey().

Referenced by client_send_thread_func(), and crypto_client_should_rekey().

◆ crypto_handshake_validate_packet_size()

asciichat_error_t crypto_handshake_validate_packet_size ( const crypto_handshake_context_t ctx,
uint16_t  packet_type,
size_t  packet_size 
)

Validate crypto packet size based on session parameters.

Parameters
ctxHandshake context (must have parameters set)
packet_typePacket type to validate
packet_sizeActual packet size received
Returns
ASCIICHAT_OK if valid, error code on failure

Definition at line 92 of file crypto/handshake/common.c.

93 {
94 if (!ctx) {
95 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters: ctx=%p", ctx);
96 }
97
98 switch (packet_type) {
100 if (packet_size != sizeof(crypto_capabilities_packet_t)) {
101 // Don't return an error code, just set the errno and return the error code
102 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid crypto capabilities packet size: %zu (expected %zu)",
103 packet_size, sizeof(crypto_capabilities_packet_t));
104 }
105 break;
106
108 if (packet_size != sizeof(crypto_parameters_packet_t)) {
109 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid crypto parameters packet size: %zu (expected %zu)", packet_size,
111 }
112 break;
113
115 // Server can send either:
116 // 1. Simple format: kex_public_key_size (when server has no identity key)
117 // 2. Authenticated format: kex_public_key_size + auth_public_key_size + signature_size
118 {
119 size_t simple_size = ctx->crypto_ctx.public_key_size;
120 size_t authenticated_size =
122
123 if (packet_size != simple_size && packet_size != authenticated_size) {
125 "Invalid KEY_EXCHANGE_INIT size: %zu (expected %zu for simple or %zu for authenticated: "
126 "kex=%u + auth=%u + sig=%u)",
127 packet_size, simple_size, authenticated_size, ctx->crypto_ctx.public_key_size,
129 }
130 }
131 break;
132
134 // Client can send either:
135 // 1. Simple format: kex_public_key_size (when server has no identity key)
136 // 2. Authenticated format: kex_public_key_size + client_auth_key_size + client_sig_size + [gpg_key_id_len:1] +
137 // [gpg_key_id:0-16]
138 {
139 size_t simple_size = ctx->crypto_ctx.public_key_size;
140 // For authenticated format, use Ed25519 sizes since client has Ed25519 key
141 size_t ed25519_auth_size = ED25519_PUBLIC_KEY_SIZE; // Ed25519 public key is always 32 bytes
142 size_t ed25519_sig_size = ED25519_SIGNATURE_SIZE; // Ed25519 signature is always 64 bytes
143 size_t authenticated_min_size = ctx->crypto_ctx.public_key_size + ed25519_auth_size + ed25519_sig_size;
144 size_t authenticated_max_size = authenticated_min_size + 1 + 40; // +1 for length, +40 for max GPG key ID
145
146 if (packet_size != simple_size &&
147 (packet_size < authenticated_min_size || packet_size > authenticated_max_size)) {
149 "Invalid KEY_EXCHANGE_RESP size: %zu (expected %zu for simple or %zu-%zu for authenticated: "
150 "kex=%u + auth=%u + sig=%u + optional GPG key ID)",
151 packet_size, simple_size, authenticated_min_size, authenticated_max_size,
152 ctx->crypto_ctx.public_key_size, ed25519_auth_size, ed25519_sig_size);
153 }
154 }
155 break;
156
158 // Server sends: 1 byte auth_flags + auth_challenge_size byte nonce
159 {
160 size_t expected_size = AUTH_CHALLENGE_FLAGS_SIZE + ctx->crypto_ctx.auth_challenge_size;
161 if (packet_size != expected_size) {
162 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid AUTH_CHALLENGE size: %zu (expected %zu: flags=%d + nonce=%u)",
163 packet_size, expected_size, AUTH_CHALLENGE_FLAGS_SIZE, ctx->crypto_ctx.auth_challenge_size);
164 }
165 }
166 break;
167
169 // Client sends: hmac_size + auth_challenge_size bytes client_nonce + [gpg_key_id_len:1] + [gpg_key_id:0-40]
170 {
171 size_t min_size = ctx->crypto_ctx.hmac_size + ctx->crypto_ctx.auth_challenge_size;
172 size_t max_size = min_size + 1 + 40; // +1 for length, +40 for max GPG key ID
173 if (packet_size < min_size || packet_size > max_size) {
175 "Invalid AUTH_RESPONSE size: %zu (expected %zu-%zu: hmac=%u + "
176 "nonce=%u + optional GPG key ID)",
177 packet_size, min_size, max_size, ctx->crypto_ctx.hmac_size,
179 }
180 }
181 break;
182
184 // Variable size - just check reasonable limits
185 if (packet_size > MAX_AUTH_FAILED_PACKET_SIZE) {
186 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid AUTH_FAILED size: %zu (max %d)", packet_size,
188 }
189 break;
190
192 // Server sends: hmac_size bytes
193 if (packet_size != ctx->crypto_ctx.hmac_size) {
194 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid SERVER_AUTH_RESP size: %zu (expected %u)", packet_size,
195 ctx->crypto_ctx.hmac_size);
196 }
197 break;
198
200 // Empty packet
201 if (packet_size != 0) {
202 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid HANDSHAKE_COMPLETE size: %zu (expected 0)", packet_size);
203 }
204 break;
205
207 // Empty packet
208 if (packet_size != 0) {
209 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid NO_ENCRYPTION size: %zu (expected 0)", packet_size);
210 }
211 break;
212
214 // Variable size - check reasonable limits
215 if (packet_size > MAX_ENCRYPTED_PACKET_SIZE) { // 64KB max for encrypted packets
216 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid ENCRYPTED size: %zu (max %d)", packet_size,
218 }
219 break;
220
221 default:
222 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Unknown crypto packet type: %u", packet_type);
223 }
224
225 return ASCIICHAT_OK;
226}
#define ED25519_SIGNATURE_SIZE
Ed25519 signature size in bytes.
#define MAX_AUTH_FAILED_PACKET_SIZE
Maximum AUTH_FAILED packet size (256 bytes)
#define MAX_ENCRYPTED_PACKET_SIZE
Maximum encrypted packet size (64KB)
#define ED25519_PUBLIC_KEY_SIZE
Ed25519 public key size in bytes.
#define AUTH_CHALLENGE_FLAGS_SIZE
Authentication flags size (1 byte)
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:73
@ PACKET_TYPE_CRYPTO_AUTH_RESPONSE
Client -> Server: {HMAC[32]} (UNENCRYPTED)
Definition packet.h:323
@ PACKET_TYPE_CRYPTO_HANDSHAKE_COMPLETE
Server -> Client: "encryption ready" (UNENCRYPTED)
Definition packet.h:329
@ PACKET_TYPE_CRYPTO_KEY_EXCHANGE_INIT
Server -> Client: {server_pubkey[32]} (UNENCRYPTED)
Definition packet.h:317
@ PACKET_TYPE_CRYPTO_KEY_EXCHANGE_RESP
Client -> Server: {client_pubkey[32]} (UNENCRYPTED)
Definition packet.h:319
@ PACKET_TYPE_CRYPTO_AUTH_FAILED
Server -> Client: "authentication failed" (UNENCRYPTED)
Definition packet.h:325
@ PACKET_TYPE_ENCRYPTED
Encrypted packet (after handshake completion)
Definition packet.h:333
@ PACKET_TYPE_CRYPTO_SERVER_AUTH_RESP
Server -> Client: {HMAC[32]} server proves knowledge (UNENCRYPTED)
Definition packet.h:327
@ PACKET_TYPE_CRYPTO_NO_ENCRYPTION
Client -> Server: "I want to proceed without encryption" (UNENCRYPTED)
Definition packet.h:331
@ PACKET_TYPE_CRYPTO_AUTH_CHALLENGE
Server -> Client: {nonce[32]} (UNENCRYPTED)
Definition packet.h:321
@ PACKET_TYPE_CRYPTO_PARAMETERS
Server -> Client: Chosen algorithms + data sizes (UNENCRYPTED)
Definition packet.h:315
@ PACKET_TYPE_CRYPTO_CAPABILITIES
Client -> Server: Supported crypto algorithms (UNENCRYPTED)
Definition packet.h:313
Crypto capabilities packet structure (Packet Type 14)
Definition packet.h:844
Crypto parameters packet structure (Packet Type 15)
Definition packet.h:873

References ASCIICHAT_OK, AUTH_CHALLENGE_FLAGS_SIZE, crypto_context_t::auth_challenge_size, crypto_context_t::auth_public_key_size, crypto_handshake_context_t::crypto_ctx, ED25519_PUBLIC_KEY_SIZE, ED25519_SIGNATURE_SIZE, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, crypto_context_t::hmac_size, MAX_AUTH_FAILED_PACKET_SIZE, MAX_ENCRYPTED_PACKET_SIZE, PACKET_TYPE_CRYPTO_AUTH_CHALLENGE, PACKET_TYPE_CRYPTO_AUTH_FAILED, PACKET_TYPE_CRYPTO_AUTH_RESPONSE, PACKET_TYPE_CRYPTO_CAPABILITIES, PACKET_TYPE_CRYPTO_HANDSHAKE_COMPLETE, PACKET_TYPE_CRYPTO_KEY_EXCHANGE_INIT, PACKET_TYPE_CRYPTO_KEY_EXCHANGE_RESP, PACKET_TYPE_CRYPTO_NO_ENCRYPTION, PACKET_TYPE_CRYPTO_PARAMETERS, PACKET_TYPE_CRYPTO_SERVER_AUTH_RESP, PACKET_TYPE_ENCRYPTED, crypto_context_t::public_key_size, SET_ERRNO, and crypto_context_t::signature_size.

Referenced by crypto_handshake_client_auth_response(), crypto_handshake_client_key_exchange(), crypto_handshake_server_auth_challenge(), and crypto_handshake_server_complete().