]> git.cryptolib.org Git - avr-crypto-lib.git/blob - echo/echo.c
43703d7cbd31f125622f47d8a682d79af71dfe9b
[avr-crypto-lib.git] / echo / echo.c
1 /* echo.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "echo.h"
22 #include "gf256mul.h"
23 #include "memxor.h"
24 #include "aes_enc_round.h"
25 #include <stdint.h>
26 #include <string.h>
27
28 #ifdef DEBUG
29 #undef DEBUG
30 #endif
31
32 #define DEBUG 0
33
34 #if DEBUG
35 #define DEBUG_DEPTH 2
36 #include "cli.h"
37 #endif
38
39
40 #define INDEX(c,r) ((c)*16*4+(r)*16)
41
42 #define GF256MUL_1(a) (a)
43 #define GF256MUL_2(a) (gf256mul(2, (a), 0x1b))
44 #define GF256MUL_3(a) (gf256mul(3, (a), 0x1b))
45
46 static void mixcol(uint8_t *s){
47         uint8_t t, tmp[4];
48         tmp[0] = *(s+16*0);
49         tmp[1] = *(s+16*1);
50         tmp[2] = *(s+16*2);
51         tmp[3] = *(s+16*3);
52
53         t = tmp[0] ^ tmp[1] ^ tmp[2] ^ tmp[3];
54         *(s+16*0) =
55                   GF256MUL_2(tmp[0]^tmp[1])
56                 ^ tmp[0]
57                 ^ t;
58         *(s+16*1) =
59                   GF256MUL_2(tmp[1]^tmp[2])
60                 ^ tmp[1]
61                 ^ t;
62         *(s+16*2) =
63                   GF256MUL_2(tmp[2]^tmp[3])
64                 ^ tmp[2]
65                 ^ t;
66         *(s+16*3) =
67                   GF256MUL_2(tmp[3]^tmp[0])
68                 ^ tmp[3]
69                 ^ t;
70 }
71
72 #if DEBUG
73 static void dump_state(void *s){
74         uint8_t row, col;
75         for(col=0; col<4; col++){
76                 for(row=0; row<4; row++){
77                         cli_putstr_P(PSTR("\r\nrow "));
78                         cli_putc('0'+row);
79                         cli_putstr_P(PSTR(", col "));
80                         cli_putc('0'+col);
81                         cli_putstr_P(PSTR(": "));
82                         cli_hexdump((uint8_t*)s+col*16*4+row*16, 4);
83                         cli_putc(' ');
84                         cli_hexdump((uint8_t*)s+col*16*4+row*16+ 4, 4);
85                         cli_putc(' ');
86                         cli_hexdump((uint8_t*)s+col*16*4+row*16+ 8, 4);
87                         cli_putc(' ');
88                         cli_hexdump((uint8_t*)s+col*16*4+row*16+12, 4);
89                 }
90         }
91 }
92 #endif
93
94 static void echo_compress(uint8_t *s, uint8_t iterations, uint64_t *c, void *salt){
95         uint8_t i, j;
96         union {
97                 uint8_t v8[16];
98                 uint64_t v64[2];
99         } k;
100 #if DEBUG
101         uint8_t round=0;
102 #endif
103         memcpy(k.v8, c, 8);
104         memset(k.v8+8, 0, 8);
105         do{
106                 /* BIG.SubWords */
107 #if DEBUG
108         cli_putstr_P(PSTR("\r\n === ROUND "));
109         cli_putc('0'+round);
110         cli_putstr_P(PSTR(" ==="));
111         if(round<DEBUG_DEPTH){
112                 dump_state(s);
113         }
114 #endif
115                 for(i=0; i<16; ++i){
116                         aes_enc_round((aes_cipher_state_t*)(s+16*i), (aes_roundkey_t*)k.v8);
117                         aes_enc_round((aes_cipher_state_t*)(s+16*i), (aes_roundkey_t*)salt);
118                         k.v64[0] += 1;
119                 }
120 #if DEBUG
121                 if(round<DEBUG_DEPTH){
122                         cli_putstr_P(PSTR("\r\nAfter SubWords"));
123                         dump_state(s);
124                 }
125 #endif
126                 /* BIG.ShiftRows */
127                 uint8_t t[16];
128                 /* "Row" 1 */
129                 memcpy(t,             s+INDEX(0, 1), 16);
130                 memcpy(s+INDEX(0, 1), s+INDEX(1, 1), 16);
131                 memcpy(s+INDEX(1, 1), s+INDEX(2, 1), 16);
132                 memcpy(s+INDEX(2, 1), s+INDEX(3, 1), 16);
133                 memcpy(s+INDEX(3, 1), t,             16);
134                 /* "Row" 2 */
135                 memcpy(t,             s+INDEX(0, 2), 16);
136                 memcpy(s+INDEX(0, 2), s+INDEX(2, 2), 16);
137                 memcpy(s+INDEX(2, 2), t,             16);
138                 memcpy(t,             s+INDEX(1, 2), 16);
139                 memcpy(s+INDEX(1, 2), s+INDEX(3, 2), 16);
140                 memcpy(s+INDEX(3, 2), t,             16);
141                 /* "Row" 3 */
142                 memcpy(t,             s+INDEX(0, 3), 16);
143                 memcpy(s+INDEX(0, 3), s+INDEX(3, 3), 16);
144                 memcpy(s+INDEX(3, 3), s+INDEX(2, 3), 16);
145                 memcpy(s+INDEX(2, 3), s+INDEX(1, 3), 16);
146                 memcpy(s+INDEX(1, 3), t,             16);
147 #if DEBUG
148                 if(round<DEBUG_DEPTH){
149                         cli_putstr_P(PSTR("\r\nAfter ShiftRows"));
150                         dump_state(s);
151                 }
152 #endif
153                 /* BIG.MixColumns */
154                 for(i=0; i<4; i+=1){
155                         for(j=0; j<16; ++j){
156                                 mixcol(s+i*64+j);
157                         }
158                 }
159 #if DEBUG
160                 if(round<DEBUG_DEPTH){
161                         cli_putstr_P(PSTR("\r\nAfter MixColumns"));
162                         dump_state(s);
163                 }
164                 round++;
165 #endif
166         }while(--iterations);
167
168 }
169
170 /******************************************************************************/
171
172 static void compress512(void *v, void *m, uint64_t *c, void *salt){
173         uint8_t s[16*16];
174         uint8_t i;
175         memcpy(s, v, 16*4);           /* load v into state */
176         memcpy(s+16*4, m, 16*12);     /* load m into state */
177
178         echo_compress(s, 8, c, salt);
179
180         /* BIG.Final */
181         for(i=0; i<3; ++i){
182                 memxor(v, (uint8_t*)m+4*16*i, 4*16);
183         }
184         for(i=0; i<4; ++i){
185                 memxor(v, s+4*16*i, 4*16);
186         }
187 }
188
189 static void compress1024(void *v, void *m, uint64_t *c, void *salt){
190         uint8_t s[16*16];
191         memcpy(s, v, 16*8);           /* load v into state */
192         memcpy(s+16*8, m, 16*8);      /* load m into state */
193
194         echo_compress(s, 10, c, salt);
195
196         /* BIG.Final */
197         memxor(v, m, 16*8);
198         memxor(v, s, 16*8);
199         memxor(v, s+16*8, 16*8);
200 }
201
202 /******************************************************************************/
203
204 void echo_small_nextBlock(echo_small_ctx_t *ctx, void *block){
205         ctx->counter += ECHO_SMALL_BLOCKSIZE;
206         compress512(ctx->v, block, &(ctx->counter), ctx->salt);
207 }
208
209 void echo_small_lastBlock(echo_small_ctx_t *ctx, void *block, uint16_t length_b){
210         while(length_b>=ECHO_SMALL_BLOCKSIZE){
211                 echo_small_nextBlock(ctx, block);
212                 block = (uint8_t*)block + ECHO_SMALL_BLOCKSIZE_B;
213                 length_b -= ECHO_SMALL_BLOCKSIZE;
214         }
215         uint8_t buffer[ECHO_SMALL_BLOCKSIZE_B];
216         uint64_t total_len;
217         memset(buffer, 0, ECHO_SMALL_BLOCKSIZE_B);
218         memcpy(buffer, block, (length_b+7)/8);
219         buffer[length_b/8] |= 0x80 >> (length_b&7);
220         total_len = (ctx->counter += length_b);
221         if(length_b>=ECHO_SMALL_BLOCKSIZE-144){
222                 compress512(ctx->v, buffer, &total_len, ctx->salt);
223                 memset(buffer, 0, ECHO_SMALL_BLOCKSIZE_B);
224                 ctx->counter = 0;
225         }
226         if(length_b==0){
227                 ctx->counter = 0;
228         }
229         memcpy(buffer+ECHO_SMALL_BLOCKSIZE_B-18, &(ctx->id), 2);
230         memcpy(buffer+ECHO_SMALL_BLOCKSIZE_B-16, &total_len, 8);
231         compress512(ctx->v, buffer, &(ctx->counter), ctx->salt);
232 }
233
234 /******************************************************************************/
235
236 void echo_large_nextBlock(echo_large_ctx_t *ctx, void *block){
237         ctx->counter += ECHO_LARGE_BLOCKSIZE;
238         compress1024(ctx->v, block, &(ctx->counter), ctx->salt);
239 }
240
241 void echo_large_lastBlock(echo_large_ctx_t *ctx, void *block, uint16_t length_b){
242         while(length_b>=ECHO_LARGE_BLOCKSIZE){
243                 echo_large_nextBlock(ctx, block);
244                 block = (uint8_t*)block + ECHO_LARGE_BLOCKSIZE_B;
245                 length_b -= ECHO_LARGE_BLOCKSIZE;
246         }
247         uint8_t buffer[ECHO_LARGE_BLOCKSIZE_B];
248         uint64_t total_len;
249         memset(buffer, 0, ECHO_LARGE_BLOCKSIZE_B);
250         memcpy(buffer, block, (length_b+7)/8);
251         buffer[length_b/8] |= 0x80 >> (length_b&7);
252         total_len = (ctx->counter += length_b);
253         if(length_b>=ECHO_LARGE_BLOCKSIZE-144){
254                 compress1024(ctx->v, buffer, &total_len, ctx->salt);
255                 memset(buffer, 0, ECHO_LARGE_BLOCKSIZE_B);
256                 ctx->counter = 0;
257         }
258         if(length_b==0){
259                 ctx->counter = 0;
260         }
261         memcpy(buffer+ECHO_LARGE_BLOCKSIZE_B-18, &(ctx->id), 2);
262         memcpy(buffer+ECHO_LARGE_BLOCKSIZE_B-16, &total_len, 8);
263         compress1024(ctx->v, buffer, &(ctx->counter), ctx->salt);
264 }
265 /******************************************************************************/
266
267 void echo_ctx2hash(void *dest, uint16_t length_b, echo_small_ctx_t *ctx){
268         memcpy(dest, ctx->v, (length_b+7)/8);
269 }
270
271 void echo224_ctx2hash(void *dest, echo_small_ctx_t *ctx){
272         memcpy(dest, ctx->v, 224/8);
273 }
274
275 void echo256_ctx2hash(void *dest, echo_small_ctx_t *ctx){
276         memcpy(dest, ctx->v, 256/8);
277 }
278
279 /******************************************************************************/
280
281 void echo384_ctx2hash(void *dest, echo_large_ctx_t *ctx){
282         memcpy(dest, ctx->v, 384/8);
283 }
284
285 void echo512_ctx2hash(void *dest, echo_large_ctx_t *ctx){
286         memcpy(dest, ctx->v, 512/8);
287 }
288
289 /******************************************************************************/
290
291 void echo224_init(echo_small_ctx_t *ctx){
292         memset(ctx->v, 0, 4*16);
293         ctx->counter = 0;
294         memset(ctx->salt, 0, 16);
295         ctx->id = 0x00E0;
296         ctx->v[0+16*0] = 0xE0;
297         ctx->v[0+16*1] = 0xE0;
298         ctx->v[0+16*2] = 0xE0;
299         ctx->v[0+16*3] = 0xE0;
300 }
301
302 void echo256_init(echo_small_ctx_t *ctx){
303         memset(ctx->v, 0, 4*16);
304         ctx->counter = 0;
305         memset(ctx->salt, 0, 16);
306         ctx->id = 0x0100;
307         ctx->v[1+16*0] = 0x01;
308         ctx->v[1+16*1] = 0x01;
309         ctx->v[1+16*2] = 0x01;
310         ctx->v[1+16*3] = 0x01;
311 }
312
313 /******************************************************************************/
314
315 void echo384_init(echo_large_ctx_t *ctx){
316         uint8_t i;
317         memset(ctx->v, 0, 8*16);
318         ctx->counter = 0;
319         memset(ctx->salt, 0, 16);
320         ctx->id = 0x0180;
321         for(i=0; i<8; ++i){
322                 ctx->v[0+16*i] = 0x80;
323                 ctx->v[1+16*i] = 0x01;
324         }
325 }
326
327 void echo512_init(echo_large_ctx_t *ctx){
328         uint8_t i;
329         memset(ctx->v, 0, 8*16);
330         ctx->counter = 0;
331         memset(ctx->salt, 0, 16);
332         ctx->id = 0x0200;
333         for(i=0; i<8; ++i){
334                 ctx->v[1+16*i] = 0x02;
335         }
336 }
337
338 /******************************************************************************/