Merge /spare/repo/linux-2.6/
[linux-2.6] / crypto / tea.c
1 /* 
2  * Cryptographic API.
3  *
4  * TEA and Xtended TEA Algorithms
5  *
6  * The TEA and Xtended TEA algorithms were developed by David Wheeler 
7  * and Roger Needham at the Computer Laboratory of Cambridge University.
8  *
9  * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  */
17
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/mm.h>
21 #include <asm/scatterlist.h>
22 #include <linux/crypto.h>
23
24 #define TEA_KEY_SIZE            16
25 #define TEA_BLOCK_SIZE          8
26 #define TEA_ROUNDS              32
27 #define TEA_DELTA               0x9e3779b9
28
29 #define XTEA_KEY_SIZE           16
30 #define XTEA_BLOCK_SIZE         8
31 #define XTEA_ROUNDS             32
32 #define XTEA_DELTA              0x9e3779b9
33
34 #define u32_in(x) le32_to_cpu(*(const __le32 *)(x))
35 #define u32_out(to, from) (*(__le32 *)(to) = cpu_to_le32(from))
36
37 struct tea_ctx {
38         u32 KEY[4];
39 };
40
41 struct xtea_ctx {
42         u32 KEY[4];
43 };
44
45 static int tea_setkey(void *ctx_arg, const u8 *in_key,
46                        unsigned int key_len, u32 *flags)
47
48
49         struct tea_ctx *ctx = ctx_arg;
50         
51         if (key_len != 16)
52         {
53                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
54                 return -EINVAL;
55         }
56
57         ctx->KEY[0] = u32_in (in_key);
58         ctx->KEY[1] = u32_in (in_key + 4);
59         ctx->KEY[2] = u32_in (in_key + 8);
60         ctx->KEY[3] = u32_in (in_key + 12);
61
62         return 0; 
63
64 }
65
66 static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
67
68         u32 y, z, n, sum = 0;
69         u32 k0, k1, k2, k3;
70
71         struct tea_ctx *ctx = ctx_arg;
72
73         y = u32_in (src);
74         z = u32_in (src + 4);
75
76         k0 = ctx->KEY[0];
77         k1 = ctx->KEY[1];
78         k2 = ctx->KEY[2];
79         k3 = ctx->KEY[3];
80
81         n = TEA_ROUNDS;
82
83         while (n-- > 0) {
84                 sum += TEA_DELTA;
85                 y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
86                 z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
87         }
88         
89         u32_out (dst, y);
90         u32_out (dst + 4, z);
91 }
92
93 static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
94
95         u32 y, z, n, sum;
96         u32 k0, k1, k2, k3;
97
98         struct tea_ctx *ctx = ctx_arg;
99
100         y = u32_in (src);
101         z = u32_in (src + 4);
102
103         k0 = ctx->KEY[0];
104         k1 = ctx->KEY[1];
105         k2 = ctx->KEY[2];
106         k3 = ctx->KEY[3];
107
108         sum = TEA_DELTA << 5;
109
110         n = TEA_ROUNDS;
111
112         while (n-- > 0) {
113                 z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
114                 y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
115                 sum -= TEA_DELTA;
116         }
117         
118         u32_out (dst, y);
119         u32_out (dst + 4, z);
120
121 }
122
123 static int xtea_setkey(void *ctx_arg, const u8 *in_key,
124                        unsigned int key_len, u32 *flags)
125
126
127         struct xtea_ctx *ctx = ctx_arg;
128         
129         if (key_len != 16)
130         {
131                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
132                 return -EINVAL;
133         }
134
135         ctx->KEY[0] = u32_in (in_key);
136         ctx->KEY[1] = u32_in (in_key + 4);
137         ctx->KEY[2] = u32_in (in_key + 8);
138         ctx->KEY[3] = u32_in (in_key + 12);
139
140         return 0; 
141
142 }
143
144 static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
145
146
147         u32 y, z, sum = 0;
148         u32 limit = XTEA_DELTA * XTEA_ROUNDS;
149
150         struct xtea_ctx *ctx = ctx_arg;
151
152         y = u32_in (src);
153         z = u32_in (src + 4);
154
155         while (sum != limit) {
156                 y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
157                 sum += XTEA_DELTA;
158                 z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
159         }
160         
161         u32_out (dst, y);
162         u32_out (dst + 4, z);
163
164 }
165
166 static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
167
168
169         u32 y, z, sum;
170         struct tea_ctx *ctx = ctx_arg;
171
172         y = u32_in (src);
173         z = u32_in (src + 4);
174
175         sum = XTEA_DELTA * XTEA_ROUNDS;
176
177         while (sum) {
178                 z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
179                 sum -= XTEA_DELTA;
180                 y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
181         }
182         
183         u32_out (dst, y);
184         u32_out (dst + 4, z);
185
186 }
187
188 static struct crypto_alg tea_alg = {
189         .cra_name               =       "tea",
190         .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
191         .cra_blocksize          =       TEA_BLOCK_SIZE,
192         .cra_ctxsize            =       sizeof (struct tea_ctx),
193         .cra_module             =       THIS_MODULE,
194         .cra_list               =       LIST_HEAD_INIT(tea_alg.cra_list),
195         .cra_u                  =       { .cipher = {
196         .cia_min_keysize        =       TEA_KEY_SIZE,
197         .cia_max_keysize        =       TEA_KEY_SIZE,
198         .cia_setkey             =       tea_setkey,
199         .cia_encrypt            =       tea_encrypt,
200         .cia_decrypt            =       tea_decrypt } }
201 };
202
203 static struct crypto_alg xtea_alg = {
204         .cra_name               =       "xtea",
205         .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
206         .cra_blocksize          =       XTEA_BLOCK_SIZE,
207         .cra_ctxsize            =       sizeof (struct xtea_ctx),
208         .cra_module             =       THIS_MODULE,
209         .cra_list               =       LIST_HEAD_INIT(xtea_alg.cra_list),
210         .cra_u                  =       { .cipher = {
211         .cia_min_keysize        =       XTEA_KEY_SIZE,
212         .cia_max_keysize        =       XTEA_KEY_SIZE,
213         .cia_setkey             =       xtea_setkey,
214         .cia_encrypt            =       xtea_encrypt,
215         .cia_decrypt            =       xtea_decrypt } }
216 };
217
218 static int __init init(void)
219 {
220         int ret = 0;
221         
222         ret = crypto_register_alg(&tea_alg);
223         if (ret < 0)
224                 goto out;
225
226         ret = crypto_register_alg(&xtea_alg);
227         if (ret < 0) {
228                 crypto_unregister_alg(&tea_alg);
229                 goto out;
230         }
231
232 out:    
233         return ret;
234 }
235
236 static void __exit fini(void)
237 {
238         crypto_unregister_alg(&tea_alg);
239         crypto_unregister_alg(&xtea_alg);
240 }
241
242 MODULE_ALIAS("xtea");
243
244 module_init(init);
245 module_exit(fini);
246
247 MODULE_LICENSE("GPL");
248 MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");