]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/shavs.c
optimizing norx32
[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 <stdio.h>
32 #include <ctype.h>
33 #include "hashfunction_descriptor.h"
34 #include "hfal-basic.h"
35 #include "shavs.h"
36 #include "string-extras.h"
37 #include "cli.h"
38
39
40 #ifdef DEBUG
41 #  undef DEBUG
42 #endif
43
44 #define DEBUG 0
45
46 #if DEBUG
47 #  include "config.h"
48 #  include <util/delay.h>
49 #endif
50
51 hfdesc_t*  shavs_algo=NULL;
52 hfdesc_t** shavs_algolist=NULL;
53
54 #define shavs_out_file stdout
55
56 void shavs_listalgos(void){
57         char option = 'a';
58
59         hfdesc_t *t;
60         uint8_t i=0;
61         fputs_P(PSTR("\nthe following algorithms are available:\n"), shavs_out_file);
62         while(option <= 'z' && (t = (hfdesc_t*)pgm_read_word(&(shavs_algolist[i])))){
63             fprintf_P(shavs_out_file, PSTR("\t%c%c:\t%S\n"),
64                 (t == shavs_algo) ? '*' : ' ', option++, pgm_read_word(&(t->name)));
65                 i++;
66         }
67 }
68
69 void shavs_setalgo(char *param){
70         param = strstrip(param);
71         if(param[1]=='\0'){ /* single letter specified */
72                 uint8_t i, option = param[0] - 'a';
73
74                 if(!shavs_algolist){
75                         fputs_P(PSTR("\nERROR: shavs_algolist not set!"), shavs_out_file);
76                         return;
77                 }
78                 for(i=0; i<=option; ++i){
79                         if((void*)pgm_read_word(&(shavs_algolist[i]))==NULL){
80                                 fputs_P(PSTR("\r\nERROR: invalid selection!"), shavs_out_file);
81                                 return;
82                         }
83                 }
84                 shavs_algo=(hfdesc_t*)pgm_read_word(&(shavs_algolist[option]));
85         } else { /* name specifyed */
86                 hfdesc_t *t=NULL;
87                 uint8_t i=0;
88                 while((t=(hfdesc_t*)pgm_read_word(&(shavs_algolist[i]))) &&
89                        strcasecmp_P(param, (void*)pgm_read_word(&(t->name))))
90                         ++i;
91                 if(t){
92                         shavs_algo=t;
93                 }else{
94                     fprintf_P(shavs_out_file, PSTR("\nERROR: could not find \"%s\"!"), param);
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         return -1;
188 }
189
190 void shavs_test1(void){ /* KAT tests */
191         uint32_t length=0;
192         int32_t expect_input=0;
193
194         if(!shavs_algo){
195                         fputs_P(PSTR("\r\nERROR: select algorithm first!"), shavs_out_file);
196                 return;
197         }
198         char c;
199         uint8_t diggest[pgm_read_word(&(shavs_algo->hashsize_b))/8];
200         shavs_ctx.buffersize_B=pgm_read_word(&(shavs_algo->blocksize_b))/8;
201         uint8_t buffer[shavs_ctx.buffersize_B+5];
202         shavs_ctx.buffer = buffer;
203         fprintf_P(shavs_out_file, PSTR("\nbuffer_size = 0x%04"PRIx16" bytes"), shavs_ctx.buffersize_B);
204         for(;;){
205                 shavs_ctx.blocks = 0;
206                 memset(buffer, 0, shavs_ctx.buffersize_B);
207                 length = getLength();
208                 if(length<0){
209                         return;
210                 }
211
212 #if DEBUG
213                 fprintf_P(shavs_out_file, PSTR("\nLen == %"PRIu32), length)
214 #endif
215                 if(length==0){
216                         expect_input=2;
217                 }else{
218                         expect_input=((length + 7) >> 2) & (~1L);
219                 }
220 #if DEBUG
221                 fprintf_P(shavs_out_file, PSTR("\r\nexpected_input == %"PRId32), expected_input);
222 #endif
223                 shavs_ctx.buffer_idx = 0;
224                 shavs_ctx.in_byte    = 0;
225                 shavs_ctx.blocks     = 0;
226                 uint8_t ret;
227 #if DEBUG
228                 fprintf_P(shavs_out_file, PSTR("\n HFAL init\n (2) expected_input == "), expected_input);
229 #endif
230                 ret = hfal_hash_init(shavs_algo, &(shavs_ctx.ctx));
231                 if(ret){
232                         fprintf_P(shavs_out_file, PSTR("\r\n HFAL init returned with: %"PRIx8), ret);
233                         return;
234                 }
235 #if DEBUG
236                 fprintf_P(shavs_out_file, PSTR("\r\n (3) expected_input == %"PRId32"\n"), expected_input)
237 #endif
238                 while((c=cli_getc_cecho())!='M' && c!='m'){
239                         if(!isblank(c)){
240                             fprintf_P(shavs_out_file, PSTR("\nERROR: wrong input (1) [0x%"PRIx8"]!\n"), c);
241                                 hfal_hash_free(&(shavs_ctx.ctx));
242                                 return;
243                         }
244                 }
245                 if((c=cli_getc_cecho())!='s' && c!='S'){
246             fputs_P(PSTR("\nERROR: wrong input (2)!\n"), shavs_out_file);
247             hfal_hash_free(&(shavs_ctx.ctx));
248             return;
249                 }
250                 if((c=cli_getc_cecho())!='g' && c!='G'){
251             fputs_P(PSTR("\nERROR: wrong input (3)!\n"), shavs_out_file);
252             hfal_hash_free(&(shavs_ctx.ctx));
253             return;
254                 }
255                 while((c=cli_getc_cecho())!='='){
256                         if(!isblank(c)){
257                 fputs_P(PSTR("\nERROR: wrong input (4)!\n"), shavs_out_file);
258                                 hfal_hash_free(&(shavs_ctx.ctx));
259                                 return;
260                         }
261                 }
262 #if DEBUG
263                 fputs_P(PSTR("\r\nparsing started"), shavs_out_file);
264 #endif
265                 shavs_ctx.buffer_idx = 0;
266                 shavs_ctx.in_byte    = 0;
267                 shavs_ctx.blocks     = 0;
268                 while(expect_input>0){
269                         c=cli_getc_cecho();
270 #if DEBUG
271                         fprintf_P(shavs_out_file, PSTR("\n\t(%"PRId32") "), expected_input);
272                         _delay_ms(500);
273 #endif
274                         if(buffer_add(c)==0){
275                                 --expect_input;
276                         }else{
277                                 if(!isblank((uint16_t)c)){
278                                     fprintf_P(shavs_out_file, PSTR("\nERROR: wrong input (5) (%c)!\n"), c);
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                 hfal_hash_lastBlock( &(shavs_ctx.ctx), buffer, /* be aware of freaking compilers!!! */
311                                     temp );
312 #if DEBUG
313                 cli_putstr_P(PSTR("\r\n starting ctx2hash"));
314                 _delay_ms(500);
315 #endif
316                 hfal_hash_ctx2hash(diggest, &(shavs_ctx.ctx));
317 #if DEBUG
318                 cli_putstr_P(PSTR("\r\n starting hash free"));
319 #endif
320                 hfal_hash_free(&(shavs_ctx.ctx));
321                 cli_putstr_P(PSTR("\r\n MD = "));
322                 cli_hexdump(diggest, pgm_read_word(&(shavs_algo->hashsize_b))/8);
323
324         }
325 }
326
327 void shavs_test2(void){ /* Monte Carlo tests for SHA-1 & SHA-2 */
328         uint16_t expected_input;
329         uint16_t count;
330         uint8_t v;
331         uint8_t index=0;
332         char c;
333         if(!shavs_algo){
334                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
335                 return;
336         }
337         uint8_t ml=pgm_read_word(&(shavs_algo->hashsize_b))/8;
338         uint8_t m[ml*4+8];
339         for(;;){
340                 while((c=cli_getc_cecho())!='S' && c!='s'){
341                         if(!isblank(c)){
342                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
343                                 cli_hexdump(&c, 1);
344                                 cli_putstr_P(PSTR("]!\r\n"));
345                                 return;
346                         }
347                 }
348                 if((c=cli_getc_cecho())!='e' && c!='e'){
349                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
350                                 return;
351                 }
352                 if((c=cli_getc_cecho())!='e' && c!='e'){
353                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
354                                 return;
355                 }
356                 if((c=cli_getc_cecho())!='d' && c!='D'){
357                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
358                                 return;
359                 }
360                 while((c=cli_getc_cecho())!='='){
361                         if(!isblank(c)){
362                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (5)!\r\n"));
363                                 return;
364                         }
365                 }
366                 expected_input = ml*2;
367                 memset(m+2*ml, 0, ml);
368                 do{
369                         v=0xff;
370                         c=cli_getc_cecho();
371                         if(c>='0' && c<='9'){
372                                 v = c - '0';
373                         }else{
374                                 c |= 'A'^'a';
375                                 if(c>='a' && c<='f'){
376                                         v = c - 'a' +10;
377                                 }
378                         }
379                         if(v<0x10){
380                                 c=m[ml*2+index/2];
381                                 if(index&1){
382                                         c |= v;
383                                 }else{
384                                         c |=v<<4;
385                                 }
386                                 m[ml*2+index/2]=c;
387                                 index++;
388                                 expected_input--;
389                         }
390                 }while(expected_input);
391                 /* so we have the seed */
392                 cli_putstr_P(PSTR("\r\nstarting processing"));
393                 uint16_t j;
394                 for(count=0; count<100; ++count){
395                         memcpy(m, m+ml*2, ml);
396                         memcpy(m+ml, m+ml*2, ml);
397                         for(j=0; j<1000; ++j){
398                                 hfal_hash_mem(shavs_algo, m+ml*3, m, ml*3*8);
399                                 memmove(m, m+ml, 3*ml);
400                         }
401                         cli_putstr_P(PSTR("\r\n\r\nCOUNT = "));
402                         if(count>=10){
403                                 cli_putc(count/10+'0');
404                         }
405                         cli_putc(count%10+'0');
406                         cli_putstr_P(PSTR("\r\nMD = "));
407                         cli_hexdump(m+ml*2, ml);
408                 }
409         }
410 }
411
412 void shavs_test3(void){ /* Monte Carlo tests for SHA-3 */
413         uint16_t expected_input;
414         uint16_t count;
415         uint8_t v;
416         uint8_t index=0;
417         char c;
418         if(!shavs_algo){
419                         cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
420                 return;
421         }
422         uint8_t ml=pgm_read_word(&(shavs_algo->hashsize_b))/8;
423         uint8_t m[ml+128];
424         for(;;){
425                 while((c=cli_getc_cecho())!='S' && c!='s'){
426                         if(!isblank(c)){
427                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
428                                 cli_hexdump(&c, 1);
429                                 cli_putstr_P(PSTR("]!\r\n"));
430                                 return;
431                         }
432                 }
433                 if((c=cli_getc_cecho())!='e' && c!='e'){
434                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
435                                 return;
436                 }
437                 if((c=cli_getc_cecho())!='e' && c!='e'){
438                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
439                                 return;
440                 }
441                 if((c=cli_getc_cecho())!='d' && c!='D'){
442                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
443                                 return;
444                 }
445                 while((c=cli_getc_cecho())!='='){
446                         if(!isblank(c)){
447                                 cli_putstr_P(PSTR("\r\nERROR: wrong input (5)!\r\n"));
448                                 return;
449                         }
450                 }
451                 expected_input = 1024/4;
452                 memset(m+ml, 0, 1024/8);
453                 do{
454                         v=0xff;
455                         c=cli_getc_cecho();
456                         if(c>='0' && c<='9'){
457                                 v = c - '0';
458                         }else{
459                                 c |= 'A'^'a';
460                                 if(c>='a' && c<='f'){
461                                         v = c - 'a' +10;
462                                 }
463                         }
464                         if(v<0x10){
465                                 c=m[ml+index/2];
466                                 if(index&1){
467                                         c |= v;
468                                 }else{
469                                         c |=v<<4;
470                                 }
471                                 m[ml+index/2]=c;
472                                 index++;
473                                 expected_input--;
474                         }
475                 }while(expected_input);
476                 /* so we have the seed */
477                 cli_putstr_P(PSTR("\r\nstarting processing"));
478                 uint16_t j;
479                 for(count=0; count<100; ++count){
480                         for(j=0; j<1000; ++j){
481                                 hfal_hash_mem(shavs_algo, m, m+ml, 1024);
482                                 memmove(m+ml, m, 1024/8);
483                         }
484                         cli_putstr_P(PSTR("\r\n\r\nj = "));
485                         if(count>=10){
486                                 cli_putc(count/10+'0');
487                         }
488                         cli_putc(count%10+'0');
489                         cli_putstr_P(PSTR("\r\nMD = "));
490                         cli_hexdump(m+ml, ml);
491
492                 }
493         }
494 }