First commit

This commit is contained in:
geoffrey 2026-01-31 16:45:53 +01:00
commit 578ef21219
30 changed files with 1589 additions and 0 deletions

1
.gitignore vendored Normal file

@ -0,0 +1 @@
**.swp

78
README.md Normal file

@ -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
```

22
argparse.c Normal file

@ -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;
}

9
argparse.h Normal file

@ -0,0 +1,9 @@
#ifndef H_ARGPARSE
#define H_ARGPARSE
#include <stdio.h>
#include <string.h>
int check_arguments(char **, const int, char *, const size_t);
#endif

13
audit/audit.h Normal file

@ -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

114
audit/file.c Normal file

@ -0,0 +1,114 @@
#include <stdio.h>
#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);
}

13
audit/file.h Normal file

@ -0,0 +1,13 @@
#ifndef H_FILE
#define H_FILE
#include <pwd.h>
#include <string.h>
#include <sys/stat.h>
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

455
audit/fips.c Normal file

@ -0,0 +1,455 @@
#include <stdio.h>
#include <string.h>
#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);
}

62
audit/fips.h Normal file

@ -0,0 +1,62 @@
#ifndef H_FIPS
#define H_FIPS
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <math.h>
#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

187
certificate.c Normal file

@ -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;
}

23
certificate.h Normal file

@ -0,0 +1,23 @@
#ifndef H_CERTIFICATE
#define H_CERTIFICATE
#include "audit/fips.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#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

12
common.h Normal file

@ -0,0 +1,12 @@
#ifndef H_COMMON
#define H_COMMON
#define PROCNAME_SIZE 256
struct random{
__u32 pid;
//__u32 len;
//char buf[128];
};
#endif

BIN
cryptodit Executable file

Binary file not shown.

88
entropy.c Normal file

@ -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
}

17
entropy.h Normal file

@ -0,0 +1,17 @@
#ifndef H_ENTROPY
#define H_ENTROPY
#include <stdio.h>
#include <stdlib.h>
#include <linux/bpf.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <linux/perf_event.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
int entropy(char **, int);
#endif

62
entropy_ebpf.c Normal file

@ -0,0 +1,62 @@
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <linux/uio.h>
//#include <linux/sched.h>
#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";

BIN
entropy_ebpf.o Normal file

Binary file not shown.

16
error.h Normal file

@ -0,0 +1,16 @@
#ifndef H_ERROR
#define H_ERROR
/* Define all Common errors */
#define COMMON_ERR_MALLOC 0x100
/* Define all FIPS errors */
#define FIPS_ERR_LOAD_KEY 0x200
#define FIPS_ERR_NEW_BIO 0x201
#define FIPS_ERR_READ_BIO 0x202
#define FIPS_ERR_LOAD_RSA_KEY 0x203
#define FIPS_ERR_LOAD_RSA_PRIV_KEY 0x204
#define FIPS_ERR_LOAD_X509 0x205
#endif

11
examples/cert.pem Normal file

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhzCCATECFD29f5mS/P9BLaM6ahD5OYfFZj9qMA0GCSqGSIb3DQEBCwUAMEUx
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjYwMTI4MDc1NTA1WhcNMjYwMjI3MDc1
NTA1WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAw
SAJBAK7yGMN7B8KGqJ2WJCrUTA8RmN37wWkofPt2gcz/emtIOQ6TPOlRQQiVlYSu
WYojc+xqLfUDYwAuGbTorfsz8KsCAwEAATANBgkqhkiG9w0BAQsFAANBAFrMiM8U
OUXEJVQXSy1sotuDu8vysnjfFuxwm1z86pY3qWm45bhHFiwePdjhAckrlOL+fv0l
/qD9p78RsKQfMdU=
-----END CERTIFICATE-----

8
examples/csr.pem Normal file

@ -0,0 +1,8 @@
-----BEGIN CERTIFICATE REQUEST-----
MIH/MIGqAgEAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwXDANBgkqhkiG9w0BAQEF
AANLADBIAkEArvIYw3sHwoaonZYkKtRMDxGY3fvBaSh8+3aBzP96a0g5DpM86VFB
CJWVhK5ZiiNz7Got9QNjAC4ZtOit+zPwqwIDAQABoAAwDQYJKoZIhvcNAQELBQAD
QQBEMrIke9mgePMjmOAhdRxQVJbL+s4pzOMxY2kf+EzkICIXW2yGg4/3EO4N+7tC
NBfzHKrFqxkdSEWLh4OOOZ+e
-----END CERTIFICATE REQUEST-----

9
examples/foo.pem Normal file

@ -0,0 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBPQIBAAJBAKxX41iNOT0dknOVXnBJ/HJp7Ka4Mu0VKePBIBn2XHFO4f3ZDHXJ
Zt5xb+NJ8nUR640Gjcoc7lOOcw0QmEj1PbMCAwEAAQJBAITEJBDYooqxWFwQarNI
W+DsNvHsntbDYgThh1BY2Lg0EAM9KcJhBDmBF1X12yhMiFlrNbSxV0ZR7/tpMij2
ycECIQDTvtc9rGQJGhD6GbAlFWP1ukWgwlB1NcC4xMZM+nalIQIhANBc4yVRq3gx
RtgcijG9m++d+IT7ZATHK8+0NlQJkzRTAiEAg5vUcLLbooSfFLQutX3sGWljqZ3d
IFz+olk739C1OcECIQCFVYt9jB+gEFh3XvwIDH/G/F3WK1C7xgCBL588c8whRQIh
AKPuzXozkJrD0K2LHU0GU9bRzl6j6m22+gBG8rDsWUwP
-----END RSA PRIVATE KEY-----

9
examples/private.key Normal file

@ -0,0 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAK7yGMN7B8KGqJ2WJCrUTA8RmN37wWkofPt2gcz/emtIOQ6TPOlR
QQiVlYSuWYojc+xqLfUDYwAuGbTorfsz8KsCAwEAAQJBAKD6suDFyAkuwd9oNdWX
TnmbNrAlJf7uu7rkfGI3P92QrOY7gc8ZsUluv/63cpekRclsvSe76CgcQmMpo/Oa
TVECIQDcxc7GV91Y90g7ACfQFzO4Lz9GgmObYExBSfurRZ8g8wIhAMrcVVxNHhG3
Mh6ZvIH0vTPHT6Wo3QUWzns+pSukxh9pAiBgl+NqgJMGE9t0hRLmRuCIG5Pxw6bV
GoMCpd4JB8Mh5QIgAkAVdlOorLuig7Ji4/IqEyP33zeTVBYfrkBQpr5KMFkCIQCd
WyZemsI/9PNb1OUUlpYMHFs+GBOGJQLbxRcFmNdjHg==
-----END RSA PRIVATE KEY-----

4
examples/public.key Normal file

@ -0,0 +1,4 @@
-----BEGIN RSA PUBLIC KEY-----
MEgCQQCu8hjDewfChqidliQq1EwPEZjd+8FpKHz7doHM/3prSDkOkzzpUUEIlZWE
rlmKI3Psai31A2MALhm06K37M/CrAgMBAAE=
-----END RSA PUBLIC KEY-----

4
examples/public_ec.pem Normal file

@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEelQ5fSfII96Q/3fP+i97M8Cm94at
GV2W16RU4Ubto25b+AEjG7Lh6cSARLogvVe7EpxQ6wgxjomstHjREK5ZIA==
-----END PUBLIC KEY-----

5
exec.sh Executable file

@ -0,0 +1,5 @@
#!/usr/bin/bash
clang-11 -g -O2 -target bpf -c entropy_ebpf.c -o entropy_ebpf.o
gcc utils.c argparse.c audit/file.c certificate.c speed.c entropy.c audit/fips.c main.c -lbpf -lcrypto -o cryptodit

63
main.c Normal file

@ -0,0 +1,63 @@
#include <stdio.h>
#include <string.h>
#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 <modules>\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 <rsa,x509>\n");
printf("\t-pubin <public certificate>\n");
printf("\t-privin <private certificate>\n");
printf("\t-text: print in text the certificate\n\n");
printf("Speed Modules:\n");
printf("\t-type <rsa, elliptic, all>\n");
}

268
speed.c Normal file

@ -0,0 +1,268 @@
#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;
}

24
speed.h Normal file

@ -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 <stdio.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ec.h>
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

5
utils.c Normal file

@ -0,0 +1,5 @@
#include "utils.h"
int char2dec(const char c){
return c - '0';
}

7
utils.h Normal file

@ -0,0 +1,7 @@
#ifndef H_UTILS
#define H_UTILS
int char2dec(const char);
unsigned long char2ulong(const char *);
#endif