From c6da2cfeb05178a11c6d062a06f8078150ee492f Mon Sep 17 00:00:00 2001 From: codeworkx Date: Sat, 2 Jun 2012 13:09:29 +0200 Subject: samsung update 1 --- crypto/Kconfig | 23 ++++--- crypto/Makefile | 5 ++ crypto/ablkcipher.c | 15 +++++ crypto/ahash.c | 30 +++++++++ crypto/algapi.c | 59 +++++++++++++++++- crypto/ansi_cprng.c | 19 +++++- crypto/api.c | 22 +++++++ crypto/fips_integrity.c | 76 +++++++++++++++++++++++ crypto/internal.h | 8 ++- crypto/proc.c | 12 +++- crypto/shash.c | 65 ++++++++++++++++++++ crypto/tcrypt.c | 160 +++++++++++++++++++++++++++++++++--------------- crypto/testmgr.c | 91 ++++++++++++++++++++++----- 13 files changed, 505 insertions(+), 80 deletions(-) create mode 100644 crypto/fips_integrity.c (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index 87b22ca..3a6933c 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -23,12 +23,22 @@ comment "Crypto core or helper" config CRYPTO_FIPS bool "FIPS 200 compliance" - depends on CRYPTO_ANSI_CPRNG && !CRYPTO_MANAGER_DISABLE_TESTS + depends on CRYPTO_ANSI_CPRNG help This options enables the fips boot option which is required if you want to system to operate in a FIPS 200 certification. You should say no unless you know what - this is. + this is. Note that CRYPTO_ANSI_CPRNG is required if this + option is selected + +config CRYPTO_FIPS_INTEG_OFFSET + hex "FIPS integrity check zImage offset" + default 0x20000000 + help + This options sets the offset from stext address where + zImage will be copied for integrity check if you want + to system to operate in FIPS mode, which enables + kernel crypto module. config CRYPTO_ALGAPI tristate @@ -100,13 +110,13 @@ config CRYPTO_MANAGER2 select CRYPTO_BLKCIPHER2 select CRYPTO_PCOMP2 -config CRYPTO_MANAGER_DISABLE_TESTS - bool "Disable run-time self tests" +config CRYPTO_MANAGER_TESTS + bool "Run algolithms' self-tests" default y depends on CRYPTO_MANAGER2 help - Disable run-time self tests that normally take place at - algorithm registration. + Run cryptomanager's tests for the new crypto algorithms being + registered. config CRYPTO_GF128MUL tristate "GF(2^128) multiplication functions (EXPERIMENTAL)" @@ -161,7 +171,6 @@ config CRYPTO_AUTHENC config CRYPTO_TEST tristate "Testing module" - depends on m select CRYPTO_MANAGER help Quick & dirty crypto test module. diff --git a/crypto/Makefile b/crypto/Makefile index ce5a813..69c46ed 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -2,6 +2,11 @@ # Cryptographic API # +ifeq ($(USE_SEC_FIPS_MODE),true) +FIPS=fips_ +endif +obj-$(CONFIG_CRYPTO_FIPS) += fips_integrity.o + obj-$(CONFIG_CRYPTO) += crypto.o crypto-y := api.o cipher.o compress.o diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index fdc67d3..f43b70a 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -50,6 +50,11 @@ void __ablkcipher_walk_complete(struct ablkcipher_walk *walk) { struct ablkcipher_buffer *p, *tmp; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return; +#endif + list_for_each_entry_safe(p, tmp, &walk->buffers, entry) { ablkcipher_buffer_write(p); list_del(&p->entry); @@ -112,6 +117,11 @@ int ablkcipher_walk_done(struct ablkcipher_request *req, struct crypto_tfm *tfm = req->base.tfm; unsigned int nbytes = 0; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if (likely(err >= 0)) { unsigned int n = walk->nbytes - err; @@ -597,6 +607,11 @@ int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, struct crypto_alg *alg; int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + type = crypto_skcipher_type(type); mask = crypto_skcipher_mask(mask); diff --git a/crypto/ahash.c b/crypto/ahash.c index f669822..5f6a8e4 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -78,6 +78,11 @@ int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err) unsigned int alignmask = walk->alignmask; unsigned int nbytes = walk->entrylen; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + walk->data -= walk->offset; if (nbytes && walk->offset & alignmask && !err) { @@ -115,6 +120,11 @@ EXPORT_SYMBOL_GPL(crypto_hash_walk_done); int crypto_hash_walk_first(struct ahash_request *req, struct crypto_hash_walk *walk) { +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + walk->total = req->nbytes; if (!walk->total) @@ -132,6 +142,11 @@ int crypto_hash_walk_first_compat(struct hash_desc *hdesc, struct crypto_hash_walk *walk, struct scatterlist *sg, unsigned int len) { +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + walk->total = len; if (!walk->total) @@ -250,6 +265,11 @@ static int crypto_ahash_op(struct ahash_request *req, struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); unsigned long alignmask = crypto_ahash_alignmask(tfm); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if ((unsigned long)req->result & alignmask) return ahash_op_unaligned(req, op); @@ -366,6 +386,11 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) struct crypto_ahash *hash = __crypto_ahash_cast(tfm); struct ahash_alg *alg = crypto_ahash_alg(hash); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + hash->setkey = ahash_nosetkey; hash->export = ahash_no_export; hash->import = ahash_no_import; @@ -468,6 +493,11 @@ int ahash_register_instance(struct crypto_template *tmpl, { int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + err = ahash_prepare_alg(&inst->alg); if (err) return err; diff --git a/crypto/algapi.c b/crypto/algapi.c index c3cf1a6..3fa383c 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -61,6 +61,15 @@ static inline int crypto_set_driver_name(struct crypto_alg *alg) static int crypto_check_alg(struct crypto_alg *alg) { +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) { + printk(KERN_ERR + "crypto_check_alg failed due to FIPS error: %s", + alg->cra_name); + return -EACCES; + } +#endif + if (alg->cra_alignmask & (alg->cra_alignmask + 1)) return -EINVAL; @@ -355,6 +364,15 @@ int crypto_register_alg(struct crypto_alg *alg) struct crypto_larval *larval; int err; +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) { + printk(KERN_ERR + "Unable to registrer alg: %s because of FIPS ERROR\n" + , alg->cra_name); + return -EACCES; + } +#endif + err = crypto_check_alg(alg); if (err) return err; @@ -411,6 +429,11 @@ int crypto_register_template(struct crypto_template *tmpl) struct crypto_template *q; int err = -EEXIST; +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_template_list, list) { @@ -478,6 +501,13 @@ static struct crypto_template *__crypto_lookup_template(const char *name) struct crypto_template *crypto_lookup_template(const char *name) { +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) { + printk(KERN_ERR + "crypto_lookup failed due to FIPS error: %s", name); + return -EACCES; + } +#endif return try_then_request_module(__crypto_lookup_template(name), name); } EXPORT_SYMBOL_GPL(crypto_lookup_template); @@ -488,6 +518,11 @@ int crypto_register_instance(struct crypto_template *tmpl, struct crypto_larval *larval; int err; +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + err = crypto_check_alg(&inst->alg); if (err) goto err; @@ -523,6 +558,11 @@ int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, { int err = -EAGAIN; +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + spawn->inst = inst; spawn->mask = mask; @@ -738,6 +778,11 @@ void *crypto_alloc_instance2(const char *name, struct crypto_alg *alg, char *p; int err; +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn), GFP_KERNEL); if (!p) @@ -769,6 +814,11 @@ struct crypto_instance *crypto_alloc_instance(const char *name, struct crypto_spawn *spawn; int err; + #ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + inst = crypto_alloc_instance2(name, alg, 0); if (IS_ERR(inst)) goto out; @@ -805,6 +855,11 @@ int crypto_enqueue_request(struct crypto_queue *queue, { int err = -EINPROGRESS; +#ifdef CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + if (unlikely(queue->qlen >= queue->max_qlen)) { err = -EBUSY; if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) @@ -909,13 +964,13 @@ EXPORT_SYMBOL_GPL(crypto_xor); static int __init crypto_algapi_init(void) { - crypto_init_proc(); + /*crypto_init_proc(); //Moved to testmgr*/ return 0; } static void __exit crypto_algapi_exit(void) { - crypto_exit_proc(); + /*crypto_exit_proc(); //Moved to testmgr*/ } module_init(crypto_algapi_init); diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index ffa0245..e8213b9 100644 --- a/crypto/ansi_cprng.c +++ b/crypto/ansi_cprng.c @@ -126,6 +126,10 @@ static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test) output = ctx->rand_data; break; case 2: +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EINVAL; +#endif /* * First check that we didn't produce the same * random data that we did last time around through this @@ -133,8 +137,9 @@ static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test) if (!memcmp(ctx->rand_data, ctx->last_rand_data, DEFAULT_BLK_SZ)) { if (cont_test) { - panic("cprng %p Failed repetition check!\n", - ctx); +#ifdef CONFIG_CRYPTO_FIPS + set_in_fips_err(); +#endif } printk(KERN_ERR @@ -372,6 +377,11 @@ static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ) return -EINVAL; +#ifdef CONFIG_CRYPTO_FIPS + if (!memcmp(key, seed, DEFAULT_PRNG_KSZ)) + return -EINVAL; +#endif + if (slen >= (2 * DEFAULT_BLK_SZ + DEFAULT_PRNG_KSZ)) dt = key + DEFAULT_PRNG_KSZ; @@ -408,6 +418,11 @@ static int fips_cprng_get_random(struct crypto_rng *tfm, u8 *rdata, { struct prng_context *prng = crypto_rng_ctx(tfm); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EINVAL; +#endif + return get_prng_bytes(rdata, dlen, prng, 1); } diff --git a/crypto/api.c b/crypto/api.c index 033a714..0686dc5 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -361,6 +361,11 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, unsigned int tfm_size; int err = -ENOMEM; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask); tfm = kzalloc(tfm_size, GFP_KERNEL); if (tfm == NULL) @@ -417,6 +422,11 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) struct crypto_tfm *tfm; int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + for (;;) { struct crypto_alg *alg; @@ -455,6 +465,13 @@ void *crypto_create_tfm(struct crypto_alg *alg, unsigned int total; int err = -ENOMEM; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) { + printk(KERN_ERR + "Fail crypto_create_tfm due to fips error state.\n"); + return ERR_PTR(-EACCES); + } +#endif tfmsize = frontend->tfmsize; total = tfmsize + sizeof(*tfm) + frontend->extsize(alg); @@ -534,6 +551,11 @@ void *crypto_alloc_tfm(const char *alg_name, void *tfm; int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + for (;;) { struct crypto_alg *alg; diff --git a/crypto/fips_integrity.c b/crypto/fips_integrity.c new file mode 100644 index 0000000..2a51f92 --- /dev/null +++ b/crypto/fips_integrity.c @@ -0,0 +1,76 @@ +/* + * Integrity check code for crypto module. + * + * 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 +#include +#include +#include +#include + +#include "internal.h" + +#define ZIMAGE_ADDR (_stext + CONFIG_CRYPTO_FIPS_INTEG_OFFSET) + +static bool need_integrity_check = true; + +void do_integrity_check(void) +{ + u8 *rbuf = (u8 *) ZIMAGE_ADDR; + u32 len; + u8 hmac[SHA256_DIGEST_SIZE]; + struct hash_desc desc; + struct scatterlist sg; + u8 *key = "12345678"; + + printk(KERN_INFO "FIPS: do kernel integrity check\n"); + + if (unlikely(!need_integrity_check || in_fips_err())) + return; + + if (*((u32 *) &rbuf[36]) != 0x016F2818) { + printk(KERN_ERR "FIPS: invalid zImage magic number."); + set_in_fips_err(); + goto err1; + } + + if (*(u32 *) &rbuf[44] <= *(u32 *) &rbuf[40]) { + printk(KERN_ERR "FIPS: invalid zImage calculated len"); + set_in_fips_err(); + goto err1; + } + + len = *(u32 *) &rbuf[44] - *(u32 *) &rbuf[40]; + + desc.tfm = crypto_alloc_hash("hmac(sha256)", 0, 0); + + if (IS_ERR(desc.tfm)) { + printk(KERN_ERR "FIPS: integ failed to allocate tfm %ld\n", + PTR_ERR(desc.tfm)); + set_in_fips_err(); + goto err; + } + + sg_init_one(&sg, rbuf, len); + crypto_hash_setkey(desc.tfm, key, strlen(key)); + crypto_hash_digest(&desc, &sg, len, hmac); + + if (!strncmp(hmac, &rbuf[len], SHA256_DIGEST_SIZE)) { + printk(KERN_INFO "FIPS: integrity check passed\n"); + } else { + printk(KERN_ERR "FIPS: integrity check failed\n"); + set_in_fips_err(); + } + + err: + crypto_free_hash(desc.tfm); + err1: + need_integrity_check = false; + + return; +} diff --git a/crypto/internal.h b/crypto/internal.h index d4384b0..0e7e9fd 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -51,7 +51,14 @@ extern struct rw_semaphore crypto_alg_sem; extern struct blocking_notifier_head crypto_chain; #ifdef CONFIG_PROC_FS +#ifdef CONFIG_CRYPTO_FIPS +void set_in_fips_err(void); +void __init crypto_init_proc(int *fips_error); +void do_integrity_check(void); +int testmgr_crypto_proc_init(void); +#else void __init crypto_init_proc(void); +#endif void __exit crypto_exit_proc(void); #else static inline void crypto_init_proc(void) @@ -138,4 +145,3 @@ static inline void crypto_notify(unsigned long val, void *v) } #endif /* _CRYPTO_INTERNAL_H */ - diff --git a/crypto/proc.c b/crypto/proc.c index 58fef67..2c0b607 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -25,8 +25,7 @@ #ifdef CONFIG_CRYPTO_FIPS static struct ctl_table crypto_sysctl_table[] = { { - .procname = "fips_enabled", - .data = &fips_enabled, + .procname = "fips_status", .maxlen = sizeof(int), .mode = 0444, .proc_handler = proc_dointvec @@ -141,11 +140,20 @@ static const struct file_operations proc_crypto_ops = { .release = seq_release }; +#ifdef CONFIG_CRYPTO_FIPS +void __init crypto_init_proc(int *fips_error) +{ + proc_create("crypto", 0, NULL, &proc_crypto_ops); + crypto_sysctl_table[0].data = fips_error; + crypto_proc_fips_init(); +} +#else void __init crypto_init_proc(void) { proc_create("crypto", 0, NULL, &proc_crypto_ops); crypto_proc_fips_init(); } +#endif void __exit crypto_exit_proc(void) { diff --git a/crypto/shash.c b/crypto/shash.c index 76f74b9..e44549c 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -99,6 +99,11 @@ int crypto_shash_update(struct shash_desc *desc, const u8 *data, struct shash_alg *shash = crypto_shash_alg(tfm); unsigned long alignmask = crypto_shash_alignmask(tfm); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if ((unsigned long)data & alignmask) return shash_update_unaligned(desc, data, len); @@ -134,6 +139,11 @@ int crypto_shash_final(struct shash_desc *desc, u8 *out) struct shash_alg *shash = crypto_shash_alg(tfm); unsigned long alignmask = crypto_shash_alignmask(tfm); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if ((unsigned long)out & alignmask) return shash_final_unaligned(desc, out); @@ -155,6 +165,11 @@ int crypto_shash_finup(struct shash_desc *desc, const u8 *data, struct shash_alg *shash = crypto_shash_alg(tfm); unsigned long alignmask = crypto_shash_alignmask(tfm); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if (((unsigned long)data | (unsigned long)out) & alignmask) return shash_finup_unaligned(desc, data, len, out); @@ -176,6 +191,11 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data, struct shash_alg *shash = crypto_shash_alg(tfm); unsigned long alignmask = crypto_shash_alignmask(tfm); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if (((unsigned long)data | (unsigned long)out) & alignmask) return shash_digest_unaligned(desc, data, len, out); @@ -208,6 +228,11 @@ static int shash_async_init(struct ahash_request *req) struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct shash_desc *desc = ahash_request_ctx(req); +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + desc->tfm = *ctx; desc->flags = req->base.flags; @@ -219,6 +244,11 @@ int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc) struct crypto_hash_walk walk; int nbytes; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) nbytes = crypto_shash_update(desc, walk.data, nbytes); @@ -242,6 +272,11 @@ int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc) struct crypto_hash_walk walk; int nbytes; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + nbytes = crypto_hash_walk_first(req, &walk); if (!nbytes) return crypto_shash_final(desc, req->result); @@ -276,6 +311,11 @@ int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) unsigned int nbytes = req->nbytes; int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { void *data; @@ -334,6 +374,11 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm) struct crypto_shash **ctx = crypto_tfm_ctx(tfm); struct crypto_shash *shash; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + if (!crypto_mod_get(calg)) return -EAGAIN; @@ -550,6 +595,11 @@ static const struct crypto_type crypto_shash_type = { struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type, u32 mask) { +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return ERR_PTR(-EACCES); +#endif + return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask); } EXPORT_SYMBOL_GPL(crypto_alloc_shash); @@ -587,6 +637,11 @@ int crypto_register_shash(struct shash_alg *alg) struct crypto_alg *base = &alg->base; int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + err = shash_prepare_alg(alg); if (err) return err; @@ -606,6 +661,11 @@ int shash_register_instance(struct crypto_template *tmpl, { int err; +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + err = shash_prepare_alg(&inst->alg); if (err) return err; @@ -625,6 +685,11 @@ int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn, struct shash_alg *alg, struct crypto_instance *inst) { +#ifdef CONFIG_CRYPTO_FIPS + if (unlikely(in_fips_err())) + return -EACCES; +#endif + return crypto_init_spawn2(&spawn->base, &alg->base, inst, &crypto_shash_type); } diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 2222617..093764e 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -33,9 +33,12 @@ #include #include #include +#ifdef CRYPTO_SPEED_TESTS #include "tcrypt.h" +#endif #include "internal.h" +#ifdef CRYPTO_SPEED_TESTS /* * Need slab memory for testing (size in number of pages). */ @@ -51,12 +54,15 @@ * Used by test_cipher_speed() */ static unsigned int sec; +#endif static char *alg = NULL; static u32 type; static u32 mask; static int mode; +#ifdef CRYPTO_SPEED_TESTS static char *tvmem[TVMEMSIZE]; +#endif static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", @@ -66,7 +72,7 @@ static char *check[] = { "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", "lzo", "cts", "zlib", NULL }; - +#ifdef CRYPTO_SPEED_TESTS static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, struct scatterlist *sg, int blen, int sec) { @@ -718,6 +724,7 @@ static void test_ahash_speed(const char *algo, unsigned int sec, out: crypto_free_ahash(tfm); } +#endif static void test_available(void) { @@ -752,15 +759,17 @@ static int do_test(int m) for (i = 1; i < 200; i++) ret += do_test(i); break; - +#ifdef CONFIG_CRYPTO_MD5 case 1: ret += tcrypt_test("md5"); break; - +#endif +#ifdef CONFIG_CRYPTO_SHA1 case 2: ret += tcrypt_test("sha1"); break; - +#endif +#ifdef CONFIG_CRYPTO_DES case 3: ret += tcrypt_test("ecb(des)"); ret += tcrypt_test("cbc(des)"); @@ -770,38 +779,47 @@ static int do_test(int m) ret += tcrypt_test("ecb(des3_ede)"); ret += tcrypt_test("cbc(des3_ede)"); break; - +#endif +#ifdef CONFIG_CRYPTO_MD4 case 5: ret += tcrypt_test("md4"); break; - +#endif case 6: ret += tcrypt_test("sha256"); break; - +#ifdef CONFIG_CRYPTO_BLOWFISH case 7: ret += tcrypt_test("ecb(blowfish)"); ret += tcrypt_test("cbc(blowfish)"); break; - +#endif +#ifdef CONFIG_CRYPTO_TWOFISH case 8: ret += tcrypt_test("ecb(twofish)"); ret += tcrypt_test("cbc(twofish)"); break; - +#endif +#ifdef CONFIG_CRYPTO_SERPENT case 9: ret += tcrypt_test("ecb(serpent)"); break; - +#endif case 10: ret += tcrypt_test("ecb(aes)"); ret += tcrypt_test("cbc(aes)"); +#ifdef CONFIG_CRYPTO_LRW ret += tcrypt_test("lrw(aes)"); +#endif +#ifdef CONFIG_CRYPTO_XTS ret += tcrypt_test("xts(aes)"); +#endif +#ifdef CONFIG_CRYPTO_CTR ret += tcrypt_test("ctr(aes)"); ret += tcrypt_test("rfc3686(ctr(aes))"); break; - +#endif +#ifdef CONFIG_CRYPTO_SHA512 case 11: ret += tcrypt_test("sha384"); break; @@ -809,31 +827,34 @@ static int do_test(int m) case 12: ret += tcrypt_test("sha512"); break; - +#endif +#ifdef CONFIG_CRYPTO_DEFLATE case 13: ret += tcrypt_test("deflate"); break; - +#endif +#ifdef CONFIG_CRYPTO_CAST5 case 14: ret += tcrypt_test("ecb(cast5)"); break; - +#endif +#ifdef CONFIG_CRYPTO_CAST6 case 15: ret += tcrypt_test("ecb(cast6)"); break; - +#endif case 16: ret += tcrypt_test("ecb(arc4)"); break; - +#ifdef CONFIG_CRYPTO_MICHAEL_MIC case 17: ret += tcrypt_test("michael_mic"); break; - +#endif case 18: ret += tcrypt_test("crc32c"); break; - +#ifdef CONFIG_CRYPTO_TEA case 19: ret += tcrypt_test("ecb(tea)"); break; @@ -841,11 +862,13 @@ static int do_test(int m) case 20: ret += tcrypt_test("ecb(xtea)"); break; - +#endif +#ifdef CONFIG_CRYPTO_KHAZAD case 21: ret += tcrypt_test("ecb(khazad)"); break; - +#endif +#ifdef CONFIG_CRYPTO_WP512 case 22: ret += tcrypt_test("wp512"); break; @@ -857,16 +880,19 @@ static int do_test(int m) case 24: ret += tcrypt_test("wp256"); break; - +#endif +#ifdef CONFIG_CRYPTO_SERPENT case 25: ret += tcrypt_test("ecb(tnepres)"); break; - +#endif +#ifdef CONFIG_CRYPTO_ANUBIS case 26: ret += tcrypt_test("ecb(anubis)"); ret += tcrypt_test("cbc(anubis)"); break; - +#endif +#ifdef CONFIG_CRYPTO_TGR192 case 27: ret += tcrypt_test("tgr192"); break; @@ -879,83 +905,100 @@ static int do_test(int m) case 29: ret += tcrypt_test("tgr128"); break; - +#endif +#ifdef CONFIG_CRYPTO_TEA case 30: ret += tcrypt_test("ecb(xeta)"); break; - +#endif +#ifdef CONFIG_CRYPTO_FCRYPT case 31: ret += tcrypt_test("pcbc(fcrypt)"); break; - +#endif +#ifdef CONFIG_CRYPTO_CAMELLIA case 32: ret += tcrypt_test("ecb(camellia)"); ret += tcrypt_test("cbc(camellia)"); break; +#endif case 33: ret += tcrypt_test("sha224"); break; - +#ifdef CONFIG_CRYPTO_SALSA20 case 34: ret += tcrypt_test("salsa20"); break; - +#endif +#ifdef CONFIG_CRYPTO_GCM case 35: ret += tcrypt_test("gcm(aes)"); break; - +#endif +#ifdef CONFIG_CRYPTO_LZO case 36: ret += tcrypt_test("lzo"); break; - +#endif +#ifdef CONFIG_CRYPTO_CCM case 37: ret += tcrypt_test("ccm(aes)"); break; - +#endif +#ifdef CONFIG_CRYPTO_CTS case 38: ret += tcrypt_test("cts(cbc(aes))"); break; - +#endif +#ifdef CONFIG_CRYPTO_RMD128 case 39: ret += tcrypt_test("rmd128"); break; - +#endif +#ifdef CONFIG_CRYPTO_RMD160 case 40: ret += tcrypt_test("rmd160"); break; - +#endif +#ifdef CONFIG_CRYPTO_RMD256 case 41: ret += tcrypt_test("rmd256"); break; - +#endif +#ifdef CONFIG_CRYPTO_RMD320 case 42: ret += tcrypt_test("rmd320"); break; - +#endif +#ifdef CONFIG_CRYPTO_SEED case 43: ret += tcrypt_test("ecb(seed)"); break; - +#endif +#ifdef CONFIG_CRYPTO_ZLIB case 44: ret += tcrypt_test("zlib"); break; - +#endif +#ifdef CONFIG_CRYPTO_CCM case 45: ret += tcrypt_test("rfc4309(ccm(aes))"); break; - +#endif +#ifdef CONFIG_CRYPTO_MD5 case 100: ret += tcrypt_test("hmac(md5)"); break; - +#endif +#ifdef CONFIG_CRYPTO_SHA1 case 101: ret += tcrypt_test("hmac(sha1)"); break; - +#endif case 102: ret += tcrypt_test("hmac(sha256)"); break; - +#ifdef CONFIG_CRYPTO_SHA512 case 103: ret += tcrypt_test("hmac(sha384)"); break; @@ -963,15 +1006,16 @@ static int do_test(int m) case 104: ret += tcrypt_test("hmac(sha512)"); break; - +#endif case 105: ret += tcrypt_test("hmac(sha224)"); break; - +#ifdef CONFIG_CRYPTO_XCBC case 106: ret += tcrypt_test("xcbc(aes)"); break; - +#endif +#ifdef CONFIG_CRYPTO_RMD case 107: ret += tcrypt_test("hmac(rmd128)"); break; @@ -979,19 +1023,23 @@ static int do_test(int m) case 108: ret += tcrypt_test("hmac(rmd160)"); break; - +#endif +#ifdef CONFIG_CRYPTO_VMAC case 109: ret += tcrypt_test("vmac(aes)"); break; - +#endif case 150: ret += tcrypt_test("ansi_cprng"); break; +#ifdef CONFIG_CRYPTO_GCM case 151: ret += tcrypt_test("rfc4106(gcm(aes))"); break; +#endif +#ifdef CRYPTO_SPEED_TESTS case 200: test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0, speed_template_16_24_32); @@ -1230,7 +1278,7 @@ static int do_test(int m) case 499: break; - +#endif case 1000: test_available(); break; @@ -1248,6 +1296,7 @@ static int do_alg_test(const char *alg, u32 type, u32 mask) static int __init tcrypt_mod_init(void) { int err = -ENOMEM; +#ifdef CRYPTO_SPEED_TESTS int i; for (i = 0; i < TVMEMSIZE; i++) { @@ -1255,6 +1304,9 @@ static int __init tcrypt_mod_init(void) if (!tvmem[i]) goto err_free_tv; } +#endif + + testmgr_crypto_proc_init(); if (alg) err = do_alg_test(alg, type, mask); @@ -1264,8 +1316,12 @@ static int __init tcrypt_mod_init(void) if (err) { printk(KERN_ERR "tcrypt: one or more tests failed!\n"); goto err_free_tv; +#ifndef CONFIG_CRYPTO_FIPS } - +#else + } else + do_integrity_check(); +#endif /* We intentionaly return -EAGAIN to prevent keeping the module, * unless we're running in fips mode. It does all its work from * init() and doesn't offer any runtime functionality, but in @@ -1277,9 +1333,10 @@ static int __init tcrypt_mod_init(void) err = -EAGAIN; err_free_tv: +#ifdef CRYPTO_SPEED_TESTS for (i = 0; i < TVMEMSIZE && tvmem[i]; i++) free_page((unsigned long)tvmem[i]); - +#endif return err; } @@ -1296,10 +1353,11 @@ module_param(alg, charp, 0); module_param(type, uint, 0); module_param(mask, uint, 0); module_param(mode, int, 0); +#ifdef SUPPORT_SPEED_TEST module_param(sec, uint, 0); MODULE_PARM_DESC(sec, "Length in seconds of speed tests " "(defaults to zero which uses CPU cycles instead)"); - +#endif MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Quick & dirty crypto testing module"); MODULE_AUTHOR("James Morris "); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index b6b93d4..158ce65 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,7 +30,7 @@ #include "internal.h" -#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS +#ifndef CONFIG_CRYPTO_MANAGER_TESTS /* a perfect nop */ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) @@ -38,6 +38,14 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) return 0; } +#ifdef CONFIG_CRYPTO_FIPS +bool in_fips_err() +{ + return false; +} +EXPORT_SYMBOL_GPL(in_fips_err); +#endif + #else #include "testmgr.h" @@ -65,6 +73,12 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) #define ENCRYPT 1 #define DECRYPT 0 +#ifdef CONFIG_CRYPTO_FIPS +#define FIPS_ERR 1 +#define FIPS_NO_ERR 0 +static int IN_FIPS_ERROR = FIPS_NO_ERR; +#endif + struct tcrypt_result { struct completion completion; int err; @@ -126,6 +140,18 @@ struct alg_test_desc { static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; +#ifdef CONFIG_CRYPTO_FIPS +bool in_fips_err() +{ + return (IN_FIPS_ERROR == FIPS_ERR); +} + +void set_in_fips_err() +{ + IN_FIPS_ERROR = FIPS_ERR; +} +#endif + static void hexdump(unsigned char *buf, unsigned int len) { print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, @@ -1692,7 +1718,9 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "ccm(aes)", .test = alg_test_aead, +#ifdef CONFIG_CRYPTO_CCM .fips_allowed = 1, +#endif .suite = { .aead = { .enc = { @@ -2061,7 +2089,9 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "gcm(aes)", .test = alg_test_aead, +#ifdef CONFIG_CRYPTO_GCM .fips_allowed = 1, +#endif .suite = { .aead = { .enc = { @@ -2077,7 +2107,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "ghash", .test = alg_test_hash, - .fips_allowed = 1, .suite = { .hash = { .vecs = ghash_tv_template, @@ -2268,6 +2297,9 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "rfc4106(gcm(aes))", .test = alg_test_aead, +#ifdef CONFIG_CRYPTO_GCM + .fips_allowed = 1, +#endif .suite = { .aead = { .enc = { @@ -2285,7 +2317,9 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "rfc4309(ccm(aes))", .test = alg_test_aead, +#ifdef CONFIG_CRYPTO_CCM .fips_allowed = 1, +#endif .suite = { .aead = { .enc = { @@ -2530,7 +2564,10 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) { int i; int j; - int rc; + int rc = 0; +#ifdef CONFIG_CRYPTO_FIPS + fips_enabled = 1; +#endif if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) { char nalg[CRYPTO_MAX_ALG_NAME]; @@ -2555,11 +2592,6 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) if (i < 0 && j < 0) goto notest; - if (fips_enabled && ((i >= 0 && !alg_test_descs[i].fips_allowed) || - (j >= 0 && !alg_test_descs[j].fips_allowed))) - goto non_fips_alg; - - rc = 0; if (i >= 0) rc |= alg_test_descs[i].test(alg_test_descs + i, driver, type, mask); @@ -2567,23 +2599,52 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) rc |= alg_test_descs[j].test(alg_test_descs + j, driver, type, mask); + if (fips_enabled && ((i >= 0 && !alg_test_descs[i].fips_allowed) || + (j >= 0 && !alg_test_descs[j].fips_allowed))) + goto non_fips_alg; + test_done: - if (fips_enabled && rc) - panic("%s: %s alg self test failed in fips mode!\n", driver, alg); + if (fips_enabled && rc) { + printk(KERN_INFO + "FIPS: %s: %s alg self test failed\n", + driver, alg); +#ifdef CONFIG_CRYPTO_FIPS + IN_FIPS_ERROR = FIPS_ERR; +#endif + return rc; + } if (fips_enabled && !rc) - printk(KERN_INFO "alg: self-tests for %s (%s) passed\n", - driver, alg); + printk(KERN_INFO "FIPS: self-tests for %s (%s) passed\n", + driver, alg); return rc; notest: - printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver); + printk(KERN_INFO "FIPS: No test for %s (%s)\n", alg, driver); return 0; non_fips_alg: - return -EINVAL; + if (!rc) + printk(KERN_INFO + "FIPS: self-tests for non-FIPS %s (%s) passed\n", + driver, alg); + else + printk(KERN_INFO + "FIPS: self-tests for non-FIPS %s (%s) failed\n", + alg, driver); + return rc; +} + +int testmgr_crypto_proc_init(void) +{ +#ifdef CONFIG_CRYPTO_FIPS + crypto_init_proc(&IN_FIPS_ERROR); +#else + crypto_init_proc(); +#endif + return 0; } -#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */ +#endif /* CONFIG_CRYPTO_MANAGER_TESTS */ EXPORT_SYMBOL_GPL(alg_test); -- cgit v1.1