]> git.cryptolib.org Git - avr-crypto-lib.git/blob - blake_small.c
+blake, bug compatibility by default off
[avr-crypto-lib.git] / blake_small.c
1 /* blake_small.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    blake_small.c
21  * \author  Daniel Otte
22  * \email   daniel.otte@rub.de
23  * \date    2009-05-04
24  * \license GPLv3 or later
25  * 
26  */
27
28 #include <stdint.h>
29 #include <string.h>
30 #include <avr/pgmspace.h>
31 #include "memxor.h"
32 #include "blake_small.h"
33 #include "blake_common.h"
34
35 #define DEBUG 0
36 #define DEBUG_2 0
37
38 #define BUG_1 0 /* bug compatibility for zero length message */
39 #define BUG_2 0 /* bug compatibility for messages of length%512=505...511 */
40
41
42 #if DEBUG_2
43  #include "cli.h"
44 #endif
45
46 #if DEBUG
47  #include "cli.h"
48  void dump_v(uint32_t* v){
49         uint8_t i;
50         cli_putstr_P(PSTR("\r\n=== v dump ==="));
51         for(i=0; i<16; ++i){
52                 if(i%8==0)
53                         cli_putstr_P(PSTR("\r\n\t"));
54                 cli_hexdump_rev(v+i, 4);
55                 cli_putc(' ');
56         }
57  }
58 #else
59  #define dump_v(v)
60 #endif
61
62 uint32_t blake_c[] PROGMEM = {
63    0x243F6A88, 0x85A308D3,
64    0x13198A2E, 0x03707344,
65    0xA4093822, 0x299F31D0,
66    0x082EFA98, 0xEC4E6C89,
67    0x452821E6, 0x38D01377,
68    0xBE5466CF, 0x34E90C6C,
69    0xC0AC29B7, 0xC97C50DD,
70    0x3F84D5B5, 0xB5470917
71 };
72
73 #define ROTL32(a, n) (((a)<<(n))|((a)>>(32-(n))))
74 #define ROTR32(a, n) (((a)>>(n))|((a)<<(32-(n))))
75 #define CHANGE_ENDIAN32(a) (((a)<<24)| \
76                             ((0x0000ff00&(a))<<8)| \
77                                                     ((0x00ff0000&(a))>>8)| \
78                                                     (a)>>24 )
79
80 void blake_small_g(uint8_t r, uint8_t i, uint32_t* v, const uint32_t* m){
81         uint8_t a,b,c,d, s0, s1;
82         a = pgm_read_byte(blake_index_lut+4*i+0);
83         b = pgm_read_byte(blake_index_lut+4*i+1);
84         c = pgm_read_byte(blake_index_lut+4*i+2);
85         d = pgm_read_byte(blake_index_lut+4*i+3);
86         s0 = pgm_read_byte(blake_sigma+16*r+2*i+0);
87         s1 = pgm_read_byte(blake_sigma+16*r+2*i+1);
88 #if DEBUG
89         if(i==0){
90                 cli_putstr_P(PSTR("\r\n s0 = "));
91                 cli_hexdump(&s0, 1);
92                 cli_putstr_P(PSTR("   s1 = "));
93                 cli_hexdump(&s1, 1);
94                 cli_putstr_P(PSTR("\r\n m[s0] = "));
95                 cli_hexdump_rev(m+s0, 4);
96                 cli_putstr_P(PSTR("\r\n m[s1] = "));
97                 cli_hexdump_rev(m+s1, 4);
98         }
99 #endif          
100         v[a] += v[b] + (m[s0] ^ pgm_read_dword(&(blake_c[s1])));
101         v[d]  = ROTR32(v[d]^v[a], 16);
102         v[c] += v[d];
103         v[b]  = ROTR32(v[b]^v[c], 12);  
104         v[a] += v[b] + (m[s1] ^ pgm_read_dword(&(blake_c[s0])));
105         v[d]  = ROTR32(v[d]^v[a], 8);
106         v[c] += v[d];
107         v[b]  = ROTR32(v[b]^v[c], 7);
108
109 }
110
111 void blake_small_expand(uint32_t* v, const blake_small_ctx_t* ctx){
112         uint8_t i;
113         memcpy(v, ctx->h, 8*4);
114         for(i=0; i<8; ++i){
115                 v[8+i] = pgm_read_dword(&(blake_c[i]));
116         }
117         memxor((uint8_t*)v+8, ctx->s, 4*4);
118         
119 }
120
121 void blake_small_changeendian(void* dest, const void* src){
122         uint8_t i;
123         for(i=0; i<16; ++i){
124                 ((uint32_t*)dest)[i] = CHANGE_ENDIAN32(((uint32_t*)src)[i]);
125         }
126 }
127
128 void blake_small_compress(uint32_t* v,const void* m){
129         uint8_t r,i;
130 #if DEBUG       
131         cli_putstr_P(PSTR("\r\n== compress 32 =="));
132         dump_v(v);
133 #endif
134 #if DEBUG_2
135         cli_putstr_P(PSTR("\r\n=== message block ===\r\n m ="));
136         cli_hexdump_block(m, 512/8, 4, 16);
137 #endif
138         for(r=0; r<10; ++r){
139                 for(i=0; i<8; ++i){
140                         blake_small_g(r, i, v, (uint32_t*)m);
141 #if DEBUG
142                         if(1){
143                                 cli_putstr_P(PSTR("\r\n ROUND: "));
144                                 cli_hexdump(&r,1);
145                                 cli_putstr_P(PSTR("    I: "));
146                                 cli_hexdump(&i,1);
147                                 dump_v(v);
148                         }
149 #endif
150                 }
151         }
152 }
153
154 void blake_small_collapse(blake_small_ctx_t* ctx, uint32_t* v){
155         uint8_t i;
156         for(i=0; i<8; ++i){
157                 ctx->h[i] ^= ctx->s[i%4] ^ v[i] ^ v[8+i];
158         }
159 }       
160
161 void blake_small_nextBlock(blake_small_ctx_t* ctx, const void* msg){
162         uint32_t v[16];
163         uint32_t m[16];
164         union {
165                 uint64_t v64;
166                 uint32_t v32[2];
167         }ctr;
168         blake_small_expand(v,ctx);
169         ctx->counter++;
170         ctr.v64 = ctx->counter*512;
171         v[12] ^= ctr.v32[0];
172         v[13] ^= ctr.v32[0];
173         v[14] ^= ctr.v32[1];
174         v[15] ^= ctr.v32[1];
175         blake_small_changeendian(m, msg);
176         blake_small_compress(v, m);
177         blake_small_collapse(ctx, v);
178 }
179
180 void blake_small_lastBlock(blake_small_ctx_t* ctx, const void* msg, uint16_t length_b){
181         while(length_b>=BLAKE_SMALL_BLOCKSIZE){
182                 blake_small_nextBlock(ctx, msg);
183                 msg = (uint8_t*)msg + BLAKE_SMALL_BLOCKSIZE_B;
184                 length_b -= BLAKE_SMALL_BLOCKSIZE;
185         }
186         uint8_t buffer[64];
187         uint32_t v[16];
188 #if BUG_2
189         uint32_t tmp=0;
190 #endif
191         union {
192                 uint64_t v64;
193                 uint32_t v32[2];
194         }ctr;
195         ctr.v64 = ctx->counter*512+length_b;
196 #if BUG_2
197         if(length_b>=505){
198                 tmp =ctr.v32[0];
199                 ctr.v32[0] = ctx->counter*512;
200                 ctr.v32[0] |= 0x40+length_b-504;
201         }
202 #endif  
203         memset(buffer, 0, 64);
204         memcpy(buffer, msg, (length_b+7)/8);
205         buffer[length_b/8] |= 0x80 >> (length_b%8);
206         blake_small_changeendian(buffer, buffer);
207         blake_small_expand(v, ctx);
208         v[12] ^= ctr.v32[0];
209         v[13] ^= ctr.v32[0];
210         v[14] ^= ctr.v32[1];
211         v[15] ^= ctr.v32[1];
212 #if BUG_2
213         if(length_b>=505)
214                 ctr.v32[0] = tmp;
215 #endif
216 #if BUG_1       
217         if(length_b==0 && ctx->counter==0){
218                 v[14] ^= 1;
219                 v[15] ^= 1;
220         }
221 #endif  
222         if(length_b>512-64-2){
223                 blake_small_compress(v, buffer);
224                 blake_small_collapse(ctx, v);
225                 memset(buffer, 0, 64-8);
226                 blake_small_expand(v, ctx);
227         }
228         if(ctx->appendone)
229                 buffer[64-8-4] |= 0x01; 
230         *((uint32_t*)(&(buffer[64-8]))) = ctr.v32[1];
231         *((uint32_t*)(&(buffer[64-4]))) = ctr.v32[0];
232         blake_small_compress(v, buffer);
233         blake_small_collapse(ctx, v);
234         
235 }
236
237 uint32_t blake32_iv[] PROGMEM = {
238         0x6A09E667L, 0xBB67AE85,
239         0x3C6EF372L, 0xA54FF53A,
240         0x510E527FL, 0x9B05688C,
241         0x1F83D9ABL, 0x5BE0CD19
242 };
243
244 void blake32_init(blake32_ctx_t* ctx){
245         uint8_t i;
246         for(i=0; i<8; ++i){
247                 ctx->h[i] = pgm_read_dword(&(blake32_iv[i]));
248         }
249         memset(ctx->s, 0, 4*4);
250         ctx->counter = 0;
251         ctx->appendone = 1;
252 }
253
254 uint32_t blake28_iv[] PROGMEM = {
255         0xC1059ED8, 0x367CD507,
256         0x3070DD17, 0xF70E5939,
257         0xFFC00B31, 0x68581511,
258         0x64F98FA7, 0xBEFA4FA4
259 };
260
261 void blake28_init(blake28_ctx_t* ctx){
262         uint8_t i;
263         for(i=0; i<8; ++i){
264                 ctx->h[i] = pgm_read_dword(&(blake28_iv[i]));
265         }
266         memset(ctx->s, 0, 4*4);
267         ctx->counter = 0;
268         ctx->appendone = 0;
269 }
270
271 void blake32_ctx2hash(void* dest, const blake32_ctx_t* ctx){
272         uint8_t i;
273         for(i=0; i<8; ++i){
274                 ((uint32_t*)dest)[i] = CHANGE_ENDIAN32(ctx->h[i]);
275         }
276 }
277
278 void blake28_ctx2hash(void* dest, const blake28_ctx_t* ctx){
279         uint8_t i;
280         for(i=0; i<7; ++i){
281                 ((uint32_t*)dest)[i] = CHANGE_ENDIAN32(ctx->h[i]);
282         }
283 }
284
285 void blake32_nextBlock(blake32_ctx_t* ctx, const void* block){
286         blake_small_nextBlock(ctx, block);
287 }
288
289 void blake28_nextBlock(blake28_ctx_t* ctx, const void* block){
290         blake_small_nextBlock(ctx, block);
291 }
292
293 void blake32_lastBlock(blake32_ctx_t* ctx, const void* block, uint16_t length_b){
294         blake_small_lastBlock(ctx, block, length_b);
295 }
296
297 void blake28_lastBlock(blake28_ctx_t* ctx, const void* block, uint16_t length_b){
298         blake_small_lastBlock(ctx, block, length_b);
299 }
300
301 void blake32(void* dest, const void* msg, uint32_t length_b){
302         blake_small_ctx_t ctx;
303         blake32_init(&ctx);
304         while(length_b>=BLAKE_SMALL_BLOCKSIZE){
305                 blake_small_nextBlock(&ctx, msg);
306                 msg = (uint8_t*)msg + BLAKE_SMALL_BLOCKSIZE_B;
307                 length_b -= BLAKE_SMALL_BLOCKSIZE;
308         }
309         blake_small_lastBlock(&ctx, msg, length_b);
310         blake32_ctx2hash(dest, &ctx);
311 }
312
313 void blake28(void* dest, const void* msg, uint32_t length_b){
314         blake_small_ctx_t ctx;
315         blake28_init(&ctx);
316         while(length_b>=BLAKE_SMALL_BLOCKSIZE){
317                 blake_small_nextBlock(&ctx, msg);
318                 msg = (uint8_t*)msg + BLAKE_SMALL_BLOCKSIZE_B;
319                 length_b -= BLAKE_SMALL_BLOCKSIZE;
320         }
321         blake_small_lastBlock(&ctx, msg, length_b);
322         blake28_ctx2hash(dest, &ctx);
323 }