]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bmw_large.c
forgotten files
[avr-crypto-lib.git] / bmw_large.c
1 /* bmw_large.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2009  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  * \file    bmw_large.c
21  * \author  Daniel Otte
22  * \email   daniel.otte@rub.de
23  * \date    2009-04-27
24  * \license GPLv3 or later
25  * 
26  */
27
28 #include <stdint.h>
29 #include <string.h>
30 #include <avr/pgmspace.h>
31 #include "bmw_large.h"
32
33 #define SHL64(a,n) ((a)<<(n))
34 #define SHR64(a,n) ((a)>>(n))
35 #define ROTL64(a,n) (((a)<<(n))|((a)>>(64-(n))))
36 #define ROTR64(a,n) (((a)>>(n))|((a)<<(64-(n))))
37
38 #define BUG24 0
39 #define F0_HACK 1
40 #define DEBUG 0
41 #if DEBUG
42  #include "cli.h"
43  
44  void ctx_dump(const bmw_large_ctx_t* ctx){
45         uint8_t i;
46         cli_putstr_P(PSTR("\r\n==== ctx dump ===="));
47         for(i=0; i<16;++i){
48                 cli_putstr_P(PSTR("\r\n h["));
49                 cli_hexdump(&i, 1);
50                 cli_putstr_P(PSTR("] = "));
51                 cli_hexdump_rev(&(ctx->h[i]), 8);
52         }
53         cli_putstr_P(PSTR("\r\n counter = "));
54         cli_hexdump(&(ctx->counter), 4);
55  }
56  
57  void dump_x(const uint64_t* q, uint8_t elements, char x){
58         uint8_t i;
59         cli_putstr_P(PSTR("\r\n==== "));
60         cli_putc(x);
61         cli_putstr_P(PSTR(" dump ===="));
62         for(i=0; i<elements;++i){
63                 cli_putstr_P(PSTR("\r\n "));
64                 cli_putc(x);
65                 cli_putstr_P(PSTR("["));
66                 cli_hexdump(&i, 1);
67                 cli_putstr_P(PSTR("] = "));
68                 cli_hexdump_rev(&(q[i]), 8);
69         }
70  }
71 #else
72  #define ctx_dump(x)
73  #define dump_x(a,b,c)
74 #endif
75
76 uint64_t bmw_large_s0(uint64_t x){
77         uint64_t r;
78         r =   SHR64(x, 1)
79                 ^ SHL64(x, 3)
80                 ^ ROTL64(x, 4)
81                 ^ ROTR64(x, 64-37);
82         return r;       
83 }
84
85 uint64_t bmw_large_s1(uint64_t x){
86         uint64_t r;
87         r =   SHR64(x, 1)
88                 ^ SHL64(x, 2)
89                 ^ ROTL64(x,13)
90                 ^ ROTR64(x,64-43);
91         return r;       
92 }
93
94 uint64_t bmw_large_s2(uint64_t x){
95         uint64_t r;
96         r =   SHR64(x, 2)
97                 ^ SHL64(x, 1)
98                 ^ ROTL64(x, 19)
99                 ^ ROTR64(x, 64-53);
100         return r;       
101 }
102
103 uint64_t bmw_large_s3(uint64_t x){
104         uint64_t r;
105         r =   SHR64(x, 2)
106                 ^ SHL64(x, 2)
107                 ^ ROTL64(x, 28)
108                 ^ ROTR64(x, 64-59);
109         return r;       
110 }
111
112 uint64_t bmw_large_s4(uint64_t x){
113         uint64_t r;
114         r =   SHR64(x, 1)
115                 ^ x;
116         return r;       
117 }
118
119 uint64_t bmw_large_s5(uint64_t x){
120         uint64_t r;
121         r =   SHR64(x, 2)
122                 ^ x;
123         return r;       
124 }
125
126 uint64_t bmw_large_r1(uint64_t x){
127         uint64_t r;
128         r =   ROTL64(x, 5);
129         return r;       
130 }
131
132 uint64_t bmw_large_r2(uint64_t x){
133         uint64_t r;
134         r =   ROTL64(x, 11);
135         return r;       
136 }
137
138 uint64_t bmw_large_r3(uint64_t x){
139         uint64_t r;
140         r =   ROTL64(x, 27);
141         return r;       
142 }
143
144 uint64_t bmw_large_r4(uint64_t x){
145         uint64_t r;
146         r =   ROTL64(x, 32);
147         return r;       
148 }
149
150 uint64_t bmw_large_r5(uint64_t x){
151         uint64_t r;
152         r =   ROTR64(x, 64-37);
153         return r;       
154 }
155
156 uint64_t bmw_large_r6(uint64_t x){
157         uint64_t r;
158         r =   ROTR64(x, 64-43);
159         return r;       
160 }
161
162 uint64_t bmw_large_r7(uint64_t x){
163         uint64_t r;
164         r =   ROTR64(x, 64-53);
165         return r;       
166 }
167 /*
168 #define K    0x0555555555555555LL
169 #define MASK 0xFFFFFFFFFFFFFFFFLL
170 static
171 uint64_t k_lut[] PROGMEM = {
172         16LL*K, 17LL*K, 18LL*K, 19LL*K, 
173         20LL*K, 21LL*K, 22LL*K, 23LL*K,
174         24LL*K, 25LL*K, 26LL*K, 27LL*K,
175         28LL*K, 29LL*K, 30LL*K, 31LL*K };
176 */      
177 /* the same as above but precomputed to avoid compiler warnings */
178 static
179 uint64_t k_lut[] PROGMEM = {
180         0x5555555555555550LL, 0x5aaaaaaaaaaaaaa5LL, 0x5ffffffffffffffaLL,
181         0x655555555555554fLL, 0x6aaaaaaaaaaaaaa4LL, 0x6ffffffffffffff9LL,
182         0x755555555555554eLL, 0x7aaaaaaaaaaaaaa3LL, 0x7ffffffffffffff8LL,
183         0x855555555555554dLL, 0x8aaaaaaaaaaaaaa2LL, 0x8ffffffffffffff7LL,
184         0x955555555555554cLL, 0x9aaaaaaaaaaaaaa1LL, 0x9ffffffffffffff6LL,
185         0xa55555555555554bLL };
186
187 uint64_t bmw_large_expand1(uint8_t j, const uint64_t* q, const void* m){
188         uint64_t(*s[])(uint64_t) = {bmw_large_s1, bmw_large_s2, bmw_large_s3, bmw_large_s0};
189         union{
190                 uint64_t v64;
191                 uint32_t v32[2];
192         } r;
193         uint8_t i;
194         /* r = 0x0555555555555555LL*(j+16); */
195         r.v32[0] = pgm_read_dword(((uint8_t*)k_lut+8*j));
196         r.v32[1] = pgm_read_dword(((uint8_t*)k_lut+8*j+4));
197         for(i=0; i<16; ++i){
198                 r.v64 += s[i%4](q[j+i]);
199         }
200         r.v64 += ((uint64_t*)m)[j];
201         r.v64 += ((uint64_t*)m)[j+3];
202         r.v64 -= ((uint64_t*)m)[j+10];
203         return r.v64;
204 }
205
206 uint64_t bmw_large_expand2(uint8_t j, const uint64_t* q, const void* m){
207         uint64_t(*rf[])(uint64_t) = {bmw_large_r1, bmw_large_r2, bmw_large_r3,
208                                      bmw_large_r4, bmw_large_r5, bmw_large_r6,
209                                                              bmw_large_r7};
210         union{
211                 uint64_t v64;
212                 uint32_t v32[2];
213         } r;
214         uint8_t i;
215         /* r = 0x0555555555555555LL*(j+16); */
216         r.v32[0] = pgm_read_dword(((uint8_t*)k_lut+8*j));
217         r.v32[1] = pgm_read_dword(((uint8_t*)k_lut+8*j+4));
218         for(i=0; i<14; i+=2){
219                 r.v64 += q[j+i];
220         }
221         for(i=0; i<14; i+=2){
222                 r.v64 += rf[i/2](q[j+i+1]);
223         }
224         r.v64 += bmw_large_s5(q[j+14]);
225         r.v64 += bmw_large_s4(q[j+15]);
226         r.v64 += ((uint64_t*)m)[j];
227         r.v64 += ((uint64_t*)m)[(j+3)%16];
228         r.v64 -= ((uint64_t*)m)[(j+10)%16];
229         return r.v64;
230 }
231
232 #if F0_HACK
233 static
234 uint8_t f0_lut[] PROGMEM ={
235          5<<1, ( 7<<1)+1, (10<<1)+0, (13<<1)+0, (14<<1)+0,
236          6<<1, ( 8<<1)+1, (11<<1)+0, (14<<1)+0, (15<<1)+1,
237          0<<1, ( 7<<1)+0, ( 9<<1)+0, (12<<1)+1, (15<<1)+0,
238          0<<1, ( 1<<1)+1, ( 8<<1)+0, (10<<1)+1, (13<<1)+0,
239          1<<1, ( 2<<1)+0, ( 9<<1)+0, (11<<1)+1, (14<<1)+1,
240          3<<1, ( 2<<1)+1, (10<<1)+0, (12<<1)+1, (15<<1)+0,
241          4<<1, ( 0<<1)+1, ( 3<<1)+1, (11<<1)+1, (13<<1)+0, 
242          1<<1, ( 4<<1)+1, ( 5<<1)+1, (12<<1)+1, (14<<1)+1,
243          2<<1, ( 5<<1)+1, ( 6<<1)+1, (13<<1)+0, (15<<1)+1,
244          0<<1, ( 3<<1)+1, ( 6<<1)+0, ( 7<<1)+1, (14<<1)+0,
245          8<<1, ( 1<<1)+1, ( 4<<1)+1, ( 7<<1)+1, (15<<1)+0,
246          8<<1, ( 0<<1)+1, ( 2<<1)+1, ( 5<<1)+1, ( 9<<1)+0,
247          1<<1, ( 3<<1)+0, ( 6<<1)+1, ( 9<<1)+1, (10<<1)+0,
248          2<<1, ( 4<<1)+0, ( 7<<1)+0, (10<<1)+0, (11<<1)+0,
249          3<<1, ( 5<<1)+1, ( 8<<1)+0, (11<<1)+1, (12<<1)+1,
250         12<<1, ( 4<<1)+1, ( 6<<1)+1, ( 9<<1)+1, (13<<1)+0
251 };
252
253 void bmw_large_f0(uint64_t* q, uint64_t* h, const void* m){
254         uint8_t i,j=-1,v,sign,l=0;
255         uint64_t(*s[])(uint64_t)={ bmw_large_s0, bmw_large_s1, bmw_large_s2,
256                                    bmw_large_s3, bmw_large_s4 };
257         for(i=0; i<16; ++i){
258                 h[i] ^= ((uint64_t*)m)[i];
259         }
260         dump_x(h, 16, 'T');
261 //      memset(q, 0, 4*16);
262         for(i=0; i<5*16; ++i){
263                 v = pgm_read_byte(f0_lut+i);
264                 sign = v&1;
265                 v >>=1;
266                 if(i==l){
267                         j++;
268                         l+=5;
269                         q[j] = h[v];
270                         continue;
271                 }
272                 if(sign){
273                         q[j] -= h[v];
274                 }else{
275                         q[j] += h[v];
276                 }
277         }
278         dump_x(q, 16, 'W');
279         for(i=0; i<16; ++i){
280                 q[i] = s[i%5](q[i]);
281         }       
282 }
283
284 #else
285 void bmw_large_f0(uint64_t* q, uint64_t* h, const void* m){
286         uint8_t i;
287         uint64_t(*s[])(uint64_t)={ bmw_large_s0, bmw_large_s1, bmw_large_s2,
288                                    bmw_large_s3, bmw_large_s4 };
289         for(i=0; i<16; ++i){
290                 h[i] ^= ((uint64_t*)m)[i];
291         }
292         dump_x(t, 16, 'T');
293         q[ 0] = (h[ 5] - h[ 7] + h[10] + h[13] + h[14]);
294         q[ 1] = (h[ 6] - h[ 8] + h[11] + h[14] - h[15]);
295         q[ 2] = (h[ 0] + h[ 7] + h[ 9] - h[12] + h[15]);
296         q[ 3] = (h[ 0] - h[ 1] + h[ 8] - h[10] + h[13]);
297         q[ 4] = (h[ 1] + h[ 2] + h[ 9] - h[11] - h[14]);
298         q[ 5] = (h[ 3] - h[ 2] + h[10] - h[12] + h[15]);
299         q[ 6] = (h[ 4] - h[ 0] - h[ 3] - h[11] + h[13]); 
300         q[ 7] = (h[ 1] - h[ 4] - h[ 5] - h[12] - h[14]);
301         q[ 8] = (h[ 2] - h[ 5] - h[ 6] + h[13] - h[15]);
302         q[ 9] = (h[ 0] - h[ 3] + h[ 6] - h[ 7] + h[14]);
303         q[10] = (h[ 8] - h[ 1] - h[ 4] - h[ 7] + h[15]);
304         q[11] = (h[ 8] - h[ 0] - h[ 2] - h[ 5] + h[ 9]);
305         q[12] = (h[ 1] + h[ 3] - h[ 6] - h[ 9] + h[10]);
306         q[13] = (h[ 2] + h[ 4] + h[ 7] + h[10] + h[11]);
307         q[14] = (h[ 3] - h[ 5] + h[ 8] - h[11] - h[12]);
308         q[15] = (h[12] - h[ 4] - h[ 6] - h[ 9] + h[13]); 
309         dump_x(q, 16, 'W');
310         for(i=0; i<16; ++i){
311                 q[i] = s[i%5](q[i]);
312         }       
313 }
314 #endif
315
316 void bmw_large_f1(uint64_t* q, const void* m){
317         uint8_t i;
318         q[16] = bmw_large_expand1(0, q, m);
319         q[17] = bmw_large_expand1(1, q, m);
320         for(i=2; i<16; ++i){
321                 q[16+i] = bmw_large_expand2(i, q, m);
322         }
323 }
324
325 void bmw_large_f2(uint64_t* h, const uint64_t* q, const void* m){
326         uint64_t xl=0, xh;
327         uint8_t i;
328         for(i=16;i<24;++i){
329                 xl ^= q[i];
330         }
331         xh = xl;
332         for(i=24;i<32;++i){
333                 xh ^= q[i];
334         }
335 #if DEBUG       
336         cli_putstr_P(PSTR("\r\n XL = "));
337         cli_hexdump_rev(&xl, 4);
338         cli_putstr_P(PSTR("\r\n XH = "));
339         cli_hexdump_rev(&xh, 4);
340 #endif
341         memcpy(h, m, 16*8);
342         h[0] ^= SHL64(xh, 5) ^ SHR64(q[16], 5);
343         h[1] ^= SHR64(xh, 7) ^ SHL64(q[17], 8);
344         h[2] ^= SHR64(xh, 5) ^ SHL64(q[18], 5);
345         h[3] ^= SHR64(xh, 1) ^ SHL64(q[19], 5);
346         h[4] ^= SHR64(xh, 3) ^ q[20];
347         h[5] ^= SHL64(xh, 6) ^ SHR64(q[21], 6);
348         h[6] ^= SHR64(xh, 4) ^ SHL64(q[22], 6);
349         h[7] ^= SHR64(xh,11) ^ SHL64(q[23], 2);
350         for(i=0; i<8; ++i){
351                 h[i] += xl ^ q[24+i] ^ q[i];
352         }
353         for(i=0; i<8; ++i){
354                 h[8+i] ^= xh ^ q[24+i];
355                 h[8+i] += ROTL64(h[(4+i)%8],i+9);
356         }
357         h[ 8] += SHL64(xl, 8) ^ q[23] ^ q[ 8];
358         h[ 9] += SHR64(xl, 6) ^ q[16] ^ q[ 9];
359         h[10] += SHL64(xl, 6) ^ q[17] ^ q[10];
360         h[11] += SHL64(xl, 4) ^ q[18] ^ q[11];
361         h[12] += SHR64(xl, 3) ^ q[19] ^ q[12];
362         h[13] += SHR64(xl, 4) ^ q[20] ^ q[13];
363         h[14] += SHR64(xl, 7) ^ q[21] ^ q[14];
364         h[15] += SHR64(xl, 2) ^ q[22] ^ q[15];
365 }
366
367 void bmw_large_nextBlock(bmw_large_ctx_t* ctx, const void* block){
368         uint64_t q[32];
369         dump_x(block, 16, 'M');
370         bmw_large_f0(q, ctx->h, block);
371         dump_x(q, 16, 'Q');
372         bmw_large_f1(q, block);
373         dump_x(q, 32, 'Q');
374         bmw_large_f2(ctx->h, q, block);
375         ctx->counter += 1;
376         ctx_dump(ctx);
377 }
378
379 void bmw_large_lastBlock(bmw_large_ctx_t* ctx, const void* block, uint16_t length_b){
380         uint8_t buffer[128];
381         while(length_b >= BMW_LARGE_BLOCKSIZE){
382                 bmw_large_nextBlock(ctx, block);
383                 length_b -= BMW_LARGE_BLOCKSIZE;
384                 block = (uint8_t*)block + BMW_LARGE_BLOCKSIZE_B;
385         }
386         memset(buffer, 0, 128);
387         memcpy(buffer, block, (length_b+7)/8);
388         buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
389         if(length_b+1>128*8-64){
390                 bmw_large_nextBlock(ctx, buffer);
391                 memset(buffer, 0, 128-8);
392                 ctx->counter -= 1;
393         }
394         *((uint64_t*)&(buffer[128-8])) = (uint64_t)(ctx->counter*1024LL)+(uint64_t)length_b;
395         bmw_large_nextBlock(ctx, buffer);
396 }
397
398 void bmw384_init(bmw384_ctx_t* ctx){
399         uint8_t i;
400         ctx->h[0] = 0x0001020304050607LL;
401         for(i=1; i<16; ++i){
402                 ctx->h[i] = ctx->h[i-1]+ 0x0808080808080808LL;
403         }
404 #if BUG24       
405         ctx->h[6] = 0x3031323324353637LL;
406 #endif
407         ctx->counter=0;
408         ctx_dump(ctx);
409 }
410
411 void bmw512_init(bmw512_ctx_t* ctx){
412         uint8_t i;
413         ctx->h[0] = 0x8081828384858687LL;
414         for(i=1; i<16; ++i){
415                 ctx->h[i] = ctx->h[i-1]+ 0x0808080808080808LL;
416         }
417         ctx->counter=0;
418         ctx_dump(ctx);
419 }
420
421 void bmw384_nextBlock(bmw384_ctx_t* ctx, const void* block){
422         bmw_large_nextBlock(ctx, block);
423 }
424
425 void bmw512_nextBlock(bmw512_ctx_t* ctx, const void* block){
426         bmw_large_nextBlock(ctx, block);
427 }
428
429 void bmw384_lastBlock(bmw384_ctx_t* ctx, const void* block, uint16_t length_b){
430         bmw_large_lastBlock(ctx, block, length_b);
431 }
432
433 void bmw512_lastBlock(bmw512_ctx_t* ctx, const void* block, uint16_t length_b){
434         bmw_large_lastBlock(ctx, block, length_b);
435 }
436
437 void bmw384_ctx2hash(void* dest, const bmw384_ctx_t* ctx){
438         memcpy(dest, &(ctx->h[10]), 384/8);
439 }
440
441 void bmw512_ctx2hash(void* dest, const bmw512_ctx_t* ctx){
442         memcpy(dest, &(ctx->h[8]), 512/8);
443 }
444
445 void bmw384(void* dest, const void* msg, uint32_t length_b){
446         bmw_large_ctx_t ctx;
447         bmw384_init(&ctx);
448         while(length_b>=BMW_LARGE_BLOCKSIZE){
449                 bmw_large_nextBlock(&ctx, msg);
450                 length_b -= BMW_LARGE_BLOCKSIZE;
451                 msg = (uint8_t*)msg + BMW_LARGE_BLOCKSIZE_B;
452         }
453         bmw_large_lastBlock(&ctx, msg, length_b);
454         bmw384_ctx2hash(dest, &ctx);
455 }
456
457 void bmw512(void* dest, const void* msg, uint32_t length_b){
458         bmw_large_ctx_t ctx;
459         bmw512_init(&ctx);
460         while(length_b>=BMW_LARGE_BLOCKSIZE){
461                 bmw_large_nextBlock(&ctx, msg);
462                 length_b -= BMW_LARGE_BLOCKSIZE;
463                 msg = (uint8_t*)msg + BMW_LARGE_BLOCKSIZE_B;
464         }
465         bmw_large_lastBlock(&ctx, msg, length_b);
466         bmw512_ctx2hash(dest, &ctx);
467 }
468