|
Nicolai Stange |
267194 |
From 3c65e45d809ab7d58fd87dfbaef307992ae7d403 Mon Sep 17 00:00:00 2001
|
|
Nicolai Stange |
267194 |
From: Nicolai Stange <nstange@suse.de>
|
|
Nicolai Stange |
267194 |
Date: Sun, 28 Nov 2021 20:45:56 +0100
|
|
Nicolai Stange |
267194 |
Subject: [PATCH 1/2] crypto: implement downstream solution for disabling
|
|
Nicolai Stange |
267194 |
drivers in FIPS mode
|
|
Nicolai Stange |
3bec27 |
References: jsc#SLE-21132,bsc#1191270,bsc#1193976
|
|
Nicolai Stange |
267194 |
Patch-mainline: Never, downstream solution to block unapproved crypto drivers
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
Non-verified crypto implementations from drivers/crypto must not be used in
|
|
Nicolai Stange |
267194 |
FIPS mode and this has to be enforced from the crypto API.
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
The most reasonable way of achieving this is to make the testmgr to force
|
|
Nicolai Stange |
267194 |
these algorithm instances' tests to fail: the crypto API's lookup
|
|
Nicolai Stange |
267194 |
primitives only return algorithm implementations which have successfully
|
|
Nicolai Stange |
267194 |
completed their associated tests. From the resp. driver's perspective, the
|
|
Nicolai Stange |
267194 |
algorithm registrations would still succeed, so no errors would get thrown
|
|
Nicolai Stange |
267194 |
e.g. during boot and potential services outside the scope of FIPS could
|
|
Nicolai Stange |
267194 |
still be provided.
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
Implement the new suse_fips_is_driver_unapproved() for searching a given
|
|
Nicolai Stange |
267194 |
driver name on a to-be-populated list of unapproved implementations to be
|
|
Nicolai Stange |
267194 |
rejected in FIPS mode. Make alg_test() query it in FIPS mode if the
|
|
Nicolai Stange |
267194 |
algorithm has not been determined to be disallowed by some other means
|
|
Nicolai Stange |
267194 |
already, i.e. if no matching test with ->fips_allowed == 0 has been found.
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
Now that it's more common to have driver algorithm instances in failed
|
|
Nicolai Stange |
267194 |
state potentially aliasing with approved implementations around, there's
|
|
Nicolai Stange |
267194 |
one subtlety in the crypto API's lookup code which needs to get addressed.
|
|
Nicolai Stange |
267194 |
A lot of those crypto drivers register "fused" implementations of certain
|
|
Nicolai Stange |
267194 |
algorithm constructions, which would otherwise get served by some generic
|
|
Nicolai Stange |
267194 |
templates. However, these instances are kept on the global algorithms list
|
|
Nicolai Stange |
267194 |
and crypto_alg_lookup() would return -ELIBBAD upon encountering a matching
|
|
Nicolai Stange |
267194 |
such one in forced-fail state, c.f. commit eb02c38f0197 ("crypto: api -
|
|
Nicolai Stange |
267194 |
Keep failed instances alive"). This would then subsequently prevent the
|
|
Nicolai Stange |
267194 |
calling code from attempting to construct an (approved) instantiation of
|
|
Nicolai Stange |
267194 |
the generic templates. Make crypto_alg_lookup()'s caller,
|
|
Nicolai Stange |
267194 |
crypto_larval_lookup(), pass on the -ELIBBAD only if it had been caused by
|
|
Nicolai Stange |
267194 |
some generic template instantiation in failed state, i.e. by a real test
|
|
Nicolai Stange |
267194 |
failure rather by than some unapproved driver.
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
Finally, due to the asynchronous nature of the testmgr execution, the
|
|
Nicolai Stange |
267194 |
algorithm registration code always keeps a placeholder test larval on the
|
|
Nicolai Stange |
267194 |
global algorithm list until alg_test() eventually gets to run and has a
|
|
Nicolai Stange |
267194 |
chance to force-fail the test for unapproved drivers. Until that has
|
|
Nicolai Stange |
267194 |
happened, any matching request coming in through crypto_alg_mod_lookup()
|
|
Nicolai Stange |
267194 |
would end up waiting on this test larval in crypto_larval_wait().
|
|
Nicolai Stange |
267194 |
crypto_larval_wait() would return -EAGAIN once the test has been
|
|
Nicolai Stange |
267194 |
force-failed asynchronously and the whole lookup would then subsequently
|
|
Nicolai Stange |
267194 |
fail. As failing test larvals are much more common in FIPS mode now, make
|
|
Nicolai Stange |
267194 |
crypto_larval_lookup() to retry the whole operation when any of its two
|
|
Nicolai Stange |
267194 |
descendant crypto_larval_wait() invocations return -EAGAIN.
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
Signed-off-by: Nicolai Stange <nstange@suse.de>
|
|
Nicolai Stange |
267194 |
---
|
|
Nicolai Stange |
3bec27 |
crypto/api.c | 46 +++++++++++++++++++++++++++
|
|
Nicolai Stange |
267194 |
crypto/suse_fips_unapproved_drivers.h | 1
|
|
Nicolai Stange |
592d0e |
crypto/testmgr.c | 57 ++++++++++++++++++++++++++++++++++
|
|
Nicolai Stange |
592d0e |
3 files changed, 104 insertions(+)
|
|
Nicolai Stange |
267194 |
create mode 100644 crypto/suse_fips_unapproved_drivers.h
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
--- a/crypto/api.c
|
|
Nicolai Stange |
267194 |
+++ b/crypto/api.c
|
|
Nicolai Stange |
267194 |
@@ -20,6 +20,7 @@
|
|
Nicolai Stange |
267194 |
#include <linux/slab.h>
|
|
Nicolai Stange |
267194 |
#include <linux/string.h>
|
|
Nicolai Stange |
267194 |
#include <linux/completion.h>
|
|
Nicolai Stange |
267194 |
+#include <linux/fips.h>
|
|
Nicolai Stange |
267194 |
#include "internal.h"
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
LIST_HEAD(crypto_alg_list);
|
|
Nicolai Stange |
3bec27 |
@@ -128,6 +129,15 @@ static struct crypto_alg *crypto_larval_
|
|
Nicolai Stange |
3bec27 |
struct crypto_alg *alg;
|
|
Nicolai Stange |
3bec27 |
struct crypto_larval *larval;
|
|
Nicolai Stange |
3bec27 |
|
|
Nicolai Stange |
3bec27 |
+ if (fips_enabled && !((type | mask) & CRYPTO_ALG_TESTED)) {
|
|
Nicolai Stange |
3bec27 |
+ /*
|
|
Nicolai Stange |
3bec27 |
+ * Make sure the __crypto_alg_lookup() below won't return
|
|
Nicolai Stange |
3bec27 |
+ * any untested algorithm.
|
|
Nicolai Stange |
3bec27 |
+ */
|
|
Nicolai Stange |
3bec27 |
+ mask |= CRYPTO_ALG_TESTED;
|
|
Nicolai Stange |
3bec27 |
+ type |= CRYPTO_ALG_TESTED;
|
|
Nicolai Stange |
3bec27 |
+ }
|
|
Nicolai Stange |
3bec27 |
+
|
|
Nicolai Stange |
3bec27 |
larval = crypto_larval_alloc(name, type, mask);
|
|
Nicolai Stange |
3bec27 |
if (IS_ERR(larval))
|
|
Nicolai Stange |
3bec27 |
return ERR_CAST(larval);
|
|
Nicolai Stange |
592d0e |
@@ -240,6 +250,7 @@ static struct crypto_alg *crypto_larval_
|
|
Nicolai Stange |
267194 |
type &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
|
|
Nicolai Stange |
267194 |
mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
+again:
|
|
Nicolai Stange |
267194 |
alg = crypto_alg_lookup(name, type, mask);
|
|
Nicolai Stange |
267194 |
if (!alg && !(mask & CRYPTO_NOLOAD)) {
|
|
Nicolai Stange |
267194 |
request_module("crypto-%s", name);
|
|
Nicolai Stange |
592d0e |
@@ -251,11 +262,46 @@ static struct crypto_alg *crypto_larval_
|
|
Nicolai Stange |
267194 |
alg = crypto_alg_lookup(name, type, mask);
|
|
Nicolai Stange |
267194 |
}
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
+ /*
|
|
Nicolai Stange |
267194 |
+ * As a downstream solution, unapproved crypto driver
|
|
Nicolai Stange |
267194 |
+ * instances' tests are forced to fail in FIPS mode from
|
|
Nicolai Stange |
267194 |
+ * testmgr. A lot of those register "fused" implementations of
|
|
Nicolai Stange |
267194 |
+ * certain algorithm constructions, which would otherwise get
|
|
Nicolai Stange |
267194 |
+ * served by some generic templates. However, those driver
|
|
Nicolai Stange |
267194 |
+ * instances are kept on the global algorithms list in failed
|
|
Nicolai Stange |
267194 |
+ * state and crypto_alg_lookup() would return -ELIBBAD upon
|
|
Nicolai Stange |
267194 |
+ * encountering a matching such one. In order to still allow
|
|
Nicolai Stange |
267194 |
+ * the generic template implementations to serve the request,
|
|
Nicolai Stange |
267194 |
+ * check if the the ELIBBAD had been coming from a matching
|
|
Nicolai Stange |
267194 |
+ * template instantiation in failed state and ignore it if
|
|
Nicolai Stange |
267194 |
+ * not.
|
|
Nicolai Stange |
267194 |
+ */
|
|
Nicolai Stange |
267194 |
+ if (fips_enabled && IS_ERR(alg) && PTR_ERR(alg) == -ELIBBAD &&
|
|
Nicolai Stange |
267194 |
+ strchr(name, '(')) {
|
|
Nicolai Stange |
267194 |
+ alg = crypto_alg_lookup(name,
|
|
Nicolai Stange |
267194 |
+ type | CRYPTO_ALG_INSTANCE,
|
|
Nicolai Stange |
267194 |
+ mask | CRYPTO_ALG_INSTANCE);
|
|
Nicolai Stange |
267194 |
+ }
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
if (!IS_ERR_OR_NULL(alg) && crypto_is_larval(alg))
|
|
Nicolai Stange |
267194 |
alg = crypto_larval_wait(alg);
|
|
Nicolai Stange |
267194 |
else if (!alg)
|
|
Nicolai Stange |
267194 |
alg = crypto_larval_add(name, type, mask);
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
+ /*
|
|
Nicolai Stange |
267194 |
+ * As outlined above, unapproved crypto driver instances'
|
|
Nicolai Stange |
267194 |
+ * tests are forced to fail in FIPS mode from testmgr. If
|
|
Nicolai Stange |
267194 |
+ * crypto_larval_wait() returned -EAGAIN, chances are the wait
|
|
Nicolai Stange |
267194 |
+ * had been on such a driver instance's failed test larval.
|
|
Nicolai Stange |
267194 |
+ * Retry the search in this case.
|
|
Nicolai Stange |
267194 |
+ */
|
|
Nicolai Stange |
267194 |
+ if (fips_enabled && IS_ERR(alg) && PTR_ERR(alg) == -EAGAIN) {
|
|
Nicolai Stange |
3bec27 |
+ if (fatal_signal_pending(current))
|
|
Nicolai Stange |
3bec27 |
+ return ERR_PTR(-EINTR);
|
|
Nicolai Stange |
267194 |
+ cond_resched();
|
|
Nicolai Stange |
267194 |
+ goto again;
|
|
Nicolai Stange |
267194 |
+ }
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
return alg;
|
|
Nicolai Stange |
267194 |
}
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
--- /dev/null
|
|
Nicolai Stange |
267194 |
+++ b/crypto/suse_fips_unapproved_drivers.h
|
|
Nicolai Stange |
267194 |
@@ -0,0 +1 @@
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
--- a/crypto/testmgr.c
|
|
Nicolai Stange |
267194 |
+++ b/crypto/testmgr.c
|
|
Nicolai Stange |
592d0e |
@@ -5559,6 +5559,50 @@ static void testmgr_onetime_init(void)
|
|
Nicolai Stange |
267194 |
#endif
|
|
Nicolai Stange |
267194 |
}
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
+#ifdef CONFIG_CRYPTO_FIPS
|
|
Nicolai Stange |
267194 |
+static bool suse_fips_is_driver_unapproved(const char *driver)
|
|
Nicolai Stange |
267194 |
+{
|
|
Nicolai Stange |
267194 |
+ /*
|
|
Nicolai Stange |
267194 |
+ * unapproved_drivers[] contains a sorted list of
|
|
Nicolai Stange |
267194 |
+ * cra_driver_name's to reject in FIPS mode.
|
|
Nicolai Stange |
267194 |
+ */
|
|
Nicolai Stange |
267194 |
+ static const char *unapproved_drivers[] = {
|
|
Nicolai Stange |
267194 |
+#include "suse_fips_unapproved_drivers.h"
|
|
Nicolai Stange |
267194 |
+ };
|
|
Nicolai Stange |
267194 |
+ int start = 0;
|
|
Nicolai Stange |
267194 |
+ int end = ARRAY_SIZE(unapproved_drivers);
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ if (!fips_enabled)
|
|
Nicolai Stange |
267194 |
+ return false;
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ while (start < end) {
|
|
Nicolai Stange |
267194 |
+ int i = (start + end) / 2;
|
|
Nicolai Stange |
267194 |
+ int diff = strcmp(unapproved_drivers[i], driver);
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ if (diff > 0) {
|
|
Nicolai Stange |
267194 |
+ end = i;
|
|
Nicolai Stange |
267194 |
+ continue;
|
|
Nicolai Stange |
267194 |
+ }
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ if (diff < 0) {
|
|
Nicolai Stange |
267194 |
+ start = i + 1;
|
|
Nicolai Stange |
267194 |
+ continue;
|
|
Nicolai Stange |
267194 |
+ }
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ pr_info("alg: disabling driver '%s' in FIPS mode\n", driver);
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ return true;
|
|
Nicolai Stange |
267194 |
+ }
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
+ return false;
|
|
Nicolai Stange |
267194 |
+}
|
|
Nicolai Stange |
267194 |
+#else /* !CONFIG_CRYPTO_FIPS */
|
|
Nicolai Stange |
267194 |
+static bool suse_fips_is_driver_unapproved(const char *driver)
|
|
Nicolai Stange |
267194 |
+{
|
|
Nicolai Stange |
267194 |
+ return false;
|
|
Nicolai Stange |
267194 |
+}
|
|
Nicolai Stange |
267194 |
+#endif /* CONFIG_CRYPTO_FIPS */
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
static int alg_find_test(const char *alg)
|
|
Nicolai Stange |
267194 |
{
|
|
Nicolai Stange |
267194 |
int start = 0;
|
|
Nicolai Stange |
592d0e |
@@ -5615,6 +5659,9 @@ int alg_test(const char *driver, const c
|
|
Nicolai Stange |
592d0e |
if (i < 0)
|
|
Nicolai Stange |
592d0e |
goto notest;
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
592d0e |
+ if (suse_fips_is_driver_unapproved(driver))
|
|
Nicolai Stange |
592d0e |
+ return -EINVAL;
|
|
Nicolai Stange |
592d0e |
+
|
|
Nicolai Stange |
267194 |
if (fips_enabled && !alg_test_descs[i].fips_allowed)
|
|
Nicolai Stange |
267194 |
goto non_fips_alg;
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
592d0e |
@@ -5630,6 +5677,8 @@ int alg_test(const char *driver, const c
|
|
Nicolai Stange |
592d0e |
if (fips_enabled) {
|
|
Nicolai Stange |
592d0e |
if (j >= 0 && !alg_test_descs[j].fips_allowed)
|
|
Nicolai Stange |
592d0e |
return -EINVAL;
|
|
Nicolai Stange |
592d0e |
+ else if (suse_fips_is_driver_unapproved(driver))
|
|
Nicolai Stange |
592d0e |
+ return -EINVAL;
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
592d0e |
if (i >= 0 && !alg_test_descs[i].fips_allowed)
|
|
Nicolai Stange |
592d0e |
goto non_fips_alg;
|
|
Nicolai Stange |
592d0e |
@@ -5662,6 +5711,14 @@ test_done:
|
|
Nicolai Stange |
267194 |
return rc;
|
|
Nicolai Stange |
267194 |
|
|
Nicolai Stange |
267194 |
notest:
|
|
Nicolai Stange |
267194 |
+ /*
|
|
Nicolai Stange |
267194 |
+ * Unapproved drivers can register constructions for which
|
|
Nicolai Stange |
267194 |
+ * there is no matching test with ->fips_allowed == 0, check
|
|
Nicolai Stange |
267194 |
+ * for this.
|
|
Nicolai Stange |
267194 |
+ */
|
|
Nicolai Stange |
267194 |
+ if (suse_fips_is_driver_unapproved(driver))
|
|
Nicolai Stange |
592d0e |
+ return -EINVAL;
|
|
Nicolai Stange |
267194 |
+
|
|
Nicolai Stange |
267194 |
printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
|
|
Nicolai Stange |
592d0e |
|
|
Nicolai Stange |
592d0e |
if (type & CRYPTO_ALG_FIPS_INTERNAL)
|