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.h File Reference

Go to the source code of this file.

Typedefs

typedef struct browser_peer_crypto browser_peer_crypto_t

Functions

browser_peer_crypto_t * peer_crypto_create (bool server, int encryption, const char *password, const uint8_t *identity, const uint8_t *expected_key)
void peer_crypto_destroy (browser_peer_crypto_t *peer)
bool peer_crypto_ready (browser_peer_crypto_t *peer)
const char * peer_crypto_error (void)
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)
const void * peer_crypto_output_data (browser_peer_crypto_t *peer)
size_t peer_crypto_output_size (browser_peer_crypto_t *peer)
void peer_crypto_output_pop (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)
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

◆ browser_peer_crypto_t

Browser-facing C interface implemented in peer_crypto.c.

Definition at line 9 of file peer_crypto.h.

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()