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

* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (54 commits)
  crypto: gf128mul - remove leftover "(EXPERIMENTAL)" in Kconfig
  crypto: serpent-sse2 - remove unneeded LRW/XTS #ifdefs
  crypto: serpent-sse2 - select LRW and XTS
  crypto: twofish-x86_64-3way - remove unneeded LRW/XTS #ifdefs
  crypto: twofish-x86_64-3way - select LRW and XTS
  crypto: xts - remove dependency on EXPERIMENTAL
  crypto: lrw - remove dependency on EXPERIMENTAL
  crypto: picoxcell - fix boolean and / or confusion
  crypto: caam - remove DECO access initialization code
  crypto: caam - fix polarity of "propagate error" logic
  crypto: caam - more desc.h cleanups
  crypto: caam - desc.h - convert spaces to tabs
  crypto: talitos - convert talitos_error to struct device
  crypto: talitos - remove NO_IRQ references
  crypto: talitos - fix bad kfree
  crypto: convert drivers/crypto/* to use module_platform_driver()
  char: hw_random: convert drivers/char/hw_random/* to use module_platform_driver()
  crypto: serpent-sse2 - should select CRYPTO_CRYPTD
  crypto: serpent - rename serpent.c to serpent_generic.c
  crypto: serpent - cleanup checkpatch errors and warnings
  ...
This commit is contained in:
Linus Torvalds
2012-01-10 22:01:27 -08:00
44 changed files with 8606 additions and 1971 deletions

View File

@@ -105,7 +105,7 @@ config CRYPTO_USER
depends on NET
select CRYPTO_MANAGER
help
Userapace configuration for cryptographic instantiations such as
Userspace configuration for cryptographic instantiations such as
cbc(aes).
config CRYPTO_MANAGER_DISABLE_TESTS
@@ -117,7 +117,7 @@ config CRYPTO_MANAGER_DISABLE_TESTS
algorithm registration.
config CRYPTO_GF128MUL
tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
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
@@ -241,8 +241,7 @@ config CRYPTO_ECB
the input block by block.
config CRYPTO_LRW
tristate "LRW support (EXPERIMENTAL)"
depends on EXPERIMENTAL
tristate "LRW support"
select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
select CRYPTO_GF128MUL
@@ -262,8 +261,7 @@ config CRYPTO_PCBC
This block cipher algorithm is required for RxRPC.
config CRYPTO_XTS
tristate "XTS support (EXPERIMENTAL)"
depends on EXPERIMENTAL
tristate "XTS support"
select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
select CRYPTO_GF128MUL
@@ -764,6 +762,46 @@ config CRYPTO_SERPENT
See also:
<http://www.cl.cam.ac.uk/~rja14/serpent.html>
config CRYPTO_SERPENT_SSE2_X86_64
tristate "Serpent cipher algorithm (x86_64/SSE2)"
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
select CRYPTO_SERPENT
select CRYPTO_LRW
select CRYPTO_XTS
help
Serpent cipher algorithm, by Anderson, Biham & Knudsen.
Keys are allowed to be from 0 to 256 bits in length, in steps
of 8 bits.
This module provides Serpent cipher algorithm that processes eigth
blocks parallel using SSE2 instruction set.
See also:
<http://www.cl.cam.ac.uk/~rja14/serpent.html>
config CRYPTO_SERPENT_SSE2_586
tristate "Serpent cipher algorithm (i586/SSE2)"
depends on X86 && !64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
select CRYPTO_SERPENT
select CRYPTO_LRW
select CRYPTO_XTS
help
Serpent cipher algorithm, by Anderson, Biham & Knudsen.
Keys are allowed to be from 0 to 256 bits in length, in steps
of 8 bits.
This module provides Serpent cipher algorithm that processes four
blocks parallel using SSE2 instruction set.
See also:
<http://www.cl.cam.ac.uk/~rja14/serpent.html>
config CRYPTO_TEA
tristate "TEA, XTEA and XETA cipher algorithms"
select CRYPTO_ALGAPI
@@ -840,6 +878,8 @@ config CRYPTO_TWOFISH_X86_64_3WAY
select CRYPTO_ALGAPI
select CRYPTO_TWOFISH_COMMON
select CRYPTO_TWOFISH_X86_64
select CRYPTO_LRW
select CRYPTO_XTS
help
Twofish cipher algorithm (x86_64, 3-way parallel).

View File

@@ -65,7 +65,7 @@ obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o
obj-$(CONFIG_CRYPTO_AES) += aes_generic.o
obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia.o
obj-$(CONFIG_CRYPTO_CAST5) += cast5.o

View File

@@ -518,6 +518,35 @@ err:
}
EXPORT_SYMBOL_GPL(crypto_register_instance);
int crypto_unregister_instance(struct crypto_alg *alg)
{
int err;
struct crypto_instance *inst = (void *)alg;
struct crypto_template *tmpl = inst->tmpl;
LIST_HEAD(users);
if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
return -EINVAL;
BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
down_write(&crypto_alg_sem);
hlist_del_init(&inst->list);
err = crypto_remove_alg(alg, &users);
up_write(&crypto_alg_sem);
if (err)
return err;
tmpl->free(inst);
crypto_remove_final(&users);
return 0;
}
EXPORT_SYMBOL_GPL(crypto_unregister_instance);
int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
struct crypto_instance *inst, u32 mask)
{

View File

@@ -414,10 +414,18 @@ static int fips_cprng_get_random(struct crypto_rng *tfm, u8 *rdata,
static int fips_cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
{
u8 rdata[DEFAULT_BLK_SZ];
u8 *key = seed + DEFAULT_BLK_SZ;
int rc;
struct prng_context *prng = crypto_rng_ctx(tfm);
if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
return -EINVAL;
/* fips strictly requires seed != key */
if (!memcmp(seed, key, DEFAULT_PRNG_KSZ))
return -EINVAL;
rc = cprng_reset(tfm, seed, slen);
if (!rc)

View File

@@ -298,7 +298,7 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
if (atomic_read(&alg->cra_refcnt) != 1)
return -EBUSY;
return crypto_unregister_alg(alg);
return crypto_unregister_instance(alg);
}
static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,

View File

@@ -3,7 +3,7 @@
*
* Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
*
* Based om ecb.c
* Based on ecb.c
* Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,6 +16,7 @@
* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html
*
* The test vectors are included in the testing module tcrypt.[ch] */
#include <crypto/algapi.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -26,21 +27,11 @@
#include <crypto/b128ops.h>
#include <crypto/gf128mul.h>
#include <crypto/lrw.h>
struct priv {
struct crypto_cipher *child;
/* optimizes multiplying a random (non incrementing, as at the
* start of a new sector) value with key2, we could also have
* used 4k optimization tables or no optimization at all. In the
* latter case we would have to store key2 here */
struct gf128mul_64k *table;
/* stores:
* key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
* key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
* key2*{ 0,0,...1,1,1,1,1 }, etc
* needed for optimized multiplication of incrementing values
* with key2 */
be128 mulinc[128];
struct lrw_table_ctx table;
};
static inline void setbit128_bbe(void *b, int bit)
@@ -54,28 +45,16 @@ static inline void setbit128_bbe(void *b, int bit)
), b);
}
static int setkey(struct crypto_tfm *parent, const u8 *key,
unsigned int keylen)
int lrw_init_table(struct lrw_table_ctx *ctx, const u8 *tweak)
{
struct priv *ctx = crypto_tfm_ctx(parent);
struct crypto_cipher *child = ctx->child;
int err, i;
be128 tmp = { 0 };
int bsize = crypto_cipher_blocksize(child);
crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
CRYPTO_TFM_REQ_MASK);
if ((err = crypto_cipher_setkey(child, key, keylen - bsize)))
return err;
crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
CRYPTO_TFM_RES_MASK);
int i;
if (ctx->table)
gf128mul_free_64k(ctx->table);
/* initialize multiplication table for Key2 */
ctx->table = gf128mul_init_64k_bbe((be128 *)(key + keylen - bsize));
ctx->table = gf128mul_init_64k_bbe((be128 *)tweak);
if (!ctx->table)
return -ENOMEM;
@@ -88,6 +67,34 @@ static int setkey(struct crypto_tfm *parent, const u8 *key,
return 0;
}
EXPORT_SYMBOL_GPL(lrw_init_table);
void lrw_free_table(struct lrw_table_ctx *ctx)
{
if (ctx->table)
gf128mul_free_64k(ctx->table);
}
EXPORT_SYMBOL_GPL(lrw_free_table);
static int setkey(struct crypto_tfm *parent, const u8 *key,
unsigned int keylen)
{
struct priv *ctx = crypto_tfm_ctx(parent);
struct crypto_cipher *child = ctx->child;
int err, bsize = LRW_BLOCK_SIZE;
const u8 *tweak = key + keylen - bsize;
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 - bsize);
if (err)
return err;
crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
CRYPTO_TFM_RES_MASK);
return lrw_init_table(&ctx->table, tweak);
}
struct sinfo {
be128 t;
@@ -134,7 +141,7 @@ static int crypt(struct blkcipher_desc *d,
{
int err;
unsigned int avail;
const int bs = crypto_cipher_blocksize(ctx->child);
const int bs = LRW_BLOCK_SIZE;
struct sinfo s = {
.tfm = crypto_cipher_tfm(ctx->child),
.fn = fn
@@ -155,7 +162,7 @@ static int crypt(struct blkcipher_desc *d,
s.t = *iv;
/* T <- I*Key2 */
gf128mul_64k_bbe(&s.t, ctx->table);
gf128mul_64k_bbe(&s.t, ctx->table.table);
goto first;
@@ -163,7 +170,8 @@ static int crypt(struct blkcipher_desc *d,
do {
/* T <- I*Key2, using the optimization
* discussed in the specification */
be128_xor(&s.t, &s.t, &ctx->mulinc[get_index128(iv)]);
be128_xor(&s.t, &s.t,
&ctx->table.mulinc[get_index128(iv)]);
inc(iv);
first:
@@ -206,6 +214,85 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
crypto_cipher_alg(ctx->child)->cia_decrypt);
}
int lrw_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
struct scatterlist *ssrc, unsigned int nbytes,
struct lrw_crypt_req *req)
{
const unsigned int bsize = LRW_BLOCK_SIZE;
const unsigned int max_blks = req->tbuflen / bsize;
struct lrw_table_ctx *ctx = req->table_ctx;
struct blkcipher_walk walk;
unsigned int nblocks;
be128 *iv, *src, *dst, *t;
be128 *t_buf = req->tbuf;
int err, i;
BUG_ON(max_blks < 1);
blkcipher_walk_init(&walk, sdst, ssrc, nbytes);
err = blkcipher_walk_virt(desc, &walk);
nbytes = walk.nbytes;
if (!nbytes)
return err;
nblocks = min(walk.nbytes / bsize, max_blks);
src = (be128 *)walk.src.virt.addr;
dst = (be128 *)walk.dst.virt.addr;
/* calculate first value of T */
iv = (be128 *)walk.iv;
t_buf[0] = *iv;
/* T <- I*Key2 */
gf128mul_64k_bbe(&t_buf[0], ctx->table);
i = 0;
goto first;
for (;;) {
do {
for (i = 0; i < nblocks; i++) {
/* T <- I*Key2, using the optimization
* discussed in the specification */
be128_xor(&t_buf[i], t,
&ctx->mulinc[get_index128(iv)]);
inc(iv);
first:
t = &t_buf[i];
/* PP <- T xor P */
be128_xor(dst + i, t, src + i);
}
/* CC <- E(Key2,PP) */
req->crypt_fn(req->crypt_ctx, (u8 *)dst,
nblocks * bsize);
/* C <- T xor CC */
for (i = 0; i < nblocks; i++)
be128_xor(dst + i, dst + i, &t_buf[i]);
src += nblocks;
dst += nblocks;
nbytes -= nblocks * bsize;
nblocks = min(nbytes / bsize, max_blks);
} while (nblocks > 0);
err = blkcipher_walk_done(desc, &walk, nbytes);
nbytes = walk.nbytes;
if (!nbytes)
break;
nblocks = min(nbytes / bsize, max_blks);
src = (be128 *)walk.src.virt.addr;
dst = (be128 *)walk.dst.virt.addr;
}
return err;
}
EXPORT_SYMBOL_GPL(lrw_crypt);
static int init_tfm(struct crypto_tfm *tfm)
{
struct crypto_cipher *cipher;
@@ -218,8 +305,9 @@ static int init_tfm(struct crypto_tfm *tfm)
if (IS_ERR(cipher))
return PTR_ERR(cipher);
if (crypto_cipher_blocksize(cipher) != 16) {
if (crypto_cipher_blocksize(cipher) != LRW_BLOCK_SIZE) {
*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
crypto_free_cipher(cipher);
return -EINVAL;
}
@@ -230,8 +318,8 @@ static int init_tfm(struct crypto_tfm *tfm)
static void exit_tfm(struct crypto_tfm *tfm)
{
struct priv *ctx = crypto_tfm_ctx(tfm);
if (ctx->table)
gf128mul_free_64k(ctx->table);
lrw_free_table(&ctx->table);
crypto_free_cipher(ctx->child);
}

View File

@@ -1,587 +0,0 @@
/*
* Cryptographic API.
*
* Serpent Cipher Algorithm.
*
* Copyright (C) 2002 Dag Arne Osvik <osvik@ii.uib.no>
* 2003 Herbert Valerio Riedel <hvr@gnu.org>
*
* Added tnepres support: Ruben Jesus Garcia Hernandez <ruben@ugr.es>, 18.10.2004
* Based on code by hvr
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <asm/byteorder.h>
#include <linux/crypto.h>
#include <linux/types.h>
/* Key is padded to the maximum of 256 bits before round key generation.
* Any key length <= 256 bits (32 bytes) is allowed by the algorithm.
*/
#define SERPENT_MIN_KEY_SIZE 0
#define SERPENT_MAX_KEY_SIZE 32
#define SERPENT_EXPKEY_WORDS 132
#define SERPENT_BLOCK_SIZE 16
#define PHI 0x9e3779b9UL
#define keyiter(a,b,c,d,i,j) \
b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; b = rol32(b,11); k[j] = b;
#define loadkeys(x0,x1,x2,x3,i) \
x0=k[i]; x1=k[i+1]; x2=k[i+2]; x3=k[i+3];
#define storekeys(x0,x1,x2,x3,i) \
k[i]=x0; k[i+1]=x1; k[i+2]=x2; k[i+3]=x3;
#define K(x0,x1,x2,x3,i) \
x3 ^= k[4*(i)+3]; x2 ^= k[4*(i)+2]; \
x1 ^= k[4*(i)+1]; x0 ^= k[4*(i)+0];
#define LK(x0,x1,x2,x3,x4,i) \
x0=rol32(x0,13);\
x2=rol32(x2,3); x1 ^= x0; x4 = x0 << 3; \
x3 ^= x2; x1 ^= x2; \
x1=rol32(x1,1); x3 ^= x4; \
x3=rol32(x3,7); x4 = x1; \
x0 ^= x1; x4 <<= 7; x2 ^= x3; \
x0 ^= x3; x2 ^= x4; x3 ^= k[4*i+3]; \
x1 ^= k[4*i+1]; x0=rol32(x0,5); x2=rol32(x2,22);\
x0 ^= k[4*i+0]; x2 ^= k[4*i+2];
#define KL(x0,x1,x2,x3,x4,i) \
x0 ^= k[4*i+0]; x1 ^= k[4*i+1]; x2 ^= k[4*i+2]; \
x3 ^= k[4*i+3]; x0=ror32(x0,5); x2=ror32(x2,22);\
x4 = x1; x2 ^= x3; x0 ^= x3; \
x4 <<= 7; x0 ^= x1; x1=ror32(x1,1); \
x2 ^= x4; x3=ror32(x3,7); x4 = x0 << 3; \
x1 ^= x0; x3 ^= x4; x0=ror32(x0,13);\
x1 ^= x2; x3 ^= x2; x2=ror32(x2,3);
#define S0(x0,x1,x2,x3,x4) \
x4 = x3; \
x3 |= x0; x0 ^= x4; x4 ^= x2; \
x4 =~ x4; x3 ^= x1; x1 &= x0; \
x1 ^= x4; x2 ^= x0; x0 ^= x3; \
x4 |= x0; x0 ^= x2; x2 &= x1; \
x3 ^= x2; x1 =~ x1; x2 ^= x4; \
x1 ^= x2;
#define S1(x0,x1,x2,x3,x4) \
x4 = x1; \
x1 ^= x0; x0 ^= x3; x3 =~ x3; \
x4 &= x1; x0 |= x1; x3 ^= x2; \
x0 ^= x3; x1 ^= x3; x3 ^= x4; \
x1 |= x4; x4 ^= x2; x2 &= x0; \
x2 ^= x1; x1 |= x0; x0 =~ x0; \
x0 ^= x2; x4 ^= x1;
#define S2(x0,x1,x2,x3,x4) \
x3 =~ x3; \
x1 ^= x0; x4 = x0; x0 &= x2; \
x0 ^= x3; x3 |= x4; x2 ^= x1; \
x3 ^= x1; x1 &= x0; x0 ^= x2; \
x2 &= x3; x3 |= x1; x0 =~ x0; \
x3 ^= x0; x4 ^= x0; x0 ^= x2; \
x1 |= x2;
#define S3(x0,x1,x2,x3,x4) \
x4 = x1; \
x1 ^= x3; x3 |= x0; x4 &= x0; \
x0 ^= x2; x2 ^= x1; x1 &= x3; \
x2 ^= x3; x0 |= x4; x4 ^= x3; \
x1 ^= x0; x0 &= x3; x3 &= x4; \
x3 ^= x2; x4 |= x1; x2 &= x1; \
x4 ^= x3; x0 ^= x3; x3 ^= x2;
#define S4(x0,x1,x2,x3,x4) \
x4 = x3; \
x3 &= x0; x0 ^= x4; \
x3 ^= x2; x2 |= x4; x0 ^= x1; \
x4 ^= x3; x2 |= x0; \
x2 ^= x1; x1 &= x0; \
x1 ^= x4; x4 &= x2; x2 ^= x3; \
x4 ^= x0; x3 |= x1; x1 =~ x1; \
x3 ^= x0;
#define S5(x0,x1,x2,x3,x4) \
x4 = x1; x1 |= x0; \
x2 ^= x1; x3 =~ x3; x4 ^= x0; \
x0 ^= x2; x1 &= x4; x4 |= x3; \
x4 ^= x0; x0 &= x3; x1 ^= x3; \
x3 ^= x2; x0 ^= x1; x2 &= x4; \
x1 ^= x2; x2 &= x0; \
x3 ^= x2;
#define S6(x0,x1,x2,x3,x4) \
x4 = x1; \
x3 ^= x0; x1 ^= x2; x2 ^= x0; \
x0 &= x3; x1 |= x3; x4 =~ x4; \
x0 ^= x1; x1 ^= x2; \
x3 ^= x4; x4 ^= x0; x2 &= x0; \
x4 ^= x1; x2 ^= x3; x3 &= x1; \
x3 ^= x0; x1 ^= x2;
#define S7(x0,x1,x2,x3,x4) \
x1 =~ x1; \
x4 = x1; x0 =~ x0; x1 &= x2; \
x1 ^= x3; x3 |= x4; x4 ^= x2; \
x2 ^= x3; x3 ^= x0; x0 |= x1; \
x2 &= x0; x0 ^= x4; x4 ^= x3; \
x3 &= x0; x4 ^= x1; \
x2 ^= x4; x3 ^= x1; x4 |= x0; \
x4 ^= x1;
#define SI0(x0,x1,x2,x3,x4) \
x4 = x3; x1 ^= x0; \
x3 |= x1; x4 ^= x1; x0 =~ x0; \
x2 ^= x3; x3 ^= x0; x0 &= x1; \
x0 ^= x2; x2 &= x3; x3 ^= x4; \
x2 ^= x3; x1 ^= x3; x3 &= x0; \
x1 ^= x0; x0 ^= x2; x4 ^= x3;
#define SI1(x0,x1,x2,x3,x4) \
x1 ^= x3; x4 = x0; \
x0 ^= x2; x2 =~ x2; x4 |= x1; \
x4 ^= x3; x3 &= x1; x1 ^= x2; \
x2 &= x4; x4 ^= x1; x1 |= x3; \
x3 ^= x0; x2 ^= x0; x0 |= x4; \
x2 ^= x4; x1 ^= x0; \
x4 ^= x1;
#define SI2(x0,x1,x2,x3,x4) \
x2 ^= x1; x4 = x3; x3 =~ x3; \
x3 |= x2; x2 ^= x4; x4 ^= x0; \
x3 ^= x1; x1 |= x2; x2 ^= x0; \
x1 ^= x4; x4 |= x3; x2 ^= x3; \
x4 ^= x2; x2 &= x1; \
x2 ^= x3; x3 ^= x4; x4 ^= x0;
#define SI3(x0,x1,x2,x3,x4) \
x2 ^= x1; \
x4 = x1; x1 &= x2; \
x1 ^= x0; x0 |= x4; x4 ^= x3; \
x0 ^= x3; x3 |= x1; x1 ^= x2; \
x1 ^= x3; x0 ^= x2; x2 ^= x3; \
x3 &= x1; x1 ^= x0; x0 &= x2; \
x4 ^= x3; x3 ^= x0; x0 ^= x1;
#define SI4(x0,x1,x2,x3,x4) \
x2 ^= x3; x4 = x0; x0 &= x1; \
x0 ^= x2; x2 |= x3; x4 =~ x4; \
x1 ^= x0; x0 ^= x2; x2 &= x4; \
x2 ^= x0; x0 |= x4; \
x0 ^= x3; x3 &= x2; \
x4 ^= x3; x3 ^= x1; x1 &= x0; \
x4 ^= x1; x0 ^= x3;
#define SI5(x0,x1,x2,x3,x4) \
x4 = x1; x1 |= x2; \
x2 ^= x4; x1 ^= x3; x3 &= x4; \
x2 ^= x3; x3 |= x0; x0 =~ x0; \
x3 ^= x2; x2 |= x0; x4 ^= x1; \
x2 ^= x4; x4 &= x0; x0 ^= x1; \
x1 ^= x3; x0 &= x2; x2 ^= x3; \
x0 ^= x2; x2 ^= x4; x4 ^= x3;
#define SI6(x0,x1,x2,x3,x4) \
x0 ^= x2; \
x4 = x0; x0 &= x3; x2 ^= x3; \
x0 ^= x2; x3 ^= x1; x2 |= x4; \
x2 ^= x3; x3 &= x0; x0 =~ x0; \
x3 ^= x1; x1 &= x2; x4 ^= x0; \
x3 ^= x4; x4 ^= x2; x0 ^= x1; \
x2 ^= x0;
#define SI7(x0,x1,x2,x3,x4) \
x4 = x3; x3 &= x0; x0 ^= x2; \
x2 |= x4; x4 ^= x1; x0 =~ x0; \
x1 |= x3; x4 ^= x0; x0 &= x2; \
x0 ^= x1; x1 &= x2; x3 ^= x2; \
x4 ^= x3; x2 &= x3; x3 |= x0; \
x1 ^= x4; x3 ^= x4; x4 &= x0; \
x4 ^= x2;
struct serpent_ctx {
u32 expkey[SERPENT_EXPKEY_WORDS];
};
static int serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
unsigned int keylen)
{
struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
u32 *k = ctx->expkey;
u8 *k8 = (u8 *)k;
u32 r0,r1,r2,r3,r4;
int i;
/* Copy key, add padding */
for (i = 0; i < keylen; ++i)
k8[i] = key[i];
if (i < SERPENT_MAX_KEY_SIZE)
k8[i++] = 1;
while (i < SERPENT_MAX_KEY_SIZE)
k8[i++] = 0;
/* Expand key using polynomial */
r0 = le32_to_cpu(k[3]);
r1 = le32_to_cpu(k[4]);
r2 = le32_to_cpu(k[5]);
r3 = le32_to_cpu(k[6]);
r4 = le32_to_cpu(k[7]);
keyiter(le32_to_cpu(k[0]),r0,r4,r2,0,0);
keyiter(le32_to_cpu(k[1]),r1,r0,r3,1,1);
keyiter(le32_to_cpu(k[2]),r2,r1,r4,2,2);
keyiter(le32_to_cpu(k[3]),r3,r2,r0,3,3);
keyiter(le32_to_cpu(k[4]),r4,r3,r1,4,4);
keyiter(le32_to_cpu(k[5]),r0,r4,r2,5,5);
keyiter(le32_to_cpu(k[6]),r1,r0,r3,6,6);
keyiter(le32_to_cpu(k[7]),r2,r1,r4,7,7);
keyiter(k[ 0],r3,r2,r0, 8, 8); keyiter(k[ 1],r4,r3,r1, 9, 9);
keyiter(k[ 2],r0,r4,r2, 10, 10); keyiter(k[ 3],r1,r0,r3, 11, 11);
keyiter(k[ 4],r2,r1,r4, 12, 12); keyiter(k[ 5],r3,r2,r0, 13, 13);
keyiter(k[ 6],r4,r3,r1, 14, 14); keyiter(k[ 7],r0,r4,r2, 15, 15);
keyiter(k[ 8],r1,r0,r3, 16, 16); keyiter(k[ 9],r2,r1,r4, 17, 17);
keyiter(k[ 10],r3,r2,r0, 18, 18); keyiter(k[ 11],r4,r3,r1, 19, 19);
keyiter(k[ 12],r0,r4,r2, 20, 20); keyiter(k[ 13],r1,r0,r3, 21, 21);
keyiter(k[ 14],r2,r1,r4, 22, 22); keyiter(k[ 15],r3,r2,r0, 23, 23);
keyiter(k[ 16],r4,r3,r1, 24, 24); keyiter(k[ 17],r0,r4,r2, 25, 25);
keyiter(k[ 18],r1,r0,r3, 26, 26); keyiter(k[ 19],r2,r1,r4, 27, 27);
keyiter(k[ 20],r3,r2,r0, 28, 28); keyiter(k[ 21],r4,r3,r1, 29, 29);
keyiter(k[ 22],r0,r4,r2, 30, 30); keyiter(k[ 23],r1,r0,r3, 31, 31);
k += 50;
keyiter(k[-26],r2,r1,r4, 32,-18); keyiter(k[-25],r3,r2,r0, 33,-17);
keyiter(k[-24],r4,r3,r1, 34,-16); keyiter(k[-23],r0,r4,r2, 35,-15);
keyiter(k[-22],r1,r0,r3, 36,-14); keyiter(k[-21],r2,r1,r4, 37,-13);
keyiter(k[-20],r3,r2,r0, 38,-12); keyiter(k[-19],r4,r3,r1, 39,-11);
keyiter(k[-18],r0,r4,r2, 40,-10); keyiter(k[-17],r1,r0,r3, 41, -9);
keyiter(k[-16],r2,r1,r4, 42, -8); keyiter(k[-15],r3,r2,r0, 43, -7);
keyiter(k[-14],r4,r3,r1, 44, -6); keyiter(k[-13],r0,r4,r2, 45, -5);
keyiter(k[-12],r1,r0,r3, 46, -4); keyiter(k[-11],r2,r1,r4, 47, -3);
keyiter(k[-10],r3,r2,r0, 48, -2); keyiter(k[ -9],r4,r3,r1, 49, -1);
keyiter(k[ -8],r0,r4,r2, 50, 0); keyiter(k[ -7],r1,r0,r3, 51, 1);
keyiter(k[ -6],r2,r1,r4, 52, 2); keyiter(k[ -5],r3,r2,r0, 53, 3);
keyiter(k[ -4],r4,r3,r1, 54, 4); keyiter(k[ -3],r0,r4,r2, 55, 5);
keyiter(k[ -2],r1,r0,r3, 56, 6); keyiter(k[ -1],r2,r1,r4, 57, 7);
keyiter(k[ 0],r3,r2,r0, 58, 8); keyiter(k[ 1],r4,r3,r1, 59, 9);
keyiter(k[ 2],r0,r4,r2, 60, 10); keyiter(k[ 3],r1,r0,r3, 61, 11);
keyiter(k[ 4],r2,r1,r4, 62, 12); keyiter(k[ 5],r3,r2,r0, 63, 13);
keyiter(k[ 6],r4,r3,r1, 64, 14); keyiter(k[ 7],r0,r4,r2, 65, 15);
keyiter(k[ 8],r1,r0,r3, 66, 16); keyiter(k[ 9],r2,r1,r4, 67, 17);
keyiter(k[ 10],r3,r2,r0, 68, 18); keyiter(k[ 11],r4,r3,r1, 69, 19);
keyiter(k[ 12],r0,r4,r2, 70, 20); keyiter(k[ 13],r1,r0,r3, 71, 21);
keyiter(k[ 14],r2,r1,r4, 72, 22); keyiter(k[ 15],r3,r2,r0, 73, 23);
keyiter(k[ 16],r4,r3,r1, 74, 24); keyiter(k[ 17],r0,r4,r2, 75, 25);
keyiter(k[ 18],r1,r0,r3, 76, 26); keyiter(k[ 19],r2,r1,r4, 77, 27);
keyiter(k[ 20],r3,r2,r0, 78, 28); keyiter(k[ 21],r4,r3,r1, 79, 29);
keyiter(k[ 22],r0,r4,r2, 80, 30); keyiter(k[ 23],r1,r0,r3, 81, 31);
k += 50;
keyiter(k[-26],r2,r1,r4, 82,-18); keyiter(k[-25],r3,r2,r0, 83,-17);
keyiter(k[-24],r4,r3,r1, 84,-16); keyiter(k[-23],r0,r4,r2, 85,-15);
keyiter(k[-22],r1,r0,r3, 86,-14); keyiter(k[-21],r2,r1,r4, 87,-13);
keyiter(k[-20],r3,r2,r0, 88,-12); keyiter(k[-19],r4,r3,r1, 89,-11);
keyiter(k[-18],r0,r4,r2, 90,-10); keyiter(k[-17],r1,r0,r3, 91, -9);
keyiter(k[-16],r2,r1,r4, 92, -8); keyiter(k[-15],r3,r2,r0, 93, -7);
keyiter(k[-14],r4,r3,r1, 94, -6); keyiter(k[-13],r0,r4,r2, 95, -5);
keyiter(k[-12],r1,r0,r3, 96, -4); keyiter(k[-11],r2,r1,r4, 97, -3);
keyiter(k[-10],r3,r2,r0, 98, -2); keyiter(k[ -9],r4,r3,r1, 99, -1);
keyiter(k[ -8],r0,r4,r2,100, 0); keyiter(k[ -7],r1,r0,r3,101, 1);
keyiter(k[ -6],r2,r1,r4,102, 2); keyiter(k[ -5],r3,r2,r0,103, 3);
keyiter(k[ -4],r4,r3,r1,104, 4); keyiter(k[ -3],r0,r4,r2,105, 5);
keyiter(k[ -2],r1,r0,r3,106, 6); keyiter(k[ -1],r2,r1,r4,107, 7);
keyiter(k[ 0],r3,r2,r0,108, 8); keyiter(k[ 1],r4,r3,r1,109, 9);
keyiter(k[ 2],r0,r4,r2,110, 10); keyiter(k[ 3],r1,r0,r3,111, 11);
keyiter(k[ 4],r2,r1,r4,112, 12); keyiter(k[ 5],r3,r2,r0,113, 13);
keyiter(k[ 6],r4,r3,r1,114, 14); keyiter(k[ 7],r0,r4,r2,115, 15);
keyiter(k[ 8],r1,r0,r3,116, 16); keyiter(k[ 9],r2,r1,r4,117, 17);
keyiter(k[ 10],r3,r2,r0,118, 18); keyiter(k[ 11],r4,r3,r1,119, 19);
keyiter(k[ 12],r0,r4,r2,120, 20); keyiter(k[ 13],r1,r0,r3,121, 21);
keyiter(k[ 14],r2,r1,r4,122, 22); keyiter(k[ 15],r3,r2,r0,123, 23);
keyiter(k[ 16],r4,r3,r1,124, 24); keyiter(k[ 17],r0,r4,r2,125, 25);
keyiter(k[ 18],r1,r0,r3,126, 26); keyiter(k[ 19],r2,r1,r4,127, 27);
keyiter(k[ 20],r3,r2,r0,128, 28); keyiter(k[ 21],r4,r3,r1,129, 29);
keyiter(k[ 22],r0,r4,r2,130, 30); keyiter(k[ 23],r1,r0,r3,131, 31);
/* Apply S-boxes */
S3(r3,r4,r0,r1,r2); storekeys(r1,r2,r4,r3, 28); loadkeys(r1,r2,r4,r3, 24);
S4(r1,r2,r4,r3,r0); storekeys(r2,r4,r3,r0, 24); loadkeys(r2,r4,r3,r0, 20);
S5(r2,r4,r3,r0,r1); storekeys(r1,r2,r4,r0, 20); loadkeys(r1,r2,r4,r0, 16);
S6(r1,r2,r4,r0,r3); storekeys(r4,r3,r2,r0, 16); loadkeys(r4,r3,r2,r0, 12);
S7(r4,r3,r2,r0,r1); storekeys(r1,r2,r0,r4, 12); loadkeys(r1,r2,r0,r4, 8);
S0(r1,r2,r0,r4,r3); storekeys(r0,r2,r4,r1, 8); loadkeys(r0,r2,r4,r1, 4);
S1(r0,r2,r4,r1,r3); storekeys(r3,r4,r1,r0, 4); loadkeys(r3,r4,r1,r0, 0);
S2(r3,r4,r1,r0,r2); storekeys(r2,r4,r3,r0, 0); loadkeys(r2,r4,r3,r0, -4);
S3(r2,r4,r3,r0,r1); storekeys(r0,r1,r4,r2, -4); loadkeys(r0,r1,r4,r2, -8);
S4(r0,r1,r4,r2,r3); storekeys(r1,r4,r2,r3, -8); loadkeys(r1,r4,r2,r3,-12);
S5(r1,r4,r2,r3,r0); storekeys(r0,r1,r4,r3,-12); loadkeys(r0,r1,r4,r3,-16);
S6(r0,r1,r4,r3,r2); storekeys(r4,r2,r1,r3,-16); loadkeys(r4,r2,r1,r3,-20);
S7(r4,r2,r1,r3,r0); storekeys(r0,r1,r3,r4,-20); loadkeys(r0,r1,r3,r4,-24);
S0(r0,r1,r3,r4,r2); storekeys(r3,r1,r4,r0,-24); loadkeys(r3,r1,r4,r0,-28);
k -= 50;
S1(r3,r1,r4,r0,r2); storekeys(r2,r4,r0,r3, 22); loadkeys(r2,r4,r0,r3, 18);
S2(r2,r4,r0,r3,r1); storekeys(r1,r4,r2,r3, 18); loadkeys(r1,r4,r2,r3, 14);
S3(r1,r4,r2,r3,r0); storekeys(r3,r0,r4,r1, 14); loadkeys(r3,r0,r4,r1, 10);
S4(r3,r0,r4,r1,r2); storekeys(r0,r4,r1,r2, 10); loadkeys(r0,r4,r1,r2, 6);
S5(r0,r4,r1,r2,r3); storekeys(r3,r0,r4,r2, 6); loadkeys(r3,r0,r4,r2, 2);
S6(r3,r0,r4,r2,r1); storekeys(r4,r1,r0,r2, 2); loadkeys(r4,r1,r0,r2, -2);
S7(r4,r1,r0,r2,r3); storekeys(r3,r0,r2,r4, -2); loadkeys(r3,r0,r2,r4, -6);
S0(r3,r0,r2,r4,r1); storekeys(r2,r0,r4,r3, -6); loadkeys(r2,r0,r4,r3,-10);
S1(r2,r0,r4,r3,r1); storekeys(r1,r4,r3,r2,-10); loadkeys(r1,r4,r3,r2,-14);
S2(r1,r4,r3,r2,r0); storekeys(r0,r4,r1,r2,-14); loadkeys(r0,r4,r1,r2,-18);
S3(r0,r4,r1,r2,r3); storekeys(r2,r3,r4,r0,-18); loadkeys(r2,r3,r4,r0,-22);
k -= 50;
S4(r2,r3,r4,r0,r1); storekeys(r3,r4,r0,r1, 28); loadkeys(r3,r4,r0,r1, 24);
S5(r3,r4,r0,r1,r2); storekeys(r2,r3,r4,r1, 24); loadkeys(r2,r3,r4,r1, 20);
S6(r2,r3,r4,r1,r0); storekeys(r4,r0,r3,r1, 20); loadkeys(r4,r0,r3,r1, 16);
S7(r4,r0,r3,r1,r2); storekeys(r2,r3,r1,r4, 16); loadkeys(r2,r3,r1,r4, 12);
S0(r2,r3,r1,r4,r0); storekeys(r1,r3,r4,r2, 12); loadkeys(r1,r3,r4,r2, 8);
S1(r1,r3,r4,r2,r0); storekeys(r0,r4,r2,r1, 8); loadkeys(r0,r4,r2,r1, 4);
S2(r0,r4,r2,r1,r3); storekeys(r3,r4,r0,r1, 4); loadkeys(r3,r4,r0,r1, 0);
S3(r3,r4,r0,r1,r2); storekeys(r1,r2,r4,r3, 0);
return 0;
}
static void serpent_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
const u32
*k = ctx->expkey;
const __le32 *s = (const __le32 *)src;
__le32 *d = (__le32 *)dst;
u32 r0, r1, r2, r3, r4;
/*
* Note: The conversions between u8* and u32* might cause trouble
* on architectures with stricter alignment rules than x86
*/
r0 = le32_to_cpu(s[0]);
r1 = le32_to_cpu(s[1]);
r2 = le32_to_cpu(s[2]);
r3 = le32_to_cpu(s[3]);
K(r0,r1,r2,r3,0);
S0(r0,r1,r2,r3,r4); LK(r2,r1,r3,r0,r4,1);
S1(r2,r1,r3,r0,r4); LK(r4,r3,r0,r2,r1,2);
S2(r4,r3,r0,r2,r1); LK(r1,r3,r4,r2,r0,3);
S3(r1,r3,r4,r2,r0); LK(r2,r0,r3,r1,r4,4);
S4(r2,r0,r3,r1,r4); LK(r0,r3,r1,r4,r2,5);
S5(r0,r3,r1,r4,r2); LK(r2,r0,r3,r4,r1,6);
S6(r2,r0,r3,r4,r1); LK(r3,r1,r0,r4,r2,7);
S7(r3,r1,r0,r4,r2); LK(r2,r0,r4,r3,r1,8);
S0(r2,r0,r4,r3,r1); LK(r4,r0,r3,r2,r1,9);
S1(r4,r0,r3,r2,r1); LK(r1,r3,r2,r4,r0,10);
S2(r1,r3,r2,r4,r0); LK(r0,r3,r1,r4,r2,11);
S3(r0,r3,r1,r4,r2); LK(r4,r2,r3,r0,r1,12);
S4(r4,r2,r3,r0,r1); LK(r2,r3,r0,r1,r4,13);
S5(r2,r3,r0,r1,r4); LK(r4,r2,r3,r1,r0,14);
S6(r4,r2,r3,r1,r0); LK(r3,r0,r2,r1,r4,15);
S7(r3,r0,r2,r1,r4); LK(r4,r2,r1,r3,r0,16);
S0(r4,r2,r1,r3,r0); LK(r1,r2,r3,r4,r0,17);
S1(r1,r2,r3,r4,r0); LK(r0,r3,r4,r1,r2,18);
S2(r0,r3,r4,r1,r2); LK(r2,r3,r0,r1,r4,19);
S3(r2,r3,r0,r1,r4); LK(r1,r4,r3,r2,r0,20);
S4(r1,r4,r3,r2,r0); LK(r4,r3,r2,r0,r1,21);
S5(r4,r3,r2,r0,r1); LK(r1,r4,r3,r0,r2,22);
S6(r1,r4,r3,r0,r2); LK(r3,r2,r4,r0,r1,23);
S7(r3,r2,r4,r0,r1); LK(r1,r4,r0,r3,r2,24);
S0(r1,r4,r0,r3,r2); LK(r0,r4,r3,r1,r2,25);
S1(r0,r4,r3,r1,r2); LK(r2,r3,r1,r0,r4,26);
S2(r2,r3,r1,r0,r4); LK(r4,r3,r2,r0,r1,27);
S3(r4,r3,r2,r0,r1); LK(r0,r1,r3,r4,r2,28);
S4(r0,r1,r3,r4,r2); LK(r1,r3,r4,r2,r0,29);
S5(r1,r3,r4,r2,r0); LK(r0,r1,r3,r2,r4,30);
S6(r0,r1,r3,r2,r4); LK(r3,r4,r1,r2,r0,31);
S7(r3,r4,r1,r2,r0); K(r0,r1,r2,r3,32);
d[0] = cpu_to_le32(r0);
d[1] = cpu_to_le32(r1);
d[2] = cpu_to_le32(r2);
d[3] = cpu_to_le32(r3);
}
static void serpent_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
const u32
*k = ((struct serpent_ctx *)ctx)->expkey;
const __le32 *s = (const __le32 *)src;
__le32 *d = (__le32 *)dst;
u32 r0, r1, r2, r3, r4;
r0 = le32_to_cpu(s[0]);
r1 = le32_to_cpu(s[1]);
r2 = le32_to_cpu(s[2]);
r3 = le32_to_cpu(s[3]);
K(r0,r1,r2,r3,32);
SI7(r0,r1,r2,r3,r4); KL(r1,r3,r0,r4,r2,31);
SI6(r1,r3,r0,r4,r2); KL(r0,r2,r4,r1,r3,30);
SI5(r0,r2,r4,r1,r3); KL(r2,r3,r0,r4,r1,29);
SI4(r2,r3,r0,r4,r1); KL(r2,r0,r1,r4,r3,28);
SI3(r2,r0,r1,r4,r3); KL(r1,r2,r3,r4,r0,27);
SI2(r1,r2,r3,r4,r0); KL(r2,r0,r4,r3,r1,26);
SI1(r2,r0,r4,r3,r1); KL(r1,r0,r4,r3,r2,25);
SI0(r1,r0,r4,r3,r2); KL(r4,r2,r0,r1,r3,24);
SI7(r4,r2,r0,r1,r3); KL(r2,r1,r4,r3,r0,23);
SI6(r2,r1,r4,r3,r0); KL(r4,r0,r3,r2,r1,22);
SI5(r4,r0,r3,r2,r1); KL(r0,r1,r4,r3,r2,21);
SI4(r0,r1,r4,r3,r2); KL(r0,r4,r2,r3,r1,20);
SI3(r0,r4,r2,r3,r1); KL(r2,r0,r1,r3,r4,19);
SI2(r2,r0,r1,r3,r4); KL(r0,r4,r3,r1,r2,18);
SI1(r0,r4,r3,r1,r2); KL(r2,r4,r3,r1,r0,17);
SI0(r2,r4,r3,r1,r0); KL(r3,r0,r4,r2,r1,16);
SI7(r3,r0,r4,r2,r1); KL(r0,r2,r3,r1,r4,15);
SI6(r0,r2,r3,r1,r4); KL(r3,r4,r1,r0,r2,14);
SI5(r3,r4,r1,r0,r2); KL(r4,r2,r3,r1,r0,13);
SI4(r4,r2,r3,r1,r0); KL(r4,r3,r0,r1,r2,12);
SI3(r4,r3,r0,r1,r2); KL(r0,r4,r2,r1,r3,11);
SI2(r0,r4,r2,r1,r3); KL(r4,r3,r1,r2,r0,10);
SI1(r4,r3,r1,r2,r0); KL(r0,r3,r1,r2,r4,9);
SI0(r0,r3,r1,r2,r4); KL(r1,r4,r3,r0,r2,8);
SI7(r1,r4,r3,r0,r2); KL(r4,r0,r1,r2,r3,7);
SI6(r4,r0,r1,r2,r3); KL(r1,r3,r2,r4,r0,6);
SI5(r1,r3,r2,r4,r0); KL(r3,r0,r1,r2,r4,5);
SI4(r3,r0,r1,r2,r4); KL(r3,r1,r4,r2,r0,4);
SI3(r3,r1,r4,r2,r0); KL(r4,r3,r0,r2,r1,3);
SI2(r4,r3,r0,r2,r1); KL(r3,r1,r2,r0,r4,2);
SI1(r3,r1,r2,r0,r4); KL(r4,r1,r2,r0,r3,1);
SI0(r4,r1,r2,r0,r3); K(r2,r3,r1,r4,0);
d[0] = cpu_to_le32(r2);
d[1] = cpu_to_le32(r3);
d[2] = cpu_to_le32(r1);
d[3] = cpu_to_le32(r4);
}
static struct crypto_alg serpent_alg = {
.cra_name = "serpent",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SERPENT_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct serpent_ctx),
.cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(serpent_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = SERPENT_MIN_KEY_SIZE,
.cia_max_keysize = SERPENT_MAX_KEY_SIZE,
.cia_setkey = serpent_setkey,
.cia_encrypt = serpent_encrypt,
.cia_decrypt = serpent_decrypt } }
};
static int tnepres_setkey(struct crypto_tfm *tfm, const u8 *key,
unsigned int keylen)
{
u8 rev_key[SERPENT_MAX_KEY_SIZE];
int i;
for (i = 0; i < keylen; ++i)
rev_key[keylen - i - 1] = key[i];
return serpent_setkey(tfm, rev_key, keylen);
}
static void tnepres_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const u32 * const s = (const u32 * const)src;
u32 * const d = (u32 * const)dst;
u32 rs[4], rd[4];
rs[0] = swab32(s[3]);
rs[1] = swab32(s[2]);
rs[2] = swab32(s[1]);
rs[3] = swab32(s[0]);
serpent_encrypt(tfm, (u8 *)rd, (u8 *)rs);
d[0] = swab32(rd[3]);
d[1] = swab32(rd[2]);
d[2] = swab32(rd[1]);
d[3] = swab32(rd[0]);
}
static void tnepres_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const u32 * const s = (const u32 * const)src;
u32 * const d = (u32 * const)dst;
u32 rs[4], rd[4];
rs[0] = swab32(s[3]);
rs[1] = swab32(s[2]);
rs[2] = swab32(s[1]);
rs[3] = swab32(s[0]);
serpent_decrypt(tfm, (u8 *)rd, (u8 *)rs);
d[0] = swab32(rd[3]);
d[1] = swab32(rd[2]);
d[2] = swab32(rd[1]);
d[3] = swab32(rd[0]);
}
static struct crypto_alg tnepres_alg = {
.cra_name = "tnepres",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SERPENT_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct serpent_ctx),
.cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(serpent_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = SERPENT_MIN_KEY_SIZE,
.cia_max_keysize = SERPENT_MAX_KEY_SIZE,
.cia_setkey = tnepres_setkey,
.cia_encrypt = tnepres_encrypt,
.cia_decrypt = tnepres_decrypt } }
};
static int __init serpent_mod_init(void)
{
int ret = crypto_register_alg(&serpent_alg);
if (ret)
return ret;
ret = crypto_register_alg(&tnepres_alg);
if (ret)
crypto_unregister_alg(&serpent_alg);
return ret;
}
static void __exit serpent_mod_fini(void)
{
crypto_unregister_alg(&tnepres_alg);
crypto_unregister_alg(&serpent_alg);
}
module_init(serpent_mod_init);
module_exit(serpent_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm");
MODULE_AUTHOR("Dag Arne Osvik <osvik@ii.uib.no>");
MODULE_ALIAS("tnepres");

684
crypto/serpent_generic.c Normal file
View File

@@ -0,0 +1,684 @@
/*
* Cryptographic API.
*
* Serpent Cipher Algorithm.
*
* Copyright (C) 2002 Dag Arne Osvik <osvik@ii.uib.no>
* 2003 Herbert Valerio Riedel <hvr@gnu.org>
*
* Added tnepres support:
* Ruben Jesus Garcia Hernandez <ruben@ugr.es>, 18.10.2004
* Based on code by hvr
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <asm/byteorder.h>
#include <linux/crypto.h>
#include <linux/types.h>
#include <crypto/serpent.h>
/* Key is padded to the maximum of 256 bits before round key generation.
* Any key length <= 256 bits (32 bytes) is allowed by the algorithm.
*/
#define PHI 0x9e3779b9UL
#define keyiter(a, b, c, d, i, j) \
({ b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; b = rol32(b, 11); k[j] = b; })
#define loadkeys(x0, x1, x2, x3, i) \
({ x0 = k[i]; x1 = k[i+1]; x2 = k[i+2]; x3 = k[i+3]; })
#define storekeys(x0, x1, x2, x3, i) \
({ k[i] = x0; k[i+1] = x1; k[i+2] = x2; k[i+3] = x3; })
#define store_and_load_keys(x0, x1, x2, x3, s, l) \
({ storekeys(x0, x1, x2, x3, s); loadkeys(x0, x1, x2, x3, l); })
#define K(x0, x1, x2, x3, i) ({ \
x3 ^= k[4*(i)+3]; x2 ^= k[4*(i)+2]; \
x1 ^= k[4*(i)+1]; x0 ^= k[4*(i)+0]; \
})
#define LK(x0, x1, x2, x3, x4, i) ({ \
x0 = rol32(x0, 13);\
x2 = rol32(x2, 3); x1 ^= x0; x4 = x0 << 3; \
x3 ^= x2; x1 ^= x2; \
x1 = rol32(x1, 1); x3 ^= x4; \
x3 = rol32(x3, 7); x4 = x1; \
x0 ^= x1; x4 <<= 7; x2 ^= x3; \
x0 ^= x3; x2 ^= x4; x3 ^= k[4*i+3]; \
x1 ^= k[4*i+1]; x0 = rol32(x0, 5); x2 = rol32(x2, 22);\
x0 ^= k[4*i+0]; x2 ^= k[4*i+2]; \
})
#define KL(x0, x1, x2, x3, x4, i) ({ \
x0 ^= k[4*i+0]; x1 ^= k[4*i+1]; x2 ^= k[4*i+2]; \
x3 ^= k[4*i+3]; x0 = ror32(x0, 5); x2 = ror32(x2, 22);\
x4 = x1; x2 ^= x3; x0 ^= x3; \
x4 <<= 7; x0 ^= x1; x1 = ror32(x1, 1); \
x2 ^= x4; x3 = ror32(x3, 7); x4 = x0 << 3; \
x1 ^= x0; x3 ^= x4; x0 = ror32(x0, 13);\
x1 ^= x2; x3 ^= x2; x2 = ror32(x2, 3); \
})
#define S0(x0, x1, x2, x3, x4) ({ \
x4 = x3; \
x3 |= x0; x0 ^= x4; x4 ^= x2; \
x4 = ~x4; x3 ^= x1; x1 &= x0; \
x1 ^= x4; x2 ^= x0; x0 ^= x3; \
x4 |= x0; x0 ^= x2; x2 &= x1; \
x3 ^= x2; x1 = ~x1; x2 ^= x4; \
x1 ^= x2; \
})
#define S1(x0, x1, x2, x3, x4) ({ \
x4 = x1; \
x1 ^= x0; x0 ^= x3; x3 = ~x3; \
x4 &= x1; x0 |= x1; x3 ^= x2; \
x0 ^= x3; x1 ^= x3; x3 ^= x4; \
x1 |= x4; x4 ^= x2; x2 &= x0; \
x2 ^= x1; x1 |= x0; x0 = ~x0; \
x0 ^= x2; x4 ^= x1; \
})
#define S2(x0, x1, x2, x3, x4) ({ \
x3 = ~x3; \
x1 ^= x0; x4 = x0; x0 &= x2; \
x0 ^= x3; x3 |= x4; x2 ^= x1; \
x3 ^= x1; x1 &= x0; x0 ^= x2; \
x2 &= x3; x3 |= x1; x0 = ~x0; \
x3 ^= x0; x4 ^= x0; x0 ^= x2; \
x1 |= x2; \
})
#define S3(x0, x1, x2, x3, x4) ({ \
x4 = x1; \
x1 ^= x3; x3 |= x0; x4 &= x0; \
x0 ^= x2; x2 ^= x1; x1 &= x3; \
x2 ^= x3; x0 |= x4; x4 ^= x3; \
x1 ^= x0; x0 &= x3; x3 &= x4; \
x3 ^= x2; x4 |= x1; x2 &= x1; \
x4 ^= x3; x0 ^= x3; x3 ^= x2; \
})
#define S4(x0, x1, x2, x3, x4) ({ \
x4 = x3; \
x3 &= x0; x0 ^= x4; \
x3 ^= x2; x2 |= x4; x0 ^= x1; \
x4 ^= x3; x2 |= x0; \
x2 ^= x1; x1 &= x0; \
x1 ^= x4; x4 &= x2; x2 ^= x3; \
x4 ^= x0; x3 |= x1; x1 = ~x1; \
x3 ^= x0; \
})
#define S5(x0, x1, x2, x3, x4) ({ \
x4 = x1; x1 |= x0; \
x2 ^= x1; x3 = ~x3; x4 ^= x0; \
x0 ^= x2; x1 &= x4; x4 |= x3; \
x4 ^= x0; x0 &= x3; x1 ^= x3; \
x3 ^= x2; x0 ^= x1; x2 &= x4; \
x1 ^= x2; x2 &= x0; \
x3 ^= x2; \
})
#define S6(x0, x1, x2, x3, x4) ({ \
x4 = x1; \
x3 ^= x0; x1 ^= x2; x2 ^= x0; \
x0 &= x3; x1 |= x3; x4 = ~x4; \
x0 ^= x1; x1 ^= x2; \
x3 ^= x4; x4 ^= x0; x2 &= x0; \
x4 ^= x1; x2 ^= x3; x3 &= x1; \
x3 ^= x0; x1 ^= x2; \
})
#define S7(x0, x1, x2, x3, x4) ({ \
x1 = ~x1; \
x4 = x1; x0 = ~x0; x1 &= x2; \
x1 ^= x3; x3 |= x4; x4 ^= x2; \
x2 ^= x3; x3 ^= x0; x0 |= x1; \
x2 &= x0; x0 ^= x4; x4 ^= x3; \
x3 &= x0; x4 ^= x1; \
x2 ^= x4; x3 ^= x1; x4 |= x0; \
x4 ^= x1; \
})
#define SI0(x0, x1, x2, x3, x4) ({ \
x4 = x3; x1 ^= x0; \
x3 |= x1; x4 ^= x1; x0 = ~x0; \
x2 ^= x3; x3 ^= x0; x0 &= x1; \
x0 ^= x2; x2 &= x3; x3 ^= x4; \
x2 ^= x3; x1 ^= x3; x3 &= x0; \
x1 ^= x0; x0 ^= x2; x4 ^= x3; \
})
#define SI1(x0, x1, x2, x3, x4) ({ \
x1 ^= x3; x4 = x0; \
x0 ^= x2; x2 = ~x2; x4 |= x1; \
x4 ^= x3; x3 &= x1; x1 ^= x2; \
x2 &= x4; x4 ^= x1; x1 |= x3; \
x3 ^= x0; x2 ^= x0; x0 |= x4; \
x2 ^= x4; x1 ^= x0; \
x4 ^= x1; \
})
#define SI2(x0, x1, x2, x3, x4) ({ \
x2 ^= x1; x4 = x3; x3 = ~x3; \
x3 |= x2; x2 ^= x4; x4 ^= x0; \
x3 ^= x1; x1 |= x2; x2 ^= x0; \
x1 ^= x4; x4 |= x3; x2 ^= x3; \
x4 ^= x2; x2 &= x1; \
x2 ^= x3; x3 ^= x4; x4 ^= x0; \
})
#define SI3(x0, x1, x2, x3, x4) ({ \
x2 ^= x1; \
x4 = x1; x1 &= x2; \
x1 ^= x0; x0 |= x4; x4 ^= x3; \
x0 ^= x3; x3 |= x1; x1 ^= x2; \
x1 ^= x3; x0 ^= x2; x2 ^= x3; \
x3 &= x1; x1 ^= x0; x0 &= x2; \
x4 ^= x3; x3 ^= x0; x0 ^= x1; \
})
#define SI4(x0, x1, x2, x3, x4) ({ \
x2 ^= x3; x4 = x0; x0 &= x1; \
x0 ^= x2; x2 |= x3; x4 = ~x4; \
x1 ^= x0; x0 ^= x2; x2 &= x4; \
x2 ^= x0; x0 |= x4; \
x0 ^= x3; x3 &= x2; \
x4 ^= x3; x3 ^= x1; x1 &= x0; \
x4 ^= x1; x0 ^= x3; \
})
#define SI5(x0, x1, x2, x3, x4) ({ \
x4 = x1; x1 |= x2; \
x2 ^= x4; x1 ^= x3; x3 &= x4; \
x2 ^= x3; x3 |= x0; x0 = ~x0; \
x3 ^= x2; x2 |= x0; x4 ^= x1; \
x2 ^= x4; x4 &= x0; x0 ^= x1; \
x1 ^= x3; x0 &= x2; x2 ^= x3; \
x0 ^= x2; x2 ^= x4; x4 ^= x3; \
})
#define SI6(x0, x1, x2, x3, x4) ({ \
x0 ^= x2; \
x4 = x0; x0 &= x3; x2 ^= x3; \
x0 ^= x2; x3 ^= x1; x2 |= x4; \
x2 ^= x3; x3 &= x0; x0 = ~x0; \
x3 ^= x1; x1 &= x2; x4 ^= x0; \
x3 ^= x4; x4 ^= x2; x0 ^= x1; \
x2 ^= x0; \
})
#define SI7(x0, x1, x2, x3, x4) ({ \
x4 = x3; x3 &= x0; x0 ^= x2; \
x2 |= x4; x4 ^= x1; x0 = ~x0; \
x1 |= x3; x4 ^= x0; x0 &= x2; \
x0 ^= x1; x1 &= x2; x3 ^= x2; \
x4 ^= x3; x2 &= x3; x3 |= x0; \
x1 ^= x4; x3 ^= x4; x4 &= x0; \
x4 ^= x2; \
})
int __serpent_setkey(struct serpent_ctx *ctx, const u8 *key,
unsigned int keylen)
{
u32 *k = ctx->expkey;
u8 *k8 = (u8 *)k;
u32 r0, r1, r2, r3, r4;
int i;
/* Copy key, add padding */
for (i = 0; i < keylen; ++i)
k8[i] = key[i];
if (i < SERPENT_MAX_KEY_SIZE)
k8[i++] = 1;
while (i < SERPENT_MAX_KEY_SIZE)
k8[i++] = 0;
/* Expand key using polynomial */
r0 = le32_to_cpu(k[3]);
r1 = le32_to_cpu(k[4]);
r2 = le32_to_cpu(k[5]);
r3 = le32_to_cpu(k[6]);
r4 = le32_to_cpu(k[7]);
keyiter(le32_to_cpu(k[0]), r0, r4, r2, 0, 0);
keyiter(le32_to_cpu(k[1]), r1, r0, r3, 1, 1);
keyiter(le32_to_cpu(k[2]), r2, r1, r4, 2, 2);
keyiter(le32_to_cpu(k[3]), r3, r2, r0, 3, 3);
keyiter(le32_to_cpu(k[4]), r4, r3, r1, 4, 4);
keyiter(le32_to_cpu(k[5]), r0, r4, r2, 5, 5);
keyiter(le32_to_cpu(k[6]), r1, r0, r3, 6, 6);
keyiter(le32_to_cpu(k[7]), r2, r1, r4, 7, 7);
keyiter(k[0], r3, r2, r0, 8, 8);
keyiter(k[1], r4, r3, r1, 9, 9);
keyiter(k[2], r0, r4, r2, 10, 10);
keyiter(k[3], r1, r0, r3, 11, 11);
keyiter(k[4], r2, r1, r4, 12, 12);
keyiter(k[5], r3, r2, r0, 13, 13);
keyiter(k[6], r4, r3, r1, 14, 14);
keyiter(k[7], r0, r4, r2, 15, 15);
keyiter(k[8], r1, r0, r3, 16, 16);
keyiter(k[9], r2, r1, r4, 17, 17);
keyiter(k[10], r3, r2, r0, 18, 18);
keyiter(k[11], r4, r3, r1, 19, 19);
keyiter(k[12], r0, r4, r2, 20, 20);
keyiter(k[13], r1, r0, r3, 21, 21);
keyiter(k[14], r2, r1, r4, 22, 22);
keyiter(k[15], r3, r2, r0, 23, 23);
keyiter(k[16], r4, r3, r1, 24, 24);
keyiter(k[17], r0, r4, r2, 25, 25);
keyiter(k[18], r1, r0, r3, 26, 26);
keyiter(k[19], r2, r1, r4, 27, 27);
keyiter(k[20], r3, r2, r0, 28, 28);
keyiter(k[21], r4, r3, r1, 29, 29);
keyiter(k[22], r0, r4, r2, 30, 30);
keyiter(k[23], r1, r0, r3, 31, 31);
k += 50;
keyiter(k[-26], r2, r1, r4, 32, -18);
keyiter(k[-25], r3, r2, r0, 33, -17);
keyiter(k[-24], r4, r3, r1, 34, -16);
keyiter(k[-23], r0, r4, r2, 35, -15);
keyiter(k[-22], r1, r0, r3, 36, -14);
keyiter(k[-21], r2, r1, r4, 37, -13);
keyiter(k[-20], r3, r2, r0, 38, -12);
keyiter(k[-19], r4, r3, r1, 39, -11);
keyiter(k[-18], r0, r4, r2, 40, -10);
keyiter(k[-17], r1, r0, r3, 41, -9);
keyiter(k[-16], r2, r1, r4, 42, -8);
keyiter(k[-15], r3, r2, r0, 43, -7);
keyiter(k[-14], r4, r3, r1, 44, -6);
keyiter(k[-13], r0, r4, r2, 45, -5);
keyiter(k[-12], r1, r0, r3, 46, -4);
keyiter(k[-11], r2, r1, r4, 47, -3);
keyiter(k[-10], r3, r2, r0, 48, -2);
keyiter(k[-9], r4, r3, r1, 49, -1);
keyiter(k[-8], r0, r4, r2, 50, 0);
keyiter(k[-7], r1, r0, r3, 51, 1);
keyiter(k[-6], r2, r1, r4, 52, 2);
keyiter(k[-5], r3, r2, r0, 53, 3);
keyiter(k[-4], r4, r3, r1, 54, 4);
keyiter(k[-3], r0, r4, r2, 55, 5);
keyiter(k[-2], r1, r0, r3, 56, 6);
keyiter(k[-1], r2, r1, r4, 57, 7);
keyiter(k[0], r3, r2, r0, 58, 8);
keyiter(k[1], r4, r3, r1, 59, 9);
keyiter(k[2], r0, r4, r2, 60, 10);
keyiter(k[3], r1, r0, r3, 61, 11);
keyiter(k[4], r2, r1, r4, 62, 12);
keyiter(k[5], r3, r2, r0, 63, 13);
keyiter(k[6], r4, r3, r1, 64, 14);
keyiter(k[7], r0, r4, r2, 65, 15);
keyiter(k[8], r1, r0, r3, 66, 16);
keyiter(k[9], r2, r1, r4, 67, 17);
keyiter(k[10], r3, r2, r0, 68, 18);
keyiter(k[11], r4, r3, r1, 69, 19);
keyiter(k[12], r0, r4, r2, 70, 20);
keyiter(k[13], r1, r0, r3, 71, 21);
keyiter(k[14], r2, r1, r4, 72, 22);
keyiter(k[15], r3, r2, r0, 73, 23);
keyiter(k[16], r4, r3, r1, 74, 24);
keyiter(k[17], r0, r4, r2, 75, 25);
keyiter(k[18], r1, r0, r3, 76, 26);
keyiter(k[19], r2, r1, r4, 77, 27);
keyiter(k[20], r3, r2, r0, 78, 28);
keyiter(k[21], r4, r3, r1, 79, 29);
keyiter(k[22], r0, r4, r2, 80, 30);
keyiter(k[23], r1, r0, r3, 81, 31);
k += 50;
keyiter(k[-26], r2, r1, r4, 82, -18);
keyiter(k[-25], r3, r2, r0, 83, -17);
keyiter(k[-24], r4, r3, r1, 84, -16);
keyiter(k[-23], r0, r4, r2, 85, -15);
keyiter(k[-22], r1, r0, r3, 86, -14);
keyiter(k[-21], r2, r1, r4, 87, -13);
keyiter(k[-20], r3, r2, r0, 88, -12);
keyiter(k[-19], r4, r3, r1, 89, -11);
keyiter(k[-18], r0, r4, r2, 90, -10);
keyiter(k[-17], r1, r0, r3, 91, -9);
keyiter(k[-16], r2, r1, r4, 92, -8);
keyiter(k[-15], r3, r2, r0, 93, -7);
keyiter(k[-14], r4, r3, r1, 94, -6);
keyiter(k[-13], r0, r4, r2, 95, -5);
keyiter(k[-12], r1, r0, r3, 96, -4);
keyiter(k[-11], r2, r1, r4, 97, -3);
keyiter(k[-10], r3, r2, r0, 98, -2);
keyiter(k[-9], r4, r3, r1, 99, -1);
keyiter(k[-8], r0, r4, r2, 100, 0);
keyiter(k[-7], r1, r0, r3, 101, 1);
keyiter(k[-6], r2, r1, r4, 102, 2);
keyiter(k[-5], r3, r2, r0, 103, 3);
keyiter(k[-4], r4, r3, r1, 104, 4);
keyiter(k[-3], r0, r4, r2, 105, 5);
keyiter(k[-2], r1, r0, r3, 106, 6);
keyiter(k[-1], r2, r1, r4, 107, 7);
keyiter(k[0], r3, r2, r0, 108, 8);
keyiter(k[1], r4, r3, r1, 109, 9);
keyiter(k[2], r0, r4, r2, 110, 10);
keyiter(k[3], r1, r0, r3, 111, 11);
keyiter(k[4], r2, r1, r4, 112, 12);
keyiter(k[5], r3, r2, r0, 113, 13);
keyiter(k[6], r4, r3, r1, 114, 14);
keyiter(k[7], r0, r4, r2, 115, 15);
keyiter(k[8], r1, r0, r3, 116, 16);
keyiter(k[9], r2, r1, r4, 117, 17);
keyiter(k[10], r3, r2, r0, 118, 18);
keyiter(k[11], r4, r3, r1, 119, 19);
keyiter(k[12], r0, r4, r2, 120, 20);
keyiter(k[13], r1, r0, r3, 121, 21);
keyiter(k[14], r2, r1, r4, 122, 22);
keyiter(k[15], r3, r2, r0, 123, 23);
keyiter(k[16], r4, r3, r1, 124, 24);
keyiter(k[17], r0, r4, r2, 125, 25);
keyiter(k[18], r1, r0, r3, 126, 26);
keyiter(k[19], r2, r1, r4, 127, 27);
keyiter(k[20], r3, r2, r0, 128, 28);
keyiter(k[21], r4, r3, r1, 129, 29);
keyiter(k[22], r0, r4, r2, 130, 30);
keyiter(k[23], r1, r0, r3, 131, 31);
/* Apply S-boxes */
S3(r3, r4, r0, r1, r2); store_and_load_keys(r1, r2, r4, r3, 28, 24);
S4(r1, r2, r4, r3, r0); store_and_load_keys(r2, r4, r3, r0, 24, 20);
S5(r2, r4, r3, r0, r1); store_and_load_keys(r1, r2, r4, r0, 20, 16);
S6(r1, r2, r4, r0, r3); store_and_load_keys(r4, r3, r2, r0, 16, 12);
S7(r4, r3, r2, r0, r1); store_and_load_keys(r1, r2, r0, r4, 12, 8);
S0(r1, r2, r0, r4, r3); store_and_load_keys(r0, r2, r4, r1, 8, 4);
S1(r0, r2, r4, r1, r3); store_and_load_keys(r3, r4, r1, r0, 4, 0);
S2(r3, r4, r1, r0, r2); store_and_load_keys(r2, r4, r3, r0, 0, -4);
S3(r2, r4, r3, r0, r1); store_and_load_keys(r0, r1, r4, r2, -4, -8);
S4(r0, r1, r4, r2, r3); store_and_load_keys(r1, r4, r2, r3, -8, -12);
S5(r1, r4, r2, r3, r0); store_and_load_keys(r0, r1, r4, r3, -12, -16);
S6(r0, r1, r4, r3, r2); store_and_load_keys(r4, r2, r1, r3, -16, -20);
S7(r4, r2, r1, r3, r0); store_and_load_keys(r0, r1, r3, r4, -20, -24);
S0(r0, r1, r3, r4, r2); store_and_load_keys(r3, r1, r4, r0, -24, -28);
k -= 50;
S1(r3, r1, r4, r0, r2); store_and_load_keys(r2, r4, r0, r3, 22, 18);
S2(r2, r4, r0, r3, r1); store_and_load_keys(r1, r4, r2, r3, 18, 14);
S3(r1, r4, r2, r3, r0); store_and_load_keys(r3, r0, r4, r1, 14, 10);
S4(r3, r0, r4, r1, r2); store_and_load_keys(r0, r4, r1, r2, 10, 6);
S5(r0, r4, r1, r2, r3); store_and_load_keys(r3, r0, r4, r2, 6, 2);
S6(r3, r0, r4, r2, r1); store_and_load_keys(r4, r1, r0, r2, 2, -2);
S7(r4, r1, r0, r2, r3); store_and_load_keys(r3, r0, r2, r4, -2, -6);
S0(r3, r0, r2, r4, r1); store_and_load_keys(r2, r0, r4, r3, -6, -10);
S1(r2, r0, r4, r3, r1); store_and_load_keys(r1, r4, r3, r2, -10, -14);
S2(r1, r4, r3, r2, r0); store_and_load_keys(r0, r4, r1, r2, -14, -18);
S3(r0, r4, r1, r2, r3); store_and_load_keys(r2, r3, r4, r0, -18, -22);
k -= 50;
S4(r2, r3, r4, r0, r1); store_and_load_keys(r3, r4, r0, r1, 28, 24);
S5(r3, r4, r0, r1, r2); store_and_load_keys(r2, r3, r4, r1, 24, 20);
S6(r2, r3, r4, r1, r0); store_and_load_keys(r4, r0, r3, r1, 20, 16);
S7(r4, r0, r3, r1, r2); store_and_load_keys(r2, r3, r1, r4, 16, 12);
S0(r2, r3, r1, r4, r0); store_and_load_keys(r1, r3, r4, r2, 12, 8);
S1(r1, r3, r4, r2, r0); store_and_load_keys(r0, r4, r2, r1, 8, 4);
S2(r0, r4, r2, r1, r3); store_and_load_keys(r3, r4, r0, r1, 4, 0);
S3(r3, r4, r0, r1, r2); storekeys(r1, r2, r4, r3, 0);
return 0;
}
EXPORT_SYMBOL_GPL(__serpent_setkey);
int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
return __serpent_setkey(crypto_tfm_ctx(tfm), key, keylen);
}
EXPORT_SYMBOL_GPL(serpent_setkey);
void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src)
{
const u32 *k = ctx->expkey;
const __le32 *s = (const __le32 *)src;
__le32 *d = (__le32 *)dst;
u32 r0, r1, r2, r3, r4;
/*
* Note: The conversions between u8* and u32* might cause trouble
* on architectures with stricter alignment rules than x86
*/
r0 = le32_to_cpu(s[0]);
r1 = le32_to_cpu(s[1]);
r2 = le32_to_cpu(s[2]);
r3 = le32_to_cpu(s[3]);
K(r0, r1, r2, r3, 0);
S0(r0, r1, r2, r3, r4); LK(r2, r1, r3, r0, r4, 1);
S1(r2, r1, r3, r0, r4); LK(r4, r3, r0, r2, r1, 2);
S2(r4, r3, r0, r2, r1); LK(r1, r3, r4, r2, r0, 3);
S3(r1, r3, r4, r2, r0); LK(r2, r0, r3, r1, r4, 4);
S4(r2, r0, r3, r1, r4); LK(r0, r3, r1, r4, r2, 5);
S5(r0, r3, r1, r4, r2); LK(r2, r0, r3, r4, r1, 6);
S6(r2, r0, r3, r4, r1); LK(r3, r1, r0, r4, r2, 7);
S7(r3, r1, r0, r4, r2); LK(r2, r0, r4, r3, r1, 8);
S0(r2, r0, r4, r3, r1); LK(r4, r0, r3, r2, r1, 9);
S1(r4, r0, r3, r2, r1); LK(r1, r3, r2, r4, r0, 10);
S2(r1, r3, r2, r4, r0); LK(r0, r3, r1, r4, r2, 11);
S3(r0, r3, r1, r4, r2); LK(r4, r2, r3, r0, r1, 12);
S4(r4, r2, r3, r0, r1); LK(r2, r3, r0, r1, r4, 13);
S5(r2, r3, r0, r1, r4); LK(r4, r2, r3, r1, r0, 14);
S6(r4, r2, r3, r1, r0); LK(r3, r0, r2, r1, r4, 15);
S7(r3, r0, r2, r1, r4); LK(r4, r2, r1, r3, r0, 16);
S0(r4, r2, r1, r3, r0); LK(r1, r2, r3, r4, r0, 17);
S1(r1, r2, r3, r4, r0); LK(r0, r3, r4, r1, r2, 18);
S2(r0, r3, r4, r1, r2); LK(r2, r3, r0, r1, r4, 19);
S3(r2, r3, r0, r1, r4); LK(r1, r4, r3, r2, r0, 20);
S4(r1, r4, r3, r2, r0); LK(r4, r3, r2, r0, r1, 21);
S5(r4, r3, r2, r0, r1); LK(r1, r4, r3, r0, r2, 22);
S6(r1, r4, r3, r0, r2); LK(r3, r2, r4, r0, r1, 23);
S7(r3, r2, r4, r0, r1); LK(r1, r4, r0, r3, r2, 24);
S0(r1, r4, r0, r3, r2); LK(r0, r4, r3, r1, r2, 25);
S1(r0, r4, r3, r1, r2); LK(r2, r3, r1, r0, r4, 26);
S2(r2, r3, r1, r0, r4); LK(r4, r3, r2, r0, r1, 27);
S3(r4, r3, r2, r0, r1); LK(r0, r1, r3, r4, r2, 28);
S4(r0, r1, r3, r4, r2); LK(r1, r3, r4, r2, r0, 29);
S5(r1, r3, r4, r2, r0); LK(r0, r1, r3, r2, r4, 30);
S6(r0, r1, r3, r2, r4); LK(r3, r4, r1, r2, r0, 31);
S7(r3, r4, r1, r2, r0); K(r0, r1, r2, r3, 32);
d[0] = cpu_to_le32(r0);
d[1] = cpu_to_le32(r1);
d[2] = cpu_to_le32(r2);
d[3] = cpu_to_le32(r3);
}
EXPORT_SYMBOL_GPL(__serpent_encrypt);
static void serpent_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
__serpent_encrypt(ctx, dst, src);
}
void __serpent_decrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src)
{
const u32 *k = ctx->expkey;
const __le32 *s = (const __le32 *)src;
__le32 *d = (__le32 *)dst;
u32 r0, r1, r2, r3, r4;
r0 = le32_to_cpu(s[0]);
r1 = le32_to_cpu(s[1]);
r2 = le32_to_cpu(s[2]);
r3 = le32_to_cpu(s[3]);
K(r0, r1, r2, r3, 32);
SI7(r0, r1, r2, r3, r4); KL(r1, r3, r0, r4, r2, 31);
SI6(r1, r3, r0, r4, r2); KL(r0, r2, r4, r1, r3, 30);
SI5(r0, r2, r4, r1, r3); KL(r2, r3, r0, r4, r1, 29);
SI4(r2, r3, r0, r4, r1); KL(r2, r0, r1, r4, r3, 28);
SI3(r2, r0, r1, r4, r3); KL(r1, r2, r3, r4, r0, 27);
SI2(r1, r2, r3, r4, r0); KL(r2, r0, r4, r3, r1, 26);
SI1(r2, r0, r4, r3, r1); KL(r1, r0, r4, r3, r2, 25);
SI0(r1, r0, r4, r3, r2); KL(r4, r2, r0, r1, r3, 24);
SI7(r4, r2, r0, r1, r3); KL(r2, r1, r4, r3, r0, 23);
SI6(r2, r1, r4, r3, r0); KL(r4, r0, r3, r2, r1, 22);
SI5(r4, r0, r3, r2, r1); KL(r0, r1, r4, r3, r2, 21);
SI4(r0, r1, r4, r3, r2); KL(r0, r4, r2, r3, r1, 20);
SI3(r0, r4, r2, r3, r1); KL(r2, r0, r1, r3, r4, 19);
SI2(r2, r0, r1, r3, r4); KL(r0, r4, r3, r1, r2, 18);
SI1(r0, r4, r3, r1, r2); KL(r2, r4, r3, r1, r0, 17);
SI0(r2, r4, r3, r1, r0); KL(r3, r0, r4, r2, r1, 16);
SI7(r3, r0, r4, r2, r1); KL(r0, r2, r3, r1, r4, 15);
SI6(r0, r2, r3, r1, r4); KL(r3, r4, r1, r0, r2, 14);
SI5(r3, r4, r1, r0, r2); KL(r4, r2, r3, r1, r0, 13);
SI4(r4, r2, r3, r1, r0); KL(r4, r3, r0, r1, r2, 12);
SI3(r4, r3, r0, r1, r2); KL(r0, r4, r2, r1, r3, 11);
SI2(r0, r4, r2, r1, r3); KL(r4, r3, r1, r2, r0, 10);
SI1(r4, r3, r1, r2, r0); KL(r0, r3, r1, r2, r4, 9);
SI0(r0, r3, r1, r2, r4); KL(r1, r4, r3, r0, r2, 8);
SI7(r1, r4, r3, r0, r2); KL(r4, r0, r1, r2, r3, 7);
SI6(r4, r0, r1, r2, r3); KL(r1, r3, r2, r4, r0, 6);
SI5(r1, r3, r2, r4, r0); KL(r3, r0, r1, r2, r4, 5);
SI4(r3, r0, r1, r2, r4); KL(r3, r1, r4, r2, r0, 4);
SI3(r3, r1, r4, r2, r0); KL(r4, r3, r0, r2, r1, 3);
SI2(r4, r3, r0, r2, r1); KL(r3, r1, r2, r0, r4, 2);
SI1(r3, r1, r2, r0, r4); KL(r4, r1, r2, r0, r3, 1);
SI0(r4, r1, r2, r0, r3); K(r2, r3, r1, r4, 0);
d[0] = cpu_to_le32(r2);
d[1] = cpu_to_le32(r3);
d[2] = cpu_to_le32(r1);
d[3] = cpu_to_le32(r4);
}
EXPORT_SYMBOL_GPL(__serpent_decrypt);
static void serpent_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
__serpent_decrypt(ctx, dst, src);
}
static struct crypto_alg serpent_alg = {
.cra_name = "serpent",
.cra_driver_name = "serpent-generic",
.cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SERPENT_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct serpent_ctx),
.cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(serpent_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = SERPENT_MIN_KEY_SIZE,
.cia_max_keysize = SERPENT_MAX_KEY_SIZE,
.cia_setkey = serpent_setkey,
.cia_encrypt = serpent_encrypt,
.cia_decrypt = serpent_decrypt } }
};
static int tnepres_setkey(struct crypto_tfm *tfm, const u8 *key,
unsigned int keylen)
{
u8 rev_key[SERPENT_MAX_KEY_SIZE];
int i;
for (i = 0; i < keylen; ++i)
rev_key[keylen - i - 1] = key[i];
return serpent_setkey(tfm, rev_key, keylen);
}
static void tnepres_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const u32 * const s = (const u32 * const)src;
u32 * const d = (u32 * const)dst;
u32 rs[4], rd[4];
rs[0] = swab32(s[3]);
rs[1] = swab32(s[2]);
rs[2] = swab32(s[1]);
rs[3] = swab32(s[0]);
serpent_encrypt(tfm, (u8 *)rd, (u8 *)rs);
d[0] = swab32(rd[3]);
d[1] = swab32(rd[2]);
d[2] = swab32(rd[1]);
d[3] = swab32(rd[0]);
}
static void tnepres_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const u32 * const s = (const u32 * const)src;
u32 * const d = (u32 * const)dst;
u32 rs[4], rd[4];
rs[0] = swab32(s[3]);
rs[1] = swab32(s[2]);
rs[2] = swab32(s[1]);
rs[3] = swab32(s[0]);
serpent_decrypt(tfm, (u8 *)rd, (u8 *)rs);
d[0] = swab32(rd[3]);
d[1] = swab32(rd[2]);
d[2] = swab32(rd[1]);
d[3] = swab32(rd[0]);
}
static struct crypto_alg tnepres_alg = {
.cra_name = "tnepres",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SERPENT_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct serpent_ctx),
.cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(serpent_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = SERPENT_MIN_KEY_SIZE,
.cia_max_keysize = SERPENT_MAX_KEY_SIZE,
.cia_setkey = tnepres_setkey,
.cia_encrypt = tnepres_encrypt,
.cia_decrypt = tnepres_decrypt } }
};
static int __init serpent_mod_init(void)
{
int ret = crypto_register_alg(&serpent_alg);
if (ret)
return ret;
ret = crypto_register_alg(&tnepres_alg);
if (ret)
crypto_unregister_alg(&serpent_alg);
return ret;
}
static void __exit serpent_mod_fini(void)
{
crypto_unregister_alg(&tnepres_alg);
crypto_unregister_alg(&serpent_alg);
}
module_init(serpent_mod_init);
module_exit(serpent_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm");
MODULE_AUTHOR("Dag Arne Osvik <osvik@ii.uib.no>");
MODULE_ALIAS("tnepres");
MODULE_ALIAS("serpent");

View File

@@ -719,6 +719,207 @@ out:
crypto_free_ahash(tfm);
}
static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
{
if (ret == -EINPROGRESS || ret == -EBUSY) {
struct tcrypt_result *tr = req->base.data;
ret = wait_for_completion_interruptible(&tr->completion);
if (!ret)
ret = tr->err;
INIT_COMPLETION(tr->completion);
}
return ret;
}
static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
int blen, int sec)
{
unsigned long start, end;
int bcount;
int ret;
for (start = jiffies, end = start + sec * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = do_one_acipher_op(req,
crypto_ablkcipher_encrypt(req));
else
ret = do_one_acipher_op(req,
crypto_ablkcipher_decrypt(req));
if (ret)
return ret;
}
pr_cont("%d operations in %d seconds (%ld bytes)\n",
bcount, sec, (long)bcount * blen);
return 0;
}
static int test_acipher_cycles(struct ablkcipher_request *req, int enc,
int blen)
{
unsigned long cycles = 0;
int ret = 0;
int i;
/* Warm-up run. */
for (i = 0; i < 4; i++) {
if (enc)
ret = do_one_acipher_op(req,
crypto_ablkcipher_encrypt(req));
else
ret = do_one_acipher_op(req,
crypto_ablkcipher_decrypt(req));
if (ret)
goto out;
}
/* The real thing. */
for (i = 0; i < 8; i++) {
cycles_t start, end;
start = get_cycles();
if (enc)
ret = do_one_acipher_op(req,
crypto_ablkcipher_encrypt(req));
else
ret = do_one_acipher_op(req,
crypto_ablkcipher_decrypt(req));
end = get_cycles();
if (ret)
goto out;
cycles += end - start;
}
out:
if (ret == 0)
pr_cont("1 operation in %lu cycles (%d bytes)\n",
(cycles + 4) / 8, blen);
return ret;
}
static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
struct cipher_speed_template *template,
unsigned int tcount, u8 *keysize)
{
unsigned int ret, i, j, iv_len;
struct tcrypt_result tresult;
const char *key;
char iv[128];
struct ablkcipher_request *req;
struct crypto_ablkcipher *tfm;
const char *e;
u32 *b_size;
if (enc == ENCRYPT)
e = "encryption";
else
e = "decryption";
pr_info("\ntesting speed of async %s %s\n", algo, e);
init_completion(&tresult.completion);
tfm = crypto_alloc_ablkcipher(algo, 0, 0);
if (IS_ERR(tfm)) {
pr_err("failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm));
return;
}
req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
if (!req) {
pr_err("tcrypt: skcipher: Failed to allocate request for %s\n",
algo);
goto out;
}
ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &tresult);
i = 0;
do {
b_size = block_sizes;
do {
struct scatterlist sg[TVMEMSIZE];
if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
pr_err("template (%u) too big for "
"tvmem (%lu)\n", *keysize + *b_size,
TVMEMSIZE * PAGE_SIZE);
goto out_free_req;
}
pr_info("test %u (%d bit key, %d byte blocks): ", i,
*keysize * 8, *b_size);
memset(tvmem[0], 0xff, PAGE_SIZE);
/* set key, plain text and IV */
key = tvmem[0];
for (j = 0; j < tcount; j++) {
if (template[j].klen == *keysize) {
key = template[j].key;
break;
}
}
crypto_ablkcipher_clear_flags(tfm, ~0);
ret = crypto_ablkcipher_setkey(tfm, key, *keysize);
if (ret) {
pr_err("setkey() failed flags=%x\n",
crypto_ablkcipher_get_flags(tfm));
goto out_free_req;
}
sg_init_table(sg, TVMEMSIZE);
sg_set_buf(sg, tvmem[0] + *keysize,
PAGE_SIZE - *keysize);
for (j = 1; j < TVMEMSIZE; j++) {
sg_set_buf(sg + j, tvmem[j], PAGE_SIZE);
memset(tvmem[j], 0xff, PAGE_SIZE);
}
iv_len = crypto_ablkcipher_ivsize(tfm);
if (iv_len)
memset(&iv, 0xff, iv_len);
ablkcipher_request_set_crypt(req, sg, sg, *b_size, iv);
if (sec)
ret = test_acipher_jiffies(req, enc,
*b_size, sec);
else
ret = test_acipher_cycles(req, enc,
*b_size);
if (ret) {
pr_err("%s() failed flags=%x\n", e,
crypto_ablkcipher_get_flags(tfm));
break;
}
b_size++;
i++;
} while (*b_size);
keysize++;
} while (*keysize);
out_free_req:
ablkcipher_request_free(req);
out:
crypto_free_ablkcipher(tfm);
}
static void test_available(void)
{
char **name = check;
@@ -789,10 +990,16 @@ static int do_test(int m)
ret += tcrypt_test("ecb(twofish)");
ret += tcrypt_test("cbc(twofish)");
ret += tcrypt_test("ctr(twofish)");
ret += tcrypt_test("lrw(twofish)");
ret += tcrypt_test("xts(twofish)");
break;
case 9:
ret += tcrypt_test("ecb(serpent)");
ret += tcrypt_test("cbc(serpent)");
ret += tcrypt_test("ctr(serpent)");
ret += tcrypt_test("lrw(serpent)");
ret += tcrypt_test("xts(serpent)");
break;
case 10:
@@ -1045,6 +1252,14 @@ static int do_test(int m)
speed_template_16_24_32);
test_cipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_cipher_speed("lrw(twofish)", ENCRYPT, sec, NULL, 0,
speed_template_32_40_48);
test_cipher_speed("lrw(twofish)", DECRYPT, sec, NULL, 0,
speed_template_32_40_48);
test_cipher_speed("xts(twofish)", ENCRYPT, sec, NULL, 0,
speed_template_32_48_64);
test_cipher_speed("xts(twofish)", DECRYPT, sec, NULL, 0,
speed_template_32_48_64);
break;
case 203:
@@ -1089,6 +1304,29 @@ static int do_test(int m)
speed_template_16_32);
break;
case 207:
test_cipher_speed("ecb(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_16_32);
test_cipher_speed("ecb(serpent)", DECRYPT, sec, NULL, 0,
speed_template_16_32);
test_cipher_speed("cbc(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_16_32);
test_cipher_speed("cbc(serpent)", DECRYPT, sec, NULL, 0,
speed_template_16_32);
test_cipher_speed("ctr(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_16_32);
test_cipher_speed("ctr(serpent)", DECRYPT, sec, NULL, 0,
speed_template_16_32);
test_cipher_speed("lrw(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_32_48);
test_cipher_speed("lrw(serpent)", DECRYPT, sec, NULL, 0,
speed_template_32_48);
test_cipher_speed("xts(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_32_64);
test_cipher_speed("xts(serpent)", DECRYPT, sec, NULL, 0,
speed_template_32_64);
break;
case 300:
/* fall through */
@@ -1241,6 +1479,78 @@ static int do_test(int m)
case 499:
break;
case 500:
test_acipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_acipher_speed("ecb(aes)", DECRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_acipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_acipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_acipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
speed_template_32_40_48);
test_acipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
speed_template_32_40_48);
test_acipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0,
speed_template_32_48_64);
test_acipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
speed_template_32_48_64);
test_acipher_speed("ctr(aes)", ENCRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_acipher_speed("ctr(aes)", DECRYPT, sec, NULL, 0,
speed_template_16_24_32);
break;
case 501:
test_acipher_speed("ecb(des3_ede)", ENCRYPT, sec,
des3_speed_template, DES3_SPEED_VECTORS,
speed_template_24);
test_acipher_speed("ecb(des3_ede)", DECRYPT, sec,
des3_speed_template, DES3_SPEED_VECTORS,
speed_template_24);
test_acipher_speed("cbc(des3_ede)", ENCRYPT, sec,
des3_speed_template, DES3_SPEED_VECTORS,
speed_template_24);
test_acipher_speed("cbc(des3_ede)", DECRYPT, sec,
des3_speed_template, DES3_SPEED_VECTORS,
speed_template_24);
break;
case 502:
test_acipher_speed("ecb(des)", ENCRYPT, sec, NULL, 0,
speed_template_8);
test_acipher_speed("ecb(des)", DECRYPT, sec, NULL, 0,
speed_template_8);
test_acipher_speed("cbc(des)", ENCRYPT, sec, NULL, 0,
speed_template_8);
test_acipher_speed("cbc(des)", DECRYPT, sec, NULL, 0,
speed_template_8);
break;
case 503:
test_acipher_speed("ecb(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_16_32);
test_acipher_speed("ecb(serpent)", DECRYPT, sec, NULL, 0,
speed_template_16_32);
test_acipher_speed("cbc(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_16_32);
test_acipher_speed("cbc(serpent)", DECRYPT, sec, NULL, 0,
speed_template_16_32);
test_acipher_speed("ctr(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_16_32);
test_acipher_speed("ctr(serpent)", DECRYPT, sec, NULL, 0,
speed_template_16_32);
test_acipher_speed("lrw(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_32_48);
test_acipher_speed("lrw(serpent)", DECRYPT, sec, NULL, 0,
speed_template_32_48);
test_acipher_speed("xts(serpent)", ENCRYPT, sec, NULL, 0,
speed_template_32_64);
test_acipher_speed("xts(serpent)", DECRYPT, sec, NULL, 0,
speed_template_32_64);
break;
case 1000:
test_available();
break;

View File

@@ -51,7 +51,9 @@ static u8 speed_template_8_32[] = {8, 32, 0};
static u8 speed_template_16_32[] = {16, 32, 0};
static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
static u8 speed_template_32_48[] = {32, 48, 0};
static u8 speed_template_32_48_64[] = {32, 48, 64, 0};
static u8 speed_template_32_64[] = {32, 64, 0};
/*
* Digest speed tests

View File

@@ -1534,6 +1534,21 @@ static int alg_test_null(const struct alg_test_desc *desc,
/* Please keep this list sorted by algorithm name. */
static const struct alg_test_desc alg_test_descs[] = {
{
.alg = "__cbc-serpent-sse2",
.test = alg_test_null,
.suite = {
.cipher = {
.enc = {
.vecs = NULL,
.count = 0
},
.dec = {
.vecs = NULL,
.count = 0
}
}
}
}, {
.alg = "__driver-cbc-aes-aesni",
.test = alg_test_null,
.suite = {
@@ -1548,6 +1563,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "__driver-cbc-serpent-sse2",
.test = alg_test_null,
.suite = {
.cipher = {
.enc = {
.vecs = NULL,
.count = 0
},
.dec = {
.vecs = NULL,
.count = 0
}
}
}
}, {
.alg = "__driver-ecb-aes-aesni",
.test = alg_test_null,
@@ -1563,6 +1593,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "__driver-ecb-serpent-sse2",
.test = alg_test_null,
.suite = {
.cipher = {
.enc = {
.vecs = NULL,
.count = 0
},
.dec = {
.vecs = NULL,
.count = 0
}
}
}
}, {
.alg = "__ghash-pclmulqdqni",
.test = alg_test_null,
@@ -1674,6 +1719,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "cbc(serpent)",
.test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
.vecs = serpent_cbc_enc_tv_template,
.count = SERPENT_CBC_ENC_TEST_VECTORS
},
.dec = {
.vecs = serpent_cbc_dec_tv_template,
.count = SERPENT_CBC_DEC_TEST_VECTORS
}
}
}
}, {
.alg = "cbc(twofish)",
.test = alg_test_skcipher,
@@ -1730,6 +1790,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "cryptd(__driver-ecb-serpent-sse2)",
.test = alg_test_null,
.suite = {
.cipher = {
.enc = {
.vecs = NULL,
.count = 0
},
.dec = {
.vecs = NULL,
.count = 0
}
}
}
}, {
.alg = "cryptd(__ghash-pclmulqdqni)",
.test = alg_test_null,
@@ -1770,6 +1845,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "ctr(serpent)",
.test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
.vecs = serpent_ctr_enc_tv_template,
.count = SERPENT_CTR_ENC_TEST_VECTORS
},
.dec = {
.vecs = serpent_ctr_dec_tv_template,
.count = SERPENT_CTR_DEC_TEST_VECTORS
}
}
}
}, {
.alg = "ctr(twofish)",
.test = alg_test_skcipher,
@@ -2206,6 +2296,36 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "lrw(serpent)",
.test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
.vecs = serpent_lrw_enc_tv_template,
.count = SERPENT_LRW_ENC_TEST_VECTORS
},
.dec = {
.vecs = serpent_lrw_dec_tv_template,
.count = SERPENT_LRW_DEC_TEST_VECTORS
}
}
}
}, {
.alg = "lrw(twofish)",
.test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
.vecs = tf_lrw_enc_tv_template,
.count = TF_LRW_ENC_TEST_VECTORS
},
.dec = {
.vecs = tf_lrw_dec_tv_template,
.count = TF_LRW_DEC_TEST_VECTORS
}
}
}
}, {
.alg = "lzo",
.test = alg_test_comp,
@@ -2513,6 +2633,36 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
}, {
.alg = "xts(serpent)",
.test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
.vecs = serpent_xts_enc_tv_template,
.count = SERPENT_XTS_ENC_TEST_VECTORS
},
.dec = {
.vecs = serpent_xts_dec_tv_template,
.count = SERPENT_XTS_DEC_TEST_VECTORS
}
}
}
}, {
.alg = "xts(twofish)",
.test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
.vecs = tf_xts_enc_tv_template,
.count = TF_XTS_ENC_TEST_VECTORS
},
.dec = {
.vecs = tf_xts_dec_tv_template,
.count = TF_XTS_DEC_TEST_VECTORS
}
}
}
}, {
.alg = "zlib",
.test = alg_test_pcomp,

File diff suppressed because it is too large Load Diff

View File

@@ -580,12 +580,9 @@ static const u8 calc_sb_tbl[512] = {
ctx->a[(j) + 1] = rol32(y, 9)
/* Perform the key setup. */
int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len)
int __twofish_setkey(struct twofish_ctx *ctx, const u8 *key,
unsigned int key_len, u32 *flags)
{
struct twofish_ctx *ctx = crypto_tfm_ctx(tfm);
u32 *flags = &tfm->crt_flags;
int i, j, k;
/* Temporaries for CALC_K. */
@@ -701,7 +698,13 @@ int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len)
return 0;
}
EXPORT_SYMBOL_GPL(__twofish_setkey);
int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len)
{
return __twofish_setkey(crypto_tfm_ctx(tfm), key, key_len,
&tfm->crt_flags);
}
EXPORT_SYMBOL_GPL(twofish_setkey);
MODULE_LICENSE("GPL");

View File

@@ -21,6 +21,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <crypto/xts.h>
#include <crypto/b128ops.h>
#include <crypto/gf128mul.h>
@@ -96,7 +97,7 @@ static int crypt(struct blkcipher_desc *d,
{
int err;
unsigned int avail;
const int bs = crypto_cipher_blocksize(ctx->child);
const int bs = XTS_BLOCK_SIZE;
struct sinfo s = {
.tfm = crypto_cipher_tfm(ctx->child),
.fn = fn
@@ -165,6 +166,78 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
crypto_cipher_alg(ctx->child)->cia_decrypt);
}
int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
struct scatterlist *ssrc, unsigned int nbytes,
struct xts_crypt_req *req)
{
const unsigned int bsize = XTS_BLOCK_SIZE;
const unsigned int max_blks = req->tbuflen / bsize;
struct blkcipher_walk walk;
unsigned int nblocks;
be128 *src, *dst, *t;
be128 *t_buf = req->tbuf;
int err, i;
BUG_ON(max_blks < 1);
blkcipher_walk_init(&walk, sdst, ssrc, nbytes);
err = blkcipher_walk_virt(desc, &walk);
nbytes = walk.nbytes;
if (!nbytes)
return err;
nblocks = min(nbytes / bsize, max_blks);
src = (be128 *)walk.src.virt.addr;
dst = (be128 *)walk.dst.virt.addr;
/* calculate first value of T */
req->tweak_fn(req->tweak_ctx, (u8 *)&t_buf[0], walk.iv);
i = 0;
goto first;
for (;;) {
do {
for (i = 0; i < nblocks; i++) {
gf128mul_x_ble(&t_buf[i], t);
first:
t = &t_buf[i];
/* PP <- T xor P */
be128_xor(dst + i, t, src + i);
}
/* CC <- E(Key2,PP) */
req->crypt_fn(req->crypt_ctx, (u8 *)dst,
nblocks * bsize);
/* C <- T xor CC */
for (i = 0; i < nblocks; i++)
be128_xor(dst + i, dst + i, &t_buf[i]);
src += nblocks;
dst += nblocks;
nbytes -= nblocks * bsize;
nblocks = min(nbytes / bsize, max_blks);
} while (nblocks > 0);
*(be128 *)walk.iv = *t;
err = blkcipher_walk_done(desc, &walk, nbytes);
nbytes = walk.nbytes;
if (!nbytes)
break;
nblocks = min(nbytes / bsize, max_blks);
src = (be128 *)walk.src.virt.addr;
dst = (be128 *)walk.dst.virt.addr;
}
return err;
}
EXPORT_SYMBOL_GPL(xts_crypt);
static int init_tfm(struct crypto_tfm *tfm)
{
struct crypto_cipher *cipher;
@@ -177,7 +250,7 @@ static int init_tfm(struct crypto_tfm *tfm)
if (IS_ERR(cipher))
return PTR_ERR(cipher);
if (crypto_cipher_blocksize(cipher) != 16) {
if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) {
*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
crypto_free_cipher(cipher);
return -EINVAL;
@@ -192,7 +265,7 @@ static int init_tfm(struct crypto_tfm *tfm)
}
/* this check isn't really needed, leave it here just in case */
if (crypto_cipher_blocksize(cipher) != 16) {
if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) {
crypto_free_cipher(cipher);
crypto_free_cipher(ctx->child);
*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;