You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'HEAD' of master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
Conflicts: crypto/Kconfig
This commit is contained in:
@@ -193,6 +193,7 @@ Original developers of the crypto algorithms:
|
||||
Kartikey Mahendra Bhatt (CAST6)
|
||||
Jon Oberheide (ARC4)
|
||||
Jouni Malinen (Michael MIC)
|
||||
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
|
||||
|
||||
SHA1 algorithm contributors:
|
||||
Jean-Francois Dive
|
||||
@@ -246,6 +247,9 @@ Tiger algorithm contributors:
|
||||
VIA PadLock contributors:
|
||||
Michal Ludvig
|
||||
|
||||
Camellia algorithm contributors:
|
||||
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
|
||||
|
||||
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
||||
|
||||
Please send any credits updates or corrections to:
|
||||
|
||||
@@ -149,6 +149,15 @@ config CRYPTO_CBC
|
||||
CBC: Cipher Block Chaining mode
|
||||
This block cipher algorithm is required for IPSec.
|
||||
|
||||
config CRYPTO_PCBC
|
||||
tristate "PCBC support"
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_MANAGER
|
||||
default m
|
||||
help
|
||||
PCBC: Propagating Cipher Block Chaining mode
|
||||
This block cipher algorithm is required for RxRPC.
|
||||
|
||||
config CRYPTO_LRW
|
||||
tristate "LRW support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
@@ -168,6 +177,13 @@ config CRYPTO_DES
|
||||
help
|
||||
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
|
||||
|
||||
config CRYPTO_FCRYPT
|
||||
tristate "FCrypt cipher algorithm"
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_BLKCIPHER
|
||||
help
|
||||
FCrypt algorithm used by RxRPC.
|
||||
|
||||
config CRYPTO_BLOWFISH
|
||||
tristate "Blowfish cipher algorithm"
|
||||
select CRYPTO_ALGAPI
|
||||
@@ -409,6 +425,21 @@ config CRYPTO_CRC32C
|
||||
See Castagnoli93. This implementation uses lib/libcrc32c.
|
||||
Module will be crc32c.
|
||||
|
||||
config CRYPTO_CAMELLIA
|
||||
tristate "Camellia cipher algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Camellia cipher algorithms module.
|
||||
|
||||
Camellia is a symmetric key block cipher developed jointly
|
||||
at NTT and Mitsubishi Electric Corporation.
|
||||
|
||||
The Camellia specifies three key sizes: 128, 192 and 256 bits.
|
||||
|
||||
See also:
|
||||
<https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
|
||||
|
||||
config CRYPTO_TEST
|
||||
tristate "Testing module"
|
||||
depends on m
|
||||
|
||||
@@ -27,13 +27,16 @@ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
|
||||
obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
|
||||
obj-$(CONFIG_CRYPTO_ECB) += ecb.o
|
||||
obj-$(CONFIG_CRYPTO_CBC) += cbc.o
|
||||
obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
|
||||
obj-$(CONFIG_CRYPTO_LRW) += lrw.o
|
||||
obj-$(CONFIG_CRYPTO_DES) += des.o
|
||||
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
|
||||
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
|
||||
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
|
||||
obj-$(CONFIG_CRYPTO_AES) += aes.o
|
||||
obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia.o
|
||||
obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
|
||||
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
|
||||
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
|
||||
|
||||
+13
-4
@@ -377,7 +377,8 @@ void crypto_drop_spawn(struct crypto_spawn *spawn)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_drop_spawn);
|
||||
|
||||
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
|
||||
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_alg *alg2;
|
||||
@@ -396,10 +397,18 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
|
||||
tfm = __crypto_alloc_tfm(alg, 0);
|
||||
if (IS_ERR(tfm))
|
||||
crypto_mod_put(alg);
|
||||
tfm = ERR_PTR(-EINVAL);
|
||||
if (unlikely((alg->cra_flags ^ type) & mask))
|
||||
goto out_put_alg;
|
||||
|
||||
tfm = __crypto_alloc_tfm(alg, type, mask);
|
||||
if (IS_ERR(tfm))
|
||||
goto out_put_alg;
|
||||
|
||||
return tfm;
|
||||
|
||||
out_put_alg:
|
||||
crypto_mod_put(alg);
|
||||
return tfm;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
|
||||
|
||||
+16
-64
@@ -212,31 +212,12 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
|
||||
|
||||
static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
|
||||
static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
{
|
||||
tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
|
||||
flags &= ~CRYPTO_TFM_REQ_MASK;
|
||||
|
||||
switch (crypto_tfm_alg_type(tfm)) {
|
||||
case CRYPTO_ALG_TYPE_CIPHER:
|
||||
return crypto_init_cipher_flags(tfm, flags);
|
||||
|
||||
case CRYPTO_ALG_TYPE_DIGEST:
|
||||
return crypto_init_digest_flags(tfm, flags);
|
||||
|
||||
case CRYPTO_ALG_TYPE_COMPRESS:
|
||||
return crypto_init_compress_flags(tfm, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
|
||||
|
||||
static int crypto_init_ops(struct crypto_tfm *tfm)
|
||||
{
|
||||
const struct crypto_type *type = tfm->__crt_alg->cra_type;
|
||||
|
||||
if (type)
|
||||
return type->init(tfm);
|
||||
if (type_obj)
|
||||
return type_obj->init(tfm, type, mask);
|
||||
|
||||
switch (crypto_tfm_alg_type(tfm)) {
|
||||
case CRYPTO_ALG_TYPE_CIPHER:
|
||||
@@ -285,29 +266,29 @@ static void crypto_exit_ops(struct crypto_tfm *tfm)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags)
|
||||
static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
|
||||
{
|
||||
const struct crypto_type *type = alg->cra_type;
|
||||
const struct crypto_type *type_obj = alg->cra_type;
|
||||
unsigned int len;
|
||||
|
||||
len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
|
||||
if (type)
|
||||
return len + type->ctxsize(alg);
|
||||
if (type_obj)
|
||||
return len + type_obj->ctxsize(alg, type, mask);
|
||||
|
||||
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
|
||||
default:
|
||||
BUG();
|
||||
|
||||
case CRYPTO_ALG_TYPE_CIPHER:
|
||||
len += crypto_cipher_ctxsize(alg, flags);
|
||||
len += crypto_cipher_ctxsize(alg);
|
||||
break;
|
||||
|
||||
case CRYPTO_ALG_TYPE_DIGEST:
|
||||
len += crypto_digest_ctxsize(alg, flags);
|
||||
len += crypto_digest_ctxsize(alg);
|
||||
break;
|
||||
|
||||
case CRYPTO_ALG_TYPE_COMPRESS:
|
||||
len += crypto_compress_ctxsize(alg, flags);
|
||||
len += crypto_compress_ctxsize(alg);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -322,24 +303,21 @@ void crypto_shoot_alg(struct crypto_alg *alg)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_shoot_alg);
|
||||
|
||||
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
|
||||
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
struct crypto_tfm *tfm = NULL;
|
||||
unsigned int tfm_size;
|
||||
int err = -ENOMEM;
|
||||
|
||||
tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
|
||||
tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
|
||||
tfm = kzalloc(tfm_size, GFP_KERNEL);
|
||||
if (tfm == NULL)
|
||||
goto out_err;
|
||||
|
||||
tfm->__crt_alg = alg;
|
||||
|
||||
err = crypto_init_flags(tfm, flags);
|
||||
if (err)
|
||||
goto out_free_tfm;
|
||||
|
||||
err = crypto_init_ops(tfm);
|
||||
err = crypto_init_ops(tfm, type, mask);
|
||||
if (err)
|
||||
goto out_free_tfm;
|
||||
|
||||
@@ -362,31 +340,6 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
|
||||
|
||||
struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
|
||||
{
|
||||
struct crypto_tfm *tfm = NULL;
|
||||
int err;
|
||||
|
||||
do {
|
||||
struct crypto_alg *alg;
|
||||
|
||||
alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
|
||||
err = PTR_ERR(alg);
|
||||
if (IS_ERR(alg))
|
||||
continue;
|
||||
|
||||
tfm = __crypto_alloc_tfm(alg, flags);
|
||||
err = 0;
|
||||
if (IS_ERR(tfm)) {
|
||||
crypto_mod_put(alg);
|
||||
err = PTR_ERR(tfm);
|
||||
tfm = NULL;
|
||||
}
|
||||
} while (err == -EAGAIN && !signal_pending(current));
|
||||
|
||||
return tfm;
|
||||
}
|
||||
|
||||
/*
|
||||
* crypto_alloc_base - Locate algorithm and allocate transform
|
||||
* @alg_name: Name of algorithm
|
||||
@@ -420,7 +373,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
|
||||
goto err;
|
||||
}
|
||||
|
||||
tfm = __crypto_alloc_tfm(alg, 0);
|
||||
tfm = __crypto_alloc_tfm(alg, type, mask);
|
||||
if (!IS_ERR(tfm))
|
||||
return tfm;
|
||||
|
||||
@@ -466,7 +419,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
|
||||
kfree(tfm);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
|
||||
EXPORT_SYMBOL_GPL(crypto_free_tfm);
|
||||
|
||||
int crypto_has_alg(const char *name, u32 type, u32 mask)
|
||||
|
||||
+7
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/scatterlist.h>
|
||||
@@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
|
||||
|
||||
if (WARN_ON_ONCE(in_irq()))
|
||||
return -EDEADLK;
|
||||
|
||||
walk->nbytes = walk->total;
|
||||
if (unlikely(!walk->total))
|
||||
return 0;
|
||||
@@ -345,7 +349,8 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key,
|
||||
return cipher->setkey(tfm, key, keylen);
|
||||
}
|
||||
|
||||
static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
|
||||
static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
struct blkcipher_alg *cipher = &alg->cra_blkcipher;
|
||||
unsigned int len = alg->cra_ctxsize;
|
||||
@@ -358,7 +363,7 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm)
|
||||
static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
{
|
||||
struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
|
||||
struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
|
||||
|
||||
+1801
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -243,6 +243,7 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct crypto_cipher *cipher;
|
||||
|
||||
switch (crypto_tfm_alg_blocksize(tfm)) {
|
||||
case 8:
|
||||
@@ -260,11 +261,11 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
|
||||
ctx->xor = xor_quad;
|
||||
}
|
||||
|
||||
tfm = crypto_spawn_tfm(spawn);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
cipher = crypto_spawn_cipher(spawn);
|
||||
if (IS_ERR(cipher))
|
||||
return PTR_ERR(cipher);
|
||||
|
||||
ctx->child = crypto_cipher_cast(tfm);
|
||||
ctx->child = cipher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+3
-444
@@ -12,274 +12,13 @@
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include "internal.h"
|
||||
#include "scatterwalk.h"
|
||||
|
||||
struct cipher_alg_compat {
|
||||
unsigned int cia_min_keysize;
|
||||
unsigned int cia_max_keysize;
|
||||
int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key,
|
||||
unsigned int keylen);
|
||||
void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
|
||||
unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
|
||||
u8 *dst, const u8 *src,
|
||||
unsigned int nbytes);
|
||||
unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
|
||||
u8 *dst, const u8 *src,
|
||||
unsigned int nbytes);
|
||||
unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
|
||||
u8 *dst, const u8 *src,
|
||||
unsigned int nbytes);
|
||||
unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
|
||||
u8 *dst, const u8 *src,
|
||||
unsigned int nbytes);
|
||||
};
|
||||
|
||||
static inline void xor_64(u8 *a, const u8 *b)
|
||||
{
|
||||
((u32 *)a)[0] ^= ((u32 *)b)[0];
|
||||
((u32 *)a)[1] ^= ((u32 *)b)[1];
|
||||
}
|
||||
|
||||
static inline void xor_128(u8 *a, const u8 *b)
|
||||
{
|
||||
((u32 *)a)[0] ^= ((u32 *)b)[0];
|
||||
((u32 *)a)[1] ^= ((u32 *)b)[1];
|
||||
((u32 *)a)[2] ^= ((u32 *)b)[2];
|
||||
((u32 *)a)[3] ^= ((u32 *)b)[3];
|
||||
}
|
||||
|
||||
static unsigned int crypt_slow(const struct cipher_desc *desc,
|
||||
struct scatter_walk *in,
|
||||
struct scatter_walk *out, unsigned int bsize)
|
||||
{
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
|
||||
u8 buffer[bsize * 2 + alignmask];
|
||||
u8 *src = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||
u8 *dst = src + bsize;
|
||||
|
||||
scatterwalk_copychunks(src, in, bsize, 0);
|
||||
desc->prfn(desc, dst, src, bsize);
|
||||
scatterwalk_copychunks(dst, out, bsize, 1);
|
||||
|
||||
return bsize;
|
||||
}
|
||||
|
||||
static inline unsigned int crypt_fast(const struct cipher_desc *desc,
|
||||
struct scatter_walk *in,
|
||||
struct scatter_walk *out,
|
||||
unsigned int nbytes, u8 *tmp)
|
||||
{
|
||||
u8 *src, *dst;
|
||||
u8 *real_src, *real_dst;
|
||||
|
||||
real_src = scatterwalk_map(in, 0);
|
||||
real_dst = scatterwalk_map(out, 1);
|
||||
|
||||
src = real_src;
|
||||
dst = scatterwalk_samebuf(in, out) ? src : real_dst;
|
||||
|
||||
if (tmp) {
|
||||
memcpy(tmp, src, nbytes);
|
||||
src = tmp;
|
||||
dst = tmp;
|
||||
}
|
||||
|
||||
nbytes = desc->prfn(desc, dst, src, nbytes);
|
||||
|
||||
if (tmp)
|
||||
memcpy(real_dst, tmp, nbytes);
|
||||
|
||||
scatterwalk_unmap(real_src, 0);
|
||||
scatterwalk_unmap(real_dst, 1);
|
||||
|
||||
scatterwalk_advance(in, nbytes);
|
||||
scatterwalk_advance(out, nbytes);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic encrypt/decrypt wrapper for ciphers, handles operations across
|
||||
* multiple page boundaries by using temporary blocks. In user context,
|
||||
* the kernel is given a chance to schedule us once per page.
|
||||
*/
|
||||
static int crypt(const struct cipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct scatter_walk walk_in, walk_out;
|
||||
struct crypto_tfm *tfm = desc->tfm;
|
||||
const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
|
||||
unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
unsigned long buffer = 0;
|
||||
|
||||
if (!nbytes)
|
||||
return 0;
|
||||
|
||||
if (nbytes % bsize) {
|
||||
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scatterwalk_start(&walk_in, src);
|
||||
scatterwalk_start(&walk_out, dst);
|
||||
|
||||
for(;;) {
|
||||
unsigned int n = nbytes;
|
||||
u8 *tmp = NULL;
|
||||
|
||||
if (!scatterwalk_aligned(&walk_in, alignmask) ||
|
||||
!scatterwalk_aligned(&walk_out, alignmask)) {
|
||||
if (!buffer) {
|
||||
buffer = __get_free_page(GFP_ATOMIC);
|
||||
if (!buffer)
|
||||
n = 0;
|
||||
}
|
||||
tmp = (u8 *)buffer;
|
||||
}
|
||||
|
||||
n = scatterwalk_clamp(&walk_in, n);
|
||||
n = scatterwalk_clamp(&walk_out, n);
|
||||
|
||||
if (likely(n >= bsize))
|
||||
n = crypt_fast(desc, &walk_in, &walk_out, n, tmp);
|
||||
else
|
||||
n = crypt_slow(desc, &walk_in, &walk_out, bsize);
|
||||
|
||||
nbytes -= n;
|
||||
|
||||
scatterwalk_done(&walk_in, 0, nbytes);
|
||||
scatterwalk_done(&walk_out, 1, nbytes);
|
||||
|
||||
if (!nbytes)
|
||||
break;
|
||||
|
||||
crypto_yield(tfm->crt_flags);
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
free_page(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypt_iv_unaligned(struct cipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct crypto_tfm *tfm = desc->tfm;
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
u8 *iv = desc->info;
|
||||
|
||||
if (unlikely(((unsigned long)iv & alignmask))) {
|
||||
unsigned int ivsize = tfm->crt_cipher.cit_ivsize;
|
||||
u8 buffer[ivsize + alignmask];
|
||||
u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||
int err;
|
||||
|
||||
desc->info = memcpy(tmp, iv, ivsize);
|
||||
err = crypt(desc, dst, src, nbytes);
|
||||
memcpy(iv, tmp, ivsize);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return crypt(desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
|
||||
u8 *dst, const u8 *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct crypto_tfm *tfm = desc->tfm;
|
||||
void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
|
||||
int bsize = crypto_tfm_alg_blocksize(tfm);
|
||||
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
|
||||
u8 *iv = desc->info;
|
||||
unsigned int done = 0;
|
||||
|
||||
nbytes -= bsize;
|
||||
|
||||
do {
|
||||
xor(iv, src);
|
||||
fn(tfm, dst, iv);
|
||||
memcpy(iv, dst, bsize);
|
||||
|
||||
src += bsize;
|
||||
dst += bsize;
|
||||
} while ((done += bsize) <= nbytes);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
|
||||
u8 *dst, const u8 *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct crypto_tfm *tfm = desc->tfm;
|
||||
void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
|
||||
int bsize = crypto_tfm_alg_blocksize(tfm);
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
|
||||
|
||||
u8 stack[src == dst ? bsize + alignmask : 0];
|
||||
u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
|
||||
u8 **dst_p = src == dst ? &buf : &dst;
|
||||
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
|
||||
u8 *iv = desc->info;
|
||||
unsigned int done = 0;
|
||||
|
||||
nbytes -= bsize;
|
||||
|
||||
do {
|
||||
u8 *tmp_dst = *dst_p;
|
||||
|
||||
fn(tfm, tmp_dst, src);
|
||||
xor(tmp_dst, iv);
|
||||
memcpy(iv, src, bsize);
|
||||
if (tmp_dst != dst)
|
||||
memcpy(dst, tmp_dst, bsize);
|
||||
|
||||
src += bsize;
|
||||
dst += bsize;
|
||||
} while ((done += bsize) <= nbytes);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
|
||||
const u8 *src, unsigned int nbytes)
|
||||
{
|
||||
struct crypto_tfm *tfm = desc->tfm;
|
||||
int bsize = crypto_tfm_alg_blocksize(tfm);
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
|
||||
unsigned int done = 0;
|
||||
|
||||
nbytes -= bsize;
|
||||
|
||||
do {
|
||||
fn(tfm, dst, src);
|
||||
|
||||
src += bsize;
|
||||
dst += bsize;
|
||||
} while ((done += bsize) <= nbytes);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
{
|
||||
@@ -293,122 +32,6 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
return cia->cia_setkey(tfm, key, keylen);
|
||||
}
|
||||
|
||||
static int ecb_encrypt(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct cipher_desc desc;
|
||||
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.crfn = cipher->cia_encrypt;
|
||||
desc.prfn = cipher->cia_encrypt_ecb ?: ecb_process;
|
||||
|
||||
return crypt(&desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static int ecb_decrypt(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct cipher_desc desc;
|
||||
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.crfn = cipher->cia_decrypt;
|
||||
desc.prfn = cipher->cia_decrypt_ecb ?: ecb_process;
|
||||
|
||||
return crypt(&desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static int cbc_encrypt(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct cipher_desc desc;
|
||||
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.crfn = cipher->cia_encrypt;
|
||||
desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
|
||||
desc.info = tfm->crt_cipher.cit_iv;
|
||||
|
||||
return crypt(&desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static int cbc_encrypt_iv(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes, u8 *iv)
|
||||
{
|
||||
struct cipher_desc desc;
|
||||
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.crfn = cipher->cia_encrypt;
|
||||
desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
|
||||
desc.info = iv;
|
||||
|
||||
return crypt_iv_unaligned(&desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static int cbc_decrypt(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct cipher_desc desc;
|
||||
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.crfn = cipher->cia_decrypt;
|
||||
desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
|
||||
desc.info = tfm->crt_cipher.cit_iv;
|
||||
|
||||
return crypt(&desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static int cbc_decrypt_iv(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes, u8 *iv)
|
||||
{
|
||||
struct cipher_desc desc;
|
||||
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.crfn = cipher->cia_decrypt;
|
||||
desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
|
||||
desc.info = iv;
|
||||
|
||||
return crypt_iv_unaligned(&desc, dst, src, nbytes);
|
||||
}
|
||||
|
||||
static int nocrypt(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int nocrypt_iv(struct crypto_tfm *tfm,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes, u8 *iv)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
|
||||
{
|
||||
u32 mode = flags & CRYPTO_TFM_MODE_MASK;
|
||||
tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
|
||||
const u8 *),
|
||||
struct crypto_tfm *tfm,
|
||||
@@ -454,7 +77,6 @@ static void cipher_decrypt_unaligned(struct crypto_tfm *tfm,
|
||||
|
||||
int crypto_init_cipher_ops(struct crypto_tfm *tfm)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cipher_tfm *ops = &tfm->crt_cipher;
|
||||
struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
|
||||
|
||||
@@ -464,70 +86,7 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
|
||||
ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
|
||||
cipher_decrypt_unaligned : cipher->cia_decrypt;
|
||||
|
||||
switch (tfm->crt_cipher.cit_mode) {
|
||||
case CRYPTO_TFM_MODE_ECB:
|
||||
ops->cit_encrypt = ecb_encrypt;
|
||||
ops->cit_decrypt = ecb_decrypt;
|
||||
ops->cit_encrypt_iv = nocrypt_iv;
|
||||
ops->cit_decrypt_iv = nocrypt_iv;
|
||||
break;
|
||||
|
||||
case CRYPTO_TFM_MODE_CBC:
|
||||
ops->cit_encrypt = cbc_encrypt;
|
||||
ops->cit_decrypt = cbc_decrypt;
|
||||
ops->cit_encrypt_iv = cbc_encrypt_iv;
|
||||
ops->cit_decrypt_iv = cbc_decrypt_iv;
|
||||
break;
|
||||
|
||||
case CRYPTO_TFM_MODE_CFB:
|
||||
ops->cit_encrypt = nocrypt;
|
||||
ops->cit_decrypt = nocrypt;
|
||||
ops->cit_encrypt_iv = nocrypt_iv;
|
||||
ops->cit_decrypt_iv = nocrypt_iv;
|
||||
break;
|
||||
|
||||
case CRYPTO_TFM_MODE_CTR:
|
||||
ops->cit_encrypt = nocrypt;
|
||||
ops->cit_decrypt = nocrypt;
|
||||
ops->cit_encrypt_iv = nocrypt_iv;
|
||||
ops->cit_decrypt_iv = nocrypt_iv;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
|
||||
unsigned long align;
|
||||
unsigned long addr;
|
||||
|
||||
switch (crypto_tfm_alg_blocksize(tfm)) {
|
||||
case 8:
|
||||
ops->cit_xor_block = xor_64;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ops->cit_xor_block = xor_128;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "%s: block size %u not supported\n",
|
||||
crypto_tfm_alg_name(tfm),
|
||||
crypto_tfm_alg_blocksize(tfm));
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
|
||||
align = crypto_tfm_alg_alignmask(tfm) + 1;
|
||||
addr = (unsigned long)crypto_tfm_ctx(tfm);
|
||||
addr = ALIGN(addr, align);
|
||||
addr += ALIGN(tfm->__crt_alg->cra_ctxsize, align);
|
||||
ops->cit_iv = (void *)addr;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
|
||||
|
||||
@@ -34,11 +34,6 @@ static int crypto_decompress(struct crypto_tfm *tfm,
|
||||
dlen);
|
||||
}
|
||||
|
||||
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
|
||||
{
|
||||
return flags ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
int crypto_init_compress_ops(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct compress_tfm *ops = &tfm->crt_compress;
|
||||
|
||||
+17
-9
@@ -14,7 +14,9 @@
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
@@ -29,8 +31,8 @@ static int init(struct hash_desc *desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update(struct hash_desc *desc,
|
||||
struct scatterlist *sg, unsigned int nbytes)
|
||||
static int update2(struct hash_desc *desc,
|
||||
struct scatterlist *sg, unsigned int nbytes)
|
||||
{
|
||||
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
|
||||
unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
@@ -81,6 +83,14 @@ static int update(struct hash_desc *desc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update(struct hash_desc *desc,
|
||||
struct scatterlist *sg, unsigned int nbytes)
|
||||
{
|
||||
if (WARN_ON_ONCE(in_irq()))
|
||||
return -EDEADLK;
|
||||
return update2(desc, sg, nbytes);
|
||||
}
|
||||
|
||||
static int final(struct hash_desc *desc, u8 *out)
|
||||
{
|
||||
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
|
||||
@@ -118,14 +128,12 @@ static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
|
||||
static int digest(struct hash_desc *desc,
|
||||
struct scatterlist *sg, unsigned int nbytes, u8 *out)
|
||||
{
|
||||
init(desc);
|
||||
update(desc, sg, nbytes);
|
||||
return final(desc, out);
|
||||
}
|
||||
if (WARN_ON_ONCE(in_irq()))
|
||||
return -EDEADLK;
|
||||
|
||||
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
|
||||
{
|
||||
return flags ? -EINVAL : 0;
|
||||
init(desc);
|
||||
update2(desc, sg, nbytes);
|
||||
return final(desc, out);
|
||||
}
|
||||
|
||||
int crypto_init_digest_ops(struct crypto_tfm *tfm)
|
||||
|
||||
+5
-4
@@ -99,12 +99,13 @@ static int crypto_ecb_init_tfm(struct crypto_tfm *tfm)
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct crypto_cipher *cipher;
|
||||
|
||||
tfm = crypto_spawn_tfm(spawn);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
cipher = crypto_spawn_cipher(spawn);
|
||||
if (IS_ERR(cipher))
|
||||
return PTR_ERR(cipher);
|
||||
|
||||
ctx->child = crypto_cipher_cast(tfm);
|
||||
ctx->child = cipher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+423
@@ -0,0 +1,423 @@
|
||||
/* FCrypt encryption algorithm
|
||||
*
|
||||
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Based on code:
|
||||
*
|
||||
* Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
|
||||
#define ROUNDS 16
|
||||
|
||||
struct fcrypt_ctx {
|
||||
u32 sched[ROUNDS];
|
||||
};
|
||||
|
||||
/* Rotate right two 32 bit numbers as a 56 bit number */
|
||||
#define ror56(hi, lo, n) \
|
||||
do { \
|
||||
u32 t = lo & ((1 << n) - 1); \
|
||||
lo = (lo >> n) | ((hi & ((1 << n) - 1)) << (32 - n)); \
|
||||
hi = (hi >> n) | (t << (24-n)); \
|
||||
} while(0)
|
||||
|
||||
/* Rotate right one 64 bit number as a 56 bit number */
|
||||
#define ror56_64(k, n) \
|
||||
do { \
|
||||
k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n)); \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Sboxes for Feistel network derived from
|
||||
* /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
|
||||
*/
|
||||
#undef Z
|
||||
#define Z(x) __constant_be32_to_cpu(x << 3)
|
||||
static const u32 sbox0[256] = {
|
||||
Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
|
||||
Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
|
||||
Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
|
||||
Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
|
||||
Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
|
||||
Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
|
||||
Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
|
||||
Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
|
||||
Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
|
||||
Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
|
||||
Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
|
||||
Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
|
||||
Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
|
||||
Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
|
||||
Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
|
||||
Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
|
||||
Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
|
||||
Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
|
||||
Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
|
||||
Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
|
||||
Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
|
||||
Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
|
||||
Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
|
||||
Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
|
||||
Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
|
||||
Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
|
||||
Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
|
||||
Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
|
||||
Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
|
||||
Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
|
||||
Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
|
||||
Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
|
||||
};
|
||||
|
||||
#undef Z
|
||||
#define Z(x) __constant_be32_to_cpu((x << 27) | (x >> 5))
|
||||
static const u32 sbox1[256] = {
|
||||
Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
|
||||
Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
|
||||
Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
|
||||
Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
|
||||
Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
|
||||
Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
|
||||
Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
|
||||
Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
|
||||
Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
|
||||
Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
|
||||
Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
|
||||
Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
|
||||
Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
|
||||
Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
|
||||
Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
|
||||
Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
|
||||
Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
|
||||
Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
|
||||
Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
|
||||
Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
|
||||
Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
|
||||
Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
|
||||
Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
|
||||
Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
|
||||
Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
|
||||
Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
|
||||
Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
|
||||
Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
|
||||
Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
|
||||
Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
|
||||
Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
|
||||
Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
|
||||
};
|
||||
|
||||
#undef Z
|
||||
#define Z(x) __constant_be32_to_cpu(x << 11)
|
||||
static const u32 sbox2[256] = {
|
||||
Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
|
||||
Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
|
||||
Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
|
||||
Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
|
||||
Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
|
||||
Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
|
||||
Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
|
||||
Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
|
||||
Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
|
||||
Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
|
||||
Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
|
||||
Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
|
||||
Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
|
||||
Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
|
||||
Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
|
||||
Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
|
||||
Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
|
||||
Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
|
||||
Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
|
||||
Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
|
||||
Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
|
||||
Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
|
||||
Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
|
||||
Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
|
||||
Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
|
||||
Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
|
||||
Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
|
||||
Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
|
||||
Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
|
||||
Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
|
||||
Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
|
||||
Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
|
||||
};
|
||||
|
||||
#undef Z
|
||||
#define Z(x) __constant_be32_to_cpu(x << 19)
|
||||
static const u32 sbox3[256] = {
|
||||
Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
|
||||
Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
|
||||
Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
|
||||
Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
|
||||
Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
|
||||
Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
|
||||
Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
|
||||
Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
|
||||
Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
|
||||
Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
|
||||
Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
|
||||
Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
|
||||
Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
|
||||
Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
|
||||
Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
|
||||
Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
|
||||
Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
|
||||
Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
|
||||
Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
|
||||
Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
|
||||
Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
|
||||
Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
|
||||
Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
|
||||
Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
|
||||
Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
|
||||
Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
|
||||
Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
|
||||
Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
|
||||
Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
|
||||
Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
|
||||
Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
|
||||
Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a 16 round Feistel network with permutation F_ENCRYPT
|
||||
*/
|
||||
#define F_ENCRYPT(R, L, sched) \
|
||||
do { \
|
||||
union lc4 { u32 l; u8 c[4]; } u; \
|
||||
u.l = sched ^ R; \
|
||||
L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* encryptor
|
||||
*/
|
||||
static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct {
|
||||
u32 l, r;
|
||||
} X;
|
||||
|
||||
memcpy(&X, src, sizeof(X));
|
||||
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
|
||||
|
||||
memcpy(dst, &X, sizeof(X));
|
||||
}
|
||||
|
||||
/*
|
||||
* decryptor
|
||||
*/
|
||||
static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct {
|
||||
u32 l, r;
|
||||
} X;
|
||||
|
||||
memcpy(&X, src, sizeof(X));
|
||||
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
|
||||
F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
|
||||
F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
|
||||
|
||||
memcpy(dst, &X, sizeof(X));
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a key schedule from key, the least significant bit in each key byte
|
||||
* is parity and shall be ignored. This leaves 56 significant bits in the key
|
||||
* to scatter over the 16 key schedules. For each schedule extract the low
|
||||
* order 32 bits and use as schedule, then rotate right by 11 bits.
|
||||
*/
|
||||
static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
#if BITS_PER_LONG == 64 /* the 64-bit version can also be used for 32-bit
|
||||
* kernels - it seems to be faster but the code is
|
||||
* larger */
|
||||
|
||||
u64 k; /* k holds all 56 non-parity bits */
|
||||
|
||||
/* discard the parity bits */
|
||||
k = (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key++) >> 1;
|
||||
k <<= 7;
|
||||
k |= (*key) >> 1;
|
||||
|
||||
/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
|
||||
ctx->sched[0x0] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x1] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x2] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x3] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x4] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x5] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x6] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x7] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x8] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0x9] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0xa] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0xb] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0xc] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0xd] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0xe] = be32_to_cpu(k); ror56_64(k, 11);
|
||||
ctx->sched[0xf] = be32_to_cpu(k);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
u32 hi, lo; /* hi is upper 24 bits and lo lower 32, total 56 */
|
||||
|
||||
/* discard the parity bits */
|
||||
lo = (*key++) >> 1;
|
||||
lo <<= 7;
|
||||
lo |= (*key++) >> 1;
|
||||
lo <<= 7;
|
||||
lo |= (*key++) >> 1;
|
||||
lo <<= 7;
|
||||
lo |= (*key++) >> 1;
|
||||
hi = lo >> 4;
|
||||
lo &= 0xf;
|
||||
lo <<= 7;
|
||||
lo |= (*key++) >> 1;
|
||||
lo <<= 7;
|
||||
lo |= (*key++) >> 1;
|
||||
lo <<= 7;
|
||||
lo |= (*key++) >> 1;
|
||||
lo <<= 7;
|
||||
lo |= (*key) >> 1;
|
||||
|
||||
/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
|
||||
ctx->sched[0x0] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x1] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x2] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x3] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x4] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x5] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x6] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x7] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x8] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0x9] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0xa] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0xb] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0xc] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0xd] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0xe] = be32_to_cpu(lo); ror56(hi, lo, 11);
|
||||
ctx->sched[0xf] = be32_to_cpu(lo);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct crypto_alg fcrypt_alg = {
|
||||
.cra_name = "fcrypt",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = 8,
|
||||
.cra_ctxsize = sizeof(struct fcrypt_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_alignmask = 3,
|
||||
.cra_list = LIST_HEAD_INIT(fcrypt_alg.cra_list),
|
||||
.cra_u = { .cipher = {
|
||||
.cia_min_keysize = 8,
|
||||
.cia_max_keysize = 8,
|
||||
.cia_setkey = fcrypt_setkey,
|
||||
.cia_encrypt = fcrypt_encrypt,
|
||||
.cia_decrypt = fcrypt_decrypt } }
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return crypto_register_alg(&fcrypt_alg);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&fcrypt_alg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
|
||||
MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
|
||||
+3
-2
@@ -16,12 +16,13 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg)
|
||||
static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type,
|
||||
u32 mask)
|
||||
{
|
||||
return alg->cra_ctxsize;
|
||||
}
|
||||
|
||||
static int crypto_init_hash_ops(struct crypto_tfm *tfm)
|
||||
static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
{
|
||||
struct hash_tfm *crt = &tfm->crt_hash;
|
||||
struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
|
||||
|
||||
+5
-4
@@ -172,15 +172,16 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
|
||||
|
||||
static int hmac_init_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_hash *hash;
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
|
||||
|
||||
tfm = crypto_spawn_tfm(spawn);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
hash = crypto_spawn_hash(spawn);
|
||||
if (IS_ERR(hash))
|
||||
return PTR_ERR(hash);
|
||||
|
||||
ctx->child = crypto_hash_cast(tfm);
|
||||
ctx->child = hash;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+6
-21
@@ -83,8 +83,7 @@ static inline void crypto_exit_proc(void)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
|
||||
int flags)
|
||||
static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg)
|
||||
{
|
||||
unsigned int len = alg->cra_ctxsize;
|
||||
|
||||
@@ -96,23 +95,12 @@ static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg,
|
||||
int flags)
|
||||
static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg)
|
||||
{
|
||||
unsigned int len = alg->cra_ctxsize;
|
||||
|
||||
switch (flags & CRYPTO_TFM_MODE_MASK) {
|
||||
case CRYPTO_TFM_MODE_CBC:
|
||||
len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
|
||||
len += alg->cra_blocksize;
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
return alg->cra_ctxsize;
|
||||
}
|
||||
|
||||
static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg,
|
||||
int flags)
|
||||
static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg)
|
||||
{
|
||||
return alg->cra_ctxsize;
|
||||
}
|
||||
@@ -121,10 +109,6 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
|
||||
struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask);
|
||||
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
|
||||
|
||||
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
|
||||
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
|
||||
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
|
||||
|
||||
int crypto_init_digest_ops(struct crypto_tfm *tfm);
|
||||
int crypto_init_cipher_ops(struct crypto_tfm *tfm);
|
||||
int crypto_init_compress_ops(struct crypto_tfm *tfm);
|
||||
@@ -136,7 +120,8 @@ void crypto_exit_compress_ops(struct crypto_tfm *tfm);
|
||||
void crypto_larval_error(const char *name, u32 type, u32 mask);
|
||||
|
||||
void crypto_shoot_alg(struct crypto_alg *alg);
|
||||
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags);
|
||||
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
|
||||
u32 mask);
|
||||
|
||||
int crypto_register_instance(struct crypto_template *tmpl,
|
||||
struct crypto_instance *inst);
|
||||
|
||||
+6
-5
@@ -201,21 +201,22 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
|
||||
static int init_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_cipher *cipher;
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct priv *ctx = crypto_tfm_ctx(tfm);
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
|
||||
tfm = crypto_spawn_tfm(spawn);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
cipher = crypto_spawn_cipher(spawn);
|
||||
if (IS_ERR(cipher))
|
||||
return PTR_ERR(cipher);
|
||||
|
||||
if (crypto_tfm_alg_blocksize(tfm) != 16) {
|
||||
if (crypto_cipher_blocksize(cipher) != 16) {
|
||||
*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx->child = crypto_cipher_cast(tfm);
|
||||
ctx->child = cipher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* PCBC: Propagating Cipher Block Chaining mode
|
||||
*
|
||||
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* Derived from cbc.c
|
||||
* - Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <crypto/algapi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct crypto_pcbc_ctx {
|
||||
struct crypto_cipher *child;
|
||||
void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
|
||||
};
|
||||
|
||||
static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(parent);
|
||||
struct crypto_cipher *child = ctx->child;
|
||||
int err;
|
||||
|
||||
crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_cipher_setkey(child, key, keylen);
|
||||
crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk,
|
||||
struct crypto_cipher *tfm,
|
||||
void (*xor)(u8 *, const u8 *,
|
||||
unsigned int))
|
||||
{
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
|
||||
crypto_cipher_alg(tfm)->cia_encrypt;
|
||||
int bsize = crypto_cipher_blocksize(tfm);
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u8 *src = walk->src.virt.addr;
|
||||
u8 *dst = walk->dst.virt.addr;
|
||||
u8 *iv = walk->iv;
|
||||
|
||||
do {
|
||||
xor(iv, src, bsize);
|
||||
fn(crypto_cipher_tfm(tfm), dst, iv);
|
||||
memcpy(iv, dst, bsize);
|
||||
xor(iv, src, bsize);
|
||||
|
||||
src += bsize;
|
||||
dst += bsize;
|
||||
} while ((nbytes -= bsize) >= bsize);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk,
|
||||
struct crypto_cipher *tfm,
|
||||
void (*xor)(u8 *, const u8 *,
|
||||
unsigned int))
|
||||
{
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
|
||||
crypto_cipher_alg(tfm)->cia_encrypt;
|
||||
int bsize = crypto_cipher_blocksize(tfm);
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u8 *src = walk->src.virt.addr;
|
||||
u8 *iv = walk->iv;
|
||||
u8 tmpbuf[bsize];
|
||||
|
||||
do {
|
||||
memcpy(tmpbuf, src, bsize);
|
||||
xor(iv, tmpbuf, bsize);
|
||||
fn(crypto_cipher_tfm(tfm), src, iv);
|
||||
memcpy(iv, src, bsize);
|
||||
xor(iv, tmpbuf, bsize);
|
||||
|
||||
src += bsize;
|
||||
} while ((nbytes -= bsize) >= bsize);
|
||||
|
||||
memcpy(walk->iv, iv, bsize);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct crypto_cipher *child = ctx->child;
|
||||
void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt(desc, &walk);
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
if (walk.src.virt.addr == walk.dst.virt.addr)
|
||||
nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
|
||||
xor);
|
||||
else
|
||||
nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
|
||||
xor);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk,
|
||||
struct crypto_cipher *tfm,
|
||||
void (*xor)(u8 *, const u8 *,
|
||||
unsigned int))
|
||||
{
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
|
||||
crypto_cipher_alg(tfm)->cia_decrypt;
|
||||
int bsize = crypto_cipher_blocksize(tfm);
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u8 *src = walk->src.virt.addr;
|
||||
u8 *dst = walk->dst.virt.addr;
|
||||
u8 *iv = walk->iv;
|
||||
|
||||
do {
|
||||
fn(crypto_cipher_tfm(tfm), dst, src);
|
||||
xor(dst, iv, bsize);
|
||||
memcpy(iv, src, bsize);
|
||||
xor(iv, dst, bsize);
|
||||
|
||||
src += bsize;
|
||||
dst += bsize;
|
||||
} while ((nbytes -= bsize) >= bsize);
|
||||
|
||||
memcpy(walk->iv, iv, bsize);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk,
|
||||
struct crypto_cipher *tfm,
|
||||
void (*xor)(u8 *, const u8 *,
|
||||
unsigned int))
|
||||
{
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
|
||||
crypto_cipher_alg(tfm)->cia_decrypt;
|
||||
int bsize = crypto_cipher_blocksize(tfm);
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u8 *src = walk->src.virt.addr;
|
||||
u8 *iv = walk->iv;
|
||||
u8 tmpbuf[bsize];
|
||||
|
||||
do {
|
||||
memcpy(tmpbuf, src, bsize);
|
||||
fn(crypto_cipher_tfm(tfm), src, src);
|
||||
xor(src, iv, bsize);
|
||||
memcpy(iv, tmpbuf, bsize);
|
||||
xor(iv, src, bsize);
|
||||
|
||||
src += bsize;
|
||||
} while ((nbytes -= bsize) >= bsize);
|
||||
|
||||
memcpy(walk->iv, iv, bsize);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct crypto_cipher *child = ctx->child;
|
||||
void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt(desc, &walk);
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
if (walk.src.virt.addr == walk.dst.virt.addr)
|
||||
nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
|
||||
xor);
|
||||
else
|
||||
nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
|
||||
xor);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
|
||||
{
|
||||
do {
|
||||
*a++ ^= *b++;
|
||||
} while (--bs);
|
||||
}
|
||||
|
||||
static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
|
||||
{
|
||||
u32 *a = (u32 *)dst;
|
||||
u32 *b = (u32 *)src;
|
||||
|
||||
do {
|
||||
*a++ ^= *b++;
|
||||
} while ((bs -= 4));
|
||||
}
|
||||
|
||||
static void xor_64(u8 *a, const u8 *b, unsigned int bs)
|
||||
{
|
||||
((u32 *)a)[0] ^= ((u32 *)b)[0];
|
||||
((u32 *)a)[1] ^= ((u32 *)b)[1];
|
||||
}
|
||||
|
||||
static void xor_128(u8 *a, const u8 *b, unsigned int bs)
|
||||
{
|
||||
((u32 *)a)[0] ^= ((u32 *)b)[0];
|
||||
((u32 *)a)[1] ^= ((u32 *)b)[1];
|
||||
((u32 *)a)[2] ^= ((u32 *)b)[2];
|
||||
((u32 *)a)[3] ^= ((u32 *)b)[3];
|
||||
}
|
||||
|
||||
static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct crypto_cipher *cipher;
|
||||
|
||||
switch (crypto_tfm_alg_blocksize(tfm)) {
|
||||
case 8:
|
||||
ctx->xor = xor_64;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ctx->xor = xor_128;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (crypto_tfm_alg_blocksize(tfm) % 4)
|
||||
ctx->xor = xor_byte;
|
||||
else
|
||||
ctx->xor = xor_quad;
|
||||
}
|
||||
|
||||
cipher = crypto_spawn_cipher(spawn);
|
||||
if (IS_ERR(cipher))
|
||||
return PTR_ERR(cipher);
|
||||
|
||||
ctx->child = cipher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
crypto_free_cipher(ctx->child);
|
||||
}
|
||||
|
||||
static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
|
||||
{
|
||||
struct crypto_instance *inst;
|
||||
struct crypto_alg *alg;
|
||||
|
||||
alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
|
||||
CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(alg))
|
||||
return ERR_PTR(PTR_ERR(alg));
|
||||
|
||||
inst = crypto_alloc_instance("pcbc", alg);
|
||||
if (IS_ERR(inst))
|
||||
goto out_put_alg;
|
||||
|
||||
inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
|
||||
inst->alg.cra_priority = alg->cra_priority;
|
||||
inst->alg.cra_blocksize = alg->cra_blocksize;
|
||||
inst->alg.cra_alignmask = alg->cra_alignmask;
|
||||
inst->alg.cra_type = &crypto_blkcipher_type;
|
||||
|
||||
if (!(alg->cra_blocksize % 4))
|
||||
inst->alg.cra_alignmask |= 3;
|
||||
inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
|
||||
inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
|
||||
inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
|
||||
|
||||
inst->alg.cra_ctxsize = sizeof(struct crypto_pcbc_ctx);
|
||||
|
||||
inst->alg.cra_init = crypto_pcbc_init_tfm;
|
||||
inst->alg.cra_exit = crypto_pcbc_exit_tfm;
|
||||
|
||||
inst->alg.cra_blkcipher.setkey = crypto_pcbc_setkey;
|
||||
inst->alg.cra_blkcipher.encrypt = crypto_pcbc_encrypt;
|
||||
inst->alg.cra_blkcipher.decrypt = crypto_pcbc_decrypt;
|
||||
|
||||
out_put_alg:
|
||||
crypto_mod_put(alg);
|
||||
return inst;
|
||||
}
|
||||
|
||||
static void crypto_pcbc_free(struct crypto_instance *inst)
|
||||
{
|
||||
crypto_drop_spawn(crypto_instance_ctx(inst));
|
||||
kfree(inst);
|
||||
}
|
||||
|
||||
static struct crypto_template crypto_pcbc_tmpl = {
|
||||
.name = "pcbc",
|
||||
.alloc = crypto_pcbc_alloc,
|
||||
.free = crypto_pcbc_free,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init crypto_pcbc_module_init(void)
|
||||
{
|
||||
return crypto_register_template(&crypto_pcbc_tmpl);
|
||||
}
|
||||
|
||||
static void __exit crypto_pcbc_module_exit(void)
|
||||
{
|
||||
crypto_unregister_template(&crypto_pcbc_tmpl);
|
||||
}
|
||||
|
||||
module_init(crypto_pcbc_module_init);
|
||||
module_exit(crypto_pcbc_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("PCBC block cipher algorithm");
|
||||
+71
-2
@@ -12,6 +12,7 @@
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
|
||||
* 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
|
||||
* 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
|
||||
*
|
||||
@@ -71,7 +72,8 @@ static char *check[] = {
|
||||
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
|
||||
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
|
||||
"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
|
||||
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL
|
||||
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
|
||||
"camellia", NULL
|
||||
};
|
||||
|
||||
static void hexdump(unsigned char *buf, unsigned int len)
|
||||
@@ -765,7 +767,7 @@ static void test_deflate(void)
|
||||
memcpy(tvmem, deflate_comp_tv_template, tsize);
|
||||
tv = (void *)tvmem;
|
||||
|
||||
tfm = crypto_alloc_tfm("deflate", 0);
|
||||
tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
|
||||
if (tfm == NULL) {
|
||||
printk("failed to load transform for deflate\n");
|
||||
return;
|
||||
@@ -964,6 +966,26 @@ static void do_test(void)
|
||||
test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template,
|
||||
XETA_DEC_TEST_VECTORS);
|
||||
|
||||
//FCrypt
|
||||
test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
|
||||
FCRYPT_ENC_TEST_VECTORS);
|
||||
test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
|
||||
FCRYPT_DEC_TEST_VECTORS);
|
||||
|
||||
//CAMELLIA
|
||||
test_cipher("ecb(camellia)", ENCRYPT,
|
||||
camellia_enc_tv_template,
|
||||
CAMELLIA_ENC_TEST_VECTORS);
|
||||
test_cipher("ecb(camellia)", DECRYPT,
|
||||
camellia_dec_tv_template,
|
||||
CAMELLIA_DEC_TEST_VECTORS);
|
||||
test_cipher("cbc(camellia)", ENCRYPT,
|
||||
camellia_cbc_enc_tv_template,
|
||||
CAMELLIA_CBC_ENC_TEST_VECTORS);
|
||||
test_cipher("cbc(camellia)", DECRYPT,
|
||||
camellia_cbc_dec_tv_template,
|
||||
CAMELLIA_CBC_DEC_TEST_VECTORS);
|
||||
|
||||
test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
|
||||
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
|
||||
test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
|
||||
@@ -980,6 +1002,10 @@ static void do_test(void)
|
||||
HMAC_SHA1_TEST_VECTORS);
|
||||
test_hash("hmac(sha256)", hmac_sha256_tv_template,
|
||||
HMAC_SHA256_TEST_VECTORS);
|
||||
test_hash("hmac(sha384)", hmac_sha384_tv_template,
|
||||
HMAC_SHA384_TEST_VECTORS);
|
||||
test_hash("hmac(sha512)", hmac_sha512_tv_template,
|
||||
HMAC_SHA512_TEST_VECTORS);
|
||||
|
||||
test_hash("xcbc(aes)", aes_xcbc128_tv_template,
|
||||
XCBC_AES_TEST_VECTORS);
|
||||
@@ -1177,6 +1203,28 @@ static void do_test(void)
|
||||
XETA_DEC_TEST_VECTORS);
|
||||
break;
|
||||
|
||||
case 31:
|
||||
test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
|
||||
FCRYPT_ENC_TEST_VECTORS);
|
||||
test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
|
||||
FCRYPT_DEC_TEST_VECTORS);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
test_cipher("ecb(camellia)", ENCRYPT,
|
||||
camellia_enc_tv_template,
|
||||
CAMELLIA_ENC_TEST_VECTORS);
|
||||
test_cipher("ecb(camellia)", DECRYPT,
|
||||
camellia_dec_tv_template,
|
||||
CAMELLIA_DEC_TEST_VECTORS);
|
||||
test_cipher("cbc(camellia)", ENCRYPT,
|
||||
camellia_cbc_enc_tv_template,
|
||||
CAMELLIA_CBC_ENC_TEST_VECTORS);
|
||||
test_cipher("cbc(camellia)", DECRYPT,
|
||||
camellia_cbc_dec_tv_template,
|
||||
CAMELLIA_CBC_DEC_TEST_VECTORS);
|
||||
break;
|
||||
|
||||
case 100:
|
||||
test_hash("hmac(md5)", hmac_md5_tv_template,
|
||||
HMAC_MD5_TEST_VECTORS);
|
||||
@@ -1192,6 +1240,16 @@ static void do_test(void)
|
||||
HMAC_SHA256_TEST_VECTORS);
|
||||
break;
|
||||
|
||||
case 103:
|
||||
test_hash("hmac(sha384)", hmac_sha384_tv_template,
|
||||
HMAC_SHA384_TEST_VECTORS);
|
||||
break;
|
||||
|
||||
case 104:
|
||||
test_hash("hmac(sha512)", hmac_sha512_tv_template,
|
||||
HMAC_SHA512_TEST_VECTORS);
|
||||
break;
|
||||
|
||||
|
||||
case 200:
|
||||
test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
|
||||
@@ -1260,6 +1318,17 @@ static void do_test(void)
|
||||
des_speed_template);
|
||||
break;
|
||||
|
||||
case 205:
|
||||
test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
|
||||
camellia_speed_template);
|
||||
test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
|
||||
camellia_speed_template);
|
||||
test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
|
||||
camellia_speed_template);
|
||||
test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
|
||||
camellia_speed_template);
|
||||
break;
|
||||
|
||||
case 300:
|
||||
/* fall through */
|
||||
|
||||
|
||||
+537
-1
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user