diff --git a/crypto/fips140-module.c b/crypto/fips140-module.c index 951fc8ea8255..79b09b070463 100644 --- a/crypto/fips140-module.c +++ b/crypto/fips140-module.c @@ -14,6 +14,8 @@ * don't need to meet these requirements. */ +#undef __DISABLE_EXPORTS + #include #include #include @@ -86,34 +88,37 @@ const u8 *__rodata_start = &__fips140_rodata_start; * When adding a new algorithm here, make sure to consider whether it needs a * self-test added to fips140_selftests[] as well. */ -static const char * const fips140_algorithms[] __initconst = { - "aes", +static const struct { + const char *name; + bool approved; +} fips140_algs_to_replace[] = { + {"aes", true}, - "cmac(aes)", - "ecb(aes)", + {"cmac(aes)", true}, + {"ecb(aes)", true}, - "cbc(aes)", - "cts(cbc(aes))", - "ctr(aes)", - "xts(aes)", - "gcm(aes)", + {"cbc(aes)", true}, + {"cts(cbc(aes))", true}, + {"ctr(aes)", true}, + {"xts(aes)", true}, + {"gcm(aes)", false}, - "hmac(sha1)", - "hmac(sha224)", - "hmac(sha256)", - "hmac(sha384)", - "hmac(sha512)", - "sha1", - "sha224", - "sha256", - "sha384", - "sha512", + {"hmac(sha1)", true}, + {"hmac(sha224)", true}, + {"hmac(sha256)", true}, + {"hmac(sha384)", true}, + {"hmac(sha512)", true}, + {"sha1", true}, + {"sha224", true}, + {"sha256", true}, + {"sha384", true}, + {"sha512", true}, - "stdrng", - "jitterentropy_rng", + {"stdrng", true}, + {"jitterentropy_rng", false}, }; -static bool __init is_fips140_algo(struct crypto_alg *alg) +static bool __init fips140_should_unregister_alg(struct crypto_alg *alg) { int i; @@ -124,12 +129,48 @@ static bool __init is_fips140_algo(struct crypto_alg *alg) if (alg->cra_flags & CRYPTO_ALG_ASYNC) return false; - for (i = 0; i < ARRAY_SIZE(fips140_algorithms); i++) - if (!strcmp(alg->cra_name, fips140_algorithms[i])) + for (i = 0; i < ARRAY_SIZE(fips140_algs_to_replace); i++) { + if (!strcmp(alg->cra_name, fips140_algs_to_replace[i].name)) return true; + } return false; } +/* + * FIPS 140-3 service indicators. FIPS 140-3 requires that all services + * "provide an indicator when the service utilises an approved cryptographic + * algorithm, security function or process in an approved manner". What this + * means is very debatable, even with the help of the FIPS 140-3 Implementation + * Guidance document. However, it was decided that a function that takes in an + * algorithm name and returns whether that algorithm is approved or not will + * meet this requirement. Note, this relies on some properties of the module: + * + * - The module doesn't distinguish between "services" and "algorithms"; its + * services are simply its algorithms. + * + * - The status of an approved algorithm is never non-approved, since (a) the + * module doesn't support operating in a non-approved mode, such as a mode + * where the self-tests are skipped; (b) there are no cases where the module + * supports non-approved settings for approved algorithms, e.g. + * non-approved key sizes; and (c) this function isn't available to be + * called until the module_init function has completed, so it's guaranteed + * that the self-tests and integrity check have already passed. + * + * - The module does support some non-approved algorithms, so a single static + * indicator ("return true;") would not be acceptable. + */ +bool fips140_is_approved_service(const char *name) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(fips140_algs_to_replace); i++) { + if (!strcmp(name, fips140_algs_to_replace[i].name)) + return fips140_algs_to_replace[i].approved; + } + return false; +} +EXPORT_SYMBOL_GPL(fips140_is_approved_service); + static LIST_HEAD(existing_live_algos); /* @@ -180,7 +221,7 @@ static void __init unregister_existing_fips140_algos(void) * that new users won't use them. */ list_for_each_entry_safe(alg, tmp, &crypto_alg_list, cra_list) { - if (!is_fips140_algo(alg)) + if (!fips140_should_unregister_alg(alg)) continue; if (refcount_read(&alg->cra_refcnt) == 1) { /* diff --git a/crypto/fips140-module.h b/crypto/fips140-module.h index f33580cf7bf8..a01d6c5c1049 100644 --- a/crypto/fips140-module.h +++ b/crypto/fips140-module.h @@ -21,4 +21,6 @@ extern struct task_struct *fips140_init_thread; bool __init __must_check fips140_run_selftests(void); +bool fips140_is_approved_service(const char *name); + #endif /* _CRYPTO_FIPS140_MODULE_H */