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.nos...@oracle.com>
---
 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


Reply via email to