First commit
This commit is contained in:
commit
578ef21219
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
**.swp
|
||||
78
README.md
Normal file
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
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
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
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
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
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
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
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
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
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
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
BIN
cryptodit
Executable file
Binary file not shown.
88
entropy.c
Normal file
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
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
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
BIN
entropy_ebpf.o
Normal file
Binary file not shown.
16
error.h
Normal file
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
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
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
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
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
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
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
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
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
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
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
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
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
|
||||
Loading…
Reference in New Issue
Block a user