[PATCH] x86-64: Improve error handling for overlapping PXMs in SRAT.
[pandora-kernel.git] / crypto / tea.c
1 /* 
2  * Cryptographic API.
3  *
4  * TEA, XTEA, and XETA crypto alogrithms
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  * Due to the order of evaluation in XTEA many people have incorrectly
10  * implemented it.  XETA (XTEA in the wrong order), exists for
11  * compatibility with these implementations.
12  *
13  * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  */
21
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/mm.h>
25 #include <asm/scatterlist.h>
26 #include <linux/crypto.h>
27
28 #define TEA_KEY_SIZE            16
29 #define TEA_BLOCK_SIZE          8
30 #define TEA_ROUNDS              32
31 #define TEA_DELTA               0x9e3779b9
32
33 #define XTEA_KEY_SIZE           16
34 #define XTEA_BLOCK_SIZE         8
35 #define XTEA_ROUNDS             32
36 #define XTEA_DELTA              0x9e3779b9
37
38 #define u32_in(x) le32_to_cpu(*(const __le32 *)(x))
39 #define u32_out(to, from) (*(__le32 *)(to) = cpu_to_le32(from))
40
41 struct tea_ctx {
42         u32 KEY[4];
43 };
44
45 struct xtea_ctx {
46         u32 KEY[4];
47 };
48
49 static int tea_setkey(void *ctx_arg, const u8 *in_key,
50                        unsigned int key_len, u32 *flags)
51
52
53         struct tea_ctx *ctx = ctx_arg;
54         
55         if (key_len != 16)
56         {
57                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
58                 return -EINVAL;
59         }
60
61         ctx->KEY[0] = u32_in (in_key);
62         ctx->KEY[1] = u32_in (in_key + 4);
63         ctx->KEY[2] = u32_in (in_key + 8);
64         ctx->KEY[3] = u32_in (in_key + 12);
65
66         return 0; 
67
68 }
69
70 static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
71
72         u32 y, z, n, sum = 0;
73         u32 k0, k1, k2, k3;
74
75         struct tea_ctx *ctx = ctx_arg;
76
77         y = u32_in (src);
78         z = u32_in (src + 4);
79
80         k0 = ctx->KEY[0];
81         k1 = ctx->KEY[1];
82         k2 = ctx->KEY[2];
83         k3 = ctx->KEY[3];
84
85         n = TEA_ROUNDS;
86
87         while (n-- > 0) {
88                 sum += TEA_DELTA;
89                 y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
90                 z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
91         }
92         
93         u32_out (dst, y);
94         u32_out (dst + 4, z);
95 }
96
97 static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
98
99         u32 y, z, n, sum;
100         u32 k0, k1, k2, k3;
101
102         struct tea_ctx *ctx = ctx_arg;
103
104         y = u32_in (src);
105         z = u32_in (src + 4);
106
107         k0 = ctx->KEY[0];
108         k1 = ctx->KEY[1];
109         k2 = ctx->KEY[2];
110         k3 = ctx->KEY[3];
111
112         sum = TEA_DELTA << 5;
113
114         n = TEA_ROUNDS;
115
116         while (n-- > 0) {
117                 z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
118                 y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
119                 sum -= TEA_DELTA;
120         }
121         
122         u32_out (dst, y);
123         u32_out (dst + 4, z);
124
125 }
126
127 static int xtea_setkey(void *ctx_arg, const u8 *in_key,
128                        unsigned int key_len, u32 *flags)
129
130
131         struct xtea_ctx *ctx = ctx_arg;
132         
133         if (key_len != 16)
134         {
135                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
136                 return -EINVAL;
137         }
138
139         ctx->KEY[0] = u32_in (in_key);
140         ctx->KEY[1] = u32_in (in_key + 4);
141         ctx->KEY[2] = u32_in (in_key + 8);
142         ctx->KEY[3] = u32_in (in_key + 12);
143
144         return 0; 
145
146 }
147
148 static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
149
150
151         u32 y, z, sum = 0;
152         u32 limit = XTEA_DELTA * XTEA_ROUNDS;
153
154         struct xtea_ctx *ctx = ctx_arg;
155
156         y = u32_in (src);
157         z = u32_in (src + 4);
158
159         while (sum != limit) {
160                 y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); 
161                 sum += XTEA_DELTA;
162                 z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); 
163         }
164         
165         u32_out (dst, y);
166         u32_out (dst + 4, z);
167
168 }
169
170 static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
171
172
173         u32 y, z, sum;
174         struct tea_ctx *ctx = ctx_arg;
175
176         y = u32_in (src);
177         z = u32_in (src + 4);
178
179         sum = XTEA_DELTA * XTEA_ROUNDS;
180
181         while (sum) {
182                 z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]);
183                 sum -= XTEA_DELTA;
184                 y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]);
185         }
186         
187         u32_out (dst, y);
188         u32_out (dst + 4, z);
189
190 }
191
192
193 static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
194
195
196         u32 y, z, sum = 0;
197         u32 limit = XTEA_DELTA * XTEA_ROUNDS;
198
199         struct xtea_ctx *ctx = ctx_arg;
200
201         y = u32_in (src);
202         z = u32_in (src + 4);
203
204         while (sum != limit) {
205                 y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
206                 sum += XTEA_DELTA;
207                 z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
208         }
209         
210         u32_out (dst, y);
211         u32_out (dst + 4, z);
212
213 }
214
215 static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
216
217
218         u32 y, z, sum;
219         struct tea_ctx *ctx = ctx_arg;
220
221         y = u32_in (src);
222         z = u32_in (src + 4);
223
224         sum = XTEA_DELTA * XTEA_ROUNDS;
225
226         while (sum) {
227                 z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
228                 sum -= XTEA_DELTA;
229                 y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
230         }
231         
232         u32_out (dst, y);
233         u32_out (dst + 4, z);
234
235 }
236
237 static struct crypto_alg tea_alg = {
238         .cra_name               =       "tea",
239         .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
240         .cra_blocksize          =       TEA_BLOCK_SIZE,
241         .cra_ctxsize            =       sizeof (struct tea_ctx),
242         .cra_module             =       THIS_MODULE,
243         .cra_list               =       LIST_HEAD_INIT(tea_alg.cra_list),
244         .cra_u                  =       { .cipher = {
245         .cia_min_keysize        =       TEA_KEY_SIZE,
246         .cia_max_keysize        =       TEA_KEY_SIZE,
247         .cia_setkey             =       tea_setkey,
248         .cia_encrypt            =       tea_encrypt,
249         .cia_decrypt            =       tea_decrypt } }
250 };
251
252 static struct crypto_alg xtea_alg = {
253         .cra_name               =       "xtea",
254         .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
255         .cra_blocksize          =       XTEA_BLOCK_SIZE,
256         .cra_ctxsize            =       sizeof (struct xtea_ctx),
257         .cra_module             =       THIS_MODULE,
258         .cra_list               =       LIST_HEAD_INIT(xtea_alg.cra_list),
259         .cra_u                  =       { .cipher = {
260         .cia_min_keysize        =       XTEA_KEY_SIZE,
261         .cia_max_keysize        =       XTEA_KEY_SIZE,
262         .cia_setkey             =       xtea_setkey,
263         .cia_encrypt            =       xtea_encrypt,
264         .cia_decrypt            =       xtea_decrypt } }
265 };
266
267 static struct crypto_alg xeta_alg = {
268         .cra_name               =       "xeta",
269         .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
270         .cra_blocksize          =       XTEA_BLOCK_SIZE,
271         .cra_ctxsize            =       sizeof (struct xtea_ctx),
272         .cra_module             =       THIS_MODULE,
273         .cra_list               =       LIST_HEAD_INIT(xtea_alg.cra_list),
274         .cra_u                  =       { .cipher = {
275         .cia_min_keysize        =       XTEA_KEY_SIZE,
276         .cia_max_keysize        =       XTEA_KEY_SIZE,
277         .cia_setkey             =       xtea_setkey,
278         .cia_encrypt            =       xeta_encrypt,
279         .cia_decrypt            =       xeta_decrypt } }
280 };
281
282 static int __init init(void)
283 {
284         int ret = 0;
285         
286         ret = crypto_register_alg(&tea_alg);
287         if (ret < 0)
288                 goto out;
289
290         ret = crypto_register_alg(&xtea_alg);
291         if (ret < 0) {
292                 crypto_unregister_alg(&tea_alg);
293                 goto out;
294         }
295
296         ret = crypto_register_alg(&xeta_alg);
297         if (ret < 0) {
298                 crypto_unregister_alg(&tea_alg);
299                 crypto_unregister_alg(&xtea_alg);
300                 goto out;
301         }
302
303 out:    
304         return ret;
305 }
306
307 static void __exit fini(void)
308 {
309         crypto_unregister_alg(&tea_alg);
310         crypto_unregister_alg(&xtea_alg);
311         crypto_unregister_alg(&xeta_alg);
312 }
313
314 MODULE_ALIAS("xtea");
315 MODULE_ALIAS("xeta");
316
317 module_init(init);
318 module_exit(fini);
319
320 MODULE_LICENSE("GPL");
321 MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms");