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