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

View File

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

View File

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

View File

@ -7,19 +7,19 @@ Result(void) run_RsaGenStdin(u32 key_size) {
Deferral(4);
printfe("reading stdin...\n");
Array(u8) input_buf = Array_alloc_size(64*1024);
Defer(Array_free(input_buf));
Array(u8) input_buf = Array_u8_alloc(64*1024);
Defer(Array_u8_destroy(&input_buf));
br_hmac_drbg_context rng = { .vtable = &br_hmac_drbg_vtable };
br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
i64 read_n = 0;
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){
Return RESULT_ERROR("ERROR: can't read stdin", false);
}
// put bytes to rng as seed
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");
br_rsa_private_key sk;
br_rsa_public_key pk;

View File

@ -29,10 +29,10 @@ Result(void) run_ServerMode(cstr config_path) {
Defer(file_close(config_file));
// 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));
Defer(Array_free(config_buf));
str config_str = Array_castTo_str(config_buf, false);
Defer(Array_u8_destroy(&config_buf));
str config_str = Array_u8_castTo_str(config_buf, false);
// init server
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
file_close(config_file);
config_file = NULL;
Array_free(config_buf);
Array_u8_destroy(&config_buf);
config_buf.data = NULL;
// start infinite loop on main thread

View File

@ -6,8 +6,8 @@ void ServerConnection_close(ServerConnection* self){
return;
RSA_destroyPublicKey(&self->server_pk);
EncryptedSocketTCP_destroy(&self->sock);
Array_free(self->token);
Array_free(self->session_key);
Array_u8_destroy(&self->token);
Array_u8_destroy(&self->session_key);
str_free(self->server_name);
str_free(self->server_description);
free(self);
@ -35,12 +35,12 @@ Result(ServerConnection*) ServerConnection_open(Client* client, cstr server_addr
RSAEncryptor_construct(&conn->rsa_enc, &conn->server_pk);
// 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
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));
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,
server_pk_hash, 1);
// 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);
// 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 };
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
try(Socket _s, i, socket_open_TCP());

View File

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

View File

@ -11,12 +11,12 @@ Result(void) recvStr(EncryptedSocketTCP* sock, u32 size, str* out_s){
try_void(
EncryptedSocketTCP_recv(
sock,
str_castTo_Array(s),
str_castTo_Array_u8(s),
SocketRecvFlag_WholeBuffer
)
);
s.data[s.size] = 0;
s.data[s.len] = 0;
*out_s = s;
success = true;
Return RESULT_VOID;
@ -32,8 +32,8 @@ Result(void) recvErrorMessage(EncryptedSocketTCP* sock, PacketHeader* res_header
try_void(EncryptedSocketTCP_recvStruct(sock, &res));
// limit msg_size to fit in single EncryptedSocketTCP_recv call
// TODO: receive ErrorMessage content in a loop
if(res.msg_size > sock->recv_buf.size)
res.msg_size = sock->recv_buf.size;
if(res.msg_size > sock->recv_buf.len)
res.msg_size = sock->recv_buf.len;
str 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_validateContentSize(res_header, res.size));
try_void(PacketHeader_validateContentSize(res_header, res.len));
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,
PacketHeader* res_header, Array(u8) res, PacketType 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,
PacketHeader* req_header, Array(u8) req);
#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){
u32 line_n = 0;
while(config_str.size > 0){
while(config_str.len > 0){
line_n++;
i32 line_end = str_seekChar(config_str, '\n', 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);
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){
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_VOID;

View File

@ -4,19 +4,19 @@
// write data from src to array and increment array data pointer
static inline void __Array_writeNext(Array(u8)* dst, u8* src, size_t 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
static inline void __Array_readNext(u8* dst, Array(u8)* src, size_t 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){
br_sha256_context 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);
}
@ -37,8 +37,8 @@ void AESBlockEncryptor_construct(AESBlockEncryptor* ptr,
void AESBlockEncryptor_changeKey(AESBlockEncryptor* ptr, Array(u8) key)
{
assert(key.size == 16 || key.size == 24 || key.size == 32);
ptr->enc_class->init((void*)ptr->enc_keys, key.data, key.size);
assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->enc_class->init((void*)ptr->enc_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum);
}
@ -46,8 +46,8 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
Array(u8) src, Array(u8) dst)
{
Deferral(4);
u32 encrypted_size = AESBlockEncryptor_calcDstSize(src.size);
try_assert(dst.size >= encrypted_size);
u32 encrypted_size = AESBlockEncryptor_calcDstSize(src.len);
try_assert(dst.len >= encrypted_size);
// generate random initial vector
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;
memset(&header, 0, sizeof(header));
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
memcpy(ptr->buf, &header, sizeof(header));
// encrypt header
@ -66,7 +66,7 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
__Array_writeNext(&dst, ptr->buf, sizeof(header));
// encrypt full AESBlockEncryptor buffers
while(src.size > __AES_BUFFER_SIZE){
while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->enc_class->run((void*)ptr->enc_keys,
ptr->iv,
@ -75,10 +75,10 @@ Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr,
}
// encrypt buffer with remaining data
if(src.size > 0){
memcpy(ptr->buf, src.data, src.size);
memset(ptr->buf + src.size, 0, header.padding_size);
u32 src_size_padded = src.size + header.padding_size;
if(src.len > 0){
memcpy(ptr->buf, src.data, src.len);
memset(ptr->buf + src.len, 0, header.padding_size);
u32 src_size_padded = src.len + header.padding_size;
ptr->enc_class->run((void*)ptr->enc_keys,
ptr->iv,
ptr->buf, src_size_padded);
@ -102,8 +102,8 @@ void AESBlockDecryptor_construct(AESBlockDecryptor* ptr,
void AESBlockDecryptor_changeKey(AESBlockDecryptor* ptr, Array(u8) key)
{
assert(key.size == 16 || key.size == 24 || key.size == 32);
ptr->dec_class->init((void*)ptr->dec_keys, key.data, key.size);
assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->dec_class->init((void*)ptr->dec_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum);
}
@ -112,9 +112,9 @@ Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr,
{
Deferral(4);
u32 overhead_size = AESBlockEncryptor_calcDstSize(0);
try_assert(src.size >= overhead_size);
try_assert(src.size % 16 == 0 && "src must be array of 16-byte blocks");
try_assert(dst.size >= src.size - overhead_size);
try_assert(src.len >= overhead_size);
try_assert(src.len % 16 == 0 && "src must be array of 16-byte blocks");
try_assert(dst.len >= src.len - overhead_size);
// read IV from the beginning of src
__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
try_assert(src.size >= header.padding_size && "invalid padding size");
u32 decrypted_size = src.size - header.padding_size;
src.size = decrypted_size;
try_assert(src.len >= header.padding_size && "invalid padding size");
u32 decrypted_size = src.len - header.padding_size;
src.len = decrypted_size;
// decrypt full buffers
while(src.size > __AES_BUFFER_SIZE){
while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->dec_class->run((void*)ptr->dec_keys,
ptr->iv,
@ -145,14 +145,14 @@ Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr,
}
// decrypt buffer with remaining data
if(src.size > 0){
memcpy(ptr->buf, src.data, src.size);
memset(ptr->buf + src.size, 0, header.padding_size);
u32 src_size_padded = src.size + header.padding_size;
if(src.len > 0){
memcpy(ptr->buf, src.data, src.len);
memset(ptr->buf + src.len, 0, header.padding_size);
u32 src_size_padded = src.len + header.padding_size;
ptr->dec_class->run((void*)ptr->dec_keys,
ptr->iv,
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);
@ -178,8 +178,8 @@ void AESStreamEncryptor_construct(AESStreamEncryptor* ptr,
void AESStreamEncryptor_changeKey(AESStreamEncryptor* ptr, Array(u8) key)
{
assert(key.size == 16 || key.size == 24 || key.size == 32);
ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.size);
assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum);
}
@ -188,7 +188,7 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
{
Deferral(4);
u32 encrypted_size = src.size;
u32 encrypted_size = src.len;
// if it is the beginning of the stream,
if(ptr->block_counter == 0){
// write IV generated during initialization
@ -204,10 +204,10 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
// write checksum to dst
__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
while(src.size > __AES_BUFFER_SIZE){
while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter,
@ -216,12 +216,12 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
}
// encrypt remaining data
if(src.size > 0){
memcpy(ptr->buf, src.data, src.size);
if(src.len > 0){
memcpy(ptr->buf, src.data, src.len);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter,
ptr->buf, src.size);
memcpy(dst.data, ptr->buf, src.size);
ptr->buf, src.len);
memcpy(dst.data, ptr->buf, src.len);
}
Return RESULT_VALUE(u, encrypted_size);
@ -242,8 +242,8 @@ void AESStreamDecryptor_construct(AESStreamDecryptor* ptr,
void AESStreamDecryptor_changeKey(AESStreamDecryptor* ptr, Array(u8) key)
{
assert(key.size == 16 || key.size == 24 || key.size == 32);
ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.size);
assert(key.len == 16 || key.len == 24 || key.len == 32);
ptr->ctr_class->init((void*)ptr->ctr_keys, key.data, key.len);
__calcKeyCheckSum(key, ptr->key_checksum);
}
@ -270,11 +270,11 @@ Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr,
}
}
// size without IV
u32 decrypted_size = src.size;
try_assert(dst.size >= decrypted_size);
u32 decrypted_size = src.len;
try_assert(dst.len >= decrypted_size);
// decrypt full buffers
while(src.size > __AES_BUFFER_SIZE){
while(src.len > __AES_BUFFER_SIZE){
__Array_readNext(ptr->buf, &src, __AES_BUFFER_SIZE);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter,
@ -283,12 +283,12 @@ Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr,
}
// decrypt remaining data
if(src.size > 0){
memcpy(ptr->buf, src.data, src.size);
if(src.len > 0){
memcpy(ptr->buf, src.data, src.len);
ptr->block_counter = ptr->ctr_class->run((void*)ptr->ctr_keys,
ptr->iv, ptr->block_counter,
ptr->buf, src.size);
memcpy(dst.data, ptr->buf, src.size);
ptr->buf, src.len);
memcpy(dst.data, ptr->buf, src.len);
}
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.
/// @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
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.
/// @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
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.
/// @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
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
/// @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
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);
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));
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;
key_base64_str.data += offset;
key_base64_str.size -= offset;
u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.size);
key_base64_str.len -= offset;
u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.len);
if(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){
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;
key_base64_str.data += offset;
key_base64_str.size -= offset;
u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.size);
key_base64_str.len -= offset;
u32 decoded_size = base64_decodedSize(key_base64_str.data, key_base64_str.len);
if(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){
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){
u32 key_size_bytes = ptr->pk->nlen;
const u32 max_src_size = RSAEncryptor_calcMaxSrcSize(key_size_bytes * 8, 256);
if(src.size > max_src_size){
return RESULT_ERROR_FMT("src.size (%u) must be <= RSAEncryptor_calcMaxSrcSize() (%u)",
src.size, max_src_size);
if(src.len > max_src_size){
return RESULT_ERROR_FMT("src.len (%u) must be <= RSAEncryptor_calcMaxSrcSize() (%u)",
src.len, max_src_size);
}
if(dst.size < key_size_bytes){
return RESULT_ERROR_FMT("dst.size (%u) must be >= key length in bytes (%u)",
dst.size, key_size_bytes);
if(dst.len < key_size_bytes){
return RESULT_ERROR_FMT("dst.len (%u) must be >= key length in bytes (%u)",
dst.len, key_size_bytes);
}
size_t sz = br_rsa_i31_oaep_encrypt(
&ptr->rng.vtable, &br_sha256_vtable,
NULL, 0,
ptr->pk,
dst.data, dst.size,
src.data, src.size);
dst.data, dst.len,
src.data, src.len);
if(sz == 0){
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){
u32 key_size_bits = ptr->sk->n_bitlen;
if(buffer.size != key_size_bits/8){
return RESULT_ERROR_FMT("buffer.size (%u) must be == key length in bytes (%u)",
buffer.size, key_size_bits/8);
if(buffer.len != key_size_bits/8){
return RESULT_ERROR_FMT("buffer.len (%u) must be == key length in bytes (%u)",
buffer.len, key_size_bits/8);
}
size_t sz = buffer.size;
size_t sz = buffer.len;
size_t r = br_rsa_i31_oaep_decrypt(
&br_sha256_vtable,
NULL, 0,

View File

@ -1,6 +1,7 @@
#pragma once
#include "tlibc/collections/Array.h"
#include "tlibc/errors.h"
#include "tlibc/collections/Array.h"
#include "tlibc/collections/Array_impl/Array_u8.h"
#include "bearssl_rand.h"
#include "bearssl_hash.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);
for(i32 i = 0; i < iterations; i++){
br_sha256_update(&sha256_ctx, password.data, password.size);
br_sha256_update(&sha256_ctx, salt.data, salt.size);
br_sha256_update(&sha256_ctx, password.data, password.len);
br_sha256_update(&sha256_ctx, salt.data, salt.len);
br_sha256_out(&sha256_ctx, out_buffer);
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->changes_file_path);
pthread_mutex_destroy(&t->mutex);
Array_free(t->enc_buf);
Array_u8_destroy(&t->enc_buf);
free(t);
}
@ -159,7 +159,7 @@ static Result(void) Table_validateHeader(Table* t){
static Result(void) Table_validateEncryption(Table* t){
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){
Return RESULT_ERROR_FMT(
"Table '%s' is encrypted, but encryption key is not set."
@ -179,7 +179,7 @@ static Result(void) Table_validateEncryption(Table* t){
try_void(
AESBlockDecryptor_decrypt(
&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
)
);
@ -208,7 +208,7 @@ void idb_close(IncrementalDB* db){
if(db == NULL)
return;
str_free(db->db_dir);
Array_free(db->aes_key);
Array_u8_destroy(&db->aes_key);
HashMap_destroy(&db->tables_map);
pthread_mutex_destroy(&db->mutex);
free(db);
@ -216,7 +216,7 @@ void idb_close(IncrementalDB* db){
Result(IncrementalDB*) idb_open(str db_dir, NULLABLE(Array(u8) aes_key)){
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));
// 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;
Defer(if(!success) idb_close(db));
if(aes_key.size != 0){
db->aes_key = Array_copy(aes_key);
if(aes_key.len != 0){
db->aes_key = Array_u8_copy(aes_key);
}
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));
// 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);
AESBlockDecryptor_construct(&t->dec, db->aes_key, AESBlockDecryptor_DEFAULT_CLASS);
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
@ -315,15 +315,15 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str table_name, u32 row_s
// create table file
t->header.magic.n = TABLE_FILE_MAGIC.n;
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.row_size = row_size;
memset(t->header.key_challenge, 0, KEY_CHALLENGE_CIPHER_SIZE);
try_void(
AESBlockEncryptor_encrypt(
&t->enc,
Array_construct_size((void*)KEY_CHALLENGE_PLAIN, KEY_CHALLENGE_PLAIN_SIZE),
Array_construct_size(t->header.key_challenge, KEY_CHALLENGE_CIPHER_SIZE)
Array_u8_construct((void*)KEY_CHALLENGE_PLAIN, KEY_CHALLENGE_PLAIN_SIZE),
Array_u8_construct(t->header.key_challenge, KEY_CHALLENGE_CIPHER_SIZE)
)
);
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_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;
// 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(
&t->dec,
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));
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;
// 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(
AESBlockEncryptor_encrypt(
&t->enc,
Array_construct_size(row_ptr, row_size),
Array_u8_construct(row_ptr, row_size),
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));
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;
// 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(
AESBlockEncryptor_encrypt(
&t->enc,
Array_construct_size(row_ptr, row_size),
Array_u8_construct(row_ptr, row_size),
t->enc_buf
)
);
@ -487,14 +487,15 @@ Result(void) idb_createListFromTable(Table* t, List_* l, bool lock_table){
Defer(idb_unlockTable(t));
}
u64 rows_count = t->row_count;
u64 total_size = rows_count * t->header.row_size;
*l = List_alloc_size(total_size);
l->size = total_size;
u64 row_count = t->row_count;
u64 row_size = t->header.row_size;
u64 total_size = row_count * row_size;
*l = _List_alloc(total_size, row_size);
l->len = row_count;
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;
Return RESULT_VOID;

View File

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

View File

@ -28,14 +28,14 @@ Result(void) EncryptedSocketTCP_send(EncryptedSocketTCP* ptr,
#define EncryptedSocketTCP_sendStruct(socket, structPtr)\
EncryptedSocketTCP_send(socket,\
Array_construct_size(structPtr, sizeof(*structPtr)))
struct_castTo_Array_u8(structPtr))
Result(u32) EncryptedSocketTCP_recv(EncryptedSocketTCP* ptr,
Array(u8) buffer, SocketRecvFlag flags);
#define EncryptedSocketTCP_recvStruct(socket, structPtr)\
EncryptedSocketTCP_recv(socket,\
Array_construct_size(structPtr, sizeof(*structPtr)),\
struct_castTo_Array_u8(structPtr),\
SocketRecvFlag_WholeBuffer)
Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr,
@ -43,14 +43,14 @@ Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr,
#define EncryptedSocketTCP_sendStructRSA(socket, rsa_enc, structPtr)\
EncryptedSocketTCP_sendRSA(socket, rsa_enc,\
Array_construct_size(structPtr, sizeof(*structPtr)))
struct_castTo_Array_u8(structPtr))
Result(u32) EncryptedSocketTCP_recvRSA(EncryptedSocketTCP* ptr,
RSADecryptor* rsa_dec, Array(u8) buffer, SocketRecvFlag flags);
#define EncryptedSocketTCP_recvStructRSA(socket, rsa_dec, structPtr)\
EncryptedSocketTCP_recvRSA(socket, rsa_dec,\
Array_construct_size(structPtr, sizeof(*structPtr)),\
struct_castTo_Array_u8(structPtr),\
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){
i32 r = send(s, buffer.data, buffer.size, 0);
i32 r = send(s, (void*)buffer.data, buffer.len, 0);
if(r < 0){
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_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){
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){
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_VOID;
@ -92,11 +92,11 @@ static inline int SocketRecvFlags_toStd(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){
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);
}
@ -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){
struct sockaddr_in remote_addr = {0};
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);
if(r < 0){
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);
}

View File

@ -16,7 +16,7 @@ str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_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(
sprintf_malloc(
"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];
if (char_isLatinLower(c) ||
char_isLatinUpper(c) ||
@ -56,8 +56,8 @@ Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* he
_PacketHeader_construct(ClientHandshake);
memset(ptr, 0, sizeof(*ptr));
try_assert(session_key.size == sizeof(ptr->session_key));
memcpy(ptr->session_key, session_key.data, session_key.size);
try_assert(session_key.len == sizeof(ptr->session_key));
memcpy(ptr->session_key, session_key.data, session_key.len);
Return RESULT_VOID;
}
@ -97,10 +97,10 @@ Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
if(name_error_str.data){
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));
memcpy(ptr->token, token.data, token.size);
try_assert(token.len == sizeof(ptr->token));
memcpy(ptr->token, token.data, token.len);
Return RESULT_VOID;
}
@ -126,10 +126,10 @@ Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* he
if(name_error_str.data){
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));
memcpy(ptr->token, token.data, token.size);
try_assert(token.len == sizeof(ptr->token));
memcpy(ptr->token, token.data, token.len);
Return RESULT_VOID;
}

View File

@ -5,7 +5,7 @@ void ClientConnection_close(ClientConnection* conn){
if(!conn)
return;
EncryptedSocketTCP_destroy(&conn->sock);
Array_free(conn->session_key);
Array_u8_destroy(&conn->session_key);
free(conn);
}
@ -22,9 +22,9 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
conn->client_end = args->client_end;
conn->session_id = args->session_id;
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
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);
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));
// 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);
// send ServerHandshake

View File

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

View File

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

View File

@ -55,7 +55,7 @@ declare_RequestHandler(Register)
UserInfo user;
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.token, req.token, sizeof(req.token));
@ -66,8 +66,8 @@ declare_RequestHandler(Register)
try(u64 user_id, u,
idb_pushRow(conn->server->users.table, &user, false)
);
try_assert(user_id == List_len(conn->server->users.cache_list, UserInfo));
List_pushMany(&conn->server->users.cache_list, UserInfo, &user, 1);
try_assert(user_id == conn->server->users.cache_list.len);
List_UserInfo_pushMany(&conn->server->users.cache_list, &user, 1);
try_assert(HashMap_tryPush(&conn->server->users.username_id_map, username_str, &user_id));
// manually unlock mutex

View File

@ -13,13 +13,30 @@ declare_RequestHandler(SendMessage)
try_void(PacketHeader_validateContentSize(req_head, sizeof(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
SendMessageResponse res;
SendMessageResponse_construct(&res, res_head, );
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
// SendMessageResponse res;
// SendMessageResponse_construct(&res, res_head, );
// try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
// try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
Return RESULT_VOID;
}

View File

@ -24,16 +24,16 @@ declare_RequestHandler(ServerPublicInfo)
Return RESULT_VOID;
}
case ServerPublicInfo_Name:
content = str_castTo_Array(conn->server->name);
content = str_castTo_Array_u8(conn->server->name);
break;
case ServerPublicInfo_Description:
content = str_castTo_Array(conn->server->description);
content = str_castTo_Array_u8(conn->server->description);
break;
}
// send response
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));
try_void(EncryptedSocketTCP_send(&conn->sock, content));

View File

@ -10,16 +10,16 @@ Result(void) sendErrorMessage(
Deferral(1);
//limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
if(msg.size > ERROR_MESSAGE_MAX_SIZE)
msg.size = ERROR_MESSAGE_MAX_SIZE;
if(msg.len > 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_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));
try_void(EncryptedSocketTCP_send(&conn->sock, str_castTo_Array(msg)));
try_void(EncryptedSocketTCP_send(&conn->sock, str_castTo_Array_u8(msg)));
Return RESULT_VOID;
}

View File

@ -21,10 +21,10 @@ void Server_free(Server* self){
idb_close(self->db);
List_destroy(&self->users.cache_list);
List_UserInfo_destroy(&self->users.cache_list);
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);
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
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));
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
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
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
try(u64 users_count, u, idb_getRowCount(self->users.table, false));
HashMap_construct(&self->users.username_id_map, u64, NULL);
for(u64 id = 0; id < users_count; id++){
UserInfo* row = &List_index(self->users.cache_list, UserInfo, id);
str key = str_construct(row->name, row->name_len, true);
UserInfo* user = self->users.cache_list.data + id;
str key = str_construct(user->name, user->name_len, true);
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);
@ -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
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
@ -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));
}
logDebug(log_ctx, "loaded "FMT_u64" message blocks", message_blocks_count);
success = true;
Return RESULT_VALUE(p, self);
@ -199,7 +200,7 @@ static void* handleConnection(void* _args){
if(r.error){
Error_addCallPos(r.error, ErrorCallPos_here());
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);
Error_free(r.error);
}
@ -213,6 +214,7 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
Deferral(16);
Server* server = args->server;
logInfo(log_ctx, "a client is trying to connect");
ClientConnection* conn = NULL;
// establish encrypted connection
try(conn, p, ClientConnection_accept(args));

View File

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