]> git.hungrycats.org Git - linux/commitdiff
[CRYPTO]: Add TEA and XTEA algorithms.
authorAaron Grothe <ajgrothe@yahoo.com>
Tue, 29 Jun 2004 15:26:40 +0000 (08:26 -0700)
committerDavid S. Miller <davem@nuts.davemloft.net>
Tue, 29 Jun 2004 15:26:40 +0000 (08:26 -0700)
The following is a patch against 2.6.7 (should apply cleanly to 2.6.5 or
above).  It implements the Tiny Encryption Algorithm (TEA) and the
Xtended TEA (XTEA) algorithms.  TEA goes back to 1994 and is a good
algorithm espically for memory constrained systems.  It is similar in
concept to the IDEA crypto.  It does NOT have any patent restrictions
and has been put in the public domain by Wheeler and Needham.  Tea is used
in quite a few products such as filesafe and even Microsoft's Xbox.

Signed-off-by: Aaron Grothe <ajgrothe@yahoo.com>
Signed-off-by: James Morris <jmorris@redhat.com>
Signed-off-by: David S. Miller <davem@redhat.com>
crypto/Kconfig
crypto/Makefile
crypto/tcrypt.c
crypto/tcrypt.h
crypto/tea.c [new file with mode: 0644]

index d0ed3ce3e0913743d3cecbc3d13a12dff935c26a..de13d3ffb7feceffff22a144a2b2541c1d7ef107 100644 (file)
@@ -152,6 +152,20 @@ config CRYPTO_CAST6
          The CAST6 encryption algorithm (synonymous with CAST-256) is
          described in RFC2612.
 
+config CRYPTO_TEA
+       tristate "TEA and XTEA cipher algorithms"
+       depends on CRYPTO
+       help
+         TEA cipher algorithm.
+
+         Tiny Encryption Algorithm is a simple cipher that uses
+         many rounds for security.  It is very fast and uses
+         little memory.
+
+         Xtendend Tiny Encryption Algorithm is a modifcation to
+         the TEA algorithm to address a potential key weakness
+         in the TEA algorithm.
+
 config CRYPTO_ARC4
        tristate "ARC4 cipher algorithm"
        depends on CRYPTO
index 105429fd288e2075a8f352c2c32835ff9b05ad61..f9310ae44741a9365173ec0280674eea2b53fd3b 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
+obj-$(CONFIG_CRYPTO_TEA) += tea.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
index 152ad41ce235a03e12558b01ee35bb332946e25a..2124e23382d0a79735a702aabc579af8e972c0e3 100644 (file)
@@ -61,7 +61,7 @@ static char *tvmem;
 static char *check[] = {
        "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
        "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-       "arc4", "michael_mic", "deflate", "crc32c", NULL
+       "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", NULL
 };
 
 static void
@@ -665,6 +665,15 @@ do_test(void)
                test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
                test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
 
+               //TEA
+               test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS);
+               test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS);
+
+
+               //XTEA
+               test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
+               test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
+
                test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
                test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
                test_deflate();
@@ -763,6 +772,16 @@ do_test(void)
                test_crc32c();
                break;
 
+       case 19:
+               test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS);
+               test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS);
+               break;
+
+       case 20:
+               test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
+               test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
+               break;
+
 #ifdef CONFIG_CRYPTO_HMAC
        case 100:
                test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
index 43563450c9c40341002c415efd5fec4fa27f421e..4f514295355edcaccd3029d3bbc2db3811b69b14 100644 (file)
@@ -1630,6 +1630,195 @@ struct cipher_testvec arc4_dec_tv_template[] =
        },
 };
 
+/* 
+ * TEA test vectors
+ */
+#define TEA_ENC_TEST_VECTORS   4
+#define TEA_DEC_TEST_VECTORS   4
+
+struct cipher_testvec tea_enc_tv_template[] =
+{
+       {
+               .key    = { [0 ... 15] = 0x00 },
+               .klen   = 16,
+               .input  = { [0 ... 8] = 0x00 },
+               .ilen   = 8,
+               .result = { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+                           0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+               .klen   = 16,
+               .input  = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+               .ilen   = 8,
+               .result = { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+                           0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+               .klen   = 16,
+               .input  = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+                           0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+               .ilen   = 16,
+               .result = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e, 
+                           0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+               .rlen   = 16,
+       }, {
+               .key    = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+                           0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+               .klen   = 16,
+               .input  = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+                           0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+                           0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+                           0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+               .ilen   = 32,
+               .result = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47, 
+                           0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8, 
+                           0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a, 
+                           0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+               .rlen   = 32,
+       }
+};
+
+struct cipher_testvec tea_dec_tv_template[] =
+{
+       {
+               .key    = { [0 ... 15] = 0x00 },
+               .klen   = 16,
+               .input  = { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
+               .ilen   = 8,
+               .result = { [0 ... 8] = 0x00 },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+                           0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+               .klen   = 16,
+               .input  = { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
+               .ilen   = 8,
+               .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+                           0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+               .klen   = 16,
+               .input  = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+                            0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+                .ilen   = 16,
+               .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+                           0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+               .rlen   = 16,
+       }, {
+               .key    = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+                           0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+               .klen   = 16,
+               .input  = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+                            0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+                            0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+                            0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+               .ilen   = 32,
+               .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+                           0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+                           0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+                           0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+               .rlen   = 32,
+       }
+};
+
+/* 
+ * XTEA test vectors 
+ */
+#define XTEA_ENC_TEST_VECTORS  4
+#define XTEA_DEC_TEST_VECTORS  4
+
+struct cipher_testvec xtea_enc_tv_template[] =
+{
+       {
+               .key    = { [0 ... 15] = 0x00 },
+               .klen   = 16,
+               .input  = { [0 ... 8] = 0x00 },
+               .ilen   = 8,
+               .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+                           0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+               .klen   = 16,
+               .input  = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+               .ilen   = 8,
+               .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+                           0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+               .klen   = 16,
+               .input  = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+                           0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+               .ilen   = 16,
+               .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+                           0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+               .rlen   = 16,
+       }, {
+               .key    = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+                           0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+               .klen   = 16,
+               .input  = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+                           0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+                           0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+                           0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+               .ilen   = 32,
+               .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+                           0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+                           0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+                           0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+               .rlen   = 32,
+       }
+};
+
+struct cipher_testvec xtea_dec_tv_template[] =
+{
+       {
+               .key    = { [0 ... 15] = 0x00 },
+               .klen   = 16,
+               .input  = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+               .ilen   = 8,
+               .result = { [0 ... 8] = 0x00 },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+                           0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+               .klen   = 16,
+               .input  = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+               .ilen   = 8,
+               .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+               .rlen   = 8,
+       }, {
+               .key    = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+                           0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+               .klen   = 16,
+               .input  = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+                           0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+               .ilen   = 16,
+               .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+                           0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+               .rlen   = 16,
+       }, {
+               .key    = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+                           0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+               .klen   = 16,
+               .input  = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+                           0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+                           0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+                           0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+               .ilen   = 32,
+               .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+                           0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+                           0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+                           0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+               .rlen   = 32,
+       }
+};
+
+
 
 /*
  * Compression stuff.
@@ -1771,4 +1960,5 @@ struct hash_testvec michael_mic_tv_template[] =
                .digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
        }
 };
+
 #endif /* _CRYPTO_TCRYPT_H */
diff --git a/crypto/tea.c b/crypto/tea.c
new file mode 100644 (file)
index 0000000..bf94329
--- /dev/null
@@ -0,0 +1,248 @@
+/* 
+ * Cryptographic API.
+ *
+ * TEA and Xtended TEA Algorithms
+ *
+ * The TEA and Xtended TEA algorithms were developed by David Wheeler 
+ * and Roger Needham at the Computer Laboratory of Cambridge University.
+ *
+ * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define TEA_KEY_SIZE           16
+#define TEA_BLOCK_SIZE         8
+#define TEA_ROUNDS             32
+#define TEA_DELTA              0x9e3779b9
+
+#define XTEA_KEY_SIZE          16
+#define XTEA_BLOCK_SIZE                8
+#define XTEA_ROUNDS            32
+#define XTEA_DELTA             0x9e3779b9
+
+#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+
+struct tea_ctx {
+       u32 KEY[4];
+};
+
+struct xtea_ctx {
+       u32 KEY[4];
+};
+
+static int tea_setkey(void *ctx_arg, const u8 *in_key,
+                       unsigned int key_len, u32 *flags)
+{ 
+
+       struct tea_ctx *ctx = ctx_arg;
+       
+       if (key_len != 16)
+       {
+               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+
+       ctx->KEY[0] = u32_in (in_key);
+       ctx->KEY[1] = u32_in (in_key + 4);
+       ctx->KEY[2] = u32_in (in_key + 8);
+       ctx->KEY[3] = u32_in (in_key + 12);
+
+       return 0; 
+
+}
+
+static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+       u32 y, z, n, sum = 0;
+       u32 k0, k1, k2, k3;
+
+       struct tea_ctx *ctx = ctx_arg;
+
+       y = u32_in (src);
+       z = u32_in (src + 4);
+
+       k0 = ctx->KEY[0];
+       k1 = ctx->KEY[1];
+       k2 = ctx->KEY[2];
+       k3 = ctx->KEY[3];
+
+       n = TEA_ROUNDS;
+
+       while (n-- > 0) {
+               sum += TEA_DELTA;
+               y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
+               z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
+       }
+       
+       u32_out (dst, y);
+       u32_out (dst + 4, z);
+}
+
+static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+       u32 y, z, n, sum;
+       u32 k0, k1, k2, k3;
+
+       struct tea_ctx *ctx = ctx_arg;
+
+       y = u32_in (src);
+       z = u32_in (src + 4);
+
+       k0 = ctx->KEY[0];
+       k1 = ctx->KEY[1];
+       k2 = ctx->KEY[2];
+       k3 = ctx->KEY[3];
+
+       sum = TEA_DELTA << 5;
+
+       n = TEA_ROUNDS;
+
+       while (n-- > 0) {
+               z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
+               y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
+               sum -= TEA_DELTA;
+       }
+       
+       u32_out (dst, y);
+       u32_out (dst + 4, z);
+
+}
+
+static int xtea_setkey(void *ctx_arg, const u8 *in_key,
+                       unsigned int key_len, u32 *flags)
+{ 
+
+       struct xtea_ctx *ctx = ctx_arg;
+       
+       if (key_len != 16)
+       {
+               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+
+       ctx->KEY[0] = u32_in (in_key);
+       ctx->KEY[1] = u32_in (in_key + 4);
+       ctx->KEY[2] = u32_in (in_key + 8);
+       ctx->KEY[3] = u32_in (in_key + 12);
+
+       return 0; 
+
+}
+
+static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+
+       u32 y, z, sum = 0;
+       u32 limit = XTEA_DELTA * XTEA_ROUNDS;
+
+       struct xtea_ctx *ctx = ctx_arg;
+
+       y = u32_in (src);
+       z = u32_in (src + 4);
+
+       while (sum != limit) {
+               y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
+               sum += TEA_DELTA;
+               z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
+       }
+       
+       u32_out (dst, y);
+       u32_out (dst + 4, z);
+
+}
+
+static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+
+       u32 y, z, sum;
+       struct tea_ctx *ctx = ctx_arg;
+
+       y = u32_in (src);
+       z = u32_in (src + 4);
+
+       sum = XTEA_DELTA * XTEA_ROUNDS;
+
+       while (sum) {
+               z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
+               sum -= XTEA_DELTA;
+               y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
+       }
+       
+       u32_out (dst, y);
+       u32_out (dst + 4, z);
+
+}
+
+static struct crypto_alg tea_alg = {
+       .cra_name               =       "tea",
+       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
+       .cra_blocksize          =       TEA_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof (struct tea_ctx),
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(tea_alg.cra_list),
+       .cra_u                  =       { .cipher = {
+       .cia_min_keysize        =       TEA_KEY_SIZE,
+       .cia_max_keysize        =       TEA_KEY_SIZE,
+       .cia_setkey             =       tea_setkey,
+       .cia_encrypt            =       tea_encrypt,
+       .cia_decrypt            =       tea_decrypt } }
+};
+
+static struct crypto_alg xtea_alg = {
+       .cra_name               =       "xtea",
+       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
+       .cra_blocksize          =       XTEA_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof (struct xtea_ctx),
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(xtea_alg.cra_list),
+       .cra_u                  =       { .cipher = {
+       .cia_min_keysize        =       XTEA_KEY_SIZE,
+       .cia_max_keysize        =       XTEA_KEY_SIZE,
+       .cia_setkey             =       xtea_setkey,
+       .cia_encrypt            =       xtea_encrypt,
+       .cia_decrypt            =       xtea_decrypt } }
+};
+
+static int __init init(void)
+{
+       int ret = 0;
+       
+       ret = crypto_register_alg(&tea_alg);
+       if (ret < 0)
+               goto out;
+
+       ret = crypto_register_alg(&xtea_alg);
+       if (ret < 0) {
+               crypto_unregister_alg(&tea_alg);
+               goto out;
+       }
+
+out:   
+       return ret;
+}
+
+static void __exit fini(void)
+{
+       crypto_unregister_alg(&tea_alg);
+       crypto_unregister_alg(&xtea_alg);
+}
+
+MODULE_ALIAS("xtea");
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");