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