ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
peer_crypto.c File Reference

Go to the source code of this file.

Data Structures

struct  peer_output
 peer output is intentionally a small, concrete record. Fields such as next, data, length give callers the identity and current value they need. It is normally borrowed from, or owned by, the surrounding subsystem—not independently managed. More...
struct  browser_peer_crypto

Typedefs

typedef struct peer_output peer_output_t
 peer output is intentionally a small, concrete record. Fields such as next, data, length give callers the identity and current value they need. It is normally borrowed from, or owned by, the surrounding subsystem—not independently managed.

Functions

const char * peer_crypto_error (void)
void peer_crypto_output_pop (browser_peer_crypto_t *peer)
void peer_crypto_destroy (browser_peer_crypto_t *peer)
browser_peer_crypto_t * peer_crypto_create (bool server, int encryption, const char *password, const uint8_t *identity, const uint8_t *expected_key)
bool peer_crypto_ready (browser_peer_crypto_t *peer)
const void * peer_crypto_output_data (browser_peer_crypto_t *peer)
size_t peer_crypto_output_size (browser_peer_crypto_t *peer)
const void * peer_crypto_received_data (browser_peer_crypto_t *peer)
size_t peer_crypto_received_size (browser_peer_crypto_t *peer)
asciichat_error_t peer_crypto_send (browser_peer_crypto_t *peer, const void *data, size_t length)
asciichat_error_t peer_crypto_receive (browser_peer_crypto_t *peer, const void *data, size_t length)
crypto_context_t * peer_security_context (browser_peer_crypto_t *peer)
asciichat_error_t peer_crypto_tick (browser_peer_crypto_t *peer)
asciichat_error_t peer_crypto_quic_begin (browser_peer_crypto_t *peer)

Typedef Documentation

◆ peer_output_t

typedef struct peer_output peer_output_t

peer output is intentionally a small, concrete record. Fields such as next, data, length give callers the identity and current value they need. It is normally borrowed from, or owned by, the surrounding subsystem—not independently managed.

Function Documentation

◆ peer_crypto_create()

browser_peer_crypto_t * peer_crypto_create ( bool server,
int encryption,
const char * password,
const uint8_t * identity,
const uint8_t * expected_key )

Definition at line 105 of file peer_crypto.c.

106 {
107 browser_peer_crypto_t *peer = SAFE_CALLOC(1, sizeof(*peer), browser_peer_crypto_t *);
108 if (!peer) {
109 SET_ERRNO(ERROR_MEMORY, "Cannot allocate peer security state");
110 return NULL;
111 }
112 crypto_policy_t policy = {.transport_secure = true,
113 .encrypt = encryption == 1,
114 .no_encrypt = encryption == 0,
115 .has_password = password && password[0],
116 .has_identity = identity != NULL,
117 .has_verification_key = expected_key != NULL};
118 asciichat_error_t result = crypto_policy_resolve(&policy, &peer->security.mode);
120 peer->security.require_encryption = policy.encrypt;
122 if (result == ASCIICHAT_OK)
123 result = policy.has_password ? crypto_handshake_init_with_password("browser_peer", ctx, server, password)
124 : crypto_handshake_init("browser_peer", ctx, server);
125 if (result != ASCIICHAT_OK) {
127 return NULL;
128 }
129 if (identity) {
130 private_key_t *key = server ? &ctx->server_private_key : &ctx->client_private_key;
131 public_key_t *public_key = server ? &ctx->server_public_key : &ctx->client_public_key;
132 key->type = KEY_TYPE_ED25519;
133 memcpy(key->key.ed25519, identity, ED25519_PRIVATE_KEY_SIZE);
134 memcpy(key->public_key, identity + ED25519_SEED_SIZE, ED25519_PUBLIC_KEY_SIZE);
135 public_key->type = KEY_TYPE_ED25519;
136 memcpy(public_key->key, identity + ED25519_SEED_SIZE, ED25519_PUBLIC_KEY_SIZE);
137 }
138 if (expected_key && server) {
140 if (!ctx->client_whitelist) {
142 SET_ERRNO(ERROR_MEMORY, "Cannot allocate peer key whitelist");
143 return NULL;
144 }
146 memcpy(ctx->client_whitelist[0].key, expected_key, ED25519_PUBLIC_KEY_SIZE);
148 ctx->require_client_auth = true;
149 } else if (expected_key) {
150 ctx->verify_server_key = true;
152 memcpy(ctx->expected_server_key_bytes, expected_key, ED25519_PUBLIC_KEY_SIZE);
153 }
154 peer->transport.methods = &peer_methods;
155 peer->transport.impl_data = peer;
156 if (acip_security_start(&peer->security, &peer->transport) != ASCIICHAT_OK) {
157 peer_crypto_destroy(peer);
158 return NULL;
159 }
160 return peer;
161}
#define SET_ERRNO(code,...)
asciichat_error_t crypto_handshake_init(const char *name, crypto_handshake_context_t *ctx, bool is_server)
Initialize named crypto handshake context.
asciichat_error_t crypto_handshake_init_with_password(const char *name, crypto_handshake_context_t *ctx, bool is_server, const char *password)
Initialize named crypto handshake context with password authentication.
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
uint8_t key[CRYPTO_PUBLIC_KEY_SIZE]
Definition key_types.h:74
uint8_t ed25519[ED25519_PRIVATE_KEY_SIZE]
Definition key_types.h:100
key_type_t type
Definition key_types.h:98
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]
Definition key_types.h:105
key_type_t type
Definition key_types.h:73
union private_key_t::@040247167361101132173265304166142033301213115260 key
@ KEY_TYPE_ED25519
Definition key_types.h:54
asciichat_error_t acip_security_start(acip_security_t *security, acip_transport_t *transport)
void peer_crypto_destroy(browser_peer_crypto_t *peer)
Definition peer_crypto.c:95
struct browser_peer_crypto browser_peer_crypto_t
Definition peer_crypto.h:9
asciichat_error_t crypto_policy_resolve(const crypto_policy_t *policy, uint8_t *mode)
Definition policy.c:4
#define ED25519_PUBLIC_KEY_SIZE
Ed25519 public key size in bytes.
Definition sizes.h:33
#define ED25519_SEED_SIZE
Definition sizes.h:165
#define ED25519_PRIVATE_KEY_SIZE
Ed25519 private key size (seed + public) in bytes.
Definition sizes.h:35
crypto_handshake_context_t handshake
void * impl_data
Transport-specific state.
const acip_transport_methods_t * methods
Method table (virtual functions).
acip_transport_t transport
Definition peer_crypto.c:26
acip_security_t security
Definition peer_crypto.c:24
Cryptographic handshake context structure.
The useful part of crypto policy is in transport_secure, encrypt, no_encrypt, no_auth: together they ...
Definition policy.h:12
bool no_encrypt
Definition policy.h:15
bool has_password
Definition policy.h:17
Private identity-key material used for server authentication and signing.
Definition key_types.h:97
The normalized public identity used by ascii-chat's crypto and key-management code.
Definition key_types.h:72

References acip_security_start(), ASCIICHAT_OK, crypto_handshake_context_t::client_private_key, crypto_handshake_context_t::client_public_key, crypto_handshake_context_t::client_whitelist, crypto_handshake_init(), crypto_handshake_init_with_password(), crypto_policy_resolve(), private_key_t::ed25519, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ED25519_SEED_SIZE, crypto_policy_t::encrypt, ERROR_MEMORY, crypto_handshake_context_t::expected_server_key_bytes, crypto_handshake_context_t::expected_server_key_bytes_set, acip_security::forbid_encryption, acip_security::handshake, crypto_policy_t::has_password, acip_transport::impl_data, private_key_t::key, public_key_t::key, KEY_TYPE_ED25519, acip_transport::methods, acip_security::mode, crypto_policy_t::no_encrypt, crypto_handshake_context_t::num_whitelisted_clients, peer_crypto_destroy(), private_key_t::public_key, crypto_handshake_context_t::require_client_auth, acip_security::require_encryption, SAFE_CALLOC, browser_peer_crypto::security, crypto_handshake_context_t::server_private_key, crypto_handshake_context_t::server_public_key, SET_ERRNO, browser_peer_crypto::transport, private_key_t::type, public_key_t::type, and crypto_handshake_context_t::verify_server_key.

Referenced by PeerCryptoBinding::PeerCryptoBinding().

◆ peer_crypto_destroy()

void peer_crypto_destroy ( browser_peer_crypto_t * peer)

Definition at line 95 of file peer_crypto.c.

95 {
96 if (!peer)
97 return;
98 while (peer->output)
102 SAFE_FREE(peer);
103}
#define buffer_release(data)
Definition buffer.h:91
#define SAFE_FREE(ptr)
Definition common.h:377
void acip_security_cleanup(acip_security_t *security)
void peer_crypto_output_pop(browser_peer_crypto_t *peer)
Definition peer_crypto.c:84
peer_output_t * output
Definition peer_crypto.c:27

References acip_security_cleanup(), buffer_release, browser_peer_crypto::output, peer_crypto_output_pop(), browser_peer_crypto::received, SAFE_FREE, and browser_peer_crypto::security.

Referenced by peer_crypto_create().

◆ peer_crypto_error()

const char * peer_crypto_error ( void )

Definition at line 32 of file peer_crypto.c.

32 {
33 static asciichat_error_context_t error;
34 return HAS_ERRNO(&error) ? error.context_message : "Peer security operation failed";
35}
#define HAS_ERRNO(context)

References asciichat_error_context_t::context_message, and HAS_ERRNO.

Referenced by PeerCryptoBinding::error().

◆ peer_crypto_output_data()

const void * peer_crypto_output_data ( browser_peer_crypto_t * peer)

Definition at line 167 of file peer_crypto.c.

167 {
168 return peer && peer->output ? peer->output->data : NULL;
169}
void * data
Definition peer_crypto.c:19

References peer_output::data, and browser_peer_crypto::output.

Referenced by PeerCryptoBinding::takeOutput().

◆ peer_crypto_output_pop()

void peer_crypto_output_pop ( browser_peer_crypto_t * peer)

Definition at line 84 of file peer_crypto.c.

84 {
85 if (!peer || !peer->output)
86 return;
87 peer_output_t *output = peer->output;
88 peer->output = output->next;
89 if (!peer->output)
90 peer->tail = NULL;
91 buffer_release(output->data);
92 SAFE_FREE(output);
93}
struct peer_output peer_output_t
peer output is intentionally a small, concrete record. Fields such as next, data, length give callers...
peer_output_t * tail
Definition peer_crypto.c:27
struct peer_output * next
Definition peer_crypto.c:18

References buffer_release, peer_output::data, peer_output::next, browser_peer_crypto::output, SAFE_FREE, and browser_peer_crypto::tail.

Referenced by peer_crypto_destroy(), and PeerCryptoBinding::takeOutput().

◆ peer_crypto_output_size()

size_t peer_crypto_output_size ( browser_peer_crypto_t * peer)

Definition at line 171 of file peer_crypto.c.

171 {
172 return peer && peer->output ? peer->output->length : 0;
173}
size_t length
Definition peer_crypto.c:20

References peer_output::length, and browser_peer_crypto::output.

Referenced by PeerCryptoBinding::takeOutput().

◆ peer_crypto_quic_begin()

asciichat_error_t peer_crypto_quic_begin ( browser_peer_crypto_t * peer)

Definition at line 261 of file peer_crypto.c.

261 {
262 if (!peer || peer->security.version_received || peer->quic_handshake || !ACIP_CRYPTO_HAS_ENCRYPT(peer->security.mode))
263 return SET_ERRNO(ERROR_INVALID_STATE, "Invalid peer QUIC handshake transition");
264 peer->quic_handshake = true;
265 return ASCIICHAT_OK;
266}
@ ERROR_INVALID_STATE
#define ACIP_CRYPTO_HAS_ENCRYPT(mode)
Check if crypto mode includes payload encryption.
Definition packet.h:1148

References ACIP_CRYPTO_HAS_ENCRYPT, ASCIICHAT_OK, ERROR_INVALID_STATE, acip_security::mode, browser_peer_crypto::quic_handshake, browser_peer_crypto::security, SET_ERRNO, and acip_security::version_received.

Referenced by PeerCryptoBinding::beginQuic().

◆ peer_crypto_ready()

bool peer_crypto_ready ( browser_peer_crypto_t * peer)

Definition at line 163 of file peer_crypto.c.

163 {
164 return peer && peer->security.ready;
165}

References acip_security::ready, and browser_peer_crypto::security.

Referenced by PeerCryptoBinding::ready().

◆ peer_crypto_receive()

asciichat_error_t peer_crypto_receive ( browser_peer_crypto_t * peer,
const void * data,
size_t length )

Definition at line 191 of file peer_crypto.c.

191 {
192 if (!peer || !data)
193 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid peer packet or security state");
194 if (length < sizeof(packet_header_t))
195 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid peer packet");
197 peer->received = NULL;
198 peer->received_length = 0;
199 packet_header_t header;
200 memcpy(&header, data, sizeof(header));
201 size_t payload_length = length - sizeof(header);
202 const void *payload = (const uint8_t *)data + sizeof(header);
203 packet_type_t type = NET_TO_HOST_U16(header.type);
204 asciichat_error_t validation = packet_validate(data, length, 0, NULL);
205 if (validation != ASCIICHAT_OK)
206 return validation;
207 if (!peer->security.ready) {
208 asciichat_error_t result = acip_security_receive(&peer->security, &peer->transport, type, payload, payload_length);
209 if (result != ASCIICHAT_OK || !peer->quic_handshake || type != PACKET_TYPE_PROTOCOL_VERSION)
210 return result;
219 result = packet_send_via_transport(&peer->transport, PACKET_TYPE_CRYPTO_CAPABILITIES, &caps, sizeof(caps), 0);
220 if (result != ASCIICHAT_OK || !caps.requires_verification)
221 return result;
224 }
225 bool encrypt = ACIP_CRYPTO_HAS_ENCRYPT(peer->security.mode);
226 if (packet_is_initial_handshake_type(type) || (encrypt != (type == PACKET_TYPE_ENCRYPTED)))
227 return SET_ERRNO(ERROR_CRYPTO, "Peer packet does not match negotiated security");
228 if (!encrypt) {
229 peer->received = buffer_alloc(NULL, length);
230 if (!peer->received)
231 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate peer input");
232 memcpy(peer->received, data, length);
233 peer->received_length = length;
234 return ASCIICHAT_OK;
235 }
236 bool consumed = false;
237 uint64_t sequence;
238 asciichat_error_t result =
240 length, (uint8_t **)&peer->received, &peer->received_length, &sequence, &consumed);
241 if (consumed) {
243 peer->received = NULL;
244 peer->received_length = 0;
245 }
246 return result;
247}
void * buffer_alloc(buffer_domain_t *domain, size_t size)
Definition buffer.c:274
#define HOST_TO_NET_U16(val)
Definition endian.h:96
#define NET_TO_HOST_U16(val)
Definition endian.h:111
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:76
@ ERROR_CRYPTO
Definition error_codes.h:93
@ ERROR_INVALID_PARAM
asciichat_error_t packet_validate(const void *packet, size_t length, size_t limit, packet_header_t *output)
Definition packet.c:86
#define AUTH_ALGO_ED25519
Ed25519 authentication (Edwards-curve signatures).
Definition packet.h:1121
#define ACIP_CRYPTO_HAS_AUTH(mode)
Check if crypto mode includes authentication.
Definition packet.h:1155
#define KEX_ALGO_X25519
X25519 key exchange (Curve25519).
Definition packet.h:1120
packet_type_t
Network protocol packet type enumeration.
Definition packet.h:301
#define AUTH_ALGO_NONE
No authentication (plaintext mode).
Definition packet.h:1122
#define CIPHER_ALGO_NONE
No encryption (plaintext mode).
Definition packet.h:1124
#define CIPHER_ALGO_XSALSA20_POLY1305
XSalsa20-Poly1305 authenticated encryption.
Definition packet.h:1123
@ PACKET_TYPE_CRYPTO_CLIENT_HELLO
Client -> Server: Expected server key fingerprint for multi-key selection (UNENCRYPTED).
Definition packet.h:314
@ PACKET_TYPE_ENCRYPTED
Encrypted packet (after handshake completion).
Definition packet.h:355
@ PACKET_TYPE_PROTOCOL_VERSION
Protocol version and capabilities negotiation.
Definition packet.h:303
@ PACKET_TYPE_CRYPTO_CAPABILITIES
Client -> Server: Supported crypto algorithms (UNENCRYPTED).
Definition packet.h:322
asciichat_error_t acip_security_open(crypto_context_t *crypto, acip_traffic_class_t flow, acip_delivery_t delivery, const void *packet, size_t length, uint8_t **output, size_t *written, uint64_t *sequence, bool *consumed)
asciichat_error_t acip_security_receive(acip_security_t *security, acip_transport_t *transport, packet_type_t type, const void *payload, size_t length)
#define CRYPTO_RECORD_ANY_CHANNEL
Definition record.h:11
asciichat_error_t packet_send_via_transport(acip_transport_t *transport, packet_type_t type, const void *payload, size_t payload_len, uint32_t client_id)
Definition send.c:190
Crypto capabilities packet structure (Packet Type 14).
Definition packet.h:1008
uint8_t preferred_auth
Preferred authentication algorithm (AUTH_ALGO_*).
Definition packet.h:1020
uint16_t supported_auth_algorithms
Supported authentication algorithms bitmask (AUTH_ALGO_*).
Definition packet.h:1012
uint16_t supported_kex_algorithms
Supported key exchange algorithms bitmask (KEX_ALGO_*).
Definition packet.h:1010
uint8_t preferred_cipher
Preferred cipher algorithm (CIPHER_ALGO_*).
Definition packet.h:1022
uint16_t supported_cipher_algorithms
Supported cipher algorithms bitmask (CIPHER_ALGO_*).
Definition packet.h:1014
uint8_t preferred_kex
Preferred key exchange algorithm (KEX_ALGO_*).
Definition packet.h:1018
uint8_t requires_verification
Server verification requirement flag (1=required, 0=optional).
Definition packet.h:1016
Fixed prefix shared by every ACIP packet on the wire.
Definition packet.h:628
@ ACIP_DELIVERY_RELIABLE
Definition traffic.h:12

References ACIP_CRYPTO_HAS_AUTH, ACIP_CRYPTO_HAS_ENCRYPT, ACIP_DELIVERY_RELIABLE, acip_security_open(), acip_security_receive(), ASCIICHAT_OK, AUTH_ALGO_ED25519, AUTH_ALGO_NONE, buffer_alloc(), buffer_release, CIPHER_ALGO_NONE, CIPHER_ALGO_XSALSA20_POLY1305, crypto_handshake_context_t::crypto_ctx, CRYPTO_RECORD_ANY_CHANNEL, ED25519_PUBLIC_KEY_SIZE, ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_MEMORY, ERROR_NETWORK_PROTOCOL, crypto_handshake_context_t::expected_server_key_bytes, acip_security::handshake, HOST_TO_NET_U16, KEX_ALGO_X25519, acip_security::mode, NET_TO_HOST_U16, packet_send_via_transport(), PACKET_TYPE_CRYPTO_CAPABILITIES, PACKET_TYPE_CRYPTO_CLIENT_HELLO, PACKET_TYPE_ENCRYPTED, PACKET_TYPE_PROTOCOL_VERSION, packet_validate(), crypto_capabilities_packet_t::preferred_auth, crypto_capabilities_packet_t::preferred_cipher, crypto_capabilities_packet_t::preferred_kex, browser_peer_crypto::quic_handshake, acip_security::ready, browser_peer_crypto::received, browser_peer_crypto::received_length, crypto_capabilities_packet_t::requires_verification, browser_peer_crypto::security, SET_ERRNO, crypto_capabilities_packet_t::supported_auth_algorithms, crypto_capabilities_packet_t::supported_cipher_algorithms, crypto_capabilities_packet_t::supported_kex_algorithms, browser_peer_crypto::transport, and crypto_handshake_context_t::verify_server_key.

◆ peer_crypto_received_data()

const void * peer_crypto_received_data ( browser_peer_crypto_t * peer)

Definition at line 175 of file peer_crypto.c.

175 {
176 return peer ? peer->received : NULL;
177}

References browser_peer_crypto::received.

Referenced by PeerCryptoBinding::received().

◆ peer_crypto_received_size()

size_t peer_crypto_received_size ( browser_peer_crypto_t * peer)

Definition at line 179 of file peer_crypto.c.

179 {
180 return peer ? peer->received_length : 0;
181}

References browser_peer_crypto::received_length.

Referenced by PeerCryptoBinding::received().

◆ peer_crypto_send()

asciichat_error_t peer_crypto_send ( browser_peer_crypto_t * peer,
const void * data,
size_t length )

Definition at line 183 of file peer_crypto.c.

183 {
184 if (!peer || !data || !length)
185 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid peer packet or security state");
186 if (!peer->security.ready)
187 return SET_ERRNO(ERROR_INVALID_STATE, "Peer security is not ready");
188 return peer_send(&peer->transport, data, length);
189}

References ERROR_INVALID_PARAM, ERROR_INVALID_STATE, acip_security::ready, browser_peer_crypto::security, SET_ERRNO, and browser_peer_crypto::transport.

◆ peer_crypto_tick()

asciichat_error_t peer_crypto_tick ( browser_peer_crypto_t * peer)

Definition at line 253 of file peer_crypto.c.

253 {
254 if (!peer)
255 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid peer security state");
256 if (!peer->security.ready || peer->quic_handshake || !ACIP_CRYPTO_HAS_ENCRYPT(peer->security.mode))
257 return ASCIICHAT_OK;
258 return acip_security_flush(&peer->transport);
259}
asciichat_error_t acip_security_flush(acip_transport_t *transport)

References ACIP_CRYPTO_HAS_ENCRYPT, acip_security_flush(), ASCIICHAT_OK, ERROR_INVALID_PARAM, acip_security::mode, browser_peer_crypto::quic_handshake, acip_security::ready, browser_peer_crypto::security, SET_ERRNO, and browser_peer_crypto::transport.

Referenced by PeerCryptoBinding::tick().

◆ peer_security_context()