better standard compliance
[rofl0r-kripto.git] / lib / block / xtea.c
blob61c4f52ccd39d9f9e442eae9cbf2e46d1799af15
1 /*
2 * Copyright (C) 2013 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
15 /* this XTEA implementation is big endian */
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <limits.h>
21 #include <kripto/cast.h>
22 #include <kripto/loadstore.h>
23 #include <kripto/rotate.h>
24 #include <kripto/memwipe.h>
25 #include <kripto/block.h>
26 #include <kripto/desc/block.h>
27 #include <kripto/object/block.h>
29 #include <kripto/block/xtea.h>
31 struct kripto_block
33 struct kripto_block_object obj;
34 unsigned int rounds;
35 size_t size;
36 uint32_t *k;
39 static void xtea_setup
41 kripto_block *s,
42 const uint8_t *key,
43 unsigned int key_len
46 uint32_t c = 0;
47 uint32_t k[4] = {0, 0, 0, 0};
48 unsigned int i;
50 /* big endian */
51 for(i = 0; i < key_len; i++)
52 k[i >> 2] |= key[i] << (24 - ((i & 3) << 3));
54 key_len = (key_len + 3) >> 2;
55 i = 0;
56 while(i < s->rounds)
58 s->k[i++] = c + k[c % key_len];
59 if(i == s->rounds) break;
60 c += 0x9E3779B9;
61 s->k[i++] = c + k[(c >> 11) % key_len];
64 kripto_memwipe(k, 16);
67 #define F(X) ((((X) << 4) ^ ((X) >> 5)) + (X))
69 static void xtea_encrypt(const kripto_block *s, const void *pt, void *ct)
71 uint32_t x0 = LOAD32B(CU8(pt));
72 uint32_t x1 = LOAD32B(CU8(pt) + 4);
73 unsigned int i = 0;
75 while(i < s->rounds)
77 x0 += F(x1) ^ s->k[i++];
79 if(i == s->rounds) break;
81 x1 += F(x0) ^ s->k[i++];
84 STORE32B(x0, U8(ct));
85 STORE32B(x1, U8(ct) + 4);
88 static void xtea_decrypt(const kripto_block *s, const void *ct, void *pt)
90 uint32_t x0 = LOAD32B(CU8(ct));
91 uint32_t x1 = LOAD32B(CU8(ct) + 4);
92 unsigned int i = s->rounds - 1;
94 while(i != UINT_MAX)
96 x1 -= F(x0) ^ s->k[i--];
98 if(i == UINT_MAX) break;
100 x0 -= F(x1) ^ s->k[i--];
103 STORE32B(x0, U8(pt));
104 STORE32B(x1, U8(pt) + 4);
107 static kripto_block *xtea_create
109 unsigned int r,
110 const void *key,
111 unsigned int key_len
114 kripto_block *s;
116 if(!r) r = 64;
118 s = malloc(sizeof(kripto_block) + (r << 2));
119 if(!s) return 0;
121 s->obj.desc = kripto_block_xtea;
122 s->size = sizeof(kripto_block) + (r << 2);
123 s->rounds = r;
124 s->k = (uint32_t *)((uint8_t *)s + sizeof(kripto_block));
126 xtea_setup(s, key, key_len);
128 return s;
131 static void xtea_destroy(kripto_block *s)
133 kripto_memwipe(s, s->size);
134 free(s);
137 static kripto_block *xtea_recreate
139 kripto_block *s,
140 unsigned int r,
141 const void *key,
142 unsigned int key_len
145 if(!r) r = 64;
147 if(sizeof(kripto_block) + (r << 2) > s->size)
149 xtea_destroy(s);
150 s = xtea_create(r, key, key_len);
152 else
154 s->rounds = r;
155 xtea_setup(s, key, key_len);
158 return s;
161 static const kripto_block_desc xtea =
163 &xtea_create,
164 &xtea_recreate,
166 &xtea_encrypt,
167 &xtea_decrypt,
168 &xtea_destroy,
169 8, /* block size */
170 16 /* max key */
173 const kripto_block_desc *const kripto_block_xtea = &xtea;