install.sh and uninstall.sh
[rofl0r-kripto.git] / lib / hash / skein256.c
blobf5dbf8b0d3a4476b5aa2939eeeb7819e2a4cc0b9
1 /*
2 * Written in 2013 by Gregor Pintar <grpintar@gmail.com>
4 * To the extent possible under law, the author(s) have dedicated
5 * all copyright and related and neighboring rights to this software
6 * to the public domain worldwide.
7 *
8 * This software is distributed without any warranty.
10 * You should have received a copy of the CC0 Public Domain Dedication.
11 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14 #include <stdint.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <limits.h>
18 #include <assert.h>
20 #include <kripto/cast.h>
21 #include <kripto/loadstore.h>
22 #include <kripto/memwipe.h>
23 #include <kripto/block.h>
24 #include <kripto/block/threefish256.h>
25 #include <kripto/hash.h>
26 #include <kripto/desc/hash.h>
27 #include <kripto/object/hash.h>
29 #include <kripto/hash/skein256.h>
31 struct kripto_hash
33 struct kripto_hash_object obj;
34 kripto_block *block;
35 unsigned int r;
36 unsigned int i;
37 int f;
38 uint8_t h[32];
39 uint8_t buf[32];
40 uint8_t tweak[16];
43 #define POS_ADD(TWEAK, ADD) \
44 { \
45 TWEAK[0] += ADD; \
46 if(!TWEAK[0]) \
47 if(!++TWEAK[1]) \
48 if(!++TWEAK[2]) \
49 if(!++TWEAK[3]) \
50 if(!++TWEAK[4]) \
51 if(!++TWEAK[5]) \
52 if(!++TWEAK[6]) \
53 if(!++TWEAK[7]) \
54 if(!++TWEAK[8]) \
55 if(!++TWEAK[9]) \
56 if(!++TWEAK[10]) \
57 { \
58 TWEAK[11]++; \
59 assert(TWEAK[11]); \
60 } \
63 static void skein256_process(kripto_hash *s)
65 unsigned int i;
67 (void)kripto_block_recreate(s->block, s->r, s->h, 32);
68 kripto_block_tweak(s->block, s->tweak, 16);
69 kripto_block_encrypt(s->block, s->buf, s->h);
71 for(i = 0; i < 32; i++) s->h[i] ^= s->buf[i];
74 static kripto_hash *skein256_recreate
76 kripto_hash *s,
77 unsigned int r,
78 size_t len
81 uint64_t t;
83 s->r = r;
84 s->i = 0;
85 s->f = 0;
86 memset(s->h, 0, 32);
87 memset(s->tweak, 0, 16);
89 t = len << 3;
91 /* CFG */
92 s->buf[0] = 'S';
93 s->buf[1] = 'H';
94 s->buf[2] = 'A';
95 s->buf[3] = '3';
96 s->buf[4] = 1;
97 s->buf[5] = 0;
98 s->buf[6] = 0;
99 s->buf[7] = 0;
100 STORE64L(t, s->buf + 8);
101 memset(s->buf + 16, 0, 16);
102 s->tweak[0] = 32;
103 s->tweak[15] = 0xC4; /* type CFG, first, final */
104 skein256_process(s);
106 /* MSG */
107 s->tweak[0] = 0;
108 s->tweak[15] = 0x70; /* type MSG, first */
110 return s;
113 static void skein256_input
115 kripto_hash *s,
116 const void *in,
117 size_t len
120 size_t i;
122 for(i = 0; i < len; i++)
124 s->buf[s->i++] = CU8(in)[i];
126 if(s->i == 32)
128 POS_ADD(s->tweak, 32);
130 skein256_process(s);
131 s->tweak[15] = 0x30; /* type MSG */
132 s->i = 0;
137 static void skein256_finish(kripto_hash *s)
139 POS_ADD(s->tweak, s->i);
141 memset(s->buf + s->i, 0, 32 - s->i);
142 s->tweak[15] |= 0x80; /* add final */
143 skein256_process(s);
145 memset(s->buf, 0, 32);
146 memset(s->tweak, 0, 12);
147 s->tweak[0] = 8; /* 8 byte counter */
148 s->tweak[15] = 0xFF; /* type OUT, first, final */
149 skein256_process(s);
151 s->i = 0;
152 s->f = -1;
155 static void skein256_output(kripto_hash *s, void *out, size_t len)
157 assert(s->i + len <= 32);
159 if(!s->f) skein256_finish(s);
161 memcpy(out, s->h + s->i, len);
162 s->i += len;
165 static kripto_hash *skein256_create(unsigned int r, size_t len)
167 kripto_hash *s;
169 s = malloc(sizeof(kripto_hash));
170 if(!s) return 0;
172 s->obj.desc = kripto_hash_skein256;
174 s->block = kripto_block_create(kripto_block_threefish256, r, "", 1);
175 if(!s->block)
177 free(s);
178 return 0;
181 (void)skein256_recreate(s, r, len);
183 return s;
186 static void skein256_destroy(kripto_hash *s)
188 kripto_block_destroy(s->block);
189 kripto_memwipe(s, sizeof(kripto_hash));
190 free(s);
193 static int skein256_hash
195 unsigned int r,
196 const void *in,
197 size_t in_len,
198 void *out,
199 size_t out_len
202 kripto_hash s;
204 s.block = kripto_block_create(kripto_block_threefish256, r, "", 1);
205 if(!s.block) return -1;
207 (void)skein256_recreate(&s, r, out_len);
208 skein256_input(&s, in, in_len);
209 skein256_output(&s, out, out_len);
211 kripto_block_destroy(s.block);
212 kripto_memwipe(&s, sizeof(kripto_hash));
214 return 0;
217 static const kripto_hash_desc skein256 =
219 &skein256_create,
220 &skein256_recreate,
221 &skein256_input,
222 &skein256_output,
223 &skein256_destroy,
224 &skein256_hash,
225 32, /* max output */
226 32 /* block_size */
229 const kripto_hash_desc *const kripto_hash_skein256 = &skein256;