Audit ECC key
This commit is contained in:
parent
3488933d1d
commit
70e07b58a2
515
audit/fips.c
515
audit/fips.c
@ -7,7 +7,7 @@
|
||||
/*
|
||||
* SSL Format
|
||||
* RSA PUBLIC KEY -> PKCS#1 format
|
||||
* PUBLIC KEY -> PEM Format
|
||||
* PUBLIC KEY -> PEM Format (SPKI)
|
||||
*/
|
||||
|
||||
static int DEBUG = 0;
|
||||
@ -16,47 +16,54 @@ int fips(const char *pkey, struct audit_fips *st_audit_fips, struct keyinfo *st_
|
||||
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);
|
||||
else
|
||||
res = fips_privkey_rsa(st_audit_fips, st_keyinfo, pkey);
|
||||
}
|
||||
else if (type == TYPE_X509){
|
||||
if (openssl_version() == 1)
|
||||
res = fips_x509_v1(st_audit_fips, st_keyinfo, pkey);
|
||||
else
|
||||
res = fips_x509_v3(st_audit_fips, st_keyinfo, pkey);
|
||||
else if (type == TYPE_ELLIPTIC){
|
||||
if (is_pubkey){
|
||||
EC_KEY *ec = fips_load_pubkey_ecc(pkey);
|
||||
if (!ec)
|
||||
return FIPS_ERR_LOAD_ECC_PUBKEY;
|
||||
|
||||
res = fips_pubkey_ecc(ec, st_audit_fips, st_keyinfo, pkey);
|
||||
}
|
||||
}
|
||||
else if (type == TYPE_X509)
|
||||
res = fips_x509(st_audit_fips, st_keyinfo, pkey);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
/* RSA part */
|
||||
/********************************************************/
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
struct rsa *rsa;
|
||||
size_t keysize;
|
||||
int res;
|
||||
|
||||
/*
|
||||
* Now, we check if the public certificate is compliant with FIPS
|
||||
* Now, we check if the public key 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){
|
||||
RSA *rsa = NULL;
|
||||
res = loadkeys_rsa(&rsa, pkey, &st_keyinfo->st_rsa.format);
|
||||
|
||||
if (res > 0 || !rsa){
|
||||
printf("Failed to read the public key\n");
|
||||
clean_rsa_st(rsa);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* We have loaded our RSA key, we can audit it */
|
||||
audit_rsa_keys(rsa, st_audit_fips, st_keyinfo, pkey);
|
||||
|
||||
// Clean
|
||||
clean_rsa_st(rsa);
|
||||
// Cleaning
|
||||
RSA_free(rsa);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
@ -64,75 +71,29 @@ static int fips_pubkey_rsa(struct audit_fips *st_audit_fips, struct keyinfo *st_
|
||||
*/
|
||||
static int fips_privkey_rsa(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey) {
|
||||
int res;
|
||||
struct rsa *rsa = NULL;
|
||||
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);
|
||||
res = load_priv_rsa_keys(&rsa, pkey);
|
||||
|
||||
if (res > 0){
|
||||
if (res > 0 || !rsa){
|
||||
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);
|
||||
RSA_free(rsa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If OpenSSL v3, we need tu use new OpenSSL functions for reading keys
|
||||
* This function load the RSA key and store to the RSA * object
|
||||
* Detect and specify the correct RSA format public key
|
||||
*/
|
||||
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){
|
||||
static int loadkeys_rsa(RSA **rsa, const char *pkey, int *format){
|
||||
BIO *bio = BIO_new(BIO_s_file());
|
||||
if (BIO_read_filename(bio, pkey) == 0){
|
||||
printf("Failed to read BIO\n");
|
||||
return FIPS_ERR_READ_BIO;
|
||||
}
|
||||
@ -141,29 +102,53 @@ static int loadkeys_rsa_v1(struct rsa **rsa, const char *pkey, int *format){
|
||||
* 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); */
|
||||
/*rsa = PEM_read_RSAPublicKey(f, NULL, NULL, NULL); */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER > 0x03000000f
|
||||
EVP_PKEY *evp = PEM_read_bio_PUBKEY_ex(bio, NULL, NULL, NULL, NULL, NULL);
|
||||
if (!evp){
|
||||
BIO_free(bio);
|
||||
return FIPS_ERR_LOAD_KEY;
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
|
||||
//printf("Keysize: %d\n", EVP_PKEY_bits(evp));
|
||||
/* EVP_PKEY_get1_RSA is deprecated, need to find another way to get the RSA key */
|
||||
*rsa = EVP_PKEY_get1_RSA(evp);
|
||||
if (!(*rsa)){
|
||||
EVP_PKEY_free(evp);
|
||||
return FIPS_ERR_LOAD_RSA_KEY;
|
||||
}
|
||||
EVP_PKEY_free(evp);
|
||||
*format = 0;
|
||||
|
||||
#else
|
||||
// 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();
|
||||
/* In case it's OpenSSL v1, we get the RSA * object from BIO */
|
||||
*rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);
|
||||
|
||||
// If we cannot read it, we try with the PKCS1 format
|
||||
if (!(*rsa)){
|
||||
// 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);
|
||||
BIO_seek(bio, 0);
|
||||
|
||||
(*rsa)->rsa = PEM_read_bio_RSA_PUBKEY((*rsa)->bio, NULL, NULL,NULL);
|
||||
*(rsa) = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL,NULL);
|
||||
|
||||
if ((*rsa)->rsa == NULL){
|
||||
if (!(*rsa)){
|
||||
if (DEBUG)
|
||||
printf("Cannot read the SPKI format of the public key\n");
|
||||
BIO_free(bio);
|
||||
return FIPS_ERR_LOAD_KEY;
|
||||
}
|
||||
|
||||
@ -172,75 +157,54 @@ static int loadkeys_rsa_v1(struct rsa **rsa, const char *pkey, int *format){
|
||||
else
|
||||
*format = RSA_FORMAT_PKCS1;
|
||||
|
||||
BIO_free(bio);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function load RSA Private key for OpenSSL v1
|
||||
* This function load RSA Private key
|
||||
*/
|
||||
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){
|
||||
static int load_priv_rsa_keys(RSA **rsa, const char *pkey){
|
||||
BIO *bio = BIO_new(BIO_s_file());
|
||||
if (!bio){
|
||||
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){
|
||||
if(BIO_read_filename(bio, pkey) == 0){
|
||||
printf("Failed to read BIO\n");
|
||||
BIO_free(bio);
|
||||
return FIPS_ERR_READ_BIO;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER > 0x03000000f
|
||||
(*rsa)->evp = PEM_read_bio_PrivateKey_ex((*rsa)->bio, NULL, NULL, NULL, NULL, NULL);
|
||||
EVP_PKEY *evp = PEM_read_bio_PrivateKey_ex(bio, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if ((*rsa)->evp == NULL){
|
||||
if (!evp){
|
||||
if (DEBUG)
|
||||
printf("Failed to read BIO PrivateKey\n");
|
||||
BIO_free(bio);
|
||||
return FIPS_ERR_READ_BIO;
|
||||
}
|
||||
(*rsa)->rsa = EVP_PKEY_get1_RSA((*rsa)->evp);
|
||||
if ((*rsa)->rsa == NULL)
|
||||
BIO_free(bio);
|
||||
|
||||
*rsa = EVP_PKEY_get1_RSA(evp);
|
||||
if (!*rsa){
|
||||
EVP_PKEY_free(evp);
|
||||
return FIPS_ERR_LOAD_RSA_KEY;
|
||||
}
|
||||
EVP_PKEY_free(evp);
|
||||
#else /* For OpenSSL v1 */
|
||||
*rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
|
||||
if (!*rsa){
|
||||
if (DEBUG)
|
||||
printf("Failed to read BIO RSAPrivateKey\n");
|
||||
BIO_free(bio);
|
||||
return FIPS_ERR_LOAD_RSA_PRIV_KEY;
|
||||
}
|
||||
BIO_free(bio);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@ -250,32 +214,32 @@ static int load_priv_rsa_keys_v3(struct rsa **rsa, const char *pkey){
|
||||
* 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){
|
||||
static void audit_rsa_keys(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->st_rsa.keysize = RSA_size(rsa);
|
||||
|
||||
st_keyinfo->algo = ALGO_RSA;
|
||||
|
||||
// The return value is a const, shouldn't be freed
|
||||
const BIGNUM *e = RSA_get0_e(rsa->rsa);
|
||||
const BIGNUM *e = RSA_get0_e(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);
|
||||
res = check_exponent(e, st_audit_fips->audit_rsa.audit_exponent.result, &st_keyinfo->st_rsa.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;
|
||||
if (st_keyinfo->st_rsa.keysize * 8 < 2048){
|
||||
sprintf(st_audit_fips->audit_rsa.audit_keysize.result, "The key size is lower than 2048. The key should be at least 2048 bits.");
|
||||
st_audit_fips->audit_rsa.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;
|
||||
sprintf(st_audit_fips->audit_rsa.audit_keysize.result, "The key size is upper or equal than 2048. The audit is passed with success.");
|
||||
st_audit_fips->audit_rsa.audit_keysize.audit = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,12 +261,9 @@ static int check_exponent(const BIGNUM *e, char *buf, unsigned long *exponent){
|
||||
|
||||
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
|
||||
@ -310,7 +271,6 @@ static int check_exponent(const BIGNUM *e, char *buf, unsigned long *exponent){
|
||||
*/
|
||||
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);
|
||||
@ -338,136 +298,195 @@ static int check_exponent(const BIGNUM *e, char *buf, unsigned long *exponent){
|
||||
OPENSSL_free(exp);
|
||||
return 0;
|
||||
}
|
||||
/********************************************************/
|
||||
/* ECC part */
|
||||
/********************************************************/
|
||||
static int fips_pubkey_ecc(EC_KEY *ec, struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey){
|
||||
st_keyinfo->algo = ALGO_EC;
|
||||
memset(&st_keyinfo->s_ecc, 0, sizeof(struct ecc*));
|
||||
|
||||
st_keyinfo->s_ecc.ec = ec;
|
||||
|
||||
int res = get_domain_parameters(&st_keyinfo->s_ecc);
|
||||
|
||||
if (res != 0)
|
||||
return res;
|
||||
|
||||
audit_ecc(st_audit_fips, st_keyinfo->s_ecc.nid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function load X509 certificate for OpenSSL v1
|
||||
* This function audit the ECC keys.
|
||||
* According to the RCC 7748 and NIST recommendation,
|
||||
* curve schemes: P-521, Curve25519 or Curve448 should be used
|
||||
* The key length recommended is at least 256 bit.
|
||||
*/
|
||||
static int fips_x509_v1(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey){
|
||||
struct rsa *rsa = (struct rsa*)malloc(sizeof(struct rsa*));
|
||||
|
||||
if (rsa == NULL){
|
||||
if (DEBUG)
|
||||
printf("Cannot malloc the structure\n");
|
||||
return COMMON_ERR_MALLOC;
|
||||
static void audit_ecc(struct audit_fips *st_audit, const int nid){
|
||||
/*
|
||||
* Recommended curve name (See file /usr/include/openssl/obj_mac):
|
||||
* NID 716 = secp521r1
|
||||
* NID 1034 = X25519 (Curve25519)
|
||||
* NID 1035 = X448 (Curve448)
|
||||
*/
|
||||
if (nid != 716 && nid != 1034 && nid != 1035){
|
||||
sprintf(st_audit->audit_ecc.audit_curve.result, "The curve scheme should be P-521, Curve25519 or Curve448.");
|
||||
st_audit->audit_ecc.audit_curve.audit = FALSE;
|
||||
}
|
||||
memset(rsa, 0, sizeof(struct rsa*));
|
||||
else{
|
||||
sprintf(st_audit->audit_ecc.audit_curve.result, "The curve scheme is enough strong and respect NIST recommendation.");
|
||||
st_audit->audit_ecc.audit_curve.audit = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
rsa->bio = BIO_new(BIO_s_file());
|
||||
if (BIO_read_filename(rsa->bio, pkey) == 0){
|
||||
/*
|
||||
* This function load the public ECC key and return the key store in the variable EVP_PKEY
|
||||
*/
|
||||
static EC_KEY *fips_load_pubkey_ecc(const char *pkey){
|
||||
BIO *bio = BIO_new(BIO_s_file());
|
||||
if (BIO_read_filename(bio, pkey) == 0){
|
||||
printf("Failed to read BIO\n");
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY *ec = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL);
|
||||
|
||||
if (!ec){
|
||||
if (DEBUG)
|
||||
printf("Cannot read the ECC Public key\n");
|
||||
BIO_free(bio);
|
||||
return NULL;
|
||||
}
|
||||
/* We don't use it anymore, we freeing it */
|
||||
BIO_free(bio);
|
||||
return ec;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This function get domain parameters from the ECC key
|
||||
*/
|
||||
static int get_domain_parameters(struct ecc *st_ecc){
|
||||
EC_GROUP *group = EC_KEY_get0_group(st_ecc->ec);
|
||||
if(!group){
|
||||
if (DEBUG)
|
||||
printf("Failed to load ECC Group\n");
|
||||
EC_KEY_free(st_ecc->ec);
|
||||
return FIPS_ERR_GET_ECC_GROUP;
|
||||
}
|
||||
|
||||
// Get cofactor
|
||||
BIGNUM *b_cofactor = EC_GROUP_get0_cofactor(group);
|
||||
if(!b_cofactor){
|
||||
printf("Cannot get cofactor\n");
|
||||
return FIPS_ERR_GET_ECC_DOMAPARAM;
|
||||
}
|
||||
st_ecc->cofactor = BN_bn2dec(b_cofactor);
|
||||
//BN_free(b_cofactor);
|
||||
|
||||
// Get field
|
||||
#if OPENSSL_VERSION_NUMBER > 0x03000000f
|
||||
|
||||
#endif
|
||||
|
||||
// Get order bit
|
||||
st_ecc->order_bits = EC_GROUP_order_bits(group);
|
||||
|
||||
// Get order
|
||||
BIGNUM *b_order = EC_GROUP_get0_order(group);
|
||||
if(!b_order){
|
||||
printf("Cannot get order\n");
|
||||
return FIPS_ERR_GET_ECC_DOMAPARAM;
|
||||
}
|
||||
st_ecc->order = BN_bn2hex(b_order);
|
||||
//OPENSSL_free(order);
|
||||
//BN_free(b_order);
|
||||
|
||||
// Get curve name
|
||||
st_ecc->nid = EC_GROUP_get_curve_name(group);
|
||||
st_ecc->curve = OBJ_nid2sn(st_ecc->nid);
|
||||
//OPENSSL_free(name); /* If I free, the program crash, because it's a const ?? */
|
||||
|
||||
// Get generator
|
||||
EC_POINT *g = EC_GROUP_get0_generator(group);
|
||||
if (!g){
|
||||
if (DEBUG)
|
||||
printf("Failed to get ECC generator\n");
|
||||
return FIPS_ERR_GET_ECC_GENERATOR;
|
||||
}
|
||||
|
||||
st_ecc->g = EC_POINT_point2hex(group, g, POINT_CONVERSION_UNCOMPRESSED, NULL);
|
||||
/*
|
||||
* It's cannot mandatory to clean EC_GROUP and EC_POINT and other objects
|
||||
* We freeing them in certificate.c file.
|
||||
* Also, for cleaning EC_GROUP and EC_POINT, just freeing EC_KEY is enough
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
/* X.509 part */
|
||||
/********************************************************/
|
||||
|
||||
/*
|
||||
* This function load X509 certificate
|
||||
*/
|
||||
static int fips_x509(struct audit_fips *st_audit_fips, struct keyinfo *st_keyinfo, const char *pkey){
|
||||
BIO *bio = BIO_new(BIO_s_file());
|
||||
if (!bio){
|
||||
printf("Failed to create new BIO\n");
|
||||
return FIPS_ERR_NEW_BIO;
|
||||
}
|
||||
if (BIO_read_filename(bio, pkey) == 0){
|
||||
printf("Failed to read BIO\n");
|
||||
return FIPS_ERR_READ_BIO;
|
||||
}
|
||||
|
||||
X509 *x = PEM_read_bio_X509(rsa->bio, NULL, 0, NULL);
|
||||
if (x == NULL){
|
||||
X509 *x = PEM_read_bio_X509(bio, NULL, 0, NULL);
|
||||
if (!x){
|
||||
printf("Failed to read the X509 certificate\n");
|
||||
clean_rsa_st(rsa);
|
||||
BIO_free(bio);
|
||||
return FIPS_ERR_LOAD_X509;
|
||||
}
|
||||
BIO_free(bio); /* We don't need it anymore, we freeing it */
|
||||
|
||||
EVP_PKEY *evp = X509_get_pubkey(x);
|
||||
if (evp == NULL){
|
||||
if (!evp){
|
||||
printf("Failed to get public certificate\n");
|
||||
X509_free(x);
|
||||
return FIPS_ERR_LOAD_RSA_KEY;
|
||||
}
|
||||
rsa->rsa = EVP_PKEY_get1_RSA(evp);
|
||||
if (rsa->rsa == NULL){
|
||||
X509_free(x);
|
||||
EVP_PKEY_free(evp);
|
||||
return FIPS_ERR_LOAD_RSA_KEY;
|
||||
}
|
||||
|
||||
// We have the RSA key, we can audit it
|
||||
audit_rsa_keys(rsa, st_audit_fips, st_keyinfo, pkey);
|
||||
/* Get certificate info, such as issuer, validity, etc. */
|
||||
|
||||
X509_free(x);
|
||||
|
||||
/* Key type identification */
|
||||
int type = EVP_PKEY_base_id(evp);
|
||||
|
||||
switch (type) {
|
||||
case EVP_PKEY_RSA: ;
|
||||
RSA *rsa = EVP_PKEY_get1_RSA(evp);
|
||||
if (!rsa)
|
||||
return FIPS_ERR_LOAD_RSA_KEY;
|
||||
// We have the RSA key, we can audit it
|
||||
audit_rsa_keys(rsa, st_audit_fips, st_keyinfo, pkey);
|
||||
RSA_free(rsa);
|
||||
break;
|
||||
case EVP_PKEY_EC: ;
|
||||
/* We free EC_KEY in certificate.c file */
|
||||
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(evp);
|
||||
if (!ec)
|
||||
return FIPS_ERR_LOAD_ECC_PUBKEY;
|
||||
int res = fips_pubkey_ecc(ec, st_audit_fips, st_keyinfo, pkey);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
EVP_PKEY_free(evp);
|
||||
clean_rsa_st(rsa);
|
||||
|
||||
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){
|
||||
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
|
||||
|
||||
71
audit/fips.h
71
audit/fips.h
@ -8,8 +8,9 @@
|
||||
#include <math.h>
|
||||
#include "audit.h"
|
||||
|
||||
#define TYPE_RSA 0x01
|
||||
#define TYPE_X509 0x02
|
||||
#define TYPE_RSA 0x01
|
||||
#define TYPE_ELLIPTIC 0x02
|
||||
#define TYPE_X509 0x03
|
||||
|
||||
#define RSA_FORMAT_PKCS1 0x1
|
||||
#define RSA_FORMAT_SPKI 0x2
|
||||
@ -19,43 +20,71 @@
|
||||
#define ALGO_RSA 0x01
|
||||
#define ALGO_EC 0x02
|
||||
|
||||
struct audit_fips{
|
||||
struct audit_fips_ecc{
|
||||
struct st_audit audit_curve;
|
||||
};
|
||||
|
||||
struct audit_fips_rsa{
|
||||
struct st_audit audit_keysize;
|
||||
struct st_audit audit_exponent;
|
||||
};
|
||||
|
||||
struct audit_fips{
|
||||
struct audit_fips_rsa audit_rsa;
|
||||
struct audit_fips_ecc audit_ecc;
|
||||
};
|
||||
|
||||
struct rsa{
|
||||
RSA *rsa;
|
||||
BIO *bio;
|
||||
#if OPENSSL_VERSION_NUMBER > 0x03000000f
|
||||
int keysize;
|
||||
unsigned long exponent;
|
||||
int format; /* Format of the RSA KEY: PKCS1 or SPKI */
|
||||
char *key;
|
||||
int algo;
|
||||
};
|
||||
|
||||
struct ecc{
|
||||
//char *prime;
|
||||
EC_KEY *ec;
|
||||
char *g;
|
||||
char *order;
|
||||
int order_bits;
|
||||
const char *curve;
|
||||
int nid;
|
||||
char *cofactor;
|
||||
};
|
||||
|
||||
struct x509{
|
||||
EVP_PKEY *evp;
|
||||
#endif
|
||||
X509_NAME *issuer;
|
||||
X509_NAME *subject;
|
||||
};
|
||||
|
||||
struct keyinfo{
|
||||
int keysize;
|
||||
unsigned long exponent;
|
||||
int format;
|
||||
char *key;
|
||||
int algo;
|
||||
int algo; /* RSA, ECC */
|
||||
|
||||
struct x509 st_x509;
|
||||
struct ecc s_ecc;
|
||||
struct rsa st_rsa;
|
||||
};
|
||||
|
||||
int fips(const char *, struct audit_fips *, struct keyinfo *, const int, const int);
|
||||
/* RSA */
|
||||
static int fips_pubkey_rsa(struct audit_fips *, struct keyinfo *, const char *);
|
||||
static int fips_privkey_rsa(struct audit_fips *, struct keyinfo *, const char *);
|
||||
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 *);
|
||||
static int loadkeys_rsa(RSA **, const char *, int *format);
|
||||
static int load_priv_rsa_keys(RSA **, const char *);
|
||||
static void audit_rsa_keys(RSA *, struct audit_fips *, struct keyinfo *, const char *);
|
||||
static int check_exponent(const BIGNUM *, char *, unsigned long *);
|
||||
|
||||
/* Elliptic */
|
||||
static int fips_pubkey_ecc(EC_KEY *, struct audit_fips *, struct keyinfo *, const char *);
|
||||
static EC_KEY *fips_load_pubkey_ecc(const char *);
|
||||
static int get_domain_parameters(struct ecc *);
|
||||
static void audit_ecc(struct audit_fips *, const int);
|
||||
|
||||
/* X509 */
|
||||
static int fips_x509_v1(struct audit_fips *, struct keyinfo *, const char *);
|
||||
static int fips_x509_v3(struct audit_fips *, struct keyinfo *, const char *);
|
||||
static int fips_x509(struct audit_fips *, struct keyinfo *, const char *);
|
||||
|
||||
static int check_exponent(const BIGNUM *, char *, unsigned long *);
|
||||
static void clean_rsa_st(struct rsa *);
|
||||
static int openssl_version();
|
||||
static void print_error();
|
||||
|
||||
|
||||
@ -90,37 +90,54 @@ int certificate(char **argv, const int argc){
|
||||
/*************************/
|
||||
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);
|
||||
if (res < 0){
|
||||
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)
|
||||
if (st_keyinfo.algo == ALGO_RSA){
|
||||
printf("\tKey size: %d bytes (%d)\n", st_keyinfo.st_rsa.keysize, (st_keyinfo.st_rsa.keysize * 8));
|
||||
printf("\tExponent: %lu\n", st_keyinfo.st_rsa.exponent);
|
||||
printf("\tAlgorithm: RSA\n");
|
||||
if (st_keyinfo.algo == ALGO_EC)
|
||||
printf("\tAlgorithm: Elliptic Curve\n");
|
||||
if (st_keyinfo.st_rsa.format == RSA_FORMAT_PKCS1)
|
||||
printf("\tFormat RSA key: PKCS#1\n");
|
||||
if (st_keyinfo.st_rsa.format == RSA_FORMAT_SPKI)
|
||||
printf("\tFormat RSA key: SPKI (PEM)\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");
|
||||
/* Print the audit result */
|
||||
printf("\nExponent result:\n");
|
||||
printf("\t%s\n", st_audit_fips.audit_rsa.audit_exponent.result);
|
||||
printf("Keysize result:\n");
|
||||
printf("\t%s\n", st_audit_fips.audit_rsa.audit_keysize.result);
|
||||
}
|
||||
if (st_keyinfo.algo == ALGO_EC) {
|
||||
printf("\tAlgorithm: Elliptic Curve\n");
|
||||
printf("\tCurve name: %s\n", st_keyinfo.s_ecc.curve);
|
||||
printf("\tCofactor: %s\n", st_keyinfo.s_ecc.cofactor);
|
||||
printf("\tOrder: %s\n", st_keyinfo.s_ecc.order);
|
||||
printf("\tOrder length: %d\n", st_keyinfo.s_ecc.order_bits);
|
||||
printf("\tGenerator: %s\n", st_keyinfo.s_ecc.g);
|
||||
|
||||
/* Should I allocate each variables in audit/fips.c and clean it ? */
|
||||
|
||||
OPENSSL_free(st_keyinfo.s_ecc.cofactor);
|
||||
/* It's a const char *, I cannot free it */
|
||||
//OPENSSL_free(st_keyinfo.s_ecc.curve);
|
||||
OPENSSL_free(st_keyinfo.s_ecc.order);
|
||||
OPENSSL_free(st_keyinfo.s_ecc.g);
|
||||
EC_KEY_free(st_keyinfo.s_ecc.ec);
|
||||
st_keyinfo.s_ecc.ec = NULL;
|
||||
|
||||
/* Print the audit result */
|
||||
printf("\nCurve result: \n");
|
||||
printf("\t%s\n", st_audit_fips.audit_ecc.audit_curve.result);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
@ -128,14 +145,14 @@ int certificate(char **argv, const int argc){
|
||||
if (to_stdout){
|
||||
int len = 0;
|
||||
|
||||
st_keyinfo.key = (char *)malloc(st_stat.st_size + 1);
|
||||
st_keyinfo.st_rsa.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';
|
||||
len = read(fd, st_keyinfo.st_rsa.key, st_stat.st_size);
|
||||
st_keyinfo.st_rsa.key[len] = '\0';
|
||||
|
||||
printf("Dump the key:\n%s\n", st_keyinfo.key);
|
||||
printf("Dump the key:\n%s\n", st_keyinfo.st_rsa.key);
|
||||
|
||||
free(st_keyinfo.key);
|
||||
free(st_keyinfo.st_rsa.key);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
@ -153,6 +170,8 @@ static int check_arguments_certificate(char **argv, const int argc, char *buf_pk
|
||||
if (strncmp(argv[i], "-type", l) == 0){
|
||||
if (strcmp(argv[i + 1], "rsa") == 0)
|
||||
*type = TYPE_RSA;
|
||||
else if (strcmp(argv[i + 1], "elliptic") == 0)
|
||||
*type = TYPE_ELLIPTIC;
|
||||
else if (strcmp(argv[i + 1], "x509") == 0)
|
||||
*type = TYPE_X509;
|
||||
else
|
||||
|
||||
BIN
cryptodit
BIN
cryptodit
Binary file not shown.
BIN
entropy_ebpf.o
BIN
entropy_ebpf.o
Binary file not shown.
18
error.h
18
error.h
@ -4,13 +4,19 @@
|
||||
/* 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
|
||||
#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
|
||||
#define FIPS_ERR_LOAD_ECC_PUBKEY 0x210
|
||||
#define FIPS_ERR_LOAD_ECC_PRIVKEY 0x211
|
||||
#define FIPS_ERR_GET_ECC_GROUP 0x212
|
||||
#define FIPS_ERR_GET_ECC_DOMAPARAM 0x213
|
||||
#define FIPS_ERR_GET_ECC_GENERATOR 0x214
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
-----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-----
|
||||
Loading…
Reference in New Issue
Block a user