@@ -222,6 +222,11 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
222222static int linuxkm_lkcapi_register (void );
223223static int linuxkm_lkcapi_unregister (void );
224224
225+ #if defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
226+ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
227+ static int enabled_fips = 0 ;
228+ #endif
229+
225230static ssize_t install_algs_handler (struct kobject * kobj , struct kobj_attribute * attr ,
226231 const char * buf , size_t count )
227232{
@@ -261,6 +266,14 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut
261266 if (ret != 0 )
262267 return ret ;
263268
269+ #if defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
270+ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
271+ if (enabled_fips ) {
272+ pr_info ("wolfCrypt: restoring fips_enabled to off." );
273+ enabled_fips = fips_enabled = 0 ;
274+ }
275+ #endif
276+
264277 return count ;
265278}
266279
@@ -305,10 +318,6 @@ static int linuxkm_lkcapi_register(void)
305318{
306319 int ret = -1 ;
307320 int seen_err = 0 ;
308- #if defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
309- !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
310- int enabled_fips = 0 ;
311- #endif
312321
313322 ret = linuxkm_lkcapi_sysfs_install ();
314323 if (ret )
@@ -321,12 +330,14 @@ static int linuxkm_lkcapi_register(void)
321330 */
322331 disable_setkey_warnings = 1 ;
323332#endif
324- #if defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
325- !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
333+ #if !defined(LINUXKM_DONT_FORCE_FIPS_ENABLED ) && \
334+ defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
335+ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
326336 if (! fips_enabled ) {
327- /* temporarily assert system-wide FIPS status, to disable FIPS-forbidden
337+ /* assert system-wide FIPS status, to disable FIPS-forbidden
328338 * test vectors and fuzzing from the CRYPTO_MANAGER.
329339 */
340+ pr_info ("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module." );
330341 enabled_fips = fips_enabled = 1 ;
331342 }
332343#endif
@@ -365,6 +376,59 @@ static int linuxkm_lkcapi_register(void)
365376 } \
366377 } while (0)
367378
379+ #if defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
380+ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
381+ /* Same as above, but allow for option to skip problematic algs that are
382+ * not consistently labeled fips_allowed in crypto/testmgr.c, and hence
383+ * may be rejected by the kernel at runtime if is_fips is true. */
384+ #define REGISTER_ALG_OPTIONAL (alg , alg_class , tester ) do {\
385+ if (! alg ## _loaded) { \
386+ ret = (crypto_register_ ## alg_class)(&(alg)); \
387+ if (ret) { \
388+ if (fips_enabled && (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))) { \
389+ pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \
390+ (alg).base.cra_driver_name); \
391+ } \
392+ else { \
393+ seen_err = ret; \
394+ pr_err("ERROR: crypto_register_" #alg_class \
395+ " for %s failed " \
396+ "with return code %d.\n", \
397+ (alg).base.cra_driver_name, ret); \
398+ } \
399+ } else { \
400+ ret = (tester()); \
401+ if (ret) { \
402+ if (fips_enabled && (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))) { \
403+ pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \
404+ (alg).base.cra_driver_name); \
405+ } \
406+ else { \
407+ seen_err = -EINVAL; \
408+ pr_err("ERROR: wolfCrypt self-test for %s failed " \
409+ "with return code %d.\n", \
410+ (alg).base.cra_driver_name, ret); \
411+ } \
412+ (crypto_unregister_ ## alg_class)(&(alg)); \
413+ if (! (alg.base.cra_flags & CRYPTO_ALG_DEAD)) { \
414+ pr_err("ERROR: alg %s not _DEAD " \
415+ "after crypto_unregister_%s -- " \
416+ "marking as loaded despite test failure.", \
417+ (alg).base.cra_driver_name, \
418+ #alg_class); \
419+ alg ## _loaded = 1; \
420+ ++linuxkm_lkcapi_n_registered; \
421+ } \
422+ } else { \
423+ alg ## _loaded = 1; \
424+ ++linuxkm_lkcapi_n_registered; \
425+ WOLFKM_INSTALL_NOTICE(alg) \
426+ } \
427+ } \
428+ } \
429+ } while (0)
430+ #endif /* HAVE_FIPS && CONFIG_CRYPTO_MANAGER && etc.. */
431+
368432 /* We always register the derivative/composite algs first, to assure that
369433 * the kernel doesn't synthesize them dynamically from our primitives.
370434 */
@@ -464,7 +528,6 @@ static int linuxkm_lkcapi_register(void)
464528#endif
465529
466530#ifdef LINUXKM_LKCAPI_REGISTER_ECDSA
467-
468531 #if (LINUX_VERSION_CODE < KERNEL_VERSION (6 , 3 , 0 )) && \
469532 defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_FIPS ) && \
470533 defined(CONFIG_CRYPTO_MANAGER ) && \
@@ -473,30 +536,43 @@ static int linuxkm_lkcapi_register(void)
473536 * ecdsa was not recognized as fips_allowed before linux v6.3
474537 * in kernel crypto/testmgr.c.
475538 */
476- fips_enabled = 0 ;
477- #endif
539+ #if defined(LINUXKM_ECC192 )
540+ REGISTER_ALG_OPTIONAL (ecdsa_nist_p192 , akcipher ,
541+ linuxkm_test_ecdsa_nist_p192 );
542+ #endif /* LINUXKM_ECC192 */
478543
479- #if defined(LINUXKM_ECC192 )
480- REGISTER_ALG (ecdsa_nist_p192 , akcipher ,
481- linuxkm_test_ecdsa_nist_p192 );
482- #endif /* LINUXKM_ECC192 */
544+ REGISTER_ALG_OPTIONAL (ecdsa_nist_p256 , akcipher ,
545+ linuxkm_test_ecdsa_nist_p256 );
483546
484- REGISTER_ALG ( ecdsa_nist_p256 , akcipher ,
485- linuxkm_test_ecdsa_nist_p256 );
547+ REGISTER_ALG_OPTIONAL ( ecdsa_nist_p384 , akcipher ,
548+ linuxkm_test_ecdsa_nist_p384 );
486549
487- REGISTER_ALG (ecdsa_nist_p384 , akcipher ,
488- linuxkm_test_ecdsa_nist_p384 );
550+ #if defined(HAVE_ECC521 )
551+ REGISTER_ALG_OPTIONAL (ecdsa_nist_p521 , akcipher ,
552+ linuxkm_test_ecdsa_nist_p521 );
553+ #endif /* HAVE_ECC521 */
554+ #else
555+ #if defined(LINUXKM_ECC192 )
556+ REGISTER_ALG (ecdsa_nist_p192 , akcipher ,
557+ linuxkm_test_ecdsa_nist_p192 );
558+ #endif /* LINUXKM_ECC192 */
489559
490- #if defined(HAVE_ECC521 )
491- REGISTER_ALG (ecdsa_nist_p521 , akcipher ,
492- linuxkm_test_ecdsa_nist_p521 );
493- #endif /* HAVE_ECC521 */
560+ REGISTER_ALG (ecdsa_nist_p256 , akcipher ,
561+ linuxkm_test_ecdsa_nist_p256 );
562+
563+ REGISTER_ALG (ecdsa_nist_p384 , akcipher ,
564+ linuxkm_test_ecdsa_nist_p384 );
565+
566+ #if defined(HAVE_ECC521 )
567+ REGISTER_ALG (ecdsa_nist_p521 , akcipher ,
568+ linuxkm_test_ecdsa_nist_p521 );
569+ #endif /* HAVE_ECC521 */
570+ #endif /* if linux < 6.3 && HAVE_FIPS && etc.. */
494571
495572 #if (LINUX_VERSION_CODE < KERNEL_VERSION (6 , 3 , 0 )) && \
496573 defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_FIPS ) && \
497574 defined(CONFIG_CRYPTO_MANAGER ) && \
498575 !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
499- fips_enabled = 1 ;
500576 #endif
501577
502578#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
@@ -514,33 +590,24 @@ static int linuxkm_lkcapi_register(void)
514590 * Given the above, and given we're not actually relying on the crypto
515591 * manager for FIPS self tests, and given the FIPS ECDH implementation passes
516592 * the non-FIPS ECDH crypto manager tests, the pragmatic solution we settle
517- * on here for ECDH is to always clear fips_enabled in target kernels that
518- * have it .
593+ * on here is for ECDH loading to be optional when fips and fips tests are
594+ * enabled. Failures because of !fips_allowed are skipped over .
519595 */
520-
521- #if defined(CONFIG_CRYPTO_FIPS ) && \
522- defined(CONFIG_CRYPTO_MANAGER ) && \
523- !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
524- fips_enabled = 0 ;
525- #endif
526-
527- #if defined(LINUXKM_ECC192 )
528- REGISTER_ALG (ecdh_nist_p192 , kpp ,
529- linuxkm_test_ecdh_nist_p192 );
530- #endif /* LINUXKM_ECC192 */
531-
532- REGISTER_ALG (ecdh_nist_p256 , kpp ,
533- linuxkm_test_ecdh_nist_p256 );
534-
535- REGISTER_ALG (ecdh_nist_p384 , kpp ,
536- linuxkm_test_ecdh_nist_p384 );
537-
538596 #if defined(CONFIG_CRYPTO_FIPS ) && \
539597 defined(CONFIG_CRYPTO_MANAGER ) && \
540598 !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
541- fips_enabled = 1 ;
542- #endif
543-
599+ #if defined(LINUXKM_ECC192 )
600+ REGISTER_ALG_OPTIONAL (ecdh_nist_p192 , kpp , linuxkm_test_ecdh_nist_p192 );
601+ #endif /* LINUXKM_ECC192 */
602+ REGISTER_ALG_OPTIONAL (ecdh_nist_p256 , kpp , linuxkm_test_ecdh_nist_p256 );
603+ REGISTER_ALG_OPTIONAL (ecdh_nist_p384 , kpp , linuxkm_test_ecdh_nist_p384 );
604+ #else
605+ #if defined(LINUXKM_ECC192 )
606+ REGISTER_ALG (ecdh_nist_p192 , kpp , linuxkm_test_ecdh_nist_p192 );
607+ #endif /* LINUXKM_ECC192 */
608+ REGISTER_ALG (ecdh_nist_p256 , kpp , linuxkm_test_ecdh_nist_p256 );
609+ REGISTER_ALG (ecdh_nist_p384 , kpp , linuxkm_test_ecdh_nist_p384 );
610+ #endif /* CONFIG_CRYPTO_FIPS && etc.. */
544611#endif /* LINUXKM_LKCAPI_REGISTER_ECDH */
545612
546613#ifdef LINUXKM_LKCAPI_REGISTER_RSA
@@ -625,12 +692,8 @@ static int linuxkm_lkcapi_register(void)
625692#endif /* LINUXKM_LKCAPI_REGISTER_DH */
626693
627694#undef REGISTER_ALG
695+ #undef REGISTER_ALG_OPTIONAL
628696
629- #if defined(HAVE_FIPS ) && defined(CONFIG_CRYPTO_MANAGER ) && \
630- !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS )
631- if (enabled_fips )
632- fips_enabled = 0 ;
633- #endif
634697#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
635698 disable_setkey_warnings = 0 ;
636699#endif
0 commit comments