linuxkm: don't toggle fips_enabled.

This commit is contained in:
jordan
2025-06-13 00:45:12 -05:00
parent 6cb0c8513d
commit bb5291aa5e
4 changed files with 151 additions and 61 deletions

View File

@@ -294,6 +294,7 @@ LIBWOLFSSL_VERSION_GIT_HASH_DATE
LIBWOLFSSL_VERSION_GIT_ORIGIN LIBWOLFSSL_VERSION_GIT_ORIGIN
LIBWOLFSSL_VERSION_GIT_SHORT_HASH LIBWOLFSSL_VERSION_GIT_SHORT_HASH
LIBWOLFSSL_VERSION_GIT_TAG LIBWOLFSSL_VERSION_GIT_TAG
LINUXKM_DONT_FORCE_FIPS_ENABLED
LINUXKM_FPU_STATES_FOLLOW_THREADS LINUXKM_FPU_STATES_FOLLOW_THREADS
LINUXKM_LKCAPI_PRIORITY_ALLOW_MASKING LINUXKM_LKCAPI_PRIORITY_ALLOW_MASKING
LINUX_CYCLE_COUNT LINUX_CYCLE_COUNT

View File

@@ -885,12 +885,23 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver,
*/ */
tfm = crypto_alloc_kpp(driver, 0, 0); tfm = crypto_alloc_kpp(driver, 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
pr_err("error: allocating kpp algorithm %s failed: %ld\n", #if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
driver, PTR_ERR(tfm)); !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
if (PTR_ERR(tfm) == -ENOMEM) if ((PTR_ERR(tfm) == -ENOENT) && fips_enabled) {
test_rc = MEMORY_E; pr_info("info: skipping unsupported kpp algorithm %s: %ld\n",
driver, PTR_ERR(tfm));
test_rc = NOT_COMPILED_IN;
}
else else
test_rc = BAD_FUNC_ARG; #endif
{
pr_err("error: allocating kpp algorithm %s failed: %ld\n",
driver, PTR_ERR(tfm));
if (PTR_ERR(tfm) == -ENOMEM)
test_rc = MEMORY_E;
else
test_rc = BAD_FUNC_ARG;
}
tfm = NULL; tfm = NULL;
goto test_ecdh_nist_end; goto test_ecdh_nist_end;
} }

View File

@@ -727,12 +727,27 @@ static int linuxkm_test_ecdsa_nist_driver(const char * driver,
*/ */
tfm = crypto_alloc_akcipher(driver, 0, 0); tfm = crypto_alloc_akcipher(driver, 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
pr_err("error: allocating akcipher algorithm %s failed: %ld\n", #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \
driver, PTR_ERR(tfm)); defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
if (PTR_ERR(tfm) == -ENOMEM) !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
test_rc = MEMORY_E; /* ecdsa was not recognized as fips_allowed before linux v6.3
* in kernel crypto/testmgr.c, and the kernel will block
* its allocation if fips_enabled is set. */
if ((PTR_ERR(tfm) == -ENOENT) && fips_enabled) {
pr_info("info: skipping unsupported akcipher algorithm %s: %ld\n",
driver, PTR_ERR(tfm));
test_rc = NOT_COMPILED_IN;
}
else else
test_rc = BAD_FUNC_ARG; #endif
{
pr_err("error: allocating akcipher algorithm %s failed: %ld\n",
driver, PTR_ERR(tfm));
if (PTR_ERR(tfm) == -ENOMEM)
test_rc = MEMORY_E;
else
test_rc = BAD_FUNC_ARG;
}
tfm = NULL; tfm = NULL;
goto test_ecdsa_nist_end; goto test_ecdsa_nist_end;
} }

View File

@@ -222,6 +222,11 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
static int linuxkm_lkcapi_register(void); static int linuxkm_lkcapi_register(void);
static int linuxkm_lkcapi_unregister(void); static int linuxkm_lkcapi_unregister(void);
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
static int enabled_fips = 0;
#endif
static ssize_t install_algs_handler(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t install_algs_handler(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
@@ -261,6 +266,14 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut
if (ret != 0) if (ret != 0)
return ret; return ret;
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
if (enabled_fips) {
pr_info("wolfCrypt: restoring fips_enabled to off.");
enabled_fips = fips_enabled = 0;
}
#endif
return count; return count;
} }
@@ -305,10 +318,6 @@ static int linuxkm_lkcapi_register(void)
{ {
int ret = -1; int ret = -1;
int seen_err = 0; int seen_err = 0;
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
int enabled_fips = 0;
#endif
ret = linuxkm_lkcapi_sysfs_install(); ret = linuxkm_lkcapi_sysfs_install();
if (ret) if (ret)
@@ -321,12 +330,14 @@ static int linuxkm_lkcapi_register(void)
*/ */
disable_setkey_warnings = 1; disable_setkey_warnings = 1;
#endif #endif
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ #if !defined(LINUXKM_DONT_FORCE_FIPS_ENABLED) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
if (! fips_enabled) { if (! fips_enabled) {
/* temporarily assert system-wide FIPS status, to disable FIPS-forbidden /* assert system-wide FIPS status, to disable FIPS-forbidden
* test vectors and fuzzing from the CRYPTO_MANAGER. * test vectors and fuzzing from the CRYPTO_MANAGER.
*/ */
pr_info("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module.");
enabled_fips = fips_enabled = 1; enabled_fips = fips_enabled = 1;
} }
#endif #endif
@@ -365,6 +376,59 @@ static int linuxkm_lkcapi_register(void)
} \ } \
} while (0) } while (0)
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
/* Same as above, but allow for option to skip problematic algs that are
* not consistently labeled fips_allowed in crypto/testmgr.c, and hence
* may be rejected by the kernel at runtime if is_fips is true. */
#define REGISTER_ALG_OPTIONAL(alg, alg_class, tester) do {\
if (! alg ## _loaded) { \
ret = (crypto_register_ ## alg_class)(&(alg)); \
if (ret) { \
if (fips_enabled && (ret == NOT_COMPILED_IN)) { \
pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \
(alg).base.cra_driver_name); \
} \
else { \
seen_err = ret; \
pr_err("ERROR: crypto_register_" #alg_class \
" for %s failed " \
"with return code %d.\n", \
(alg).base.cra_driver_name, ret); \
} \
} else { \
ret = (tester()); \
if (ret) { \
if (fips_enabled && (ret == NOT_COMPILED_IN)) { \
pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \
(alg).base.cra_driver_name); \
} \
else { \
seen_err = -EINVAL; \
pr_err("ERROR: wolfCrypt self-test for %s failed " \
"with return code %d.\n", \
(alg).base.cra_driver_name, ret); \
} \
(crypto_unregister_ ## alg_class)(&(alg)); \
if (! (alg.base.cra_flags & CRYPTO_ALG_DEAD)) { \
pr_err("ERROR: alg %s not _DEAD " \
"after crypto_unregister_%s -- " \
"marking as loaded despite test failure.", \
(alg).base.cra_driver_name, \
#alg_class); \
alg ## _loaded = 1; \
++linuxkm_lkcapi_n_registered; \
} \
} else { \
alg ## _loaded = 1; \
++linuxkm_lkcapi_n_registered; \
WOLFKM_INSTALL_NOTICE(alg) \
} \
} \
} \
} while (0)
#endif /* HAVE_FIPS && CONFIG_CRYPTO_MANAGER && etc.. */
/* We always register the derivative/composite algs first, to assure that /* We always register the derivative/composite algs first, to assure that
* the kernel doesn't synthesize them dynamically from our primitives. * the kernel doesn't synthesize them dynamically from our primitives.
*/ */
@@ -464,7 +528,6 @@ static int linuxkm_lkcapi_register(void)
#endif #endif
#ifdef LINUXKM_LKCAPI_REGISTER_ECDSA #ifdef LINUXKM_LKCAPI_REGISTER_ECDSA
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \ #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \
defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \ defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \
defined(CONFIG_CRYPTO_MANAGER) && \ defined(CONFIG_CRYPTO_MANAGER) && \
@@ -473,30 +536,43 @@ static int linuxkm_lkcapi_register(void)
* ecdsa was not recognized as fips_allowed before linux v6.3 * ecdsa was not recognized as fips_allowed before linux v6.3
* in kernel crypto/testmgr.c. * in kernel crypto/testmgr.c.
*/ */
fips_enabled = 0; #if defined(LINUXKM_ECC192)
#endif REGISTER_ALG_OPTIONAL(ecdsa_nist_p192, akcipher,
linuxkm_test_ecdsa_nist_p192);
#endif /* LINUXKM_ECC192 */
#if defined(LINUXKM_ECC192) REGISTER_ALG_OPTIONAL(ecdsa_nist_p256, akcipher,
REGISTER_ALG(ecdsa_nist_p192, akcipher, linuxkm_test_ecdsa_nist_p256);
linuxkm_test_ecdsa_nist_p192);
#endif /* LINUXKM_ECC192 */
REGISTER_ALG(ecdsa_nist_p256, akcipher, REGISTER_ALG_OPTIONAL(ecdsa_nist_p384, akcipher,
linuxkm_test_ecdsa_nist_p256); linuxkm_test_ecdsa_nist_p384);
REGISTER_ALG(ecdsa_nist_p384, akcipher, #if defined(HAVE_ECC521)
linuxkm_test_ecdsa_nist_p384); REGISTER_ALG_OPTIONAL(ecdsa_nist_p521, akcipher,
linuxkm_test_ecdsa_nist_p521);
#endif /* HAVE_ECC521 */
#else
#if defined(LINUXKM_ECC192)
REGISTER_ALG(ecdsa_nist_p192, akcipher,
linuxkm_test_ecdsa_nist_p192);
#endif /* LINUXKM_ECC192 */
#if defined(HAVE_ECC521) REGISTER_ALG(ecdsa_nist_p256, akcipher,
REGISTER_ALG(ecdsa_nist_p521, akcipher, linuxkm_test_ecdsa_nist_p256);
linuxkm_test_ecdsa_nist_p521);
#endif /* HAVE_ECC521 */ REGISTER_ALG(ecdsa_nist_p384, akcipher,
linuxkm_test_ecdsa_nist_p384);
#if defined(HAVE_ECC521)
REGISTER_ALG(ecdsa_nist_p521, akcipher,
linuxkm_test_ecdsa_nist_p521);
#endif /* HAVE_ECC521 */
#endif /* if linux < 6.3 && HAVE_FIPS && etc.. */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \ #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \
defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \ defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \
defined(CONFIG_CRYPTO_MANAGER) && \ defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
fips_enabled = 1;
#endif #endif
#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */ #endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
@@ -514,33 +590,24 @@ static int linuxkm_lkcapi_register(void)
* Given the above, and given we're not actually relying on the crypto * Given the above, and given we're not actually relying on the crypto
* manager for FIPS self tests, and given the FIPS ECDH implementation passes * manager for FIPS self tests, and given the FIPS ECDH implementation passes
* the non-FIPS ECDH crypto manager tests, the pragmatic solution we settle * the non-FIPS ECDH crypto manager tests, the pragmatic solution we settle
* on here for ECDH is to always clear fips_enabled in target kernels that * on here is for ECDH loading to be optional when fips and fips tests are
* have it. * enabled. Failures because of !fips_allowed are skipped over.
*/ */
#if defined(CONFIG_CRYPTO_FIPS) && \ #if defined(CONFIG_CRYPTO_FIPS) && \
defined(CONFIG_CRYPTO_MANAGER) && \ defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
fips_enabled = 0; #if defined(LINUXKM_ECC192)
#endif REGISTER_ALG_OPTIONAL(ecdh_nist_p192, kpp, linuxkm_test_ecdh_nist_p192);
#endif /* LINUXKM_ECC192 */
#if defined(LINUXKM_ECC192) REGISTER_ALG_OPTIONAL(ecdh_nist_p256, kpp, linuxkm_test_ecdh_nist_p256);
REGISTER_ALG(ecdh_nist_p192, kpp, REGISTER_ALG_OPTIONAL(ecdh_nist_p384, kpp, linuxkm_test_ecdh_nist_p384);
linuxkm_test_ecdh_nist_p192); #else
#endif /* LINUXKM_ECC192 */ #if defined(LINUXKM_ECC192)
REGISTER_ALG(ecdh_nist_p192, kpp, linuxkm_test_ecdh_nist_p192);
REGISTER_ALG(ecdh_nist_p256, kpp, #endif /* LINUXKM_ECC192 */
linuxkm_test_ecdh_nist_p256); REGISTER_ALG(ecdh_nist_p256, kpp, linuxkm_test_ecdh_nist_p256);
REGISTER_ALG(ecdh_nist_p384, kpp, linuxkm_test_ecdh_nist_p384);
REGISTER_ALG(ecdh_nist_p384, kpp, #endif /* CONFIG_CRYPTO_FIPS && etc.. */
linuxkm_test_ecdh_nist_p384);
#if defined(CONFIG_CRYPTO_FIPS) && \
defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
fips_enabled = 1;
#endif
#endif /* LINUXKM_LKCAPI_REGISTER_ECDH */ #endif /* LINUXKM_LKCAPI_REGISTER_ECDH */
#ifdef LINUXKM_LKCAPI_REGISTER_RSA #ifdef LINUXKM_LKCAPI_REGISTER_RSA
@@ -625,12 +692,8 @@ static int linuxkm_lkcapi_register(void)
#endif /* LINUXKM_LKCAPI_REGISTER_DH */ #endif /* LINUXKM_LKCAPI_REGISTER_DH */
#undef REGISTER_ALG #undef REGISTER_ALG
#undef REGISTER_ALG_OPTIONAL
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
if (enabled_fips)
fips_enabled = 0;
#endif
#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
disable_setkey_warnings = 0; disable_setkey_warnings = 0;
#endif #endif