]> git.cryptolib.org Git - avr-crypto-lib.git/blob - echo/echo.c
Echo optimized
[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 <stdint.h>
25 #include <string.h>
26
27 #ifdef DEBUG
28 #undef DEBUG
29 #endif
30
31 #define DEBUG 0
32
33 #if DEBUG
34 #define DEBUG_DEPTH 2
35 #include "cli.h"
36 #endif
37
38 void aes_encrypt_round(void* state, void* key);
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 compress512(void* v, void* m, uint64_t* c, void* salt){
95         uint8_t i, j, l;
96         uint8_t s[16*16];
97         uint8_t k[16];
98
99         memcpy(s, v, 16*4);           /* load v into state */
100         memcpy(s+16*4, m, 16*12);     /* load m into state */
101
102         memcpy(k, c, 8);
103         memset(k+8, 0, 8);
104         for(i=0; i<8; ++i){
105                 /* BIG.SubWords */
106 #if DEBUG
107         cli_putstr_P(PSTR("\r\n === ROUND "));
108         cli_putc('1'+i);
109         cli_putstr_P(PSTR(" ==="));
110         if(i<DEBUG_DEPTH){
111                 dump_state(s);
112         }
113 #endif
114                 for(j=0; j<16; ++j){
115                         aes_encrypt_round(s+16*j, k);
116                         aes_encrypt_round(s+16*j, salt);
117                         *((uint64_t*)(k)) += 1;
118                 }
119 #if DEBUG
120                 if(i<DEBUG_DEPTH){
121                         cli_putstr_P(PSTR("\r\nAfter SubWords"));
122                         dump_state(s);
123                 }
124 #endif
125                 /* BIG.ShiftRows */
126                 uint8_t t[16];
127                 /* "Row" 1 */
128                 memcpy(t,             s+INDEX(0, 1), 16);
129                 memcpy(s+INDEX(0, 1), s+INDEX(1, 1), 16);
130                 memcpy(s+INDEX(1, 1), s+INDEX(2, 1), 16);
131                 memcpy(s+INDEX(2, 1), s+INDEX(3, 1), 16);
132                 memcpy(s+INDEX(3, 1), t,             16);
133                 /* "Row" 2 */
134                 memcpy(t,             s+INDEX(0, 2), 16);
135                 memcpy(s+INDEX(0, 2), s+INDEX(2, 2), 16);
136                 memcpy(s+INDEX(2, 2), t,             16);
137                 memcpy(t,             s+INDEX(1, 2), 16);
138                 memcpy(s+INDEX(1, 2), s+INDEX(3, 2), 16);
139                 memcpy(s+INDEX(3, 2), t,             16);
140                 /* "Row" 3 */
141                 memcpy(t,             s+INDEX(0, 3), 16);
142                 memcpy(s+INDEX(0, 3), s+INDEX(3, 3), 16);
143                 memcpy(s+INDEX(3, 3), s+INDEX(2, 3), 16);
144                 memcpy(s+INDEX(2, 3), s+INDEX(1, 3), 16);
145                 memcpy(s+INDEX(1, 3), t,             16);
146 #if DEBUG
147                 if(i<DEBUG_DEPTH){
148                         cli_putstr_P(PSTR("\r\nAfter ShiftRows"));
149                         dump_state(s);
150                 }
151 #endif
152                 /* BIG.MixColumns */
153                 for(j=0; j<4; j+=1){
154                         for(l=0; l<16; ++l){
155                                 mixcol(s+j*64+l);
156                         }
157                 }
158 #if DEBUG
159                 if(i<DEBUG_DEPTH){
160                         cli_putstr_P(PSTR("\r\nAfter MixColumns"));
161                         dump_state(s);
162                 }
163 #endif
164         }
165
166         /* BIG.Final */
167         for(i=0; i<3; ++i){
168                 memxor(v, (uint8_t*)m+4*16*i, 4*16);
169         }
170         for(i=0; i<4; ++i){
171                 memxor(v, s+4*16*i, 4*16);
172         }
173 }
174
175 void echo_small_nextBlock(echo_small_ctx_t* ctx, void* block){
176         ctx->counter += ECHO_SMALL_BLOCKSIZE;
177         compress512(ctx->v, block, &(ctx->counter), ctx->salt);
178 }
179
180 void echo_small_lastBlock(echo_small_ctx_t* ctx, void* block, uint16_t length_b){
181         while(length_b>=ECHO_SMALL_BLOCKSIZE){
182                 echo_small_nextBlock(ctx, block);
183                 block = (uint8_t*)block + ECHO_SMALL_BLOCKSIZE_B;
184                 length_b -= ECHO_SMALL_BLOCKSIZE;
185         }
186         uint8_t buffer[ECHO_SMALL_BLOCKSIZE_B];
187         uint64_t total_len;
188         memset(buffer, 0, ECHO_SMALL_BLOCKSIZE_B);
189         memcpy(buffer, block, (length_b+7)/8);
190         buffer[length_b/8] |= 0x80 >> (length_b&7);
191         total_len = (ctx->counter += length_b);
192         if(length_b>=ECHO_SMALL_BLOCKSIZE-144){
193                 compress512(ctx->v, buffer, &total_len, ctx->salt);
194                 memset(buffer, 0, ECHO_SMALL_BLOCKSIZE_B);
195                 ctx->counter = 0;
196         }
197         if(length_b==0){
198                 ctx->counter = 0;
199         }
200         memcpy(buffer+ECHO_SMALL_BLOCKSIZE_B-18, &(ctx->id), 2);
201         memcpy(buffer+ECHO_SMALL_BLOCKSIZE_B-16, &total_len, 8);
202         compress512(ctx->v, buffer, &(ctx->counter), ctx->salt);
203 }
204
205 /******************************************************************************/
206
207 void echo_small_ctx2hash(void* dest, uint16_t length_b, echo_small_ctx_t* ctx){
208         memcpy(dest, ctx->v, (length_b+7)/8);
209 }
210
211 void echo224_ctx2hash(void* dest, echo_small_ctx_t* ctx){
212         memcpy(dest, ctx->v, 224/8);
213 }
214
215 void echo256_ctx2hash(void* dest, echo_small_ctx_t* ctx){
216         memcpy(dest, ctx->v, 256/8);
217 }
218
219 /******************************************************************************/
220
221 void echo224_init(echo_small_ctx_t* ctx){
222         memset(ctx->v, 0, 4*16);
223         ctx->counter = 0;
224         memset(ctx->salt, 0, 16);
225         ctx->id = 0x00E0;
226         ctx->v[0+16*0] = 0xE0;
227         ctx->v[0+16*1] = 0xE0;
228         ctx->v[0+16*2] = 0xE0;
229         ctx->v[0+16*3] = 0xE0;
230 }
231
232 void echo256_init(echo_small_ctx_t* ctx){
233         memset(ctx->v, 0, 4*16);
234         ctx->counter = 0;
235         memset(ctx->salt, 0, 16);
236         ctx->id = 0x0100;
237         ctx->v[1+16*0] = 0x01;
238         ctx->v[1+16*1] = 0x01;
239         ctx->v[1+16*2] = 0x01;
240         ctx->v[1+16*3] = 0x01;
241 }
242
243 /******************************************************************************/
244