rsa key initialization

This commit is contained in:
2025-09-13 02:29:26 +05:00
parent f01c5fc8a9
commit 98ae36ad2f
8 changed files with 292 additions and 16 deletions

View File

@@ -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
View 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){
}

View File

@@ -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
View 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));
}