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
This commit is contained in:
commit
f6bccf6954
25 changed files with 12249 additions and 10059 deletions
|
@ -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
|
||||
|
|
197
arch/x86/crypto/crc32c-intel.c
Normal file
197
arch/x86/crypto/crc32c-intel.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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");
|
||||
|
127
crypto/Kconfig
127
crypto/Kconfig
|
@ -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
|
||||
|
||||
#
|
||||
|
|
147
crypto/algapi.c
147
crypto/algapi.c
|
@ -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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_register_alg);
|
||||
|
||||
|
@ -335,8 +431,8 @@ EXPORT_SYMBOL_GPL(crypto_lookup_template);
|
|||
int crypto_register_instance(struct crypto_template *tmpl,
|
||||
struct crypto_instance *inst)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
int err = -EINVAL;
|
||||
struct crypto_larval *larval;
|
||||
int err;
|
||||
|
||||
err = crypto_check_alg(&inst->alg);
|
||||
if (err)
|
||||
|
@ -346,8 +442,8 @@ int crypto_register_instance(struct crypto_template *tmpl,
|
|||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
err = __crypto_register_alg(&inst->alg, &list);
|
||||
if (err)
|
||||
larval = __crypto_register_alg(&inst->alg);
|
||||
if (IS_ERR(larval))
|
||||
goto unlock;
|
||||
|
||||
hlist_add_head(&inst->list, &tmpl->instances);
|
||||
|
@ -356,7 +452,12 @@ int crypto_register_instance(struct crypto_template *tmpl,
|
|||
unlock:
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
crypto_remove_final(&list);
|
||||
err = PTR_ERR(larval);
|
||||
if (IS_ERR(larval))
|
||||
goto err;
|
||||
|
||||
crypto_wait_for_test(larval);
|
||||
err = 0;
|
||||
|
||||
err:
|
||||
return err;
|
||||
|
|
|
@ -45,6 +45,15 @@ struct cryptomgr_param {
|
|||
|
||||
char larval[CRYPTO_MAX_ALG_NAME];
|
||||
char template[CRYPTO_MAX_ALG_NAME];
|
||||
|
||||
u32 otype;
|
||||
u32 omask;
|
||||
};
|
||||
|
||||
struct crypto_test_param {
|
||||
char driver[CRYPTO_MAX_ALG_NAME];
|
||||
char alg[CRYPTO_MAX_ALG_NAME];
|
||||
u32 type;
|
||||
};
|
||||
|
||||
static int cryptomgr_probe(void *data)
|
||||
|
@ -76,8 +85,7 @@ static int cryptomgr_probe(void *data)
|
|||
module_put_and_exit(0);
|
||||
|
||||
err:
|
||||
crypto_larval_error(param->larval, param->type.data.type,
|
||||
param->type.data.mask);
|
||||
crypto_larval_error(param->larval, param->otype, param->omask);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -169,13 +177,65 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
|
|||
|
||||
param->type.attr.rta_len = sizeof(param->type);
|
||||
param->type.attr.rta_type = CRYPTOA_TYPE;
|
||||
param->type.data.type = larval->alg.cra_flags;
|
||||
param->type.data.mask = larval->mask;
|
||||
param->type.data.type = larval->alg.cra_flags & ~CRYPTO_ALG_TESTED;
|
||||
param->type.data.mask = larval->mask & ~CRYPTO_ALG_TESTED;
|
||||
param->tb[0] = ¶m->type.attr;
|
||||
|
||||
param->otype = larval->alg.cra_flags;
|
||||
param->omask = larval->mask;
|
||||
|
||||
memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME);
|
||||
|
||||
thread = kthread_run(cryptomgr_probe, param, "cryptomgr");
|
||||
thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe");
|
||||
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 cryptomgr_test(void *data)
|
||||
{
|
||||
struct crypto_test_param *param = data;
|
||||
u32 type = param->type;
|
||||
int err = 0;
|
||||
|
||||
if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
|
||||
CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV))
|
||||
goto skiptest;
|
||||
|
||||
err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED);
|
||||
|
||||
skiptest:
|
||||
crypto_alg_tested(param->driver, err);
|
||||
|
||||
kfree(param);
|
||||
module_put_and_exit(0);
|
||||
}
|
||||
|
||||
static int cryptomgr_schedule_test(struct crypto_alg *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, alg->cra_name, sizeof(param->alg));
|
||||
param->type = alg->cra_flags;
|
||||
|
||||
thread = kthread_run(cryptomgr_test, param, "cryptomgr_test");
|
||||
if (IS_ERR(thread))
|
||||
goto err_free_param;
|
||||
|
||||
|
@ -195,6 +255,8 @@ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg,
|
|||
switch (msg) {
|
||||
case CRYPTO_MSG_ALG_REQUEST:
|
||||
return cryptomgr_schedule_probe(data);
|
||||
case CRYPTO_MSG_ALG_REGISTER:
|
||||
return cryptomgr_schedule_test(data);
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
|
@ -206,16 +268,32 @@ static struct notifier_block cryptomgr_notifier = {
|
|||
|
||||
static int __init cryptomgr_init(void)
|
||||
{
|
||||
return crypto_register_notifier(&cryptomgr_notifier);
|
||||
int err;
|
||||
|
||||
err = testmgr_init();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crypto_register_notifier(&cryptomgr_notifier);
|
||||
if (err)
|
||||
goto free_testmgr;
|
||||
|
||||
return 0;
|
||||
|
||||
free_testmgr:
|
||||
testmgr_exit();
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit cryptomgr_exit(void)
|
||||
{
|
||||
int err = crypto_unregister_notifier(&cryptomgr_notifier);
|
||||
BUG_ON(err);
|
||||
|
||||
testmgr_exit();
|
||||
}
|
||||
|
||||
module_init(cryptomgr_init);
|
||||
subsys_initcall(cryptomgr_init);
|
||||
module_exit(cryptomgr_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
417
crypto/ansi_cprng.c
Normal file
417
crypto/ansi_cprng.c
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* PRNG: Pseudo Random Number Generator
|
||||
* Based on NIST Recommended PRNG From ANSI X9.31 Appendix A.2.4 using
|
||||
* AES 128 cipher
|
||||
*
|
||||
* (C) Neil Horman <nhorman@tuxdriver.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
|
||||
* any later version.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <crypto/internal/rng.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define DEFAULT_PRNG_KEY "0123456789abcdef"
|
||||
#define DEFAULT_PRNG_KSZ 16
|
||||
#define DEFAULT_BLK_SZ 16
|
||||
#define DEFAULT_V_SEED "zaybxcwdveuftgsh"
|
||||
|
||||
/*
|
||||
* Flags for the prng_context flags field
|
||||
*/
|
||||
|
||||
#define PRNG_FIXED_SIZE 0x1
|
||||
#define PRNG_NEED_RESET 0x2
|
||||
|
||||
/*
|
||||
* Note: DT is our counter value
|
||||
* I is our intermediate value
|
||||
* V is our seed vector
|
||||
* See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
||||
* for implementation details
|
||||
*/
|
||||
|
||||
|
||||
struct prng_context {
|
||||
spinlock_t prng_lock;
|
||||
unsigned char rand_data[DEFAULT_BLK_SZ];
|
||||
unsigned char last_rand_data[DEFAULT_BLK_SZ];
|
||||
unsigned char DT[DEFAULT_BLK_SZ];
|
||||
unsigned char I[DEFAULT_BLK_SZ];
|
||||
unsigned char V[DEFAULT_BLK_SZ];
|
||||
u32 rand_data_valid;
|
||||
struct crypto_cipher *tfm;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
static int dbg;
|
||||
|
||||
static void hexdump(char *note, unsigned char *buf, unsigned int len)
|
||||
{
|
||||
if (dbg) {
|
||||
printk(KERN_CRIT "%s", note);
|
||||
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
|
||||
16, 1,
|
||||
buf, len, false);
|
||||
}
|
||||
}
|
||||
|
||||
#define dbgprint(format, args...) do {\
|
||||
if (dbg)\
|
||||
printk(format, ##args);\
|
||||
} while (0)
|
||||
|
||||
static void xor_vectors(unsigned char *in1, unsigned char *in2,
|
||||
unsigned char *out, unsigned int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
out[i] = in1[i] ^ in2[i];
|
||||
|
||||
}
|
||||
/*
|
||||
* Returns DEFAULT_BLK_SZ bytes of random data per call
|
||||
* returns 0 if generation succeded, <0 if something went wrong
|
||||
*/
|
||||
static int _get_more_prng_bytes(struct prng_context *ctx)
|
||||
{
|
||||
int i;
|
||||
unsigned char tmp[DEFAULT_BLK_SZ];
|
||||
unsigned char *output = NULL;
|
||||
|
||||
|
||||
dbgprint(KERN_CRIT "Calling _get_more_prng_bytes for context %p\n",
|
||||
ctx);
|
||||
|
||||
hexdump("Input DT: ", ctx->DT, DEFAULT_BLK_SZ);
|
||||
hexdump("Input I: ", ctx->I, DEFAULT_BLK_SZ);
|
||||
hexdump("Input V: ", ctx->V, DEFAULT_BLK_SZ);
|
||||
|
||||
/*
|
||||
* This algorithm is a 3 stage state machine
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
/*
|
||||
* Start by encrypting the counter value
|
||||
* This gives us an intermediate value I
|
||||
*/
|
||||
memcpy(tmp, ctx->DT, DEFAULT_BLK_SZ);
|
||||
output = ctx->I;
|
||||
hexdump("tmp stage 0: ", tmp, DEFAULT_BLK_SZ);
|
||||
break;
|
||||
case 1:
|
||||
|
||||
/*
|
||||
* Next xor I with our secret vector V
|
||||
* encrypt that result to obtain our
|
||||
* pseudo random data which we output
|
||||
*/
|
||||
xor_vectors(ctx->I, ctx->V, tmp, DEFAULT_BLK_SZ);
|
||||
hexdump("tmp stage 1: ", tmp, DEFAULT_BLK_SZ);
|
||||
output = ctx->rand_data;
|
||||
break;
|
||||
case 2:
|
||||
/*
|
||||
* First check that we didn't produce the same
|
||||
* random data that we did last time around through this
|
||||
*/
|
||||
if (!memcmp(ctx->rand_data, ctx->last_rand_data,
|
||||
DEFAULT_BLK_SZ)) {
|
||||
printk(KERN_ERR
|
||||
"ctx %p Failed repetition check!\n",
|
||||
ctx);
|
||||
ctx->flags |= PRNG_NEED_RESET;
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(ctx->last_rand_data, ctx->rand_data,
|
||||
DEFAULT_BLK_SZ);
|
||||
|
||||
/*
|
||||
* Lastly xor the random data with I
|
||||
* and encrypt that to obtain a new secret vector V
|
||||
*/
|
||||
xor_vectors(ctx->rand_data, ctx->I, tmp,
|
||||
DEFAULT_BLK_SZ);
|
||||
output = ctx->V;
|
||||
hexdump("tmp stage 2: ", tmp, DEFAULT_BLK_SZ);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* do the encryption */
|
||||
crypto_cipher_encrypt_one(ctx->tfm, output, tmp);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Now update our DT value
|
||||
*/
|
||||
for (i = 0; i < DEFAULT_BLK_SZ; i++) {
|
||||
ctx->DT[i] += 1;
|
||||
if (ctx->DT[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
dbgprint("Returning new block for context %p\n", ctx);
|
||||
ctx->rand_data_valid = 0;
|
||||
|
||||
hexdump("Output DT: ", ctx->DT, DEFAULT_BLK_SZ);
|
||||
hexdump("Output I: ", ctx->I, DEFAULT_BLK_SZ);
|
||||
hexdump("Output V: ", ctx->V, DEFAULT_BLK_SZ);
|
||||
hexdump("New Random Data: ", ctx->rand_data, DEFAULT_BLK_SZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our exported functions */
|
||||
static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned char *ptr = buf;
|
||||
unsigned int byte_count = (unsigned int)nbytes;
|
||||
int err;
|
||||
|
||||
|
||||
if (nbytes < 0)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&ctx->prng_lock, flags);
|
||||
|
||||
err = -EINVAL;
|
||||
if (ctx->flags & PRNG_NEED_RESET)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* If the FIXED_SIZE flag is on, only return whole blocks of
|
||||
* pseudo random data
|
||||
*/
|
||||
err = -EINVAL;
|
||||
if (ctx->flags & PRNG_FIXED_SIZE) {
|
||||
if (nbytes < DEFAULT_BLK_SZ)
|
||||
goto done;
|
||||
byte_count = DEFAULT_BLK_SZ;
|
||||
}
|
||||
|
||||
err = byte_count;
|
||||
|
||||
dbgprint(KERN_CRIT "getting %d random bytes for context %p\n",
|
||||
byte_count, ctx);
|
||||
|
||||
|
||||
remainder:
|
||||
if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
|
||||
if (_get_more_prng_bytes(ctx) < 0) {
|
||||
memset(buf, 0, nbytes);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy up to the next whole block size
|
||||
*/
|
||||
if (byte_count < DEFAULT_BLK_SZ) {
|
||||
for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
|
||||
ctx->rand_data_valid++) {
|
||||
*ptr = ctx->rand_data[ctx->rand_data_valid];
|
||||
ptr++;
|
||||
byte_count--;
|
||||
if (byte_count == 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now copy whole blocks
|
||||
*/
|
||||
for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) {
|
||||
if (_get_more_prng_bytes(ctx) < 0) {
|
||||
memset(buf, 0, nbytes);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ);
|
||||
ctx->rand_data_valid += DEFAULT_BLK_SZ;
|
||||
ptr += DEFAULT_BLK_SZ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now copy any extra partial data
|
||||
*/
|
||||
if (byte_count)
|
||||
goto remainder;
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&ctx->prng_lock, flags);
|
||||
dbgprint(KERN_CRIT "returning %d from get_prng_bytes in context %p\n",
|
||||
err, ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void free_prng_context(struct prng_context *ctx)
|
||||
{
|
||||
crypto_free_cipher(ctx->tfm);
|
||||
}
|
||||
|
||||
static int reset_prng_context(struct prng_context *ctx,
|
||||
unsigned char *key, size_t klen,
|
||||
unsigned char *V, unsigned char *DT)
|
||||
{
|
||||
int ret;
|
||||
int rc = -EINVAL;
|
||||
unsigned char *prng_key;
|
||||
|
||||
spin_lock(&ctx->prng_lock);
|
||||
ctx->flags |= PRNG_NEED_RESET;
|
||||
|
||||
prng_key = (key != NULL) ? key : (unsigned char *)DEFAULT_PRNG_KEY;
|
||||
|
||||
if (!key)
|
||||
klen = DEFAULT_PRNG_KSZ;
|
||||
|
||||
if (V)
|
||||
memcpy(ctx->V, V, DEFAULT_BLK_SZ);
|
||||
else
|
||||
memcpy(ctx->V, DEFAULT_V_SEED, DEFAULT_BLK_SZ);
|
||||
|
||||
if (DT)
|
||||
memcpy(ctx->DT, DT, DEFAULT_BLK_SZ);
|
||||
else
|
||||
memset(ctx->DT, 0, DEFAULT_BLK_SZ);
|
||||
|
||||
memset(ctx->rand_data, 0, DEFAULT_BLK_SZ);
|
||||
memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ);
|
||||
|
||||
if (ctx->tfm)
|
||||
crypto_free_cipher(ctx->tfm);
|
||||
|
||||
ctx->tfm = crypto_alloc_cipher("aes", 0, 0);
|
||||
if (IS_ERR(ctx->tfm)) {
|
||||
dbgprint(KERN_CRIT "Failed to alloc tfm for context %p\n",
|
||||
ctx);
|
||||
ctx->tfm = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->rand_data_valid = DEFAULT_BLK_SZ;
|
||||
|
||||
ret = crypto_cipher_setkey(ctx->tfm, prng_key, klen);
|
||||
if (ret) {
|
||||
dbgprint(KERN_CRIT "PRNG: setkey() failed flags=%x\n",
|
||||
crypto_cipher_get_flags(ctx->tfm));
|
||||
crypto_free_cipher(ctx->tfm);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
ctx->flags &= ~PRNG_NEED_RESET;
|
||||
out:
|
||||
spin_unlock(&ctx->prng_lock);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
static int cprng_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct prng_context *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
spin_lock_init(&ctx->prng_lock);
|
||||
|
||||
return reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL);
|
||||
}
|
||||
|
||||
static void cprng_exit(struct crypto_tfm *tfm)
|
||||
{
|
||||
free_prng_context(crypto_tfm_ctx(tfm));
|
||||
}
|
||||
|
||||
static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata,
|
||||
unsigned int dlen)
|
||||
{
|
||||
struct prng_context *prng = crypto_rng_ctx(tfm);
|
||||
|
||||
return get_prng_bytes(rdata, dlen, prng);
|
||||
}
|
||||
|
||||
static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
|
||||
{
|
||||
struct prng_context *prng = crypto_rng_ctx(tfm);
|
||||
u8 *key = seed + DEFAULT_PRNG_KSZ;
|
||||
|
||||
if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
|
||||
return -EINVAL;
|
||||
|
||||
reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, NULL);
|
||||
|
||||
if (prng->flags & PRNG_NEED_RESET)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct crypto_alg rng_alg = {
|
||||
.cra_name = "stdrng",
|
||||
.cra_driver_name = "ansi_cprng",
|
||||
.cra_priority = 100,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_RNG,
|
||||
.cra_ctxsize = sizeof(struct prng_context),
|
||||
.cra_type = &crypto_rng_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(rng_alg.cra_list),
|
||||
.cra_init = cprng_init,
|
||||
.cra_exit = cprng_exit,
|
||||
.cra_u = {
|
||||
.rng = {
|
||||
.rng_make_random = cprng_get_random,
|
||||
.rng_reset = cprng_reset,
|
||||
.seedsize = DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Module initalization */
|
||||
static int __init prng_mod_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fips_enabled)
|
||||
rng_alg.cra_priority += 200;
|
||||
|
||||
ret = crypto_register_alg(&rng_alg);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit prng_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&rng_alg);
|
||||
return;
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Software Pseudo Random Number Generator");
|
||||
MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>");
|
||||
module_param(dbg, int, 0);
|
||||
MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)");
|
||||
module_init(prng_mod_init);
|
||||
module_exit(prng_mod_fini);
|
||||
MODULE_ALIAS("stdrng");
|
81
crypto/api.c
81
crypto/api.c
|
@ -55,7 +55,13 @@ void crypto_mod_put(struct crypto_alg *alg)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_mod_put);
|
||||
|
||||
struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask)
|
||||
static inline int crypto_is_test_larval(struct crypto_larval *larval)
|
||||
{
|
||||
return larval->alg.cra_driver_name[0];
|
||||
}
|
||||
|
||||
static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
struct crypto_alg *q, *alg = NULL;
|
||||
int best = -2;
|
||||
|
@ -70,6 +76,7 @@ struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask)
|
|||
continue;
|
||||
|
||||
if (crypto_is_larval(q) &&
|
||||
!crypto_is_test_larval((struct crypto_larval *)q) &&
|
||||
((struct crypto_larval *)q)->mask != mask)
|
||||
continue;
|
||||
|
||||
|
@ -92,7 +99,6 @@ struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask)
|
|||
|
||||
return alg;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__crypto_alg_lookup);
|
||||
|
||||
static void crypto_larval_destroy(struct crypto_alg *alg)
|
||||
{
|
||||
|
@ -104,10 +110,8 @@ static void crypto_larval_destroy(struct crypto_alg *alg)
|
|||
kfree(larval);
|
||||
}
|
||||
|
||||
static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
|
||||
u32 mask)
|
||||
struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_larval *larval;
|
||||
|
||||
larval = kzalloc(sizeof(*larval), GFP_KERNEL);
|
||||
|
@ -119,10 +123,25 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
|
|||
larval->alg.cra_priority = -1;
|
||||
larval->alg.cra_destroy = crypto_larval_destroy;
|
||||
|
||||
atomic_set(&larval->alg.cra_refcnt, 2);
|
||||
strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
|
||||
init_completion(&larval->completion);
|
||||
|
||||
return larval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_larval_alloc);
|
||||
|
||||
static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_larval *larval;
|
||||
|
||||
larval = crypto_larval_alloc(name, type, mask);
|
||||
if (IS_ERR(larval))
|
||||
return ERR_CAST(larval);
|
||||
|
||||
atomic_set(&larval->alg.cra_refcnt, 2);
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
alg = __crypto_alg_lookup(name, type, mask);
|
||||
if (!alg) {
|
||||
|
@ -152,21 +171,29 @@ EXPORT_SYMBOL_GPL(crypto_larval_kill);
|
|||
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_larval *larval = (void *)alg;
|
||||
long timeout;
|
||||
|
||||
timeout = wait_for_completion_interruptible_timeout(
|
||||
&larval->completion, 60 * HZ);
|
||||
|
||||
wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ);
|
||||
alg = larval->adult;
|
||||
if (alg) {
|
||||
if (!crypto_mod_get(alg))
|
||||
alg = ERR_PTR(-EAGAIN);
|
||||
} else
|
||||
if (timeout < 0)
|
||||
alg = ERR_PTR(-EINTR);
|
||||
else if (!timeout)
|
||||
alg = ERR_PTR(-ETIMEDOUT);
|
||||
else if (!alg)
|
||||
alg = ERR_PTR(-ENOENT);
|
||||
else if (crypto_is_test_larval(larval) &&
|
||||
!(alg->cra_flags & CRYPTO_ALG_TESTED))
|
||||
alg = ERR_PTR(-EAGAIN);
|
||||
else if (!crypto_mod_get(alg))
|
||||
alg = ERR_PTR(-EAGAIN);
|
||||
crypto_mod_put(&larval->alg);
|
||||
|
||||
return alg;
|
||||
}
|
||||
|
||||
static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
|
||||
u32 mask)
|
||||
struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, u32 mask)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
|
||||
|
@ -176,6 +203,7 @@ static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
|
|||
|
||||
return alg;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_alg_lookup);
|
||||
|
||||
struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
|
||||
{
|
||||
|
@ -192,25 +220,40 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
|
|||
if (alg)
|
||||
return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
|
||||
|
||||
return crypto_larval_alloc(name, type, mask);
|
||||
return crypto_larval_add(name, type, mask);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_larval_lookup);
|
||||
|
||||
int crypto_probing_notify(unsigned long val, void *v)
|
||||
{
|
||||
int ok;
|
||||
|
||||
ok = blocking_notifier_call_chain(&crypto_chain, val, v);
|
||||
if (ok == NOTIFY_DONE) {
|
||||
request_module("cryptomgr");
|
||||
ok = blocking_notifier_call_chain(&crypto_chain, val, v);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_probing_notify);
|
||||
|
||||
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_alg *larval;
|
||||
int ok;
|
||||
|
||||
if (!(mask & CRYPTO_ALG_TESTED)) {
|
||||
type |= CRYPTO_ALG_TESTED;
|
||||
mask |= CRYPTO_ALG_TESTED;
|
||||
}
|
||||
|
||||
larval = crypto_larval_lookup(name, type, mask);
|
||||
if (IS_ERR(larval) || !crypto_is_larval(larval))
|
||||
return larval;
|
||||
|
||||
ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval);
|
||||
if (ok == NOTIFY_DONE) {
|
||||
request_module("cryptomgr");
|
||||
ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval);
|
||||
}
|
||||
ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval);
|
||||
|
||||
if (ok == NOTIFY_STOP)
|
||||
alg = crypto_larval_wait(larval);
|
||||
|
|
|
@ -696,34 +696,5 @@ void skcipher_geniv_exit(struct crypto_tfm *tfm)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(skcipher_geniv_exit);
|
||||
|
||||
static int __init blkcipher_module_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = chainiv_module_init();
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = eseqiv_module_init();
|
||||
if (err)
|
||||
goto eseqiv_err;
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
||||
eseqiv_err:
|
||||
chainiv_module_exit();
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void __exit blkcipher_module_exit(void)
|
||||
{
|
||||
eseqiv_module_exit();
|
||||
chainiv_module_exit();
|
||||
}
|
||||
|
||||
module_init(blkcipher_module_init);
|
||||
module_exit(blkcipher_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic block chaining cipher type");
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
*/
|
||||
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/rng.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
@ -83,6 +83,7 @@ static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
|
|||
{
|
||||
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
|
||||
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
|
||||
int err = 0;
|
||||
|
||||
spin_lock_bh(&ctx->lock);
|
||||
if (crypto_ablkcipher_crt(geniv)->givencrypt !=
|
||||
|
@ -90,11 +91,15 @@ static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
|
|||
goto unlock;
|
||||
|
||||
crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt;
|
||||
get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
|
||||
err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv,
|
||||
crypto_ablkcipher_ivsize(geniv));
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&ctx->lock);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return chainiv_givencrypt(req);
|
||||
}
|
||||
|
||||
|
@ -203,6 +208,7 @@ static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
|
|||
{
|
||||
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
|
||||
struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
|
||||
int err = 0;
|
||||
|
||||
if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
|
||||
goto out;
|
||||
|
@ -212,11 +218,15 @@ static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
|
|||
goto unlock;
|
||||
|
||||
crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt;
|
||||
get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
|
||||
err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv,
|
||||
crypto_ablkcipher_ivsize(geniv));
|
||||
|
||||
unlock:
|
||||
clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
out:
|
||||
return async_chainiv_givencrypt(req);
|
||||
}
|
||||
|
@ -284,9 +294,13 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
|
|||
if (IS_ERR(algt))
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = crypto_get_default_rng();
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0);
|
||||
if (IS_ERR(inst))
|
||||
goto out;
|
||||
goto put_rng;
|
||||
|
||||
inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first;
|
||||
|
||||
|
@ -311,21 +325,37 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
|
|||
|
||||
out:
|
||||
return inst;
|
||||
|
||||
put_rng:
|
||||
crypto_put_default_rng();
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void chainiv_free(struct crypto_instance *inst)
|
||||
{
|
||||
skcipher_geniv_free(inst);
|
||||
crypto_put_default_rng();
|
||||
}
|
||||
|
||||
static struct crypto_template chainiv_tmpl = {
|
||||
.name = "chainiv",
|
||||
.alloc = chainiv_alloc,
|
||||
.free = skcipher_geniv_free,
|
||||
.free = chainiv_free,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
int __init chainiv_module_init(void)
|
||||
static int __init chainiv_module_init(void)
|
||||
{
|
||||
return crypto_register_template(&chainiv_tmpl);
|
||||
}
|
||||
|
||||
void chainiv_module_exit(void)
|
||||
static void chainiv_module_exit(void)
|
||||
{
|
||||
crypto_unregister_template(&chainiv_tmpl);
|
||||
}
|
||||
|
||||
module_init(chainiv_module_init);
|
||||
module_exit(chainiv_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Chain IV Generator");
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
*/
|
||||
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/rng.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
|
@ -163,17 +163,22 @@ static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
|
|||
{
|
||||
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
|
||||
struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
|
||||
int err = 0;
|
||||
|
||||
spin_lock_bh(&ctx->lock);
|
||||
if (crypto_ablkcipher_crt(geniv)->givencrypt != eseqiv_givencrypt_first)
|
||||
goto unlock;
|
||||
|
||||
crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt;
|
||||
get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
|
||||
err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
|
||||
crypto_ablkcipher_ivsize(geniv));
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&ctx->lock);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return eseqiv_givencrypt(req);
|
||||
}
|
||||
|
||||
|
@ -216,9 +221,13 @@ static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
|
|||
struct crypto_instance *inst;
|
||||
int err;
|
||||
|
||||
err = crypto_get_default_rng();
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0);
|
||||
if (IS_ERR(inst))
|
||||
goto out;
|
||||
goto put_rng;
|
||||
|
||||
err = -EINVAL;
|
||||
if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize)
|
||||
|
@ -238,22 +247,36 @@ static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
|
|||
free_inst:
|
||||
skcipher_geniv_free(inst);
|
||||
inst = ERR_PTR(err);
|
||||
put_rng:
|
||||
crypto_put_default_rng();
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void eseqiv_free(struct crypto_instance *inst)
|
||||
{
|
||||
skcipher_geniv_free(inst);
|
||||
crypto_put_default_rng();
|
||||
}
|
||||
|
||||
static struct crypto_template eseqiv_tmpl = {
|
||||
.name = "eseqiv",
|
||||
.alloc = eseqiv_alloc,
|
||||
.free = skcipher_geniv_free,
|
||||
.free = eseqiv_free,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
int __init eseqiv_module_init(void)
|
||||
static int __init eseqiv_module_init(void)
|
||||
{
|
||||
return crypto_register_template(&eseqiv_tmpl);
|
||||
}
|
||||
|
||||
void __exit eseqiv_module_exit(void)
|
||||
static void __exit eseqiv_module_exit(void)
|
||||
{
|
||||
crypto_unregister_template(&eseqiv_tmpl);
|
||||
}
|
||||
|
||||
module_init(eseqiv_module_init);
|
||||
module_exit(eseqiv_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
|
||||
|
|
27
crypto/fips.c
Normal file
27
crypto/fips.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* FIPS 200 support.
|
||||
*
|
||||
* Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.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 "internal.h"
|
||||
|
||||
int fips_enabled;
|
||||
EXPORT_SYMBOL_GPL(fips_enabled);
|
||||
|
||||
/* Process kernel command-line parameter at boot time. fips=0 or fips=1 */
|
||||
static int fips_enable(char *str)
|
||||
{
|
||||
fips_enabled = !!simple_strtol(str, NULL, 0);
|
||||
printk(KERN_INFO "fips mode: %s\n",
|
||||
fips_enabled ? "enabled" : "disabled");
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("fips=", fips_enable);
|
|
@ -26,6 +26,12 @@
|
|||
#include <linux/rwsem.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#ifdef CONFIG_CRYPTO_FIPS
|
||||
extern int fips_enabled;
|
||||
#else
|
||||
#define fips_enabled 0
|
||||
#endif
|
||||
|
||||
/* Crypto notification events. */
|
||||
enum {
|
||||
CRYPTO_MSG_ALG_REQUEST,
|
||||
|
@ -82,7 +88,7 @@ static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg)
|
|||
}
|
||||
|
||||
struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
|
||||
struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask);
|
||||
struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, u32 mask);
|
||||
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
|
||||
|
||||
int crypto_init_digest_ops(struct crypto_tfm *tfm);
|
||||
|
@ -94,9 +100,11 @@ 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);
|
||||
|
||||
struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
|
||||
void crypto_larval_kill(struct crypto_alg *alg);
|
||||
struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
|
||||
void crypto_larval_error(const char *name, u32 type, u32 mask);
|
||||
void crypto_alg_tested(const char *name, int err);
|
||||
|
||||
void crypto_shoot_alg(struct crypto_alg *alg);
|
||||
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
|
||||
|
@ -107,6 +115,10 @@ int crypto_register_instance(struct crypto_template *tmpl,
|
|||
|
||||
int crypto_register_notifier(struct notifier_block *nb);
|
||||
int crypto_unregister_notifier(struct notifier_block *nb);
|
||||
int crypto_probing_notify(unsigned long val, void *v);
|
||||
|
||||
int __init testmgr_init(void);
|
||||
void testmgr_exit(void);
|
||||
|
||||
static inline void crypto_alg_put(struct crypto_alg *alg)
|
||||
{
|
||||
|
@ -139,9 +151,9 @@ static inline int crypto_is_moribund(struct crypto_alg *alg)
|
|||
return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING);
|
||||
}
|
||||
|
||||
static inline int crypto_notify(unsigned long val, void *v)
|
||||
static inline void crypto_notify(unsigned long val, void *v)
|
||||
{
|
||||
return blocking_notifier_call_chain(&crypto_chain, val, v);
|
||||
blocking_notifier_call_chain(&crypto_chain, val, v);
|
||||
}
|
||||
|
||||
#endif /* _CRYPTO_INTERNAL_H */
|
||||
|
|
66
crypto/krng.c
Normal file
66
crypto/krng.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* RNG implementation using standard kernel RNG.
|
||||
*
|
||||
* 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
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <crypto/internal/rng.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
static int krng_get_random(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen)
|
||||
{
|
||||
get_random_bytes(rdata, dlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int krng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct crypto_alg krng_alg = {
|
||||
.cra_name = "stdrng",
|
||||
.cra_driver_name = "krng",
|
||||
.cra_priority = 200,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_RNG,
|
||||
.cra_ctxsize = 0,
|
||||
.cra_type = &crypto_rng_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(krng_alg.cra_list),
|
||||
.cra_u = {
|
||||
.rng = {
|
||||
.rng_make_random = krng_get_random,
|
||||
.rng_reset = krng_reset,
|
||||
.seedsize = 0,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Module initalization */
|
||||
static int __init krng_mod_init(void)
|
||||
{
|
||||
return crypto_register_alg(&krng_alg);
|
||||
}
|
||||
|
||||
static void __exit krng_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&krng_alg);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(krng_mod_init);
|
||||
module_exit(krng_mod_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Kernel Random Number Generator");
|
||||
MODULE_ALIAS("stdrng");
|
|
@ -19,8 +19,53 @@
|
|||
#include <linux/rwsem.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef CONFIG_CRYPTO_FIPS
|
||||
static struct ctl_table crypto_sysctl_table[] = {
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "fips_enabled",
|
||||
.data = &fips_enabled,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0444,
|
||||
.proc_handler = &proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ctl_table crypto_dir_table[] = {
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "crypto",
|
||||
.mode = 0555,
|
||||
.child = crypto_sysctl_table
|
||||
},
|
||||
{
|
||||
.ctl_name = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ctl_table_header *crypto_sysctls;
|
||||
|
||||
static void crypto_proc_fips_init(void)
|
||||
{
|
||||
crypto_sysctls = register_sysctl_table(crypto_dir_table);
|
||||
}
|
||||
|
||||
static void crypto_proc_fips_exit(void)
|
||||
{
|
||||
if (crypto_sysctls)
|
||||
unregister_sysctl_table(crypto_sysctls);
|
||||
}
|
||||
#else
|
||||
#define crypto_proc_fips_init()
|
||||
#define crypto_proc_fips_exit()
|
||||
#endif
|
||||
|
||||
static void *c_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
down_read(&crypto_alg_sem);
|
||||
|
@ -46,8 +91,11 @@ static int c_show(struct seq_file *m, void *p)
|
|||
seq_printf(m, "module : %s\n", module_name(alg->cra_module));
|
||||
seq_printf(m, "priority : %d\n", alg->cra_priority);
|
||||
seq_printf(m, "refcnt : %d\n", atomic_read(&alg->cra_refcnt));
|
||||
seq_printf(m, "selftest : %s\n",
|
||||
(alg->cra_flags & CRYPTO_ALG_TESTED) ?
|
||||
"passed" : "unknown");
|
||||
|
||||
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
|
||||
switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
|
||||
case CRYPTO_ALG_TYPE_CIPHER:
|
||||
seq_printf(m, "type : cipher\n");
|
||||
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
|
||||
|
@ -67,7 +115,10 @@ static int c_show(struct seq_file *m, void *p)
|
|||
seq_printf(m, "type : compression\n");
|
||||
break;
|
||||
default:
|
||||
if (alg->cra_type && alg->cra_type->show)
|
||||
if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
|
||||
seq_printf(m, "type : larval\n");
|
||||
seq_printf(m, "flags : 0x%x\n", alg->cra_flags);
|
||||
} else if (alg->cra_type && alg->cra_type->show)
|
||||
alg->cra_type->show(m, alg);
|
||||
else
|
||||
seq_printf(m, "type : unknown\n");
|
||||
|
@ -100,9 +151,11 @@ static const struct file_operations proc_crypto_ops = {
|
|||
void __init crypto_init_proc(void)
|
||||
{
|
||||
proc_create("crypto", 0, NULL, &proc_crypto_ops);
|
||||
crypto_proc_fips_init();
|
||||
}
|
||||
|
||||
void __exit crypto_exit_proc(void)
|
||||
{
|
||||
crypto_proc_fips_exit();
|
||||
remove_proc_entry("crypto", NULL);
|
||||
}
|
||||
|
|
126
crypto/rng.c
Normal file
126
crypto/rng.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* RNG operations.
|
||||
*
|
||||
* Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.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 <asm/atomic.h>
|
||||
#include <crypto/internal/rng.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
static DEFINE_MUTEX(crypto_default_rng_lock);
|
||||
struct crypto_rng *crypto_default_rng;
|
||||
EXPORT_SYMBOL_GPL(crypto_default_rng);
|
||||
static int crypto_default_rng_refcnt;
|
||||
|
||||
static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
|
||||
{
|
||||
u8 *buf = NULL;
|
||||
int err;
|
||||
|
||||
if (!seed && slen) {
|
||||
buf = kmalloc(slen, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
get_random_bytes(buf, slen);
|
||||
seed = buf;
|
||||
}
|
||||
|
||||
err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen);
|
||||
|
||||
kfree(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
{
|
||||
struct rng_alg *alg = &tfm->__crt_alg->cra_rng;
|
||||
struct rng_tfm *ops = &tfm->crt_rng;
|
||||
|
||||
ops->rng_gen_random = alg->rng_make_random;
|
||||
ops->rng_reset = rngapi_reset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
{
|
||||
seq_printf(m, "type : rng\n");
|
||||
seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize);
|
||||
}
|
||||
|
||||
static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
return alg->cra_ctxsize;
|
||||
}
|
||||
|
||||
const struct crypto_type crypto_rng_type = {
|
||||
.ctxsize = crypto_rng_ctxsize,
|
||||
.init = crypto_init_rng_ops,
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_rng_show,
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_rng_type);
|
||||
|
||||
int crypto_get_default_rng(void)
|
||||
{
|
||||
struct crypto_rng *rng;
|
||||
int err;
|
||||
|
||||
mutex_lock(&crypto_default_rng_lock);
|
||||
if (!crypto_default_rng) {
|
||||
rng = crypto_alloc_rng("stdrng", 0, 0);
|
||||
err = PTR_ERR(rng);
|
||||
if (IS_ERR(rng))
|
||||
goto unlock;
|
||||
|
||||
err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
|
||||
if (err) {
|
||||
crypto_free_rng(rng);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
crypto_default_rng = rng;
|
||||
}
|
||||
|
||||
crypto_default_rng_refcnt++;
|
||||
err = 0;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&crypto_default_rng_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_get_default_rng);
|
||||
|
||||
void crypto_put_default_rng(void)
|
||||
{
|
||||
mutex_lock(&crypto_default_rng_lock);
|
||||
if (!--crypto_default_rng_refcnt) {
|
||||
crypto_free_rng(crypto_default_rng);
|
||||
crypto_default_rng = NULL;
|
||||
}
|
||||
mutex_unlock(&crypto_default_rng_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_put_default_rng);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Random Number Genertor");
|
|
@ -15,11 +15,11 @@
|
|||
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/rng.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
|
@ -189,17 +189,22 @@ static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
|
|||
{
|
||||
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
|
||||
struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
|
||||
int err = 0;
|
||||
|
||||
spin_lock_bh(&ctx->lock);
|
||||
if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first)
|
||||
goto unlock;
|
||||
|
||||
crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt;
|
||||
get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
|
||||
err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
|
||||
crypto_ablkcipher_ivsize(geniv));
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&ctx->lock);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return seqiv_givencrypt(req);
|
||||
}
|
||||
|
||||
|
@ -207,17 +212,22 @@ static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req)
|
|||
{
|
||||
struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
|
||||
struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
|
||||
int err = 0;
|
||||
|
||||
spin_lock_bh(&ctx->lock);
|
||||
if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first)
|
||||
goto unlock;
|
||||
|
||||
crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt;
|
||||
get_random_bytes(ctx->salt, crypto_aead_ivsize(geniv));
|
||||
err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
|
||||
crypto_aead_ivsize(geniv));
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&ctx->lock);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return seqiv_aead_givencrypt(req);
|
||||
}
|
||||
|
||||
|
@ -298,19 +308,27 @@ static struct crypto_instance *seqiv_alloc(struct rtattr **tb)
|
|||
if (IS_ERR(algt))
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = crypto_get_default_rng();
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
|
||||
inst = seqiv_ablkcipher_alloc(tb);
|
||||
else
|
||||
inst = seqiv_aead_alloc(tb);
|
||||
|
||||
if (IS_ERR(inst))
|
||||
goto out;
|
||||
goto put_rng;
|
||||
|
||||
inst->alg.cra_alignmask |= __alignof__(u32) - 1;
|
||||
inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
|
||||
|
||||
out:
|
||||
return inst;
|
||||
|
||||
put_rng:
|
||||
crypto_put_default_rng();
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void seqiv_free(struct crypto_instance *inst)
|
||||
|
@ -319,6 +337,7 @@ static void seqiv_free(struct crypto_instance *inst)
|
|||
skcipher_geniv_free(inst);
|
||||
else
|
||||
aead_geniv_free(inst);
|
||||
crypto_put_default_rng();
|
||||
}
|
||||
|
||||
static struct crypto_template seqiv_tmpl = {
|
||||
|
|
1347
crypto/tcrypt.c
1347
crypto/tcrypt.c
File diff suppressed because it is too large
Load diff
8709
crypto/tcrypt.h
8709
crypto/tcrypt.h
File diff suppressed because it is too large
Load diff
1868
crypto/testmgr.c
Normal file
1868
crypto/testmgr.c
Normal file
File diff suppressed because it is too large
Load diff
8738
crypto/testmgr.h
Normal file
8738
crypto/testmgr.h
Normal file
File diff suppressed because it is too large
Load diff
26
include/crypto/internal/rng.h
Normal file
26
include/crypto/internal/rng.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* RNG: Random Number Generator algorithms under the crypto API
|
||||
*
|
||||
* Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_INTERNAL_RNG_H
|
||||
#define _CRYPTO_INTERNAL_RNG_H
|
||||
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/rng.h>
|
||||
|
||||
extern const struct crypto_type crypto_rng_type;
|
||||
|
||||
static inline void *crypto_rng_ctx(struct crypto_rng *tfm)
|
||||
{
|
||||
return crypto_tfm_ctx(&tfm->base);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/skcipher.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct rtattr;
|
||||
|
@ -65,11 +64,6 @@ void skcipher_geniv_free(struct crypto_instance *inst);
|
|||
int skcipher_geniv_init(struct crypto_tfm *tfm);
|
||||
void skcipher_geniv_exit(struct crypto_tfm *tfm);
|
||||
|
||||
int __init eseqiv_module_init(void);
|
||||
void __exit eseqiv_module_exit(void);
|
||||
int __init chainiv_module_init(void);
|
||||
void chainiv_module_exit(void);
|
||||
|
||||
static inline struct crypto_ablkcipher *skcipher_geniv_cipher(
|
||||
struct crypto_ablkcipher *geniv)
|
||||
{
|
||||
|
|
75
include/crypto/rng.h
Normal file
75
include/crypto/rng.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* RNG: Random Number Generator algorithms under the crypto API
|
||||
*
|
||||
* Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_RNG_H
|
||||
#define _CRYPTO_RNG_H
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
extern struct crypto_rng *crypto_default_rng;
|
||||
|
||||
int crypto_get_default_rng(void);
|
||||
void crypto_put_default_rng(void);
|
||||
|
||||
static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm)
|
||||
{
|
||||
return (struct crypto_rng *)tfm;
|
||||
}
|
||||
|
||||
static inline struct crypto_rng *crypto_alloc_rng(const char *alg_name,
|
||||
u32 type, u32 mask)
|
||||
{
|
||||
type &= ~CRYPTO_ALG_TYPE_MASK;
|
||||
type |= CRYPTO_ALG_TYPE_RNG;
|
||||
mask |= CRYPTO_ALG_TYPE_MASK;
|
||||
|
||||
return __crypto_rng_cast(crypto_alloc_base(alg_name, type, mask));
|
||||
}
|
||||
|
||||
static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm)
|
||||
{
|
||||
return &tfm->base;
|
||||
}
|
||||
|
||||
static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm)
|
||||
{
|
||||
return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng;
|
||||
}
|
||||
|
||||
static inline struct rng_tfm *crypto_rng_crt(struct crypto_rng *tfm)
|
||||
{
|
||||
return &crypto_rng_tfm(tfm)->crt_rng;
|
||||
}
|
||||
|
||||
static inline void crypto_free_rng(struct crypto_rng *tfm)
|
||||
{
|
||||
crypto_free_tfm(crypto_rng_tfm(tfm));
|
||||
}
|
||||
|
||||
static inline int crypto_rng_get_bytes(struct crypto_rng *tfm,
|
||||
u8 *rdata, unsigned int dlen)
|
||||
{
|
||||
return crypto_rng_crt(tfm)->rng_gen_random(tfm, rdata, dlen);
|
||||
}
|
||||
|
||||
static inline int crypto_rng_reset(struct crypto_rng *tfm,
|
||||
u8 *seed, unsigned int slen)
|
||||
{
|
||||
return crypto_rng_crt(tfm)->rng_reset(tfm, seed, slen);
|
||||
}
|
||||
|
||||
static inline int crypto_rng_seedsize(struct crypto_rng *tfm)
|
||||
{
|
||||
return crypto_rng_alg(tfm)->seedsize;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -38,6 +38,7 @@
|
|||
#define CRYPTO_ALG_TYPE_DIGEST 0x00000008
|
||||
#define CRYPTO_ALG_TYPE_HASH 0x00000009
|
||||
#define CRYPTO_ALG_TYPE_AHASH 0x0000000a
|
||||
#define CRYPTO_ALG_TYPE_RNG 0x0000000c
|
||||
|
||||
#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
|
||||
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c
|
||||
|
@ -60,6 +61,14 @@
|
|||
*/
|
||||
#define CRYPTO_ALG_GENIV 0x00000200
|
||||
|
||||
/*
|
||||
* Set if the algorithm has passed automated run-time testing. Note that
|
||||
* if there is no run-time testing for a given algorithm it is considered
|
||||
* to have passed.
|
||||
*/
|
||||
|
||||
#define CRYPTO_ALG_TESTED 0x00000400
|
||||
|
||||
/*
|
||||
* Transform masks and values (for crt_flags).
|
||||
*/
|
||||
|
@ -105,6 +114,7 @@ struct crypto_aead;
|
|||
struct crypto_blkcipher;
|
||||
struct crypto_hash;
|
||||
struct crypto_ahash;
|
||||
struct crypto_rng;
|
||||
struct crypto_tfm;
|
||||
struct crypto_type;
|
||||
struct aead_givcrypt_request;
|
||||
|
@ -290,6 +300,15 @@ struct compress_alg {
|
|||
unsigned int slen, u8 *dst, unsigned int *dlen);
|
||||
};
|
||||
|
||||
struct rng_alg {
|
||||
int (*rng_make_random)(struct crypto_rng *tfm, u8 *rdata,
|
||||
unsigned int dlen);
|
||||
int (*rng_reset)(struct crypto_rng *tfm, u8 *seed, unsigned int slen);
|
||||
|
||||
unsigned int seedsize;
|
||||
};
|
||||
|
||||
|
||||
#define cra_ablkcipher cra_u.ablkcipher
|
||||
#define cra_aead cra_u.aead
|
||||
#define cra_blkcipher cra_u.blkcipher
|
||||
|
@ -298,6 +317,7 @@ struct compress_alg {
|
|||
#define cra_hash cra_u.hash
|
||||
#define cra_ahash cra_u.ahash
|
||||
#define cra_compress cra_u.compress
|
||||
#define cra_rng cra_u.rng
|
||||
|
||||
struct crypto_alg {
|
||||
struct list_head cra_list;
|
||||
|
@ -325,6 +345,7 @@ struct crypto_alg {
|
|||
struct hash_alg hash;
|
||||
struct ahash_alg ahash;
|
||||
struct compress_alg compress;
|
||||
struct rng_alg rng;
|
||||
} cra_u;
|
||||
|
||||
int (*cra_init)(struct crypto_tfm *tfm);
|
||||
|
@ -430,6 +451,12 @@ struct compress_tfm {
|
|||
u8 *dst, unsigned int *dlen);
|
||||
};
|
||||
|
||||
struct rng_tfm {
|
||||
int (*rng_gen_random)(struct crypto_rng *tfm, u8 *rdata,
|
||||
unsigned int dlen);
|
||||
int (*rng_reset)(struct crypto_rng *tfm, u8 *seed, unsigned int slen);
|
||||
};
|
||||
|
||||
#define crt_ablkcipher crt_u.ablkcipher
|
||||
#define crt_aead crt_u.aead
|
||||
#define crt_blkcipher crt_u.blkcipher
|
||||
|
@ -437,6 +464,7 @@ struct compress_tfm {
|
|||
#define crt_hash crt_u.hash
|
||||
#define crt_ahash crt_u.ahash
|
||||
#define crt_compress crt_u.compress
|
||||
#define crt_rng crt_u.rng
|
||||
|
||||
struct crypto_tfm {
|
||||
|
||||
|
@ -450,6 +478,7 @@ struct crypto_tfm {
|
|||
struct hash_tfm hash;
|
||||
struct ahash_tfm ahash;
|
||||
struct compress_tfm compress;
|
||||
struct rng_tfm rng;
|
||||
} crt_u;
|
||||
|
||||
struct crypto_alg *__crt_alg;
|
||||
|
@ -481,6 +510,10 @@ struct crypto_hash {
|
|||
struct crypto_tfm base;
|
||||
};
|
||||
|
||||
struct crypto_rng {
|
||||
struct crypto_tfm base;
|
||||
};
|
||||
|
||||
enum {
|
||||
CRYPTOA_UNSPEC,
|
||||
CRYPTOA_ALG,
|
||||
|
@ -515,6 +548,8 @@ struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
|
|||
struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask);
|
||||
void crypto_free_tfm(struct crypto_tfm *tfm);
|
||||
|
||||
int alg_test(const char *driver, const char *alg, u32 type, u32 mask);
|
||||
|
||||
/*
|
||||
* Transform helpers which query the underlying algorithm.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue