ascii-chat 0.11.33
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
61#include <stdbool.h>
62#include <stddef.h>
63#include <stdint.h>
64
65// libsodium includes
66#include <sodium.h>
67
68// Include required types
69#include "key_types.h" // For private_key_t
70#include "../common.h" // For asciichat_error_t
71#include "../util/time.h" // For NS_PER_SEC_INT
72
79#define MIN_PASSWORD_LENGTH 8
81#define MAX_PASSWORD_LENGTH 256
82
91#define X25519_KEY_SIZE 32
93#define ED25519_PUBLIC_KEY_SIZE 32
95#define ED25519_PRIVATE_KEY_SIZE 64
97#define ED25519_SIGNATURE_SIZE 64
99#define XSALSA20_NONCE_SIZE 24
101#define POLY1305_MAC_SIZE 16
103#define HMAC_SHA256_SIZE 32
105#define ARGON2ID_SALT_SIZE 32
107#define SECRETBOX_KEY_SIZE 32
109#define AES256_KEY_SIZE 32
111#define AES_IV_SIZE 16
113#define AES256_DERIVED_SIZE (AES256_KEY_SIZE + AES_IV_SIZE)
115#define SESSION_ID_SIZE 16
116
127#define CRYPTO_PUBLIC_KEY_SIZE X25519_KEY_SIZE
129#define CRYPTO_PRIVATE_KEY_SIZE X25519_KEY_SIZE
131#define CRYPTO_SHARED_KEY_SIZE X25519_KEY_SIZE
133#define CRYPTO_ED25519_PUBLIC_KEY_SIZE ED25519_PUBLIC_KEY_SIZE
135#define CRYPTO_ED25519_PRIVATE_KEY_SIZE ED25519_PRIVATE_KEY_SIZE
137#define CRYPTO_ED25519_SIGNATURE_SIZE ED25519_SIGNATURE_SIZE
139#define CRYPTO_NONCE_SIZE XSALSA20_NONCE_SIZE
141#define CRYPTO_SALT_SIZE ARGON2ID_SALT_SIZE
143#define CRYPTO_ENCRYPTION_KEY_SIZE SECRETBOX_KEY_SIZE
145#define CRYPTO_MAC_SIZE POLY1305_MAC_SIZE
147#define CRYPTO_HMAC_SIZE HMAC_SHA256_SIZE
148
157#define AUTH_HMAC_SIZE 32
159#define AUTH_CHALLENGE_SIZE 32
161#define AUTH_COMBINED_SIZE (AUTH_HMAC_SIZE + AUTH_CHALLENGE_SIZE)
163#define AUTH_SIGNATURE_SIZE 64
165#define AUTH_SIGNATURE_COMBINED_SIZE (AUTH_SIGNATURE_SIZE + AUTH_CHALLENGE_SIZE)
166
175#define AUTH_CHALLENGE_FLAGS_SIZE 1
177#define AUTH_CHALLENGE_PACKET_SIZE (AUTH_CHALLENGE_FLAGS_SIZE + AUTH_CHALLENGE_SIZE)
178
187#define AUTH_RESPONSE_PASSWORD_SIZE (AUTH_HMAC_SIZE + AUTH_CHALLENGE_SIZE)
189#define AUTH_RESPONSE_SIGNATURE_SIZE (AUTH_SIGNATURE_SIZE + AUTH_CHALLENGE_SIZE)
190
194#define SERVER_AUTH_RESPONSE_SIZE AUTH_HMAC_SIZE
195
202#define MAX_AUTH_FAILED_PACKET_SIZE 256
204#define MAX_ENCRYPTED_PACKET_SIZE 65536
205
214#define HEX_STRING_SIZE_32 (32 * 2 + 1)
216#define HEX_STRING_SIZE_64 (64 * 2 + 1)
218#define PASSWORD_BUFFER_SIZE 256
220#define ZERO_KEY_SIZE X25519_KEY_SIZE
221
230#define CRYPTO_MAX_PLAINTEXT_SIZE ((size_t)1024 * 1024)
232#define CRYPTO_MAX_CIPHERTEXT_SIZE (CRYPTO_MAX_PLAINTEXT_SIZE + CRYPTO_MAC_SIZE)
233
325
349
350// =============================================================================
351// SSH Key Structure Constants
352// =============================================================================
353
354// SSH key blob structure sizes
355#define SSH_KEY_TYPE_LENGTH_SIZE 4 // Length of "ssh-ed25519" (4 bytes)
356#define SSH_KEY_TYPE_STRING_SIZE 11 // "ssh-ed25519" string length
357#define SSH_KEY_PUBLIC_KEY_LENGTH_SIZE 4 // Length of public key (4 bytes)
358#define SSH_KEY_PUBLIC_KEY_SIZE 32 // Ed25519 public key size
359#define SSH_KEY_HEADER_SIZE \
360 (SSH_KEY_TYPE_LENGTH_SIZE + SSH_KEY_TYPE_STRING_SIZE + SSH_KEY_PUBLIC_KEY_LENGTH_SIZE + SSH_KEY_PUBLIC_KEY_SIZE)
361
362// =============================================================================
363// Cryptographic Key Size Constants
364// =============================================================================
365
373#define CRYPTO_KEY_SIZE 32
374
382#define CRYPTO_FINGERPRINT_SIZE 32
383
384// =============================================================================
385// Hex String Size Constants
386// =============================================================================
387
394#define CRYPTO_HEX_KEY_SIZE 64
396#define CRYPTO_HEX_KEY_SIZE_NULL 65
398#define CRYPTO_HEX_KEY64_SIZE 128
400#define CRYPTO_HEX_KEY64_SIZE_NULL 129
401
404// =============================================================================
405// String Literal Constants
406// =============================================================================
407
414#define SSH_ED25519_KEY_TYPE "ssh-ed25519"
416#define X25519_KEY_TYPE "x25519"
418#define NO_IDENTITY_MARKER "no-identity"
419
422// =============================================================================
423// File Permission Constants
424// =============================================================================
425
426#ifndef _WIN32
427#define SSH_KEY_PERMISSIONS_MASK (S_IRWXG | S_IRWXO) // Group and other permissions mask
428#define SSH_KEY_RECOMMENDED_PERMISSIONS 0600 // Recommended SSH key permissions
429#endif
430
431// =============================================================================
432// String and Display Constants
433// =============================================================================
434
435#define MAX_COMMENT_LEN 256 // Maximum key comment length
436#define MAX_GPG_KEYGRIP_LEN 64 // Maximum GPG keygrip length
437
460
475
488
500
523
539
550bool crypto_is_ready(const crypto_context_t *ctx);
551
575crypto_result_t crypto_validate_password(const char *password);
576
601
617bool crypto_verify_password(const crypto_context_t *ctx, const char *password);
618
638 uint8_t encryption_key[CRYPTO_ENCRYPTION_KEY_SIZE]);
639
682crypto_result_t crypto_encrypt(crypto_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len,
683 uint8_t *ciphertext_out, size_t ciphertext_out_size, size_t *ciphertext_len_out);
684
713crypto_result_t crypto_decrypt(crypto_context_t *ctx, const uint8_t *ciphertext, size_t ciphertext_len,
714 uint8_t *plaintext_out, size_t plaintext_out_size, size_t *plaintext_len_out);
715
733const char *crypto_result_to_string(crypto_result_t result);
734
753void crypto_get_status(const crypto_context_t *ctx, char *status_buffer, size_t buffer_size);
754
772bool crypto_secure_compare(const uint8_t *lhs, const uint8_t *rhs, size_t len);
773
789crypto_result_t crypto_random_bytes(uint8_t *buffer, size_t len);
790
814
830crypto_result_t crypto_compute_hmac(crypto_context_t *ctx, const uint8_t key[32], const uint8_t data[32],
831 uint8_t hmac[32]);
832
849crypto_result_t crypto_compute_hmac_ex(const crypto_context_t *ctx, const uint8_t key[32], const uint8_t *data,
850 size_t data_len, uint8_t hmac[32]);
851
866bool crypto_verify_hmac(const uint8_t key[32], const uint8_t data[32], const uint8_t expected_hmac[32]);
867
883bool crypto_verify_hmac_ex(const uint8_t key[32], const uint8_t *data, size_t data_len,
884 const uint8_t expected_hmac[32]);
885
888// =============================================================================
889// High-level authentication helpers (shared between client and server)
890// =============================================================================
891
924 uint8_t hmac_out[32]);
925
945bool crypto_verify_auth_response(const crypto_context_t *ctx, const uint8_t nonce[32], const uint8_t expected_hmac[32]);
946
966crypto_result_t crypto_create_auth_challenge(const crypto_context_t *ctx, uint8_t *packet_out, size_t packet_size,
967 size_t *packet_len_out);
968
987crypto_result_t crypto_process_auth_challenge(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len);
988
1007crypto_result_t crypto_process_auth_response(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len);
1008
1037crypto_result_t crypto_create_public_key_packet(const crypto_context_t *ctx, uint8_t *packet_out, size_t packet_size,
1038 size_t *packet_len_out);
1039
1058crypto_result_t crypto_process_public_key_packet(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len);
1059
1085 uint8_t *packet_out, size_t packet_size, size_t *packet_len_out);
1086
1110crypto_result_t crypto_process_encrypted_packet(crypto_context_t *ctx, const uint8_t *packet, size_t packet_len,
1111 uint8_t *data_out, size_t data_size, size_t *data_len_out);
1112
1141asciichat_error_t crypto_compute_password_hmac(crypto_context_t *ctx, const uint8_t *password_key, const uint8_t *nonce,
1142 const uint8_t *shared_secret, uint8_t *hmac_out);
1143
1162asciichat_error_t crypto_verify_peer_signature(const uint8_t *peer_public_key, const uint8_t *ephemeral_key,
1163 size_t ephemeral_key_size, const uint8_t *signature);
1164
1183asciichat_error_t crypto_sign_ephemeral_key(const private_key_t *private_key, const uint8_t *ephemeral_key,
1184 size_t ephemeral_key_size, uint8_t *signature_out);
1185
1199void crypto_combine_auth_data(const uint8_t *hmac, const uint8_t *challenge_nonce, uint8_t *combined_out);
1200
1214void crypto_extract_auth_data(const uint8_t *combined_data, uint8_t *hmac_out, uint8_t *challenge_out);
1215
1240#define REKEY_MIN_INTERVAL (3LL * NS_PER_SEC_INT)
1242#define REKEY_DEFAULT_TIME_THRESHOLD (3600LL * NS_PER_SEC_INT)
1244#define REKEY_DEFAULT_PACKET_THRESHOLD 1000000
1246#define REKEY_TEST_TIME_THRESHOLD (30LL * NS_PER_SEC_INT)
1248#define REKEY_TEST_PACKET_THRESHOLD 1000
1250#define REKEY_MAX_FAILURE_COUNT 10
1252#define REKEY_MIN_REQUEST_INTERVAL (60LL * NS_PER_SEC_INT)
1253
1272bool crypto_should_rekey(const crypto_context_t *ctx);
1273
1292
1310
1327
1345
1360
1378void crypto_get_rekey_status(const crypto_context_t *ctx, char *status_buffer, size_t buffer_size);
1379
/* Session Rekeying Protocol */
1381
/* crypto */
int buffer_size
Size of circular buffer.
Definition grep.c:90
unsigned short uint16_t
Definition common.h:57
unsigned long long uint64_t
Definition common.h:59
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.
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.
#define AUTH_CHALLENGE_SIZE
Challenge nonce size (32 bytes)
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.
#define CRYPTO_HMAC_SIZE
HMAC size (HMAC-SHA256)
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.
#define CRYPTO_PRIVATE_KEY_SIZE
Private key size (X25519)
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.
#define CRYPTO_ENCRYPTION_KEY_SIZE
Encryption key size (XSalsa20-Poly1305)
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.
#define CRYPTO_SHARED_KEY_SIZE
Shared key size (X25519)
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.
#define CRYPTO_SALT_SIZE
Salt size (Argon2id)
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)
#define CRYPTO_PUBLIC_KEY_SIZE
Public key size (X25519)
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:49
ClangTool/LibTooling compatibility shim for stdbool.h.
Cryptographic context structure.
Private key structure (for server –ssh-key)
Definition key_types.h:91