]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/shavs.c
clean up
[avr-crypto-lib.git] / test_src / shavs.c
1 /* shavs.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006 2007 2008 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        shavs.c
21  * \author  Daniel Otte
22  * \date    2006-05-16
23  * \license     GPLv3 or later
24  *
25  */
26
27 #include <avr/pgmspace.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include "hashfunction_descriptor.h"
33 #include "hfal/hfal-basic.h"
34 #include "shavs.h"
35 #include "string-extras.h"
36 #include "cli.h"
37
38
39 #ifdef DEBUG
40 #  undef DEBUG
41 #endif
42
43 #define DEBUG 0
44
45 #if DEBUG
46 #  include "config.h"
47 #  include <util/delay.h>
48 #endif
49
50 hfdesc_t*  shavs_algo=NULL;
51 hfdesc_t** shavs_algolist=NULL;
52
53 void shavs_listalgos(void){
54         char option = 'a';
55
56         hfdesc_t* t;
57         uint8_t i=0;
58         cli_putstr_P(PSTR("\r\nthe following algorithms are available:\r\n"));
59         while(option<='z' && (t=(hfdesc_t*)pgm_read_word(&(shavs_algolist[i])))){
60                 cli_putc('\t');
61                 cli_putc((t==shavs_algo)?'*':' ');
62                 cli_putc(option++);
63                 cli_putstr_P(PSTR(":\t"));
64                 cli_putstr_P((void*)(pgm_read_word(&(t->name))));
65                 cli_putstr_P(PSTR("\r\n"));
66                 i++;
67         }
68 }
69
70 void shavs_setalgo(char* param){
71         param = strstrip(param);
72         if(param[1]=='\0'){ /* single letter specified */
73                 uint8_t i,option = param[0]-'a';
74
75                 if(!shavs_algolist){
76                         cli_putstr_P(PSTR("\r\nERROR: shavs_algolist not set!"));
77                         return;
78                 }
79                 for(i=0; i<=option; ++i){
80                         if((void*)pgm_read_word(&(shavs_algolist[i]))==NULL){
81                                 cli_putstr_P(PSTR("\r\nERROR: invalid selection!"));
82                                 return;
83                         }
84                 }
85                 shavs_algo=(hfdesc_t*)pgm_read_word(&(shavs_algolist[option]));
86         } else { /* name specifyed */
87                 hfdesc_t* t=NULL;
88                 uint8_t i=0;
89                 while((t=(hfdesc_t*)pgm_read_word(&(shavs_algolist[i]))) &&
90                        strcasecmp_P(param, (void*)pgm_read_word(&(t->name))))
91                         ++i;
92                 if(t){
93                         shavs_algo=t;
94                 }else{
95                         cli_putstr_P(PSTR("\r\nERROR: could not find \""));
96                         cli_putstr(param);
97                         cli_putstr_P(PSTR("\"!"));
98                 }
99         }
100 }
101
102 typedef struct {
103         uint16_t buffer_idx;
104         uint16_t buffersize_B;
105         uint32_t blocks;
106         hfgen_ctx_t ctx;
107         uint8_t* buffer;
108         uint8_t  in_byte;
109 } shavs_ctx_t;
110
111 static shavs_ctx_t shavs_ctx;
112
113 uint8_t buffer_add(char c){
114         uint8_t v,t;
115         if(shavs_ctx.buffer_idx==shavs_ctx.buffersize_B){
116                 hfal_hash_nextBlock(&(shavs_ctx.ctx), shavs_ctx.buffer);
117                 ++shavs_ctx.blocks;
118                 shavs_ctx.buffer_idx=0;
119                 shavs_ctx.in_byte=0;
120                 cli_putc('.');
121                 memset(shavs_ctx.buffer, 0, shavs_ctx.buffersize_B);
122         }
123         if(c>='0' && c<='9'){
124                 v=c-'0';
125         }else{
126                 c &= (uint8_t)~('a' ^ 'A');
127                 if(c>='A' && c<='F'){
128                         v=c-'A'+10;
129                 }else{
130                         return 1;
131                 }
132         }
133         t=shavs_ctx.buffer[shavs_ctx.buffer_idx];
134         if(shavs_ctx.in_byte){
135                 t |= v;
136                 shavs_ctx.buffer[shavs_ctx.buffer_idx]=t;
137                 shavs_ctx.buffer_idx++;
138                 shavs_ctx.in_byte = 0;
139         }else{
140                 t |= v<<4;
141                 shavs_ctx.buffer[shavs_ctx.buffer_idx]=t;
142                 shavs_ctx.in_byte = 1;
143         }
144         return 0;
145 }
146
147 int32_t getLength(void){
148         uint32_t len=0;
149         char lenstr[21];
150         char* len2;
151         for(;;){
152                 memset(lenstr, 0, 21);
153                 cli_getsn_cecho(lenstr, 20);
154                 len2 = strstrip(lenstr);
155                 if(!strncasecmp_P(len2, PSTR("LEN"), 3)){
156                         while(*len2 && *len2!='=')
157                                 len2++;
158                         if(*len2=='='){
159                                 do{
160                                         len2++;
161                                 }while(*len2 && !isdigit(*len2));
162                                 len=(uint32_t)strtoul(len2, NULL, 10);
163                                 return len;
164                         }
165                 } else {
166                         if(!strncasecmp_P(len2, PSTR("EXIT"), 4)){
167                                 return -1;
168                         }
169                 }
170         }
171 }
172
173 void shavs_test1(void){ /* KAT tests */
174         uint32_t length=0;
175         int32_t expect_input=0;
176
177         if(!shavs_algo){
178                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
179                 return;
180         }
181         char c;
182         uint8_t diggest[pgm_read_word(&(shavs_algo->hashsize_b))/8];
183         shavs_ctx.buffersize_B=pgm_read_word(&(shavs_algo->blocksize_b))/8;
184         uint8_t buffer[shavs_ctx.buffersize_B+5];
185         shavs_ctx.buffer = buffer;
186         cli_putstr_P(PSTR("\r\nbuffer_size = 0x"));
187         cli_hexdump_rev(&(shavs_ctx.buffersize_B), 2);
188         cli_putstr_P(PSTR(" bytes"));
189         for(;;){
190                 shavs_ctx.blocks = 0;
191                 memset(buffer, 0, shavs_ctx.buffersize_B);
192                 length = getLength();
193                 if(length<0){
194                         return;
195                 }
196
197 #if DEBUG
198                 cli_putstr_P(PSTR("\r\nLen == "));
199                 cli_hexdump_rev(&length, 4);
200 #endif
201                 if(length==0){
202                         expect_input=2;
203                 }else{
204                         expect_input=((length+7)>>2)&(~1L);
205                 }
206 #if DEBUG
207                 cli_putstr_P(PSTR("\r\nexpected_input == "));
208                 cli_hexdump_rev(&expect_input, 4);
209                 if(expect_input==0)
210                         cli_putstr_P(PSTR("\r\nexpected_input == 0 !!!"));
211 #endif
212                 shavs_ctx.buffer_idx = 0;
213                 shavs_ctx.in_byte    = 0;
214                 shavs_ctx.blocks     = 0;
215                 uint8_t ret;
216 #if DEBUG
217                 cli_putstr_P(PSTR("\r\n HFAL init"));
218                 cli_putstr_P(PSTR("\r\n (2) expected_input == "));
219                 cli_hexdump_rev(&expect_input, 4);
220 #endif
221                 ret = hfal_hash_init(shavs_algo, &(shavs_ctx.ctx));
222                 if(ret){
223                         cli_putstr_P(PSTR("\r\n HFAL init returned with: "));
224                         cli_hexdump(&ret, 1);
225                         return;
226                 }
227 #if DEBUG
228                 cli_putstr_P(PSTR("\r\n (3) expected_input == "));
229                 cli_hexdump_rev(&expect_input, 4);
230                 cli_putstr_P(PSTR("\r\n"));
231 #endif
232                 while((c=cli_getc_cecho())!='M' && c!='m'){
233                         if(!isblank(c)){
234                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
235                                 cli_hexdump(&c, 1);
236                                 cli_putstr_P(PSTR("]!\r\n"));
237                                 hfal_hash_free(&(shavs_ctx.ctx));
238                                 return;
239                         }
240                 }
241                 if((c=cli_getc_cecho())!='s' && c!='S'){
242                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
243                                 hfal_hash_free(&(shavs_ctx.ctx));
244                                 return;
245                 }
246                 if((c=cli_getc_cecho())!='g' && c!='G'){
247                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
248                                 hfal_hash_free(&(shavs_ctx.ctx));
249                                 return;
250                 }
251                 while((c=cli_getc_cecho())!='='){
252                         if(!isblank(c)){
253                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
254                                 hfal_hash_free(&(shavs_ctx.ctx));
255                                 return;
256                         }
257                 }
258 #if DEBUG
259                 cli_putstr_P(PSTR("\r\nparsing started"));
260 #endif
261                 shavs_ctx.buffer_idx = 0;
262                 shavs_ctx.in_byte    = 0;
263                 shavs_ctx.blocks     = 0;
264                 while(expect_input>0){
265                         c=cli_getc_cecho();
266 #if DEBUG
267                         cli_putstr_P(PSTR("\r\n\t("));
268                         cli_hexdump_rev(&expect_input, 4);
269                         cli_putstr_P(PSTR(") "));
270                         _delay_ms(500);
271 #endif
272                         if(buffer_add(c)==0){
273                                 --expect_input;
274                         }else{
275                                 if(!isblank((uint16_t)c)){
276                                         cli_putstr_P(PSTR("\r\nERROR: wrong input (5) ("));
277                                         cli_putc(c);
278                                         cli_putstr_P(PSTR(")!\r\n"));
279                                         hfal_hash_free(&(shavs_ctx.ctx));
280                                         return;
281                                 }
282                         }
283                 }
284 #if DEBUG
285                 cli_putstr_P(PSTR("\r\nBuffer-A:"));
286                 cli_hexdump_block(buffer, shavs_ctx.buffersize_B, 5, 8);
287
288                 cli_putstr_P(PSTR("\r\n starting finalisation"));
289                 cli_putstr_P(PSTR("\r\n\tblocks     == "));
290                 cli_hexdump_rev(&(shavs_ctx.blocks),4);
291                 cli_putstr_P(PSTR("\r\n\tbuffer_idx == "));
292                 cli_hexdump_rev(&(shavs_ctx.buffer_idx),2);
293                 cli_putstr_P(PSTR("\r\n\tin_byte    == "));
294                 cli_hexdump_rev(&(shavs_ctx.in_byte),1);
295                 _delay_ms(500);
296
297                 cli_putstr_P(PSTR("\r\n starting last block"));
298                 cli_putstr_P(PSTR("\r\n\tlength       == "));
299                 cli_hexdump_rev(&length,4);
300                 cli_putstr_P(PSTR("\r\n\tbuffersize_B == "));
301                 cli_hexdump_rev(&(shavs_ctx.buffersize_B),2);
302                 uint16_t temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
303                 cli_putstr_P(PSTR("\r\n\t (temp)      == "));
304                 cli_hexdump_rev(&temp,2);
305                 _delay_ms(500);
306                 temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
307 #else
308                 uint16_t temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
309 #endif
310                 /*              cli_putstr_P(PSTR("\r\n\t (temp)      == "));
311                 cli_hexdump_rev(&temp,2); */
312                 hfal_hash_lastBlock( &(shavs_ctx.ctx), buffer, /* be aware of freaking compilers!!! */
313 //                                                      length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8));
314                                     temp );
315 #if DEBUG
316                 cli_putstr_P(PSTR("\r\n starting ctx2hash"));
317                 _delay_ms(500);
318 #endif
319                 hfal_hash_ctx2hash(diggest, &(shavs_ctx.ctx));
320 #if DEBUG
321                 cli_putstr_P(PSTR("\r\n starting hash free"));
322 #endif
323                 hfal_hash_free(&(shavs_ctx.ctx));
324                 cli_putstr_P(PSTR("\r\n MD = "));
325                 cli_hexdump(diggest, pgm_read_word(&(shavs_algo->hashsize_b))/8);
326
327         }
328 }
329
330 void shavs_test2(void){ /* Monte Carlo tests for SHA-1 & SHA-2 */
331         uint16_t expected_input;
332         uint16_t count;
333         uint8_t v;
334         uint8_t index=0;
335         char c;
336         if(!shavs_algo){
337                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
338                 return;
339         }
340         uint8_t ml=pgm_read_word(&(shavs_algo->hashsize_b))/8;
341         uint8_t m[ml*4+8];
342         for(;;){
343                 while((c=cli_getc_cecho())!='S' && c!='s'){
344                         if(!isblank(c)){
345                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
346                                 cli_hexdump(&c, 1);
347                                 cli_putstr_P(PSTR("]!\r\n"));
348                                 return;
349                         }
350                 }
351                 if((c=cli_getc_cecho())!='e' && c!='e'){
352                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
353                                 return;
354                 }
355                 if((c=cli_getc_cecho())!='e' && c!='e'){
356                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
357                                 return;
358                 }
359                 if((c=cli_getc_cecho())!='d' && c!='D'){
360                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
361                                 return;
362                 }
363                 while((c=cli_getc_cecho())!='='){
364                         if(!isblank(c)){
365                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (5)!\r\n"));
366                                 return;
367                         }
368                 }
369                 expected_input = ml*2;
370                 memset(m+2*ml, 0, ml);
371                 do{
372                         v=0xff;
373                         c=cli_getc_cecho();
374                         if(c>='0' && c<='9'){
375                                 v = c - '0';
376                         }else{
377                                 c |= 'A'^'a';
378                                 if(c>='a' && c<='f'){
379                                         v = c - 'a' +10;
380                                 }
381                         }
382                         if(v<0x10){
383                                 c=m[ml*2+index/2];
384                                 if(index&1){
385                                         c |= v;
386                                 }else{
387                                         c |=v<<4;
388                                 }
389                                 m[ml*2+index/2]=c;
390                                 index++;
391                                 expected_input--;
392                         }
393                 }while(expected_input);
394                 /* so we have the seed */
395                 cli_putstr_P(PSTR("\r\nstarting processing"));
396                 uint16_t j;
397                 for(count=0; count<100; ++count){
398                         memcpy(m, m+ml*2, ml);
399                         memcpy(m+ml, m+ml*2, ml);
400                         for(j=0; j<1000; ++j){
401                                 hfal_hash_mem(shavs_algo, m+ml*3, m, ml*3*8);
402                                 memmove(m, m+ml, 3*ml);
403                         }
404                         cli_putstr_P(PSTR("\r\n\r\nCOUNT = "));
405                         if(count>=10){
406                                 cli_putc(count/10+'0');
407                         }
408                         cli_putc(count%10+'0');
409                         cli_putstr_P(PSTR("\r\nMD = "));
410                         cli_hexdump(m+ml*2, ml);
411                 }
412         }
413 }
414
415 void shavs_test3(void){ /* Monte Carlo tests for SHA-3 */
416         uint16_t expected_input;
417         uint16_t count;
418         uint8_t v;
419         uint8_t index=0;
420         char c;
421         if(!shavs_algo){
422                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
423                 return;
424         }
425         uint8_t ml=pgm_read_word(&(shavs_algo->hashsize_b))/8;
426         uint8_t m[ml+128];
427         for(;;){
428                 while((c=cli_getc_cecho())!='S' && c!='s'){
429                         if(!isblank(c)){
430                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
431                                 cli_hexdump(&c, 1);
432                                 cli_putstr_P(PSTR("]!\r\n"));
433                                 return;
434                         }
435                 }
436                 if((c=cli_getc_cecho())!='e' && c!='e'){
437                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
438                                 return;
439                 }
440                 if((c=cli_getc_cecho())!='e' && c!='e'){
441                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
442                                 return;
443                 }
444                 if((c=cli_getc_cecho())!='d' && c!='D'){
445                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
446                                 return;
447                 }
448                 while((c=cli_getc_cecho())!='='){
449                         if(!isblank(c)){
450                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (5)!\r\n"));
451                                 return;
452                         }
453                 }
454                 expected_input = 1024/4;
455                 memset(m+ml, 0, 1024/8);
456                 do{
457                         v=0xff;
458                         c=cli_getc_cecho();
459                         if(c>='0' && c<='9'){
460                                 v = c - '0';
461                         }else{
462                                 c |= 'A'^'a';
463                                 if(c>='a' && c<='f'){
464                                         v = c - 'a' +10;
465                                 }
466                         }
467                         if(v<0x10){
468                                 c=m[ml+index/2];
469                                 if(index&1){
470                                         c |= v;
471                                 }else{
472                                         c |=v<<4;
473                                 }
474                                 m[ml+index/2]=c;
475                                 index++;
476                                 expected_input--;
477                         }
478                 }while(expected_input);
479                 /* so we have the seed */
480                 cli_putstr_P(PSTR("\r\nstarting processing"));
481                 uint16_t j;
482                 for(count=0; count<100; ++count){
483                         for(j=0; j<1000; ++j){
484                                 hfal_hash_mem(shavs_algo, m, m+ml, 1024);
485                                 memmove(m+ml, m, 1024/8);
486                         }
487                         cli_putstr_P(PSTR("\r\n\r\nj = "));
488                         if(count>=10){
489                                 cli_putc(count/10+'0');
490                         }
491                         cli_putc(count%10+'0');
492                         cli_putstr_P(PSTR("\r\nMD = "));
493                         cli_hexdump(m+ml, ml);
494
495                 }
496         }
497 }