diff --git a/audit/fips.c b/audit/fips.c index db0816b..367a83d 100644 --- a/audit/fips.c +++ b/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); + + RSA *rsa = NULL; + res = loadkeys_rsa(&rsa, pkey, &st_keyinfo->st_rsa.format); - if (res > 0 || rsa == NULL){ + 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,106 +71,84 @@ 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){ +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; } - - #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); */ + /*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 diff --git a/audit/fips.h b/audit/fips.h index a8679ef..ef9ae1b 100644 --- a/audit/fips.h +++ b/audit/fips.h @@ -8,8 +8,9 @@ #include #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(); diff --git a/certificate.c b/certificate.c index bc50025..9397f09 100644 --- a/certificate.c +++ b/certificate.c @@ -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 diff --git a/cryptodit b/cryptodit index f1f6985..50bcaef 100755 Binary files a/cryptodit and b/cryptodit differ diff --git a/entropy_ebpf.o b/entropy_ebpf.o index 0ee8c9f..658f403 100644 Binary files a/entropy_ebpf.o and b/entropy_ebpf.o differ diff --git a/error.h b/error.h index 1771521..610ddee 100644 --- a/error.h +++ b/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 diff --git a/examples/foo.pem b/examples/foo.pem deleted file mode 100644 index 0b6ed9b..0000000 --- a/examples/foo.pem +++ /dev/null @@ -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-----