refactored tlibc collections

This commit is contained in:
Timerix 2025-11-25 16:31:58 +05:00
parent 7a3808ba59
commit 8bc98a321d
32 changed files with 294 additions and 265 deletions

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit b557881168a15797bd3bd3d989cd7d48d3fb0804 Subproject commit 82bd234d08e2556ae37fff8e414a72c5caaa355b

View File

@ -16,3 +16,5 @@
#define CHANNEL_NAME_SIZE_MIN 1 #define CHANNEL_NAME_SIZE_MIN 1
#define CHANNEL_NAME_SIZE_MAX 127 #define CHANNEL_NAME_SIZE_MAX 127
#define CHANNEL_DESC_SIZE_MAX 1023 #define CHANNEL_DESC_SIZE_MAX 1023
#define MESSAGE_SIZE_MIN 1
#define MESSAGE_SIZE_MAX 4000

View File

@ -39,7 +39,7 @@ void ClientCLI_destroy(ClientCLI* self){
Client_free(self->client); Client_free(self->client);
idb_close(self->db); idb_close(self->db);
List_destroy(&self->servers.list); List_ServerInfo_destroy(&self->servers.list);
HashMap_destroy(&self->servers.addr_id_map); HashMap_destroy(&self->servers.addr_id_map);
} }
void ClientCLI_construct(ClientCLI* self){ void ClientCLI_construct(ClientCLI* self){
@ -51,7 +51,7 @@ Result(void) ClientCLI_run(ClientCLI* self) {
try_void(term_init()); try_void(term_init());
term_clear(); term_clear();
printf(FMT_str"\n", greeting_art.size, greeting_art.data); printf(FMT_str"\n", greeting_art.len, greeting_art.data);
// create Client // create Client
str username = str_null, password = str_null; str username = str_null, password = str_null;
@ -62,7 +62,7 @@ Result(void) ClientCLI_run(ClientCLI* self) {
); );
Client_free(self->client); Client_free(self->client);
try(self->client, p, Client_create(username, password)); try(self->client, p, Client_create(username, password));
memset(password.data, 0, password.size); memset(password.data, 0, password.len);
// init db // init db
try_void(ClientCLI_openUserDB(self)); try_void(ClientCLI_openUserDB(self));
@ -77,14 +77,14 @@ Result(void) ClientCLI_run(ClientCLI* self) {
command_input = str_from_cstr(input_buf); command_input = str_from_cstr(input_buf);
str_trim(&command_input, true); str_trim(&command_input, true);
if(command_input.size == 0) if(command_input.len == 0)
continue; continue;
ResultVar(void) com_result = ClientCLI_execCommand(self, command_input, &stop); ResultVar(void) com_result = ClientCLI_execCommand(self, command_input, &stop);
if(com_result.error){ if(com_result.error){
Error_addCallPos(com_result.error, ErrorCallPos_here()); Error_addCallPos(com_result.error, ErrorCallPos_here());
str e_str = Error_toStr(com_result.error); str e_str = Error_toStr(com_result.error);
printf("\n"FMT_str"\n", e_str.size, e_str.data); printf("\n"FMT_str"\n", e_str.len, e_str.data);
str_free(e_str); str_free(e_str);
Error_free(com_result.error); Error_free(com_result.error);
} }
@ -98,33 +98,33 @@ static Result(void) ClientCLI_askUserNameAndPassword(str* username_out, str* pas
bool success = false; bool success = false;
// ask username // ask username
Array(char) username_buf = Array_alloc_size(128); Array(char) username_buf = Array_char_alloc(128);
Defer(if(!success) Array_free(username_buf)); Defer(if(!success) Array_char_destroy(&username_buf));
str username = str_null; str username = str_null;
while(true) { while(true) {
printf("username: "); printf("username: ");
try_void(term_readLine(username_buf.data, username_buf.size)); try_void(term_readLine(username_buf.data, username_buf.len));
username = str_from_cstr(username_buf.data); username = str_from_cstr(username_buf.data);
str_trim(&username, true); str_trim(&username, true);
str name_error_str = validateUsername_str(username); str name_error_str = validateUsername_str(username);
if(name_error_str.data){ if(name_error_str.data){
printf("ERROR: "FMT_str"\n", printf("ERROR: "FMT_str"\n",
name_error_str.size, name_error_str.data); name_error_str.len, name_error_str.data);
} }
else break; else break;
} }
// ask password // ask password
Array(char) password_buf = Array_alloc_size(128); Array(char) password_buf = Array_char_alloc(128);
Defer(if(!success) Array_free(password_buf)); Defer(if(!success) Array_char_destroy(&password_buf));
str password = str_null; str password = str_null;
while(true) { while(true) {
printf("password: "); printf("password: ");
// TODO: hide password // TODO: hide password
try_void(term_readLineHidden(password_buf.data, password_buf.size)); try_void(term_readLineHidden(password_buf.data, password_buf.len));
password = str_from_cstr(password_buf.data); password = str_from_cstr(password_buf.data);
str_trim(&password, true); str_trim(&password, true);
if(password.size < PASSWORD_SIZE_MIN || password.size > PASSWORD_SIZE_MAX){ if(password.len < PASSWORD_SIZE_MIN || password.len > PASSWORD_SIZE_MAX){
printf("ERROR: password length (in bytes) must be >= %i and <= %i\n", printf("ERROR: password length (in bytes) must be >= %i and <= %i\n",
PASSWORD_SIZE_MIN, PASSWORD_SIZE_MAX); PASSWORD_SIZE_MIN, PASSWORD_SIZE_MAX);
} }
@ -141,7 +141,7 @@ static Result(void) ClientCLI_execCommand(ClientCLI* self, str command, bool* st
Deferral(64); Deferral(64);
if(is_alias("q") || is_alias("quit") || is_alias("exit")){ if(is_alias("q") || is_alias("quit") || is_alias("exit")){
printf(FMT_str"\n", farewell_art.size, farewell_art.data); printf(FMT_str"\n", farewell_art.len, farewell_art.data);
*stop = true; *stop = true;
} }
else if(is_alias("clear")){ else if(is_alias("clear")){
@ -230,16 +230,16 @@ static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
idb_lockTable(self->servers.table); idb_lockTable(self->servers.table);
Defer(idb_unlockTable(self->servers.table)); Defer(idb_unlockTable(self->servers.table));
u32 servers_count = List_len(self->servers.list, ServerInfo); u32 servers_count = self->servers.list.len;
if(servers_count == 0){ if(servers_count == 0){
printf("No servers found in cache\n"); printf("No servers found in cache\n");
Return RESULT_VOID; Return RESULT_VOID;
} }
for(u32 id = 0; id < servers_count; id++){ for(u32 id = 0; id < servers_count; id++){
ServerInfo* row = &List_index(self->servers.list, ServerInfo, id); ServerInfo* server = self->servers.list.data + id;
printf("[%02u] "FMT_str" "FMT_str"\n", printf("[%02u] "FMT_str" "FMT_str"\n",
id, row->address_len, row->address, row->name_len, row->name); id, server->address_len, server->address, server->name_len, server->name);
} }
char buf[32]; char buf[32];
@ -261,7 +261,7 @@ static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
} }
else break; else break;
} }
ServerInfo* server = &List_index(self->servers.list, ServerInfo, id); ServerInfo* server = self->servers.list.data + id;
printf("Connecting to '"FMT_str"'...\n", server->address_len, server->address); printf("Connecting to '"FMT_str"'...\n", server->address_len, server->address);
try_void(Client_connect(self->client, server->address, server->pk_base64)); try_void(Client_connect(self->client, server->address, server->pk_base64));
@ -273,9 +273,9 @@ static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
try_void(Client_getServerName(self->client, &name)); try_void(Client_getServerName(self->client, &name));
if(!str_equals(name, str_construct(server->name, server->name_len, true))){ if(!str_equals(name, str_construct(server->name, server->name_len, true))){
server_info_changed = true; server_info_changed = true;
if(name.size > SERVER_NAME_SIZE_MAX) if(name.len > SERVER_NAME_SIZE_MAX)
name.size = SERVER_NAME_SIZE_MAX; name.len = SERVER_NAME_SIZE_MAX;
server->name_len = name.size; server->name_len = name.len;
memcpy(server->name, name.data, server->name_len); memcpy(server->name, name.data, server->name_len);
} }
// update cached server description // update cached server description
@ -283,9 +283,9 @@ static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
try_void(Client_getServerDescription(self->client, &desc)); try_void(Client_getServerDescription(self->client, &desc));
if(!str_equals(desc, str_construct(server->desc, server->desc_len, true))){ if(!str_equals(desc, str_construct(server->desc, server->desc_len, true))){
server_info_changed = true; server_info_changed = true;
if(desc.size > SERVER_DESC_SIZE_MAX) if(desc.len > SERVER_DESC_SIZE_MAX)
desc.size = SERVER_DESC_SIZE_MAX; desc.len = SERVER_DESC_SIZE_MAX;
server->desc_len = desc.size; server->desc_len = desc.len;
memcpy(server->desc, desc.data, server->desc_len); memcpy(server->desc, desc.data, server->desc_len);
} }
if(server_info_changed){ if(server_info_changed){
@ -335,7 +335,7 @@ static Result(void) ClientCLI_openUserDB(ClientCLI* self){
// load whole servers table to list // load whole servers table to list
try_void( try_void(
idb_createListFromTable(self->servers.table, &self->servers.list, false) idb_createListFromTable(self->servers.table, (void*)&self->servers.list, false)
); );
// build address-id map // build address-id map
@ -344,10 +344,12 @@ static Result(void) ClientCLI_openUserDB(ClientCLI* self){
); );
HashMap_construct(&self->servers.addr_id_map, u64, NULL); HashMap_construct(&self->servers.addr_id_map, u64, NULL);
for(u64 id = 0; id < servers_count; id++){ for(u64 id = 0; id < servers_count; id++){
ServerInfo* row = &List_index(self->servers.list, ServerInfo, id); ServerInfo* server = self->servers.list.data + id;
str key = str_construct(row->address, row->address_len, true); str key = str_construct(server->address, server->address_len, true);
if(!HashMap_tryPush(&self->servers.addr_id_map, key, &id)){ if(!HashMap_tryPush(&self->servers.addr_id_map, key, &id)){
Return RESULT_ERROR_FMT("duplicate server address '"FMT_str"'", key.size, key.data); Return RESULT_ERROR_FMT(
"duplicate server address '"FMT_str"'",
key.len, key.data);
} }
} }
@ -362,24 +364,24 @@ static Result(ServerInfo*) ClientCLI_saveServerInfo(ClientCLI* self,
ServerInfo server; ServerInfo server;
memset(&server, 0, sizeof(ServerInfo)); memset(&server, 0, sizeof(ServerInfo));
// address // address
if(addr.size > HOSTADDR_SIZE_MAX) if(addr.len > HOSTADDR_SIZE_MAX)
addr.size = HOSTADDR_SIZE_MAX; addr.len = HOSTADDR_SIZE_MAX;
server.address_len = addr.size; server.address_len = addr.len;
memcpy(server.address, addr.data, server.address_len); memcpy(server.address, addr.data, server.address_len);
// public key // public key
if(pk_base64.size > PUBLIC_KEY_BASE64_SIZE_MAX) if(pk_base64.len > PUBLIC_KEY_BASE64_SIZE_MAX)
pk_base64.size = PUBLIC_KEY_BASE64_SIZE_MAX; pk_base64.len = PUBLIC_KEY_BASE64_SIZE_MAX;
server.pk_base64_len = pk_base64.size; server.pk_base64_len = pk_base64.len;
memcpy(server.pk_base64, pk_base64.data, server.pk_base64_len); memcpy(server.pk_base64, pk_base64.data, server.pk_base64_len);
// name // name
if(name.size > SERVER_NAME_SIZE_MAX) if(name.len > SERVER_NAME_SIZE_MAX)
name.size = SERVER_NAME_SIZE_MAX; name.len = SERVER_NAME_SIZE_MAX;
server.name_len = name.size; server.name_len = name.len;
memcpy(server.name, name.data, server.name_len); memcpy(server.name, name.data, server.name_len);
// description // description
if(desc.size > SERVER_DESC_SIZE_MAX) if(desc.len > SERVER_DESC_SIZE_MAX)
desc.size = SERVER_DESC_SIZE_MAX; desc.len = SERVER_DESC_SIZE_MAX;
server.desc_len = desc.size; server.desc_len = desc.len;
memcpy(server.desc, desc.data, server.desc_len); memcpy(server.desc, desc.data, server.desc_len);
// Lock table until this function returns. // Lock table until this function returns.
@ -395,16 +397,16 @@ static Result(ServerInfo*) ClientCLI_saveServerInfo(ClientCLI* self,
// update existing server // update existing server
u64 id = *id_ptr; u64 id = *id_ptr;
try_void(idb_updateRow(self->servers.table, id, &server, false)); try_void(idb_updateRow(self->servers.table, id, &server, false));
try_assert(id < List_len(self->servers.list, ServerInfo)); try_assert(id < self->servers.list.len);
cached_row_ptr = &List_index(self->servers.list, ServerInfo, id); cached_row_ptr = self->servers.list.data + id;
memcpy(cached_row_ptr, &server, sizeof(ServerInfo)); memcpy(cached_row_ptr, &server, sizeof(ServerInfo));
} }
else { else {
// push new server // push new server
try(u64 id, u, idb_pushRow(self->servers.table, &server, false)); try(u64 id, u, idb_pushRow(self->servers.table, &server, false));
try_assert(id == List_len(self->servers.list, ServerInfo)); try_assert(id == self->servers.list.len);
List_pushMany(&self->servers.list, ServerInfo, &server, 1); List_ServerInfo_pushMany(&self->servers.list, &server, 1);
cached_row_ptr = &List_index(self->servers.list, ServerInfo, id); cached_row_ptr = self->servers.list.data + id;
try_assert(HashMap_tryPush(&self->servers.addr_id_map, addr, &id)); try_assert(HashMap_tryPush(&self->servers.addr_id_map, addr, &id));
} }

View File

@ -6,6 +6,8 @@
#include "db/idb.h" #include "db/idb.h"
#include "db/tables.h" #include "db/tables.h"
List_declare(ServerInfo);
typedef struct ClientCLI { typedef struct ClientCLI {
Client* client; Client* client;
IncrementalDB* db; IncrementalDB* db;

View File

@ -8,13 +8,13 @@ Result(void) run_RandomBytes(u32 key_size) {
printfe("generating random bytes...\n"); printfe("generating random bytes...\n");
br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable };
rng_init_sha256_seedFromSystem(&rng.vtable); rng_init_sha256_seedFromSystem(&rng.vtable);
Array(u8) random_buf = Array_alloc_size(1024); Array(u8) random_buf = Array_u8_alloc(1024);
u32 full_buffers_n = key_size / random_buf.size; u32 full_buffers_n = key_size / random_buf.len;
u32 remaining_n = key_size % random_buf.size; u32 remaining_n = key_size % random_buf.len;
while(full_buffers_n > 0){ while(full_buffers_n > 0){
full_buffers_n--; full_buffers_n--;
br_hmac_drbg_generate(&rng, random_buf.data, random_buf.size); br_hmac_drbg_generate(&rng, random_buf.data, random_buf.len);
fwrite(random_buf.data, 1, random_buf.size, stdout); fwrite(random_buf.data, 1, random_buf.len, stdout);
} }
br_hmac_drbg_generate(&rng, random_buf.data, remaining_n); br_hmac_drbg_generate(&rng, random_buf.data, remaining_n);
@ -29,15 +29,15 @@ Result(void) run_RandomBytesBase64(u32 key_size) {
printfe("generating random bytes...\n"); printfe("generating random bytes...\n");
br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable };
rng_init_sha256_seedFromSystem(&rng.vtable); rng_init_sha256_seedFromSystem(&rng.vtable);
Array(u8) random_buf = Array_alloc_size(1024); Array(u8) random_buf = Array_u8_alloc(1024);
Array(u8) base64_buf = Array_alloc_size(base64_encodedSize(random_buf.size)); Array(char) base64_buf = Array_char_alloc(base64_encodedSize(random_buf.len));
u32 full_buffers_n = key_size / random_buf.size; u32 full_buffers_n = key_size / random_buf.len;
u32 remaining_n = key_size % random_buf.size; u32 remaining_n = key_size % random_buf.len;
u32 enc_size = 0; u32 enc_size = 0;
while(full_buffers_n > 0){ while(full_buffers_n > 0){
full_buffers_n--; full_buffers_n--;
br_hmac_drbg_generate(&rng, random_buf.data, random_buf.size); br_hmac_drbg_generate(&rng, random_buf.data, random_buf.len);
enc_size = base64_encode(random_buf.data, random_buf.size, base64_buf.data); enc_size = base64_encode(random_buf.data, random_buf.len, base64_buf.data);
fwrite(base64_buf.data, 1, enc_size, stdout); fwrite(base64_buf.data, 1, enc_size, stdout);
} }

View File

@ -7,19 +7,19 @@ Result(void) run_RsaGenStdin(u32 key_size) {
Deferral(4); Deferral(4);
printfe("reading stdin...\n"); printfe("reading stdin...\n");
Array(u8) input_buf = Array_alloc_size(64*1024); Array(u8) input_buf = Array_u8_alloc(64*1024);
Defer(Array_free(input_buf)); Defer(Array_u8_destroy(&input_buf));
br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable };
br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0); br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
i64 read_n = 0; i64 read_n = 0;
do { do {
read_n = fread(input_buf.data, 1, input_buf.size, stdin); read_n = fread(input_buf.data, 1, input_buf.len, stdin);
if(read_n < 0){ if(read_n < 0){
Return RESULT_ERROR("ERROR: can't read stdin", false); Return RESULT_ERROR("ERROR: can't read stdin", false);
} }
// put bytes to rng as seed // put bytes to rng as seed
br_hmac_drbg_update(&rng, input_buf.data, read_n); br_hmac_drbg_update(&rng, input_buf.data, read_n);
} while(read_n == input_buf.size); } while(read_n == input_buf.len);
printfe("generating RSA key pair based on stdin...\n"); printfe("generating RSA key pair based on stdin...\n");
br_rsa_private_key sk; br_rsa_private_key sk;
br_rsa_public_key pk; br_rsa_public_key pk;

View File

@ -29,10 +29,10 @@ Result(void) run_ServerMode(cstr config_path) {
Defer(file_close(config_file)); Defer(file_close(config_file));
// read whole file into str // read whole file into str
Array(u8) config_buf = Array_null; Array(u8) config_buf = Array_u8_construct(NULL, 0);
try_void(file_readWhole(config_file, &config_buf)); try_void(file_readWhole(config_file, &config_buf));
Defer(Array_free(config_buf)); Defer(Array_u8_destroy(&config_buf));
str config_str = Array_castTo_str(config_buf, false); str config_str = Array_u8_castTo_str(config_buf, false);
// init server // init server
try(Server* server, p, Server_create(config_str, NULL, log_func)); try(Server* server, p, Server_create(config_str, NULL, log_func));
@ -41,7 +41,7 @@ Result(void) run_ServerMode(cstr config_path) {
// manually close file and free config_buf // manually close file and free config_buf
file_close(config_file); file_close(config_file);
config_file = NULL; config_file = NULL;
Array_free(config_buf); Array_u8_destroy(&config_buf);
config_buf.data = NULL; config_buf.data = NULL;
// start infinite loop on main thread // start infinite loop on main thread

View File

@ -6,8 +6,8 @@ void ServerConnection_close(ServerConnection* self){
return; return;
RSA_destroyPublicKey(&self->server_pk); RSA_destroyPublicKey(&self->server_pk);
EncryptedSocketTCP_destroy(&self->sock); EncryptedSocketTCP_destroy(&self->sock);
Array_free(self->token); Array_u8_destroy(&self->token);
Array_free(self->session_key); Array_u8_destroy(&self->session_key);
str_free(self->server_name); str_free(self->server_name);
str_free(self->server_description); str_free(self->server_description);
free(self); free(self);
@ -35,12 +35,12 @@ Result(ServerConnection*) ServerConnection_open(Client* client, cstr server_addr
RSAEncryptor_construct(&conn->rsa_enc, &conn->server_pk); RSAEncryptor_construct(&conn->rsa_enc, &conn->server_pk);
// lvl 2 hash - is used for authentification // lvl 2 hash - is used for authentification
conn->token = Array_alloc(u8, PASSWORD_HASH_SIZE); conn->token = Array_u8_alloc(PASSWORD_HASH_SIZE);
// hash user_data_key with server_pk once // hash user_data_key with server_pk once
Array(u8) server_pk_data = Array_construct_size(conn->server_pk.n, Array(u8) server_pk_data = Array_u8_construct(conn->server_pk.n,
BR_RSA_KBUF_PUB_SIZE(conn->server_pk.nlen * 8)); BR_RSA_KBUF_PUB_SIZE(conn->server_pk.nlen * 8));
u8 server_pk_hash[PASSWORD_HASH_SIZE]; u8 server_pk_hash[PASSWORD_HASH_SIZE];
Array(u8) server_pk_hash_array = Array_construct_size(server_pk_hash, PASSWORD_HASH_SIZE); Array(u8) server_pk_hash_array = Array_u8_construct(server_pk_hash, PASSWORD_HASH_SIZE);
hash_password(conn->client->user_data_key, server_pk_data, hash_password(conn->client->user_data_key, server_pk_data,
server_pk_hash, 1); server_pk_hash, 1);
// hash user_data_key with server_pk_hash // hash user_data_key with server_pk_hash
@ -48,10 +48,10 @@ Result(ServerConnection*) ServerConnection_open(Client* client, cstr server_addr
conn->token.data, PASSWORD_HASH_LVL_ROUNDS); conn->token.data, PASSWORD_HASH_LVL_ROUNDS);
// generate session random AES key // generate session random AES key
conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE); conn->session_key = Array_u8_alloc(AES_SESSION_KEY_SIZE);
br_hmac_drbg_context key_rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context key_rng = { .vtable = &br_hmac_drbg_vtable };
rng_init_sha256_seedFromSystem(&key_rng.vtable); rng_init_sha256_seedFromSystem(&key_rng.vtable);
br_hmac_drbg_generate(&key_rng, conn->session_key.data, conn->session_key.size); br_hmac_drbg_generate(&key_rng, conn->session_key.data, conn->session_key.len);
// connect to server address // connect to server address
try(Socket _s, i, socket_open_TCP()); try(Socket _s, i, socket_open_TCP());

View File

@ -6,7 +6,7 @@ void Client_free(Client* self){
return; return;
str_free(self->username); str_free(self->username);
Array_free(self->user_data_key); Array_u8_destroy(&self->user_data_key);
ServerConnection_close(self->conn); ServerConnection_close(self->conn);
free(self); free(self);
} }
@ -22,8 +22,8 @@ Result(Client*) Client_create(str username, str password){
self->username = str_copy(username); self->username = str_copy(username);
// lvl 1 hash - is used as AES key for user data // lvl 1 hash - is used as AES key for user data
self->user_data_key = Array_alloc(u8, PASSWORD_HASH_SIZE); self->user_data_key = Array_u8_alloc(PASSWORD_HASH_SIZE);
hash_password(str_castTo_Array(password), str_castTo_Array(username), hash_password(str_castTo_Array_u8(password), str_castTo_Array_u8(username),
self->user_data_key.data, PASSWORD_HASH_LVL_ROUNDS); self->user_data_key.data, PASSWORD_HASH_LVL_ROUNDS);
success = true; success = true;

View File

@ -11,12 +11,12 @@ Result(void) recvStr(EncryptedSocketTCP* sock, u32 size, str* out_s){
try_void( try_void(
EncryptedSocketTCP_recv( EncryptedSocketTCP_recv(
sock, sock,
str_castTo_Array(s), str_castTo_Array_u8(s),
SocketRecvFlag_WholeBuffer SocketRecvFlag_WholeBuffer
) )
); );
s.data[s.size] = 0; s.data[s.len] = 0;
*out_s = s; *out_s = s;
success = true; success = true;
Return RESULT_VOID; Return RESULT_VOID;
@ -32,8 +32,8 @@ Result(void) recvErrorMessage(EncryptedSocketTCP* sock, PacketHeader* res_header
try_void(EncryptedSocketTCP_recvStruct(sock, &res)); try_void(EncryptedSocketTCP_recvStruct(sock, &res));
// limit msg_size to fit in single EncryptedSocketTCP_recv call // limit msg_size to fit in single EncryptedSocketTCP_recv call
// TODO: receive ErrorMessage content in a loop // TODO: receive ErrorMessage content in a loop
if(res.msg_size > sock->recv_buf.size) if(res.msg_size > sock->recv_buf.len)
res.msg_size = sock->recv_buf.size; res.msg_size = sock->recv_buf.len;
str err_msg; str err_msg;
try_void(recvStr(sock, res.msg_size, &err_msg)); try_void(recvStr(sock, res.msg_size, &err_msg));

View File

@ -15,7 +15,7 @@ Result(void) _recvResponse(EncryptedSocketTCP* sock,
} }
try_void(PacketHeader_validateType(res_header, res_type)); try_void(PacketHeader_validateType(res_header, res_type));
try_void(PacketHeader_validateContentSize(res_header, res.size)); try_void(PacketHeader_validateContentSize(res_header, res.len));
try_void(EncryptedSocketTCP_recv(sock, res, SocketRecvFlag_WholeBuffer)); try_void(EncryptedSocketTCP_recv(sock, res, SocketRecvFlag_WholeBuffer));

View File

@ -11,10 +11,10 @@ Result(void) recvStr(EncryptedSocketTCP* sock, u32 size, str* out_s);
Result(void) _recvResponse(EncryptedSocketTCP* sock, Result(void) _recvResponse(EncryptedSocketTCP* sock,
PacketHeader* res_header, Array(u8) res, PacketType res_type); PacketHeader* res_header, Array(u8) res, PacketType res_type);
#define recvResponse(sock, res_header_ptr, res_ptr, res_type) \ #define recvResponse(sock, res_header_ptr, res_ptr, res_type) \
_recvResponse(sock, res_header_ptr, struct_castTo_Array(res_ptr), res_type) _recvResponse(sock, res_header_ptr, struct_castTo_Array_u8(res_ptr), res_type)
Result(void) _sendRequest(EncryptedSocketTCP* sock, Result(void) _sendRequest(EncryptedSocketTCP* sock,
PacketHeader* req_header, Array(u8) req); PacketHeader* req_header, Array(u8) req);
#define sendRequest(sock, req_header_ptr, req_ptr) \ #define sendRequest(sock, req_header_ptr, req_ptr) \
_sendRequest(sock, req_header_ptr, struct_castTo_Array(req_ptr)) _sendRequest(sock, req_header_ptr, struct_castTo_Array_u8(req_ptr))

View File

@ -2,11 +2,11 @@
Result(void) config_findValue(str config_str, str key, str* value, bool throwNotFoundError){ Result(void) config_findValue(str config_str, str key, str* value, bool throwNotFoundError){
u32 line_n = 0; u32 line_n = 0;
while(config_str.size > 0){ while(config_str.len > 0){
line_n++; line_n++;
i32 line_end = str_seekChar(config_str, '\n', 0); i32 line_end = str_seekChar(config_str, '\n', 0);
if(line_end < 0) if(line_end < 0)
line_end = config_str.size - 1; line_end = config_str.len - 1;
str line = str_sliceBefore(config_str, line_end); str line = str_sliceBefore(config_str, line_end);
config_str = str_sliceAfter(config_str, line_end + 1); config_str = str_sliceAfter(config_str, line_end + 1);
@ -27,7 +27,7 @@ Result(void) config_findValue(str config_str, str key, str* value, bool throwNot
} }
if(throwNotFoundError){ if(throwNotFoundError){
char* err_msg = sprintf_malloc("can't find key '"FMT_str"'", key.size, key.data); char* err_msg = sprintf_malloc("can't find key '"FMT_str"'", key.len, key.data);
return RESULT_ERROR(err_msg, true); return RESULT_ERROR(err_msg, true);
} }
return RESULT_VOID; return RESULT_VOID;

View File

@ -4,19 +4,19 @@
// write data from src to array and increment array data pointer // write data from src to array and increment array data pointer
static inline void __Array_writeNext(Array(u8)* dst, u8* src, size_t size){ static inline void __Array_writeNext(Array(u8)* dst, u8* src, size_t size){
memcpy(dst->data, src, size); memcpy(dst->data, src, size);
*dst = Array_sliceFrom(*dst, size); *dst = Array_u8_sliceFrom(*dst, size);
} }
// read data from array to dst and increment array data pointer // read data from array to dst and increment array data pointer
static inline void __Array_readNext(u8* dst, Array(u8)* src, size_t size){ static inline void __Array_readNext(u8* dst, Array(u8)* src, size_t size){
memcpy(dst, src->data, size); memcpy(dst, src->data, size);
*src = Array_sliceFrom(*src, size); *src = Array_u8_sliceFrom(*src, size);
} }
static void __calcKeyCheckSum(Array(u8) key, void* dst){ static void __calcKeyCheckSum(Array(u8) key, void* dst){
br_sha256_context sha_ctx; br_sha256_context sha_ctx;
br_sha256_init(&sha_ctx); br_sha256_init(&sha_ctx);
br_sha256_update(&sha_ctx, key.data, key.size); br_sha256_update(&sha_ctx, key.data, key.len);
br_sha256_out(&sha_ctx, dst); br_sha256_out(&sha_ctx, dst);
} }
@ -37,8 +37,8 @@ void AESBlockEncryptor_construct(AESBlockEncryptor* ptr,
void AESBlockEncryptor_changeKey(AESBlockEncryptor* ptr, Array(u8) key) void AESBlockEncryptor_changeKey(AESBlockEncryptor* ptr, Array(u8) key)
{ {
assert(key.size == 16 || key.size == 24 || key.size == 32); assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->enc_class->init((void*)ptr->enc_keys, key.data, key.size); ptr->enc_class->init((void*)ptr->enc_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum); __calcKeyCheckSum(key, ptr->key_checksum);
} }
@ -46,8 +46,8 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
Array(u8) src, Array(u8) dst) Array(u8) src, Array(u8) dst)
{ {
Deferral(4); Deferral(4);
u32 encrypted_size = AESBlockEncryptor_calcDstSize(src.size); u32 encrypted_size = AESBlockEncryptor_calcDstSize(src.len);
try_assert(dst.size >= encrypted_size); try_assert(dst.len >= encrypted_size);
// generate random initial vector // generate random initial vector
br_hmac_drbg_generate(&ptr->rng_ctx, ptr->iv, __AES_BLOCK_IV_SIZE); br_hmac_drbg_generate(&ptr->rng_ctx, ptr->iv, __AES_BLOCK_IV_SIZE);
@ -57,7 +57,7 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
EncryptedBlockHeader header; EncryptedBlockHeader header;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.key_checksum, ptr->key_checksum, __AES_BLOCK_KEY_CHECKSUM_SIZE); memcpy(header.key_checksum, ptr->key_checksum, __AES_BLOCK_KEY_CHECKSUM_SIZE);
header.padding_size = (16 - src.size % 16) % 16; header.padding_size = (16 - src.len % 16) % 16;
// write header to buffer // write header to buffer
memcpy(ptr->buf, &header, sizeof(header)); memcpy(ptr->buf, &header, sizeof(header));
// encrypt header // encrypt header
@ -66,7 +66,7 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
__Array_writeNext(&dst, ptr->buf, sizeof(header)); __Array_writeNext(&dst, ptr->buf, sizeof(header));
// encrypt full AESBlockEncryptor buffers // encrypt full AESBlockEncryptor buffers
while(src.size > __AES_BUFFER_SIZE){ while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE); __Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->enc_class->run((void*)ptr->enc_keys, ptr->enc_class->run((void*)ptr->enc_keys,
ptr->iv, ptr->iv,
@ -75,10 +75,10 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
} }
// encrypt buffer with remaining data // encrypt buffer with remaining data
if(src.size > 0){ if(src.len > 0){
memcpy(ptr->buf, src.data, src.size); memcpy(ptr->buf, src.data, src.len);
memset(ptr->buf + src.size, 0, header.padding_size); memset(ptr->buf + src.len, 0, header.padding_size);
u32 src_size_padded = src.size + header.padding_size; u32 src_size_padded = src.len + header.padding_size;
ptr->enc_class->run((void*)ptr->enc_keys, ptr->enc_class->run((void*)ptr->enc_keys,
ptr->iv, ptr->iv,
ptr->buf, src_size_padded); ptr->buf, src_size_padded);
@ -102,8 +102,8 @@ void AESBlockDecryptor_construct(AESBlockDecryptor* ptr,
void AESBlockDecryptor_changeKey(AESBlockDecryptor* ptr, Array(u8) key) void AESBlockDecryptor_changeKey(AESBlockDecryptor* ptr, Array(u8) key)
{ {
assert(key.size == 16 || key.size == 24 || key.size == 32); assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->dec_class->init((void*)ptr->dec_keys, key.data, key.size); ptr->dec_class->init((void*)ptr->dec_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum); __calcKeyCheckSum(key, ptr->key_checksum);
} }
@ -112,9 +112,9 @@ Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr,
{ {
Deferral(4); Deferral(4);
u32 overhead_size = AESBlockEncryptor_calcDstSize(0); u32 overhead_size = AESBlockEncryptor_calcDstSize(0);
try_assert(src.size >= overhead_size); try_assert(src.len >= overhead_size);
try_assert(src.size % 16 == 0 && "src must be array of 16-byte blocks"); try_assert(src.len % 16 == 0 && "src must be array of 16-byte blocks");
try_assert(dst.size >= src.size - overhead_size); try_assert(dst.len >= src.len - overhead_size);
// read IV from the beginning of src // read IV from the beginning of src
__Array_readNext(ptr->iv, &src, __AES_BLOCK_IV_SIZE); __Array_readNext(ptr->iv, &src, __AES_BLOCK_IV_SIZE);
@ -131,12 +131,12 @@ Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr,
} }
// size of decrypted data without padding // size of decrypted data without padding
try_assert(src.size >= header.padding_size && "invalid padding size"); try_assert(src.len >= header.padding_size && "invalid padding size");
u32 decrypted_size = src.size - header.padding_size; u32 decrypted_size = src.len - header.padding_size;
src.size = decrypted_size; src.len = decrypted_size;
// decrypt full buffers // decrypt full buffers
while(src.size > __AES_BUFFER_SIZE){ while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE); __Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->dec_class->run((void*)ptr->dec_keys, ptr->dec_class->run((void*)ptr->dec_keys,
ptr->iv, ptr->iv,
@ -145,14 +145,14 @@ Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr,
} }
// decrypt buffer with remaining data // decrypt buffer with remaining data
if(src.size > 0){ if(src.len > 0){
memcpy(ptr->buf, src.data, src.size); memcpy(ptr->buf, src.data, src.len);
memset(ptr->buf + src.size, 0, header.padding_size); memset(ptr->buf + src.len, 0, header.padding_size);
u32 src_size_padded = src.size + header.padding_size; u32 src_size_padded = src.len + header.padding_size;
ptr->dec_class->run((void*)ptr->dec_keys, ptr->dec_class->run((void*)ptr->dec_keys,
ptr->iv, ptr->iv,
ptr->buf, src_size_padded); ptr->buf, src_size_padded);
memcpy(dst.data, ptr->buf, src.size); memcpy(dst.data, ptr->buf, src.len);
} }
Return RESULT_VALUE(u, decrypted_size); Return RESULT_VALUE(u, decrypted_size);
@ -178,8 +178,8 @@ void AESStreamEncryptor_construct(AESStreamEncryptor* ptr,
void AESStreamEncryptor_changeKey(AESStreamEncryptor* ptr, Array(u8) key) void AESStreamEncryptor_changeKey(AESStreamEncryptor* ptr, Array(u8) key)
{ {
assert(key.size == 16 || key.size == 24 || key.size == 32); assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.size); ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum); __calcKeyCheckSum(key, ptr->key_checksum);
} }
@ -188,7 +188,7 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
{ {
Deferral(4); Deferral(4);
u32 encrypted_size = src.size; u32 encrypted_size = src.len;
// if it is the beginning of the stream, // if it is the beginning of the stream,
if(ptr->block_counter == 0){ if(ptr->block_counter == 0){
// write IV generated during initialization // write IV generated during initialization
@ -204,10 +204,10 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
// write checksum to dst // write checksum to dst
__Array_writeNext(&dst, key_checksum, __AES_BLOCK_KEY_CHECKSUM_SIZE); __Array_writeNext(&dst, key_checksum, __AES_BLOCK_KEY_CHECKSUM_SIZE);
} }
try_assert(dst.size >= encrypted_size); try_assert(dst.len >= encrypted_size);
// encrypt full buffers // encrypt full buffers
while(src.size > __AES_BUFFER_SIZE){ while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE); __Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys, ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter, ptr->iv, ptr->block_counter,
@ -216,12 +216,12 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
} }
// encrypt remaining data // encrypt remaining data
if(src.size > 0){ if(src.len > 0){
memcpy(ptr->buf, src.data, src.size); memcpy(ptr->buf, src.data, src.len);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys, ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter, ptr->iv, ptr->block_counter,
ptr->buf, src.size); ptr->buf, src.len);
memcpy(dst.data, ptr->buf, src.size); memcpy(dst.data, ptr->buf, src.len);
} }
Return RESULT_VALUE(u, encrypted_size); Return RESULT_VALUE(u, encrypted_size);
@ -242,8 +242,8 @@ void AESStreamDecryptor_construct(AESStreamDecryptor* ptr,
void AESStreamDecryptor_changeKey(AESStreamDecryptor* ptr, Array(u8) key) void AESStreamDecryptor_changeKey(AESStreamDecryptor* ptr, Array(u8) key)
{ {
assert(key.size == 16 || key.size == 24 || key.size == 32); assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.size); ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum); __calcKeyCheckSum(key, ptr->key_checksum);
} }
@ -270,11 +270,11 @@ Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr,
} }
} }
// size without IV // size without IV
u32 decrypted_size = src.size; u32 decrypted_size = src.len;
try_assert(dst.size >= decrypted_size); try_assert(dst.len >= decrypted_size);
// decrypt full buffers // decrypt full buffers
while(src.size > __AES_BUFFER_SIZE){ while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE); __Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys, ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter, ptr->iv, ptr->block_counter,
@ -283,12 +283,12 @@ Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr,
} }
// decrypt remaining data // decrypt remaining data
if(src.size > 0){ if(src.len > 0){
memcpy(ptr->buf, src.data, src.size); memcpy(ptr->buf, src.data, src.len);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys, ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter, ptr->iv, ptr->block_counter,
ptr->buf, src.size); ptr->buf, src.len);
memcpy(dst.data, ptr->buf, src.size); memcpy(dst.data, ptr->buf, src.len);
} }
Return RESULT_VALUE(u, decrypted_size); Return RESULT_VALUE(u, decrypted_size);

View File

@ -48,7 +48,7 @@ void AESBlockEncryptor_changeKey(AESBlockEncryptor* ptr, Array(u8) key);
/// @brief Encrypts a complete message. For part-by-part encryption use AESStreamEncryptor. /// @brief Encrypts a complete message. For part-by-part encryption use AESStreamEncryptor.
/// @param src array of any size /// @param src array of any size
/// @param dst array of size >= AESBlockEncryptor_calcDstSize(src.size) /// @param dst array of size >= AESBlockEncryptor_calcDstSize(src.len)
/// @return size of encrypted data /// @return size of encrypted data
Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr, Array(u8) src, Array(u8) dst); Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr, Array(u8) src, Array(u8) dst);
@ -75,7 +75,7 @@ void AESBlockDecryptor_changeKey(AESBlockDecryptor* ptr, Array(u8) key);
/// @brief Decrypts a complete message. For part-by-part decryption use AESStreamEncryptor. /// @brief Decrypts a complete message. For part-by-part decryption use AESStreamEncryptor.
/// @param src array of size at least AESBlockEncryptor_calcDstSize(0). Size must be multiple of 16. /// @param src array of size at least AESBlockEncryptor_calcDstSize(0). Size must be multiple of 16.
/// @param dst array of size >= src.size /// @param dst array of size >= src.len
/// @return size of decrypted data /// @return size of decrypted data
Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr, Array(u8) src, Array(u8) dst); Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr, Array(u8) src, Array(u8) dst);
@ -107,7 +107,7 @@ void AESStreamEncryptor_changeKey(AESStreamEncryptor* ptr, Array(u8) key);
/// @brief If ptr->block_counter == 0, writes random IV to `dst`. After that writes encrypted data to dst. /// @brief If ptr->block_counter == 0, writes random IV to `dst`. After that writes encrypted data to dst.
/// @param src array of any size /// @param src array of any size
/// @param dst array of size >= `AESStreamEncryptor_calcDstSize(src.size)` for first block and `src.size `for other blocks /// @param dst array of size >= `AESStreamEncryptor_calcDstSize(src.len)` for first block and `src.len `for other blocks
/// @return size of encrypted data /// @return size of encrypted data
Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr, Array(u8) src, Array(u8) dst); Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr, Array(u8) src, Array(u8) dst);
@ -134,6 +134,6 @@ void AESStreamDecryptor_changeKey(AESStreamDecryptor* ptr, Array(u8) key);
/// @brief Reads IV from `src`, then decrypts data and writes it to dst /// @brief Reads IV from `src`, then decrypts data and writes it to dst
/// @param src array of any size /// @param src array of any size
/// @param dst array of size >= src.size /// @param dst array of size >= src.len
/// @return size of decrypted data /// @return size of decrypted data
Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr, Array(u8) src, Array(u8) dst); Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr, Array(u8) src, Array(u8) dst);

View File

@ -46,7 +46,7 @@ Result(void) RSA_generateKeyPairFromPassword(u32 key_size,
{ {
Deferral(4); Deferral(4);
br_hmac_drbg_context password_based_rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context password_based_rng = { .vtable = &br_hmac_drbg_vtable };
br_hmac_drbg_init(&password_based_rng, &br_sha256_vtable, password.data, password.size); br_hmac_drbg_init(&password_based_rng, &br_sha256_vtable, password.data, password.len);
try_void(RSA_generateKeyPair(key_size, sk, pk, &password_based_rng.vtable)); try_void(RSA_generateKeyPair(key_size, sk, pk, &password_based_rng.vtable));
Return RESULT_VOID; Return RESULT_VOID;
} }
@ -129,12 +129,12 @@ Result(void) RSA_parsePublicKey_base64(cstr src, br_rsa_public_key* pk){
} }
str key_base64_str = src_str; str key_base64_str = src_str;
key_base64_str.data += offset; key_base64_str.data += offset;
key_base64_str.size -= offset; key_base64_str.len -= offset;
u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.size); u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.len);
if(decoded_size != key_buffer_size){ if(decoded_size != key_buffer_size){
Return RESULT_ERROR_FMT("decoded key size is %u, must be %u", decoded_size, key_buffer_size); Return RESULT_ERROR_FMT("decoded key size is %u, must be %u", decoded_size, key_buffer_size);
} }
decoded_size = base64_decode(key_base64_str.data, key_base64_str.size, pk->n); decoded_size = base64_decode(key_base64_str.data, key_base64_str.len, pk->n);
if(decoded_size != key_buffer_size){ if(decoded_size != key_buffer_size){
Return RESULT_ERROR("key decoding failed", false); Return RESULT_ERROR("key decoding failed", false);
} }
@ -163,12 +163,12 @@ Result(void) RSA_parsePrivateKey_base64(cstr src, br_rsa_private_key* sk){
} }
str key_base64_str = src_str; str key_base64_str = src_str;
key_base64_str.data += offset; key_base64_str.data += offset;
key_base64_str.size -= offset; key_base64_str.len -= offset;
u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.size); u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.len);
if(decoded_size != key_buffer_size){ if(decoded_size != key_buffer_size){
Return RESULT_ERROR_FMT("decoded key size is %u, must be %u", decoded_size, key_buffer_size); Return RESULT_ERROR_FMT("decoded key size is %u, must be %u", decoded_size, key_buffer_size);
} }
decoded_size = base64_decode(key_base64_str.data, key_base64_str.size, sk->p); decoded_size = base64_decode(key_base64_str.data, key_base64_str.len, sk->p);
if(decoded_size != key_buffer_size){ if(decoded_size != key_buffer_size){
Return RESULT_ERROR("key decoding failed", false); Return RESULT_ERROR("key decoding failed", false);
} }
@ -189,20 +189,20 @@ void RSAEncryptor_construct(RSAEncryptor* ptr, const br_rsa_public_key* pk){
Result(u32) RSAEncryptor_encrypt(RSAEncryptor* ptr, Array(u8) src, Array(u8) dst){ Result(u32) RSAEncryptor_encrypt(RSAEncryptor* ptr, Array(u8) src, Array(u8) dst){
u32 key_size_bytes = ptr->pk->nlen; u32 key_size_bytes = ptr->pk->nlen;
const u32 max_src_size = RSAEncryptor_calcMaxSrcSize(key_size_bytes * 8, 256); const u32 max_src_size = RSAEncryptor_calcMaxSrcSize(key_size_bytes * 8, 256);
if(src.size > max_src_size){ if(src.len > max_src_size){
return RESULT_ERROR_FMT("src.size (%u) must be <= RSAEncryptor_calcMaxSrcSize() (%u)", return RESULT_ERROR_FMT("src.len (%u) must be <= RSAEncryptor_calcMaxSrcSize() (%u)",
src.size, max_src_size); src.len, max_src_size);
} }
if(dst.size < key_size_bytes){ if(dst.len < key_size_bytes){
return RESULT_ERROR_FMT("dst.size (%u) must be >= key length in bytes (%u)", return RESULT_ERROR_FMT("dst.len (%u) must be >= key length in bytes (%u)",
dst.size, key_size_bytes); dst.len, key_size_bytes);
} }
size_t sz = br_rsa_i31_oaep_encrypt( size_t sz = br_rsa_i31_oaep_encrypt(
&ptr->rng.vtable, &br_sha256_vtable, &ptr->rng.vtable, &br_sha256_vtable,
NULL, 0, NULL, 0,
ptr->pk, ptr->pk,
dst.data, dst.size, dst.data, dst.len,
src.data, src.size); src.data, src.len);
if(sz == 0){ if(sz == 0){
return RESULT_ERROR("RSA encryption failed", false); return RESULT_ERROR("RSA encryption failed", false);
@ -221,12 +221,12 @@ void RSADecryptor_construct(RSADecryptor* ptr, const br_rsa_private_key* sk){
Result(u32) RSADecryptor_decrypt(RSADecryptor* ptr, Array(u8) buffer){ Result(u32) RSADecryptor_decrypt(RSADecryptor* ptr, Array(u8) buffer){
u32 key_size_bits = ptr->sk->n_bitlen; u32 key_size_bits = ptr->sk->n_bitlen;
if(buffer.size != key_size_bits/8){ if(buffer.len != key_size_bits/8){
return RESULT_ERROR_FMT("buffer.size (%u) must be == key length in bytes (%u)", return RESULT_ERROR_FMT("buffer.len (%u) must be == key length in bytes (%u)",
buffer.size, key_size_bits/8); buffer.len, key_size_bits/8);
} }
size_t sz = buffer.size; size_t sz = buffer.len;
size_t r = br_rsa_i31_oaep_decrypt( size_t r = br_rsa_i31_oaep_decrypt(
&br_sha256_vtable, &br_sha256_vtable,
NULL, 0, NULL, 0,

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "tlibc/collections/Array.h"
#include "tlibc/errors.h" #include "tlibc/errors.h"
#include "tlibc/collections/Array.h"
#include "tlibc/collections/Array_impl/Array_u8.h"
#include "bearssl_rand.h" #include "bearssl_rand.h"
#include "bearssl_hash.h" #include "bearssl_hash.h"
#include "tcp-chat/common_constants.h" #include "tcp-chat/common_constants.h"

View File

@ -8,8 +8,8 @@ void hash_password(Array(u8) password, Array(u8) salt, u8* out_buffer, i32 itera
br_sha256_init(&sha256_ctx); br_sha256_init(&sha256_ctx);
for(i32 i = 0; i < iterations; i++){ for(i32 i = 0; i < iterations; i++){
br_sha256_update(&sha256_ctx, password.data, password.size); br_sha256_update(&sha256_ctx, password.data, password.len);
br_sha256_update(&sha256_ctx, salt.data, salt.size); br_sha256_update(&sha256_ctx, salt.data, salt.len);
br_sha256_out(&sha256_ctx, out_buffer); br_sha256_out(&sha256_ctx, out_buffer);
br_sha256_update(&sha256_ctx, out_buffer, PASSWORD_HASH_SIZE); br_sha256_update(&sha256_ctx, out_buffer, PASSWORD_HASH_SIZE);
} }

View File

@ -53,7 +53,7 @@ static void Table_close(Table* t){
str_free(t->table_file_path); str_free(t->table_file_path);
str_free(t->changes_file_path); str_free(t->changes_file_path);
pthread_mutex_destroy(&t->mutex); pthread_mutex_destroy(&t->mutex);
Array_free(t->enc_buf); Array_u8_destroy(&t->enc_buf);
free(t); free(t);
} }
@ -159,7 +159,7 @@ static Result(void) Table_validateHeader(Table* t){
static Result(void) Table_validateEncryption(Table* t){ static Result(void) Table_validateEncryption(Table* t){
Deferral(1); Deferral(1);
bool db_encrypted = t->db->aes_key.size != 0; bool db_encrypted = t->db->aes_key.len != 0;
if(t->header.encrypted && !db_encrypted){ if(t->header.encrypted && !db_encrypted){
Return RESULT_ERROR_FMT( Return RESULT_ERROR_FMT(
"Table '%s' is encrypted, but encryption key is not set." "Table '%s' is encrypted, but encryption key is not set."
@ -179,7 +179,7 @@ static Result(void) Table_validateEncryption(Table* t){
try_void( try_void(
AESBlockDecryptor_decrypt( AESBlockDecryptor_decrypt(
&t->dec, &t->dec,
Array_construct_size(t->header.key_challenge, KEY_CHALLENGE_CIPHER_SIZE), Array_u8_construct(t->header.key_challenge, KEY_CHALLENGE_CIPHER_SIZE),
t->enc_buf t->enc_buf
) )
); );
@ -208,7 +208,7 @@ void idb_close(IncrementalDB* db){
if(db == NULL) if(db == NULL)
return; return;
str_free(db->db_dir); str_free(db->db_dir);
Array_free(db->aes_key); Array_u8_destroy(&db->aes_key);
HashMap_destroy(&db->tables_map); HashMap_destroy(&db->tables_map);
pthread_mutex_destroy(&db->mutex); pthread_mutex_destroy(&db->mutex);
free(db); free(db);
@ -216,7 +216,7 @@ void idb_close(IncrementalDB* db){
Result(IncrementalDB*) idb_open(str db_dir, NULLABLE(Array(u8) aes_key)){ Result(IncrementalDB*) idb_open(str db_dir, NULLABLE(Array(u8) aes_key)){
Deferral(16); Deferral(16);
try_assert(aes_key.size == 0 || aes_key.size == 16 || aes_key.size == 24 || aes_key.size == 32); try_assert(aes_key.len == 0 || aes_key.len == 16 || aes_key.len == 24 || aes_key.len == 32);
IncrementalDB* db = (IncrementalDB*)malloc(sizeof(IncrementalDB)); IncrementalDB* db = (IncrementalDB*)malloc(sizeof(IncrementalDB));
// value of *db must be set to zero or behavior of idb_close will be undefined // value of *db must be set to zero or behavior of idb_close will be undefined
@ -225,8 +225,8 @@ Result(IncrementalDB*) idb_open(str db_dir, NULLABLE(Array(u8) aes_key)){
bool success = false; bool success = false;
Defer(if(!success) idb_close(db)); Defer(if(!success) idb_close(db));
if(aes_key.size != 0){ if(aes_key.len != 0){
db->aes_key = Array_copy(aes_key); db->aes_key = Array_u8_copy(aes_key);
} }
db->db_dir = str_copy(db_dir); db->db_dir = str_copy(db_dir);
@ -295,11 +295,11 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str table_name, u32 row_s
try(t->changes_file, p, file_openOrCreateReadWrite(t->changes_file_path.data)); try(t->changes_file, p, file_openOrCreateReadWrite(t->changes_file_path.data));
// init encryptor and decryptor now to use them in table header validation/creation // init encryptor and decryptor now to use them in table header validation/creation
if(db->aes_key.size != 0) { if(db->aes_key.len != 0) {
AESBlockEncryptor_construct(&t->enc, db->aes_key, AESBlockEncryptor_DEFAULT_CLASS); AESBlockEncryptor_construct(&t->enc, db->aes_key, AESBlockEncryptor_DEFAULT_CLASS);
AESBlockDecryptor_construct(&t->dec, db->aes_key, AESBlockDecryptor_DEFAULT_CLASS); AESBlockDecryptor_construct(&t->dec, db->aes_key, AESBlockDecryptor_DEFAULT_CLASS);
u32 row_size_in_file = AESBlockEncryptor_calcDstSize(row_size); u32 row_size_in_file = AESBlockEncryptor_calcDstSize(row_size);
t->enc_buf = Array_alloc_size(row_size_in_file); t->enc_buf = Array_u8_alloc(row_size_in_file);
} }
// init header // init header
@ -315,15 +315,15 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str table_name, u32 row_s
// create table file // create table file
t->header.magic.n = TABLE_FILE_MAGIC.n; t->header.magic.n = TABLE_FILE_MAGIC.n;
t->header.version = IDB_VERSION; t->header.version = IDB_VERSION;
t->header.encrypted = db->aes_key.size != 0; t->header.encrypted = db->aes_key.len != 0;
t->header._dirty_bit = false; t->header._dirty_bit = false;
t->header.row_size = row_size; t->header.row_size = row_size;
memset(t->header.key_challenge, 0, KEY_CHALLENGE_CIPHER_SIZE); memset(t->header.key_challenge, 0, KEY_CHALLENGE_CIPHER_SIZE);
try_void( try_void(
AESBlockEncryptor_encrypt( AESBlockEncryptor_encrypt(
&t->enc, &t->enc,
Array_construct_size((void*)KEY_CHALLENGE_PLAIN, KEY_CHALLENGE_PLAIN_SIZE), Array_u8_construct((void*)KEY_CHALLENGE_PLAIN, KEY_CHALLENGE_PLAIN_SIZE),
Array_construct_size(t->header.key_challenge, KEY_CHALLENGE_CIPHER_SIZE) Array_u8_construct(t->header.key_challenge, KEY_CHALLENGE_CIPHER_SIZE)
) )
); );
try_void(Table_writeHeader(t)); try_void(Table_writeHeader(t));
@ -355,7 +355,7 @@ Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count, bool lock_table
} }
u32 row_size = t->header.row_size; u32 row_size = t->header.row_size;
u32 row_size_in_file = t->header.encrypted ? t->enc_buf.size : row_size; u32 row_size_in_file = t->header.encrypted ? t->enc_buf.len : row_size;
i64 file_pos = sizeof(t->header) + id * row_size_in_file; i64 file_pos = sizeof(t->header) + id * row_size_in_file;
// seek for the row position in file // seek for the row position in file
@ -373,7 +373,7 @@ Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count, bool lock_table
AESBlockDecryptor_decrypt( AESBlockDecryptor_decrypt(
&t->dec, &t->dec,
t->enc_buf, t->enc_buf,
Array_construct_size(row_ptr, row_size) Array_u8_construct(row_ptr, row_size)
) )
); );
} }
@ -401,7 +401,7 @@ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count, bool l
Defer(IGNORE_RESULT Table_setDirtyBit(t, false)); Defer(IGNORE_RESULT Table_setDirtyBit(t, false));
u32 row_size = t->header.row_size; u32 row_size = t->header.row_size;
u32 row_size_in_file = t->header.encrypted ? t->enc_buf.size : row_size; u32 row_size_in_file = t->header.encrypted ? t->enc_buf.len : row_size;
i64 file_pos = sizeof(t->header) + id * row_size_in_file; i64 file_pos = sizeof(t->header) + id * row_size_in_file;
// TODO: set dirty bit in backup file too // TODO: set dirty bit in backup file too
@ -417,7 +417,7 @@ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count, bool l
try_void( try_void(
AESBlockEncryptor_encrypt( AESBlockEncryptor_encrypt(
&t->enc, &t->enc,
Array_construct_size(row_ptr, row_size), Array_u8_construct(row_ptr, row_size),
t->enc_buf t->enc_buf
) )
); );
@ -441,7 +441,7 @@ Result(u64) idb_pushRows(Table* t, const void* src, u64 count, bool lock_table){
Defer(IGNORE_RESULT Table_setDirtyBit(t, false)); Defer(IGNORE_RESULT Table_setDirtyBit(t, false));
u32 row_size = t->header.row_size; u32 row_size = t->header.row_size;
u32 row_size_in_file = t->header.encrypted ? t->enc_buf.size : row_size; u32 row_size_in_file = t->header.encrypted ? t->enc_buf.len : row_size;
const u64 new_row_index = t->row_count; const u64 new_row_index = t->row_count;
// seek for end of the file // seek for end of the file
@ -454,7 +454,7 @@ Result(u64) idb_pushRows(Table* t, const void* src, u64 count, bool lock_table){
try_void( try_void(
AESBlockEncryptor_encrypt( AESBlockEncryptor_encrypt(
&t->enc, &t->enc,
Array_construct_size(row_ptr, row_size), Array_u8_construct(row_ptr, row_size),
t->enc_buf t->enc_buf
) )
); );
@ -487,14 +487,15 @@ Result(void) idb_createListFromTable(Table* t, List_* l, bool lock_table){
Defer(idb_unlockTable(t)); Defer(idb_unlockTable(t));
} }
u64 rows_count = t->row_count; u64 row_count = t->row_count;
u64 total_size = rows_count * t->header.row_size; u64 row_size = t->header.row_size;
*l = List_alloc_size(total_size); u64 total_size = row_count * row_size;
l->size = total_size; *l = _List_alloc(total_size, row_size);
l->len = row_count;
bool success = false; bool success = false;
Defer(if(!success) List_destroy(l)); Defer(if(!success) _List_destroy(l));
try_void(idb_getRows(t, 0, l->data, rows_count, false)); try_void(idb_getRows(t, 0, l->data, row_count, false));
success = true; success = true;
Return RESULT_VOID; Return RESULT_VOID;

View File

@ -10,16 +10,16 @@ void EncryptedSocketTCP_construct(EncryptedSocketTCP* ptr,
ptr->sock = sock; ptr->sock = sock;
AESStreamEncryptor_construct(&ptr->enc, aes_key, AESStream_DEFAULT_CLASS); AESStreamEncryptor_construct(&ptr->enc, aes_key, AESStream_DEFAULT_CLASS);
AESStreamDecryptor_construct(&ptr->dec, aes_key, AESStream_DEFAULT_CLASS); AESStreamDecryptor_construct(&ptr->dec, aes_key, AESStream_DEFAULT_CLASS);
ptr->recv_buf = Array_alloc_size(crypto_buffer_size); ptr->recv_buf = Array_u8_alloc(crypto_buffer_size);
ptr->send_buf = Array_alloc_size(crypto_buffer_size); ptr->send_buf = Array_u8_alloc(crypto_buffer_size);
} }
void EncryptedSocketTCP_destroy(EncryptedSocketTCP* ptr){ void EncryptedSocketTCP_destroy(EncryptedSocketTCP* ptr){
if(!ptr) if(!ptr)
return; return;
socket_close(ptr->sock); socket_close(ptr->sock);
Array_free(ptr->recv_buf); Array_u8_destroy(&ptr->recv_buf);
Array_free(ptr->send_buf); Array_u8_destroy(&ptr->send_buf);
} }
void EncryptedSocketTCP_changeKey(EncryptedSocketTCP* ptr, Array(u8) aes_key){ void EncryptedSocketTCP_changeKey(EncryptedSocketTCP* ptr, Array(u8) aes_key){
@ -42,11 +42,11 @@ Result(void) EncryptedSocketTCP_send(EncryptedSocketTCP* ptr,
try_void( try_void(
socket_send( socket_send(
ptr->sock, ptr->sock,
Array_sliceTo(ptr->send_buf, encrypted_size) Array_u8_sliceTo(ptr->send_buf, encrypted_size)
) )
); );
// printf("SEND data_size: %u, enc_size: %u\n", buffer.size, encrypted_size); // printf("SEND data_size: %u, enc_size: %u\n", buffer.len, encrypted_size);
Return RESULT_VOID; Return RESULT_VOID;
} }
@ -55,7 +55,7 @@ Result(u32) EncryptedSocketTCP_recv(EncryptedSocketTCP* ptr,
{ {
Deferral(1); Deferral(1);
u32 size_to_receive = buffer.size; u32 size_to_receive = buffer.len;
if(ptr->dec.block_counter == 0){ if(ptr->dec.block_counter == 0){
// There is some metadata at the beginning of AES stream // There is some metadata at the beginning of AES stream
size_to_receive = AESStreamEncryptor_calcDstSize(size_to_receive); size_to_receive = AESStreamEncryptor_calcDstSize(size_to_receive);
@ -63,14 +63,14 @@ Result(u32) EncryptedSocketTCP_recv(EncryptedSocketTCP* ptr,
try(i32 received_size, i, try(i32 received_size, i,
socket_recv( socket_recv(
ptr->sock, ptr->sock,
Array_sliceTo(ptr->recv_buf, size_to_receive), Array_u8_sliceTo(ptr->recv_buf, size_to_receive),
flags flags
) )
); );
try(u32 decrypted_size, u, try(u32 decrypted_size, u,
AESStreamDecryptor_decrypt( AESStreamDecryptor_decrypt(
&ptr->dec, &ptr->dec,
Array_sliceTo(ptr->recv_buf, received_size), Array_u8_sliceTo(ptr->recv_buf, received_size),
buffer buffer
) )
); );
@ -94,11 +94,11 @@ Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr,
try_void( try_void(
socket_send( socket_send(
ptr->sock, ptr->sock,
Array_sliceTo(ptr->send_buf, encrypted_size) Array_u8_sliceTo(ptr->send_buf, encrypted_size)
) )
); );
// printf("SEND-RSA data_size: %u, enc_size: %u\n", buffer.size, encrypted_size); // printf("SEND-RSA data_size: %u, enc_size: %u\n", buffer.len, encrypted_size);
Return RESULT_VOID; Return RESULT_VOID;
} }
@ -119,30 +119,30 @@ Result(u32) EncryptedSocketTCP_recvRSA(EncryptedSocketTCP* ptr,
try(i32 received_size, i, try(i32 received_size, i,
socket_recv( socket_recv(
ptr->sock, ptr->sock,
Array_sliceTo(ptr->recv_buf, size_to_receive), Array_u8_sliceTo(ptr->recv_buf, size_to_receive),
flags flags
) )
); );
try(u32 decrypted_size, u, try(u32 decrypted_size, u,
RSADecryptor_decrypt( RSADecryptor_decrypt(
rsa_dec, rsa_dec,
Array_sliceTo(ptr->recv_buf, received_size) Array_u8_sliceTo(ptr->recv_buf, received_size)
) )
); );
if(fill_whole_buffer){ if(fill_whole_buffer){
if(decrypted_size != buffer.size){ if(decrypted_size != buffer.len){
Return RESULT_ERROR_FMT( Return RESULT_ERROR_FMT(
"SocketRecvFlag_WholeBuffer is set, " "SocketRecvFlag_WholeBuffer is set, "
"but decrypted_size (%u) != buffer.size (%u)", "but decrypted_size (%u) != buffer.len (%u)",
decrypted_size, buffer.size decrypted_size, buffer.len
); );
} }
} }
else if(decrypted_size > buffer.size){ else if(decrypted_size > buffer.len){
Return RESULT_ERROR_FMT( Return RESULT_ERROR_FMT(
"decrypted_size (%u) > buffer.size (%u)", "decrypted_size (%u) > buffer.len (%u)",
decrypted_size, buffer.size decrypted_size, buffer.len
); );
} }
@ -163,16 +163,16 @@ void EncryptedSocketUDP_construct(EncryptedSocketUDP* ptr,
ptr->sock = sock; ptr->sock = sock;
AESBlockEncryptor_construct(&ptr->enc, aes_key, AESBlockEncryptor_DEFAULT_CLASS); AESBlockEncryptor_construct(&ptr->enc, aes_key, AESBlockEncryptor_DEFAULT_CLASS);
AESBlockDecryptor_construct(&ptr->dec, aes_key, AESBlockDecryptor_DEFAULT_CLASS); AESBlockDecryptor_construct(&ptr->dec, aes_key, AESBlockDecryptor_DEFAULT_CLASS);
ptr->recv_buf = Array_alloc_size(crypto_buffer_size); ptr->recv_buf = Array_u8_alloc(crypto_buffer_size);
ptr->send_buf = Array_alloc_size(crypto_buffer_size); ptr->send_buf = Array_u8_alloc(crypto_buffer_size);
} }
void EncryptedSocketUDP_destroy(EncryptedSocketUDP* ptr){ void EncryptedSocketUDP_destroy(EncryptedSocketUDP* ptr){
if(!ptr) if(!ptr)
return; return;
socket_close(ptr->sock); socket_close(ptr->sock);
Array_free(ptr->recv_buf); Array_u8_destroy(&ptr->recv_buf);
Array_free(ptr->send_buf); Array_u8_destroy(&ptr->send_buf);
} }
void EncryptedSocketUDP_changeKey(EncryptedSocketUDP* ptr, Array(u8) aes_key){ void EncryptedSocketUDP_changeKey(EncryptedSocketUDP* ptr, Array(u8) aes_key){
@ -195,7 +195,7 @@ Result(void) EncryptedSocketUDP_sendto(EncryptedSocketUDP* ptr,
try_void( try_void(
socket_sendto( socket_sendto(
ptr->sock, ptr->sock,
Array_sliceTo(ptr->send_buf, encrypted_size), Array_u8_sliceTo(ptr->send_buf, encrypted_size),
remote_end remote_end
) )
); );
@ -209,11 +209,11 @@ Result(i32) EncryptedSocketUDP_recvfrom(EncryptedSocketUDP* ptr,
Deferral(1); Deferral(1);
// There is some metadata at the start of each AES block // There is some metadata at the start of each AES block
u32 size_to_receive = AESBlockEncryptor_calcDstSize(buffer.size); u32 size_to_receive = AESBlockEncryptor_calcDstSize(buffer.len);
try(i32 received_size, i, try(i32 received_size, i,
socket_recvfrom( socket_recvfrom(
ptr->sock, ptr->sock,
Array_sliceTo(ptr->recv_buf, size_to_receive), Array_u8_sliceTo(ptr->recv_buf, size_to_receive),
flags, flags,
remote_end remote_end
) )
@ -221,7 +221,7 @@ Result(i32) EncryptedSocketUDP_recvfrom(EncryptedSocketUDP* ptr,
try(u32 decrypted_size, u, try(u32 decrypted_size, u,
AESBlockDecryptor_decrypt( AESBlockDecryptor_decrypt(
&ptr->dec, &ptr->dec,
Array_sliceTo(ptr->recv_buf, received_size), Array_u8_sliceTo(ptr->recv_buf, received_size),
buffer buffer
) )
); );

View File

@ -28,14 +28,14 @@ Result(void) EncryptedSocketTCP_send(EncryptedSocketTCP* ptr,
#define EncryptedSocketTCP_sendStruct(socket, structPtr)\ #define EncryptedSocketTCP_sendStruct(socket, structPtr)\
EncryptedSocketTCP_send(socket,\ EncryptedSocketTCP_send(socket,\
Array_construct_size(structPtr, sizeof(*structPtr))) struct_castTo_Array_u8(structPtr))
Result(u32) EncryptedSocketTCP_recv(EncryptedSocketTCP* ptr, Result(u32) EncryptedSocketTCP_recv(EncryptedSocketTCP* ptr,
Array(u8) buffer, SocketRecvFlag flags); Array(u8) buffer, SocketRecvFlag flags);
#define EncryptedSocketTCP_recvStruct(socket, structPtr)\ #define EncryptedSocketTCP_recvStruct(socket, structPtr)\
EncryptedSocketTCP_recv(socket,\ EncryptedSocketTCP_recv(socket,\
Array_construct_size(structPtr, sizeof(*structPtr)),\ struct_castTo_Array_u8(structPtr),\
SocketRecvFlag_WholeBuffer) SocketRecvFlag_WholeBuffer)
Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr, Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr,
@ -43,14 +43,14 @@ Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr,
#define EncryptedSocketTCP_sendStructRSA(socket, rsa_enc, structPtr)\ #define EncryptedSocketTCP_sendStructRSA(socket, rsa_enc, structPtr)\
EncryptedSocketTCP_sendRSA(socket, rsa_enc,\ EncryptedSocketTCP_sendRSA(socket, rsa_enc,\
Array_construct_size(structPtr, sizeof(*structPtr))) struct_castTo_Array_u8(structPtr))
Result(u32) EncryptedSocketTCP_recvRSA(EncryptedSocketTCP* ptr, Result(u32) EncryptedSocketTCP_recvRSA(EncryptedSocketTCP* ptr,
RSADecryptor* rsa_dec, Array(u8) buffer, SocketRecvFlag flags); RSADecryptor* rsa_dec, Array(u8) buffer, SocketRecvFlag flags);
#define EncryptedSocketTCP_recvStructRSA(socket, rsa_dec, structPtr)\ #define EncryptedSocketTCP_recvStructRSA(socket, rsa_dec, structPtr)\
EncryptedSocketTCP_recvRSA(socket, rsa_dec,\ EncryptedSocketTCP_recvRSA(socket, rsa_dec,\
Array_construct_size(structPtr, sizeof(*structPtr)),\ struct_castTo_Array_u8(structPtr),\
SocketRecvFlag_WholeBuffer) SocketRecvFlag_WholeBuffer)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -60,11 +60,11 @@ Result(void) socket_connect(Socket s, EndpointIPv4 remote_end){
} }
Result(void) socket_send(Socket s, Array(u8) buffer){ Result(void) socket_send(Socket s, Array(u8) buffer){
i32 r = send(s, buffer.data, buffer.size, 0); i32 r = send(s, (void*)buffer.data, buffer.len, 0);
if(r < 0){ if(r < 0){
return RESULT_ERROR_SOCKET(); return RESULT_ERROR_SOCKET();
} }
if((u32)r != buffer.size){ if((u32)r != buffer.len){
return RESULT_ERROR_FMT("Socket was unable to send data"); return RESULT_ERROR_FMT("Socket was unable to send data");
} }
return RESULT_VOID; return RESULT_VOID;
@ -72,11 +72,11 @@ Result(void) socket_send(Socket s, Array(u8) buffer){
Result(void) socket_sendto(Socket s, Array(u8) buffer, EndpointIPv4 dst){ Result(void) socket_sendto(Socket s, Array(u8) buffer, EndpointIPv4 dst){
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(dst); struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(dst);
i32 r = sendto(s, buffer.data, buffer.size, 0, (void*)&sockaddr, sizeof(sockaddr)); i32 r = sendto(s, (void*)buffer.data, buffer.len, 0, (void*)&sockaddr, sizeof(sockaddr));
if(r < 0){ if(r < 0){
return RESULT_ERROR_SOCKET(); return RESULT_ERROR_SOCKET();
} }
if((u32)r != buffer.size){ if((u32)r != buffer.len){
return RESULT_ERROR_FMT("Socket was unable to send data"); return RESULT_ERROR_FMT("Socket was unable to send data");
} }
return RESULT_VOID; return RESULT_VOID;
@ -92,11 +92,11 @@ static inline int SocketRecvFlags_toStd(SocketRecvFlag flags){
} }
Result(i32) socket_recv(Socket s, Array(u8) buffer, SocketRecvFlag flags){ Result(i32) socket_recv(Socket s, Array(u8) buffer, SocketRecvFlag flags){
i32 r = recv(s, buffer.data, buffer.size, SocketRecvFlags_toStd(flags)); i32 r = recv(s, (void*)buffer.data, buffer.len, SocketRecvFlags_toStd(flags));
if(r < 0){ if(r < 0){
return RESULT_ERROR_SOCKET(); return RESULT_ERROR_SOCKET();
} }
if(r == 0 || (flags & SocketRecvFlag_WholeBuffer && (u32)r != buffer.size)) if(r == 0 || (flags & SocketRecvFlag_WholeBuffer && (u32)r != buffer.len))
{ {
return RESULT_ERROR("Socket closed", false); return RESULT_ERROR("Socket closed", false);
} }
@ -106,12 +106,12 @@ Result(i32) socket_recv(Socket s, Array(u8) buffer, SocketRecvFlag flags){
Result(i32) socket_recvfrom(Socket s, Array(u8) buffer, SocketRecvFlag flags, NULLABLE(EndpointIPv4*) remote_end){ Result(i32) socket_recvfrom(Socket s, Array(u8) buffer, SocketRecvFlag flags, NULLABLE(EndpointIPv4*) remote_end){
struct sockaddr_in remote_addr = {0}; struct sockaddr_in remote_addr = {0};
i32 sockaddr_size = sizeof(remote_addr); i32 sockaddr_size = sizeof(remote_addr);
i32 r = recvfrom(s, buffer.data, buffer.size, SocketRecvFlags_toStd(flags), i32 r = recvfrom(s, (void*)buffer.data, buffer.len, SocketRecvFlags_toStd(flags),
(struct sockaddr*)&remote_addr, (void*)&sockaddr_size); (struct sockaddr*)&remote_addr, (void*)&sockaddr_size);
if(r < 0){ if(r < 0){
return RESULT_ERROR_SOCKET(); return RESULT_ERROR_SOCKET();
} }
if(r == 0 || (flags & SocketRecvFlag_WholeBuffer && (u32)r != buffer.size)) if(r == 0 || (flags & SocketRecvFlag_WholeBuffer && (u32)r != buffer.len))
{ {
return RESULT_ERROR("Socket closed", false); return RESULT_ERROR("Socket closed", false);
} }

View File

@ -16,7 +16,7 @@ str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_
} }
str validateUsername_str(str username){ str validateUsername_str(str username){
if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){ if(username.len < USERNAME_SIZE_MIN || username.len > USERNAME_SIZE_MAX){
return str_from_cstr( return str_from_cstr(
sprintf_malloc( sprintf_malloc(
"username length (in bytes) must be >= %i and <= %i\n", "username length (in bytes) must be >= %i and <= %i\n",
@ -25,7 +25,7 @@ str validateUsername_str(str username){
); );
} }
for(u32 i = 0; i < username.size; i++){ for(u32 i = 0; i < username.len; i++){
char c = username.data[i]; char c = username.data[i];
if (char_isLatinLower(c) || if (char_isLatinLower(c) ||
char_isLatinUpper(c) || char_isLatinUpper(c) ||
@ -56,8 +56,8 @@ Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* he
_PacketHeader_construct(ClientHandshake); _PacketHeader_construct(ClientHandshake);
memset(ptr, 0, sizeof(*ptr)); memset(ptr, 0, sizeof(*ptr));
try_assert(session_key.size == sizeof(ptr->session_key)); try_assert(session_key.len == sizeof(ptr->session_key));
memcpy(ptr->session_key, session_key.data, session_key.size); memcpy(ptr->session_key, session_key.data, session_key.len);
Return RESULT_VOID; Return RESULT_VOID;
} }
@ -97,10 +97,10 @@ Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
if(name_error_str.data){ if(name_error_str.data){
Return RESULT_ERROR(name_error_str.data, true); Return RESULT_ERROR(name_error_str.data, true);
} }
memcpy(ptr->username, username.data, username.size); memcpy(ptr->username, username.data, username.len);
try_assert(token.size == sizeof(ptr->token)); try_assert(token.len == sizeof(ptr->token));
memcpy(ptr->token, token.data, token.size); memcpy(ptr->token, token.data, token.len);
Return RESULT_VOID; Return RESULT_VOID;
} }
@ -126,10 +126,10 @@ Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* he
if(name_error_str.data){ if(name_error_str.data){
Return RESULT_ERROR(name_error_str.data, true); Return RESULT_ERROR(name_error_str.data, true);
} }
memcpy(ptr->username, username.data, username.size); memcpy(ptr->username, username.data, username.len);
try_assert(token.size == sizeof(ptr->token)); try_assert(token.len == sizeof(ptr->token));
memcpy(ptr->token, token.data, token.size); memcpy(ptr->token, token.data, token.len);
Return RESULT_VOID; Return RESULT_VOID;
} }

View File

@ -5,7 +5,7 @@ void ClientConnection_close(ClientConnection* conn){
if(!conn) if(!conn)
return; return;
EncryptedSocketTCP_destroy(&conn->sock); EncryptedSocketTCP_destroy(&conn->sock);
Array_free(conn->session_key); Array_u8_destroy(&conn->session_key);
free(conn); free(conn);
} }
@ -22,9 +22,9 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
conn->client_end = args->client_end; conn->client_end = args->client_end;
conn->session_id = args->session_id; conn->session_id = args->session_id;
conn->authorized = false; conn->authorized = false;
conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE); conn->session_key = Array_u8_alloc(AES_SESSION_KEY_SIZE);
// correct session key will be received from client later // correct session key will be received from client later
Array_memset(conn->session_key, 0); Array_u8_memset(&conn->session_key, 0);
EncryptedSocketTCP_construct(&conn->sock, args->accepted_socket_tcp, NETWORK_BUFFER_SIZE, conn->session_key); EncryptedSocketTCP_construct(&conn->sock, args->accepted_socket_tcp, NETWORK_BUFFER_SIZE, conn->session_key);
try_void(socket_TCP_enableAliveChecks_default(args->accepted_socket_tcp)); try_void(socket_TCP_enableAliveChecks_default(args->accepted_socket_tcp));
@ -44,7 +44,7 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &client_handshake)); try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &client_handshake));
// use received session key // use received session key
memcpy(conn->session_key.data, client_handshake.session_key, conn->session_key.size); memcpy(conn->session_key.data, client_handshake.session_key, conn->session_key.len);
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key); EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
// send ServerHandshake // send ServerHandshake

View File

@ -14,10 +14,10 @@ declare_RequestHandler(GetMessageBlock)
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
// send response // send response
GetMessageBlockResponse res; // GetMessageBlockResponse res;
GetMessageBlockResponse_construct(&res, res_head, ); // GetMessageBlockResponse_construct(&res, res_head, );
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); // try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); // try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
Return RESULT_VOID; Return RESULT_VOID;
} }

View File

@ -54,8 +54,8 @@ declare_RequestHandler(Login)
u64 user_id = *id_ptr; u64 user_id = *id_ptr;
// get user by id // get user by id
try_assert(user_id < List_len(conn->server->users.cache_list, UserInfo)); try_assert(user_id < conn->server->users.cache_list.len);
UserInfo* u = &List_index(conn->server->users.cache_list, UserInfo, user_id); UserInfo* u = conn->server->users.cache_list.data + user_id;
// validate token hash // validate token hash
if(memcmp(req.token, u->token, sizeof(req.token)) != 0){ if(memcmp(req.token, u->token, sizeof(req.token)) != 0){

View File

@ -55,7 +55,7 @@ declare_RequestHandler(Register)
UserInfo user; UserInfo user;
memset(&user, 0, sizeof(UserInfo)); memset(&user, 0, sizeof(UserInfo));
user.name_len = username_str.size; user.name_len = username_str.len;
memcpy(user.name, username_str.data, user.name_len); memcpy(user.name, username_str.data, user.name_len);
memcpy(user.token, req.token, sizeof(req.token)); memcpy(user.token, req.token, sizeof(req.token));
@ -66,8 +66,8 @@ declare_RequestHandler(Register)
try(u64 user_id, u, try(u64 user_id, u,
idb_pushRow(conn->server->users.table, &user, false) idb_pushRow(conn->server->users.table, &user, false)
); );
try_assert(user_id == List_len(conn->server->users.cache_list, UserInfo)); try_assert(user_id == conn->server->users.cache_list.len);
List_pushMany(&conn->server->users.cache_list, UserInfo, &user, 1); List_UserInfo_pushMany(&conn->server->users.cache_list, &user, 1);
try_assert(HashMap_tryPush(&conn->server->users.username_id_map, username_str, &user_id)); try_assert(HashMap_tryPush(&conn->server->users.username_id_map, username_str, &user_id));
// manually unlock mutex // manually unlock mutex

View File

@ -13,13 +13,30 @@ declare_RequestHandler(SendMessage)
try_void(PacketHeader_validateContentSize(req_head, sizeof(req))); try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
if(req.data_size < MESSAGE_SIZE_MIN || req.data_size > MESSAGE_SIZE_MAX){
try_void(sendErrorMessage_f(log_ctx, conn, res_head,
LogSeverity_Warn,
"message size must be >= %i and <= %i",
MESSAGE_SIZE_MIN, MESSAGE_SIZE_MAX
));
// this will close socket connection
Return RESULT_ERROR("invalid message size", false);
}
// receive message data
Array(u8) message_data = Array_u8_alloc(req.data_size);
try_void(EncryptedSocketTCP_recv(&conn->sock, message_data, SocketRecvFlag_WholeBuffer));
for(u16 i = 0; i < message_data.len; i++){
u8 b = message_data.data[i];
}
// send response // send response
SendMessageResponse res; // SendMessageResponse res;
SendMessageResponse_construct(&res, res_head, ); // SendMessageResponse_construct(&res, res_head, );
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); // try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); // try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
Return RESULT_VOID; Return RESULT_VOID;
} }

View File

@ -24,16 +24,16 @@ declare_RequestHandler(ServerPublicInfo)
Return RESULT_VOID; Return RESULT_VOID;
} }
case ServerPublicInfo_Name: case ServerPublicInfo_Name:
content = str_castTo_Array(conn->server->name); content = str_castTo_Array_u8(conn->server->name);
break; break;
case ServerPublicInfo_Description: case ServerPublicInfo_Description:
content = str_castTo_Array(conn->server->description); content = str_castTo_Array_u8(conn->server->description);
break; break;
} }
// send response // send response
ServerPublicInfoResponse res; ServerPublicInfoResponse res;
ServerPublicInfoResponse_construct(&res, res_head, content.size); ServerPublicInfoResponse_construct(&res, res_head, content.len);
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
try_void(EncryptedSocketTCP_send(&conn->sock, content)); try_void(EncryptedSocketTCP_send(&conn->sock, content));

View File

@ -10,16 +10,16 @@ Result(void) sendErrorMessage(
Deferral(1); Deferral(1);
//limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size //limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
if(msg.size > ERROR_MESSAGE_MAX_SIZE) if(msg.len > ERROR_MESSAGE_MAX_SIZE)
msg.size = ERROR_MESSAGE_MAX_SIZE; msg.len = ERROR_MESSAGE_MAX_SIZE;
log(log_severity, log_ctx, FMT_str, msg.size, msg.data); log(log_severity, log_ctx, FMT_str, msg.len, msg.data);
ErrorMessage res; ErrorMessage res;
ErrorMessage_construct(&res, res_head, msg.size); ErrorMessage_construct(&res, res_head, msg.len);
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
try_void(EncryptedSocketTCP_send(&conn->sock, str_castTo_Array(msg))); try_void(EncryptedSocketTCP_send(&conn->sock, str_castTo_Array_u8(msg)));
Return RESULT_VOID; Return RESULT_VOID;
} }

View File

@ -21,10 +21,10 @@ void Server_free(Server* self){
idb_close(self->db); idb_close(self->db);
List_destroy(&self->users.cache_list); List_UserInfo_destroy(&self->users.cache_list);
HashMap_destroy(&self->users.username_id_map); HashMap_destroy(&self->users.username_id_map);
List_destroy(&self->messages.blocks_meta_list); List_MessageBlockMeta_destroy(&self->messages.blocks_meta_list);
LList_MessageBlock_destroy(&self->messages.blocks_queue); LList_MessageBlock_destroy(&self->messages.blocks_queue);
free(self->messages.incomplete_block); free(self->messages.incomplete_block);
@ -86,9 +86,9 @@ Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_fu
// parse db_aes_key // parse db_aes_key
try_void(config_findValue(config_str, STR("db_aes_key"), &tmp_str, true)); try_void(config_findValue(config_str, STR("db_aes_key"), &tmp_str, true));
Array(u8) db_aes_key = Array_alloc_size(base64_decodedSize(tmp_str.data, tmp_str.size)); Array(u8) db_aes_key = Array_u8_alloc(base64_decodedSize(tmp_str.data, tmp_str.len));
Defer(free(db_aes_key.data)); Defer(free(db_aes_key.data));
base64_decode(tmp_str.data, tmp_str.size, db_aes_key.data); base64_decode(tmp_str.data, tmp_str.len, db_aes_key.data);
// parse db_dir and open db // parse db_dir and open db
try_void(config_findValue(config_str, STR("db_dir"), &tmp_str, true)); try_void(config_findValue(config_str, STR("db_dir"), &tmp_str, true));
@ -102,17 +102,17 @@ Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_fu
// load whole users table to list // load whole users table to list
try_void( try_void(
idb_createListFromTable(self->users.table, &self->users.cache_list, false) idb_createListFromTable(self->users.table, (void*)&self->users.cache_list, false)
); );
// build name-id map // build name-id map
try(u64 users_count, u, idb_getRowCount(self->users.table, false)); try(u64 users_count, u, idb_getRowCount(self->users.table, false));
HashMap_construct(&self->users.username_id_map, u64, NULL); HashMap_construct(&self->users.username_id_map, u64, NULL);
for(u64 id = 0; id < users_count; id++){ for(u64 id = 0; id < users_count; id++){
UserInfo* row = &List_index(self->users.cache_list, UserInfo, id); UserInfo* user = self->users.cache_list.data + id;
str key = str_construct(row->name, row->name_len, true); str key = str_construct(user->name, user->name_len, true);
if(!HashMap_tryPush(&self->users.username_id_map, key, &id)){ if(!HashMap_tryPush(&self->users.username_id_map, key, &id)){
Return RESULT_ERROR_FMT("duplicate user name '"FMT_str"'", key.size, key.data); Return RESULT_ERROR_FMT("duplicate user name '"FMT_str"'", key.len, key.data);
} }
} }
logDebug(log_ctx, "loaded "FMT_u64" users", users_count); logDebug(log_ctx, "loaded "FMT_u64" users", users_count);
@ -129,7 +129,7 @@ Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_fu
// load whole message_blocks_meta table to list // load whole message_blocks_meta table to list
try_void( try_void(
idb_createListFromTable(self->messages.blocks_meta_table, &self->messages.blocks_meta_list, false) idb_createListFromTable(self->messages.blocks_meta_table, (void*)&self->messages.blocks_meta_list, false)
); );
// load N last blocks to the queue // load N last blocks to the queue
@ -148,6 +148,7 @@ Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_fu
); );
try_void(idb_getRow(self->messages.blocks_table, id, node->value.data, false)); try_void(idb_getRow(self->messages.blocks_table, id, node->value.data, false));
} }
logDebug(log_ctx, "loaded "FMT_u64" message blocks", message_blocks_count);
success = true; success = true;
Return RESULT_VALUE(p, self); Return RESULT_VALUE(p, self);
@ -199,7 +200,7 @@ static void* handleConnection(void* _args){
if(r.error){ if(r.error){
Error_addCallPos(r.error, ErrorCallPos_here()); Error_addCallPos(r.error, ErrorCallPos_here());
str e_str = Error_toStr(r.error); str e_str = Error_toStr(r.error);
logError(log_ctx, FMT_str, e_str.size, e_str.data); logError(log_ctx, FMT_str, e_str.len, e_str.data);
str_free(e_str); str_free(e_str);
Error_free(r.error); Error_free(r.error);
} }
@ -213,6 +214,7 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
Deferral(16); Deferral(16);
Server* server = args->server; Server* server = args->server;
logInfo(log_ctx, "a client is trying to connect");
ClientConnection* conn = NULL; ClientConnection* conn = NULL;
// establish encrypted connection // establish encrypted connection
try(conn, p, ClientConnection_accept(args)); try(conn, p, ClientConnection_accept(args));

View File

@ -11,6 +11,8 @@
typedef struct ClientConnection ClientConnection; typedef struct ClientConnection ClientConnection;
List_declare(UserInfo);
List_declare(MessageBlockMeta);
LList_declare(MessageBlock); LList_declare(MessageBlock);
#define MESSAGE_BLOCKS_CACHE_COUNT 50 #define MESSAGE_BLOCKS_CACHE_COUNT 50