From 578ef21219a8a6fef74d686f4d4f2c7fe6b8d9d3 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 31 Jan 2026 16:45:53 +0100 Subject: [PATCH] First commit --- .gitignore | 1 + README.md | 78 +++++++ argparse.c | 22 ++ argparse.h | 9 + audit/audit.h | 13 ++ audit/file.c | 114 +++++++++++ audit/file.h | 13 ++ audit/fips.c | 455 +++++++++++++++++++++++++++++++++++++++++ audit/fips.h | 62 ++++++ certificate.c | 187 +++++++++++++++++ certificate.h | 23 +++ common.h | 12 ++ cryptodit | Bin 0 -> 38368 bytes entropy.c | 88 ++++++++ entropy.h | 17 ++ entropy_ebpf.c | 62 ++++++ entropy_ebpf.o | Bin 0 -> 8024 bytes error.h | 16 ++ examples/cert.pem | 11 + examples/csr.pem | 8 + examples/foo.pem | 9 + examples/private.key | 9 + examples/public.key | 4 + examples/public_ec.pem | 4 + exec.sh | 5 + main.c | 63 ++++++ speed.c | 268 ++++++++++++++++++++++++ speed.h | 24 +++ utils.c | 5 + utils.h | 7 + 30 files changed, 1589 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 argparse.c create mode 100644 argparse.h create mode 100644 audit/audit.h create mode 100644 audit/file.c create mode 100644 audit/file.h create mode 100644 audit/fips.c create mode 100644 audit/fips.h create mode 100644 certificate.c create mode 100644 certificate.h create mode 100644 common.h create mode 100755 cryptodit create mode 100644 entropy.c create mode 100644 entropy.h create mode 100644 entropy_ebpf.c create mode 100644 entropy_ebpf.o create mode 100644 error.h create mode 100644 examples/cert.pem create mode 100644 examples/csr.pem create mode 100644 examples/foo.pem create mode 100644 examples/private.key create mode 100644 examples/public.key create mode 100644 examples/public_ec.pem create mode 100755 exec.sh create mode 100644 main.c create mode 100644 speed.c create mode 100644 speed.h create mode 100644 utils.c create mode 100644 utils.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a43f9f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**.swp diff --git a/README.md b/README.md new file mode 100644 index 0000000..2cb8bb2 --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# CryptoDit +CryptoDit (short for Cryptography Audit). This program audit the cryptography modules. +- The program check the speed for generating RSA/ECDSA key +- Check if the RSA key are compliant with FIPS Key size, exponent, ownership, file permissions, etc.) +- Check the entropy pool in the kernel with the eBPF technology + +## Requirements +The program use the library of OpenSSL for reading a certificate and eBPF for the entropy module. It's important to install the following package: + +* libssl-dev. +* bpftool +* clang-11 +* libbpf-dev +* gcc and gcc-multilib + + +# Examples + +## Speed test +``` +$ ./cryptodit -m speed -type all +Module: speed +The generation of the RSA key 2048 bits took 116 ms +The generation of the RSA key 4192 bits took 2218 ms +The generation of the EC key secp256 took 1 ms +``` + +## RSA public key compliance + +``` +$ ./cryptodit -m certificate -type rsa -pubin public.pem +Module: certificate +File information + Filename: public.pem + File size: 182 + Permission: 644 + +Checking file ownerships compliance... +Audit passed with success. The owner of the file isn't root. + +Checking file permissions compliance... +The certificate has the correct permission for the owner. +The group has the permission to manipulate the file. Should be removed. +The other has the permission to manipulate the file. Should be removed. + +Checking FIPS compliance... +Certificate information: + Key size: 64 bytes (512) + Exponent: 65537 + Format RSA key: SPKI + +Exponent result: + The exponent is correct, the FIPS compliance is respected. +Keysize result: + The key size is lower than 2048. The key should be at least 2048 bits. +``` + +## X.509 compliance + +``` +$ ./cryptodit -m certificate -type x509 -pubin cert.pem +``` +## Entropy +``` +$ sudo ./cryptodit -m entropy +Module: entropy +libbpf: elf: skipping unrecognized data section(8) .rodata.str1.1 +proc: (openssl); pid: 85059 +proc: (WebExtensions); pid: 4520 +proc: (Privileged; pid: 4549 +proc: (Isolated; pid: 82753 +proc: (MainThread); pid: 85089 +proc: (tracker-extract); pid: 85188 +proc: (tracker-extract); pid: 85209 +proc: (terminator); pid: 8774 +proc: (python3); pid: 85231 +``` + diff --git a/argparse.c b/argparse.c new file mode 100644 index 0000000..5643d4b --- /dev/null +++ b/argparse.c @@ -0,0 +1,22 @@ +#include "argparse.h" + +/* + * This function check all arguments + * Return the 0 if success or 1 if failed +*/ +int check_arguments(char **args, const int len, char *buf_module, const size_t bufsize){ + int i; + int res = -1; + // Bypass the first arguments, because it's the script itself + for (i = 1; i < len; i++){ + // check if it's an option + if (args[i][0] == '-'){ + if (args[i][1] == 'm') { + // Get the module + strcpy(buf_module, args[i + 1]); + res = 0; + } + } + } + return res; +} diff --git a/argparse.h b/argparse.h new file mode 100644 index 0000000..1083181 --- /dev/null +++ b/argparse.h @@ -0,0 +1,9 @@ +#ifndef H_ARGPARSE +#define H_ARGPARSE + +#include +#include + +int check_arguments(char **, const int, char *, const size_t); + +#endif diff --git a/audit/audit.h b/audit/audit.h new file mode 100644 index 0000000..2b7c78c --- /dev/null +++ b/audit/audit.h @@ -0,0 +1,13 @@ +#ifndef H_AUDIT +#define H_AUDIT + +#define BUF_SIZE_AUDIT 256 +#define TRUE 0 +#define FALSE 1 + +struct st_audit{ + char result[BUF_SIZE_AUDIT]; + int audit; /* TRUE or FALSE */ +}; + +#endif diff --git a/audit/file.c b/audit/file.c new file mode 100644 index 0000000..898829d --- /dev/null +++ b/audit/file.c @@ -0,0 +1,114 @@ +#include +#include "file.h" +#include "audit.h" + +/* + * This function check the ownership of the file + * If the owner is root, the audit test fail + * Return the struct st_audit which contain the result + */ +struct st_audit ownership(uid_t uid, char *username, size_t len){ + struct st_audit st_audit; + get_username(uid, username); + if (strncmp(username, "root", 64) == 0){ + //printf("The %s account is not recommended. You should change the owner.\n", username); + char result[BUF_SIZE_AUDIT]; + sprintf(st_audit.result, "The account %s is not recommended. You should change the owner.", username); + st_audit.audit = FALSE; + } + else{ + //printf("The owner of the file is not root, it's recommended.\n"); + sprintf(st_audit.result, "Audit passed with success. The owner of the file isn't root."); + st_audit.audit = TRUE; + } + return st_audit; +} +/* + * This function check the permission of the file + * Return the struct st_audit which contain the result + * https://www.man7.org/linux/man-pages/man2/chmod.2.html + */ +void permission(mode_t mode, struct st_audit *st_audit_owner, struct st_audit *st_audit_group, struct st_audit *st_audit_other){ + + /* Owner */ + int irusr = mode & S_IRUSR; + int iwusr = mode & S_IWUSR; + int ixusr = mode & S_IXUSR; + if (irusr == 0 && iwusr == 0) { + sprintf(st_audit_owner->result, "Audit passed with success. Only the owner has the privilege to read/write the file."); + st_audit_owner->audit = TRUE; + } + else if (ixusr != 0){ + sprintf(st_audit_owner->result, "The file can be executabled for the owner. The permission should be removed."); + st_audit_owner->audit = FALSE; + } + else{ + sprintf(st_audit_owner->result, "The certificate has the correct permission for the owner."); + st_audit_owner->audit = TRUE; + } + + /* Group */ + int irgrp = mode & S_IRGRP; + int iwgrp = mode & S_IWGRP; + int ixgrp = mode & S_IXGRP; + if (irgrp != 0 || iwgrp != 0 || ixgrp != 0){ + sprintf(st_audit_group->result, "The group has the permission to manipulate the file. Should be removed."); + st_audit_group->audit = FALSE; + } + else + st_audit_group->audit = TRUE; + + /* Other */ + int iroth = mode & S_IROTH; + int iwoth = mode & S_IWOTH; + int ixoth = mode & S_IXOTH; + if (iroth != 0 || iwoth != 0 || ixoth != 0){ + sprintf(st_audit_other->result, "The other has the permission to manipulate the file. Should be removed."); + st_audit_other->audit = FALSE; + } + else + st_audit_other->audit = TRUE; +} +/* + * This function convert the mode_t value to human-readable value + */ +int convert_mode_t(mode_t mode){ + int perm = 0; + + /* Owner */ + if (mode & S_IRUSR) + perm += 400; + if (mode & S_IWUSR) + perm += 200; + if (mode & S_IXUSR) + perm += 100; + /* Group */ + if (mode & S_IRGRP) + perm += 40; + if (mode & S_IWGRP) + perm += 20; + if (mode & S_IXGRP) + perm += 10; + /* Other */ + if (mode & S_IROTH) + perm += 4; + if (mode & S_IWOTH) + perm += 2; + if (mode & S_IXOTH) + perm += 1; + + return perm; +} +/* + * This function retrieve the username from the uid_t passed in argument + */ +static void get_username(uid_t uid, char *username){ + struct passwd *p; + p = getpwuid(uid); + if (p == NULL){ + //printf("Failed to get the username from the UID\n"); + strncpy(username, "Unknown", 8); + return; + } + strncpy(username, p->pw_name, 64); +} diff --git a/audit/file.h b/audit/file.h new file mode 100644 index 0000000..988f917 --- /dev/null +++ b/audit/file.h @@ -0,0 +1,13 @@ +#ifndef H_FILE +#define H_FILE + +#include +#include +#include + +struct st_audit ownership(uid_t, char *, size_t); +void permission(mode_t, struct st_audit *, struct st_audit *, struct st_audit *); +int convert_mode_t(mode_t); +static void get_username(uid_t uid, char *); + +#endif diff --git a/audit/fips.c b/audit/fips.c new file mode 100644 index 0000000..a22ada2 --- /dev/null +++ b/audit/fips.c @@ -0,0 +1,455 @@ +#include +#include +#include "fips.h" +#include "../utils.h" +#include "../error.h" + +/* + * SSL Format + * RSA PUBLIC KEY -> PKCS#1 format + * PUBLIC KEY -> PEM Format + */ + +static int DEBUG = 0; + +int fips(const char *pkey, struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const int type, const int is_pubkey, const int to_stdout){ + int res; + + if(type == TYPE_RSA){ + /* If it's a pub key, we are going to analyse it */ + if (is_pubkey == 1) + res = fips_pubkey_rsa(st_audit_fips, st_keyinfo, pkey, to_stdout); + else + res = fips_privkey_rsa(st_audit_fips, st_keyinfo, pkey, to_stdout); + } + else if (type == TYPE_X509){ + if (openssl_version() == 1) + res = fips_x509_v1(st_audit_fips, st_keyinfo, pkey, to_stdout); + else + res = fips_x509_v3(st_audit_fips, st_keyinfo, pkey, to_stdout); + } + return res; +} +/* + * This function load public RSA key and make an audit on it + */ +static int fips_pubkey_rsa(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey, const int to_stdout) { + struct rsa *rsa; + size_t keysize; + int res; + + /* + * Now, we check if the public certificate is compliant with FIPS + * The program check the length of the key, the exponent + */ + if (openssl_version() == 1) + res = loadkeys_rsa_v1(&rsa, pkey, &st_keyinfo->format); + else /* OpenSSL version 3 */ + res = loadkeys_rsa_v3(&rsa, pkey, &st_keyinfo->format); + + if (res > 0 || rsa == NULL){ + printf("Failed to read the public key\n"); + clean_rsa_st(rsa); + return res; + } + + audit_rsa_keys(rsa, st_audit_fips, st_keyinfo, pkey); + + // Clean + clean_rsa_st(rsa); + return 0; +} +/* + * This function audit RSA private key + */ +static int fips_privkey_rsa(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey, const int to_stdout) { + int res; + struct rsa *rsa = NULL; + + if (openssl_version() == 1) + res = load_priv_rsa_keys_v1(&rsa, pkey); + else /* OpenSSL version 3 */ + res = load_priv_rsa_keys_v3(&rsa, pkey); + + if (res > 0){ + printf("Failed to read the private key\n"); + clean_rsa_st(rsa); + return res; + } + + audit_rsa_keys(rsa, st_audit_fips, st_keyinfo, pkey); + + // Clean + clean_rsa_st(rsa); + return 0; +} + +/* + * If OpenSSL v3, we need tu use new OpenSSL functions for reading keys + */ +static int loadkeys_rsa_v3(struct rsa **rsa, const char *pkey, int *format){ + *rsa = (struct rsa*)malloc(sizeof(struct rsa*)); + + if (*rsa == NULL){ + if (DEBUG) + printf("Cannot malloc the structure\n"); + return COMMON_ERR_MALLOC; + } + + memset(*rsa, 0, sizeof(struct rsa*)); + + (*rsa)->bio = BIO_new(BIO_s_file()); + if (BIO_read_filename((*rsa)->bio, pkey) == 0){ + printf("Failed to read BIO\n"); + return FIPS_ERR_READ_BIO; + } + + #if OPENSSL_VERSION_NUMBER > 0x03000000f + (*rsa)->evp = PEM_read_bio_PUBKEY_ex((*rsa)->bio, NULL, NULL, NULL, NULL, NULL); + if ((*rsa)->evp == NULL){ + return FIPS_ERR_LOAD_KEY; + } + + //printf("Keysize: %d\n", EVP_PKEY_bits((*rsa)->evp)); + (*rsa)->rsa = EVP_PKEY_get1_RSA((*rsa)->evp); + if ((*rsa)->rsa == NULL){ + return FIPS_ERR_LOAD_RSA_KEY; + } + #endif + + // Get the format of the key + *format = 0; + return 0; +} +static int loadkeys_rsa_v1(struct rsa **rsa, const char *pkey, int *format){ + *rsa = (struct rsa*)malloc(sizeof(struct rsa*)); + + if (*rsa == NULL){ + if (DEBUG) + printf("Cannot malloc the structure\n"); + return COMMON_ERR_MALLOC; + } + memset(*rsa, 0, sizeof(struct rsa*)); + + (*rsa)->bio = BIO_new(BIO_s_file()); + if(BIO_read_filename((*rsa)->bio, pkey) == 0){ + printf("Failed to read BIO\n"); + return FIPS_ERR_READ_BIO; + } + + /* + * Works with PEM_read_RSAPublicKey, but when we try to read the file + * we cannot. This function "block" the access to the file + */ + /*rsa->rsa = PEM_read_RSAPublicKey(f, NULL, NULL, NULL); */ + + // Deprecated in OpenSSL v3 + /* + * RSAPublicKey read publickey at the PEM format + * RSA_PUBKEY read publickey at the PKCS1 format + */ + (*rsa)->rsa = PEM_read_bio_RSAPublicKey((*rsa)->bio, NULL, NULL, NULL); + if ((*rsa)->rsa == NULL){ + //print_error(); + + /* + * We need to reset or reseek the BIO, otherwise, we cannot read it + * https://docs.openssl.org/3.0/man3/BIO_ctrl/#synopsis + */ + //BIO_reset((*rsa)->bio); /* Works too */ + BIO_seek((*rsa)->bio, 0); + + (*rsa)->rsa = PEM_read_bio_RSA_PUBKEY((*rsa)->bio, NULL, NULL,NULL); + + if ((*rsa)->rsa == NULL){ + if (DEBUG) + printf("Cannot read the SPKI format of the public key\n"); + return FIPS_ERR_LOAD_KEY; + } + + *format = RSA_FORMAT_SPKI; + } + else + *format = RSA_FORMAT_PKCS1; + + return 0; +} + +/* + * This function load RSA Private key for OpenSSL v1 + */ +static int load_priv_rsa_keys_v1(struct rsa **rsa, const char *pkey){ + *rsa = (struct rsa*)malloc(sizeof(struct rsa*)); + + if (*rsa == NULL){ + if (DEBUG) + printf("Cannot malloc the structure\n"); + return COMMON_ERR_MALLOC; + } + + (*rsa)->bio = BIO_new(BIO_s_file()); + if ((*rsa)->bio == NULL){ + if (DEBUG) + printf("Failed to create new BIO\n"); + return FIPS_ERR_NEW_BIO; + } + if(BIO_read_filename((*rsa)->bio, pkey) == 0){ + printf("Failed to read BIO\n"); + return FIPS_ERR_READ_BIO; + } + + (*rsa)->rsa = PEM_read_bio_RSAPrivateKey((*rsa)->bio, NULL, NULL, NULL); + if ((*rsa)->rsa == NULL){ + if (DEBUG) + printf("Failed to read BIO RSAPrivateKey\n"); + return FIPS_ERR_LOAD_RSA_PRIV_KEY; + } + + return 0; +} +/* + * This function load RSA Private key for OpenSSL v3 + */ +static int load_priv_rsa_keys_v3(struct rsa **rsa, const char *pkey){ + *rsa = (struct rsa*)malloc(sizeof(struct rsa*)); + + if (*rsa == NULL){ + if (DEBUG) + printf("Cannot malloc the structure\n"); + return COMMON_ERR_MALLOC; + } + + (*rsa)->bio = BIO_new(BIO_s_file()); + if ((*rsa)->bio == NULL){ + if (DEBUG) + printf("Failed to create new BIO\n"); + return FIPS_ERR_NEW_BIO; + } + if(BIO_read_filename((*rsa)->bio, pkey) == 0){ + printf("Failed to read BIO\n"); + return FIPS_ERR_READ_BIO; + } + + #if OPENSSL_VERSION_NUMBER > 0x03000000f + (*rsa)->evp = PEM_read_bio_PrivateKey_ex((*rsa)->bio, NULL, NULL, NULL, NULL, NULL); + + if ((*rsa)->evp == NULL){ + if (DEBUG) + printf("Failed to read BIO PrivateKey\n"); + return FIPS_ERR_READ_BIO; + } + (*rsa)->rsa = EVP_PKEY_get1_RSA((*rsa)->evp); + if ((*rsa)->rsa == NULL) + return FIPS_ERR_LOAD_RSA_KEY; + #endif + + return 0; +} + +/* + * This function audit the RSA keys, both public and private + * For the audit, the function check the exponent (modulus) and the key size + */ +static void audit_rsa_keys(struct rsa *rsa, struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey){ + int res; + + st_keyinfo->keysize = RSA_size(rsa->rsa); + + st_keyinfo->algo = ALGO_RSA; + + // The return value is a const, shouldn't be freed + const BIGNUM *e = RSA_get0_e(rsa->rsa); + char *exponent = BN_bn2dec(e); + //free(exponent); + OPENSSL_free(exponent); + + /* Exponent has been set up, we can check it */ + res = check_exponent(e, st_audit_fips->audit_exponent.result, &st_keyinfo->exponent); + + /* + * Audit the key size. For a better security, the key size is at least 2048 bits + */ + if (st_keyinfo->keysize * 8 < 2048){ + sprintf(st_audit_fips->audit_keysize.result, "The key size is lower than 2048. The key should be at least 2048 bits."); + st_audit_fips->audit_keysize.audit = FALSE; + } + else{ + sprintf(st_audit_fips->audit_keysize.result, "The key size is upper or equal than 2048. The audit is passed with success."); + st_audit_fips->audit_keysize.audit = TRUE; + } +} + +/* + * In this function, we are going to check the exponent + * For testing if the exponent is odd or even, we apply a modulo 2 on the exponent + * If the result is 1, means the key has a remainder and the key is odd, if the result is 0, the exponent is even. + * Regarding to the FIPS 186-5, the exponent must be odd. + * The function check also the size of the exponent. + * When the key has been generated with OpenSSL, by default the exponent is 65537. + * The exponent e size must be 2 ** 16 < e < 2 ** 256 + */ +static int check_exponent(const BIGNUM *e, char *buf, unsigned long *exponent){ + BIGNUM *rem = BN_new(), *a = BN_new(), *m = BN_new(); + char nExponent[4]; + BN_CTX *ctx; + char *r; + int error = 0; + + sprintf(nExponent, "%d", 2); + BN_dec2bn(&m, nExponent); + //BN_mod(rem, e, m); + ctx = BN_CTX_new(); + BN_div(NULL, rem, e, m, ctx); + //r = malloc(4); + r = BN_bn2dec(rem); + //printf("%s\n", r); + + /* + * According to the FIPS 186-5, the exponent size must be 2 ** 16 < e < 2 ** 256 + * The exponent must be odd too + */ + char *exp = BN_bn2dec(e); + *exponent = (char2dec(exp[0]) * 10000) + (char2dec(exp[1]) * 1000) + (char2dec(exp[2])* 100) + (char2dec(exp[3]) * 10) + (char2dec(exp[4])); + // printf("Exp: %lu\n", exp); + + if (strcmp(r, "0") == 0){ + strncpy(buf, "The exponent is even, should be odd", BUF_SIZE_AUDIT); + error += 1; + } + + // Check the exponent size + double minSize = pow(2, 16); + double maxSize = pow(2, 256); + if (*exponent < minSize || *exponent > maxSize){ + strncpy(buf, "The exponent size is not correct. The minimum size is 2 ** 16 and maximum size 2 ** 256.", BUF_SIZE_AUDIT); + error += 1; + } + + // If no error + if (error == 0) + strncpy(buf, "The exponent is correct, the FIPS compliance is respected.", BUF_SIZE_AUDIT); + + // Cleaning + free(r); + BN_free(rem); + BN_free(a); + BN_free(m); + BN_CTX_free(ctx); + OPENSSL_free(exp); + return 0; +} + +/* + * This function load X509 certificate for OpenSSL v1 + */ +static int fips_x509_v1(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey, const int to_stdout){ + + return 0; +} +/* + * This function load X509 certificate for OpenSSL v3 + */ +static int fips_x509_v3(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey, const int to_stdout){ + struct rsa *rsa = (struct rsa*)malloc(sizeof(struct rsa*)); + + if (rsa == NULL){ + if (DEBUG) + printf("Cannot malloc the structure\n"); + return COMMON_ERR_MALLOC; + } + memset(rsa, 0, sizeof(struct rsa*)); + + rsa->bio = BIO_new(BIO_s_file()); + if (BIO_read_filename(rsa->bio, pkey) == 0){ + printf("Failed to read BIO\n"); + return FIPS_ERR_READ_BIO; + } + + #if OPENSSL_VERSION_NUMBER > 0x03000000f + rsa->evp = NULL; // Otherwise, I have a seg fault during clean rsa st + + X509 *x = PEM_read_bio_X509(rsa->bio, NULL, 0, NULL); + if (x == NULL){ + printf("Failed to read the X509 certificate\n"); + clean_rsa_st(rsa); + return FIPS_ERR_LOAD_X509; + } + + rsa->evp = X509_get_pubkey(x); + if (rsa->evp == NULL){ + printf("Failed to get public certificate\n"); + X509_free(x); + return FIPS_ERR_LOAD_RSA_KEY; + } + rsa->rsa = EVP_PKEY_get1_RSA(rsa->evp); + if (rsa->rsa == NULL){ + X509_free(x); + return FIPS_ERR_LOAD_RSA_KEY; + } + #endif + + /* + * TODO: Need to identify public-key cryptosystem: RSA or EC + */ + + // We have the RSA key, we can audit it + audit_rsa_keys(rsa, st_audit_fips, st_keyinfo, pkey); + + #if OPENSSL_VERSION_NUMBER > 0x03000000f + X509_free(x); + #endif + clean_rsa_st(rsa); + return 0; +} + +/* + * This function clean the RSA structure + */ +static void clean_rsa_st(struct rsa *rsa){ + if (DEBUG) + printf("\nCleaning RSA\n"); + + if (rsa == NULL) + return; + + if (rsa->bio != NULL) + BIO_free(rsa->bio); + + if (openssl_version() == 3){ + #if OPENSSL_VERSION_NUMBER > 0x03000000f + if (rsa->evp != NULL) + EVP_PKEY_free(rsa->evp); + #endif + } + + if (rsa->rsa != NULL) + RSA_free(rsa->rsa); + + free(rsa); + rsa = NULL; +} + +/* + * Return 1 if the version is upper than 1 and less than 3 + * Return 3 for the version v3 + */ +static int openssl_version(){ + unsigned long version = OPENSSL_VERSION_NUMBER; + + if (DEBUG) + printf("OpenSSL Version: %lx\n", version); + if (version <= 0x03000000f) + return 1; + if (version >= 0x03000000f) + return 3; +} +/* + * In case we have an error with OpenSSL librairy, we can print the error message + */ +static void print_error(){ + unsigned long err = ERR_get_error(); + char b[256]; + ERR_error_string(err, b); + printf("%s\n", b); +} + diff --git a/audit/fips.h b/audit/fips.h new file mode 100644 index 0000000..d5764a1 --- /dev/null +++ b/audit/fips.h @@ -0,0 +1,62 @@ +#ifndef H_FIPS +#define H_FIPS + +#include +#include +#include +#include +#include +#include "audit.h" + +#define TYPE_RSA 0x01 +#define TYPE_X509 0x02 + +#define RSA_FORMAT_PKCS1 0x1 +#define RSA_FORMAT_SPKI 0x2 + +#define BUF_SIZE_RESULT 256 + +#define ALGO_RSA 0x01 +#define ALGO_EC 0x02 + +struct audit_fips{ + struct st_audit audit_keysize; + struct st_audit audit_exponent; +}; + +struct rsa{ + RSA *rsa; + BIO *bio; +#if OPENSSL_VERSION_NUMBER > 0x03000000f + EVP_PKEY *evp; +#endif +}; + +struct keyinfo{ + int keysize; + unsigned long exponent; + int format; + char *key; + int algo; +}; + +int fips(const char *, struct audit_fips *, struct keyinfo *, const int, const int, const int); +/* RSA */ +static int fips_pubkey_rsa(struct audit_fips *, struct keyinfo *, const char *, const int); +static int fips_privkey_rsa(struct audit_fips *, struct keyinfo *, const char *, const int); +static int loadkeys_rsa_v1(struct rsa **, const char *, int *format); +static int loadkeys_rsa_v3(struct rsa **, const char *, int *format); +static int load_priv_rsa_keys_v1(struct rsa **, const char *); +static int load_priv_rsa_keys_v3(struct rsa **, const char *); +static void audit_rsa_keys(struct rsa *, struct audit_fips *, struct keyinfo *, const char *); + +/* X509 */ +static int fips_x509_v1(struct audit_fips *, struct keyinfo *, const char *, const int); +static int fips_x509_v3(struct audit_fips *, struct keyinfo *, const char *, const int); + +static int check_exponent(const BIGNUM *, char *, unsigned long *); +static void clean_rsa_st(struct rsa *); +static int openssl_version(); +static void print_error(); + +#endif diff --git a/certificate.c b/certificate.c new file mode 100644 index 0000000..78f71a9 --- /dev/null +++ b/certificate.c @@ -0,0 +1,187 @@ +#include "certificate.h" +#include "audit/audit.h" +#include "audit/file.h" + + +int certificate(char **argv, const int argc){ + int res; + int is_pubkey = 0; + int to_stdout = 0; + char buf_pkey[BUF_PATH_PKEY]; + struct stat st_stat; + int fd; + off_t len; + int type; /* Indicate the type of file: RSA, x509 */ + + /* struct st_audit for permission */ + struct st_audit st_audit_owner = {0}; + struct st_audit st_audit_group = {0}; + struct st_audit st_audit_other = {0}; + + /* struct audit_fips for the FIPS audit */ + struct audit_fips st_audit_fips = {0}; + + /* struct for keyinformation */ + struct keyinfo st_keyinfo = {0}; + + // TODO: need to review how to parse args + res = check_arguments_certificate(argv, argc, buf_pkey, &type, &is_pubkey, &to_stdout); + + if (res == -1) + return -1; + + if (type <= 0) + return -1; + + // Check if public key file exist + if (file_exist(buf_pkey) == -1){ + printf("The file %s doesn't exist\n", buf_pkey); + return -1; + } + + // Check if public key file exist + if (file_exist(buf_pkey) == -1){ + printf("The file %s doesn't exist\n", buf_pkey); + return -1; + } + + /* + * Print the filename, + * Owner of the file + * Size of the file + * And other information + */ + if ((fd = open(buf_pkey, O_RDONLY)) < 0){ + printf("Failed to open the file\n"); + } + fstat(fd, &st_stat); + + printf("File information\n"); + printf("\tFilename: %s\n", buf_pkey); + printf("\tFile size: %ld\n", st_stat.st_size); + printf("\tPermission: %d\n", convert_mode_t(st_stat.st_mode)); + + /* + * Check certificate's file + * - owner of the certificate + * - permission of the file + */ + printf("\nChecking file ownerships compliance...\n"); + + uid_t uid = st_stat.st_uid; + char username[64]; + struct st_audit audit_ownshp = ownership(uid, username, 64); + printf("%s\n", audit_ownshp.result); + + /* + * Checking permission file + * For a better security, only the owner can have the privilege to read/write the certificate + */ + printf("\nChecking file permissions compliance...\n"); + permission(st_stat.st_mode, &st_audit_owner, &st_audit_group, &st_audit_other); + printf("%s\n", st_audit_owner.result); + if (st_audit_group.audit == FALSE) + printf("%s\n", st_audit_group.result); + if (st_audit_other.audit == FALSE) + printf("%s\n", st_audit_other.result); + + /*************************/ + /* Check FIPS compliance */ + /*************************/ + printf("\nChecking FIPS compliance...\n"); + + /*if (type == TYPE_X509){ + printf("Cannot decrypt x509 certifcate, it is not implemented yet\n"); + return 0; + }*/ + res = fips(buf_pkey, &st_audit_fips, &st_keyinfo, type, is_pubkey, to_stdout); + if (res < 0){ + printf("Error during check FIPS compliance\n"); + return -1; + } + + /* Print information regarding the key */ + printf("Certificate information:\n"); + printf("\tKey size: %d bytes (%d)\n", st_keyinfo.keysize, (st_keyinfo.keysize * 8)); + printf("\tExponent: %lu\n", st_keyinfo.exponent); + if (st_keyinfo.algo == ALGO_RSA) + printf("\tAlgorithm: RSA\n"); + if (st_keyinfo.algo == ALGO_EC) + printf("\tAlgorithm: Elliptic Curve\n"); + + if (st_keyinfo.format == RSA_FORMAT_PKCS1) + printf("\tFormat RSA key: PKCS#1\n"); + if (st_keyinfo.format == RSA_FORMAT_SPKI) + printf("\tFormat RSA key: SPKI\n"); + + printf("\n"); + + /* Print the audit result */ + printf("Exponent result:\n"); + printf("\t%s\n", st_audit_fips.audit_exponent.result); + printf("Keysize result:\n"); + printf("\t%s\n", st_audit_fips.audit_keysize.result); + + printf("\n"); + + /* If we dump the key, we read it */ + if (to_stdout){ + int len = 0; + + st_keyinfo.key = (char *)malloc(st_stat.st_size + 1); + lseek(fd, 0, SEEK_SET); + len = read(fd, st_keyinfo.key, st_stat.st_size); + st_keyinfo.key[len] = '\0'; + + printf("Dump the key:\n%s\n", st_keyinfo.key); + + free(st_keyinfo.key); + } + + close(fd); +} +/* + * This function check arguments passed for executing the program. For the certificate module, the type argument is mandatory, which indicate the type of key (RSA or x509). + Also, the argument -privin or -pubin is mandatory. One is for the private key followed by the pathname and the second one is the public key. + */ +static int check_arguments_certificate(char **argv, const int argc, char *buf_pkey, int *type, int *is_pubkey, int *to_stdout){ + int res = -1; + /* we bypass the first action arguments */ + for (int i = 3; i < argc; i++){ + /*if(argv[i][0] == '-'){}*/ + size_t l = strlen(argv[i]); + if (strncmp(argv[i], "-type", l) == 0){ + if (strcmp(argv[i + 1], "rsa") == 0) + *type = TYPE_RSA; + else if (strcmp(argv[i + 1], "x509") == 0) + *type = TYPE_X509; + else + res = -1; + } + if (strncmp(argv[i], "-pubin", l) == 0){ + //printf("%s\n", argv[i + 1]); + strncpy(buf_pkey, argv[i + 1], BUF_PATH_PKEY); + res = 0; + *is_pubkey = 1; + } + if (strncmp(argv[i], "-privin", l) == 0){ + strncpy(buf_pkey, argv[i + 1], BUF_PATH_PKEY); + res = 0; + *is_pubkey = 0; + } + if (strncmp(argv[i], "-text", l) == 0) + *to_stdout = 1; + } + + return res; +} +/* + * This function check if the file exist + * If yes, return 0, otherwise return-1 + */ +static int file_exist(const char *file){ + if (access(file, F_OK) == 0) + return 0; + return -1; +} + diff --git a/certificate.h b/certificate.h new file mode 100644 index 0000000..132d01e --- /dev/null +++ b/certificate.h @@ -0,0 +1,23 @@ +#ifndef H_CERTIFICATE +#define H_CERTIFICATE + +#include "audit/fips.h" +#include +#include +#include +#include + +#define BUF_PATH_PKEY 256 + +struct args{ + char *pathname; + int is_pubkey; + int to_stdout; +}; + +int certificate(char **, const int); +static int check_arguments_certificate(char **, const int, char *, int *, int *, int *); +static int file_exist(const char *); +static void get_username(uid_t, char *); + +#endif diff --git a/common.h b/common.h new file mode 100644 index 0000000..3cdbf0a --- /dev/null +++ b/common.h @@ -0,0 +1,12 @@ +#ifndef H_COMMON +#define H_COMMON + +#define PROCNAME_SIZE 256 + +struct random{ + __u32 pid; + //__u32 len; + //char buf[128]; +}; + +#endif diff --git a/cryptodit b/cryptodit new file mode 100755 index 0000000000000000000000000000000000000000..08a5f995aa0b7d88ca68dc3d3c36544b065aa3ec GIT binary patch literal 38368 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 ABLDyZ literal 0 HcmV?d00001 diff --git a/entropy.c b/entropy.c new file mode 100644 index 0000000..17e421d --- /dev/null +++ b/entropy.c @@ -0,0 +1,88 @@ +#include "entropy.h" +#include "common.h" + + +int handle_event(void *ctx, void *data, size_t data_sz){ + struct random *s_random = (struct random*)data; + pid_t pid = s_random->pid; + char procname[PROCNAME_SIZE]; + char pathname[64]; + FILE *fd; + memset(procname, 0, PROCNAME_SIZE); + memset(pathname, 0, 64); + + // Get the proc name + snprintf(pathname, 64, "/proc/%d/stat", pid); + if ((fd = fopen(pathname, "r")) == NULL){ + printf("Failed to open the file\n"); + return -1; + } + fscanf(fd, "%*d %s", procname); + + printf("proc: %s; pid: %d\n", procname, s_random->pid); + + fclose(fd); + + return 0; +} +int entropy(char **argv, int argc){ + const char *fileObj = "entropy_ebpf.o"; + struct bpf_object *obj; + struct bpf_program *program; + struct ring_buffer *rb; + int err; + int fd_map_data; + int running = 1; + + // Load eBPF + obj = bpf_object__open_file(fileObj, NULL); + if (!obj){ + printf("Failed to open %s\n", fileObj); + return -1; + } + + err = bpf_object__load(obj); + + if (err){ + printf("Failed to load object\n"); + return -1; + } + + //program = bpf_object__find_program_by_name(obj, "get_random"); + program = bpf_object__find_program_by_name(obj, "get_random_user"); + if (!program){ + printf("Failed to find the program\n"); + return -1; + } + + fd_map_data = bpf_object__find_map_fd_by_name(obj, "data"); + if (!fd_map_data){ + printf("Failed to find the FD of the map\n"); + return -1; + } + + bpf_program__attach(program); + + /* Start the ringbuffer */ + rb = ring_buffer__new(fd_map_data, handle_event, NULL, NULL); + if (!rb){ + printf("Failed to create the ringbuf\n"); + bpf_object__close(obj); + return -1; + } + + while(running){ + err = ring_buffer__poll(rb, 100 /* timeout, ms */); + if (err == -EINTR){ + printf("Failed to get the ringbuf\n"); + running = 0; + break; + } + } + + ring_buffer__free(rb); + bpf_object__close(obj); + + // Generate RSA keys and check the entropy available + +} diff --git a/entropy.h b/entropy.h new file mode 100644 index 0000000..3507aaf --- /dev/null +++ b/entropy.h @@ -0,0 +1,17 @@ +#ifndef H_ENTROPY +#define H_ENTROPY + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int entropy(char **, int); + +#endif diff --git a/entropy_ebpf.c b/entropy_ebpf.c new file mode 100644 index 0000000..87ecda9 --- /dev/null +++ b/entropy_ebpf.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +//#include +#include "common.h" + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024 /* 256kb */); +} data SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 4194304); /* /proc/sys/kernel/pid_max */ + __type(key, __u32); + __type(value, __u32); +} m_pid SEC(".maps"); + +// https://lwn.net/Articles/605828/ + +// https://lwn.net/Articles/625077/ +// cat /proc/kallsyms | grep get_random_bytes +SEC("kprobe/get_random_bytes_user") +int get_random_user(){ + struct random *s_random = 0; + __u32 pid = bpf_get_current_pid_tgid() >> 32; + + __u32 *n_pid = bpf_map_lookup_elem(&m_pid, &pid); + if (!n_pid) + return 0; + // bpf_printk("pid: %d", pid); + + /* + * To avoid to "burst" the user-space + * We add the pid in a map. If doesn't exist, we send data to the ring buffer + */ + if (*n_pid == 0){ + // bpf_printk("value: %d %d", pid, *n_pid); + /* TODO: get the procname */ + /*struct task_struct *task = (struct task_struct *)bpf_get_current_task(); + if (!task) + return 0; + struct mm_struct *mm = task->mm;*/ + + if (bpf_map_update_elem(&m_pid, &pid, &pid, BPF_ANY) < 0){ + bpf_printk("Failed to update map"); + return 0; + } + + s_random = bpf_ringbuf_reserve(&data, sizeof(struct random *), 0); + if (!s_random) + return 0; + + s_random->pid = pid; + bpf_ringbuf_submit(s_random, 0); + } + + return 0; +} +char LICENSE[] SEC("license") = "Dual BSD/GPL"; diff --git a/entropy_ebpf.o b/entropy_ebpf.o new file mode 100644 index 0000000000000000000000000000000000000000..658f4038aa55036344863975e04f524ab2e35574 GIT binary patch literal 8024 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 +#include +#include "argparse.h" +#include "certificate.h" +#include "speed.h" +#include "entropy.h" + +#define BUF_MODULE_SIZE 64 + +static void usage(const char *); +int main(int argc, char *argv[]){ + int res = -1; + char modules[BUF_MODULE_SIZE]; + memset(modules, 0, BUF_MODULE_SIZE); + + res = check_arguments(argv, argc, modules, BUF_MODULE_SIZE); + + if (res == -1){ + usage(argv[0]); + return -1; + } + + printf("Module: %s\n", modules); + + + if (strncmp(modules, "speed", BUF_MODULE_SIZE) == 0){ + res = speed(argv, argc); + if (res == -1){ + usage(argv[0]); + return -1; + } + } + if (strncmp(modules, "certificate", BUF_MODULE_SIZE) == 0){ + res = certificate(argv, argc); + if (res == -1){ + usage(argv[0]); + return -1; + } + } + if (strncmp(modules, "entropy", BUF_MODULE_SIZE) == 0){ + res = entropy(argv, argc); + if (res == -1){ + usage(argv[0]); + return -1; + } + } + return 0; +} + +static void usage(const char *script){ + printf("Usage %s -m \n", script); + printf("Modules:\n"); + printf("\tcertificate: Check if the certificate is compliant with FIP 140-3 and check the certificate security file\n"); + printf("\tspeed: Check the time for creating the certificate\n"); + printf("\tentropy: Check the entropy in the kernel\n\n"); + printf("Certificate Modules:\n"); + printf("\t-type \n"); + printf("\t-pubin \n"); + printf("\t-privin \n"); + printf("\t-text: print in text the certificate\n\n"); + printf("Speed Modules:\n"); + printf("\t-type \n"); +} diff --git a/speed.c b/speed.c new file mode 100644 index 0000000..15c954a --- /dev/null +++ b/speed.c @@ -0,0 +1,268 @@ +#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; +} diff --git a/speed.h b/speed.h new file mode 100644 index 0000000..ecff1a4 --- /dev/null +++ b/speed.h @@ -0,0 +1,24 @@ +#ifndef H_SPEED +#define H_SPEED + +#define TYPE_SPEED_ALL 0x1 +#define TYPE_SPEED_RSA 0x2 +#define TYPE_SPEED_ELLIPTIC 0x3 + +#include +#include +#include +#include +#include +#include +#include + +int speed(char **, int); +static int check_arguments_speed(char **, const int, int *, size_t *, int *); +static int speed_generate_rsa_keys(size_t, const int); +static void print_key(BIO *); +static int speed_generate_elliptic_keys(size_t, const int); +static int ec_get_pub_key(const EC_KEY *, const EC_POINT *); +static unsigned long getms(); + +#endif diff --git a/utils.c b/utils.c new file mode 100644 index 0000000..e4ccce9 --- /dev/null +++ b/utils.c @@ -0,0 +1,5 @@ +#include "utils.h" + +int char2dec(const char c){ + return c - '0'; +} diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..108ea02 --- /dev/null +++ b/utils.h @@ -0,0 +1,7 @@ +#ifndef H_UTILS +#define H_UTILS + +int char2dec(const char); +unsigned long char2ulong(const char *); + +#endif