--- serpent.c?rev=1.1.2.1	2003-12-19 12:58:27.119527344 +0100
+++ serpent.c	2003-12-19 12:58:52.925604224 +0100
@@ -4,6 +4,7 @@
  * Serpent Cipher Algorithm.
  *
  * Copyright (C) 2002 Dag Arne Osvik <osvik@ii.uib.no>
+ *               2003 Herbert Valerio Riedel <hvr@gnu.org>
  *
  * 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
@@ -211,7 +212,7 @@
 	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;
@@ -361,7 +362,7 @@
 	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,
@@ -419,7 +420,7 @@
 	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,
@@ -483,18 +484,102 @@
 	.cia_min_keysize	=	SERPENT_MIN_KEY_SIZE,
 	.cia_max_keysize	=	SERPENT_MAX_KEY_SIZE,
 	.cia_ivsize		=	SERPENT_BLOCK_SIZE,
-	.cia_setkey   		= 	setkey,
-	.cia_encrypt 		=	encrypt,
-	.cia_decrypt  		=	decrypt } }
+	.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)
+{
+	if ((keylen < SERPENT_MIN_KEY_SIZE)
+	    || (keylen > SERPENT_MAX_KEY_SIZE)) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	} else {
+		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(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_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_ivsize		=	SERPENT_BLOCK_SIZE,
+	.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 < 0)
+		return ret;
+
+	ret = crypto_register_alg(&tnepres_alg);
+
+	if (ret < 0)
+		crypto_unregister_alg(&serpent_alg);
+
+	return ret;
 }
 
 static void __exit fini(void)
 {
+	crypto_unregister_alg(&tnepres_alg);
 	crypto_unregister_alg(&serpent_alg);
 }
 
