ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
include/ascii-chat/crypto/crypto.h
Go to the documentation of this file.
1#pragma once
2
60
62#include <stdbool.h>
63#include <stddef.h>
64#include <stdint.h>
65
66// libsodium includes
67#include <sodium.h>
68
69// Include required types
70#include "sizes.h"
71#include "key_types.h" // For private_key_t
72#include "../common.h" // For asciichat_error_t
73#include "../util/time.h" // For NS_PER_SEC_INT
74
79
81#define CRYPTO_MAX_PLAINTEXT_SIZE ((size_t)1024 * 1024)
83#define CRYPTO_MAX_CIPHERTEXT_SIZE (CRYPTO_MAX_PLAINTEXT_SIZE + CRYPTO_MAC_SIZE)
84
86
126typedef struct crypto_context_t {
132
136
143
151
159
163
167
174
180
184
189
195
197
221
222// =============================================================================
223// SSH Key Structure Constants
224// =============================================================================
225
226// SSH key blob structure sizes
227#define SSH_KEY_TYPE_LENGTH_SIZE 4 // Length of "ssh-ed25519" (4 bytes)
228#define SSH_KEY_TYPE_STRING_SIZE 11 // "ssh-ed25519" string length
229#define SSH_KEY_PUBLIC_KEY_LENGTH_SIZE 4 // Length of public key (4 bytes)
230#define SSH_KEY_PUBLIC_KEY_SIZE 32 // Ed25519 public key size
231#define SSH_KEY_HEADER_SIZE \
232 (SSH_KEY_TYPE_LENGTH_SIZE + SSH_KEY_TYPE_STRING_SIZE + SSH_KEY_PUBLIC_KEY_LENGTH_SIZE + SSH_KEY_PUBLIC_KEY_SIZE)
233
234// =============================================================================
235// Cryptographic Key Size Constants
236// =============================================================================
237
245#define CRYPTO_KEY_SIZE 32
246
254#define CRYPTO_FINGERPRINT_SIZE 32
255
256// =============================================================================
257// Hex String Size Constants
258// =============================================================================
259
264
266#define CRYPTO_HEX_KEY_SIZE 64
268#define CRYPTO_HEX_KEY_SIZE_NULL 65
270#define CRYPTO_HEX_KEY64_SIZE 128
272#define CRYPTO_HEX_KEY64_SIZE_NULL 129
273
275
276// =============================================================================
277// String Literal Constants
278// =============================================================================
279
284
286#define SSH_ED25519_KEY_TYPE "ssh-ed25519"
288#define X25519_KEY_TYPE "x25519"
290#define NO_IDENTITY_MARKER "no-identity"
291
293
294// =============================================================================
295// File Permission Constants
296// =============================================================================
297
298#ifndef _WIN32
299#define SSH_KEY_PERMISSIONS_MASK (S_IRWXG | S_IRWXO) // Group and other permissions mask
300#define SSH_KEY_RECOMMENDED_PERMISSIONS 0600 // Recommended SSH key permissions
301#endif
302
303// =============================================================================
304// String and Display Constants
305// =============================================================================
306
311
329
344
357
369
371
379
392
408
419bool crypto_is_ready(const crypto_context_t *ctx);
420
422
431
444crypto_result_t crypto_validate_password(const char *password);
445
470
486bool crypto_verify_password(const crypto_context_t *ctx, const char *password);
487
507 uint8_t encryption_key[CRYPTO_ENCRYPTION_KEY_SIZE]);
508
516
551crypto_result_t crypto_encrypt(crypto_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len,
552 uint8_t *ciphertext_out, size_t ciphertext_out_size, size_t *ciphertext_len_out);
553
582crypto_result_t crypto_decrypt(crypto_context_t *ctx, const uint8_t *ciphertext, size_t ciphertext_len,
583 uint8_t *plaintext_out, size_t plaintext_out_size, size_t *plaintext_len_out);
584
586
591
602const char *crypto_result_to_string(crypto_result_t result);
603
622void crypto_get_status(const crypto_context_t *ctx, char *status_buffer, size_t buffer_size);
623
641bool crypto_secure_compare(const uint8_t *lhs, const uint8_t *rhs, size_t len);
642
658crypto_result_t crypto_random_bytes(uint8_t *buffer, size_t len);
659
661
669
683
701
719 const uint8_t *data, size_t data_len, uint8_t hmac[HMAC_SHA256_SIZE]);
720
736 const uint8_t expected_hmac[HMAC_SHA256_SIZE]);
737
753bool crypto_verify_hmac_ex(const uint8_t key[HMAC_SHA256_KEY_SIZE], const uint8_t *data, size_t data_len,
754 const uint8_t expected_hmac[HMAC_SHA256_SIZE]);
755
757
758// =============================================================================
759// High-level authentication helpers (shared between client and server)
760// =============================================================================
761
769
794 uint8_t hmac_out[HMAC_SHA256_SIZE]);
795
816 const uint8_t expected_hmac[HMAC_SHA256_SIZE]);
817
837crypto_result_t crypto_create_auth_challenge(const crypto_context_t *ctx, uint8_t *packet_out, size_t packet_size,
838 size_t *packet_len_out);
839
858crypto_result_t crypto_process_auth_challenge(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len);
859
878crypto_result_t crypto_process_auth_response(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len);
879
881
889
908crypto_result_t crypto_create_public_key_packet(const crypto_context_t *ctx, uint8_t *packet_out, size_t packet_size,
909 size_t *packet_len_out);
910
929crypto_result_t crypto_process_public_key_packet(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len);
930
956 uint8_t *packet_out, size_t packet_size, size_t *packet_len_out);
957
981crypto_result_t crypto_process_encrypted_packet(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len,
982 uint8_t *data_out, size_t data_size, size_t *data_len_out);
983
985
993
1012asciichat_error_t crypto_compute_password_hmac(crypto_context_t *ctx, const uint8_t *password_key, const uint8_t *nonce,
1013 const uint8_t *shared_secret, uint8_t *hmac_out);
1014
1033asciichat_error_t crypto_verify_peer_signature(const uint8_t *peer_public_key, const uint8_t *ephemeral_key,
1034 size_t ephemeral_key_size, const uint8_t *signature);
1035
1054asciichat_error_t crypto_sign_ephemeral_key(const private_key_t *private_key, const uint8_t *ephemeral_key,
1055 size_t ephemeral_key_size, uint8_t *signature_out);
1056
1070void crypto_combine_auth_data(const uint8_t *hmac, const uint8_t *challenge_nonce, uint8_t *combined_out);
1071
1085void crypto_extract_auth_data(const uint8_t *combined_data, uint8_t *hmac_out, uint8_t *challenge_out);
1086
1088
1109
1111#define REKEY_MIN_INTERVAL (3LL * NS_PER_SEC_INT)
1113#define REKEY_DEFAULT_TIME_THRESHOLD (3600LL * NS_PER_SEC_INT)
1115#define REKEY_DEFAULT_PACKET_THRESHOLD 1000000
1117#define REKEY_TEST_TIME_THRESHOLD (30LL * NS_PER_SEC_INT)
1119#define REKEY_TEST_PACKET_THRESHOLD 1000
1121#define REKEY_MAX_FAILURE_COUNT 10
1123#define REKEY_MIN_REQUEST_INTERVAL (60LL * NS_PER_SEC_INT)
1124
1143bool crypto_should_rekey(const crypto_context_t *ctx);
1144
1163
1181
1198
1216
1231
1249void crypto_get_rekey_status(const crypto_context_t *ctx, char *status_buffer, size_t buffer_size);
1250 /* Session Rekeying Protocol */
1252 /* crypto */
⚙️ Common definitions, error codes, macros, and types shared throughout the application
int buffer_size
Size of circular buffer.
Definition grep.c:68
unsigned short uint16_t
Definition common.h:61
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
crypto_result_t crypto_rekey_commit(crypto_context_t *ctx)
Commit to new keys after successful REKEY_COMPLETE.
crypto_result_t crypto_create_auth_challenge(const crypto_context_t *ctx, uint8_t *packet_out, size_t packet_size, size_t *packet_len_out)
Create authentication challenge packet.
crypto_result_t crypto_process_public_key_packet(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len)
Process received public key packet from peer.
crypto_result_t crypto_compute_hmac_ex(const crypto_context_t *ctx, const uint8_t key[32], const uint8_t *data, size_t data_len, uint8_t hmac[32])
Compute HMAC-SHA256 for variable-length data.
crypto_result_t crypto_set_peer_public_key(crypto_context_t *ctx, const uint8_t *peer_public_key)
Set peer's public key and compute shared secret (step 2 of handshake).
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.
crypto_result_t crypto_compute_auth_response(const crypto_context_t *ctx, const uint8_t nonce[32], uint8_t hmac_out[32])
Compute authentication response HMAC bound to DH shared_secret.
crypto_result_t crypto_init(crypto_context_t *ctx)
Initialize libsodium and crypto context.
crypto_result_t crypto_generate_nonce(uint8_t nonce[32])
Generate random nonce for authentication.
asciichat_error_t crypto_compute_password_hmac(crypto_context_t *ctx, const uint8_t *password_key, const uint8_t *nonce, const uint8_t *shared_secret, uint8_t *hmac_out)
Compute password-based HMAC for authentication.
const char * crypto_result_to_string(crypto_result_t result)
Convert crypto result to human-readable string.
crypto_result_t
Cryptographic operation result codes.
asciichat_error_t crypto_verify_peer_signature(const uint8_t *peer_public_key, const uint8_t *ephemeral_key, size_t ephemeral_key_size, const uint8_t *signature)
Verify peer's signature on ephemeral key.
bool crypto_verify_hmac_ex(const uint8_t key[32], const uint8_t *data, size_t data_len, const uint8_t expected_hmac[32])
Verify HMAC-SHA256 for variable-length data.
bool crypto_verify_password(const crypto_context_t *ctx, const char *password)
Verify password matches stored salt/key.
crypto_result_t crypto_get_public_key(const crypto_context_t *ctx, uint8_t *public_key_out)
Get public key for sending to peer (step 1 of handshake).
crypto_result_t crypto_create_encrypted_packet(crypto_context_t *ctx, const uint8_t *data, size_t data_len, uint8_t *packet_out, size_t packet_size, size_t *packet_len_out)
Create encrypted data packet for network transmission.
void crypto_get_rekey_status(const crypto_context_t *ctx, char *status_buffer, size_t buffer_size)
Get the current rekeying state for debugging/logging.
bool crypto_should_rekey(const crypto_context_t *ctx)
Check if rekeying should be triggered based on time or packet count thresholds.
crypto_result_t crypto_process_auth_response(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len)
Process authentication response packet.
crypto_result_t crypto_generate_keypair(crypto_context_t *ctx)
Generate new X25519 key pair for key exchange.
void crypto_combine_auth_data(const uint8_t *hmac, const uint8_t *challenge_nonce, uint8_t *combined_out)
Combine HMAC and challenge nonce for transmission.
bool crypto_verify_hmac(const uint8_t key[32], const uint8_t data[32], const uint8_t expected_hmac[32])
Verify HMAC-SHA256 for fixed 32-byte data.
crypto_result_t crypto_process_auth_challenge(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len)
Process authentication challenge packet.
void crypto_extract_auth_data(const uint8_t *combined_data, uint8_t *hmac_out, uint8_t *challenge_out)
Extract HMAC and challenge nonce from combined data.
void crypto_get_status(const crypto_context_t *ctx, char *status_buffer, size_t buffer_size)
Get crypto context status information for debugging.
void crypto_rekey_abort(crypto_context_t *ctx)
Abort rekeying and fallback to old keys.
bool crypto_is_ready(const crypto_context_t *ctx)
Check if key exchange is complete and ready for encryption.
crypto_result_t crypto_validate_password(const char *password)
Validate password length requirements.
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).
asciichat_error_t crypto_sign_ephemeral_key(const private_key_t *private_key, const uint8_t *ephemeral_key, size_t ephemeral_key_size, uint8_t *signature_out)
Sign ephemeral key with private key.
bool crypto_secure_compare(const uint8_t *lhs, const uint8_t *rhs, size_t len)
Secure constant-time comparison of byte arrays.
crypto_result_t crypto_compute_hmac(crypto_context_t *ctx, const uint8_t key[32], const uint8_t data[32], uint8_t hmac[32])
Compute HMAC-SHA256 for fixed 32-byte data.
crypto_result_t crypto_derive_password_key(crypto_context_t *ctx, const char *password)
Derive key from password using Argon2id.
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_result_t crypto_derive_password_encryption_key(const char *password, uint8_t encryption_key[32])
Derive deterministic encryption key from password for handshake.
crypto_result_t crypto_init_with_password(crypto_context_t *ctx, const char *password)
Initialize with password-based encryption.
crypto_result_t crypto_create_public_key_packet(const crypto_context_t *ctx, uint8_t *packet_out, size_t packet_size, size_t *packet_len_out)
Create public key packet for network transmission.
void crypto_destroy(crypto_context_t *ctx)
Cleanup crypto context with secure memory wiping.
crypto_result_t crypto_rekey_init(crypto_context_t *ctx)
Initiate rekeying by generating new ephemeral keys.
crypto_result_t crypto_random_bytes(uint8_t *buffer, size_t len)
Generate cryptographically secure random bytes.
crypto_result_t crypto_process_encrypted_packet(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len, uint8_t *data_out, size_t data_size, size_t *data_len_out)
Process received encrypted packet from peer.
bool crypto_verify_auth_response(const crypto_context_t *ctx, const uint8_t nonce[32], const uint8_t expected_hmac[32])
Verify authentication response HMAC bound to DH shared_secret.
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).
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
#define SESSION_ID_SIZE
#define HMAC_SHA256_KEY_SIZE
Definition sizes.h:45
#define AUTH_CHALLENGE_SIZE
Challenge nonce size (32 bytes).
Definition sizes.h:99
#define CRYPTO_HMAC_SIZE
HMAC size (HMAC-SHA256).
Definition sizes.h:87
#define HMAC_SHA256_SIZE
HMAC-SHA256 output size in bytes.
Definition sizes.h:43
#define CRYPTO_PRIVATE_KEY_SIZE
Private key size (X25519).
Definition sizes.h:69
#define CRYPTO_ENCRYPTION_KEY_SIZE
Encryption key size (XSalsa20-Poly1305).
Definition sizes.h:83
#define CRYPTO_SHARED_KEY_SIZE
Shared key size (X25519).
Definition sizes.h:71
#define CRYPTO_SALT_SIZE
Salt size (Argon2id).
Definition sizes.h:81
#define CRYPTO_PUBLIC_KEY_SIZE
Public key size (X25519).
Definition sizes.h:67
Endpoint cryptographic state for handshake, packet protection, authentication, and rekeying.
struct crypto_session * session
Endpoint cryptographic state for handshake, packet protection, authentication, and rekeying.
For crypto session, this is the live record that ties owner, mutex, records, rotation together....
Private identity-key material used for server authentication and signing.
Definition key_types.h:97
⏱️ High-precision timing utilities using sokol_time.h and uthash