Compare commits

...

3 Commits

Author SHA1 Message Date
1e41ab49e5 implemented some socket functions 2025-07-21 18:55:40 +03:00
bce385a4b5 updated tlibc 2025-07-21 16:24:13 +03:00
992fcf6b98 implemented encryption of EncryptedBlockInfo 2025-07-21 16:01:15 +03:00
13 changed files with 237 additions and 45 deletions

View File

@ -4,8 +4,9 @@
"name": "all",
"defines": [],
"includePath": [
"dependencies",
"src",
"dependencies",
"dependencies/tlibc/include",
"${default}"
],
"cStandard": "c99"

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit ebe6e58ef3b777a7e45f10b5552ca95bc96e8cc8
Subproject commit ba7a81d205a7dfe49d64f0f9c6b8d97d693d5ec2

View File

@ -26,7 +26,7 @@ OBJDIR="obj"
OUTDIR="bin"
STATIC_LIB_FILE="lib$PROJECT.a"
INCLUDE="-I./src -I./dependencies"
INCLUDE="-I./src -I./dependencies -I./dependencies/tlibc/include"
# OS-specific options
case "$OS" in

View File

@ -1,26 +1,7 @@
#include "cryptography.h"
#include <BearSSL/inc/bearssl_block.h>
#include <BearSSL/inc/bearssl_hash.h>
#include <BearSSL/inc/bearssl_rand.h>
#include "BearSSL/inc/bearssl_block.h"
#include <assert.h>
Array hash_password(str password, i32 iterations){
Array hash_buffer = Array_alloc(u8, br_sha256_SIZE);
Array_memset(&hash_buffer, 0);
br_sha256_context sha256_ctx;
br_sha256_init(&sha256_ctx);
for(i32 i = 0; i < iterations; i++){
br_sha256_update(&sha256_ctx, password.data, password.size);
br_sha256_out(&sha256_ctx, hash_buffer.data);
br_sha256_update(&sha256_ctx, hash_buffer.data, hash_buffer.size);
}
br_sha256_out(&sha256_ctx, hash_buffer.data);
return hash_buffer;
}
// size must be multiple of 16
#define __AES_BUFFER_SIZE 256
@ -61,11 +42,14 @@ void EncryptorAES_destroy(EncryptorAES* ptr){
void EncryptorAES_encrypt(EncryptorAES* ptr, Array src, Array dst){
assert(dst.size >= EncryptorAES_calcDstSize(src.size));
const EncryptedBlockInfo block_info = { .padding_size = 16 - src.size % 16 };
memcpy(ptr->buf.data, &block_info, sizeof(EncryptedBlockInfo));
// encrypt this struct
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv.data, ptr->buf.data, sizeof(EncryptedBlockInfo));
// emit EncryptedBlockInfo to beginning of result
EncryptedBlockInfo block_info = { .padding_size = 16 - src.size % 16 };
memcpy(dst.data, &block_info, sizeof(block_info));
dst.data += sizeof(block_info);
dst.size -= sizeof(block_info);
memcpy(dst.data, ptr->buf.data, sizeof(EncryptedBlockInfo));
dst.data += sizeof(EncryptedBlockInfo);
dst.size -= sizeof(EncryptedBlockInfo);
// write full blocks
while(src.size > ptr->buf.size){
@ -114,9 +98,11 @@ void DecryptorAES_decrypt(DecryptorAES* ptr, Array src, Array dst, u32* decrypte
// read EncryptedBlockInfo from beginning of data
EncryptedBlockInfo block_info;
memcpy(&block_info, src.data, sizeof(block_info));
src.data += sizeof(block_info);
src.size -= sizeof(block_info);
memcpy(&block_info, src.data, sizeof(EncryptedBlockInfo));
src.data += sizeof(EncryptedBlockInfo);
src.size -= sizeof(EncryptedBlockInfo);
// decrypt this struct
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv.data, &block_info, sizeof(EncryptedBlockInfo));
*decrypted_size = src.size - block_info.padding_size;
// write full blocks

View File

@ -1,7 +1,7 @@
#pragma once
#include <tlibc/include/std.h>
#include <tlibc/include/collections/Array.h>
#include <tlibc/include/string/str.h>
#include "tlibc/std.h"
#include "tlibc/collections/Array.h"
#include "tlibc/string/str.h"
/// @brief hashes password multiple times using its own hash as salt
/// @param password some byte array

18
src/cryptography/hash.c Executable file
View File

@ -0,0 +1,18 @@
#include "cryptography.h"
#include "BearSSL/inc/bearssl_hash.h"
Array hash_password(str password, i32 iterations){
Array hash_buffer = Array_alloc(u8, br_sha256_SIZE);
Array_memset(&hash_buffer, 0);
br_sha256_context sha256_ctx;
br_sha256_init(&sha256_ctx);
for(i32 i = 0; i < iterations; i++){
br_sha256_update(&sha256_ctx, password.data, password.size);
br_sha256_out(&sha256_ctx, hash_buffer.data);
br_sha256_update(&sha256_ctx, hash_buffer.data, hash_buffer.size);
}
br_sha256_out(&sha256_ctx, hash_buffer.data);
return hash_buffer;
}

View File

@ -1,18 +1,13 @@
#include <cryptography.h>
#include <tlibc/include/string/StringBuilder.h>
#include "cryptography/cryptography.h"
#include "network/network.h"
#include "network/socket.h"
str hex_to_str(Array buf) {
StringBuilder sb = StringBuilder_alloc(buf.size * 2 + 1);
StringBuilder_append_memory(&sb, buf);
return StringBuilder_getStr(&sb);
}
int main(){
void test_aes(){
const str password = STR("abobus");
const Array data = str_castTo_Array(STR("0123456789_hii_"));
const Array key_hash = hash_password(password, 1e5);
str hash_str = hex_to_str(key_hash);
str hash_str = hex_to_str(key_hash, true);
printf("password hash [%i] %s\n", key_hash.size, hash_str.data);
free(hash_str.data);
@ -24,7 +19,8 @@ int main(){
Array buffer = Array_alloc_size(EncryptorAES_calcDstSize(data.size));
EncryptorAES_encrypt(encr, data, buffer);
EncryptorAES_destroy(encr);
str encrypted_str = hex_to_str(buffer);
str encrypted_str = hex_to_str(buffer, true);
printf("data encrypted (hex): %s\n", encrypted_str.data);
free(encrypted_str.data);
@ -32,9 +28,22 @@ int main(){
u32 decrypted_size = 0;
DecryptorAES_decrypt(decr, buffer, buffer, &decrypted_size);
DecryptorAES_destroy(decr);
str decrypted_str = str_copy(str_construct(buffer.data, decrypted_size, false));
printf("data decrypted (utf8): %s\n", decrypted_str.data);
free(decrypted_str.data);
}
void test_server(){
try_fatal(_10, network_init(), );
try_fatal(main_socket, socket_open_TCP(), );
EndpointIPv4 server_end = EndpointIPv4_create(AddressIPv4_LOOPBACK, 24500);
try_fatal(_20, socket_bind(main_socket.v_i64, server_end), );
try_fatal(_30, socket_listen(main_socket.v_i64, 64), );
try_fatal(_100, network_deinit(), );
}
int main(){
test_server();
return 0;
}
}

28
src/network/endpoint.c Executable file
View File

@ -0,0 +1,28 @@
#include "endpoint.h"
#include "network.h"
struct sockaddr_in EndpointIPv4_toSockaddr(EndpointIPv4 end){
struct sockaddr_in saddr = {0};
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = end.address.UintBigEndian;
/* transforms port number to big endian (network order) */
saddr.sin_port = htons(end.port);
return saddr;
}
EndpointIPv4 EndpointIPv4_fromSockaddr(struct sockaddr_in saddr){
EndpointIPv4 end;
end.address = AddressIPv4_fromU32(saddr.sin_addr.s_addr);
/* transforms port number to little endian (normal order) */
end.port = ntohs(saddr.sin_port);
return end;
}
AddressIPv4 AddressIPv4_fromStr(cstr);
str AddressIPv4_toStr(AddressIPv4 address);
EndpointIPv4 EndpointIPv4_fromStr(cstr s);
str EndpointIPv4_toStr(EndpointIPv4 end);

39
src/network/endpoint.h Executable file
View File

@ -0,0 +1,39 @@
#pragma once
#include "tlibc/std.h"
#include "tlibc/string/str.h"
#include "network.h"
#define port_INVALID ((port)~0)
#define port_is_invalid(PORT) (PORT == port_INVALID)
typedef union AddressIPv4 {
u32 UintBigEndian;
u8 bytes[4];
} AddressIPv4;
#define AddressIPv4_ANY AddressIPv4_fromBytes(0,0,0,0)
#define AddressIPv4_LOOPBACK AddressIPv4_fromBytes(127,0,0,1)
#define AddressIPv4_INVALID AddressIPv4_fromBytes(255,255,255,255)
#define AddressIPv4_is_invalid(ADDR) (ADDR.UintBigEndian == (u32)~0)
#define AddressIPv4_fromBytes(A, B, C, D) ((AddressIPv4){.bytes={A,B,C,D}})
#define AddressIPv4_fromU32(N) ((AddressIPv4){.UintBigEndian=N})
AddressIPv4 AddressIPv4_fromStr(cstr);
str AddressIPv4_toStr(AddressIPv4 address);
typedef struct EndpointIPv4 {
AddressIPv4 address;
u16 port;
} EndpointIPv4;
#define EndpointIPv4_INVALID EndpointIPv4_create(AddressIPv4_INVALID, port_INVALID)
#define EndpointIPv4_is_invalid(ENDP) (AddressIPv4_is_invalid(ENDP.address) || port_is_invalid(ENDP.port))
#define EndpointIPv4_create(ADDR, PORT) ((EndpointIPv4){ADDR, PORT})
EndpointIPv4 EndpointIPv4_fromStr(cstr s);
str EndpointIPv4_toStr(EndpointIPv4 end);
struct sockaddr_in EndpointIPv4_toSockaddr(EndpointIPv4 end);
EndpointIPv4 EndpointIPv4_fromSockaddr(struct sockaddr_in saddr);

25
src/network/network.c Executable file
View File

@ -0,0 +1,25 @@
#include "network.h"
#include "network.h"
Result(void) network_init(){
#if _WIN32
// Initialize Winsock
WSADATA wsaData = {0};
int result = WSAStartup(MAKEWORD(2,2), &wsaData);
if (result != 0) {
return RESULT_ERROR(sprintf_malloc(64, "WSAStartup failed with error code 0x%X", result), true);
}
#endif
return RESULT_VOID;
}
Result(void) network_deinit(){
#if _WIN32
// Deinitialize Winsock
int result = WSACleanup();
if (result != 0) {
return RESULT_ERROR(sprintf_malloc(64, "WSACleanup failed with error code 0x%X", result), true);
}
#endif
return RESULT_VOID;
}

22
src/network/network.h Executable file
View File

@ -0,0 +1,22 @@
#pragma once
#include "tlibc/errors.h"
#if defined(_WIN64) || defined(_WIN32)
#define KN_USE_WINSOCK 1
#else
#define KN_USE_WINSOCK 0
#endif
#if KN_USE_WINSOCK
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif
Result(void) network_init();
Result(void) network_deinit();

46
src/network/socket.c Executable file
View File

@ -0,0 +1,46 @@
#include "network.h"
#include "network.h"
#include "socket.h"
Result(Socket) socket_open_TCP(){
Socket s = socket(AF_INET, SOCK_STREAM, 0);
if(s == -1){
return RESULT_ERROR("can't create socket", false);
}
return RESULT_VALUE(i64, s);
}
void socket_close(Socket s){
#if KN_USE_WINSOCK
closesocket(s);
#else
close(s);
#endif
}
Result(void) socket_shutdown(Socket s, SocketShutdownType direction){
if(shutdown(s, (int)direction) == -1)
return RESULT_ERROR("shutdown() failed", false);
return RESULT_VOID;
}
Result(void) socket_bind(Socket s, EndpointIPv4 local_end){
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(local_end);
if(bind(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
return RESULT_ERROR("bind() failed", false);
return RESULT_VOID;
}
Result(void) socket_listen(Socket s, i32 backlog){
if(listen(s, backlog) != 0)
return RESULT_ERROR("listen() failed", false);
return RESULT_VOID;
}
Result(Socket) socket_accept(Socket main_socket) {
struct sockaddr_in remote_addr = {0};
i32 sockaddr_size = sizeof(remote_addr);
Socket user_connection = accept(main_socket, (struct sockaddr*)&remote_addr, (void*)&sockaddr_size);
return RESULT_VALUE(i64, user_connection);
}

18
src/network/socket.h Executable file
View File

@ -0,0 +1,18 @@
#pragma once
#include "endpoint.h"
#include "tlibc/errors.h"
typedef enum SocketShutdownType {
SocketShutdownType_Receive = 0,
SocketShutdownType_Send = 1,
SocketShutdownType_Both = 2,
} SocketShutdownType;
typedef i64 Socket;
Result(Socket) socket_open_TCP();
void socket_close(Socket s);
Result(void) socket_shutdown(Socket s, SocketShutdownType direction);
Result(void) socket_bind(Socket s, EndpointIPv4 local_end);
Result(void) socket_listen(Socket s, i32 backlog);
Result(Socket) socket_accept(Socket main_socket);