CryptoDit/speed.c
2026-01-31 16:45:53 +01:00

269 lines
6.4 KiB
C

#include "speed.h"
#include <sys/time.h>
int speed(char **argv, int argc){
int res = 0;
size_t keysize;
int type = 0;
int to_stdout = 0;
res = check_arguments_speed(argv, argc, &type, &keysize, &to_stdout);
if (res < 0)
return -1;
// Generate key
if (type == TYPE_SPEED_RSA || type == TYPE_SPEED_ALL){
res = speed_generate_rsa_keys(2048, to_stdout);
if (res < 0)
return -1;
res = speed_generate_rsa_keys(4192, to_stdout);
if (res < 0 )
return -1;
}
if (type == TYPE_SPEED_ELLIPTIC || type == TYPE_SPEED_ALL){
res = speed_generate_elliptic_keys(2048, to_stdout);
}
return res;
}
/*
* This function generate RSA keys
*/
static int speed_generate_rsa_keys(size_t keysize, const int to_stdout){
RSA *rsa = NULL;
BIGNUM *e = NULL;
char nE[5];
BIO *bioPublic = NULL;
BIO *bioPrivate = NULL;
char buf_public[2049];
char buf_private[2049];
size_t keys;
unsigned long ms_start;
unsigned long ms_end;
// For the exponent: RSA_F4 = 65537
sprintf(nE, "%ld", RSA_F4);
//printf("%s\n", nE);
BN_dec2bn(&e, nE);
ms_start = getms();
rsa = RSA_new();
if (rsa == NULL){
printf("Failed to create RSA\n");
return -1;
}
RSA_generate_key_ex(rsa, keysize, e, NULL);
bioPublic = BIO_new(BIO_s_mem());
if (bioPublic == NULL){
RSA_free(rsa);
BN_free(e);
printf("Failed to new BIO public\n");
return -1;
}
bioPrivate = BIO_new(BIO_s_mem());
if (bioPrivate == NULL){
printf("Failed to create BIO private key\n");
RSA_free(rsa);
BIO_free(bioPublic);
BN_free(e);
return -1;
}
PEM_write_bio_RSAPublicKey(bioPublic, rsa);
PEM_write_bio_RSAPrivateKey(bioPrivate, rsa, NULL, NULL, 0, NULL, NULL);
ms_end = getms();
long diff = ms_end - ms_start;
/* Dump the both public and privte keys */
if (to_stdout){
printf("RSA public key:\n");
print_key(bioPublic);
printf("RSA private key:\n");
print_key(bioPrivate);
}
/* Print the output of the test */
printf("The generation of the RSA key %ld bits took %ld ms\n", keysize, diff);
// Clean
BIO_free(bioPublic);
BIO_free(bioPrivate);
RSA_free(rsa);
BN_free(e);
return 0;
}
/*
* This function dump the key from BIO
*/
static void print_key(BIO *bio){
char *buf = NULL;
size_t key_size = BIO_pending(bio);
buf = malloc(key_size + 1);
if (buf == NULL){
printf("Failed to allocate memory\n");
return;
}
BIO_read(bio, buf, key_size);
buf[key_size] = '\0';
printf("%s\n", buf);
free(buf);
}
/*
* This function generate elliptic keys
https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
*/
static int speed_generate_elliptic_keys(size_t keysize, const int to_stdout){
EC_GROUP *curve = NULL;
EC_KEY *key = NULL;
const EC_POINT *pub = NULL;
unsigned long ms_start;
unsigned long ms_end;
/*
* List of curve:
* /usr/include/openssl/obj_mac.h
* $ openssl ecparam -list_curves
*/
/*curve = EC_GROUP_new_by_curve_name_ex(NULL, NULL, NID_X9_62_prime256v1);
if (curve == NULL){
printf("Failed to generate the curve\n");
return -1;
}*/
ms_start = getms();
key = EC_KEY_new_by_curve_name(NID_secp256k1);
if (key == NULL){
printf("Failed to generate the curve keys\n");
return -1;
}
/*
* Generating both private and public keys
* return 1 on success, otherwise it's 0
*/
if (EC_KEY_generate_key(key) == 0){
EC_KEY_free(key);
return -1;
}
ms_end = getms();
long diff = ms_end - ms_start;
/*
* Both private and public keys has been set up.
* We can get them
*/
pub = EC_KEY_get0_public_key(key);
if (pub == NULL){
printf("Failed to get the EC public key\n");
EC_KEY_free(key);
return -1;
}
if (to_stdout){
if (ec_get_pub_key(key, pub) < 0){
EC_KEY_free(key);
return -1;
}
}
/* Print the output of the test */
printf("The generation of the EC key secp256 took %ld ms\n", diff);
EC_KEY_free(key);
return 0;
}
/*
* This function load and dump the EC public key
*/
static int ec_get_pub_key(const EC_KEY *key, const EC_POINT *pub){
const EC_GROUP *curve = NULL;
BIGNUM *bn = NULL;
uint8_t len = 0;
char *buf = NULL;
bn = BN_new();
if (bn == NULL){
return -1;
}
/* For pub key, get the EC group */
curve = EC_KEY_get0_group(key);
if (curve == NULL){
printf("Failed to get the EC Group\n");
return -1;
}
BN_CTX *bn_ctx = BN_CTX_new();
buf = EC_POINT_point2hex(curve, pub, POINT_CONVERSION_UNCOMPRESSED, bn_ctx);
printf("Public key:\n%s\n", buf);
// Galois Field degree
int bits = EC_GROUP_get_degree(curve);
//printf("%d\n", bits);
bits = EC_GROUP_order_bits(curve);
//printf("%d\n", bits);
// Save to file
/*FILE *f = fopen("public_ec.pem", "w");
PEM_write_EC_PUBKEY(f, key);
fclose(f);*/
BN_free(bn);
OPENSSL_free(buf);
BN_CTX_free(bn_ctx);
return 0;
}
static int check_arguments_speed(char **argv, const int argc, int *type, size_t *keysize, int *to_stdout){
int res = -1;
/* we bypass the first action arguments */
for (int i = 3; i < argc; i++){
size_t l = strlen(argv[i]);
if (strncmp(argv[i], "-type", l) == 0){
if (strcmp(argv[i + 1], "rsa") == 0)
*type = TYPE_SPEED_RSA;
else if (strcmp(argv[i + 1], "elliptic") == 0)
*type = TYPE_SPEED_ELLIPTIC;
else if (strcmp(argv[i + 1], "all") == 0)
*type = TYPE_SPEED_ALL;
res = 0;
}
if (strncmp(argv[i], "-text", l) == 0)
*to_stdout = 1;
}
return res;
}
static unsigned long getms() {
/*
* struct timeval store second and microseconds values
* tv_sec -> seconds
* tv_usec -> microseconds
* https://man7.org/linux/man-pages/man3/timeval.3type.html
*/
struct timeval tp;
gettimeofday(&tp, NULL);
/*
* We multiple by 1000 for converting second to milliseconds
* Then, we need to convert micro to millis by dividing by 1000
*/
return tp.tv_sec * 1000 + tp.tv_usec / 1000;
}