multof moved from descriptor to object
[rofl0r-kripto.git] / lib / stream / skein512.c
blob18759646840469bb83f682da8bda39b53c38545a
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 #include <stdint.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <limits.h>
19 #include <assert.h>
21 #include <kripto/cast.h>
22 #include <kripto/loadstore.h>
23 #include <kripto/memwipe.h>
24 #include <kripto/block.h>
25 #include <kripto/block/threefish512.h>
26 #include <kripto/stream.h>
27 #include <kripto/desc/stream.h>
28 #include <kripto/object/stream.h>
30 #include <kripto/stream/skein512.h>
32 struct kripto_stream
34 struct kripto_stream_object obj;
35 kripto_block *block;
36 unsigned int r;
37 unsigned int i;
38 uint8_t ctr[64];
39 uint8_t buf[64];
42 #define POS_ADD(TWEAK, ADD) \
43 { \
44 TWEAK[0] += ADD; \
45 if(!TWEAK[0]) \
46 if(!++TWEAK[1]) \
47 if(!++TWEAK[2]) \
48 if(!++TWEAK[3]) \
49 if(!++TWEAK[4]) \
50 if(!++TWEAK[5]) \
51 if(!++TWEAK[6]) \
52 if(!++TWEAK[7]) \
53 if(!++TWEAK[8]) \
54 if(!++TWEAK[9]) \
55 if(!++TWEAK[10]) \
56 { \
57 TWEAK[11]++; \
58 assert(TWEAK[11]); \
59 } \
62 static kripto_stream *skein512_recreate
64 kripto_stream *s,
65 unsigned int r,
66 const void *key,
67 unsigned int key_len,
68 const void *iv,
69 unsigned int iv_len
72 uint8_t tweak[16];
73 uint8_t k[64];
74 unsigned int block;
75 unsigned int i;
77 s->r = r;
78 s->i = 0;
79 memset(k, 0, 64);
80 memset(s->ctr, 0, 64);
82 /* KEY */
83 memset(tweak, 0, 16);
84 tweak[15] = 0x40; /* type KEY, first */
86 while(key_len)
88 if(key_len > 64) block = 64;
89 else block = key_len;
91 memcpy(s->buf, key, block);
92 memset(s->buf, 0, 64 - block);
94 POS_ADD(tweak, block);
96 key_len -= block;
98 if(!key_len) tweak[15] |= 0x80; /* add final */
100 /* process */
101 (void)kripto_block_recreate(s->block, s->r, k, 64);
102 kripto_block_tweak(s->block, tweak, 16);
103 kripto_block_encrypt(s->block, s->buf, k);
104 for(i = 0; i < 64; i++) k[i] ^= s->buf[i];
106 tweak[15] &= 0xBF; /* remove first */
109 /* CFG */
110 s->buf[0] = 'S';
111 s->buf[1] = 'H';
112 s->buf[2] = 'A';
113 s->buf[3] = '3';
114 s->buf[4] = 1;
115 s->buf[5] = 0;
116 s->buf[6] = 0;
117 s->buf[7] = 0;
118 memset(s->buf + 8, 0xFF, 8); /* output UINT64_MAX */
119 memset(s->buf + 16, 0, 48);
120 memset(tweak, 0, 12);
121 tweak[0] = 32;
122 tweak[15] = 0xC4; /* type CFG, first, final */
124 /* process */
125 (void)kripto_block_recreate(s->block, s->r, k, 64);
126 kripto_block_tweak(s->block, tweak, 16);
127 kripto_block_encrypt(s->block, s->buf, k);
128 for(i = 0; i < 64; i++) k[i] ^= s->buf[i];
130 /* NONCE */
131 memset(tweak, 0, 12);
132 tweak[15] = 0x54; /* type NONCE, first */
134 while(iv_len)
136 if(iv_len > 64) block = 64;
137 else block = iv_len;
139 memcpy(s->buf, iv, block);
140 memset(s->buf, 0, 64 - block);
142 POS_ADD(tweak, block);
144 iv_len -= block;
146 if(!iv_len) tweak[15] |= 0x80; /* add final */
148 /* process */
149 (void)kripto_block_recreate(s->block, s->r, k, 64);
150 kripto_block_tweak(s->block, tweak, 16);
151 kripto_block_encrypt(s->block, s->buf, k);
152 for(i = 0; i < 64; i++) k[i] ^= s->buf[i];
154 tweak[15] &= 0xBF; /* remove first */
157 /* final setup */
158 (void)kripto_block_recreate(s->block, s->r, k, 64);
159 memset(tweak, 0, 12);
160 tweak[0] = 8; /* 8 byte counter */
161 tweak[15] = 0xFF; /* type OUTPUT, first, final */
162 kripto_block_tweak(s->block, tweak, 16);
164 kripto_memwipe(k, 64);
166 return s;
169 static void skein512_crypt
171 kripto_stream *s,
172 const void *in,
173 void *out,
174 size_t len
177 size_t i;
179 for(i = 0; i < len; i++)
181 if(s->i == 64)
183 kripto_block_encrypt(s->block, s->ctr, s->buf);
184 for(s->i = 0; s->i < 64; s->i++)
185 s->buf[s->i] ^= s->ctr[s->i];
187 if(!++s->ctr[0])
188 if(!++s->ctr[1])
189 if(!++s->ctr[2])
190 if(!++s->ctr[3])
191 if(!++s->ctr[4])
192 if(!++s->ctr[5])
193 if(!++s->ctr[6])
195 s->ctr[7]++;
196 assert(s->ctr[7]);
199 s->i = 0;
202 U8(out)[i] = CU8(in)[i] ^ s->buf[s->i++];
206 static void skein512_prng(kripto_stream *s, void *out, size_t len)
208 size_t i;
210 for(i = 0; i < len; i++)
212 if(s->i == 64)
214 kripto_block_encrypt(s->block, s->ctr, s->buf);
215 for(s->i = 0; s->i < 64; s->i++)
216 s->buf[s->i] ^= s->ctr[s->i];
218 if(!++s->ctr[0])
219 if(!++s->ctr[1])
220 if(!++s->ctr[2])
221 if(!++s->ctr[3])
222 if(!++s->ctr[4])
223 if(!++s->ctr[5])
224 if(!++s->ctr[6])
226 s->ctr[7]++;
227 assert(s->ctr[7]);
230 s->i = 0;
233 U8(out)[i] = s->buf[s->i++];
237 static kripto_stream *skein512_create
239 const kripto_stream_desc *desc,
240 unsigned int r,
241 const void *key,
242 unsigned int key_len,
243 const void *iv,
244 unsigned int iv_len
247 kripto_stream *s;
249 (void)desc;
251 s = malloc(sizeof(kripto_stream));
252 if(!s) return 0;
254 s->obj.desc = kripto_stream_skein512;
255 s->obj.multof = 1;
257 s->block = kripto_block_create(kripto_block_threefish512, r, "", 1);
258 if(!s->block)
260 free(s);
261 return 0;
264 (void)skein512_recreate(s, r, key, key_len, iv, iv_len);
266 return s;
269 static void skein512_destroy(kripto_stream *s)
271 kripto_block_destroy(s->block);
272 kripto_memwipe(s, sizeof(kripto_stream));
273 free(s);
276 static const kripto_stream_desc skein512 =
278 &skein512_create,
279 &skein512_recreate,
280 &skein512_crypt,
281 &skein512_crypt,
282 &skein512_prng,
283 &skein512_destroy,
284 UINT_MAX, /* max key */
285 UINT_MAX /* max iv */
288 const kripto_stream_desc *const kripto_stream_skein512 = &skein512;