Commit f6bccf69 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: skcipher - Use RNG interface instead of get_random_bytes
  crypto: rng - RNG interface and implementation
  crypto: api - Add fips_enable flag
  crypto: skcipher - Move IV generators into their own modules
  crypto: cryptomgr - Test ciphers using ECB
  crypto: api - Use test infrastructure
  crypto: cryptomgr - Add test infrastructure
  crypto: tcrypt - Add alg_test interface
  crypto: tcrypt - Abort and only log if there is an error
  crypto: crc32c - Use Intel CRC32 instruction
  crypto: tcrypt - Avoid using contiguous pages
  crypto: api - Display larval objects properly
  crypto: api - Export crypto_alg_lookup instead of __crypto_alg_lookup
  crypto: Kconfig - Replace leading spaces with tabs
parents 3af73d39 a0f000ec
......@@ -10,6 +10,8 @@ obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
aes-i586-y := aes-i586-asm_32.o aes_glue.o
twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
......
/*
* Using hardware provided CRC32 instruction to accelerate the CRC32 disposal.
* CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE)
* CRC32 is a new instruction in Intel SSE4.2, the reference can be found at:
* http://www.intel.com/products/processor/manuals/
* Intel(R) 64 and IA-32 Architectures Software Developer's Manual
* Volume 2A: Instruction Set Reference, A-M
*
* Copyright (c) 2008 Austin Zhang <austin_zhang@linux.intel.com>
* Copyright (c) 2008 Kent Liu <kent.liu@intel.com>
*
* 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/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <crypto/internal/hash.h>
#include <asm/cpufeature.h>
#define CHKSUM_BLOCK_SIZE 1
#define CHKSUM_DIGEST_SIZE 4
#define SCALE_F sizeof(unsigned long)
#ifdef CONFIG_X86_64
#define REX_PRE "0x48, "
#else
#define REX_PRE
#endif
static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
{
while (length--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
:"=S"(crc)
:"0"(crc), "c"(*data)
);
data++;
}
return crc;
}
static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len)
{
unsigned int iquotient = len / SCALE_F;
unsigned int iremainder = len % SCALE_F;
unsigned long *ptmp = (unsigned long *)p;
while (iquotient--) {
__asm__ __volatile__(
".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*ptmp)
);
ptmp++;
}
if (iremainder)
crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp,
iremainder);
return crc;
}
/*
* Setting the seed allows arbitrary accumulators and flexible XOR policy
* If your algorithm starts with ~0, then XOR with ~0 before you set
* the seed.
*/
static int crc32c_intel_setkey(struct crypto_ahash *hash, const u8 *key,
unsigned int keylen)
{
u32 *mctx = crypto_ahash_ctx(hash);
if (keylen != sizeof(u32)) {
crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
}
*mctx = le32_to_cpup((__le32 *)key);
return 0;
}
static int crc32c_intel_init(struct ahash_request *req)
{
u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
u32 *crcp = ahash_request_ctx(req);
*crcp = *mctx;
return 0;
}
static int crc32c_intel_update(struct ahash_request *req)
{
struct crypto_hash_walk walk;
u32 *crcp = ahash_request_ctx(req);
u32 crc = *crcp;
int nbytes;
for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
nbytes = crypto_hash_walk_done(&walk, 0))
crc = crc32c_intel_le_hw(crc, walk.data, nbytes);
*crcp = crc;
return 0;
}
static int crc32c_intel_final(struct ahash_request *req)
{
u32 *crcp = ahash_request_ctx(req);
*(__le32 *)req->result = ~cpu_to_le32p(crcp);
return 0;
}
static int crc32c_intel_digest(struct ahash_request *req)
{
struct crypto_hash_walk walk;
u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
u32 crc = *mctx;
int nbytes;
for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
nbytes = crypto_hash_walk_done(&walk, 0))
crc = crc32c_intel_le_hw(crc, walk.data, nbytes);
*(__le32 *)req->result = ~cpu_to_le32(crc);
return 0;
}
static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
{
u32 *key = crypto_tfm_ctx(tfm);
*key = ~0;
tfm->crt_ahash.reqsize = sizeof(u32);
return 0;
}
static struct crypto_alg alg = {
.cra_name = "crc32c",
.cra_driver_name = "crc32c-intel",
.cra_priority = 200,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
.cra_alignmask = 3,
.cra_ctxsize = sizeof(u32),
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_init = crc32c_intel_cra_init,
.cra_type = &crypto_ahash_type,
.cra_u = {
.ahash = {
.digestsize = CHKSUM_DIGEST_SIZE,
.setkey = crc32c_intel_setkey,
.init = crc32c_intel_init,
.update = crc32c_intel_update,
.final = crc32c_intel_final,
.digest = crc32c_intel_digest,
}
}
};
static int __init crc32c_intel_mod_init(void)
{
if (cpu_has_xmm4_2)
return crypto_register_alg(&alg);
else
return -ENODEV;
}
static void __exit crc32c_intel_mod_fini(void)
{
crypto_unregister_alg(&alg);
}
module_init(crc32c_intel_mod_init);
module_exit(crc32c_intel_mod_fini);
MODULE_AUTHOR("Austin Zhang <austin.zhang@intel.com>, Kent Liu <kent.liu@intel.com>");
MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware.");
MODULE_LICENSE("GPL");
MODULE_ALIAS("crc32c");
MODULE_ALIAS("crc32c-intel");
......@@ -21,6 +21,14 @@ if CRYPTO
comment "Crypto core or helper"
config CRYPTO_FIPS
bool "FIPS 200 compliance"
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.
config CRYPTO_ALGAPI
tristate
help
......@@ -33,14 +41,21 @@ config CRYPTO_AEAD
config CRYPTO_BLKCIPHER
tristate
select CRYPTO_ALGAPI
select CRYPTO_RNG
config CRYPTO_HASH
tristate
select CRYPTO_ALGAPI
config CRYPTO_RNG
tristate
select CRYPTO_ALGAPI
config CRYPTO_MANAGER
tristate "Cryptographic algorithm manager"
select CRYPTO_ALGAPI
select CRYPTO_AEAD
select CRYPTO_HASH
select CRYPTO_BLKCIPHER
help
Create default cryptographic template instantiations such as
cbc(aes).
......@@ -85,9 +100,7 @@ config CRYPTO_AUTHENC
config CRYPTO_TEST
tristate "Testing module"
depends on m
select CRYPTO_ALGAPI
select CRYPTO_AEAD
select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
help
Quick & dirty crypto test module.
......@@ -113,6 +126,7 @@ config CRYPTO_SEQIV
tristate "Sequence Number IV Generator"
select CRYPTO_AEAD
select CRYPTO_BLKCIPHER
select CRYPTO_RNG
help
This IV generator generates an IV based on a sequence number by
xoring it with a salt. This algorithm is mainly useful for CTR
......@@ -219,7 +233,19 @@ config CRYPTO_CRC32C
Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
by iSCSI for header and data digests and by others.
See Castagnoli93. This implementation uses lib/libcrc32c.
Module will be crc32c.
Module will be crc32c.
config CRYPTO_CRC32C_INTEL
tristate "CRC32c INTEL hardware acceleration"
depends on X86
select CRYPTO_HASH
help
In Intel processor with SSE4.2 supported, the processor will
support CRC32C implementation using hardware accelerated CRC32
instruction. This option will create 'crc32c-intel' module,
which will enable any routine to use the CRC32 instruction to
gain performance compared with software implementation.
Module will be crc32c-intel.
config CRYPTO_MD4
tristate "MD4 digest algorithm"
......@@ -243,55 +269,58 @@ config CRYPTO_MICHAEL_MIC
of the algorithm.
config CRYPTO_RMD128
tristate "RIPEMD-128 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-128 (ISO/IEC 10118-3:2004).
tristate "RIPEMD-128 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-128 (ISO/IEC 10118-3:2004).
RIPEMD-128 is a 128-bit cryptographic hash function. It should only
to be used as a secure replacement for RIPEMD. For other use cases
RIPEMD-160 should be used.
RIPEMD-128 is a 128-bit cryptographic hash function. It should only
to be used as a secure replacement for RIPEMD. For other use cases
RIPEMD-160 should be used.
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
config CRYPTO_RMD160
tristate "RIPEMD-160 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-160 (ISO/IEC 10118-3:2004).
tristate "RIPEMD-160 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-160 (ISO/IEC 10118-3:2004).
RIPEMD-160 is a 160-bit cryptographic hash function. It is intended
to be used as a secure replacement for the 128-bit hash functions
MD4, MD5 and it's predecessor RIPEMD (not to be confused with RIPEMD-128).
RIPEMD-160 is a 160-bit cryptographic hash function. It is intended
to be used as a secure replacement for the 128-bit hash functions
MD4, MD5 and it's predecessor RIPEMD
(not to be confused with RIPEMD-128).
It's speed is comparable to SHA1 and there are no known attacks against
RIPEMD-160.
It's speed is comparable to SHA1 and there are no known attacks
against RIPEMD-160.
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
config CRYPTO_RMD256
tristate "RIPEMD-256 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-256 is an optional extension of RIPEMD-128 with a 256 bit hash.
It is intended for applications that require longer hash-results, without
needing a larger security level (than RIPEMD-128).
tristate "RIPEMD-256 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-256 is an optional extension of RIPEMD-128 with a
256 bit hash. It is intended for applications that require
longer hash-results, without needing a larger security level
(than RIPEMD-128).
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
config CRYPTO_RMD320
tristate "RIPEMD-320 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-320 is an optional extension of RIPEMD-160 with a 320 bit hash.
It is intended for applications that require longer hash-results, without
needing a larger security level (than RIPEMD-160).
tristate "RIPEMD-320 digest algorithm"
select CRYPTO_ALGAPI
help
RIPEMD-320 is an optional extension of RIPEMD-160 with a
320 bit hash. It is intended for applications that require
longer hash-results, without needing a larger security level
(than RIPEMD-160).
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html>
config CRYPTO_SHA1
tristate "SHA1 digest algorithm"
......@@ -308,8 +337,8 @@ config CRYPTO_SHA256
This version of SHA implements a 256 bit hash with 128 bits of
security against collision attacks.
This code also includes SHA-224, a 224 bit hash with 112 bits
of security against collision attacks.
This code also includes SHA-224, a 224 bit hash with 112 bits
of security against collision attacks.
config CRYPTO_SHA512
tristate "SHA384 and SHA512 digest algorithms"
......@@ -666,6 +695,18 @@ config CRYPTO_LZO
help
This is the LZO algorithm.
comment "Random Number Generation"
config CRYPTO_ANSI_CPRNG
tristate "Pseudo Random Number Generation for Cryptographic modules"
select CRYPTO_AES
select CRYPTO_RNG
select CRYPTO_FIPS
help
This option enables the generic pseudo random number generator
for cryptographic modules. Uses the Algorithm specified in
ANSI X9.31 A.2.4
source "drivers/crypto/Kconfig"
endif # if CRYPTO
......@@ -5,6 +5,8 @@
obj-$(CONFIG_CRYPTO) += crypto.o
crypto-objs := api.o cipher.o digest.o compress.o
obj-$(CONFIG_CRYPTO_FIPS) += fips.o
crypto_algapi-$(CONFIG_PROC_FS) += proc.o
crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
......@@ -13,15 +15,17 @@ obj-$(CONFIG_CRYPTO_AEAD) += aead.o
crypto_blkcipher-objs := ablkcipher.o
crypto_blkcipher-objs += blkcipher.o
crypto_blkcipher-objs += chainiv.o
crypto_blkcipher-objs += eseqiv.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
crypto_hash-objs := hash.o
crypto_hash-objs += ahash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
cryptomgr-objs := algboss.o testmgr.o
obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
......@@ -69,7 +73,9 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
obj-$(CONFIG_CRYPTO_RNG) += rng.o
obj-$(CONFIG_CRYPTO_RNG) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
#
......
......@@ -21,15 +21,15 @@
#include "internal.h"
static void crypto_remove_final(struct list_head *list);
static LIST_HEAD(crypto_template_list);
void crypto_larval_error(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
down_read(&crypto_alg_sem);
alg = __crypto_alg_lookup(name, type, mask);
up_read(&crypto_alg_sem);
alg = crypto_alg_lookup(name, type, mask);
if (alg) {
if (crypto_is_larval(alg)) {
......@@ -128,23 +128,97 @@ static void crypto_remove_spawns(struct list_head *spawns,
}
}
static int __crypto_register_alg(struct crypto_alg *alg,
struct list_head *list)
static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
{
struct crypto_alg *q;
struct crypto_larval *larval;
int ret = -EAGAIN;
if (crypto_is_dead(alg))
goto out;
goto err;
INIT_LIST_HEAD(&alg->cra_users);
/* No cheating! */
alg->cra_flags &= ~CRYPTO_ALG_TESTED;
ret = -EEXIST;
atomic_set(&alg->cra_refcnt, 1);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (q == alg)
goto out;
goto err;
if (crypto_is_larval(q)) {
if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
goto err;
continue;
}
if (!strcmp(q->cra_driver_name, alg->cra_name) ||
!strcmp(q->cra_name, alg->cra_driver_name))
goto err;
}
larval = crypto_larval_alloc(alg->cra_name,
alg->cra_flags | CRYPTO_ALG_TESTED, 0);
if (IS_ERR(larval))
goto out;
ret = -ENOENT;
larval->adult = crypto_mod_get(alg);
if (!larval->adult)
goto free_larval;
atomic_set(&larval->alg.cra_refcnt, 1);
memcpy(larval->alg.cra_driver_name, alg->cra_driver_name,
CRYPTO_MAX_ALG_NAME);
larval->alg.cra_priority = alg->cra_priority;
list_add(&alg->cra_list, &crypto_alg_list);
list_add(&larval->alg.cra_list, &crypto_alg_list);
out:
return larval;
free_larval:
kfree(larval);
err:
larval = ERR_PTR(ret);
goto out;
}
void crypto_alg_tested(const char *name, int err)
{
struct crypto_larval *test;
struct crypto_alg *alg;
struct crypto_alg *q;
LIST_HEAD(list);
down_write(&crypto_alg_sem);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (!crypto_is_larval(q))
continue;
test = (struct crypto_larval *)q;
if (!strcmp(q->cra_driver_name, name))
goto found;
}
printk(KERN_ERR "alg: Unexpected test result for %s: %d\n", name, err);
goto unlock;
found:
alg = test->adult;
if (err || list_empty(&alg->cra_list))
goto complete;
alg->cra_flags |= CRYPTO_ALG_TESTED;
list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (q == alg)
continue;
if (crypto_is_moribund(q))
continue;
......@@ -180,17 +254,18 @@ static int __crypto_register_alg(struct crypto_alg *alg,
q->cra_priority > alg->cra_priority)
continue;
crypto_remove_spawns(&q->cra_users, list, alg->cra_flags);
crypto_remove_spawns(&q->cra_users, &list, alg->cra_flags);
}
list_add(&alg->cra_list, &crypto_alg_list);
crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg);
ret = 0;
complete:
complete_all(&test->completion);
out:
return ret;
unlock:
up_write(&crypto_alg_sem);
crypto_remove_final(&list);
}
EXPORT_SYMBOL_GPL(crypto_alg_tested);
static void crypto_remove_final(struct list_head *list)
{
......@@ -203,9 +278,27 @@ static void crypto_remove_final(struct list_head *list)
}
}
static void crypto_wait_for_test(struct crypto_larval *larval)
{
int err;
err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
if (err != NOTIFY_STOP) {
if (WARN_ON(err != NOTIFY_DONE))
goto out;
crypto_alg_tested(larval->alg.cra_driver_name, 0);
}
err = wait_for_completion_interruptible(&larval->completion);
WARN_ON(err);
out:
crypto_larval_kill(&larval->alg);
}
int crypto_register_alg(struct crypto_alg *alg)
{
LIST_HEAD(list);
struct crypto_larval *larval;
int err;
err = crypto_check_alg(alg);
......@@ -213,11 +306,14 @@ int crypto_register_alg(struct crypto_alg *alg)
return err;
down_write(&crypto_alg_sem);
err = __crypto_register_alg(alg, &list);
larval = __crypto_register_alg(alg);
up_write(&crypto_alg_sem);
crypto_remove_final(&list);
return err;
if (IS_ERR(larval))
return PTR_ERR(larval);
crypto_wait_for_test(larval);
return 0;
}