From: Herbert Xu <herbert@gondor.apana.org.au> Date: Wed, 27 Aug 2008 10:18:37 +1000 Subject: [CRYPTO] cryptomgr - Test ciphers using ECB Message-id: E1KY8k9-0002Hl-00@gondolin.me.apana.org.au O-Subject: [PATCH 15/19] crypto: cryptomgr - Test ciphers using ECB Bugzilla: 446522 RHEL5 bugzilla #446522 crypto: cryptomgr - Test ciphers using ECB As it is we only test ciphers when combined with a mode. That means users that do not invoke a mode of operations may get an untested cipher. This patch tests all ciphers using the ECB mode so that simple cipher users such as ansi-cprng are also protected. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> diff --git a/crypto/Makefile b/crypto/Makefile index 23e36b9..2e20c06 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o obj-$(CONFIG_CRYPTO_API) += crypto_api.o obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o obj-$(CONFIG_CRYPTO_MANAGER) += testmgr.o +obj-$(CONFIG_CRYPTO_MANAGER) += testmgr_cipher.o obj-$(CONFIG_CRYPTO_HMAC) += hmac_old.o obj-$(CONFIG_CRYPTO_NHMAC) += hmac.o obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o diff --git a/crypto/api.c b/crypto/api.c index aa3552f..43fb654 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -15,7 +15,7 @@ * */ -#include <linux/compiler.h> +#include <linux/completion.h> #include <linux/init.h> #include <linux/crypto.h> #include <linux/errno.h> @@ -30,6 +30,9 @@ LIST_HEAD(crypto_alg_list); DECLARE_RWSEM(crypto_alg_sem); +BLOCKING_NOTIFIER_HEAD(ocrypto_chain); +EXPORT_SYMBOL_GPL(ocrypto_chain); + static inline int crypto_alg_get(struct crypto_alg *alg) { return try_module_get(alg->cra_module); @@ -254,12 +257,35 @@ static inline int crypto_set_driver_name(struct crypto_alg *alg) return 0; } +static int ocrypto_probing_notify(unsigned long val, void *v) +{ + int ok; + + ok = blocking_notifier_call_chain(&ocrypto_chain, val, v); + if (ok == NOTIFY_DONE) { + request_module("testmgr_cipher"); + ok = blocking_notifier_call_chain(&ocrypto_chain, val, v); + } + + return ok; +} + +static DECLARE_COMPLETION(test_done); +static int test_err; + +void ocrypto_alg_tested(const char *name, int err) +{ + test_err = err; + complete(&test_done); +} +EXPORT_SYMBOL_GPL(ocrypto_alg_tested); + int crypto_register_alg(struct crypto_alg *alg) { int ret; struct crypto_alg *q; - char name[CRYPTO_MAX_ALG_NAME]; - DEFINE_MUTEX(test_lock); + struct crypto_cipher_test param; + static DEFINE_MUTEX(test_lock); if (alg->cra_alignmask & (alg->cra_alignmask + 1)) return -EINVAL; @@ -277,7 +303,8 @@ int crypto_register_alg(struct crypto_alg *alg) if (unlikely(ret)) return ret; - memcpy(name, alg->cra_name, CRYPTO_MAX_ALG_NAME); + param.alg = alg; + memcpy(param.name, alg->cra_name, CRYPTO_MAX_ALG_NAME); memcpy(alg->cra_name, "untested", sizeof("untested")); mutex_lock(&test_lock); @@ -299,8 +326,27 @@ out: goto out2; switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { + case CRYPTO_ALG_TYPE_CIPHER: + INIT_COMPLETION(test_done); + ret = ocrypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, ¶m); + if (ret != NOTIFY_STOP) { + if (unlikely(ret != NOTIFY_DONE)) { + WARN_ON(1); + ret = -EINVAL; + break; + } + ocrypto_alg_tested(alg->cra_driver_name, 0); + } + + ret = wait_for_completion_interruptible(&test_done); + if (unlikely(ret)) + WARN_ON(1); + else + ret = test_err; + break; + case CRYPTO_ALG_TYPE_DIGEST: - ret = digest_test(alg->cra_driver_name, name); + ret = digest_test(alg->cra_driver_name, param.name); break; } @@ -308,7 +354,7 @@ out: crypto_unregister_alg(alg); out2: - memcpy(alg->cra_name, name, CRYPTO_MAX_ALG_NAME); + memcpy(alg->cra_name, param.name, CRYPTO_MAX_ALG_NAME); mutex_unlock(&test_lock); return ret; } @@ -346,6 +392,18 @@ int crypto_alg_available(const char *name, u32 flags) return ret; } +int ocrypto_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&ocrypto_chain, nb); +} +EXPORT_SYMBOL_GPL(ocrypto_register_notifier); + +int ocrypto_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&ocrypto_chain, nb); +} +EXPORT_SYMBOL_GPL(ocrypto_unregister_notifier); + static int __init init_crypto(void) { printk(KERN_INFO "Initializing Cryptographic API\n"); diff --git a/crypto/internal.h b/crypto/internal.h index d942449..c7c68f4 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -19,12 +19,28 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/kernel.h> +#include <linux/notifier.h> #include <linux/rwsem.h> #include <linux/slab.h> #include <asm/kmap_types.h> +/* Crypto notification events. */ +enum { + CRYPTO_MSG_ALG_REQUEST, + CRYPTO_MSG_ALG_REGISTER, + CRYPTO_MSG_ALG_UNREGISTER, + CRYPTO_MSG_TMPL_REGISTER, + CRYPTO_MSG_TMPL_UNREGISTER, +}; + +struct crypto_cipher_test { + struct crypto_alg *alg; + char name[CRYPTO_MAX_ALG_NAME]; +}; + extern struct list_head crypto_alg_list; extern struct rw_semaphore crypto_alg_sem; +extern struct blocking_notifier_head ocrypto_chain; extern enum km_type crypto_km_types[]; @@ -108,6 +124,10 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm); void crypto_exit_cipher_ops(struct crypto_tfm *tfm); void crypto_exit_compress_ops(struct crypto_tfm *tfm); +int ocrypto_register_notifier(struct notifier_block *nb); +int ocrypto_unregister_notifier(struct notifier_block *nb); +void ocrypto_alg_tested(const char *name, int err); + int digest_test(const char *driver, const char *alg); #endif /* _CRYPTO_INTERNAL_H */ diff --git a/crypto/ninternal.h b/crypto/ninternal.h index 07d729c..0ed1e96 100644 --- a/crypto/ninternal.h +++ b/crypto/ninternal.h @@ -18,15 +18,6 @@ #include "internal.h" -/* Crypto notification events. */ -enum { - CRYPTO_MSG_ALG_REQUEST, - CRYPTO_MSG_ALG_REGISTER, - CRYPTO_MSG_ALG_UNREGISTER, - CRYPTO_MSG_TMPL_REGISTER, - CRYPTO_MSG_TMPL_UNREGISTER, -}; - struct crypto_larval { struct ncrypto_alg alg; struct ncrypto_alg *adult; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 1c93fc7..721bfba 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -516,9 +516,74 @@ out: return ret; } -static int test_cipher(struct crypto_ablkcipher *tfm, int enc, +static int test_cipher(struct crypto_cipher *tfm, int enc, struct cipher_testvec *template, unsigned int tcount) { + const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm)); + unsigned int i, j, k; + int ret; + char *q; + const char *e; + void *data; + + if (enc == ENCRYPT) + e = "encryption"; + else + e = "decryption"; + + j = 0; + for (i = 0; i < tcount; i++) { + if (template[i].np) + continue; + + j++; + + data = xbuf[0]; + memcpy(data, template[i].input, template[i].ilen); + + crypto_cipher_clear_flags(tfm, ~0); + if (template[i].wk) + crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); + + ret = crypto_cipher_setkey(tfm, template[i].key, + template[i].klen); + if (!ret == template[i].fail) { + printk(KERN_ERR "alg: cipher: setkey failed " + "on test %d for %s: flags=%x\n", j, + algo, crypto_cipher_get_flags(tfm)); + goto out; + } else if (ret) + continue; + + for (k = 0; k < template[i].ilen; + k += crypto_cipher_blocksize(tfm)) { + if (enc) + crypto_cipher_encrypt_one(tfm, data + k, + data + k); + else + crypto_cipher_decrypt_one(tfm, data + k, + data + k); + } + + q = data; + if (memcmp(q, template[i].result, template[i].rlen)) { + printk(KERN_ERR "alg: cipher: Test %d failed " + "on %s for %s\n", j, e, algo); + hexdump(q, template[i].rlen); + ret = -EINVAL; + goto out; + } + } + + ret = 0; + +out: + return ret; +} + +static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, + struct cipher_testvec *template, unsigned int tcount) +{ const char *algo = ncrypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); unsigned int i, j, k, n, temp; @@ -540,8 +605,8 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, req = ablkcipher_request_alloc(tfm, GFP_KERNEL); if (!req) { - printk(KERN_ERR "alg: cipher: Failed to allocate request for " - "%s\n", algo); + printk(KERN_ERR "alg: skcipher: Failed to allocate request " + "for %s\n", algo); ret = -ENOMEM; goto out; } @@ -570,7 +635,7 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, ret = crypto_ablkcipher_setkey(tfm, template[i].key, template[i].klen); if (!ret == template[i].fail) { - printk(KERN_ERR "alg: cipher: setkey failed " + printk(KERN_ERR "alg: skcipher: setkey failed " "on test %d for %s: flags=%x\n", j, algo, crypto_ablkcipher_get_flags(tfm)); goto out; @@ -598,7 +663,7 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, } /* fall through */ default: - printk(KERN_ERR "alg: cipher: %s failed on " + printk(KERN_ERR "alg: skcipher: %s failed on " "test %d for %s: ret=%d\n", e, j, algo, -ret); goto out; @@ -606,8 +671,8 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, q = data; if (memcmp(q, template[i].result, template[i].rlen)) { - printk(KERN_ERR "alg: cipher: Test %d failed " - "on %s for %s\n", j, e, algo); + printk(KERN_ERR "alg: skcipher: Test %d " + "failed on %s for %s\n", j, e, algo); hexdump(q, template[i].rlen); ret = -EINVAL; goto out; @@ -634,7 +699,7 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, ret = crypto_ablkcipher_setkey(tfm, template[i].key, template[i].klen); if (!ret == template[i].fail) { - printk(KERN_ERR "alg: cipher: setkey failed " + printk(KERN_ERR "alg: skcipher: setkey failed " "on chunk test %d for %s: flags=%x\n", j, algo, crypto_ablkcipher_get_flags(tfm)); @@ -687,7 +752,7 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, } /* fall through */ default: - printk(KERN_ERR "alg: cipher: %s failed on " + printk(KERN_ERR "alg: skcipher: %s failed on " "chunk test %d for %s: ret=%d\n", e, j, algo, -ret); goto out; @@ -701,7 +766,7 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, if (memcmp(q, template[i].result + temp, template[i].tap[k])) { - printk(KERN_ERR "alg: cipher: Chunk " + printk(KERN_ERR "alg: skcipher: Chunk " "test %d failed on %s at page " "%u for %s\n", j, e, k, algo); hexdump(q, template[i].tap[k]); @@ -712,7 +777,7 @@ static int test_cipher(struct crypto_ablkcipher *tfm, int enc, for (n = 0; offset_in_page(q + n) && q[n]; n++) ; if (n) { - printk(KERN_ERR "alg: cipher: " + printk(KERN_ERR "alg: skcipher: " "Result buffer corruption in " "chunk test %d on %s at page " "%u for %s: %u bytes:\n", j, e, @@ -764,10 +829,10 @@ out: static int alg_test_cipher(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { - struct crypto_ablkcipher *tfm; + struct crypto_cipher *tfm; int err = 0; - tfm = crypto_alloc_ablkcipher(driver, type, mask); + tfm = crypto_alloc_cipher(driver, type, mask); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: cipher: Failed to load transform for " "%s: %ld\n", driver, PTR_ERR(tfm)); @@ -786,6 +851,35 @@ static int alg_test_cipher(const struct alg_test_desc *desc, desc->suite.cipher.dec.count); out: + crypto_free_cipher(tfm); + return err; +} + +static int alg_test_skcipher(const struct alg_test_desc *desc, + const char *driver, u32 type, u32 mask) +{ + struct crypto_ablkcipher *tfm; + int err = 0; + + tfm = crypto_alloc_ablkcipher(driver, type, mask); + if (IS_ERR(tfm)) { + printk(KERN_ERR "alg: skcipher: Failed to load transform for " + "%s: %ld\n", driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + if (desc->suite.cipher.enc.vecs) { + err = test_skcipher(tfm, ENCRYPT, desc->suite.cipher.enc.vecs, + desc->suite.cipher.enc.count); + if (err) + goto out; + } + + if (desc->suite.cipher.dec.vecs) + err = test_skcipher(tfm, DECRYPT, desc->suite.cipher.dec.vecs, + desc->suite.cipher.dec.count); + +out: crypto_free_ablkcipher(tfm); return err; } @@ -813,7 +907,7 @@ static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, static const struct alg_test_desc alg_test_descs[] = { { .alg = "cbc(aes)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -828,7 +922,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "cbc(anubis)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -843,7 +937,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "cbc(blowfish)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -858,7 +952,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "cbc(des)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -873,7 +967,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "cbc(des3_ede)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -888,7 +982,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "cbc(twofish)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -918,7 +1012,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(aes)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -933,7 +1027,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(anubis)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -948,7 +1042,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(arc4)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -963,7 +1057,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(blowfish)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -978,7 +1072,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(cast5)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -993,7 +1087,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(cast6)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1008,7 +1102,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(des)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1023,7 +1117,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(des3_ede)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1038,7 +1132,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(khazad)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1053,7 +1147,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(serpent)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1068,7 +1162,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(tea)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1083,7 +1177,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(tnepres)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1098,7 +1192,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(twofish)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1113,7 +1207,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(xeta)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1128,7 +1222,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ecb(xtea)", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1170,7 +1264,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "rfc3686(ctr(aes))", - .test = alg_test_cipher, + .test = alg_test_skcipher, .suite = { .cipher = { .enc = { @@ -1195,7 +1289,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }; -int alg_test(const char *driver, const char *alg, u32 type, u32 mask) +static int alg_find_test(const char *alg) { int start = 0; int end = ARRAY_SIZE(alg_test_descs); @@ -1214,10 +1308,38 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) continue; } - return alg_test_descs[i].test(alg_test_descs + i, driver, - type, mask); + return i; + } + + return -1; +} + +int alg_test(const char *driver, const char *alg, u32 type, u32 mask) +{ + int i; + + if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) { + char nalg[CRYPTO_MAX_ALG_NAME]; + + if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >= + sizeof(nalg)) + return -ENAMETOOLONG; + + i = alg_find_test(nalg); + if (i < 0) + goto notest; + + return alg_test_cipher(alg_test_descs + i, driver, type, mask); } + i = alg_find_test(alg); + if (i < 0) + goto notest; + + return alg_test_descs[i].test(alg_test_descs + i, driver, + type, mask); + +notest: printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver); return 0; } @@ -1233,10 +1355,7 @@ static int cryptomgr_test(void *data) NCRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & NCRYPTO_ALG_GENIV)) goto skiptest; - if ((type & NCRYPTO_ALG_TYPE_MASK) == NCRYPTO_ALG_TYPE_CIPHER) - goto skiptest; - - err = alg_test(param->driver, param->alg, 0, NCRYPTO_ALG_TESTED); + err = alg_test(param->driver, param->alg, type, NCRYPTO_ALG_TESTED); skiptest: crypto_alg_tested(param->driver, err); diff --git a/crypto/testmgr_cipher.c b/crypto/testmgr_cipher.c new file mode 100644 index 0000000..fec2cca --- /dev/null +++ b/crypto/testmgr_cipher.c @@ -0,0 +1,109 @@ +/* + * Algorithm testing framework and tests. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> + * Copyright (c) 2007 Nokia Siemens Networks + * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kthread.h> +#include <linux/module.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include "ninternal.h" + +struct crypto_test_param { + char driver[CRYPTO_MAX_ALG_NAME]; + char alg[CRYPTO_MAX_ALG_NAME]; + u32 type; +}; + +static int cryptomgr_test_cipher(void *data) +{ + struct crypto_test_param *param = data; + u32 type = param->type; + + ocrypto_alg_tested(param->driver, + alg_test(param->driver, param->alg, type, + NCRYPTO_ALG_TESTED)); + + kfree(param); + module_put_and_exit(0); +} + +static int cryptomgr_schedule_test_cipher(struct crypto_cipher_test *test) +{ + struct crypto_alg *alg = test->alg; + struct task_struct *thread; + struct crypto_test_param *param; + + if (!try_module_get(THIS_MODULE)) + goto err; + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) + goto err_put_module; + + memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver)); + memcpy(param->alg, test->name, sizeof(param->alg)); + param->type = alg->cra_flags; + + thread = kthread_run(cryptomgr_test_cipher, param, + "cryptomgr_test_cipher"); + if (IS_ERR(thread)) + goto err_free_param; + + return NOTIFY_STOP; + +err_free_param: + kfree(param); +err_put_module: + module_put(THIS_MODULE); +err: + return NOTIFY_OK; +} + +static int otestmgr_notify(struct notifier_block *this, unsigned long msg, + void *data) +{ + switch (msg) { + case CRYPTO_MSG_ALG_REGISTER: + return cryptomgr_schedule_test_cipher(data); + } + + return NOTIFY_DONE; +} + +static struct notifier_block otestmgr_notifier = { + .notifier_call = otestmgr_notify, +}; + +static int __init testmgr_cipher_init(void) +{ + return ocrypto_register_notifier(&otestmgr_notifier); +} + +static void __exit testmgr_cipher_exit(void) +{ + int err; + + err = ocrypto_unregister_notifier(&otestmgr_notifier); + BUG_ON(err); +} + +subsys_initcall(testmgr_cipher_init); +module_exit(testmgr_cipher_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Algorithm Test Manager for Ciphers"); diff --git a/crypto/testmgr_cipher.h b/crypto/testmgr_cipher.h new file mode 100644 index 0000000..2226e04 --- /dev/null +++ b/crypto/testmgr_cipher.h @@ -0,0 +1,22 @@ +/* + * Algorithm testing framework and tests. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> + * Copyright (c) 2007 Nokia Siemens Networks + * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_TESTMGR_CIPHER_H +#define _CRYPTO_TESTMGR_CIPHER_H + +#include <linux/notifier.h> + +extern struct notifier_block otestmgr_notifier; + +#endif /* _CRYPTO_TESTMGR_CIPHER_H */