#include "speed.h" #include 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; }