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.cpp
Go to the documentation of this file.
1#include <emscripten/bind.h>
2extern "C" {
3#include "../peer_crypto.h"
4#include "../client.h"
5#include "../security.h"
6}
7#include "networking.h"
8#include <sodium.h>
9#include "byte_arrays.h"
10
11#include <memory>
12#include <cstddef>
13#include <cstdint>
14#include <string>
15#include <vector>
16
17EMSCRIPTEN_DECLARE_VAL_TYPE(NullablePeerBytes);
18
19static int configure_crypto(PeerBytes password, PeerBytes identity, PeerBytes expected) {
20 auto pass = binding_copy_input(password);
21 auto secret = binding_copy_input(identity);
22 auto key = binding_copy_input(expected);
23 int result;
24 if ((secret.empty() || secret.size() == 64) && (key.empty() || key.size() == 32)) {
25 pass.push_back(0);
26 result =
27 client_configure_crypto_options(pass.size() > 1 ? reinterpret_cast<char *>(pass.data()) : nullptr,
28 secret.empty() ? nullptr : secret.data(), key.empty() ? nullptr : key.data());
29 } else {
30 result = SET_ERRNO(ERROR_INVALID_PARAM, "Invalid client identity or verification key length");
31 }
32 if (!pass.empty())
33 sodium_memzero(pass.data(), pass.size());
34 if (!secret.empty())
35 sodium_memzero(secret.data(), secret.size());
36 if (!key.empty())
37 sodium_memzero(key.data(), key.size());
38 return result;
39}
40
42public:
43 PeerCryptoBinding(bool server, int encryption, PeerBytes password, PeerBytes identity, PeerBytes expected) {
44 auto pass = binding_copy_input(password);
45 auto secret = binding_copy_input(identity);
46 auto key = binding_copy_input(expected);
47 if ((!secret.empty() && secret.size() != 64) || (!key.empty() && key.size() != 32)) {
48 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid peer identity or verification key length");
49 } else {
50 pass.push_back(0);
51 peer_.reset(peer_crypto_create(server, encryption,
52 pass.size() > 1 ? reinterpret_cast<char *>(pass.data()) : nullptr,
53 secret.empty() ? nullptr : secret.data(), key.empty() ? nullptr : key.data()));
54 }
55 if (!pass.empty())
56 sodium_memzero(pass.data(), pass.size());
57 if (!secret.empty())
58 sodium_memzero(secret.data(), secret.size());
59 if (!key.empty())
60 sodium_memzero(key.data(), key.size());
61 }
64
65 bool valid() const {
66 return static_cast<bool>(peer_);
67 }
68 bool ready() const {
69 return peer_ && peer_crypto_ready(peer_.get());
70 }
71 std::string error() const {
72 return peer_crypto_error();
73 }
74 int send(PeerBytes packet) {
75 return input(packet, false);
76 }
77 int receive(PeerBytes packet) {
78 return input(packet, true);
79 }
80 int tick() {
81 return peer_crypto_tick(peer_.get());
82 }
83 int beginQuic() {
84 return peer_crypto_quic_begin(peer_.get());
85 }
86 int initQuic() {
88 }
89 int tickQuic() {
91 }
92 double quicEpoch() {
94 }
95
96 NullablePeerBytes takeOutput() {
97 const void *data = peer_crypto_output_data(peer_.get());
98 if (!data)
99 return NullablePeerBytes(emscripten::val::null());
100 emscripten::val output = binding_copy_output(data, peer_crypto_output_size(peer_.get()));
101 peer_crypto_output_pop(peer_.get());
102 return NullablePeerBytes(output);
103 }
104 NullablePeerBytes received() {
105 const void *data = peer_crypto_received_data(peer_.get());
106 const size_t length = peer_crypto_received_size(peer_.get());
107 return NullablePeerBytes(data && length ? binding_copy_output(data, length) : emscripten::val::null());
108 }
109 QuicControlResult takeQuicOutput() {
110 return network_quic_output(peer_security_context(peer_.get()));
111 }
112 QuicPacketResult quicPacket(bool seal, unsigned flow, unsigned delivery, PeerBytes packet) {
113 return network_quic_packet(peer_security_context(peer_.get()), seal, flow, delivery, packet);
114 }
115
116private:
117 int input(PeerBytes packet, bool receive) {
118 auto bytes = binding_copy_input(packet);
119 int result = receive ? peer_crypto_receive(peer_.get(), bytes.data(), bytes.size())
120 : peer_crypto_send(peer_.get(), bytes.data(), bytes.size());
121 if (!bytes.empty())
122 sodium_memzero(bytes.data(), bytes.size());
123 return result;
124 }
125 std::unique_ptr<browser_peer_crypto_t, decltype(&peer_crypto_destroy)> peer_{nullptr, &peer_crypto_destroy};
126};
127
128EMSCRIPTEN_BINDINGS(ascii_chat_peer_crypto) {
129 emscripten::register_type<PeerBytes>("PeerBytes", "Uint8Array");
130 emscripten::register_type<NullablePeerBytes>("NullablePeerBytes", "Uint8Array | null");
131 emscripten::function("configureCrypto", &configure_crypto);
132 emscripten::class_<PeerCryptoBinding>("PeerCryptoBinding")
133 .constructor<bool, int, PeerBytes, PeerBytes, PeerBytes>()
134 .function("valid", &PeerCryptoBinding::valid)
135 .function("ready", &PeerCryptoBinding::ready)
136 .function("error", &PeerCryptoBinding::error)
137 .function("send", &PeerCryptoBinding::send)
138 .function("receive", &PeerCryptoBinding::receive)
139 .function("tick", &PeerCryptoBinding::tick)
140 .function("beginQuic", &PeerCryptoBinding::beginQuic)
141 .function("initQuic", &PeerCryptoBinding::initQuic)
142 .function("tickQuic", &PeerCryptoBinding::tickQuic)
143 .function("quicEpoch", &PeerCryptoBinding::quicEpoch)
144 .function("takeOutput", &PeerCryptoBinding::takeOutput)
145 .function("received", &PeerCryptoBinding::received)
146 .function("takeQuicOutput", &PeerCryptoBinding::takeQuicOutput)
147 .function("quicPacket", &PeerCryptoBinding::quicPacket);
148}
#define SET_ERRNO(code,...)
emscripten::val binding_copy_output(const void *data, size_t length)
Definition byte_arrays.h:18
std::vector< uint8_t > binding_copy_input(emscripten::val bytes)
Definition byte_arrays.h:6
PeerCryptoBinding(bool server, int encryption, PeerBytes password, PeerBytes identity, PeerBytes expected)
NullablePeerBytes received()
std::string error() const
bool valid() const
int send(PeerBytes packet)
PeerCryptoBinding(const PeerCryptoBinding &)=delete
QuicControlResult takeQuicOutput()
int receive(PeerBytes packet)
NullablePeerBytes takeOutput()
PeerCryptoBinding & operator=(const PeerCryptoBinding &)=delete
QuicPacketResult quicPacket(bool seal, unsigned flow, unsigned delivery, PeerBytes packet)
bool ready() const
@ ERROR_INVALID_PARAM
QuicControlResult network_quic_output(crypto_context_t *context)
QuicPacketResult network_quic_packet(crypto_context_t *context, bool seal, unsigned flow, unsigned delivery, PeerBytes packet)
const void * peer_crypto_received_data(browser_peer_crypto_t *peer)
asciichat_error_t peer_crypto_tick(browser_peer_crypto_t *peer)
bool peer_crypto_ready(browser_peer_crypto_t *peer)
asciichat_error_t peer_crypto_send(browser_peer_crypto_t *peer, const void *data, size_t length)
const char * peer_crypto_error(void)
Definition peer_crypto.c:32
size_t peer_crypto_received_size(browser_peer_crypto_t *peer)
void peer_crypto_output_pop(browser_peer_crypto_t *peer)
Definition peer_crypto.c:84
size_t peer_crypto_output_size(browser_peer_crypto_t *peer)
crypto_context_t * peer_security_context(browser_peer_crypto_t *peer)
asciichat_error_t peer_crypto_quic_begin(browser_peer_crypto_t *peer)
void peer_crypto_destroy(browser_peer_crypto_t *peer)
Definition peer_crypto.c:95
asciichat_error_t peer_crypto_receive(browser_peer_crypto_t *peer, const void *data, size_t length)
browser_peer_crypto_t * peer_crypto_create(bool server, int encryption, const char *password, const uint8_t *identity, const uint8_t *expected_key)
const void * peer_crypto_output_data(browser_peer_crypto_t *peer)
EMSCRIPTEN_BINDINGS(ascii_chat_peer_crypto)
EMSCRIPTEN_DECLARE_VAL_TYPE(NullablePeerBytes)
struct browser_peer_crypto browser_peer_crypto_t
Definition peer_crypto.h:9
int client_configure_crypto_options(const char *password, const uint8_t *identity_secret_key, const uint8_t *expected_server_public_key)
double browser_security_epoch(crypto_context_t *ctx)
asciichat_error_t browser_security_tick(crypto_context_t *ctx)
asciichat_error_t browser_security_init(crypto_context_t *ctx)