269 lines
6.4 KiB
C
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;
|
|
}
|