X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=fips%2Ffips_test_suite.c;h=447d1088bd8aea74d9e93d7ca8c0b9daecbee616;hb=4420b3b17acf19f78f4fdea1a69d5f0a644c8154;hp=bcb2c7a0dcd879ca7eaffccc60dd02cfd55157aa;hpb=37942b93af4fca91ca915d4da1f68d7965a9522f;p=oweals%2Fopenssl.git diff --git a/fips/fips_test_suite.c b/fips/fips_test_suite.c index bcb2c7a0dc..447d1088bd 100644 --- a/fips/fips_test_suite.c +++ b/fips/fips_test_suite.c @@ -43,6 +43,7 @@ int main(int argc, char *argv[]) #include #include +#include #include "fips_utl.h" /* AES: encrypt and decrypt known plaintext, verify result matches original plaintext @@ -408,7 +409,7 @@ static int FIPS_cmac_aes128_test() 0xd7,0xd5,0x66,0xf5, 0xd2,0x8d,0xbd,0x2a, }; unsigned char *out = NULL; - unsigned int outlen; + size_t outlen; CMAC_CTX *ctx = CMAC_CTX_new(); int r = 0; @@ -459,7 +460,7 @@ static int FIPS_cmac_aes192_test() 0xb1,0x4a,0x0b,0xf2, 0xc6,0x3c,0x47,0x1f, }; unsigned char *out = NULL; - unsigned int outlen; + size_t outlen; CMAC_CTX *ctx = CMAC_CTX_new(); int r = 0; @@ -511,7 +512,7 @@ static int FIPS_cmac_aes256_test() 0xb0,0x86,0x37,0x5f, 0x15,0x60,0xba,0x1f, }; unsigned char *out = NULL; - unsigned int outlen; + size_t outlen; CMAC_CTX *ctx = CMAC_CTX_new(); int r = 0; @@ -548,56 +549,6 @@ static int FIPS_cmac_aes256_test() return r; } -/* CMAC-TDEA2: generate hash of known digest value and compare to known - precomputed correct hash -*/ -static int FIPS_cmac_tdea2_test() - { - unsigned char key[] = { 0x4c,0xf1,0x51,0x34, 0xa2,0x85,0x0d,0xd5, - 0x8a,0x3d,0x10,0xba, 0x80,0x57,0x0d,0x38, }; - unsigned char data[] = "Sample text"; - unsigned char kaval[] = - {0x73, 0xf7, 0xa0, 0x48, 0xf8, 0x94, 0xed, 0xdd, 0x0a, 0xea, 0xea, 0x56, 0x1b, 0x61, 0x2e, 0x70, - 0xb2, 0xfb, 0xec, 0xc6}; - - unsigned char *out = NULL; - unsigned int outlen; - CMAC_CTX *ctx = CMAC_CTX_new(); - int r = 0; - - ERR_clear_error(); - - if (!ctx) - goto end; - if (!CMAC_Init(ctx,key,sizeof(key),EVP_des_ede_cbc(),NULL)) - goto end; - if (!CMAC_Update(ctx,data,sizeof(data)-1)) - goto end; - /* This should return 1. If not, there's a programming error... */ - if (!CMAC_Final(ctx, out, &outlen)) - goto end; - out = OPENSSL_malloc(outlen); - if (!CMAC_Final(ctx, out, &outlen)) - goto end; -#if 1 - { - char *hexout = OPENSSL_malloc(outlen * 2 + 1); - bin2hex(out, outlen, hexout); - printf("CMAC-TDEA2: res = %s\n", hexout); - OPENSSL_free(hexout); - } - r = 1; -#else - if (!memcmp(out,kaval,outlen)) - r = 1; -#endif - end: - CMAC_CTX_free(ctx); - if (out) - OPENSSL_free(out); - return r; - } - /* CMAC-TDEA3: generate hash of known digest value and compare to known precomputed correct hash */ @@ -611,7 +562,7 @@ static int FIPS_cmac_tdea3_test() { 0xb4,0x06,0x4e,0xbf, 0x59,0x89,0xba,0x68, }; unsigned char *out = NULL; - unsigned int outlen; + size_t outlen; CMAC_CTX *ctx = CMAC_CTX_new(); int r = 0; @@ -703,6 +654,103 @@ static int Zeroize() return 1; } +/* Dummy Entropy for DRBG tests. WARNING: THIS IS TOTALLY BOGUS + * HAS ZERO SECURITY AND MUST NOT BE USED IN REAL APPLICATIONS. + */ + +static unsigned char dummy_drbg_entropy[1024]; + +static size_t drbg_test_cb(DRBG_CTX *ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len) + { + *pout = dummy_drbg_entropy; + /* Round up to multiple of block size */ + return (min_len + 0xf) & ~0xf; + } + +/* DRBG test: just generate lots of data and trigger health checks */ + +static int do_drbg_test(int type, int flags) + { + DRBG_CTX *dctx; + int rv = 0; + size_t i; + unsigned char randout[1024]; + dctx = FIPS_drbg_new(type, flags); + if (!dctx) + return 0; + FIPS_drbg_set_callbacks(dctx, drbg_test_cb, 0, 0x10, drbg_test_cb, 0); + for (i = 0; i < sizeof(dummy_drbg_entropy); i++) + { + dummy_drbg_entropy[i] = i & 0xff; + } + if (!FIPS_drbg_instantiate(dctx, dummy_drbg_entropy, 10)) + goto err; + FIPS_drbg_set_check_interval(dctx, 10); + for (i = 0; i < 32; i++) + { + if (!FIPS_drbg_generate(dctx, randout, sizeof(randout), 0, NULL, 0)) + goto err; + if (!FIPS_drbg_generate(dctx, randout, sizeof(randout), 0, dummy_drbg_entropy, 1)) + goto err; + } + rv = 1; + err: + FIPS_drbg_uninstantiate(dctx); + return rv; + } + +typedef struct + { + int type, flags; + } DRBG_LIST; + +static int do_drbg_all(void) + { + static DRBG_LIST drbg_types[] = + { + {NID_sha1, 0}, + {NID_sha224, 0}, + {NID_sha256, 0}, + {NID_sha384, 0}, + {NID_sha512, 0}, + {NID_hmacWithSHA1, 0}, + {NID_hmacWithSHA224, 0}, + {NID_hmacWithSHA256, 0}, + {NID_hmacWithSHA384, 0}, + {NID_hmacWithSHA512, 0}, + {NID_aes_128_ctr, 0}, + {NID_aes_192_ctr, 0}, + {NID_aes_256_ctr, 0}, + {NID_aes_128_ctr, DRBG_FLAG_CTR_USE_DF}, + {NID_aes_192_ctr, DRBG_FLAG_CTR_USE_DF}, + {NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF}, + {(NID_X9_62_prime256v1 << 16)|NID_sha1, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha224, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha256, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha384, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha512, 0}, + {(NID_secp384r1 << 16)|NID_sha224, 0}, + {(NID_secp384r1 << 16)|NID_sha256, 0}, + {(NID_secp384r1 << 16)|NID_sha384, 0}, + {(NID_secp384r1 << 16)|NID_sha512, 0}, + {(NID_secp521r1 << 16)|NID_sha256, 0}, + {(NID_secp521r1 << 16)|NID_sha384, 0}, + {(NID_secp521r1 << 16)|NID_sha512, 0}, + {0, 0} + }; + DRBG_LIST *lst; + int rv = 1; + for (lst = drbg_types;; lst++) + { + if (lst->type == 0) + break; + if (!do_drbg_test(lst->type, lst->flags)) + rv = 0; + } + return rv; + } + static int Error; static const char * Fail(const char *msg) { @@ -715,74 +763,307 @@ static void test_msg(const char *msg, int result) printf("%s...%s\n", msg, result ? "successful" : Fail("Failed!")); } +/* Table of IDs for POST translating between NIDs and names */ + +typedef struct + { + int id; + const char *name; + } POST_ID; + +POST_ID id_list[] = { + {NID_sha1, "SHA1"}, + {NID_sha224, "SHA224"}, + {NID_sha256, "SHA256"}, + {NID_sha384, "SHA384"}, + {NID_sha512, "SHA512"}, + {NID_hmacWithSHA1, "HMAC-SHA1"}, + {NID_hmacWithSHA224, "HMAC-SHA224"}, + {NID_hmacWithSHA256, "HMAC-SHA256"}, + {NID_hmacWithSHA384, "HMAC-SHA384"}, + {NID_hmacWithSHA512, "HMAC-SHA512"}, + {EVP_PKEY_RSA, "RSA"}, + {EVP_PKEY_DSA, "DSA"}, + {EVP_PKEY_EC, "ECDSA"}, + {NID_aes_128_cbc, "AES-128-CBC"}, + {NID_aes_192_cbc, "AES-192-CBC"}, + {NID_aes_256_cbc, "AES-256-CBC"}, + {NID_aes_128_ctr, "AES-128-CTR"}, + {NID_aes_192_ctr, "AES-192-CTR"}, + {NID_aes_256_ctr, "AES-256-CTR"}, + {NID_aes_128_ecb, "AES-128-ECB"}, + {NID_aes_128_xts, "AES-128-XTS"}, + {NID_aes_256_xts, "AES-256-XTS"}, + {NID_des_ede3_cbc, "DES-EDE3-CBC"}, + {NID_des_ede3_ecb, "DES-EDE3-ECB"}, + {NID_X9_62_prime256v1, "P-256"}, + {NID_secp384r1, "P-384"}, + {NID_secp521r1, "P-521"}, + {0, NULL} +}; + +static const char *lookup_id(int id) + { + POST_ID *n; + static char out[40]; + for (n = id_list; n->name; n++) + { + if (n->id == id) + return n->name; + } + sprintf(out, "ID=%d", id); + return out; + } + +static int fail_id = -1; +static int fail_sub = -1; +static int fail_key = -1; + +static int post_cb(int op, int id, int subid, void *ex) + { + const char *idstr, *exstr = ""; + char asctmp[20]; + int keytype = -1; +#ifdef FIPS_POST_TIME + static struct timespec start, end, tstart, tend; +#endif + switch(id) + { + case FIPS_TEST_INTEGRITY: + idstr = "Integrity"; + break; + + case FIPS_TEST_DIGEST: + idstr = "Digest"; + exstr = lookup_id(subid); + break; + + case FIPS_TEST_CIPHER: + exstr = lookup_id(subid); + idstr = "Cipher"; + break; + + case FIPS_TEST_SIGNATURE: + if (ex) + { + EVP_PKEY *pkey = ex; + keytype = pkey->type; + exstr = lookup_id(keytype); + } + idstr = "Signature"; + break; + + case FIPS_TEST_HMAC: + exstr = lookup_id(subid); + idstr = "HMAC"; + break; + + case FIPS_TEST_CMAC: + idstr = "CMAC"; + exstr = lookup_id(subid); + break; + + case FIPS_TEST_GCM: + idstr = "GCM"; + break; + + case FIPS_TEST_XTS: + idstr = "XTS"; + exstr = lookup_id(subid); + break; + + case FIPS_TEST_CCM: + idstr = "CCM"; + break; + + case FIPS_TEST_X931: + idstr = "X9.31 PRNG"; + sprintf(asctmp, "keylen=%d", subid); + exstr = asctmp; + break; + + case FIPS_TEST_DRBG: + idstr = "DRBG"; + if (*(int *)ex & DRBG_FLAG_CTR_USE_DF) + { + sprintf(asctmp, "%s DF", lookup_id(subid)); + exstr = asctmp; + } + else if (subid >> 16) + { + sprintf(asctmp, "%s %s", + lookup_id(subid >> 16), + lookup_id(subid & 0xFFFF)); + exstr = asctmp; + } + else + exstr = lookup_id(subid); + break; + + case FIPS_TEST_PAIRWISE: + if (ex) + { + EVP_PKEY *pkey = ex; + keytype = pkey->type; + exstr = lookup_id(keytype); + } + idstr = "Pairwise Consistency"; + break; + + case FIPS_TEST_CONTINUOUS: + idstr = "Continuous PRNG"; + break; + + default: + idstr = "Unknown"; + break; + + } + + switch(op) + { + case FIPS_POST_BEGIN: +#ifdef FIPS_POST_TIME + clock_getres(CLOCK_REALTIME, &tstart); + printf("\tTimer resolution %ld s, %ld ns\n", + (long)tstart.tv_sec, (long)tstart.tv_nsec); + clock_gettime(CLOCK_REALTIME, &tstart); +#endif + printf("\tPOST started\n"); + break; + + case FIPS_POST_END: + printf("\tPOST %s\n", id ? "Success" : "Failed"); +#ifdef FIPS_POST_TIME + clock_gettime(CLOCK_REALTIME, &tend); + printf("\t\tTook %f seconds\n", + (double)((tend.tv_sec+tend.tv_nsec*1e-9) + - (tstart.tv_sec+tstart.tv_nsec*1e-9))); +#endif + break; + + case FIPS_POST_STARTED: + printf("\t\t%s %s test started\n", idstr, exstr); +#ifdef FIPS_POST_TIME + clock_gettime(CLOCK_REALTIME, &start); +#endif + break; + + case FIPS_POST_SUCCESS: + printf("\t\t%s %s test OK\n", idstr, exstr); +#ifdef FIPS_POST_TIME + clock_gettime(CLOCK_REALTIME, &end); + printf("\t\t\tTook %f seconds\n", + (double)((end.tv_sec+end.tv_nsec*1e-9) + - (start.tv_sec+start.tv_nsec*1e-9))); +#endif + break; + + case FIPS_POST_FAIL: + printf("\t\t%s %s test FAILED!!\n", idstr, exstr); + break; + + case FIPS_POST_CORRUPT: + if (fail_id == id + && (fail_key == -1 || fail_key == keytype) + && (fail_sub == -1 || fail_sub == subid)) + { + printf("\t\t%s %s test failure induced\n", idstr, exstr); + return 0; + } + break; + + } + return 1; + } + int main(int argc,char **argv) { - - int do_corrupt_rsa_keygen = 0, do_corrupt_dsa_keygen = 0; int bad_rsa = 0, bad_dsa = 0; int do_rng_stick = 0; + int do_drbg_stick = 0; int no_exit = 0; + int no_dh = 0; - fips_set_error_print(); + FIPS_post_set_callback(post_cb); - printf("\tFIPS-mode test application\n\n"); + printf("\tFIPS-mode test application\n"); - /* Load entropy from external file, if any */ - RAND_load_file(".rnd", 1024); + printf("\t%s\n\n", FIPS_module_version_text()); if (argv[1]) { /* Corrupted KAT tests */ - if (!strcmp(argv[1], "aes")) { - FIPS_corrupt_aes(); - printf("AES encryption/decryption with corrupted KAT...\n"); + if (!strcmp(argv[1], "integrity")) { + fail_id = FIPS_TEST_INTEGRITY; + } else if (!strcmp(argv[1], "aes")) { + fail_id = FIPS_TEST_CIPHER; + fail_sub = NID_aes_128_ecb; + } else if (!strcmp(argv[1], "aes-ccm")) { + fail_id = FIPS_TEST_CCM; } else if (!strcmp(argv[1], "aes-gcm")) { - FIPS_corrupt_aes_gcm(); - printf("AES-GCM encryption/decryption with corrupted KAT...\n"); + fail_id = FIPS_TEST_GCM; + } else if (!strcmp(argv[1], "aes-xts")) { + fail_id = FIPS_TEST_XTS; } else if (!strcmp(argv[1], "des")) { - FIPS_corrupt_des(); - printf("DES3-ECB encryption/decryption with corrupted KAT...\n"); + fail_id = FIPS_TEST_CIPHER; + fail_sub = NID_des_ede3_ecb; } else if (!strcmp(argv[1], "dsa")) { - FIPS_corrupt_dsa(); - printf("DSA key generation and signature validation with corrupted KAT...\n"); + fail_id = FIPS_TEST_SIGNATURE; + fail_key = EVP_PKEY_DSA; } else if (!strcmp(argv[1], "ecdsa")) { - FIPS_corrupt_ecdsa(); - printf("ECDSA key generation and signature validation with corrupted KAT...\n"); + fail_id = FIPS_TEST_SIGNATURE; + fail_key = EVP_PKEY_EC; } else if (!strcmp(argv[1], "rsa")) { - FIPS_corrupt_rsa(); - printf("RSA key generation and signature validation with corrupted KAT...\n"); + fail_id = FIPS_TEST_SIGNATURE; + fail_key = EVP_PKEY_RSA; } else if (!strcmp(argv[1], "rsakey")) { printf("RSA key generation and signature validation with corrupted key...\n"); bad_rsa = 1; no_exit = 1; } else if (!strcmp(argv[1], "rsakeygen")) { - do_corrupt_rsa_keygen = 1; + fail_id = FIPS_TEST_PAIRWISE; + fail_key = EVP_PKEY_RSA; no_exit = 1; - printf("RSA key generation and signature validation with corrupted keygen...\n"); } else if (!strcmp(argv[1], "dsakey")) { printf("DSA key generation and signature validation with corrupted key...\n"); bad_dsa = 1; no_exit = 1; } else if (!strcmp(argv[1], "dsakeygen")) { - do_corrupt_dsa_keygen = 1; + fail_id = FIPS_TEST_PAIRWISE; + fail_key = EVP_PKEY_DSA; no_exit = 1; - printf("DSA key generation and signature validation with corrupted keygen...\n"); } else if (!strcmp(argv[1], "sha1")) { - FIPS_corrupt_sha1(); - printf("SHA-1 hash with corrupted KAT...\n"); + fail_id = FIPS_TEST_DIGEST; + } else if (!strcmp(argv[1], "hmac")) { + fail_id = FIPS_TEST_HMAC; + } else if (!strcmp(argv[1], "cmac")) { + fail_id = FIPS_TEST_CMAC; } else if (!strcmp(argv[1], "drbg")) { - FIPS_corrupt_drbg(); + fail_id = FIPS_TEST_DRBG; } else if (!strcmp(argv[1], "rng")) { - FIPS_corrupt_rng(); + fail_id = FIPS_TEST_X931; + } else if (!strcmp(argv[1], "nodh")) { + no_dh = 1; + no_exit = 1; + } else if (!strcmp(argv[1], "post")) { + fail_id = -1; } else if (!strcmp(argv[1], "rngstick")) { do_rng_stick = 1; no_exit = 1; printf("RNG test with stuck continuous test...\n"); + } else if (!strcmp(argv[1], "drbgentstick")) { + do_entropy_stick(); + } else if (!strcmp(argv[1], "drbgstick")) { + do_drbg_stick = 1; + no_exit = 1; + printf("DRBG test with stuck continuous test...\n"); } else { printf("Bad argument \"%s\"\n", argv[1]); exit(1); } if (!no_exit) { - if (!FIPS_mode_set(1)) { + fips_algtest_init_nofips(); + if (!FIPS_module_mode_set(1)) { printf("Power-up self test failed\n"); exit(1); } @@ -791,23 +1072,26 @@ int main(int argc,char **argv) } } + fips_algtest_init_nofips(); + /* Non-Approved cryptographic operation */ printf("1. Non-Approved cryptographic operation test...\n"); - test_msg("\ta. Included algorithm (D-H)...", dh_test()); + if (no_dh) + printf("\t D-H test skipped\n"); + else + test_msg("\ta. Included algorithm (D-H)...", dh_test()); /* Power-up self test */ ERR_clear_error(); - test_msg("2. Automatic power-up self test", FIPS_mode_set(1)); - if (!FIPS_mode()) + test_msg("2. Automatic power-up self test", FIPS_module_mode_set(1)); + if (!FIPS_module_mode()) exit(1); - if (do_corrupt_dsa_keygen) - FIPS_corrupt_dsa_keygen(); - if (do_corrupt_rsa_keygen) - FIPS_corrupt_rsa_keygen(); + if (do_drbg_stick) + FIPS_drbg_stick(); if (do_rng_stick) - FIPS_rng_stick(); + FIPS_x931_stick(); /* AES encryption/decryption */ @@ -888,6 +1172,7 @@ int main(int argc,char **argv) */ printf("9. Non-Approved cryptographic operation test...\n"); printf("\ta. Included algorithm (D-H)...%s\n", + no_dh ? "skipped" : dh_test() ? "successful as expected" : Fail("failed INCORRECTLY!") ); @@ -897,6 +1182,14 @@ int main(int argc,char **argv) Zeroize() ? "successful as expected" : Fail("failed INCORRECTLY!") ); + printf("11. Complete DRBG health check...\n"); + printf("\t%s\n", FIPS_selftest_drbg_all() ? "successful as expected" + : Fail("failed INCORRECTLY!") ); + + printf("12. DRBG generation check...\n"); + printf("\t%s\n", do_drbg_all() ? "successful as expected" + : Fail("failed INCORRECTLY!") ); + printf("\nAll tests completed with %d errors\n", Error); return Error ? 1 : 0; }