better standard compliance
[rofl0r-kripto.git] / lib / mac / skein1024.c
blob3f345f345b87fd33bb9abd8631f3092b85eca9d0
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/threefish1024.h>
26 #include <kripto/mac.h>
27 #include <kripto/desc/mac.h>
28 #include <kripto/object/mac.h>
30 #include <kripto/mac/skein1024.h>
32 struct kripto_mac
34 struct kripto_mac_object obj;
35 kripto_block *block;
36 unsigned int r;
37 unsigned int i;
38 int f;
39 uint8_t h[128];
40 uint8_t buf[128];
41 uint8_t tweak[16];
44 #define POS_ADD(TWEAK, ADD) \
45 { \
46 TWEAK[0] += ADD; \
47 if(!TWEAK[0]) \
48 if(!++TWEAK[1]) \
49 if(!++TWEAK[2]) \
50 if(!++TWEAK[3]) \
51 if(!++TWEAK[4]) \
52 if(!++TWEAK[5]) \
53 if(!++TWEAK[6]) \
54 if(!++TWEAK[7]) \
55 if(!++TWEAK[8]) \
56 if(!++TWEAK[9]) \
57 if(!++TWEAK[10]) \
58 { \
59 TWEAK[11]++; \
60 assert(TWEAK[11]); \
61 } \
64 static void skein1024_process(kripto_mac *s)
66 unsigned int i;
68 (void)kripto_block_recreate(s->block, s->r, s->h, 128);
69 kripto_block_tweak(s->block, s->tweak, 16);
70 kripto_block_encrypt(s->block, s->buf, s->h);
72 for(i = 0; i < 128; i++) s->h[i] ^= s->buf[i];
75 static kripto_mac *skein1024_recreate
77 kripto_mac *s,
78 unsigned int r,
79 const void *key,
80 unsigned int key_len,
81 unsigned int tag_len
84 uint64_t t;
85 unsigned int block;
87 s->r = r;
88 s->i = 0;
89 s->f = 0;
90 memset(s->h, 0, 128);
91 memset(s->tweak, 0, 16);
93 t = tag_len << 3;
95 /* KEY */
96 s->tweak[15] = 0x40; /* type KEY, first */
98 while(key_len)
100 if(key_len > 128) block = 128;
101 else block = key_len;
103 memcpy(s->buf, key, block);
104 memset(s->buf, 0, 128 - block);
106 POS_ADD(s->tweak, block);
108 key_len -= block;
110 if(!key_len) s->tweak[15] |= 0x80; /* add final */
112 skein1024_process(s);
114 s->tweak[15] &= 0xBF; /* remove first */
117 /* CFG */
118 s->buf[0] = 'S';
119 s->buf[1] = 'H';
120 s->buf[2] = 'A';
121 s->buf[3] = '3';
122 s->buf[4] = 1;
123 s->buf[5] = 0;
124 s->buf[6] = 0;
125 s->buf[7] = 0;
126 STORE64L(t, s->buf + 8);
127 memset(s->buf + 16, 0, 112);
128 s->tweak[0] = 32;
129 s->tweak[15] = 0xC4; /* type CFG, first, final */
130 skein1024_process(s);
132 /* MSG */
133 s->tweak[0] = 0;
134 s->tweak[15] = 0x70; /* type MSG, first */
136 return s;
139 static void skein1024_input
141 kripto_mac *s,
142 const void *in,
143 size_t len
146 size_t i;
148 for(i = 0; i < len; i++)
150 s->buf[s->i++] = CU8(in)[i];
152 if(s->i == 128)
154 POS_ADD(s->tweak, 128);
156 skein1024_process(s);
157 s->tweak[15] = 0x30; /* type MSG */
158 s->i = 0;
163 static void skein1024_finish(kripto_mac *s)
165 POS_ADD(s->tweak, s->i);
167 memset(s->buf + s->i, 0, 128 - s->i);
168 s->tweak[15] |= 0x80; /* add final */
169 skein1024_process(s);
171 memset(s->buf, 0, 128);
172 memset(s->tweak, 0, 12);
173 s->tweak[0] = 8; /* 8 byte counter */
174 s->tweak[15] = 0xFF; /* type OUT, first, final */
175 skein1024_process(s);
177 s->i = 0;
178 s->f = -1;
181 static void skein1024_tag(kripto_mac *s, void *tag, unsigned int len)
183 assert(s->i + len <= 128);
185 if(!s->f) skein1024_finish(s);
187 memcpy(tag, s->h + s->i, len);
188 s->i += len;
191 static kripto_mac *skein1024_create
193 const kripto_mac_desc *desc,
194 unsigned int r,
195 const void *key,
196 unsigned int key_len,
197 unsigned int tag_len
200 kripto_mac *s;
202 (void)desc;
204 s = malloc(sizeof(kripto_mac));
205 if(!s) return 0;
207 s->obj.desc = kripto_mac_skein1024;
209 s->block = kripto_block_create(kripto_block_threefish1024, r, "", 1);
210 if(!s->block)
212 free(s);
213 return 0;
216 (void)skein1024_recreate(s, r, key, key_len, tag_len);
218 return s;
221 static void skein1024_destroy(kripto_mac *s)
223 kripto_block_destroy(s->block);
224 kripto_memwipe(s, sizeof(kripto_mac));
225 free(s);
228 static const kripto_mac_desc skein1024 =
230 &skein1024_create,
231 &skein1024_recreate,
232 &skein1024_input,
233 &skein1024_tag,
234 &skein1024_destroy,
235 128 /* max tag */
238 const kripto_mac_desc *const kripto_mac_skein1024 = &skein1024;