* 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
#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_BLOCK_SIZE 16
#define PHI 0x9e3779b9UL
-#define ROL(x,r) ((x) = ((x) << (r)) | ((x) >> (32-(r))))
-#define ROR(x,r) ((x) = ((x) >> (r)) | ((x) << (32-(r))))
#define keyiter(a,b,c,d,i,j) \
- b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; ROL(b,11); k[j] = b;
+ 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];
x1 ^= k[4*(i)+1]; x0 ^= k[4*(i)+0];
#define LK(x0,x1,x2,x3,x4,i) \
- ROL(x0,13); \
- ROL(x2,3); x1 ^= x0; x4 = x0 << 3; \
+ x0=rol32(x0,13);\
+ x2=rol32(x2,3); x1 ^= x0; x4 = x0 << 3; \
x3 ^= x2; x1 ^= x2; \
- ROL(x1,1); x3 ^= x4; \
- ROL(x3,7); x4 = x1; \
+ 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]; ROL(x0,5); ROL(x2,22); \
+ 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]; ROR(x0,5); ROR(x2,22); \
+ x3 ^= k[4*i+3]; x0=ror32(x0,5); x2=ror32(x2,22);\
x4 = x1; x2 ^= x3; x0 ^= x3; \
- x4 <<= 7; x0 ^= x1; ROR(x1,1); \
- x2 ^= x4; ROR(x3,7); x4 = x0 << 3; \
- x1 ^= x0; x3 ^= x4; ROR(x0,13); \
- x1 ^= x2; x3 ^= x2; ROR(x2,3);
+ 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; \
x4 ^= x2;
struct serpent_ctx {
- u8 iv[SERPENT_BLOCK_SIZE];
u32 expkey[SERPENT_EXPKEY_WORDS];
};
-static int setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+
+static int serpent_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
{
u32 *k = ((struct serpent_ctx *)ctx)->expkey;
u8 *k8 = (u8 *)k;
return 0;
}
-static void encrypt(void *ctx, u8 *dst, const u8 *src)
+static void serpent_encrypt(void *ctx, u8 *dst, const u8 *src)
{
const u32
*k = ((struct serpent_ctx *)ctx)->expkey,
d[3] = cpu_to_le32(r3);
}
-static void decrypt(void *ctx, u8 *dst, const u8 *src)
+static void serpent_decrypt(void *ctx, u8 *dst, const u8 *src)
{
const u32
*k = ((struct serpent_ctx *)ctx)->expkey,
.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(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+{
+ u8 rev_key[SERPENT_MAX_KEY_SIZE];
+ int i;
+
+ if ((keylen < SERPENT_MIN_KEY_SIZE)
+ || (keylen > SERPENT_MAX_KEY_SIZE)) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < keylen; ++i)
+ rev_key[keylen - i - 1] = key[i];
+
+ return serpent_setkey(ctx, rev_key, keylen, flags);
+}
+
+static void tnepres_encrypt(void *ctx, 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(ctx, (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(void *ctx, 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(ctx, (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 = setkey,
- .cia_encrypt = encrypt,
- .cia_decrypt = decrypt } }
+ .cia_setkey = tnepres_setkey,
+ .cia_encrypt = tnepres_encrypt,
+ .cia_decrypt = tnepres_decrypt } }
};
static int __init init(void)
{
- return crypto_register_alg(&serpent_alg);
+ 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 fini(void)
{
+ crypto_unregister_alg(&tnepres_alg);
crypto_unregister_alg(&serpent_alg);
}
module_exit(fini);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Serpent Cipher Algorithm");
+MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm");
MODULE_AUTHOR("Dag Arne Osvik <osvik@ii.uib.no>");
+MODULE_ALIAS("tnepres");