rsa key initialization
This commit is contained in:
parent
f01c5fc8a9
commit
98ae36ad2f
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
||||
Subproject commit c415e2ca8ff51f41984ace8fe796187e6ad0fa27
|
||||
Subproject commit 7e7bd195a9715abceb4131b21232aed7d990b75d
|
||||
10
src/client.c
10
src/client.c
@ -77,7 +77,7 @@ Result(void) client_run() {
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
#define inp_eq(LITERAL) str_equals(command, STR(LITERAL))
|
||||
#define is_alias(LITERAL) str_equals(command, STR(LITERAL))
|
||||
|
||||
static ClientCredential* client_credential = NULL;
|
||||
|
||||
@ -132,7 +132,7 @@ void ClientCredential_free(ClientCredential* cred){
|
||||
|
||||
#define __passhash_lvl_iter 1e5
|
||||
|
||||
static Result(ClientCredential*) ClientCredential_create(str username, str password){
|
||||
Result(ClientCredential*) ClientCredential_create(str username, str password){
|
||||
Deferral(32);
|
||||
ClientCredential* cred = (ClientCredential*)malloc(sizeof(ClientCredential));
|
||||
memset(cred, 0, sizeof(ClientCredential));
|
||||
@ -154,7 +154,7 @@ static Result(ClientCredential*) ClientCredential_create(str username, str passw
|
||||
u8 passhash_lvl1[password_hash_size];
|
||||
hash_password(StringBuilder_getStr(&sb), passhash_lvl1, __passhash_lvl_iter);
|
||||
// lvl 2 hash - is being used to authorize client on server
|
||||
str _passhash_lvl1_str = str_construct(passhash_lvl1, password_hash_size, false);
|
||||
str _passhash_lvl1_str = str_construct((void*)passhash_lvl1, password_hash_size, false);
|
||||
hash_password(_passhash_lvl1_str, cred->passhash_lvl2, __passhash_lvl_iter);
|
||||
|
||||
|
||||
@ -162,7 +162,7 @@ static Result(ClientCredential*) ClientCredential_create(str username, str passw
|
||||
return RESULT_VALUE(p, cred);
|
||||
}
|
||||
|
||||
static void ServerConnection_close(ServerConnection* conn){
|
||||
void ServerConnection_close(ServerConnection* conn){
|
||||
if(conn == NULL)
|
||||
return;
|
||||
socket_close(conn->system_socket);
|
||||
@ -170,7 +170,7 @@ static void ServerConnection_close(ServerConnection* conn){
|
||||
free(conn);
|
||||
}
|
||||
|
||||
static Result(ServerConnection*) connectToServer(EndpointIPv4 server_end, str server_key){
|
||||
Result(ServerConnection*) connectToServer(EndpointIPv4 server_end, str server_key){
|
||||
Deferral(64);
|
||||
if(client_credential == NULL){
|
||||
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
#include "cryptography.h"
|
||||
#include <assert.h>
|
||||
#include "tlibc/time.h"
|
||||
|
||||
void EncryptorAES_create(EncryptorAES* ptr, Array(u8) key){
|
||||
//TODO: use AES CTR encryption instead of my own padding algorithm
|
||||
|
||||
void EncryptorAES_init(EncryptorAES* ptr, Array(u8) key){
|
||||
assert(key.size == 16 || key.size == 24 || key.size == 32);
|
||||
|
||||
br_aes_ct64_cbcenc_init(&ptr->enc_ctx, key.data, key.size);
|
||||
|
||||
// uses CLOCK_REALTIME to seed rng
|
||||
nsec_t time_now = getTimeNsec();
|
||||
br_hmac_drbg_init(&ptr->rng_ctx, &br_sha256_vtable, &time_now, sizeof(time_now));
|
||||
rng_init_sha256_seedFromTime(&br_hmac_drbg_vtable, &ptr->rng_ctx.vtable);
|
||||
|
||||
memset(ptr->buf, 0, __AES_BUFFER_SIZE);
|
||||
memset(ptr->iv, 0, sizeof(ptr->iv));
|
||||
@ -51,7 +49,7 @@ void EncryptorAES_encrypt(EncryptorAES* ptr, Array(u8) src, Array(u8) dst){
|
||||
}
|
||||
|
||||
|
||||
void DecryptorAES_create(DecryptorAES* ptr, Array(u8) key){
|
||||
void DecryptorAES_init(DecryptorAES* ptr, Array(u8) key){
|
||||
assert(key.size == 16 || key.size == 24 || key.size == 32);
|
||||
|
||||
br_aes_ct64_cbcdec_init(&ptr->dec_ctx, key.data, key.size);
|
||||
|
||||
164
src/cryptography/RSA.c
Normal file
164
src/cryptography/RSA.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include "cryptography.h"
|
||||
#include <assert.h>
|
||||
#include "bearssl_x509.h"
|
||||
|
||||
// https://crypto.stackexchange.com/questions/3110/impacts-of-not-using-rsa-exponent-of-65537
|
||||
#define DEFAULT_PUBLIC_EXPONENT 65537
|
||||
|
||||
bool RSA_generateKeyPair(u32 key_size,
|
||||
br_rsa_private_key* sk, void* sk_buf,
|
||||
NULLABLE(br_rsa_public_key*) pk, NULLABLE(void* pk_buf))
|
||||
{
|
||||
br_hmac_drbg_context rng_ctx;
|
||||
const br_prng_class** rng_class_ptr = &rng_ctx.vtable;
|
||||
rng_init_sha256_seedFromTime(&br_hmac_drbg_vtable, rng_class_ptr);
|
||||
u32 r = br_rsa_i31_keygen(rng_class_ptr, sk, sk_buf, pk, pk_buf, key_size, DEFAULT_PUBLIC_EXPONENT);
|
||||
return r;
|
||||
}
|
||||
|
||||
Result(void) RSA_computePublicKey(br_rsa_private_key* sk, br_rsa_public_key* pk){
|
||||
Deferral(16);
|
||||
br_rsa_compute_modulus compute_modulus = br_rsa_i31_compute_modulus;
|
||||
br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp;
|
||||
|
||||
size_t modulus_size = compute_modulus(NULL, sk);
|
||||
if (modulus_size == 0) {
|
||||
Return RESULT_ERROR("compute_modulus", false);
|
||||
}
|
||||
void* modulus = malloc(modulus_size);
|
||||
bool success = false;
|
||||
Defer(
|
||||
if(!success)
|
||||
free(modulus)
|
||||
);
|
||||
if (compute_modulus(modulus, sk) != modulus_size) {
|
||||
Return RESULT_ERROR("compute_modulus", false);
|
||||
}
|
||||
|
||||
u32 pubexp_little_endian = compute_pubexp(sk);
|
||||
if (pubexp_little_endian == 0) {
|
||||
Return RESULT_ERROR("compute_pubexp", false);
|
||||
}
|
||||
u8 pubexp_big_endian[4];
|
||||
pubexp_big_endian[0] = pubexp_little_endian >> 24;
|
||||
pubexp_big_endian[1] = pubexp_little_endian >> 16;
|
||||
pubexp_big_endian[2] = pubexp_little_endian >> 8;
|
||||
pubexp_big_endian[3] = pubexp_little_endian;
|
||||
|
||||
pk->n = modulus;
|
||||
pk->nlen = modulus_size;
|
||||
pk->e = pubexp_big_endian;
|
||||
pk->elen = sizeof pubexp_big_endian;
|
||||
success = true;
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) RSA_serializePrivateKey_RawDER(
|
||||
br_rsa_private_key* sk,
|
||||
NULLABLE(br_rsa_public_key*) pk,
|
||||
Array(u8)* out_der)
|
||||
{
|
||||
Deferral(32);
|
||||
br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp;
|
||||
br_rsa_compute_privexp compute_privexp = br_rsa_i31_compute_privexp;
|
||||
|
||||
if(pk == NULL){
|
||||
try_void(RSA_computePublicKey(sk, pk));
|
||||
Defer(free(pk->n));
|
||||
}
|
||||
|
||||
u32 pubexp_little_endian = compute_pubexp(sk);
|
||||
if (pubexp_little_endian == 0) {
|
||||
Return RESULT_ERROR("compute_pubexp", false);
|
||||
}
|
||||
size_t privexp_size = compute_privexp(NULL, sk, pubexp_little_endian);
|
||||
if (privexp_size == 0) {
|
||||
Return RESULT_ERROR("compute_privexp", false);
|
||||
}
|
||||
void* privexp = malloc(privexp_size);
|
||||
Defer(free(privexp));
|
||||
if (compute_privexp(privexp, sk, pubexp_little_endian) != privexp_size) {
|
||||
Return RESULT_ERROR("compute_privexp", false);
|
||||
}
|
||||
|
||||
|
||||
size_t der_size = br_encode_rsa_raw_der(NULL, sk, pk, privexp, privexp_size);
|
||||
if (der_size == 0) {
|
||||
Return RESULT_ERROR("br_encode_rsa_raw_der", false);
|
||||
}
|
||||
void* der = malloc(der_size);
|
||||
bool success = false;
|
||||
Defer(
|
||||
if(!success)
|
||||
free(der)
|
||||
);
|
||||
if (br_encode_rsa_raw_der(der, sk, pk, privexp, privexp_size) != der_size) {
|
||||
Return RESULT_ERROR("br_encode_rsa_raw_der", false);
|
||||
}
|
||||
|
||||
success = true;
|
||||
out_der->data = der;
|
||||
out_der->size = der_size;
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
void PEM_encode(Array(u8) src, Array(u8)* dst, cstr label){
|
||||
u64 encoded_size = br_pem_encode(NULL, src.data, src.size, label, 0);
|
||||
// br_pem_encode doesn't count '\0' but writes it
|
||||
*dst = Array_alloc_size(encoded_size + 1);
|
||||
br_pem_encode(dst->data, src.data, src.size, label, 0);
|
||||
}
|
||||
|
||||
|
||||
Result(void) RSA_parsePrivateKey_DER(Array(u8) _src, br_rsa_private_key* sk){
|
||||
Deferral(16);
|
||||
// private key data will be written in this buffer on success
|
||||
Array(u8) buf = Array_copy(_src);
|
||||
bool success = false;
|
||||
Defer(free(buf.data));
|
||||
|
||||
br_skey_decoder_context decoder;
|
||||
br_skey_decoder_init(&decoder);
|
||||
br_skey_decoder_push(&decoder, buf.data, buf.size);
|
||||
i32 errcode = br_skey_decoder_last_error(&decoder);
|
||||
if (errcode != 0) {
|
||||
Return RESULT_ERROR_FMT("br_skey_decoder error %i", errcode);
|
||||
}
|
||||
i32 parsed_type = br_skey_decoder_key_type(&decoder);
|
||||
if(parsed_type != BR_KEYTYPE_RSA){
|
||||
Return RESULT_ERROR_FMT("parsed key has unsupported type %i", parsed_type);
|
||||
}
|
||||
const br_rsa_private_key* decoded_key = br_skey_decoder_get_rsa(&decoder);
|
||||
if(decoded_key == NULL){
|
||||
Return RESULT_ERROR("decoder failed without errors", false);
|
||||
}
|
||||
|
||||
success = true;
|
||||
memcpy(sk, decoded_key, sizeof(*decoded_key));
|
||||
|
||||
// sk fields still point to stack array decoder.key_data
|
||||
// This code copies the data and adjusts sk fields to point to the copied chunk
|
||||
Array(u8) key_data_copy = Array_alloc_size(BR_RSA_KBUF_PRIV_SIZE(decoded_key->n_bitlen));
|
||||
Defer(
|
||||
if(!success)
|
||||
free(key_data_copy.data);
|
||||
);
|
||||
memcpy(key_data_copy.data, decoder.key_data, key_data_copy.size);
|
||||
u64 memory_distance = (u64)key_data_copy.data - (u64)(void*)decoder.key_data;
|
||||
u8** sk_pointer_fields[] = {
|
||||
&sk->p, &sk->q, &sk->dp, &sk->dq, &sk->iq
|
||||
};
|
||||
for(u32 i = 0; i < ARRAY_LEN(sk_pointer_fields); i++){
|
||||
u8** field_place = sk_pointer_fields[i];
|
||||
u64 field_value = (u64)*field_place;
|
||||
field_value += memory_distance;
|
||||
*field_place = (void*)field_value;
|
||||
}
|
||||
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
void EncryptorRSA_init(EncryptorRSA* ptr, Array(u8) key){
|
||||
|
||||
}
|
||||
|
||||
@ -2,9 +2,15 @@
|
||||
#include "tlibc/std.h"
|
||||
#include "tlibc/collections/Array.h"
|
||||
#include "tlibc/string/str.h"
|
||||
#include "tlibc/errors.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_rand.h"
|
||||
#include "bearssl_rsa.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// hash.c //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @brief hashes password multiple times using its own hash as salt
|
||||
/// @param password some byte array
|
||||
@ -14,6 +20,25 @@ void hash_password(str password, u8* out_buffer, i32 iterations);
|
||||
#define password_hash_size 32
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// rng.c //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @brief Initialize prng context with sha256 hashing algorithm and seed from CLOCK_REALTIME.
|
||||
/// @param rng_class pointer to static vtable variable
|
||||
/// @param rng_ctx pointer to vtable field in prng context
|
||||
/// EXAMPLE:
|
||||
/// ```
|
||||
/// br_hmac_drbg_context rng_ctx;
|
||||
/// rng_init_sha256_seedFromTime(&br_hmac_drbg_vtable, &rng_ctx.vtable);
|
||||
/// ```
|
||||
void rng_init_sha256_seedFromTime(const br_prng_class* rng_class, const br_prng_class** rng_ctx);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AES.c //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct EncryptedBlockInfo {
|
||||
u8 padding_size;
|
||||
u32 _reserved;
|
||||
@ -33,7 +58,7 @@ typedef struct EncryptorAES {
|
||||
} EncryptorAES;
|
||||
|
||||
/// @param key Array<u8, 16 | 24 | 32>
|
||||
void EncryptorAES_create(EncryptorAES* ptr, Array(u8) key);
|
||||
void EncryptorAES_init(EncryptorAES* ptr, Array(u8) key);
|
||||
|
||||
/// @brief Encrypts `src` and writes output to `dst`.
|
||||
/// @param src array of any size
|
||||
@ -50,7 +75,7 @@ typedef struct DecryptorAES {
|
||||
} DecryptorAES;
|
||||
|
||||
/// @param key Array<u8, 16 | 24 | 32>
|
||||
void DecryptorAES_create(DecryptorAES* ptr, Array(u8) key);
|
||||
void DecryptorAES_init(DecryptorAES* ptr, Array(u8) key);
|
||||
|
||||
/// @brief Decrypts `src` and writes output to `dst`.
|
||||
/// @param src array of any size
|
||||
@ -59,12 +84,47 @@ void DecryptorAES_create(DecryptorAES* ptr, Array(u8) key);
|
||||
void DecryptorAES_decrypt(DecryptorAES* ptr, Array(u8) src, Array(u8) dst, u32* decrypted_size);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// RSA.c //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RSA_generateKeyPair(u32 key_size,
|
||||
br_rsa_private_key* sk, void* sk_buf,
|
||||
NULLABLE(br_rsa_public_key*) pk, NULLABLE(void* pk_buf));
|
||||
|
||||
/// @param sk some private key
|
||||
/// @param pk out public key. WARNING: .n is allocated on heap
|
||||
Result(void) RSA_computePublicKey(br_rsa_private_key* sk, br_rsa_public_key* pk);
|
||||
|
||||
/// @brief Serialize key in raw DER binary format
|
||||
/// @param sk the private key
|
||||
/// @param pk set to NULL to calculate automatically
|
||||
/// @param out_der out array. WARNING: .data is allocated on heap
|
||||
Result(void) RSA_serializePrivateKey_RawDER(
|
||||
br_rsa_private_key* sk,
|
||||
NULLABLE(br_rsa_public_key*) pk,
|
||||
Array(u8)* out_der);
|
||||
|
||||
/// @brief Encode key data in human-readable format
|
||||
/// @param src some data
|
||||
/// @param dst out array. WARNING: .data is allocated on heap
|
||||
/// @param label some string to write at the top of PEM file
|
||||
void PEM_encode(Array(u8) src, Array(u8)* dst, cstr label);
|
||||
|
||||
/// @param src serialized private key in DER format
|
||||
/// @param sk out private key. WARNING: .p is allocated on heap
|
||||
Result(void) RSA_parsePrivateKey_DER(Array(u8) src, br_rsa_private_key* sk);
|
||||
|
||||
typedef struct EncryptorRSA {
|
||||
br_rsa_public_key public_key;
|
||||
} EncryptorRSA;
|
||||
/// @param key Array<u8, 16 | 24 | 32>
|
||||
void EncryptorRSA_init(EncryptorRSA* ptr, Array(u8) key);
|
||||
|
||||
|
||||
typedef struct DecryptorRSA {
|
||||
br_rsa_private_key private_key;
|
||||
} DecryptorRSA;
|
||||
|
||||
/// @param key Array<u8, 16 | 24 | 32>
|
||||
void DecryptorRSA_init(DecryptorRSA* ptr, Array(u8) key);
|
||||
|
||||
7
src/cryptography/rng.c
Normal file
7
src/cryptography/rng.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "cryptography.h"
|
||||
#include "tlibc/time.h"
|
||||
|
||||
void rng_init_sha256_seedFromTime(const br_prng_class* rng_class, const br_prng_class** rng_ctx){
|
||||
nsec_t time_now = getTimeNsec();
|
||||
rng_class->init(rng_ctx, &br_sha256_vtable, &time_now, sizeof(time_now));
|
||||
}
|
||||
46
src/main.c
46
src/main.c
@ -1,5 +1,6 @@
|
||||
#include "network/network.h"
|
||||
#include "chat.h"
|
||||
#include "cryptography/cryptography.h"
|
||||
|
||||
typedef enum ProgramMode {
|
||||
Client,
|
||||
@ -11,6 +12,51 @@ typedef enum ProgramMode {
|
||||
int main(const int argc, cstr const* argv){
|
||||
Deferral(32);
|
||||
|
||||
const u32 key_size = 2048;
|
||||
|
||||
br_rsa_private_key sk;
|
||||
const u32 sk_buf_size = BR_RSA_KBUF_PRIV_SIZE(key_size);
|
||||
u8 sk_buf[sk_buf_size];
|
||||
memset(sk_buf, 0, sk_buf_size);
|
||||
|
||||
br_rsa_public_key pk;
|
||||
const u32 pk_buf_size = BR_RSA_KBUF_PUB_SIZE(key_size);
|
||||
u8 pk_buf[pk_buf_size];
|
||||
memset(pk_buf, 0, pk_buf_size);
|
||||
|
||||
if(!RSA_generateKeyPair(key_size, &sk, sk_buf, &pk, pk_buf)){
|
||||
printfe("ERROR: can't generate RSA key pair\n");
|
||||
Return 1;
|
||||
}
|
||||
|
||||
br_rsa_public_key pk2;
|
||||
try_fatal_void(RSA_computePublicKey(&sk, &pk2));
|
||||
Defer(free(pk2.n));
|
||||
if(memcmp(pk2.n, pk.n, pk.nlen) != 0){
|
||||
printfe("public key computation failed\n");
|
||||
Return 1;
|
||||
}
|
||||
|
||||
Array(u8) der;
|
||||
try_fatal_void(RSA_serializePrivateKey_RawDER(&sk, &pk, &der));
|
||||
Defer(free(der.data));
|
||||
Array(u8) pem;
|
||||
Defer(free(pem.data));
|
||||
PEM_encode(der, &pem, "RSA PRIVATE KEY");
|
||||
printf("\nserialized key:\n%s\n\n", (char*)pem.data);
|
||||
|
||||
br_rsa_private_key sk2;
|
||||
try_fatal_void(RSA_parsePrivateKey_DER(der, &sk2));
|
||||
Defer(free(sk2.p));
|
||||
|
||||
free(der.data);
|
||||
try_fatal_void(RSA_serializePrivateKey_RawDER(&sk2, &pk, &der));
|
||||
free(pem.data);
|
||||
PEM_encode(der, &pem, "RSA PRIVATE KEY");
|
||||
printf("\nparsed key:\n%s\n\n", (char*)pem.data);
|
||||
|
||||
Return 0;
|
||||
|
||||
ProgramMode mode = Client;
|
||||
cstr server_endpoint_cstr;
|
||||
|
||||
|
||||
@ -12,7 +12,8 @@ static void* handle_connection(void* _args);
|
||||
|
||||
Result(void) server_run(cstr server_endpoint_str){
|
||||
Deferral(32);
|
||||
EndpointIPv4 server_end = EndpointIPv4_fromStr(server_endpoint_str);
|
||||
EndpointIPv4 server_end;
|
||||
EndpointIPv4_parse(server_endpoint_str, &server_end);
|
||||
//TODO: add log
|
||||
try(Socket main_socket, i, socket_open_TCP());
|
||||
try_void(socket_bind(main_socket, server_end));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user