#include #include #include #include #include #include #include "fips140.h" #include "fips140_test.h" // TODO: to be removed #if defined (__clang__) #pragma clang optimize off #elif defined (__GNUC__) #pragma GCC push_options #pragma GCC optimize ("O0") #endif int fips_enabled; EXPORT_SYMBOL_GPL(fips_enabled); #ifdef CONFIG_CRYPTO_FIPS_FUNC_TEST static int functest_status; #endif static int __init fips140_post(void) { int err_kat = -1; int err_integrity = -1; fips_enabled = 0; pr_info("FIPS : POST (%s)\n", SKC_VERSION_TEXT); err_kat = fips140_kat(); err_integrity = do_integrity_check(); if (err_kat || err_integrity) { pr_err("FIPS : POST - one or more selftests failed\n"); #ifdef CONFIG_CRYPTO_FIPS_FUNC_TEST if (functest_status) { pr_err("FIPS : POST - bypass panic because of functional test\n"); return -1; } else panic("FIPS : POST - one or more selftests failed\n"); #else panic("FIPS : POST - one or more selftests failed\n"); #endif } fips_enabled = 1; pr_info("FIPS : POST - CRYPTO API started in FIPS approved mode : fips_enabled = %d\n", fips_enabled); return 0; } // When SKC_FUNC_TEST is defined, this function will be called instead of tcrypt_mode_init // tcyprt_mode_init will be called as test case number // after all tests are done, the normal POST test will start #ifdef CONFIG_CRYPTO_FIPS_FUNC_TEST static int __init fips140_post_func_test(void) { int i; int err = -ENOMEM; struct crypto_skcipher *tfm = NULL; pr_info("FIPS FUNC : Functional test start\n"); functest_status = 1; for (i = 0; i < SKC_FUNCTEST_KAT_CASE_NUM; i++) { set_fips_functest_KAT_mode(i); pr_info("FIPS FUNC : --------------------------------------------------\n"); pr_info("FIPS FUNC : Failure inducement case %d - [%s]\n", i + 1, get_fips_functest_mode()); pr_info("FIPS FUNC : --------------------------------------------------\n"); err = fips140_post(); pr_info("FIPS FUNC : (%d) POST done. SKC module FIPS status : fips140_post() returns %d | %s\n", i+1, err, fips_enabled ? "passed" : "failed"); } functest_status = 0; for (i = 0; i < SKC_FUNCTEST_CONDITIONAL_CASE_NUM; i++) { set_fips_functest_conditional_mode(i); pr_info("FIPS FUNC : --------------------------------------------------\n"); pr_info("FIPS FUNC : conditional test case %d - [%s]\n", i + 1, get_fips_functest_mode()); pr_info("FIPS FUNC : --------------------------------------------------\n"); if (!strcmp("zeroization", get_fips_functest_mode())) { uint8_t key[AES_KEYSIZE_256]; memset(key, 0xFE, AES_KEYSIZE_256); tfm = crypto_alloc_skcipher("ecb(aes-ce)", 0, 0); if (tfm) { crypto_skcipher_setkey(tfm, key, AES_KEYSIZE_256); crypto_free_skcipher(tfm); } } } set_fips_functest_conditional_mode(-1); pr_info("FIPS FUNC : Functional test end\n"); pr_info("FIPS FUNC : Normal POST start\n"); return fips140_post(); } #endif /* * If an init function is provided, an exit function must also be provided * to allow module unload. */ static void __exit fips140_fini(void) { } #ifdef CONFIG_CRYPTO_FIPS_FUNC_TEST late_initcall(fips140_post_func_test); #else late_initcall(fips140_post); #endif module_exit(fips140_fini); // TODO: to be removed #if defined (__clang__) #pragma clang optimize on #elif defined (__GNUC__) #pragma GCC reset_options #endif MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("FIPS140 POST");