]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/shavs.c
a lot of fixes
[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-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                 cli_putc('.');
120         }
121         if(c>='0' && c<='9'){
122                 v=c-'0';
123         }else{
124                 c &= (uint8_t)~('a' ^ 'A');
125                 if(c>='A' && c<='F'){
126                         v=c-'A'+10;
127                 }else{
128                         return 1;
129                 }
130         }
131         t=shavs_ctx.buffer[shavs_ctx.buffer_idx];
132         if(shavs_ctx.in_byte){
133                 t |= v;
134                 shavs_ctx.buffer[shavs_ctx.buffer_idx] = t;
135                 shavs_ctx.buffer_idx++;
136                 shavs_ctx.in_byte = 0;
137         }else{
138                 t = v<<4;
139                 shavs_ctx.buffer[shavs_ctx.buffer_idx] = t;
140                 shavs_ctx.in_byte = 1;
141         }
142         return 0;
143 }
144
145 static
146 uint32_t my_strtoul(const char* str){
147         uint32_t r=0;
148         while(*str && (*str<'0' || *str>'9')){
149                 str++;
150         }
151         if(!*str){
152                 return 0;
153         }
154         while(*str && (*str>='0' && *str<='9')){
155                 r *= 10;
156                 r += *str-'0';
157                 str++;
158         }
159         return r;
160 }
161
162 int32_t getLength(void){
163         uint32_t len=0;
164         char lenstr[21];
165         char* len2;
166         for(;;){
167                 memset(lenstr, 0, 21);
168                 cli_getsn_cecho(lenstr, 20);
169                 len2 = strstrip(lenstr);
170                 if(!strncasecmp_P(len2, PSTR("LEN"), 3)){
171                         while(*len2 && *len2!='=')
172                                 len2++;
173                         if(*len2=='='){
174                                 do{
175                                         len2++;
176                                 }while(*len2 && !isdigit((uint8_t)*len2));
177                                 len = my_strtoul(len2);
178                                 //len=(uint32_t)strtoul(len2, NULL, 10);
179                                 return len;
180                         }
181                 } else {
182                         if(!strncasecmp_P(len2, PSTR("EXIT"), 4)){
183                                 return -1;
184                         }
185                 }
186         }
187 }
188
189 void shavs_test1(void){ /* KAT tests */
190         uint32_t length=0;
191         int32_t expect_input=0;
192
193         if(!shavs_algo){
194                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
195                 return;
196         }
197         char c;
198         uint8_t diggest[pgm_read_word(&(shavs_algo->hashsize_b))/8];
199         shavs_ctx.buffersize_B=pgm_read_word(&(shavs_algo->blocksize_b))/8;
200         uint8_t buffer[shavs_ctx.buffersize_B+5];
201         shavs_ctx.buffer = buffer;
202         cli_putstr_P(PSTR("\r\nbuffer_size = 0x"));
203         cli_hexdump_rev(&(shavs_ctx.buffersize_B), 2);
204         cli_putstr_P(PSTR(" bytes"));
205         for(;;){
206                 shavs_ctx.blocks = 0;
207                 memset(buffer, 0, shavs_ctx.buffersize_B);
208                 length = getLength();
209                 if(length<0){
210                         return;
211                 }
212
213 #if DEBUG
214                 cli_putstr_P(PSTR("\r\nLen == "));
215                 cli_hexdump_rev(&length, 4);
216 #endif
217                 if(length==0){
218                         expect_input=2;
219                 }else{
220                         expect_input=((length + 7) >> 2) & (~1L);
221                 }
222 #if DEBUG
223                 cli_putstr_P(PSTR("\r\nexpected_input == "));
224                 cli_hexdump_rev(&expect_input, 4);
225                 if(expect_input==0)
226                         cli_putstr_P(PSTR("\r\nexpected_input == 0 !!!"));
227 #endif
228                 shavs_ctx.buffer_idx = 0;
229                 shavs_ctx.in_byte    = 0;
230                 shavs_ctx.blocks     = 0;
231                 uint8_t ret;
232 #if DEBUG
233                 cli_putstr_P(PSTR("\r\n HFAL init"));
234                 cli_putstr_P(PSTR("\r\n (2) expected_input == "));
235                 cli_hexdump_rev(&expect_input, 4);
236 #endif
237                 ret = hfal_hash_init(shavs_algo, &(shavs_ctx.ctx));
238                 if(ret){
239                         cli_putstr_P(PSTR("\r\n HFAL init returned with: "));
240                         cli_hexdump(&ret, 1);
241                         return;
242                 }
243 #if DEBUG
244                 cli_putstr_P(PSTR("\r\n (3) expected_input == "));
245                 cli_hexdump_rev(&expect_input, 4);
246                 cli_putstr_P(PSTR("\r\n"));
247 #endif
248                 while((c=cli_getc_cecho())!='M' && c!='m'){
249                         if(!isblank(c)){
250                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
251                                 cli_hexdump(&c, 1);
252                                 cli_putstr_P(PSTR("]!\r\n"));
253                                 hfal_hash_free(&(shavs_ctx.ctx));
254                                 return;
255                         }
256                 }
257                 if((c=cli_getc_cecho())!='s' && c!='S'){
258                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
259                                 hfal_hash_free(&(shavs_ctx.ctx));
260                                 return;
261                 }
262                 if((c=cli_getc_cecho())!='g' && c!='G'){
263                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
264                                 hfal_hash_free(&(shavs_ctx.ctx));
265                                 return;
266                 }
267                 while((c=cli_getc_cecho())!='='){
268                         if(!isblank(c)){
269                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
270                                 hfal_hash_free(&(shavs_ctx.ctx));
271                                 return;
272                         }
273                 }
274 #if DEBUG
275                 cli_putstr_P(PSTR("\r\nparsing started"));
276 #endif
277                 shavs_ctx.buffer_idx = 0;
278                 shavs_ctx.in_byte    = 0;
279                 shavs_ctx.blocks     = 0;
280                 while(expect_input>0){
281                         c=cli_getc_cecho();
282 #if DEBUG
283                         cli_putstr_P(PSTR("\r\n\t("));
284                         cli_hexdump_rev(&expect_input, 4);
285                         cli_putstr_P(PSTR(") "));
286                         _delay_ms(500);
287 #endif
288                         if(buffer_add(c)==0){
289                                 --expect_input;
290                         }else{
291                                 if(!isblank((uint16_t)c)){
292                                         cli_putstr_P(PSTR("\r\nERROR: wrong input (5) ("));
293                                         cli_putc(c);
294                                         cli_putstr_P(PSTR(")!\r\n"));
295                                         hfal_hash_free(&(shavs_ctx.ctx));
296                                         return;
297                                 }
298                         }
299                 }
300 #if DEBUG
301                 cli_putstr_P(PSTR("\r\nBuffer-A:"));
302                 cli_hexdump_block(buffer, shavs_ctx.buffersize_B, 5, 8);
303
304                 cli_putstr_P(PSTR("\r\n starting finalisation"));
305                 cli_putstr_P(PSTR("\r\n\tblocks     == "));
306                 cli_hexdump_rev(&(shavs_ctx.blocks),4);
307                 cli_putstr_P(PSTR("\r\n\tbuffer_idx == "));
308                 cli_hexdump_rev(&(shavs_ctx.buffer_idx),2);
309                 cli_putstr_P(PSTR("\r\n\tin_byte    == "));
310                 cli_hexdump_rev(&(shavs_ctx.in_byte),1);
311                 _delay_ms(500);
312
313                 cli_putstr_P(PSTR("\r\n starting last block"));
314                 cli_putstr_P(PSTR("\r\n\tlength       == "));
315                 cli_hexdump_rev(&length,4);
316                 cli_putstr_P(PSTR("\r\n\tbuffersize_B == "));
317                 cli_hexdump_rev(&(shavs_ctx.buffersize_B),2);
318                 uint16_t temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
319                 cli_putstr_P(PSTR("\r\n\t (temp)      == "));
320                 cli_hexdump_rev(&temp,2);
321                 _delay_ms(500);
322                 temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
323 #else
324                 uint16_t temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
325 #endif
326                 hfal_hash_lastBlock( &(shavs_ctx.ctx), buffer, /* be aware of freaking compilers!!! */
327                                     temp );
328 #if DEBUG
329                 cli_putstr_P(PSTR("\r\n starting ctx2hash"));
330                 _delay_ms(500);
331 #endif
332                 hfal_hash_ctx2hash(diggest, &(shavs_ctx.ctx));
333 #if DEBUG
334                 cli_putstr_P(PSTR("\r\n starting hash free"));
335 #endif
336                 hfal_hash_free(&(shavs_ctx.ctx));
337                 cli_putstr_P(PSTR("\r\n MD = "));
338                 cli_hexdump(diggest, pgm_read_word(&(shavs_algo->hashsize_b))/8);
339
340         }
341 }
342
343 void shavs_test2(void){ /* Monte Carlo tests for SHA-1 & SHA-2 */
344         uint16_t expected_input;
345         uint16_t count;
346         uint8_t v;
347         uint8_t index=0;
348         char c;
349         if(!shavs_algo){
350                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
351                 return;
352         }
353         uint8_t ml=pgm_read_word(&(shavs_algo->hashsize_b))/8;
354         uint8_t m[ml*4+8];
355         for(;;){
356                 while((c=cli_getc_cecho())!='S' && c!='s'){
357                         if(!isblank(c)){
358                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
359                                 cli_hexdump(&c, 1);
360                                 cli_putstr_P(PSTR("]!\r\n"));
361                                 return;
362                         }
363                 }
364                 if((c=cli_getc_cecho())!='e' && c!='e'){
365                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
366                                 return;
367                 }
368                 if((c=cli_getc_cecho())!='e' && c!='e'){
369                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
370                                 return;
371                 }
372                 if((c=cli_getc_cecho())!='d' && c!='D'){
373                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
374                                 return;
375                 }
376                 while((c=cli_getc_cecho())!='='){
377                         if(!isblank(c)){
378                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (5)!\r\n"));
379                                 return;
380                         }
381                 }
382                 expected_input = ml*2;
383                 memset(m+2*ml, 0, ml);
384                 do{
385                         v=0xff;
386                         c=cli_getc_cecho();
387                         if(c>='0' && c<='9'){
388                                 v = c - '0';
389                         }else{
390                                 c |= 'A'^'a';
391                                 if(c>='a' && c<='f'){
392                                         v = c - 'a' +10;
393                                 }
394                         }
395                         if(v<0x10){
396                                 c=m[ml*2+index/2];
397                                 if(index&1){
398                                         c |= v;
399                                 }else{
400                                         c |=v<<4;
401                                 }
402                                 m[ml*2+index/2]=c;
403                                 index++;
404                                 expected_input--;
405                         }
406                 }while(expected_input);
407                 /* so we have the seed */
408                 cli_putstr_P(PSTR("\r\nstarting processing"));
409                 uint16_t j;
410                 for(count=0; count<100; ++count){
411                         memcpy(m, m+ml*2, ml);
412                         memcpy(m+ml, m+ml*2, ml);
413                         for(j=0; j<1000; ++j){
414                                 hfal_hash_mem(shavs_algo, m+ml*3, m, ml*3*8);
415                                 memmove(m, m+ml, 3*ml);
416                         }
417                         cli_putstr_P(PSTR("\r\n\r\nCOUNT = "));
418                         if(count>=10){
419                                 cli_putc(count/10+'0');
420                         }
421                         cli_putc(count%10+'0');
422                         cli_putstr_P(PSTR("\r\nMD = "));
423                         cli_hexdump(m+ml*2, ml);
424                 }
425         }
426 }
427
428 void shavs_test3(void){ /* Monte Carlo tests for SHA-3 */
429         uint16_t expected_input;
430         uint16_t count;
431         uint8_t v;
432         uint8_t index=0;
433         char c;
434         if(!shavs_algo){
435                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
436                 return;
437         }
438         uint8_t ml=pgm_read_word(&(shavs_algo->hashsize_b))/8;
439         uint8_t m[ml+128];
440         for(;;){
441                 while((c=cli_getc_cecho())!='S' && c!='s'){
442                         if(!isblank(c)){
443                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
444                                 cli_hexdump(&c, 1);
445                                 cli_putstr_P(PSTR("]!\r\n"));
446                                 return;
447                         }
448                 }
449                 if((c=cli_getc_cecho())!='e' && c!='e'){
450                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
451                                 return;
452                 }
453                 if((c=cli_getc_cecho())!='e' && c!='e'){
454                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
455                                 return;
456                 }
457                 if((c=cli_getc_cecho())!='d' && c!='D'){
458                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
459                                 return;
460                 }
461                 while((c=cli_getc_cecho())!='='){
462                         if(!isblank(c)){
463                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (5)!\r\n"));
464                                 return;
465                         }
466                 }
467                 expected_input = 1024/4;
468                 memset(m+ml, 0, 1024/8);
469                 do{
470                         v=0xff;
471                         c=cli_getc_cecho();
472                         if(c>='0' && c<='9'){
473                                 v = c - '0';
474                         }else{
475                                 c |= 'A'^'a';
476                                 if(c>='a' && c<='f'){
477                                         v = c - 'a' +10;
478                                 }
479                         }
480                         if(v<0x10){
481                                 c=m[ml+index/2];
482                                 if(index&1){
483                                         c |= v;
484                                 }else{
485                                         c |=v<<4;
486                                 }
487                                 m[ml+index/2]=c;
488                                 index++;
489                                 expected_input--;
490                         }
491                 }while(expected_input);
492                 /* so we have the seed */
493                 cli_putstr_P(PSTR("\r\nstarting processing"));
494                 uint16_t j;
495                 for(count=0; count<100; ++count){
496                         for(j=0; j<1000; ++j){
497                                 hfal_hash_mem(shavs_algo, m, m+ml, 1024);
498                                 memmove(m+ml, m, 1024/8);
499                         }
500                         cli_putstr_P(PSTR("\r\n\r\nj = "));
501                         if(count>=10){
502                                 cli_putc(count/10+'0');
503                         }
504                         cli_putc(count%10+'0');
505                         cli_putstr_P(PSTR("\r\nMD = "));
506                         cli_hexdump(m+ml, ml);
507
508                 }
509         }
510 }