aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /crypto
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Kconfig23
-rw-r--r--crypto/Makefile5
-rw-r--r--crypto/ablkcipher.c15
-rw-r--r--crypto/ahash.c30
-rw-r--r--crypto/algapi.c59
-rw-r--r--crypto/ansi_cprng.c19
-rw-r--r--crypto/api.c22
-rw-r--r--crypto/fips_integrity.c76
-rw-r--r--crypto/internal.h8
-rw-r--r--crypto/proc.c12
-rw-r--r--crypto/shash.c65
-rw-r--r--crypto/tcrypt.c160
-rw-r--r--crypto/testmgr.c91
13 files changed, 505 insertions, 80 deletions
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 <crypto/hash.h>
+#include <crypto/sha.h>
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+#include <asm-generic/sections.h>
+
+#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 <linux/jiffies.h>
#include <linux/timex.h>
#include <linux/interrupt.h>
+#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 <jmorris@intercode.com.au>");
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);