123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- #undef aead_register_instance
- #undef ahash_register_instance
- #undef crypto_register_aead
- #undef crypto_register_aeads
- #undef crypto_register_ahash
- #undef crypto_register_ahashes
- #undef crypto_register_alg
- #undef crypto_register_algs
- #undef crypto_register_rng
- #undef crypto_register_rngs
- #undef crypto_register_shash
- #undef crypto_register_shashes
- #undef crypto_register_skcipher
- #undef crypto_register_skciphers
- #undef shash_register_instance
- #undef skcipher_register_instance
- #include <crypto/algapi.h>
- #include <crypto/internal/aead.h>
- #include <crypto/internal/hash.h>
- #include <crypto/internal/rng.h>
- #include <crypto/internal/skcipher.h>
- #include <linux/xarray.h>
- #include "fips140-module.h"
- DECLARE_COMPLETION(fips140_tests_done);
- struct task_struct *fips140_init_thread;
- static DEFINE_XARRAY(fips140_init_func_map);
- static bool fips140_ready(void)
- {
- return completion_done(&fips140_tests_done);
- }
- static bool fips140_wait_until_ready(struct crypto_alg *alg)
- {
- if (fips140_ready())
- return true;
-
- if (current == fips140_init_thread)
- return false;
- pr_info("blocking user of %s until tests complete\n",
- alg->cra_driver_name);
- wait_for_completion(&fips140_tests_done);
- pr_info("tests done, allowing %s to proceed\n", alg->cra_driver_name);
- return true;
- }
- static int fips140_store_init_function(struct crypto_alg *alg, void *func)
- {
- void *ret;
-
- if (WARN_ON((unsigned long)func & 3))
- return -EINVAL;
- ret = xa_store(&fips140_init_func_map, (unsigned long)alg, func,
- GFP_KERNEL);
- return xa_err(ret);
- }
- static void *fips140_load_init_function(struct crypto_alg *alg)
- {
- return xa_load(&fips140_init_func_map, (unsigned long)alg);
- }
- static int fips140_alg_init_tfm(struct crypto_tfm *tfm)
- {
- struct crypto_alg *alg = tfm->__crt_alg;
- int (*cra_init)(struct crypto_tfm *tfm) =
- fips140_load_init_function(alg);
- if (fips140_wait_until_ready(alg))
- WRITE_ONCE(alg->cra_init, cra_init);
- return cra_init ? cra_init(tfm) : 0;
- }
- static int fips140_aead_init_tfm(struct crypto_aead *tfm)
- {
- struct aead_alg *alg = crypto_aead_alg(tfm);
- int (*init)(struct crypto_aead *tfm) =
- fips140_load_init_function(&alg->base);
- if (fips140_wait_until_ready(&alg->base))
- WRITE_ONCE(alg->init, init);
- return init ? init(tfm) : 0;
- }
- static int fips140_ahash_init_tfm(struct crypto_ahash *tfm)
- {
- struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
- struct ahash_alg *alg = container_of(halg, struct ahash_alg, halg);
- int (*init_tfm)(struct crypto_ahash *tfm) =
- fips140_load_init_function(&halg->base);
- if (fips140_wait_until_ready(&halg->base))
- WRITE_ONCE(alg->init_tfm, init_tfm);
- return init_tfm ? init_tfm(tfm) : 0;
- }
- static int fips140_shash_init_tfm(struct crypto_shash *tfm)
- {
- struct shash_alg *alg = crypto_shash_alg(tfm);
- int (*init_tfm)(struct crypto_shash *tfm) =
- fips140_load_init_function(&alg->base);
- if (fips140_wait_until_ready(&alg->base))
- WRITE_ONCE(alg->init_tfm, init_tfm);
- return init_tfm ? init_tfm(tfm) : 0;
- }
- static int fips140_skcipher_init_tfm(struct crypto_skcipher *tfm)
- {
- struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
- int (*init)(struct crypto_skcipher *tfm) =
- fips140_load_init_function(&alg->base);
- if (fips140_wait_until_ready(&alg->base))
- WRITE_ONCE(alg->init, init);
- return init ? init(tfm) : 0;
- }
- #define prepare_alg(alg, base_alg, field, wrapper_func) \
- ({ \
- int err = 0; \
- \
- if (!fips140_ready() && alg->field != wrapper_func) { \
- err = fips140_store_init_function(base_alg, alg->field);\
- if (err == 0) \
- alg->field = wrapper_func; \
- } \
- err; \
- })
- static int fips140_prepare_alg(struct crypto_alg *alg)
- {
-
- return prepare_alg(alg, alg, cra_init, fips140_alg_init_tfm);
- }
- static int fips140_prepare_aead_alg(struct aead_alg *alg)
- {
- return prepare_alg(alg, &alg->base, init, fips140_aead_init_tfm);
- }
- static int fips140_prepare_ahash_alg(struct ahash_alg *alg)
- {
- return prepare_alg(alg, &alg->halg.base, init_tfm,
- fips140_ahash_init_tfm);
- }
- static int fips140_prepare_rng_alg(struct rng_alg *alg)
- {
-
- return fips140_prepare_alg(&alg->base);
- }
- static int fips140_prepare_shash_alg(struct shash_alg *alg)
- {
- return prepare_alg(alg, &alg->base, init_tfm, fips140_shash_init_tfm);
- }
- static int fips140_prepare_skcipher_alg(struct skcipher_alg *alg)
- {
- return prepare_alg(alg, &alg->base, init, fips140_skcipher_init_tfm);
- }
- int fips140_crypto_register_alg(struct crypto_alg *alg)
- {
- return fips140_prepare_alg(alg) ?: crypto_register_alg(alg);
- }
- int fips140_crypto_register_aead(struct aead_alg *alg)
- {
- return fips140_prepare_aead_alg(alg) ?: crypto_register_aead(alg);
- }
- int fips140_crypto_register_ahash(struct ahash_alg *alg)
- {
- return fips140_prepare_ahash_alg(alg) ?: crypto_register_ahash(alg);
- }
- int fips140_crypto_register_rng(struct rng_alg *alg)
- {
- return fips140_prepare_rng_alg(alg) ?: crypto_register_rng(alg);
- }
- int fips140_crypto_register_shash(struct shash_alg *alg)
- {
- return fips140_prepare_shash_alg(alg) ?: crypto_register_shash(alg);
- }
- int fips140_crypto_register_skcipher(struct skcipher_alg *alg)
- {
- return fips140_prepare_skcipher_alg(alg) ?:
- crypto_register_skcipher(alg);
- }
- int fips140_aead_register_instance(struct crypto_template *tmpl,
- struct aead_instance *inst)
- {
- return fips140_prepare_aead_alg(&inst->alg) ?:
- aead_register_instance(tmpl, inst);
- }
- int fips140_ahash_register_instance(struct crypto_template *tmpl,
- struct ahash_instance *inst)
- {
- return fips140_prepare_ahash_alg(&inst->alg) ?:
- ahash_register_instance(tmpl, inst);
- }
- int fips140_shash_register_instance(struct crypto_template *tmpl,
- struct shash_instance *inst)
- {
- return fips140_prepare_shash_alg(&inst->alg) ?:
- shash_register_instance(tmpl, inst);
- }
- int fips140_skcipher_register_instance(struct crypto_template *tmpl,
- struct skcipher_instance *inst)
- {
- return fips140_prepare_skcipher_alg(&inst->alg) ?:
- skcipher_register_instance(tmpl, inst);
- }
- int fips140_crypto_register_algs(struct crypto_alg *algs, int count)
- {
- int i;
- int err;
- for (i = 0; i < count; i++) {
- err = fips140_prepare_alg(&algs[i]);
- if (err)
- return err;
- }
- return crypto_register_algs(algs, count);
- }
- int fips140_crypto_register_aeads(struct aead_alg *algs, int count)
- {
- int i;
- int err;
- for (i = 0; i < count; i++) {
- err = fips140_prepare_aead_alg(&algs[i]);
- if (err)
- return err;
- }
- return crypto_register_aeads(algs, count);
- }
- int fips140_crypto_register_ahashes(struct ahash_alg *algs, int count)
- {
- int i;
- int err;
- for (i = 0; i < count; i++) {
- err = fips140_prepare_ahash_alg(&algs[i]);
- if (err)
- return err;
- }
- return crypto_register_ahashes(algs, count);
- }
- int fips140_crypto_register_rngs(struct rng_alg *algs, int count)
- {
- int i;
- int err;
- for (i = 0; i < count; i++) {
- err = fips140_prepare_rng_alg(&algs[i]);
- if (err)
- return err;
- }
- return crypto_register_rngs(algs, count);
- }
- int fips140_crypto_register_shashes(struct shash_alg *algs, int count)
- {
- int i;
- int err;
- for (i = 0; i < count; i++) {
- err = fips140_prepare_shash_alg(&algs[i]);
- if (err)
- return err;
- }
- return crypto_register_shashes(algs, count);
- }
- int fips140_crypto_register_skciphers(struct skcipher_alg *algs, int count)
- {
- int i;
- int err;
- for (i = 0; i < count; i++) {
- err = fips140_prepare_skcipher_alg(&algs[i]);
- if (err)
- return err;
- }
- return crypto_register_skciphers(algs, count);
- }
|