[PATCH RFC 016/104] crypto: alg - add CRYPTO_ALG_FIPS_PROVIDED flag

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Use a new flag to record whether a particular algorithm is provided by
a standalone FIPS 140 module.

Note: This does not mean the algorithm is "FIPS approved" or even "FIPS
allowed" -- it simply means the algorithm is implemented within the FIPS
module.

Signed-off-by: Vegard Nossum <vegard.nossum@xxxxxxxxxx>
---
 crypto/algapi.c        | 30 ++++++++++++++++++++++++++++++
 crypto/testmgr.c       | 22 +++++++++++++++-------
 include/linux/crypto.h |  8 ++++++++
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/crypto/algapi.c b/crypto/algapi.c
index 54b8d4acd651..29076797a938 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -450,6 +450,9 @@ int crypto_register_alg(struct crypto_alg *alg)
 	if (err)
 		return err;
 
+	/* Blatant API misuse */
+	BUG_ON(alg->cra_flags & CRYPTO_ALG_FIPS_PROVIDED);
+
 	if (alg->cra_flags & CRYPTO_ALG_DUP_FIRST &&
 	    !WARN_ON_ONCE(alg->cra_destroy)) {
 		unsigned int algsize = alg->cra_type->algsize;
@@ -463,6 +466,13 @@ int crypto_register_alg(struct crypto_alg *alg)
 		alg->cra_destroy = crypto_free_alg;
 	}
 
+#ifdef FIPS_MODULE
+	if (alg->cra_module == THIS_MODULE) {
+		alg->cra_flags |= CRYPTO_ALG_FIPS_PROVIDED;
+		alg->cra_priority |= 4096;
+	}
+#endif
+
 	down_write(&crypto_alg_sem);
 	larval = __crypto_register_alg(alg, &algs_to_put);
 	if (!IS_ERR_OR_NULL(larval)) {
@@ -666,6 +676,9 @@ int crypto_register_instance(struct crypto_template *tmpl,
 	struct crypto_larval *larval;
 	struct crypto_spawn *spawn;
 	u32 fips_internal = 0;
+#ifdef FIPS_MODULE
+	u32 fips_provided = ~0;
+#endif
 	LIST_HEAD(algs_to_put);
 	int err;
 
@@ -673,6 +686,9 @@ int crypto_register_instance(struct crypto_template *tmpl,
 	if (err)
 		return err;
 
+	/* Blatant API misuse */
+	BUG_ON(inst->alg.cra_flags & CRYPTO_ALG_FIPS_PROVIDED);
+
 	inst->alg.cra_module = tmpl->module;
 	inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
 	inst->alg.cra_destroy = crypto_destroy_instance;
@@ -692,6 +708,13 @@ int crypto_register_instance(struct crypto_template *tmpl,
 
 		fips_internal |= spawn->alg->cra_flags;
 
+#ifdef FIPS_MODULE
+		if (spawn->alg->cra_module == THIS_MODULE)
+			fips_provided &= spawn->alg->cra_flags;
+		else
+			fips_provided = 0;
+#endif
+
 		crypto_mod_put(spawn->alg);
 
 		spawn = next;
@@ -699,6 +722,13 @@ int crypto_register_instance(struct crypto_template *tmpl,
 
 	inst->alg.cra_flags |= (fips_internal & CRYPTO_ALG_FIPS_INTERNAL);
 
+#ifdef FIPS_MODULE
+	if (tmpl->module == THIS_MODULE && (fips_provided & CRYPTO_ALG_FIPS_PROVIDED)) {
+		inst->alg.cra_flags |= CRYPTO_ALG_FIPS_PROVIDED;
+		inst->alg.cra_priority |= 4096;
+	}
+#endif
+
 	larval = __crypto_register_alg(&inst->alg, &algs_to_put);
 	if (IS_ERR(larval))
 		goto unlock;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 25aadf5b6690..1dfd37761a4f 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5771,15 +5771,23 @@ static int alg_fips_disabled(const char *driver, const char *alg)
 	return -ECANCELED;
 }
 
-static int alg_test_fips_disabled(const struct alg_test_desc *desc)
+static int alg_test_fips_disabled(const struct crypto_alg *alg, const struct alg_test_desc *desc)
 {
 	if (!fips_enabled)
 		return 0;
 
 	/*
-	 * Only allow FIPS-allowed algorithms to be tested.
+	 * If the algorithm is completely provided by the FIPS module
+	 * we still require it to be allowed accoding to our test table.
 	 */
-	return !(desc->fips_allowed & FIPS_ALLOWED);
+	if (alg->cra_flags & CRYPTO_ALG_FIPS_PROVIDED)
+		return !(desc->fips_allowed & FIPS_ALLOWED);
+
+	/*
+	 * If the algorithm is not provided by the FIPS module, then
+	 * it must be FIPS_NON_CRYPTOGRAPHIC.
+	 */
+	return !(desc->fips_allowed & FIPS_NON_CRYPTOGRAPHIC);
 }
 
 int alg_test(struct crypto_alg *alg, const char *driver, const char *name, u32 type, u32 mask)
@@ -5806,7 +5814,7 @@ int alg_test(struct crypto_alg *alg, const char *driver, const char *name, u32 t
 		if (i < 0)
 			goto notest;
 
-		if (alg_test_fips_disabled(&alg_test_descs[i]))
+		if (alg_test_fips_disabled(alg, &alg_test_descs[i]))
 			goto non_fips_alg;
 
 		rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
@@ -5819,9 +5827,9 @@ int alg_test(struct crypto_alg *alg, const char *driver, const char *name, u32 t
 		goto notest;
 
 	if (fips_enabled) {
-		if (j >= 0 && alg_test_fips_disabled(&alg_test_descs[j]))
+		if (j >= 0 && alg_test_fips_disabled(alg, &alg_test_descs[j]))
 			return -EINVAL;
-		if (i >= 0 && alg_test_fips_disabled(&alg_test_descs[i]))
+		if (i >= 0 && alg_test_fips_disabled(alg, &alg_test_descs[i]))
 			goto non_fips_alg;
 	}
 
@@ -5865,7 +5873,7 @@ int alg_test(struct crypto_alg *alg, const char *driver, const char *name, u32 t
 		if (i < 0)
 			goto notest2;
 
-		if (alg_test_fips_disabled(&alg_test_descs[i]))
+		if (alg_test_fips_disabled(alg, &alg_test_descs[i]))
 			goto non_fips_alg;
 
 		rc = alg_test_skcipher(alg_test_descs + i, driver, type, mask);
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index a2137e19be7d..737e53a642d4 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -139,6 +139,14 @@
 /* Set if the algorithm cannot have a fallback (e.g., phmac). */
 #define CRYPTO_ALG_NO_FALLBACK		0x00080000
 
+/*
+ * The algorithm is provided by the FIPS module.
+ *
+ * NOTE: an algorithm can be provided by the FIPS module and not be
+ * approved, depending on the exact parameters like key size, etc.
+ */
+#define CRYPTO_ALG_FIPS_PROVIDED	0x00100000
+
 /* The high bits 0xff000000 are reserved for type-specific flags. */
 
 /*
-- 
2.39.3





[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]
  Powered by Linux