diff --git a/core/src/crypto/crypto.cpp b/core/src/crypto/crypto.cpp index c94ab3e..92f77bd 100644 --- a/core/src/crypto/crypto.cpp +++ b/core/src/crypto/crypto.cpp @@ -12,7 +12,6 @@ namespace voicecat::crypto { -// ── Helpers ─────────────────────────────────────────────────────────────────── static void throw_if(int rc, const char* msg) { if (rc != 0) { @@ -35,7 +34,7 @@ static std::string compute_hex_fingerprint(const uint8_t* data, size_t len) { return s; } -// ── ServerIdentity ──────────────────────────────────────────────────────────── +// ServerIdentity ServerIdentity ServerIdentity::generate() { ServerIdentity id; @@ -75,7 +74,7 @@ std::string ServerIdentity::fingerprint_hex() const { return s; } -// ── ServerCert ──────────────────────────────────────────────────────────────── +// ServerCert ServerCert ServerCert::generate(const std::string& server_name) { mbedtls_entropy_context entropy; @@ -171,7 +170,7 @@ void ServerCert::save(const std::filesystem::path& cert_path, write_file(key_path, pem_key); } -// ── TlsContext ──────────────────────────────────────────────────────────────── +// TlsContext TlsContext::TlsContext(Role role, const ServerCert* server_cert, const std::array* pinned_fp) @@ -217,7 +216,7 @@ TlsContext::TlsContext(Role role, const ServerCert* server_cert, } if (role == Role::Client) { - // Skip CA chain verification — we use TOFU via the server identity fingerprint. + // Skip CA chain verification, we use TOFU via the server identity fingerprint. mbedtls_ssl_conf_authmode(&conf_, MBEDTLS_SSL_VERIFY_NONE); } @@ -284,7 +283,7 @@ bool TlsContext::peer_cert_fingerprint(std::array& out) const { return true; } -// ── SodiumMediaCrypto ───────────────────────────────────────────────────────── +// SodiumMediaCrypto SodiumMediaCrypto::SodiumMediaCrypto( const uint8_t key[crypto_aead_chacha20poly1305_ietf_KEYBYTES]) { @@ -347,8 +346,7 @@ long SodiumMediaCrypto::open(const uint8_t* sealed, size_t len, const uint8_t* a if (out_cap < len - crypto_aead_chacha20poly1305_ietf_ABYTES) return -1; // Read the full 64-bit nonce counter directly from aad[8..15] (seq, big-endian - // u64). Protocol v2 carries the full counter on the wire, so the nonce is exact — - // no reconstruction/rollover guessing needed. + // u64). if (aad_len < 16) return -1; uint64_t counter = (static_cast(aad[8]) << 56) | (static_cast(aad[9]) << 48) | @@ -364,7 +362,7 @@ long SodiumMediaCrypto::open(const uint8_t* sealed, size_t len, const uint8_t* a // window before the AEAD tag is verified — otherwise a single corrupted/forged // packet would shove recv_highest_ far ahead and reject every later legitimate // packet as "too old", permanently wedging the stream. Order per RFC 3711 §3.3: - // replay-check → authenticate → update. + // replay-check authenticate update. if (recv_initialized_ && counter <= recv_highest_) { uint64_t offset = recv_highest_ - counter; if (offset >= 64) return -1; // too old @@ -381,7 +379,7 @@ long SodiumMediaCrypto::open(const uint8_t* sealed, size_t len, const uint8_t* a nonce, key_.data()) != 0) return -1; // auth failure — leave the replay window untouched - // ── Authenticated: now it's safe to advance the window ──────────────────── + // Authenticated: now it's safe to advance the window ──────────────────── if (!recv_initialized_) { recv_highest_ = counter; recv_window_ = 1; // bit0 = highest itself diff --git a/core/src/crypto/crypto.h b/core/src/crypto/crypto.h index 8970622..f9e8792 100644 --- a/core/src/crypto/crypto.h +++ b/core/src/crypto/crypto.h @@ -1,7 +1,7 @@ /* - * crypto/crypto.h — TLS 1.3 (mbedTLS) and the media AEAD (libsodium). + * crypto/crypto.h: TLS 1.3 (mbedTLS) and the media AEAD (libsodium). * - * Design: docs/security.md. Control channel = TLS 1.3. Media = keys exported from the TLS + *Control channel = TLS 1.3. Media = keys exported from the TLS * session (RFC 5705 / 8446) + per-frame ChaCha20-Poly1305 with a counter nonce and a * sliding-window replay filter. Encryption is MANDATORY — never add a plaintext path. */ @@ -30,7 +30,7 @@ namespace voicecat::crypto { -// ── Server identity ──────────────────────────────────────────────────────────── +// Server identity // Long-lived Ed25519 key identifying this server instance across cert rotations. // Fingerprint is the 32-byte SHA-256 of the public key. struct ServerIdentity { @@ -44,7 +44,7 @@ struct ServerIdentity { std::string fingerprint_hex() const; }; -// ── Server TLS certificate ───────────────────────────────────────────────────── +// Server TLS certificate // Self-signed ECDSA-P256 cert for TLS. On first run, generated and persisted. struct ServerCert { std::string pem_cert; @@ -57,7 +57,7 @@ struct ServerCert { const std::filesystem::path& key_path) const; }; -// ── TLS 1.3 context ─────────────────────────────────────────────────────────── +// TLS 1.3 context // Wraps mbedTLS for one TLS connection (server or client side). // All public methods must be called from a single thread at a time. class TlsContext { @@ -119,7 +119,7 @@ class TlsContext { mbedtls_net_context net_ctx_{}; }; -// ── Media AEAD ───────────────────────────────────────────────────────────────── +// Media AEAD // Per-frame voice encryption. Abstracted so the backend is swappable. class MediaCrypto { public: @@ -135,7 +135,7 @@ class MediaCrypto { uint8_t* out, size_t out_cap) = 0; }; -// ── ChaCha20-Poly1305 backend ────────────────────────────────────────────────── +// ChaCha20-Poly1305 backend // Keys are derived from the TLS session via RFC 5705 / mbedTLS exporter. // Nonce scheme: 4 zero bytes ‖ monotonic-counter(u64 big-endian, 8 bytes). // Anti-replay: 64-bit sliding window keyed on the received counter. @@ -145,10 +145,10 @@ class SodiumMediaCrypto final : public MediaCrypto { static std::unique_ptr derive(TlsContext& tls, uint8_t ctx_byte); // Convenience: derive the key used to encrypt outgoing frames. - // is_client=true → ctx=0x00 (client sends); is_client=false → ctx=0x01 (server sends). + // is_client=true ctx=0x00 (client sends); is_client=false ctx=0x01 (server sends). static std::unique_ptr derive_send(TlsContext& tls, bool is_client); // Convenience: derive the key used to decrypt incoming frames. - // is_client=true → ctx=0x01 (client recvs); is_client=false → ctx=0x00 (server recvs). + // is_client=true ctx=0x01 (client recvs); is_client=false ctx=0x00 (server recvs). static std::unique_ptr derive_recv(TlsContext& tls, bool is_client); // Unit-test constructor: supply a raw 32-byte key directly. diff --git a/core/src/crypto/tofu_store.h b/core/src/crypto/tofu_store.h index cf5187b..368bc2f 100644 --- a/core/src/crypto/tofu_store.h +++ b/core/src/crypto/tofu_store.h @@ -1,5 +1,5 @@ /* - * crypto/tofu_store.h — Trust-On-First-Use pin storage. + * crypto/tofu_store.h: Trust-On-First-Use pin storage. * * File format: one "host:port \n" line per entry. * Used by clients to remember server fingerprints across reconnects.