rsa key initialization
This commit is contained in:
@@ -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));
|
||||
}
|
||||
Reference in New Issue
Block a user