Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu: "Here is the crypto update for 5.3: API: - Test shash interface directly in testmgr - cra_driver_name is now mandatory Algorithms: - Replace arc4 crypto_cipher with library helper - Implement 5 way interleave for ECB, CBC and CTR on arm64 - Add xxhash - Add continuous self-test on noise source to drbg - Update jitter RNG Drivers: - Add support for SHA204A random number generator - Add support for 7211 in iproc-rng200 - Fix fuzz test failures in inside-secure - Fix fuzz test failures in talitos - Fix fuzz test failures in qat" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (143 commits) crypto: stm32/hash - remove interruptible condition for dma crypto: stm32/hash - Fix hmac issue more than 256 bytes crypto: stm32/crc32 - rename driver file crypto: amcc - remove memset after dma_alloc_coherent crypto: ccp - Switch to SPDX license identifiers crypto: ccp - Validate the the error value used to index error messages crypto: doc - Fix formatting of new crypto engine content crypto: doc - Add parameter documentation crypto: arm64/aes-ce - implement 5 way interleave for ECB, CBC and CTR crypto: arm64/aes-ce - add 5 way interleave routines crypto: talitos - drop icv_ool crypto: talitos - fix hash on SEC1. crypto: talitos - move struct talitos_edesc into talitos.h lib/scatterlist: Fix mapping iterator when sg->offset is greater than PAGE_SIZE crypto/NX: Set receive window credits to max number of CRBs in RxFIFO crypto: asymmetric_keys - select CRYPTO_HASH where needed crypto: serpent - mark __serpent_setkey_sbox noinline crypto: testmgr - dynamically allocate crypto_shash crypto: testmgr - dynamically allocate testvec_config crypto: talitos - eliminate unneeded 'done' functions at build time ...
This commit is contained in:
@@ -61,7 +61,6 @@ config CRYPTO_BLKCIPHER2
|
||||
tristate
|
||||
select CRYPTO_ALGAPI2
|
||||
select CRYPTO_RNG2
|
||||
select CRYPTO_WORKQUEUE
|
||||
|
||||
config CRYPTO_HASH
|
||||
tristate
|
||||
@@ -137,10 +136,11 @@ config CRYPTO_USER
|
||||
Userspace configuration for cryptographic instantiations such as
|
||||
cbc(aes).
|
||||
|
||||
if CRYPTO_MANAGER2
|
||||
|
||||
config CRYPTO_MANAGER_DISABLE_TESTS
|
||||
bool "Disable run-time self tests"
|
||||
default y
|
||||
depends on CRYPTO_MANAGER2
|
||||
help
|
||||
Disable run-time self tests that normally take place at
|
||||
algorithm registration.
|
||||
@@ -155,14 +155,10 @@ config CRYPTO_MANAGER_EXTRA_TESTS
|
||||
This is intended for developer use only, as these tests take much
|
||||
longer to run than the normal self tests.
|
||||
|
||||
endif # if CRYPTO_MANAGER2
|
||||
|
||||
config CRYPTO_GF128MUL
|
||||
tristate "GF(2^128) multiplication functions"
|
||||
help
|
||||
Efficient table driven implementation of multiplications in the
|
||||
field GF(2^128). This is needed by some cypher modes. This
|
||||
option will be selected automatically if you select such a
|
||||
cipher mode. Only select this option by hand if you expect to load
|
||||
an external module that requires these functions.
|
||||
tristate
|
||||
|
||||
config CRYPTO_NULL
|
||||
tristate "Null algorithms"
|
||||
@@ -186,15 +182,11 @@ config CRYPTO_PCRYPT
|
||||
This converts an arbitrary crypto algorithm into a parallel
|
||||
algorithm that executes in kernel threads.
|
||||
|
||||
config CRYPTO_WORKQUEUE
|
||||
tristate
|
||||
|
||||
config CRYPTO_CRYPTD
|
||||
tristate "Software async crypto daemon"
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_MANAGER
|
||||
select CRYPTO_WORKQUEUE
|
||||
help
|
||||
This is a generic software asynchronous crypto daemon that
|
||||
converts an arbitrary synchronous software crypto algorithm
|
||||
@@ -279,6 +271,7 @@ config CRYPTO_CCM
|
||||
select CRYPTO_CTR
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
Support for Counter with CBC MAC. Required for IPsec.
|
||||
|
||||
@@ -288,6 +281,7 @@ config CRYPTO_GCM
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_GHASH
|
||||
select CRYPTO_NULL
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
Support for Galois/Counter Mode (GCM) and Galois Message
|
||||
Authentication Code (GMAC). Required for IPSec.
|
||||
@@ -297,6 +291,7 @@ config CRYPTO_CHACHA20POLY1305
|
||||
select CRYPTO_CHACHA20
|
||||
select CRYPTO_POLY1305
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
ChaCha20-Poly1305 AEAD support, RFC7539.
|
||||
|
||||
@@ -411,6 +406,7 @@ config CRYPTO_SEQIV
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_NULL
|
||||
select CRYPTO_RNG_DEFAULT
|
||||
select CRYPTO_MANAGER
|
||||
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
|
||||
@@ -420,7 +416,7 @@ config CRYPTO_ECHAINIV
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_NULL
|
||||
select CRYPTO_RNG_DEFAULT
|
||||
default m
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
This IV generator generates an IV based on the encryption of
|
||||
a sequence number xored with a salt. This is the default
|
||||
@@ -456,6 +452,7 @@ config CRYPTO_CTR
|
||||
config CRYPTO_CTS
|
||||
tristate "CTS support"
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
CTS: Cipher Text Stealing
|
||||
This is the Cipher Text Stealing mode as described by
|
||||
@@ -521,6 +518,7 @@ config CRYPTO_XTS
|
||||
config CRYPTO_KEYWRAP
|
||||
tristate "Key wrapping support"
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
Support for key wrapping (NIST SP800-38F / RFC3394) without
|
||||
padding.
|
||||
@@ -551,6 +549,7 @@ config CRYPTO_ADIANTUM
|
||||
select CRYPTO_CHACHA20
|
||||
select CRYPTO_POLY1305
|
||||
select CRYPTO_NHPOLY1305
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
Adiantum is a tweakable, length-preserving encryption mode
|
||||
designed for fast and secure disk encryption, especially on
|
||||
@@ -684,6 +683,14 @@ config CRYPTO_CRC32_MIPS
|
||||
instructions, when available.
|
||||
|
||||
|
||||
config CRYPTO_XXHASH
|
||||
tristate "xxHash hash algorithm"
|
||||
select CRYPTO_HASH
|
||||
select XXHASH
|
||||
help
|
||||
xxHash non-cryptographic hash algorithm. Extremely fast, working at
|
||||
speeds close to RAM limits.
|
||||
|
||||
config CRYPTO_CRCT10DIF
|
||||
tristate "CRCT10DIF algorithm"
|
||||
select CRYPTO_HASH
|
||||
@@ -1230,9 +1237,13 @@ config CRYPTO_ANUBIS
|
||||
<https://www.cosic.esat.kuleuven.be/nessie/reports/>
|
||||
<http://www.larc.usp.br/~pbarreto/AnubisPage.html>
|
||||
|
||||
config CRYPTO_LIB_ARC4
|
||||
tristate
|
||||
|
||||
config CRYPTO_ARC4
|
||||
tristate "ARC4 cipher algorithm"
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_LIB_ARC4
|
||||
help
|
||||
ARC4 cipher algorithm.
|
||||
|
||||
|
@@ -6,8 +6,6 @@
|
||||
obj-$(CONFIG_CRYPTO) += crypto.o
|
||||
crypto-y := api.o cipher.o compress.o memneq.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_ENGINE) += crypto_engine.o
|
||||
obj-$(CONFIG_CRYPTO_FIPS) += fips.o
|
||||
|
||||
@@ -131,6 +129,7 @@ obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
|
||||
obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o
|
||||
obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
|
||||
obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
|
||||
obj-$(CONFIG_CRYPTO_XXHASH) += xxhash_generic.o
|
||||
obj-$(CONFIG_CRYPTO_842) += 842.o
|
||||
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
|
||||
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
|
||||
|
@@ -84,6 +84,42 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
|
||||
|
||||
int crypto_aead_encrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct crypto_alg *alg = aead->base.__crt_alg;
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
int ret;
|
||||
|
||||
crypto_stats_get(alg);
|
||||
if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
|
||||
ret = -ENOKEY;
|
||||
else
|
||||
ret = crypto_aead_alg(aead)->encrypt(req);
|
||||
crypto_stats_aead_encrypt(cryptlen, alg, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_aead_encrypt);
|
||||
|
||||
int crypto_aead_decrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct crypto_alg *alg = aead->base.__crt_alg;
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
int ret;
|
||||
|
||||
crypto_stats_get(alg);
|
||||
if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
|
||||
ret = -ENOKEY;
|
||||
else if (req->cryptlen < crypto_aead_authsize(aead))
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = crypto_aead_alg(aead)->decrypt(req);
|
||||
crypto_stats_aead_decrypt(cryptlen, alg, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_aead_decrypt);
|
||||
|
||||
static void crypto_aead_exit_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_aead *aead = __crypto_aead_cast(tfm);
|
||||
|
@@ -21,23 +21,6 @@
|
||||
|
||||
static LIST_HEAD(crypto_template_list);
|
||||
|
||||
static inline int crypto_set_driver_name(struct crypto_alg *alg)
|
||||
{
|
||||
static const char suffix[] = "-generic";
|
||||
char *driver_name = alg->cra_driver_name;
|
||||
int len;
|
||||
|
||||
if (*driver_name)
|
||||
return 0;
|
||||
|
||||
len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
|
||||
if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
memcpy(driver_name + len, suffix, sizeof(suffix));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void crypto_check_module_sig(struct module *mod)
|
||||
{
|
||||
if (fips_enabled && mod && !module_sig_ok(mod))
|
||||
@@ -49,6 +32,9 @@ static int crypto_check_alg(struct crypto_alg *alg)
|
||||
{
|
||||
crypto_check_module_sig(alg->cra_module);
|
||||
|
||||
if (!alg->cra_name[0] || !alg->cra_driver_name[0])
|
||||
return -EINVAL;
|
||||
|
||||
if (alg->cra_alignmask & (alg->cra_alignmask + 1))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -74,7 +60,7 @@ static int crypto_check_alg(struct crypto_alg *alg)
|
||||
|
||||
refcount_set(&alg->cra_refcnt, 1);
|
||||
|
||||
return crypto_set_driver_name(alg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crypto_free_instance(struct crypto_instance *inst)
|
||||
@@ -947,19 +933,6 @@ struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_dequeue_request);
|
||||
|
||||
int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_async_request *req;
|
||||
|
||||
list_for_each_entry(req, &queue->list, list) {
|
||||
if (req->tfm == tfm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
|
||||
|
||||
static inline void crypto_inc_byte(u8 *a, unsigned int size)
|
||||
{
|
||||
u8 *b = (a + size);
|
||||
|
@@ -673,6 +673,7 @@ static void anubis_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
|
||||
static struct crypto_alg anubis_alg = {
|
||||
.cra_name = "anubis",
|
||||
.cra_driver_name = "anubis-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = ANUBIS_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof (struct anubis_ctx),
|
||||
|
125
crypto/arc4.c
125
crypto/arc4.c
@@ -13,84 +13,15 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
struct arc4_ctx {
|
||||
u32 S[256];
|
||||
u32 x, y;
|
||||
};
|
||||
|
||||
static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
static int crypto_arc4_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int i, j = 0, k = 0;
|
||||
struct arc4_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
|
||||
ctx->x = 1;
|
||||
ctx->y = 0;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
ctx->S[i] = i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
u32 a = ctx->S[i];
|
||||
j = (j + in_key[k] + a) & 0xff;
|
||||
ctx->S[i] = ctx->S[j];
|
||||
ctx->S[j] = a;
|
||||
if (++k >= key_len)
|
||||
k = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return arc4_setkey(ctx, in_key, key_len);
|
||||
}
|
||||
|
||||
static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
return arc4_set_key(&tfm->base, in_key, key_len);
|
||||
}
|
||||
|
||||
static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in,
|
||||
unsigned int len)
|
||||
{
|
||||
u32 *const S = ctx->S;
|
||||
u32 x, y, a, b;
|
||||
u32 ty, ta, tb;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
x = ctx->x;
|
||||
y = ctx->y;
|
||||
|
||||
a = S[x];
|
||||
y = (y + a) & 0xff;
|
||||
b = S[y];
|
||||
|
||||
do {
|
||||
S[y] = a;
|
||||
a = (a + b) & 0xff;
|
||||
S[x] = b;
|
||||
x = (x + 1) & 0xff;
|
||||
ta = S[x];
|
||||
ty = (y + ta) & 0xff;
|
||||
tb = S[ty];
|
||||
*out++ = *in++ ^ S[a];
|
||||
if (--len == 0)
|
||||
break;
|
||||
y = ty;
|
||||
a = ta;
|
||||
b = tb;
|
||||
} while (true);
|
||||
|
||||
ctx->x = x;
|
||||
ctx->y = y;
|
||||
}
|
||||
|
||||
static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in)
|
||||
{
|
||||
arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1);
|
||||
}
|
||||
|
||||
static int ecb_arc4_crypt(struct skcipher_request *req)
|
||||
static int crypto_arc4_crypt(struct skcipher_request *req)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct arc4_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
@@ -108,54 +39,32 @@ static int ecb_arc4_crypt(struct skcipher_request *req)
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct crypto_alg arc4_cipher = {
|
||||
.cra_name = "arc4",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = ARC4_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct arc4_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_u = {
|
||||
.cipher = {
|
||||
.cia_min_keysize = ARC4_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = ARC4_MAX_KEY_SIZE,
|
||||
.cia_setkey = arc4_set_key,
|
||||
.cia_encrypt = arc4_crypt_one,
|
||||
.cia_decrypt = arc4_crypt_one,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct skcipher_alg arc4_skcipher = {
|
||||
static struct skcipher_alg arc4_alg = {
|
||||
/*
|
||||
* For legacy reasons, this is named "ecb(arc4)", not "arc4".
|
||||
* Nevertheless it's actually a stream cipher, not a block cipher.
|
||||
*/
|
||||
.base.cra_name = "ecb(arc4)",
|
||||
.base.cra_driver_name = "ecb(arc4)-generic",
|
||||
.base.cra_priority = 100,
|
||||
.base.cra_blocksize = ARC4_BLOCK_SIZE,
|
||||
.base.cra_ctxsize = sizeof(struct arc4_ctx),
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.min_keysize = ARC4_MIN_KEY_SIZE,
|
||||
.max_keysize = ARC4_MAX_KEY_SIZE,
|
||||
.setkey = arc4_set_key_skcipher,
|
||||
.encrypt = ecb_arc4_crypt,
|
||||
.decrypt = ecb_arc4_crypt,
|
||||
.setkey = crypto_arc4_setkey,
|
||||
.encrypt = crypto_arc4_crypt,
|
||||
.decrypt = crypto_arc4_crypt,
|
||||
};
|
||||
|
||||
static int __init arc4_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = crypto_register_alg(&arc4_cipher);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crypto_register_skcipher(&arc4_skcipher);
|
||||
if (err)
|
||||
crypto_unregister_alg(&arc4_cipher);
|
||||
return err;
|
||||
return crypto_register_skcipher(&arc4_alg);
|
||||
}
|
||||
|
||||
static void __exit arc4_exit(void)
|
||||
{
|
||||
crypto_unregister_alg(&arc4_cipher);
|
||||
crypto_unregister_skcipher(&arc4_skcipher);
|
||||
crypto_unregister_skcipher(&arc4_alg);
|
||||
}
|
||||
|
||||
subsys_initcall(arc4_init);
|
||||
@@ -164,4 +73,4 @@ module_exit(arc4_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
|
||||
MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
|
||||
MODULE_ALIAS_CRYPTO("arc4");
|
||||
MODULE_ALIAS_CRYPTO("ecb(arc4)");
|
||||
|
@@ -15,6 +15,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
select MPILIB
|
||||
select CRYPTO_HASH_INFO
|
||||
select CRYPTO_AKCIPHER
|
||||
select CRYPTO_HASH
|
||||
help
|
||||
This option provides support for asymmetric public key type handling.
|
||||
If signature generation and/or verification are to be used,
|
||||
@@ -65,6 +66,7 @@ config TPM_KEY_PARSER
|
||||
config PKCS7_MESSAGE_PARSER
|
||||
tristate "PKCS#7 message parser"
|
||||
depends on X509_CERTIFICATE_PARSER
|
||||
select CRYPTO_HASH
|
||||
select ASN1
|
||||
select OID_REGISTRY
|
||||
help
|
||||
@@ -87,6 +89,7 @@ config SIGNED_PE_FILE_VERIFICATION
|
||||
bool "Support for PE file signature verification"
|
||||
depends on PKCS7_MESSAGE_PARSER=y
|
||||
depends on SYSTEM_DATA_VERIFICATION
|
||||
select CRYPTO_HASH
|
||||
select ASN1
|
||||
select OID_REGISTRY
|
||||
help
|
||||
|
@@ -61,6 +61,8 @@ struct chachapoly_req_ctx {
|
||||
unsigned int cryptlen;
|
||||
/* Actual AD, excluding IV */
|
||||
unsigned int assoclen;
|
||||
/* request flags, with MAY_SLEEP cleared if needed */
|
||||
u32 flags;
|
||||
union {
|
||||
struct poly_req poly;
|
||||
struct chacha_req chacha;
|
||||
@@ -70,8 +72,12 @@ struct chachapoly_req_ctx {
|
||||
static inline void async_done_continue(struct aead_request *req, int err,
|
||||
int (*cont)(struct aead_request *))
|
||||
{
|
||||
if (!err)
|
||||
if (!err) {
|
||||
struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
|
||||
|
||||
rctx->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
err = cont(req);
|
||||
}
|
||||
|
||||
if (err != -EINPROGRESS && err != -EBUSY)
|
||||
aead_request_complete(req, err);
|
||||
@@ -129,16 +135,12 @@ static int chacha_decrypt(struct aead_request *req)
|
||||
|
||||
chacha_iv(creq->iv, req, 1);
|
||||
|
||||
sg_init_table(rctx->src, 2);
|
||||
src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
|
||||
dst = src;
|
||||
|
||||
if (req->src != req->dst) {
|
||||
sg_init_table(rctx->dst, 2);
|
||||
if (req->src != req->dst)
|
||||
dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
|
||||
}
|
||||
|
||||
skcipher_request_set_callback(&creq->req, aead_request_flags(req),
|
||||
skcipher_request_set_callback(&creq->req, rctx->flags,
|
||||
chacha_decrypt_done, req);
|
||||
skcipher_request_set_tfm(&creq->req, ctx->chacha);
|
||||
skcipher_request_set_crypt(&creq->req, src, dst,
|
||||
@@ -172,17 +174,13 @@ static int poly_tail(struct aead_request *req)
|
||||
struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
|
||||
struct poly_req *preq = &rctx->u.poly;
|
||||
__le64 len;
|
||||
int err;
|
||||
|
||||
sg_init_table(preq->src, 1);
|
||||
len = cpu_to_le64(rctx->assoclen);
|
||||
memcpy(&preq->tail.assoclen, &len, sizeof(len));
|
||||
len = cpu_to_le64(rctx->cryptlen);
|
||||
memcpy(&preq->tail.cryptlen, &len, sizeof(len));
|
||||
sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail));
|
||||
preq->tail.assoclen = cpu_to_le64(rctx->assoclen);
|
||||
preq->tail.cryptlen = cpu_to_le64(rctx->cryptlen);
|
||||
sg_init_one(preq->src, &preq->tail, sizeof(preq->tail));
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_tail_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
ahash_request_set_crypt(&preq->req, preq->src,
|
||||
@@ -205,15 +203,14 @@ static int poly_cipherpad(struct aead_request *req)
|
||||
struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
|
||||
struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
|
||||
struct poly_req *preq = &rctx->u.poly;
|
||||
unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
|
||||
unsigned int padlen;
|
||||
int err;
|
||||
|
||||
padlen = (bs - (rctx->cryptlen % bs)) % bs;
|
||||
padlen = -rctx->cryptlen % POLY1305_BLOCK_SIZE;
|
||||
memset(preq->pad, 0, sizeof(preq->pad));
|
||||
sg_init_table(preq->src, 1);
|
||||
sg_set_buf(preq->src, &preq->pad, padlen);
|
||||
sg_init_one(preq->src, preq->pad, padlen);
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_cipherpad_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
|
||||
@@ -241,10 +238,9 @@ static int poly_cipher(struct aead_request *req)
|
||||
if (rctx->cryptlen == req->cryptlen) /* encrypting */
|
||||
crypt = req->dst;
|
||||
|
||||
sg_init_table(rctx->src, 2);
|
||||
crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen);
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_cipher_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen);
|
||||
@@ -266,15 +262,14 @@ static int poly_adpad(struct aead_request *req)
|
||||
struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
|
||||
struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
|
||||
struct poly_req *preq = &rctx->u.poly;
|
||||
unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
|
||||
unsigned int padlen;
|
||||
int err;
|
||||
|
||||
padlen = (bs - (rctx->assoclen % bs)) % bs;
|
||||
padlen = -rctx->assoclen % POLY1305_BLOCK_SIZE;
|
||||
memset(preq->pad, 0, sizeof(preq->pad));
|
||||
sg_init_table(preq->src, 1);
|
||||
sg_set_buf(preq->src, preq->pad, padlen);
|
||||
sg_init_one(preq->src, preq->pad, padlen);
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_adpad_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
|
||||
@@ -298,7 +293,7 @@ static int poly_ad(struct aead_request *req)
|
||||
struct poly_req *preq = &rctx->u.poly;
|
||||
int err;
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_ad_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen);
|
||||
@@ -322,10 +317,9 @@ static int poly_setkey(struct aead_request *req)
|
||||
struct poly_req *preq = &rctx->u.poly;
|
||||
int err;
|
||||
|
||||
sg_init_table(preq->src, 1);
|
||||
sg_set_buf(preq->src, rctx->key, sizeof(rctx->key));
|
||||
sg_init_one(preq->src, rctx->key, sizeof(rctx->key));
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_setkey_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key));
|
||||
@@ -349,7 +343,7 @@ static int poly_init(struct aead_request *req)
|
||||
struct poly_req *preq = &rctx->u.poly;
|
||||
int err;
|
||||
|
||||
ahash_request_set_callback(&preq->req, aead_request_flags(req),
|
||||
ahash_request_set_callback(&preq->req, rctx->flags,
|
||||
poly_init_done, req);
|
||||
ahash_request_set_tfm(&preq->req, ctx->poly);
|
||||
|
||||
@@ -381,13 +375,12 @@ static int poly_genkey(struct aead_request *req)
|
||||
rctx->assoclen -= 8;
|
||||
}
|
||||
|
||||
sg_init_table(creq->src, 1);
|
||||
memset(rctx->key, 0, sizeof(rctx->key));
|
||||
sg_set_buf(creq->src, rctx->key, sizeof(rctx->key));
|
||||
sg_init_one(creq->src, rctx->key, sizeof(rctx->key));
|
||||
|
||||
chacha_iv(creq->iv, req, 0);
|
||||
|
||||
skcipher_request_set_callback(&creq->req, aead_request_flags(req),
|
||||
skcipher_request_set_callback(&creq->req, rctx->flags,
|
||||
poly_genkey_done, req);
|
||||
skcipher_request_set_tfm(&creq->req, ctx->chacha);
|
||||
skcipher_request_set_crypt(&creq->req, creq->src, creq->src,
|
||||
@@ -418,16 +411,12 @@ static int chacha_encrypt(struct aead_request *req)
|
||||
|
||||
chacha_iv(creq->iv, req, 1);
|
||||
|
||||
sg_init_table(rctx->src, 2);
|
||||
src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
|
||||
dst = src;
|
||||
|
||||
if (req->src != req->dst) {
|
||||
sg_init_table(rctx->dst, 2);
|
||||
if (req->src != req->dst)
|
||||
dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
|
||||
}
|
||||
|
||||
skcipher_request_set_callback(&creq->req, aead_request_flags(req),
|
||||
skcipher_request_set_callback(&creq->req, rctx->flags,
|
||||
chacha_encrypt_done, req);
|
||||
skcipher_request_set_tfm(&creq->req, ctx->chacha);
|
||||
skcipher_request_set_crypt(&creq->req, src, dst,
|
||||
@@ -445,6 +434,7 @@ static int chachapoly_encrypt(struct aead_request *req)
|
||||
struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
|
||||
|
||||
rctx->cryptlen = req->cryptlen;
|
||||
rctx->flags = aead_request_flags(req);
|
||||
|
||||
/* encrypt call chain:
|
||||
* - chacha_encrypt/done()
|
||||
@@ -466,6 +456,7 @@ static int chachapoly_decrypt(struct aead_request *req)
|
||||
struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
|
||||
|
||||
rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE;
|
||||
rctx->flags = aead_request_flags(req);
|
||||
|
||||
/* decrypt call chain:
|
||||
* - poly_genkey/done()
|
||||
|
@@ -32,7 +32,7 @@ static void chacha_docrypt(u32 *state, u8 *dst, const u8 *src,
|
||||
}
|
||||
|
||||
static int chacha_stream_xor(struct skcipher_request *req,
|
||||
struct chacha_ctx *ctx, u8 *iv)
|
||||
const struct chacha_ctx *ctx, const u8 *iv)
|
||||
{
|
||||
struct skcipher_walk walk;
|
||||
u32 state[16];
|
||||
@@ -56,7 +56,7 @@ static int chacha_stream_xor(struct skcipher_request *req,
|
||||
return err;
|
||||
}
|
||||
|
||||
void crypto_chacha_init(u32 *state, struct chacha_ctx *ctx, u8 *iv)
|
||||
void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv)
|
||||
{
|
||||
state[0] = 0x61707865; /* "expa" */
|
||||
state[1] = 0x3320646e; /* "nd 3" */
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/cryptd.h>
|
||||
#include <crypto/crypto_wq.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
@@ -26,11 +25,14 @@
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
static unsigned int cryptd_max_cpu_qlen = 1000;
|
||||
module_param(cryptd_max_cpu_qlen, uint, 0);
|
||||
MODULE_PARM_DESC(cryptd_max_cpu_qlen, "Set cryptd Max queue depth");
|
||||
|
||||
static struct workqueue_struct *cryptd_wq;
|
||||
|
||||
struct cryptd_cpu_queue {
|
||||
struct crypto_queue queue;
|
||||
struct work_struct work;
|
||||
@@ -136,7 +138,7 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue,
|
||||
if (err == -ENOSPC)
|
||||
goto out_put_cpu;
|
||||
|
||||
queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
|
||||
queue_work_on(cpu, cryptd_wq, &cpu_queue->work);
|
||||
|
||||
if (!atomic_read(refcnt))
|
||||
goto out_put_cpu;
|
||||
@@ -179,7 +181,7 @@ static void cryptd_queue_worker(struct work_struct *work)
|
||||
req->complete(req, 0);
|
||||
|
||||
if (cpu_queue->queue.qlen)
|
||||
queue_work(kcrypto_wq, &cpu_queue->work);
|
||||
queue_work(cryptd_wq, &cpu_queue->work);
|
||||
}
|
||||
|
||||
static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm)
|
||||
@@ -919,7 +921,7 @@ static int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
|
||||
switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
|
||||
case CRYPTO_ALG_TYPE_BLKCIPHER:
|
||||
return cryptd_create_skcipher(tmpl, tb, &queue);
|
||||
case CRYPTO_ALG_TYPE_DIGEST:
|
||||
case CRYPTO_ALG_TYPE_HASH:
|
||||
return cryptd_create_hash(tmpl, tb, &queue);
|
||||
case CRYPTO_ALG_TYPE_AEAD:
|
||||
return cryptd_create_aead(tmpl, tb, &queue);
|
||||
@@ -1119,19 +1121,31 @@ static int __init cryptd_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
cryptd_wq = alloc_workqueue("cryptd", WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
|
||||
1);
|
||||
if (!cryptd_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
err = cryptd_init_queue(&queue, cryptd_max_cpu_qlen);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_destroy_wq;
|
||||
|
||||
err = crypto_register_template(&cryptd_tmpl);
|
||||
if (err)
|
||||
cryptd_fini_queue(&queue);
|
||||
goto err_fini_queue;
|
||||
|
||||
return 0;
|
||||
|
||||
err_fini_queue:
|
||||
cryptd_fini_queue(&queue);
|
||||
err_destroy_wq:
|
||||
destroy_workqueue(cryptd_wq);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit cryptd_exit(void)
|
||||
{
|
||||
destroy_workqueue(cryptd_wq);
|
||||
cryptd_fini_queue(&queue);
|
||||
crypto_unregister_template(&cryptd_tmpl);
|
||||
}
|
||||
|
@@ -100,6 +100,7 @@ static struct shash_alg digest_null = {
|
||||
.final = null_final,
|
||||
.base = {
|
||||
.cra_name = "digest_null",
|
||||
.cra_driver_name = "digest_null-generic",
|
||||
.cra_blocksize = NULL_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
@@ -122,6 +123,7 @@ static struct skcipher_alg skcipher_null = {
|
||||
|
||||
static struct crypto_alg null_algs[] = { {
|
||||
.cra_name = "cipher_null",
|
||||
.cra_driver_name = "cipher_null-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = NULL_BLOCK_SIZE,
|
||||
.cra_ctxsize = 0,
|
||||
@@ -134,6 +136,7 @@ static struct crypto_alg null_algs[] = { {
|
||||
.cia_decrypt = null_crypt } }
|
||||
}, {
|
||||
.cra_name = "compress_null",
|
||||
.cra_driver_name = "compress_null-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_blocksize = NULL_BLOCK_SIZE,
|
||||
.cra_ctxsize = 0,
|
||||
|
@@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Workqueue for crypto subsystem
|
||||
*
|
||||
* Copyright (c) 2009 Intel Corp.
|
||||
* Author: Huang Ying <ying.huang@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/module.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/crypto_wq.h>
|
||||
|
||||
struct workqueue_struct *kcrypto_wq;
|
||||
EXPORT_SYMBOL_GPL(kcrypto_wq);
|
||||
|
||||
static int __init crypto_wq_init(void)
|
||||
{
|
||||
kcrypto_wq = alloc_workqueue("crypto",
|
||||
WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1);
|
||||
if (unlikely(!kcrypto_wq))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit crypto_wq_exit(void)
|
||||
{
|
||||
destroy_workqueue(kcrypto_wq);
|
||||
}
|
||||
|
||||
subsys_initcall(crypto_wq_init);
|
||||
module_exit(crypto_wq_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Workqueue for crypto subsystem");
|
@@ -275,6 +275,7 @@ static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "deflate",
|
||||
.cra_driver_name = "deflate-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct deflate_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
|
@@ -219,6 +219,57 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FIPS 140-2 continuous self test for the noise source
|
||||
* The test is performed on the noise source input data. Thus, the function
|
||||
* implicitly knows the size of the buffer to be equal to the security
|
||||
* strength.
|
||||
*
|
||||
* Note, this function disregards the nonce trailing the entropy data during
|
||||
* initial seeding.
|
||||
*
|
||||
* drbg->drbg_mutex must have been taken.
|
||||
*
|
||||
* @drbg DRBG handle
|
||||
* @entropy buffer of seed data to be checked
|
||||
*
|
||||
* return:
|
||||
* 0 on success
|
||||
* -EAGAIN on when the CTRNG is not yet primed
|
||||
* < 0 on error
|
||||
*/
|
||||
static int drbg_fips_continuous_test(struct drbg_state *drbg,
|
||||
const unsigned char *entropy)
|
||||
{
|
||||
unsigned short entropylen = drbg_sec_strength(drbg->core->flags);
|
||||
int ret = 0;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_CRYPTO_FIPS))
|
||||
return 0;
|
||||
|
||||
/* skip test if we test the overall system */
|
||||
if (list_empty(&drbg->test_data.list))
|
||||
return 0;
|
||||
/* only perform test in FIPS mode */
|
||||
if (!fips_enabled)
|
||||
return 0;
|
||||
|
||||
if (!drbg->fips_primed) {
|
||||
/* Priming of FIPS test */
|
||||
memcpy(drbg->prev, entropy, entropylen);
|
||||
drbg->fips_primed = true;
|
||||
/* priming: another round is needed */
|
||||
return -EAGAIN;
|
||||
}
|
||||
ret = memcmp(drbg->prev, entropy, entropylen);
|
||||
if (!ret)
|
||||
panic("DRBG continuous self test failed\n");
|
||||
memcpy(drbg->prev, entropy, entropylen);
|
||||
|
||||
/* the test shall pass when the two values are not equal */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an integer into a byte representation of this integer.
|
||||
* The byte representation is big-endian
|
||||
@@ -998,6 +1049,22 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int drbg_get_random_bytes(struct drbg_state *drbg,
|
||||
unsigned char *entropy,
|
||||
unsigned int entropylen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
get_random_bytes(entropy, entropylen);
|
||||
ret = drbg_fips_continuous_test(drbg, entropy);
|
||||
if (ret && ret != -EAGAIN)
|
||||
return ret;
|
||||
} while (ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drbg_async_seed(struct work_struct *work)
|
||||
{
|
||||
struct drbg_string data;
|
||||
@@ -1006,16 +1073,20 @@ static void drbg_async_seed(struct work_struct *work)
|
||||
seed_work);
|
||||
unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
|
||||
unsigned char entropy[32];
|
||||
int ret;
|
||||
|
||||
BUG_ON(!entropylen);
|
||||
BUG_ON(entropylen > sizeof(entropy));
|
||||
get_random_bytes(entropy, entropylen);
|
||||
|
||||
drbg_string_fill(&data, entropy, entropylen);
|
||||
list_add_tail(&data.list, &seedlist);
|
||||
|
||||
mutex_lock(&drbg->drbg_mutex);
|
||||
|
||||
ret = drbg_get_random_bytes(drbg, entropy, entropylen);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/* If nonblocking pool is initialized, deactivate Jitter RNG */
|
||||
crypto_free_rng(drbg->jent);
|
||||
drbg->jent = NULL;
|
||||
@@ -1030,6 +1101,7 @@ static void drbg_async_seed(struct work_struct *work)
|
||||
if (drbg->seeded)
|
||||
drbg->reseed_threshold = drbg_max_requests(drbg);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&drbg->drbg_mutex);
|
||||
|
||||
memzero_explicit(entropy, entropylen);
|
||||
@@ -1081,7 +1153,9 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
||||
BUG_ON((entropylen * 2) > sizeof(entropy));
|
||||
|
||||
/* Get seed from in-kernel /dev/urandom */
|
||||
get_random_bytes(entropy, entropylen);
|
||||
ret = drbg_get_random_bytes(drbg, entropy, entropylen);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!drbg->jent) {
|
||||
drbg_string_fill(&data1, entropy, entropylen);
|
||||
@@ -1094,7 +1168,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
||||
entropylen);
|
||||
if (ret) {
|
||||
pr_devel("DRBG: jent failed with %d\n", ret);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drbg_string_fill(&data1, entropy, entropylen * 2);
|
||||
@@ -1121,6 +1195,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
||||
|
||||
ret = __drbg_seed(drbg, &seedlist, reseed);
|
||||
|
||||
out:
|
||||
memzero_explicit(entropy, entropylen * 2);
|
||||
|
||||
return ret;
|
||||
@@ -1142,6 +1217,11 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
|
||||
drbg->reseed_ctr = 0;
|
||||
drbg->d_ops = NULL;
|
||||
drbg->core = NULL;
|
||||
if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
|
||||
kzfree(drbg->prev);
|
||||
drbg->prev = NULL;
|
||||
drbg->fips_primed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1211,6 +1291,14 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
|
||||
drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
|
||||
drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags),
|
||||
GFP_KERNEL);
|
||||
if (!drbg->prev)
|
||||
goto fini;
|
||||
drbg->fips_primed = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fini:
|
||||
|
@@ -391,6 +391,7 @@ static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key
|
||||
|
||||
static struct crypto_alg fcrypt_alg = {
|
||||
.cra_name = "fcrypt",
|
||||
.cra_driver_name = "fcrypt-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = 8,
|
||||
.cra_ctxsize = sizeof(struct fcrypt_ctx),
|
||||
|
@@ -31,6 +31,7 @@ static int ghash_setkey(struct crypto_shash *tfm,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
|
||||
be128 k;
|
||||
|
||||
if (keylen != GHASH_BLOCK_SIZE) {
|
||||
crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||
@@ -39,7 +40,12 @@ static int ghash_setkey(struct crypto_shash *tfm,
|
||||
|
||||
if (ctx->gf128)
|
||||
gf128mul_free_4k(ctx->gf128);
|
||||
ctx->gf128 = gf128mul_init_4k_lle((be128 *)key);
|
||||
|
||||
BUILD_BUG_ON(sizeof(k) != GHASH_BLOCK_SIZE);
|
||||
memcpy(&k, key, GHASH_BLOCK_SIZE); /* avoid violating alignment rules */
|
||||
ctx->gf128 = gf128mul_init_4k_lle(&k);
|
||||
memzero_explicit(&k, GHASH_BLOCK_SIZE);
|
||||
|
||||
if (!ctx->gf128)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@@ -56,11 +56,6 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector);
|
||||
* Helper function
|
||||
***************************************************************************/
|
||||
|
||||
__u64 jent_rol64(__u64 word, unsigned int shift)
|
||||
{
|
||||
return rol64(word, shift);
|
||||
}
|
||||
|
||||
void *jent_zalloc(unsigned int len)
|
||||
{
|
||||
return kzalloc(len, GFP_KERNEL);
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* Non-physical true random number generator based on timing jitter --
|
||||
* Jitter RNG standalone code.
|
||||
*
|
||||
* Copyright Stephan Mueller <smueller@chronox.de>, 2015
|
||||
* Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2019
|
||||
*
|
||||
* Design
|
||||
* ======
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
/*
|
||||
* This Jitterentropy RNG is based on the jitterentropy library
|
||||
* version 1.1.0 provided at http://www.chronox.de/jent.html
|
||||
* version 2.1.2 provided at http://www.chronox.de/jent.html
|
||||
*/
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
@@ -71,10 +71,7 @@ struct rand_data {
|
||||
#define DATA_SIZE_BITS ((sizeof(__u64)) * 8)
|
||||
__u64 last_delta; /* SENSITIVE stuck test */
|
||||
__s64 last_delta2; /* SENSITIVE stuck test */
|
||||
unsigned int stuck:1; /* Time measurement stuck */
|
||||
unsigned int osr; /* Oversample rate */
|
||||
unsigned int stir:1; /* Post-processing stirring */
|
||||
unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */
|
||||
#define JENT_MEMORY_BLOCKS 64
|
||||
#define JENT_MEMORY_BLOCKSIZE 32
|
||||
#define JENT_MEMORY_ACCESSLOOPS 128
|
||||
@@ -89,8 +86,6 @@ struct rand_data {
|
||||
};
|
||||
|
||||
/* Flags that can be used to initialize the RNG */
|
||||
#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */
|
||||
#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */
|
||||
#define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
|
||||
* entropy, saves MEMORY_SIZE RAM for
|
||||
* entropy collector */
|
||||
@@ -99,19 +94,16 @@ struct rand_data {
|
||||
#define JENT_ENOTIME 1 /* Timer service not available */
|
||||
#define JENT_ECOARSETIME 2 /* Timer too coarse for RNG */
|
||||
#define JENT_ENOMONOTONIC 3 /* Timer is not monotonic increasing */
|
||||
#define JENT_EMINVARIATION 4 /* Timer variations too small for RNG */
|
||||
#define JENT_EVARVAR 5 /* Timer does not produce variations of
|
||||
* variations (2nd derivation of time is
|
||||
* zero). */
|
||||
#define JENT_EMINVARVAR 6 /* Timer variations of variations is tooi
|
||||
* small. */
|
||||
#define JENT_ESTUCK 8 /* Too many stuck results during init. */
|
||||
|
||||
/***************************************************************************
|
||||
* Helper functions
|
||||
***************************************************************************/
|
||||
|
||||
void jent_get_nstime(__u64 *out);
|
||||
__u64 jent_rol64(__u64 word, unsigned int shift);
|
||||
void *jent_zalloc(unsigned int len);
|
||||
void jent_zfree(void *ptr);
|
||||
int jent_fips_enabled(void);
|
||||
@@ -140,16 +132,16 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
|
||||
|
||||
jent_get_nstime(&time);
|
||||
/*
|
||||
* mix the current state of the random number into the shuffle
|
||||
* calculation to balance that shuffle a bit more
|
||||
* Mix the current state of the random number into the shuffle
|
||||
* calculation to balance that shuffle a bit more.
|
||||
*/
|
||||
if (ec)
|
||||
time ^= ec->data;
|
||||
/*
|
||||
* we fold the time value as much as possible to ensure that as many
|
||||
* bits of the time stamp are included as possible
|
||||
* We fold the time value as much as possible to ensure that as many
|
||||
* bits of the time stamp are included as possible.
|
||||
*/
|
||||
for (i = 0; (DATA_SIZE_BITS / bits) > i; i++) {
|
||||
for (i = 0; ((DATA_SIZE_BITS + bits - 1) / bits) > i; i++) {
|
||||
shuffle ^= time & mask;
|
||||
time = time >> bits;
|
||||
}
|
||||
@@ -169,38 +161,28 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
|
||||
* CPU Jitter noise source -- this is the noise source based on the CPU
|
||||
* execution time jitter
|
||||
*
|
||||
* This function folds the time into one bit units by iterating
|
||||
* through the DATA_SIZE_BITS bit time value as follows: assume our time value
|
||||
* is 0xabcd
|
||||
* 1st loop, 1st shift generates 0xd000
|
||||
* 1st loop, 2nd shift generates 0x000d
|
||||
* 2nd loop, 1st shift generates 0xcd00
|
||||
* 2nd loop, 2nd shift generates 0x000c
|
||||
* 3rd loop, 1st shift generates 0xbcd0
|
||||
* 3rd loop, 2nd shift generates 0x000b
|
||||
* 4th loop, 1st shift generates 0xabcd
|
||||
* 4th loop, 2nd shift generates 0x000a
|
||||
* Now, the values at the end of the 2nd shifts are XORed together.
|
||||
* This function injects the individual bits of the time value into the
|
||||
* entropy pool using an LFSR.
|
||||
*
|
||||
* The code is deliberately inefficient and shall stay that way. This function
|
||||
* is the root cause why the code shall be compiled without optimization. This
|
||||
* function not only acts as folding operation, but this function's execution
|
||||
* is used to measure the CPU execution time jitter. Any change to the loop in
|
||||
* this function implies that careful retesting must be done.
|
||||
* The code is deliberately inefficient with respect to the bit shifting
|
||||
* and shall stay that way. This function is the root cause why the code
|
||||
* shall be compiled without optimization. This function not only acts as
|
||||
* folding operation, but this function's execution is used to measure
|
||||
* the CPU execution time jitter. Any change to the loop in this function
|
||||
* implies that careful retesting must be done.
|
||||
*
|
||||
* Input:
|
||||
* @ec entropy collector struct -- may be NULL
|
||||
* @time time stamp to be folded
|
||||
* @time time stamp to be injected
|
||||
* @loop_cnt if a value not equal to 0 is set, use the given value as number of
|
||||
* loops to perform the folding
|
||||
*
|
||||
* Output:
|
||||
* @folded result of folding operation
|
||||
* updated ec->data
|
||||
*
|
||||
* @return Number of loops the folding operation is performed
|
||||
*/
|
||||
static __u64 jent_fold_time(struct rand_data *ec, __u64 time,
|
||||
__u64 *folded, __u64 loop_cnt)
|
||||
static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
|
||||
{
|
||||
unsigned int i;
|
||||
__u64 j = 0;
|
||||
@@ -217,15 +199,34 @@ static __u64 jent_fold_time(struct rand_data *ec, __u64 time,
|
||||
if (loop_cnt)
|
||||
fold_loop_cnt = loop_cnt;
|
||||
for (j = 0; j < fold_loop_cnt; j++) {
|
||||
new = 0;
|
||||
new = ec->data;
|
||||
for (i = 1; (DATA_SIZE_BITS) >= i; i++) {
|
||||
__u64 tmp = time << (DATA_SIZE_BITS - i);
|
||||
|
||||
tmp = tmp >> (DATA_SIZE_BITS - 1);
|
||||
|
||||
/*
|
||||
* Fibonacci LSFR with polynomial of
|
||||
* x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
|
||||
* primitive according to
|
||||
* http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
|
||||
* (the shift values are the polynomial values minus one
|
||||
* due to counting bits from 0 to 63). As the current
|
||||
* position is always the LSB, the polynomial only needs
|
||||
* to shift data in from the left without wrap.
|
||||
*/
|
||||
tmp ^= ((new >> 63) & 1);
|
||||
tmp ^= ((new >> 60) & 1);
|
||||
tmp ^= ((new >> 55) & 1);
|
||||
tmp ^= ((new >> 30) & 1);
|
||||
tmp ^= ((new >> 27) & 1);
|
||||
tmp ^= ((new >> 22) & 1);
|
||||
new <<= 1;
|
||||
new ^= tmp;
|
||||
}
|
||||
}
|
||||
*folded = new;
|
||||
ec->data = new;
|
||||
|
||||
return fold_loop_cnt;
|
||||
}
|
||||
|
||||
@@ -258,7 +259,6 @@ static __u64 jent_fold_time(struct rand_data *ec, __u64 time,
|
||||
*/
|
||||
static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
|
||||
{
|
||||
unsigned char *tmpval = NULL;
|
||||
unsigned int wrap = 0;
|
||||
__u64 i = 0;
|
||||
#define MAX_ACC_LOOP_BIT 7
|
||||
@@ -278,7 +278,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
|
||||
acc_loop_cnt = loop_cnt;
|
||||
|
||||
for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
|
||||
tmpval = ec->mem + ec->memlocation;
|
||||
unsigned char *tmpval = ec->mem + ec->memlocation;
|
||||
/*
|
||||
* memory access: just add 1 to one byte,
|
||||
* wrap at 255 -- memory access implies read
|
||||
@@ -316,7 +316,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
|
||||
* 0 jitter measurement not stuck (good bit)
|
||||
* 1 jitter measurement stuck (reject bit)
|
||||
*/
|
||||
static void jent_stuck(struct rand_data *ec, __u64 current_delta)
|
||||
static int jent_stuck(struct rand_data *ec, __u64 current_delta)
|
||||
{
|
||||
__s64 delta2 = ec->last_delta - current_delta;
|
||||
__s64 delta3 = delta2 - ec->last_delta2;
|
||||
@@ -325,14 +325,15 @@ static void jent_stuck(struct rand_data *ec, __u64 current_delta)
|
||||
ec->last_delta2 = delta2;
|
||||
|
||||
if (!current_delta || !delta2 || !delta3)
|
||||
ec->stuck = 1;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the heart of the entropy generation: calculate time deltas and
|
||||
* use the CPU jitter in the time deltas. The jitter is folded into one
|
||||
* bit. You can call this function the "random bit generator" as it
|
||||
* produces one random bit per invocation.
|
||||
* use the CPU jitter in the time deltas. The jitter is injected into the
|
||||
* entropy pool.
|
||||
*
|
||||
* WARNING: ensure that ->prev_time is primed before using the output
|
||||
* of this function! This can be done by calling this function
|
||||
@@ -341,12 +342,11 @@ static void jent_stuck(struct rand_data *ec, __u64 current_delta)
|
||||
* Input:
|
||||
* @entropy_collector Reference to entropy collector
|
||||
*
|
||||
* @return One random bit
|
||||
* @return result of stuck test
|
||||
*/
|
||||
static __u64 jent_measure_jitter(struct rand_data *ec)
|
||||
static int jent_measure_jitter(struct rand_data *ec)
|
||||
{
|
||||
__u64 time = 0;
|
||||
__u64 data = 0;
|
||||
__u64 current_delta = 0;
|
||||
|
||||
/* Invoke one noise source before time measurement to add variations */
|
||||
@@ -360,109 +360,11 @@ static __u64 jent_measure_jitter(struct rand_data *ec)
|
||||
current_delta = time - ec->prev_time;
|
||||
ec->prev_time = time;
|
||||
|
||||
/* Now call the next noise sources which also folds the data */
|
||||
jent_fold_time(ec, current_delta, &data, 0);
|
||||
/* Now call the next noise sources which also injects the data */
|
||||
jent_lfsr_time(ec, current_delta, 0);
|
||||
|
||||
/*
|
||||
* Check whether we have a stuck measurement. The enforcement
|
||||
* is performed after the stuck value has been mixed into the
|
||||
* entropy pool.
|
||||
*/
|
||||
jent_stuck(ec, current_delta);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Von Neuman unbias as explained in RFC 4086 section 4.2. As shown in the
|
||||
* documentation of that RNG, the bits from jent_measure_jitter are considered
|
||||
* independent which implies that the Von Neuman unbias operation is applicable.
|
||||
* A proof of the Von-Neumann unbias operation to remove skews is given in the
|
||||
* document "A proposal for: Functionality classes for random number
|
||||
* generators", version 2.0 by Werner Schindler, section 5.4.1.
|
||||
*
|
||||
* Input:
|
||||
* @entropy_collector Reference to entropy collector
|
||||
*
|
||||
* @return One random bit
|
||||
*/
|
||||
static __u64 jent_unbiased_bit(struct rand_data *entropy_collector)
|
||||
{
|
||||
do {
|
||||
__u64 a = jent_measure_jitter(entropy_collector);
|
||||
__u64 b = jent_measure_jitter(entropy_collector);
|
||||
|
||||
if (a == b)
|
||||
continue;
|
||||
if (1 == a)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the pool a bit by mixing some value with a bijective function (XOR)
|
||||
* into the pool.
|
||||
*
|
||||
* The function generates a mixer value that depends on the bits set and the
|
||||
* location of the set bits in the random number generated by the entropy
|
||||
* source. Therefore, based on the generated random number, this mixer value
|
||||
* can have 2**64 different values. That mixer value is initialized with the
|
||||
* first two SHA-1 constants. After obtaining the mixer value, it is XORed into
|
||||
* the random number.
|
||||
*
|
||||
* The mixer value is not assumed to contain any entropy. But due to the XOR
|
||||
* operation, it can also not destroy any entropy present in the entropy pool.
|
||||
*
|
||||
* Input:
|
||||
* @entropy_collector Reference to entropy collector
|
||||
*/
|
||||
static void jent_stir_pool(struct rand_data *entropy_collector)
|
||||
{
|
||||
/*
|
||||
* to shut up GCC on 32 bit, we have to initialize the 64 variable
|
||||
* with two 32 bit variables
|
||||
*/
|
||||
union c {
|
||||
__u64 u64;
|
||||
__u32 u32[2];
|
||||
};
|
||||
/*
|
||||
* This constant is derived from the first two 32 bit initialization
|
||||
* vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1
|
||||
*/
|
||||
union c constant;
|
||||
/*
|
||||
* The start value of the mixer variable is derived from the third
|
||||
* and fourth 32 bit initialization vector of SHA-1 as defined in
|
||||
* FIPS 180-4 section 5.3.1
|
||||
*/
|
||||
union c mixer;
|
||||
unsigned int i = 0;
|
||||
|
||||
/*
|
||||
* Store the SHA-1 constants in reverse order to make up the 64 bit
|
||||
* value -- this applies to a little endian system, on a big endian
|
||||
* system, it reverses as expected. But this really does not matter
|
||||
* as we do not rely on the specific numbers. We just pick the SHA-1
|
||||
* constants as they have a good mix of bit set and unset.
|
||||
*/
|
||||
constant.u32[1] = 0x67452301;
|
||||
constant.u32[0] = 0xefcdab89;
|
||||
mixer.u32[1] = 0x98badcfe;
|
||||
mixer.u32[0] = 0x10325476;
|
||||
|
||||
for (i = 0; i < DATA_SIZE_BITS; i++) {
|
||||
/*
|
||||
* get the i-th bit of the input random number and only XOR
|
||||
* the constant into the mixer value when that bit is set
|
||||
*/
|
||||
if ((entropy_collector->data >> i) & 1)
|
||||
mixer.u64 ^= constant.u64;
|
||||
mixer.u64 = jent_rol64(mixer.u64, 1);
|
||||
}
|
||||
entropy_collector->data ^= mixer.u64;
|
||||
/* Check whether we have a stuck measurement. */
|
||||
return jent_stuck(ec, current_delta);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,48 +382,9 @@ static void jent_gen_entropy(struct rand_data *ec)
|
||||
jent_measure_jitter(ec);
|
||||
|
||||
while (1) {
|
||||
__u64 data = 0;
|
||||
|
||||
if (ec->disable_unbias == 1)
|
||||
data = jent_measure_jitter(ec);
|
||||
else
|
||||
data = jent_unbiased_bit(ec);
|
||||
|
||||
/* enforcement of the jent_stuck test */
|
||||
if (ec->stuck) {
|
||||
/*
|
||||
* We only mix in the bit considered not appropriate
|
||||
* without the LSFR. The reason is that if we apply
|
||||
* the LSFR and we do not rotate, the 2nd bit with LSFR
|
||||
* will cancel out the first LSFR application on the
|
||||
* bad bit.
|
||||
*
|
||||
* And we do not rotate as we apply the next bit to the
|
||||
* current bit location again.
|
||||
*/
|
||||
ec->data ^= data;
|
||||
ec->stuck = 0;
|
||||
/* If a stuck measurement is received, repeat measurement */
|
||||
if (jent_measure_jitter(ec))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fibonacci LSFR with polynom of
|
||||
* x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
|
||||
* primitive according to
|
||||
* http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
|
||||
* (the shift values are the polynom values minus one
|
||||
* due to counting bits from 0 to 63). As the current
|
||||
* position is always the LSB, the polynom only needs
|
||||
* to shift data in from the left without wrap.
|
||||
*/
|
||||
ec->data ^= data;
|
||||
ec->data ^= ((ec->data >> 63) & 1);
|
||||
ec->data ^= ((ec->data >> 60) & 1);
|
||||
ec->data ^= ((ec->data >> 55) & 1);
|
||||
ec->data ^= ((ec->data >> 30) & 1);
|
||||
ec->data ^= ((ec->data >> 27) & 1);
|
||||
ec->data ^= ((ec->data >> 22) & 1);
|
||||
ec->data = jent_rol64(ec->data, 1);
|
||||
|
||||
/*
|
||||
* We multiply the loop value with ->osr to obtain the
|
||||
@@ -530,8 +393,6 @@ static void jent_gen_entropy(struct rand_data *ec)
|
||||
if (++k >= (DATA_SIZE_BITS * ec->osr))
|
||||
break;
|
||||
}
|
||||
if (ec->stir)
|
||||
jent_stir_pool(ec);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,12 +500,6 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
|
||||
osr = 1; /* minimum sampling rate is 1 */
|
||||
entropy_collector->osr = osr;
|
||||
|
||||
entropy_collector->stir = 1;
|
||||
if (flags & JENT_DISABLE_STIR)
|
||||
entropy_collector->stir = 0;
|
||||
if (flags & JENT_DISABLE_UNBIAS)
|
||||
entropy_collector->disable_unbias = 1;
|
||||
|
||||
/* fill the data pad with non-zero values */
|
||||
jent_gen_entropy(entropy_collector);
|
||||
|
||||
@@ -656,7 +511,6 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector)
|
||||
jent_zfree(entropy_collector->mem);
|
||||
entropy_collector->mem = NULL;
|
||||
jent_zfree(entropy_collector);
|
||||
entropy_collector = NULL;
|
||||
}
|
||||
|
||||
int jent_entropy_init(void)
|
||||
@@ -665,8 +519,9 @@ int jent_entropy_init(void)
|
||||
__u64 delta_sum = 0;
|
||||
__u64 old_delta = 0;
|
||||
int time_backwards = 0;
|
||||
int count_var = 0;
|
||||
int count_mod = 0;
|
||||
int count_stuck = 0;
|
||||
struct rand_data ec = { 0 };
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
* that we only have a few loop counts to do testing. These
|
||||
@@ -695,12 +550,14 @@ int jent_entropy_init(void)
|
||||
for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
|
||||
__u64 time = 0;
|
||||
__u64 time2 = 0;
|
||||
__u64 folded = 0;
|
||||
__u64 delta = 0;
|
||||
unsigned int lowdelta = 0;
|
||||
int stuck;
|
||||
|
||||
/* Invoke core entropy collection logic */
|
||||
jent_get_nstime(&time);
|
||||
jent_fold_time(NULL, time, &folded, 1<<MIN_FOLD_LOOP_BIT);
|
||||
ec.prev_time = time;
|
||||
jent_lfsr_time(&ec, time, 0);
|
||||
jent_get_nstime(&time2);
|
||||
|
||||
/* test whether timer works */
|
||||
@@ -715,6 +572,8 @@ int jent_entropy_init(void)
|
||||
if (!delta)
|
||||
return JENT_ECOARSETIME;
|
||||
|
||||
stuck = jent_stuck(&ec, delta);
|
||||
|
||||
/*
|
||||
* up to here we did not modify any variable that will be
|
||||
* evaluated later, but we already performed some work. Thus we
|
||||
@@ -725,14 +584,14 @@ int jent_entropy_init(void)
|
||||
if (CLEARCACHE > i)
|
||||
continue;
|
||||
|
||||
if (stuck)
|
||||
count_stuck++;
|
||||
|
||||
/* test whether we have an increasing timer */
|
||||
if (!(time2 > time))
|
||||
time_backwards++;
|
||||
|
||||
/*
|
||||
* Avoid modulo of 64 bit integer to allow code to compile
|
||||
* on 32 bit architectures.
|
||||
*/
|
||||
/* use 32 bit value to ensure compilation on 32 bit arches */
|
||||
lowdelta = time2 - time;
|
||||
if (!(lowdelta % 100))
|
||||
count_mod++;
|
||||
@@ -743,14 +602,10 @@ int jent_entropy_init(void)
|
||||
* only after the first loop is executed as we need to prime
|
||||
* the old_data value
|
||||
*/
|
||||
if (i) {
|
||||
if (delta != old_delta)
|
||||
count_var++;
|
||||
if (delta > old_delta)
|
||||
delta_sum += (delta - old_delta);
|
||||
else
|
||||
delta_sum += (old_delta - delta);
|
||||
}
|
||||
if (delta > old_delta)
|
||||
delta_sum += (delta - old_delta);
|
||||
else
|
||||
delta_sum += (old_delta - delta);
|
||||
old_delta = delta;
|
||||
}
|
||||
|
||||
@@ -763,25 +618,29 @@ int jent_entropy_init(void)
|
||||
*/
|
||||
if (3 < time_backwards)
|
||||
return JENT_ENOMONOTONIC;
|
||||
/* Error if the time variances are always identical */
|
||||
if (!delta_sum)
|
||||
return JENT_EVARVAR;
|
||||
|
||||
/*
|
||||
* Variations of deltas of time must on average be larger
|
||||
* than 1 to ensure the entropy estimation
|
||||
* implied with 1 is preserved
|
||||
*/
|
||||
if (delta_sum <= 1)
|
||||
return JENT_EMINVARVAR;
|
||||
if ((delta_sum) <= 1)
|
||||
return JENT_EVARVAR;
|
||||
|
||||
/*
|
||||
* Ensure that we have variations in the time stamp below 10 for at
|
||||
* least 10% of all checks -- on some platforms, the counter
|
||||
* increments in multiples of 100, but not always
|
||||
* least 10% of all checks -- on some platforms, the counter increments
|
||||
* in multiples of 100, but not always
|
||||
*/
|
||||
if ((TESTLOOPCOUNT/10 * 9) < count_mod)
|
||||
return JENT_ECOARSETIME;
|
||||
|
||||
/*
|
||||
* If we have more than 90% stuck results, then this Jitter RNG is
|
||||
* likely to not work well.
|
||||
*/
|
||||
if ((TESTLOOPCOUNT/10 * 9) < count_stuck)
|
||||
return JENT_ESTUCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -848,6 +848,7 @@ static void khazad_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
|
||||
static struct crypto_alg khazad_alg = {
|
||||
.cra_name = "khazad",
|
||||
.cra_driver_name = "khazad-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = KHAZAD_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof (struct khazad_ctx),
|
||||
|
@@ -384,7 +384,7 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
|
||||
inst->alg.base.cra_priority = alg->base.cra_priority;
|
||||
inst->alg.base.cra_blocksize = LRW_BLOCK_SIZE;
|
||||
inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
|
||||
(__alignof__(__be32) - 1);
|
||||
(__alignof__(be128) - 1);
|
||||
|
||||
inst->alg.ivsize = LRW_BLOCK_SIZE;
|
||||
inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) +
|
||||
|
@@ -106,6 +106,7 @@ static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
|
||||
|
||||
static struct crypto_alg alg_lz4 = {
|
||||
.cra_name = "lz4",
|
||||
.cra_driver_name = "lz4-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct lz4_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
|
@@ -107,6 +107,7 @@ static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
|
||||
|
||||
static struct crypto_alg alg_lz4hc = {
|
||||
.cra_name = "lz4hc",
|
||||
.cra_driver_name = "lz4hc-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct lz4hc_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
|
@@ -109,6 +109,7 @@ static int lzorle_sdecompress(struct crypto_scomp *tfm, const u8 *src,
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "lzo-rle",
|
||||
.cra_driver_name = "lzo-rle-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct lzorle_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
|
@@ -109,6 +109,7 @@ static int lzo_sdecompress(struct crypto_scomp *tfm, const u8 *src,
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "lzo",
|
||||
.cra_driver_name = "lzo-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct lzo_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
|
@@ -216,9 +216,10 @@ static struct shash_alg alg = {
|
||||
.final = md4_final,
|
||||
.descsize = sizeof(struct md4_ctx),
|
||||
.base = {
|
||||
.cra_name = "md4",
|
||||
.cra_blocksize = MD4_HMAC_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "md4",
|
||||
.cra_driver_name = "md4-generic",
|
||||
.cra_blocksize = MD4_HMAC_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -228,9 +228,10 @@ static struct shash_alg alg = {
|
||||
.descsize = sizeof(struct md5_state),
|
||||
.statesize = sizeof(struct md5_state),
|
||||
.base = {
|
||||
.cra_name = "md5",
|
||||
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "md5",
|
||||
.cra_driver_name = "md5-generic",
|
||||
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -156,6 +156,7 @@ static struct shash_alg alg = {
|
||||
.descsize = sizeof(struct michael_mic_desc_ctx),
|
||||
.base = {
|
||||
.cra_name = "michael_mic",
|
||||
.cra_driver_name = "michael_mic-generic",
|
||||
.cra_blocksize = 8,
|
||||
.cra_alignmask = 3,
|
||||
.cra_ctxsize = sizeof(struct michael_mic_ctx),
|
||||
|
@@ -298,6 +298,7 @@ static struct shash_alg alg = {
|
||||
.descsize = sizeof(struct rmd128_ctx),
|
||||
.base = {
|
||||
.cra_name = "rmd128",
|
||||
.cra_driver_name = "rmd128-generic",
|
||||
.cra_blocksize = RMD128_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
|
@@ -342,6 +342,7 @@ static struct shash_alg alg = {
|
||||
.descsize = sizeof(struct rmd160_ctx),
|
||||
.base = {
|
||||
.cra_name = "rmd160",
|
||||
.cra_driver_name = "rmd160-generic",
|
||||
.cra_blocksize = RMD160_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
|
@@ -317,6 +317,7 @@ static struct shash_alg alg = {
|
||||
.descsize = sizeof(struct rmd256_ctx),
|
||||
.base = {
|
||||
.cra_name = "rmd256",
|
||||
.cra_driver_name = "rmd256-generic",
|
||||
.cra_blocksize = RMD256_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
|
@@ -366,6 +366,7 @@ static struct shash_alg alg = {
|
||||
.descsize = sizeof(struct rmd320_ctx),
|
||||
.base = {
|
||||
.cra_name = "rmd320",
|
||||
.cra_driver_name = "rmd320-generic",
|
||||
.cra_blocksize = RMD320_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
|
@@ -225,7 +225,13 @@
|
||||
x4 ^= x2; \
|
||||
})
|
||||
|
||||
static void __serpent_setkey_sbox(u32 r0, u32 r1, u32 r2, u32 r3, u32 r4, u32 *k)
|
||||
/*
|
||||
* both gcc and clang have misoptimized this function in the past,
|
||||
* producing horrible object code from spilling temporary variables
|
||||
* on the stack. Forcing this part out of line avoids that.
|
||||
*/
|
||||
static noinline void __serpent_setkey_sbox(u32 r0, u32 r1, u32 r2,
|
||||
u32 r3, u32 r4, u32 *k)
|
||||
{
|
||||
k += 100;
|
||||
S3(r3, r4, r0, r1, r2); store_and_load_keys(r1, r2, r4, r3, 28, 24);
|
||||
@@ -637,6 +643,7 @@ static struct crypto_alg srp_algs[2] = { {
|
||||
.cia_decrypt = serpent_decrypt } }
|
||||
}, {
|
||||
.cra_name = "tnepres",
|
||||
.cra_driver_name = "tnepres-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = SERPENT_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct serpent_ctx),
|
||||
|
@@ -837,6 +837,40 @@ static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_skcipher_encrypt(struct skcipher_request *req)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct crypto_alg *alg = tfm->base.__crt_alg;
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
int ret;
|
||||
|
||||
crypto_stats_get(alg);
|
||||
if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
|
||||
ret = -ENOKEY;
|
||||
else
|
||||
ret = tfm->encrypt(req);
|
||||
crypto_stats_skcipher_encrypt(cryptlen, ret, alg);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_skcipher_encrypt);
|
||||
|
||||
int crypto_skcipher_decrypt(struct skcipher_request *req)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct crypto_alg *alg = tfm->base.__crt_alg;
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
int ret;
|
||||
|
||||
crypto_stats_get(alg);
|
||||
if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
|
||||
ret = -ENOKEY;
|
||||
else
|
||||
ret = tfm->decrypt(req);
|
||||
crypto_stats_skcipher_decrypt(cryptlen, ret, alg);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_skcipher_decrypt);
|
||||
|
||||
static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
|
||||
|
@@ -216,6 +216,7 @@ static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
|
||||
static struct crypto_alg tea_algs[3] = { {
|
||||
.cra_name = "tea",
|
||||
.cra_driver_name = "tea-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = TEA_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof (struct tea_ctx),
|
||||
@@ -229,6 +230,7 @@ static struct crypto_alg tea_algs[3] = { {
|
||||
.cia_decrypt = tea_decrypt } }
|
||||
}, {
|
||||
.cra_name = "xtea",
|
||||
.cra_driver_name = "xtea-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = XTEA_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof (struct xtea_ctx),
|
||||
@@ -242,6 +244,7 @@ static struct crypto_alg tea_algs[3] = { {
|
||||
.cia_decrypt = xtea_decrypt } }
|
||||
}, {
|
||||
.cra_name = "xeta",
|
||||
.cra_driver_name = "xeta-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = XTEA_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof (struct xtea_ctx),
|
||||
|
478
crypto/testmgr.c
478
crypto/testmgr.c
@@ -1032,6 +1032,205 @@ static void crypto_reenable_simd_for_test(void)
|
||||
}
|
||||
#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
|
||||
|
||||
static int build_hash_sglist(struct test_sglist *tsgl,
|
||||
const struct hash_testvec *vec,
|
||||
const struct testvec_config *cfg,
|
||||
unsigned int alignmask,
|
||||
const struct test_sg_division *divs[XBUFSIZE])
|
||||
{
|
||||
struct kvec kv;
|
||||
struct iov_iter input;
|
||||
|
||||
kv.iov_base = (void *)vec->plaintext;
|
||||
kv.iov_len = vec->psize;
|
||||
iov_iter_kvec(&input, WRITE, &kv, 1, vec->psize);
|
||||
return build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
|
||||
&input, divs);
|
||||
}
|
||||
|
||||
static int check_hash_result(const char *type,
|
||||
const u8 *result, unsigned int digestsize,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const char *driver,
|
||||
const struct testvec_config *cfg)
|
||||
{
|
||||
if (memcmp(result, vec->digest, digestsize) != 0) {
|
||||
pr_err("alg: %s: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
|
||||
type, driver, vec_name, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: %s: %s overran result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
type, driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_shash_op(const char *op, int err,
|
||||
const char *driver, const char *vec_name,
|
||||
const struct testvec_config *cfg)
|
||||
{
|
||||
if (err)
|
||||
pr_err("alg: shash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, op, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline const void *sg_data(struct scatterlist *sg)
|
||||
{
|
||||
return page_address(sg_page(sg)) + sg->offset;
|
||||
}
|
||||
|
||||
/* Test one hash test vector in one configuration, using the shash API */
|
||||
static int test_shash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
struct crypto_shash *tfm = desc->tfm;
|
||||
const unsigned int alignmask = crypto_shash_alignmask(tfm);
|
||||
const unsigned int digestsize = crypto_shash_digestsize(tfm);
|
||||
const unsigned int statesize = crypto_shash_statesize(tfm);
|
||||
const struct test_sg_division *divs[XBUFSIZE];
|
||||
unsigned int i;
|
||||
u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
|
||||
int err;
|
||||
|
||||
/* Set the key, if specified */
|
||||
if (vec->ksize) {
|
||||
err = crypto_shash_setkey(tfm, vec->key, vec->ksize);
|
||||
if (err) {
|
||||
if (err == vec->setkey_error)
|
||||
return 0;
|
||||
pr_err("alg: shash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
|
||||
driver, vec_name, vec->setkey_error, err,
|
||||
crypto_shash_get_flags(tfm));
|
||||
return err;
|
||||
}
|
||||
if (vec->setkey_error) {
|
||||
pr_err("alg: shash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
|
||||
driver, vec_name, vec->setkey_error);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the scatterlist for the source data */
|
||||
err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
|
||||
if (err) {
|
||||
pr_err("alg: shash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Do the actual hashing */
|
||||
|
||||
testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
|
||||
testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
|
||||
|
||||
if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
|
||||
vec->digest_error) {
|
||||
/* Just using digest() */
|
||||
if (tsgl->nents != 1)
|
||||
return 0;
|
||||
if (cfg->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_digest(desc, sg_data(&tsgl->sgl[0]),
|
||||
tsgl->sgl[0].length, result);
|
||||
if (cfg->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
if (err) {
|
||||
if (err == vec->digest_error)
|
||||
return 0;
|
||||
pr_err("alg: shash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, err,
|
||||
cfg->name);
|
||||
return err;
|
||||
}
|
||||
if (vec->digest_error) {
|
||||
pr_err("alg: shash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
goto result_ready;
|
||||
}
|
||||
|
||||
/* Using init(), zero or more update(), then final() or finup() */
|
||||
|
||||
if (cfg->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_init(desc);
|
||||
if (cfg->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("init", err, driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < tsgl->nents; i++) {
|
||||
if (i + 1 == tsgl->nents &&
|
||||
cfg->finalization_type == FINALIZATION_TYPE_FINUP) {
|
||||
if (divs[i]->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_finup(desc, sg_data(&tsgl->sgl[i]),
|
||||
tsgl->sgl[i].length, result);
|
||||
if (divs[i]->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("finup", err, driver, vec_name,
|
||||
cfg);
|
||||
if (err)
|
||||
return err;
|
||||
goto result_ready;
|
||||
}
|
||||
if (divs[i]->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_update(desc, sg_data(&tsgl->sgl[i]),
|
||||
tsgl->sgl[i].length);
|
||||
if (divs[i]->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("update", err, driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) {
|
||||
/* Test ->export() and ->import() */
|
||||
testmgr_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN);
|
||||
err = crypto_shash_export(desc, hashstate);
|
||||
err = check_shash_op("export", err, driver, vec_name,
|
||||
cfg);
|
||||
if (err)
|
||||
return err;
|
||||
if (!testmgr_is_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: shash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
|
||||
err = crypto_shash_import(desc, hashstate);
|
||||
err = check_shash_op("import", err, driver, vec_name,
|
||||
cfg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_final(desc, result);
|
||||
if (cfg->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("final", err, driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
result_ready:
|
||||
return check_hash_result("shash", result, digestsize, vec, vec_name,
|
||||
driver, cfg);
|
||||
}
|
||||
|
||||
static int do_ahash_op(int (*op)(struct ahash_request *req),
|
||||
struct ahash_request *req,
|
||||
struct crypto_wait *wait, bool nosimd)
|
||||
@@ -1049,31 +1248,32 @@ static int do_ahash_op(int (*op)(struct ahash_request *req),
|
||||
return crypto_wait_req(err, wait);
|
||||
}
|
||||
|
||||
static int check_nonfinal_hash_op(const char *op, int err,
|
||||
u8 *result, unsigned int digestsize,
|
||||
const char *driver, const char *vec_name,
|
||||
const struct testvec_config *cfg)
|
||||
static int check_nonfinal_ahash_op(const char *op, int err,
|
||||
u8 *result, unsigned int digestsize,
|
||||
const char *driver, const char *vec_name,
|
||||
const struct testvec_config *cfg)
|
||||
{
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, op, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
if (!testmgr_is_poison(result, digestsize)) {
|
||||
pr_err("alg: hash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, op, vec_name, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_hash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct ahash_request *req,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
/* Test one hash test vector in one configuration, using the ahash API */
|
||||
static int test_ahash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct ahash_request *req,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
const unsigned int alignmask = crypto_ahash_alignmask(tfm);
|
||||
@@ -1082,8 +1282,6 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
|
||||
const struct test_sg_division *divs[XBUFSIZE];
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
struct kvec _input;
|
||||
struct iov_iter input;
|
||||
unsigned int i;
|
||||
struct scatterlist *pending_sgl;
|
||||
unsigned int pending_len;
|
||||
@@ -1096,26 +1294,22 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
if (err) {
|
||||
if (err == vec->setkey_error)
|
||||
return 0;
|
||||
pr_err("alg: hash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
|
||||
pr_err("alg: ahash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
|
||||
driver, vec_name, vec->setkey_error, err,
|
||||
crypto_ahash_get_flags(tfm));
|
||||
return err;
|
||||
}
|
||||
if (vec->setkey_error) {
|
||||
pr_err("alg: hash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
|
||||
pr_err("alg: ahash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
|
||||
driver, vec_name, vec->setkey_error);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the scatterlist for the source data */
|
||||
_input.iov_base = (void *)vec->plaintext;
|
||||
_input.iov_len = vec->psize;
|
||||
iov_iter_kvec(&input, WRITE, &_input, 1, vec->psize);
|
||||
err = build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
|
||||
&input, divs);
|
||||
err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
@@ -1135,13 +1329,13 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
if (err) {
|
||||
if (err == vec->digest_error)
|
||||
return 0;
|
||||
pr_err("alg: hash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, err,
|
||||
cfg->name);
|
||||
return err;
|
||||
}
|
||||
if (vec->digest_error) {
|
||||
pr_err("alg: hash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1153,8 +1347,8 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
|
||||
ahash_request_set_crypt(req, NULL, result, 0);
|
||||
err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd);
|
||||
err = check_nonfinal_hash_op("init", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("init", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1170,9 +1364,9 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
pending_len);
|
||||
err = do_ahash_op(crypto_ahash_update, req, &wait,
|
||||
divs[i]->nosimd);
|
||||
err = check_nonfinal_hash_op("update", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("update", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
pending_sgl = NULL;
|
||||
@@ -1183,23 +1377,23 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
testmgr_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN);
|
||||
err = crypto_ahash_export(req, hashstate);
|
||||
err = check_nonfinal_hash_op("export", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("export", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
if (!testmgr_is_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: hash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
|
||||
err = crypto_ahash_import(req, hashstate);
|
||||
err = check_nonfinal_hash_op("import", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("import", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1213,13 +1407,13 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) {
|
||||
/* finish with update() and final() */
|
||||
err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd);
|
||||
err = check_nonfinal_hash_op("update", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("update", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
err = do_ahash_op(crypto_ahash_final, req, &wait, cfg->nosimd);
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
@@ -1227,31 +1421,49 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
/* finish with finup() */
|
||||
err = do_ahash_op(crypto_ahash_finup, req, &wait, cfg->nosimd);
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
result_ready:
|
||||
/* Check that the algorithm produced the correct digest */
|
||||
if (memcmp(result, vec->digest, digestsize) != 0) {
|
||||
pr_err("alg: hash: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: hash: %s overran result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
return check_hash_result("ahash", result, digestsize, vec, vec_name,
|
||||
driver, cfg);
|
||||
}
|
||||
|
||||
static int test_hash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct ahash_request *req,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* For algorithms implemented as "shash", most bugs will be detected by
|
||||
* both the shash and ahash tests. Test the shash API first so that the
|
||||
* failures involve less indirection, so are easier to debug.
|
||||
*/
|
||||
|
||||
if (desc) {
|
||||
err = test_shash_vec_cfg(driver, vec, vec_name, cfg, desc, tsgl,
|
||||
hashstate);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return test_ahash_vec_cfg(driver, vec, vec_name, cfg, req, tsgl,
|
||||
hashstate);
|
||||
}
|
||||
|
||||
static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
unsigned int vec_num, struct ahash_request *req,
|
||||
struct test_sglist *tsgl, u8 *hashstate)
|
||||
struct shash_desc *desc, struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
char vec_name[16];
|
||||
unsigned int i;
|
||||
@@ -1262,7 +1474,7 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) {
|
||||
err = test_hash_vec_cfg(driver, vec, vec_name,
|
||||
&default_hash_testvec_configs[i],
|
||||
req, tsgl, hashstate);
|
||||
req, desc, tsgl, hashstate);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1276,9 +1488,10 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
generate_random_testvec_config(&cfg, cfgname,
|
||||
sizeof(cfgname));
|
||||
err = test_hash_vec_cfg(driver, vec, vec_name, &cfg,
|
||||
req, tsgl, hashstate);
|
||||
req, desc, tsgl, hashstate);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1290,14 +1503,12 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
* Generate a hash test vector from the given implementation.
|
||||
* Assumes the buffers in 'vec' were already allocated.
|
||||
*/
|
||||
static void generate_random_hash_testvec(struct crypto_shash *tfm,
|
||||
static void generate_random_hash_testvec(struct shash_desc *desc,
|
||||
struct hash_testvec *vec,
|
||||
unsigned int maxkeysize,
|
||||
unsigned int maxdatasize,
|
||||
char *name, size_t max_namelen)
|
||||
{
|
||||
SHASH_DESC_ON_STACK(desc, tfm);
|
||||
|
||||
/* Data */
|
||||
vec->psize = generate_random_length(maxdatasize);
|
||||
generate_random_bytes((u8 *)vec->plaintext, vec->psize);
|
||||
@@ -1314,7 +1525,7 @@ static void generate_random_hash_testvec(struct crypto_shash *tfm,
|
||||
vec->ksize = 1 + (prandom_u32() % maxkeysize);
|
||||
generate_random_bytes((u8 *)vec->key, vec->ksize);
|
||||
|
||||
vec->setkey_error = crypto_shash_setkey(tfm, vec->key,
|
||||
vec->setkey_error = crypto_shash_setkey(desc->tfm, vec->key,
|
||||
vec->ksize);
|
||||
/* If the key couldn't be set, no need to continue to digest. */
|
||||
if (vec->setkey_error)
|
||||
@@ -1322,7 +1533,6 @@ static void generate_random_hash_testvec(struct crypto_shash *tfm,
|
||||
}
|
||||
|
||||
/* Digest */
|
||||
desc->tfm = tfm;
|
||||
vec->digest_error = crypto_shash_digest(desc, vec->plaintext,
|
||||
vec->psize, (u8 *)vec->digest);
|
||||
done:
|
||||
@@ -1338,6 +1548,7 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
const char *generic_driver,
|
||||
unsigned int maxkeysize,
|
||||
struct ahash_request *req,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
@@ -1348,10 +1559,11 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
const char *algname = crypto_hash_alg_common(tfm)->base.cra_name;
|
||||
char _generic_driver[CRYPTO_MAX_ALG_NAME];
|
||||
struct crypto_shash *generic_tfm = NULL;
|
||||
struct shash_desc *generic_desc = NULL;
|
||||
unsigned int i;
|
||||
struct hash_testvec vec = { 0 };
|
||||
char vec_name[64];
|
||||
struct testvec_config cfg;
|
||||
struct testvec_config *cfg;
|
||||
char cfgname[TESTVEC_CONFIG_NAMELEN];
|
||||
int err;
|
||||
|
||||
@@ -1381,6 +1593,20 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
return err;
|
||||
}
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
generic_desc = kzalloc(sizeof(*desc) +
|
||||
crypto_shash_descsize(generic_tfm), GFP_KERNEL);
|
||||
if (!generic_desc) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
generic_desc->tfm = generic_tfm;
|
||||
|
||||
/* Check the algorithm properties for consistency. */
|
||||
|
||||
if (digestsize != crypto_shash_digestsize(generic_tfm)) {
|
||||
@@ -1412,23 +1638,25 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
}
|
||||
|
||||
for (i = 0; i < fuzz_iterations * 8; i++) {
|
||||
generate_random_hash_testvec(generic_tfm, &vec,
|
||||
generate_random_hash_testvec(generic_desc, &vec,
|
||||
maxkeysize, maxdatasize,
|
||||
vec_name, sizeof(vec_name));
|
||||
generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
|
||||
generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
|
||||
|
||||
err = test_hash_vec_cfg(driver, &vec, vec_name, &cfg,
|
||||
req, tsgl, hashstate);
|
||||
err = test_hash_vec_cfg(driver, &vec, vec_name, cfg,
|
||||
req, desc, tsgl, hashstate);
|
||||
if (err)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
kfree(cfg);
|
||||
kfree(vec.key);
|
||||
kfree(vec.plaintext);
|
||||
kfree(vec.digest);
|
||||
crypto_free_shash(generic_tfm);
|
||||
kzfree(generic_desc);
|
||||
return err;
|
||||
}
|
||||
#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
|
||||
@@ -1436,6 +1664,7 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
const char *generic_driver,
|
||||
unsigned int maxkeysize,
|
||||
struct ahash_request *req,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
@@ -1443,26 +1672,67 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
}
|
||||
#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
|
||||
|
||||
static int alloc_shash(const char *driver, u32 type, u32 mask,
|
||||
struct crypto_shash **tfm_ret,
|
||||
struct shash_desc **desc_ret)
|
||||
{
|
||||
struct crypto_shash *tfm;
|
||||
struct shash_desc *desc;
|
||||
|
||||
tfm = crypto_alloc_shash(driver, type, mask);
|
||||
if (IS_ERR(tfm)) {
|
||||
if (PTR_ERR(tfm) == -ENOENT) {
|
||||
/*
|
||||
* This algorithm is only available through the ahash
|
||||
* API, not the shash API, so skip the shash tests.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
pr_err("alg: hash: failed to allocate shash transform for %s: %ld\n",
|
||||
driver, PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
}
|
||||
|
||||
desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
crypto_free_shash(tfm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
desc->tfm = tfm;
|
||||
|
||||
*tfm_ret = tfm;
|
||||
*desc_ret = desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
unsigned int num_vecs, const char *driver,
|
||||
u32 type, u32 mask,
|
||||
const char *generic_driver, unsigned int maxkeysize)
|
||||
{
|
||||
struct crypto_ahash *tfm;
|
||||
struct crypto_ahash *atfm = NULL;
|
||||
struct ahash_request *req = NULL;
|
||||
struct crypto_shash *stfm = NULL;
|
||||
struct shash_desc *desc = NULL;
|
||||
struct test_sglist *tsgl = NULL;
|
||||
u8 *hashstate = NULL;
|
||||
unsigned int statesize;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
tfm = crypto_alloc_ahash(driver, type, mask);
|
||||
if (IS_ERR(tfm)) {
|
||||
/*
|
||||
* Always test the ahash API. This works regardless of whether the
|
||||
* algorithm is implemented as ahash or shash.
|
||||
*/
|
||||
|
||||
atfm = crypto_alloc_ahash(driver, type, mask);
|
||||
if (IS_ERR(atfm)) {
|
||||
pr_err("alg: hash: failed to allocate transform for %s: %ld\n",
|
||||
driver, PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
driver, PTR_ERR(atfm));
|
||||
return PTR_ERR(atfm);
|
||||
}
|
||||
|
||||
req = ahash_request_alloc(tfm, GFP_KERNEL);
|
||||
req = ahash_request_alloc(atfm, GFP_KERNEL);
|
||||
if (!req) {
|
||||
pr_err("alg: hash: failed to allocate request for %s\n",
|
||||
driver);
|
||||
@@ -1470,6 +1740,14 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If available also test the shash API, to cover corner cases that may
|
||||
* be missed by testing the ahash API only.
|
||||
*/
|
||||
err = alloc_shash(driver, type, mask, &stfm, &desc);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
tsgl = kmalloc(sizeof(*tsgl), GFP_KERNEL);
|
||||
if (!tsgl || init_test_sglist(tsgl) != 0) {
|
||||
pr_err("alg: hash: failed to allocate test buffers for %s\n",
|
||||
@@ -1480,8 +1758,10 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
hashstate = kmalloc(crypto_ahash_statesize(tfm) + TESTMGR_POISON_LEN,
|
||||
GFP_KERNEL);
|
||||
statesize = crypto_ahash_statesize(atfm);
|
||||
if (stfm)
|
||||
statesize = max(statesize, crypto_shash_statesize(stfm));
|
||||
hashstate = kmalloc(statesize + TESTMGR_POISON_LEN, GFP_KERNEL);
|
||||
if (!hashstate) {
|
||||
pr_err("alg: hash: failed to allocate hash state buffer for %s\n",
|
||||
driver);
|
||||
@@ -1490,20 +1770,24 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
}
|
||||
|
||||
for (i = 0; i < num_vecs; i++) {
|
||||
err = test_hash_vec(driver, &vecs[i], i, req, tsgl, hashstate);
|
||||
err = test_hash_vec(driver, &vecs[i], i, req, desc, tsgl,
|
||||
hashstate);
|
||||
if (err)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
err = test_hash_vs_generic_impl(driver, generic_driver, maxkeysize, req,
|
||||
tsgl, hashstate);
|
||||
desc, tsgl, hashstate);
|
||||
out:
|
||||
kfree(hashstate);
|
||||
if (tsgl) {
|
||||
destroy_test_sglist(tsgl);
|
||||
kfree(tsgl);
|
||||
}
|
||||
kfree(desc);
|
||||
crypto_free_shash(stfm);
|
||||
ahash_request_free(req);
|
||||
crypto_free_ahash(tfm);
|
||||
crypto_free_ahash(atfm);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1755,6 +2039,7 @@ static int test_aead_vec(const char *driver, int enc,
|
||||
&cfg, req, tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1864,7 +2149,7 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
unsigned int i;
|
||||
struct aead_testvec vec = { 0 };
|
||||
char vec_name[64];
|
||||
struct testvec_config cfg;
|
||||
struct testvec_config *cfg;
|
||||
char cfgname[TESTVEC_CONFIG_NAMELEN];
|
||||
int err;
|
||||
|
||||
@@ -1894,6 +2179,12 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
return err;
|
||||
}
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL);
|
||||
if (!generic_req) {
|
||||
err = -ENOMEM;
|
||||
@@ -1948,13 +2239,13 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
generate_random_aead_testvec(generic_req, &vec,
|
||||
maxkeysize, maxdatasize,
|
||||
vec_name, sizeof(vec_name));
|
||||
generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
|
||||
generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
|
||||
|
||||
err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, &cfg,
|
||||
err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, cfg,
|
||||
req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, &cfg,
|
||||
err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, cfg,
|
||||
req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
@@ -1962,6 +2253,7 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
kfree(cfg);
|
||||
kfree(vec.key);
|
||||
kfree(vec.iv);
|
||||
kfree(vec.assoc);
|
||||
@@ -1994,6 +2286,7 @@ static int test_aead(const char *driver, int enc,
|
||||
tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2336,6 +2629,7 @@ static int test_skcipher_vec(const char *driver, int enc,
|
||||
&cfg, req, tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2409,7 +2703,7 @@ static int test_skcipher_vs_generic_impl(const char *driver,
|
||||
unsigned int i;
|
||||
struct cipher_testvec vec = { 0 };
|
||||
char vec_name[64];
|
||||
struct testvec_config cfg;
|
||||
struct testvec_config *cfg;
|
||||
char cfgname[TESTVEC_CONFIG_NAMELEN];
|
||||
int err;
|
||||
|
||||
@@ -2443,6 +2737,12 @@ static int test_skcipher_vs_generic_impl(const char *driver,
|
||||
return err;
|
||||
}
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
generic_req = skcipher_request_alloc(generic_tfm, GFP_KERNEL);
|
||||
if (!generic_req) {
|
||||
err = -ENOMEM;
|
||||
@@ -2490,20 +2790,21 @@ static int test_skcipher_vs_generic_impl(const char *driver,
|
||||
for (i = 0; i < fuzz_iterations * 8; i++) {
|
||||
generate_random_cipher_testvec(generic_req, &vec, maxdatasize,
|
||||
vec_name, sizeof(vec_name));
|
||||
generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
|
||||
generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
|
||||
|
||||
err = test_skcipher_vec_cfg(driver, ENCRYPT, &vec, vec_name,
|
||||
&cfg, req, tsgls);
|
||||
cfg, req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
err = test_skcipher_vec_cfg(driver, DECRYPT, &vec, vec_name,
|
||||
&cfg, req, tsgls);
|
||||
cfg, req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
kfree(cfg);
|
||||
kfree(vec.key);
|
||||
kfree(vec.iv);
|
||||
kfree(vec.ptext);
|
||||
@@ -2535,6 +2836,7 @@ static int test_skcipher(const char *driver, int enc,
|
||||
tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4125,6 +4427,7 @@ static const struct alg_test_desc alg_test_descs[] = {
|
||||
}
|
||||
}, {
|
||||
.alg = "ecb(arc4)",
|
||||
.generic_driver = "ecb(arc4)-generic",
|
||||
.test = alg_test_skcipher,
|
||||
.suite = {
|
||||
.cipher = __VECS(arc4_tv_template)
|
||||
@@ -4789,6 +5092,13 @@ static const struct alg_test_desc alg_test_descs[] = {
|
||||
.alg = "xts512(paes)",
|
||||
.test = alg_test_null,
|
||||
.fips_allowed = 1,
|
||||
}, {
|
||||
.alg = "xxhash64",
|
||||
.test = alg_test_hash,
|
||||
.fips_allowed = 1,
|
||||
.suite = {
|
||||
.hash = __VECS(xxhash64_tv_template)
|
||||
}
|
||||
}, {
|
||||
.alg = "zlib-deflate",
|
||||
.test = alg_test_comp,
|
||||
|
116
crypto/testmgr.h
116
crypto/testmgr.h
@@ -38,7 +38,7 @@ struct hash_testvec {
|
||||
const char *key;
|
||||
const char *plaintext;
|
||||
const char *digest;
|
||||
unsigned short psize;
|
||||
unsigned int psize;
|
||||
unsigned short ksize;
|
||||
int setkey_error;
|
||||
int digest_error;
|
||||
@@ -69,7 +69,7 @@ struct cipher_testvec {
|
||||
const char *ctext;
|
||||
unsigned char wk; /* weak key flag */
|
||||
unsigned short klen;
|
||||
unsigned short len;
|
||||
unsigned int len;
|
||||
bool fips_skip;
|
||||
bool generates_iv;
|
||||
int setkey_error;
|
||||
@@ -105,9 +105,9 @@ struct aead_testvec {
|
||||
unsigned char novrfy;
|
||||
unsigned char wk;
|
||||
unsigned char klen;
|
||||
unsigned short plen;
|
||||
unsigned short clen;
|
||||
unsigned short alen;
|
||||
unsigned int plen;
|
||||
unsigned int clen;
|
||||
unsigned int alen;
|
||||
int setkey_error;
|
||||
int setauthsize_error;
|
||||
int crypt_error;
|
||||
@@ -33382,6 +33382,112 @@ static const struct hash_testvec crc32c_tv_template[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hash_testvec xxhash64_tv_template[] = {
|
||||
{
|
||||
.psize = 0,
|
||||
.digest = "\x99\xe9\xd8\x51\x37\xdb\x46\xef",
|
||||
},
|
||||
{
|
||||
.plaintext = "\x40",
|
||||
.psize = 1,
|
||||
.digest = "\x20\x5c\x91\xaa\x88\xeb\x59\xd0",
|
||||
},
|
||||
{
|
||||
.plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d"
|
||||
"\x88\xc7\x9a\x09\x1a\x9b",
|
||||
.psize = 14,
|
||||
.digest = "\xa8\xe8\x2b\xa9\x92\xa1\x37\x4a",
|
||||
},
|
||||
{
|
||||
.plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d"
|
||||
"\x88\xc7\x9a\x09\x1a\x9b\x42\xe0"
|
||||
"\xd4\x38\xa5\x2a\x26\xa5\x19\x4b"
|
||||
"\x57\x65\x7f\xad\xc3\x7d\xca\x40"
|
||||
"\x31\x65\x05\xbb\x31\xae\x51\x11"
|
||||
"\xa8\xc0\xb3\x28\x42\xeb\x3c\x46"
|
||||
"\xc8\xed\xed\x0f\x8d\x0b\xfa\x6e"
|
||||
"\xbc\xe3\x88\x53\xca\x8f\xc8\xd9"
|
||||
"\x41\x26\x7a\x3d\x21\xdb\x1a\x3c"
|
||||
"\x01\x1d\xc9\xe9\xb7\x3a\x78\x67"
|
||||
"\x57\x20\x94\xf1\x1e\xfd\xce\x39"
|
||||
"\x99\x57\x69\x39\xa5\xd0\x8d\xd9"
|
||||
"\x43\xfe\x1d\x66\x04\x3c\x27\x6a"
|
||||
"\xe1\x0d\xe7\xc9\xfa\xc9\x07\x56"
|
||||
"\xa5\xb3\xec\xd9\x1f\x42\x65\x66"
|
||||
"\xaa\xbf\x87\x9b\xc5\x41\x9c\x27"
|
||||
"\x3f\x2f\xa9\x55\x93\x01\x27\x33"
|
||||
"\x43\x99\x4d\x81\x85\xae\x82\x00"
|
||||
"\x6c\xd0\xd1\xa3\x57\x18\x06\xcc"
|
||||
"\xec\x72\xf7\x8e\x87\x2d\x1f\x5e"
|
||||
"\xd7\x5b\x1f\x36\x4c\xfa\xfd\x18"
|
||||
"\x89\x76\xd3\x5e\xb5\x5a\xc0\x01"
|
||||
"\xd2\xa1\x9a\x50\xe6\x08\xb4\x76"
|
||||
"\x56\x4f\x0e\xbc\x54\xfc\x67\xe6"
|
||||
"\xb9\xc0\x28\x4b\xb5\xc3\xff\x79"
|
||||
"\x52\xea\xa1\x90\xc3\xaf\x08\x70"
|
||||
"\x12\x02\x0c\xdb\x94\x00\x38\x95"
|
||||
"\xed\xfd\x08\xf7\xe8\x04",
|
||||
.psize = 222,
|
||||
.digest = "\x41\xfc\xd4\x29\xfe\xe7\x85\x17",
|
||||
},
|
||||
{
|
||||
.psize = 0,
|
||||
.key = "\xb1\x79\x37\x9e\x00\x00\x00\x00",
|
||||
.ksize = 8,
|
||||
.digest = "\xef\x17\x9b\x92\xa2\xfd\x75\xac",
|
||||
},
|
||||
|
||||
{
|
||||
.plaintext = "\x40",
|
||||
.psize = 1,
|
||||
.key = "\xb1\x79\x37\x9e\x00\x00\x00\x00",
|
||||
.ksize = 8,
|
||||
.digest = "\xd1\x70\x4f\x14\x02\xc4\x9e\x71",
|
||||
},
|
||||
{
|
||||
.plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d"
|
||||
"\x88\xc7\x9a\x09\x1a\x9b",
|
||||
.psize = 14,
|
||||
.key = "\xb1\x79\x37\x9e\x00\x00\x00\x00",
|
||||
.ksize = 8,
|
||||
.digest = "\xa4\xcd\xfe\x8e\x37\xe2\x1c\x64"
|
||||
},
|
||||
{
|
||||
.plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d"
|
||||
"\x88\xc7\x9a\x09\x1a\x9b\x42\xe0"
|
||||
"\xd4\x38\xa5\x2a\x26\xa5\x19\x4b"
|
||||
"\x57\x65\x7f\xad\xc3\x7d\xca\x40"
|
||||
"\x31\x65\x05\xbb\x31\xae\x51\x11"
|
||||
"\xa8\xc0\xb3\x28\x42\xeb\x3c\x46"
|
||||
"\xc8\xed\xed\x0f\x8d\x0b\xfa\x6e"
|
||||
"\xbc\xe3\x88\x53\xca\x8f\xc8\xd9"
|
||||
"\x41\x26\x7a\x3d\x21\xdb\x1a\x3c"
|
||||
"\x01\x1d\xc9\xe9\xb7\x3a\x78\x67"
|
||||
"\x57\x20\x94\xf1\x1e\xfd\xce\x39"
|
||||
"\x99\x57\x69\x39\xa5\xd0\x8d\xd9"
|
||||
"\x43\xfe\x1d\x66\x04\x3c\x27\x6a"
|
||||
"\xe1\x0d\xe7\xc9\xfa\xc9\x07\x56"
|
||||
"\xa5\xb3\xec\xd9\x1f\x42\x65\x66"
|
||||
"\xaa\xbf\x87\x9b\xc5\x41\x9c\x27"
|
||||
"\x3f\x2f\xa9\x55\x93\x01\x27\x33"
|
||||
"\x43\x99\x4d\x81\x85\xae\x82\x00"
|
||||
"\x6c\xd0\xd1\xa3\x57\x18\x06\xcc"
|
||||
"\xec\x72\xf7\x8e\x87\x2d\x1f\x5e"
|
||||
"\xd7\x5b\x1f\x36\x4c\xfa\xfd\x18"
|
||||
"\x89\x76\xd3\x5e\xb5\x5a\xc0\x01"
|
||||
"\xd2\xa1\x9a\x50\xe6\x08\xb4\x76"
|
||||
"\x56\x4f\x0e\xbc\x54\xfc\x67\xe6"
|
||||
"\xb9\xc0\x28\x4b\xb5\xc3\xff\x79"
|
||||
"\x52\xea\xa1\x90\xc3\xaf\x08\x70"
|
||||
"\x12\x02\x0c\xdb\x94\x00\x38\x95"
|
||||
"\xed\xfd\x08\xf7\xe8\x04",
|
||||
.psize = 222,
|
||||
.key = "\xb1\x79\x37\x9e\x00\x00\x00\x00",
|
||||
.ksize = 8,
|
||||
.digest = "\x58\xbc\x55\xf2\x42\x81\x5c\xf0"
|
||||
},
|
||||
};
|
||||
|
||||
static const struct comp_testvec lz4_comp_tv_template[] = {
|
||||
{
|
||||
.inlen = 255,
|
||||
|
@@ -630,9 +630,10 @@ static struct shash_alg tgr_algs[3] = { {
|
||||
.final = tgr192_final,
|
||||
.descsize = sizeof(struct tgr192_ctx),
|
||||
.base = {
|
||||
.cra_name = "tgr192",
|
||||
.cra_blocksize = TGR192_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "tgr192",
|
||||
.cra_driver_name = "tgr192-generic",
|
||||
.cra_blocksize = TGR192_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
}, {
|
||||
.digestsize = TGR160_DIGEST_SIZE,
|
||||
@@ -641,9 +642,10 @@ static struct shash_alg tgr_algs[3] = { {
|
||||
.final = tgr160_final,
|
||||
.descsize = sizeof(struct tgr192_ctx),
|
||||
.base = {
|
||||
.cra_name = "tgr160",
|
||||
.cra_blocksize = TGR192_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "tgr160",
|
||||
.cra_driver_name = "tgr160-generic",
|
||||
.cra_blocksize = TGR192_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
}, {
|
||||
.digestsize = TGR128_DIGEST_SIZE,
|
||||
@@ -652,9 +654,10 @@ static struct shash_alg tgr_algs[3] = { {
|
||||
.final = tgr128_final,
|
||||
.descsize = sizeof(struct tgr192_ctx),
|
||||
.base = {
|
||||
.cra_name = "tgr128",
|
||||
.cra_blocksize = TGR192_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "tgr128",
|
||||
.cra_driver_name = "tgr128-generic",
|
||||
.cra_blocksize = TGR192_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
} };
|
||||
|
||||
|
@@ -1126,9 +1126,10 @@ static struct shash_alg wp_algs[3] = { {
|
||||
.final = wp512_final,
|
||||
.descsize = sizeof(struct wp512_ctx),
|
||||
.base = {
|
||||
.cra_name = "wp512",
|
||||
.cra_blocksize = WP512_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "wp512",
|
||||
.cra_driver_name = "wp512-generic",
|
||||
.cra_blocksize = WP512_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
}, {
|
||||
.digestsize = WP384_DIGEST_SIZE,
|
||||
@@ -1137,9 +1138,10 @@ static struct shash_alg wp_algs[3] = { {
|
||||
.final = wp384_final,
|
||||
.descsize = sizeof(struct wp512_ctx),
|
||||
.base = {
|
||||
.cra_name = "wp384",
|
||||
.cra_blocksize = WP512_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "wp384",
|
||||
.cra_driver_name = "wp384-generic",
|
||||
.cra_blocksize = WP512_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
}, {
|
||||
.digestsize = WP256_DIGEST_SIZE,
|
||||
@@ -1148,9 +1150,10 @@ static struct shash_alg wp_algs[3] = { {
|
||||
.final = wp256_final,
|
||||
.descsize = sizeof(struct wp512_ctx),
|
||||
.base = {
|
||||
.cra_name = "wp256",
|
||||
.cra_blocksize = WP512_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_name = "wp256",
|
||||
.cra_driver_name = "wp256-generic",
|
||||
.cra_blocksize = WP512_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
} };
|
||||
|
||||
|
108
crypto/xxhash_generic.c
Normal file
108
crypto/xxhash_generic.c
Normal file
@@ -0,0 +1,108 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/xxhash.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define XXHASH64_BLOCK_SIZE 32
|
||||
#define XXHASH64_DIGEST_SIZE 8
|
||||
|
||||
struct xxhash64_tfm_ctx {
|
||||
u64 seed;
|
||||
};
|
||||
|
||||
struct xxhash64_desc_ctx {
|
||||
struct xxh64_state xxhstate;
|
||||
};
|
||||
|
||||
static int xxhash64_setkey(struct crypto_shash *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(tfm);
|
||||
|
||||
if (keylen != sizeof(tctx->seed)) {
|
||||
crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
tctx->seed = get_unaligned_le64(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xxhash64_init(struct shash_desc *desc)
|
||||
{
|
||||
struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||
|
||||
xxh64_reset(&dctx->xxhstate, tctx->seed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xxhash64_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int length)
|
||||
{
|
||||
struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||
|
||||
xxh64_update(&dctx->xxhstate, data, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xxhash64_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||
|
||||
put_unaligned_le64(xxh64_digest(&dctx->xxhstate), out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xxhash64_digest(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int length, u8 *out)
|
||||
{
|
||||
struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
|
||||
put_unaligned_le64(xxh64(data, length, tctx->seed), out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct shash_alg alg = {
|
||||
.digestsize = XXHASH64_DIGEST_SIZE,
|
||||
.setkey = xxhash64_setkey,
|
||||
.init = xxhash64_init,
|
||||
.update = xxhash64_update,
|
||||
.final = xxhash64_final,
|
||||
.digest = xxhash64_digest,
|
||||
.descsize = sizeof(struct xxhash64_desc_ctx),
|
||||
.base = {
|
||||
.cra_name = "xxhash64",
|
||||
.cra_driver_name = "xxhash64-generic",
|
||||
.cra_priority = 100,
|
||||
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
|
||||
.cra_blocksize = XXHASH64_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct xxhash64_tfm_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init xxhash_mod_init(void)
|
||||
{
|
||||
return crypto_register_shash(&alg);
|
||||
}
|
||||
|
||||
static void __exit xxhash_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_shash(&alg);
|
||||
}
|
||||
|
||||
subsys_initcall(xxhash_mod_init);
|
||||
module_exit(xxhash_mod_fini);
|
||||
|
||||
MODULE_AUTHOR("Nikolay Borisov <nborisov@suse.com>");
|
||||
MODULE_DESCRIPTION("xxhash calculations wrapper for lib/xxhash.c");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_CRYPTO("xxhash64");
|
||||
MODULE_ALIAS_CRYPTO("xxhash64-generic");
|
@@ -206,6 +206,7 @@ static int zstd_sdecompress(struct crypto_scomp *tfm, const u8 *src,
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "zstd",
|
||||
.cra_driver_name = "zstd-generic",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct zstd_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
|
Reference in New Issue
Block a user