OpenCores
URL https://opencores.org/ocsvn/bluespec_md6/bluespec_md6/trunk

Subversion Repositories bluespec_md6

[/] [bluespec_md6/] [trunk/] [C_implementation/] [md6_test.c] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 kfleming
/* File:    md6_test.c
2
** Author:  Ronald L. Rivest
3
** Address: Room 32G-692 Stata Center
4
**          32 Vassar Street
5
**          Cambridge, MA 02139
6
** Email:   rivest@mit.edu
7
** Date:    9/25/2008
8
**
9
** (The following license is known as "The MIT License")
10
**
11
** Copyright (c) 2008 Ronald L. Rivest
12
**
13
** Permission is hereby granted, free of charge, to any person obtaining a copy
14
** of this software and associated documentation files (the "Software"), to deal
15
** in the Software without restriction, including without limitation the rights
16
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
** copies of the Software, and to permit persons to whom the Software is
18
** furnished to do so, subject to the following conditions:
19
**
20
** The above copyright notice and this permission notice shall be included in
21
** all copies or substantial portions of the Software.
22
**
23
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
** THE SOFTWARE.
30
**
31
** (end of license)
32
**
33
** This file illustrates the use of the MD6 hash function.
34
** The files defining the md6 hash function are:
35
**    md6.h
36
**    md6_compress.c
37
**    md6_mode.c
38
**
39
** The files defining the interface between MD6 and the NIST SHA-3
40
** API are:
41
**    md6_nist.h
42
**    md6_nist.c
43
** The NIST SHA-3 API is defined in:
44
**    http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf
45
**
46
** See  http://groups.csail.mit.edu/cis/md6  for more information.
47
**
48
** Utility and test routines for working with md6:
49
**   md6_print_state       -- prints out "md6_state" data structure
50
**   md6_string            -- computes hash of a given input string
51
**   md6_file              -- computes hash of a given file
52
**   md6_test_1            -- simple test suite
53
**   md6_test_2            -- time trial
54
**   md6_test_3            -- writes out intermediate results to a file
55
**   main                  -- calls tests 1,2,3
56
*/
57
 
58
#include <assert.h>
59
#include <stdio.h>
60
#include <string.h>
61
#include <time.h>
62
 
63
#include "md6.h"
64
 
65
#define w  md6_w
66
#define c  md6_c
67
#define n  md6_n
68
#define b  md6_b
69
#define u  md6_u
70
#define v  md6_v
71
#define k  md6_k
72
#define q  md6_q
73
 
74
/* Useful macros: min and max */
75
#ifndef min
76
#define min(a,b) ((a)<(b)? (a) : (b))
77
#endif
78
#ifndef max
79
#define max(a,b) ((a)>(b)? (a) : (b))
80
#endif
81
 
82
 /* Print state.
83
*/
84
 
85
void md6_print_state(md6_state* st)
86
/*
87
** print out an md6_state in a nice way.
88
*/
89
{
90
  int i,j;
91
  printf("\nPrintout of md6_state:\n");
92
  printf(" initialized = %d\n",st->initialized);
93
  printf(" finalized =   %d\n",st->finalized);
94
  printf(" hashbitlen =    %d\n",st->hashbitlen);
95
  printf(" Key:\n");
96
  for (i=0;i<k;i++)
97
    printf("  %4d " PR_MD6_WORD "\n",i,(md6_word)(st->K[i]));
98
  printf(" L =                %d\n",st->L);
99
  printf(" r =                %d\n",st->r);
100
  printf(" Bits processed =   %lld\n",(uint64_t)st->bits_processed);
101
  printf(" Stack top =        %d\n",st->top);
102
  printf(" N:\n");
103
  for (j = 0;j<b;j++)
104
    { for (i = 1;i<=st->top;i++)
105
        printf("%4d %4d " PR_MD6_WORD,i,j,(md6_word)st->B[i][j]);
106
      printf("\n");
107
    }
108
  printf(" Bits on each level:\n");
109
  for (i=0;i<=st->top;i++)
110
    printf("  Level %2d: %2d\n",i,st->bits[i]);
111
  printf(" Hash Value:\n");
112
  for (i=0;i<c;i++)
113
    {
114
      if (i%32 == 0) printf("  ");
115
      printf("%02x",st->hashval[i]);
116
      if (i%8==7) printf(" ");
117
      if (i%32==31) printf("\n");
118
    }
119
  printf(" Hex Hash Value:\n");
120
  printf("  %s\n",st->hexhashval);
121
  printf("End of md6_state printout.\n\n");
122
}
123
 
124
 
125
void md6_print_hash(md6_state *st)
126
/*
127
** print out the hash value stored in the md6 state
128
*/
129
{
130
  printf("%s",st->hexhashval);
131
}
132
 
133
 
134
void md6_string(unsigned char *M,
135
                int rep,
136
                unsigned char *key,
137
                int d)
138
/*
139
** Compute the md6 hash of a zero-terminated input byte string M
140
** repeated rep times.  Print this hash value out with a trailing space
141
** and carriage return.
142
** Input:
143
**   M      input array of length m bytes
144
**   rep    number of times to repeat M
145
**   key    input zero-terminated key string
146
**   d      desired output hash size, in bits 1 <= d <= (c*w/2)
147
**          (c*w/2 = 512 bits)
148
*/
149
{
150
  md6_state st;
151
  uint64_t m;
152
  int i, keylen;
153
  int err;
154
 
155
  m = strlen((char *)M);
156
  keylen = (int)strlen((char *)key);
157
 
158
  /* check that input values are sensible */
159
  assert(( M != NULL ));
160
  assert(( (key == NULL) || ( (0<=keylen) && (keylen <= k*(w/8))) ) );
161
  assert(( (1 <= d) && (d <= c*w/2) ));
162
 
163
  /* printf("md6_string..."); */
164
 
165
  if ((err=md6_full_init(&st,d,key,keylen,md6_default_L,md6_default_r(d))))
166
      printf("Error code: %d\n",err);
167
  for (i=0;i<rep;i++)
168
    if ((err = md6_update(&st,M,8*(uint64_t)m)))
169
      printf("Error code: %d\n",err);
170
  if ((err = md6_final(&st,NULL)))
171
      printf("Error code: %d\n",err);
172
  md6_print_hash(&st);
173
  printf(" \"%s\"",M);
174
  if (rep>1) printf(" * %d",rep);
175
  printf("\n");
176
}
177
 
178
 
179
static void md6_file(char *filename)
180
/*
181
** compute and print out hash value for a file with given filename.
182
*/
183
{
184
  FILE *inFile = fopen (filename, "rb");
185
  md6_state st;
186
  uint64_t bytes;
187
  unsigned char data[1024];
188
  int err;
189
 
190
  if (inFile == NULL) {
191
    printf ("%s can't be opened.\n", filename);
192
    return;
193
  }
194
 
195
  if ((err=md6_init(&st,256)))
196
      printf("Error code: %d\n",err);
197
  while ((bytes = fread (data, 1, 1024, inFile)) != 0)
198
    if ((err=md6_update(&st, data, bytes*8)))
199
      printf("Error code: %d\n",err);
200
  if ((err=md6_final(&st,NULL)))
201
      printf("Error code: %d\n",err);
202
  md6_print_hash(&st);
203
  printf (" file: %s\n", filename);
204
  fclose (inFile);
205
}
206
 
207
 
208
void md6_test_1(void)
209
/*
210
** run a simple set of test values
211
*/
212
{ unsigned char *key;
213
  int d;
214
 
215
  printf("------------------------------------------------------------\n");
216
  printf("md6_test_1: start. [simple test suite]\n");
217
  printf(">> string * n means string repeated n times.\n\n");
218
 
219
  key = (unsigned char *)"";   /* yields all-zero key */
220
  d = min(256,c*w/2);
221
  printf(">> Key is all zeros.\n");
222
  printf(">> Hash Bit Length is %d bits.\n",d);
223
  md6_string((unsigned char *)"",1,key,d);
224
  md6_string((unsigned char *)"a",1,key,d);
225
  md6_string((unsigned char *)"abc",1,key,d);
226
  md6_string((unsigned char *)"abcdefghijklmnopqrstuvwxyz",1,key,d);
227
  md6_string((unsigned char *)"1234567890",1000000,key,d);
228
  printf("\n");
229
 
230
  key = (unsigned char *)"abcd1234";
231
  d = min(256,c*w/2);
232
  printf(">> Key is '%s'.\n",key);
233
  printf(">> Hash Bit Length is %d bits.\n",d);
234
  md6_string((unsigned char *)"",1,key,d);
235
  md6_string((unsigned char *)"a",1,key,d);
236
  md6_string((unsigned char *)"abc",1,key,d);
237
  md6_string((unsigned char *)"abcdefghijklmnopqrstuvwxyz",1,key,d);
238
  md6_string((unsigned char *)"1234567890",1000000,key,d);
239
  printf("\n");
240
 
241
  key = (unsigned char *)"";   /* yields all-zero key */
242
  d = min(160,c*w/2);
243
  printf(">> Key is all zeros.\n");
244
  printf(">> Hash Bit Length is %d bits.\n",d);
245
  md6_string((unsigned char *)"",1,key,d);
246
  md6_string((unsigned char *)"a",1,key,d);
247
  md6_string((unsigned char *)"abc",1,key,d);
248
  md6_string((unsigned char *)"abcdefghijklmnopqrstuvwxyz",1,key,d);
249
  md6_string((unsigned char *)"1234567890",1000000,key,d);
250
  printf("\n");
251
 
252
  printf("md6_test_1: end.\n\n");
253
}
254
 
255
 
256
/*
257
** rdtsc()
258
** returns CPU cycle counter using RDTSC intruction
259
** see http://en.wikipedia.org/wiki/RDTSC
260
** GNU Version -- see wikipedia for Microsoft Visual C++ version
261
** following routine is copied from Wikipedia page referenced above
262
* UNTESTED SO FAR...
263
*/
264
#if 0
265
extern "C" {
266
  __inline__ uint64_t rdtsc() {
267
    uint32_t lo, hi;
268
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
269
    /* we cannot use "=A" since this would use %rax on x86_64 */
270
    return (uint64_t)hi << 32 | lo;
271
  }
272
}
273
#endif
274
 
275
 
276
 
277
void md6_test_2(void)
278
/*
279
** run a simple time trial
280
*/
281
#define TEST_BLOCK_SIZE 100000                    /*     10**5 bytes*/
282
#define TEST_BLOCKS 1000                          /*     10**3 */
283
#define TEST_BYTES (TEST_BLOCKS*TEST_BLOCK_SIZE)  /*     10**9 bytes */
284
{ md6_state st;
285
  double endTime, startTime;
286
  unsigned char data[TEST_BLOCK_SIZE];
287
  unsigned long long int i;
288
  unsigned int dvals[] = {160,224,256,384,512};
289
  int ndvals = 5;
290
  int err;
291
  md6_word A[md6_max_r*c+n];
292
  int j;
293
  int d;
294
 
295
  printf("------------------------------------------------------------\n");
296
  printf("md6_test_2: start. [time trial]\n");
297
  printf(">> Key is all zeros.\n");
298
  printf ("Processing %lld characters...\n", (long long)TEST_BYTES);
299
 
300
  /* initialize test data */
301
  for (i = 0; i < TEST_BLOCK_SIZE; i++)
302
    data[i] = (unsigned char)(i & 0xFF);
303
 
304
  for (j=0;j<ndvals;j++)
305
    { d = dvals[j];
306
      printf("\nd = %d (hash bit length)\n",d);
307
      /* start timer */
308
      startTime = ((double)clock())/CLOCKS_PER_SEC;
309
 
310
      /* Process data in TEST_BLOCK_SIZE byte blocks */
311
      err = md6_init(&st,d);
312
      if (err) printf("Error code: %d\n",err);
313
      for (i = TEST_BLOCKS; i > 0; i--)
314
        if ((err=md6_update (&st, data, 8*TEST_BLOCK_SIZE)))
315
          printf("Error code %d\n",err);
316
      if ((err = md6_final(&st,NULL)))
317
        printf("Error code: %d\n",err);
318
 
319
      endTime = ((double)clock())/CLOCKS_PER_SEC;
320
      md6_print_hash(&st);printf (" is hash of test input.\n");
321
      printf
322
        ("time to process test input: %.3f seconds.\n", (endTime-startTime));
323
      if (endTime>startTime)
324
        printf
325
          ("md6 bytes per second: %f\n", TEST_BYTES/(endTime-startTime));
326
      printf("md6 time per compression function (512 bytes) = %g microseconds.\n",
327
             (((endTime-startTime))*1.0e6 / (4.0*TEST_BYTES/(3.0*512.0))));
328
      /* there are 4/3 as many c.f. operations as bytes/512, due to tree */
329
 
330
      /* Now look at time just to do that many compression operations. */
331
      printf("Now computing time for just the compression function portions...\n");
332
      md6_init(&st,d);
333
      startTime = ((double)clock())/CLOCKS_PER_SEC;
334
      for (i=0;i<(long long)TEST_BYTES*4/(3*b*(w/8));i++)
335
        md6_main_compression_loop(A,md6_default_r(d));
336
      endTime = ((double)clock())/CLOCKS_PER_SEC;
337
      printf
338
        ("time to process test input: %.3f seconds.\n", (endTime-startTime));
339
      if (endTime>startTime)
340
        printf("md6 bytes per second: %g\n", TEST_BYTES/(endTime-startTime));
341
      printf("md6 time per compression function (512 bytes) = %g microseconds.\n",
342
             (((endTime-startTime))*1.0e6 / (4.0*TEST_BYTES/(3.0*512.0))));
343
    } /* end of loop on j for different d's */
344
 
345
  printf("md6_test_2: end.\n\n");
346
}
347
 
348
 /* testing and debugging */
349
 
350
/* Global variables used by compression_hook_1 */
351
FILE *outFile;
352
int  hook_print_intermediate_values;
353
 
354
void compression_hook_1(md6_word *C,
355
                        const md6_word *Q,
356
                        md6_word *K,
357
                        int ell,
358
                        int ii,
359
                        int r,
360
                        int L,
361
                        int z,
362
                        int p,
363
                        int keylen,
364
                        int d,
365
                        md6_word *B
366
)
367
{ int i;
368
  // md6_word A[r*c+n];
369
  md6_word A[5000];
370
 
371
  md6_pack(A,Q,K,ell,ii,r,L,z,p,keylen,d,B);
372
 
373
  md6_main_compression_loop( A, md6_default_r(d));
374
 
375
  fprintf(outFile,"MD6 compression function computation ");
376
  fprintf(outFile,"(level %d, index %d):\n",ell,ii);
377
  fprintf(outFile,"Inputs (%d words):\n",n);
378
  for (i=0;i<r*c+n;i++)
379
    {
380
      if ((i<q))
381
        { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]);
382
          fprintf(outFile," Q[%d]\n",i);
383
        }
384
      else if ((i>=q)&&(i<q+k))
385
        { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]);
386
          fprintf(outFile," key K[%d]\n",i-q);
387
        }
388
      else if ((u>0)&&(i==q+k+u-1))
389
        { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]);
390
          fprintf(outFile," nodeID U = (ell,i) = (%d,%d)\n",ell,ii);
391
        }
392
      else if ((v>0)&&(i==q+k+u+v-1))
393
        { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]);
394
          fprintf(outFile," control word V = "
395
                          "(r,L,z,p,keylen,d) = "
396
                  "(%d,%d,%d,%d,%d,%d)\n",r,L,z,p,keylen,d);
397
        }
398
      else if ((i>=q+k+u+v)&&(i<n))
399
        { fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]);
400
          fprintf(outFile," data B[%2d] ",i-q-k-u-v);
401
          if (ell == 1)
402
            { if ( (i+(p/w))<n )
403
                fprintf(outFile,"input message word %4d",ii*b+(i-(q+k+u+v)));
404
            }
405
          else
406
            if ( (i+(p/w))< n )
407
              fprintf(outFile,
408
                      "chaining from (%d,%d)",
409
                      ell-1,
410
                      4*ii+(i-(q+k+u+v))/c);
411
          fprintf(outFile,"\n");
412
        }
413
      else if ((i>=r*c+n-c))
414
        { if ((i==r*c+n-c))
415
            fprintf(outFile,"Output (%d words of chaining values):\n",c);
416
          fprintf(outFile,"A[%4d] = " PR_MD6_WORD,i,A[i]);
417
          fprintf(outFile," output chaining value C[%d]\n",i-(r*c+n-c));
418
        }
419
      else
420
        { if (i==n)
421
            { if (hook_print_intermediate_values)
422
                fprintf(outFile,"Intermediate values:\n");
423
              else
424
                fprintf(outFile,"Intermediate values A[%d..%d] omitted...\n",n,r*c+n-c-1);
425
            }
426
          if (hook_print_intermediate_values)
427
            fprintf(outFile,"A[%4d] = " PR_MD6_WORD "\n",i,A[i]);
428
        }
429
    }
430
  fprintf(outFile,"\n");
431
}
432
 
433
/* Trace -- print out details of an md6 computation.
434
*/
435
 
436
void trace_md6 ( char* filename,
437
                 int print_intermediate_values,
438
                 char* M,
439
                 uint64_t m,
440
                 int d,
441
                 char* key,
442
                 int keylen,
443
                 int L,
444
                 int r
445
                 )
446
/*
447
** print to file intermediate results of a hash function computation,
448
** for each compression function call
449
**   M, m, d, L, r, key, keylen -- as usual
450
**   (but assumes K is 0-terminated)
451
**   filename = output file name
452
**   print_intermediate_values = 1 to print non-I/O values of A
453
**                             = 0 to only print I/O values of A
454
*/
455
{
456
  md6_state st;
457
  time_t now;
458
  int i;
459
  int j;
460
 
461
  /* save switch regarding the printing of intermediate values
462
  ** for compression_hook_1 to use later.
463
  */
464
  hook_print_intermediate_values = print_intermediate_values;
465
 
466
  /* check that input values are sensible */
467
  assert(( M != NULL ));
468
  assert(( (key == NULL) || ( (0<=keylen) && (keylen <= k*8) ) ));
469
  assert(( (1 <= d) && (d <= c*w/2) ));
470
 
471
  outFile = fopen (filename, "w");
472
  if (outFile == NULL)
473
    { printf( "%s can't be opened.\n", filename );
474
      printf( "trace_md6: aborted.\n" );
475
      return;
476
    }
477
 
478
  fprintf(outFile,"Trace of md6 computation.\n");
479
  time(&now);
480
  fprintf(outFile,"%s",ctime(&now));
481
  fprintf(outFile,"Filename: %s\n\n",filename);
482
  fprintf(outFile,"d = %6d (digest length in bits)\n",d);
483
  fprintf(outFile,"L = %6d (number of parallel passes)\n",L);
484
  fprintf(outFile,"r = %6d (number of rounds)\n",r);
485
  fprintf(outFile,"K = '%s' (key)\n",key);
486
  fprintf(outFile,"k = %6d (key length in bytes)\n",keylen);
487
  fprintf(outFile,"M = (hex) ");
488
  for (i=0;i<18;i++) fprintf(outFile,"%02x ",M[i]);
489
  fprintf(outFile,"...\n");
490
  fprintf(outFile,"    (input message repeats with period 7)\n");
491
  fprintf(outFile,"m = %6lld (message length in bits)\n",m);
492
  fprintf(outFile,"    %6lld (message length in (full or partial) bytes)\n",(m+7)/8);
493
  fprintf(outFile,"\n");
494
 
495
  md6_full_init(&st,d,key,keylen,L,r);
496
  compression_hook = compression_hook_1;   /* must be done *after* init */
497
  md6_update(&st,M,(uint64_t)m);
498
  md6_final(&st,NULL);
499
 
500
  fprintf(outFile,"Final hash value = \n");
501
  for (i=0; i<d; i+=64)
502
    {
503
      fprintf(outFile,"          ");
504
      for (j=0;j<min(64,d-i);j+=8)
505
        fprintf(outFile,"%02x",st.hashval[(i+j)/8]);
506
      fprintf(outFile,"\n");
507
    }
508
  fprintf(outFile,"End of trace of md6 computation.\n");
509
  fclose(outFile);
510
}
511
 
512
/* md6_test_3 -- trace various computations.
513
*/
514
 
515
void md6_test_3()
516
{
517
  unsigned char M[10000];
518
  int d;
519
  int L;
520
  int r;
521
  unsigned char *key;
522
  int keylen;
523
  int i;
524
  char *filename;
525
 
526
  filename = "md6_test_3.txt";
527
  printf( "------------------------------------------------------------\n" );
528
  printf( "md6_test_3.\n" );
529
  printf( "Starting trace of md6 computation.\n" );
530
  printf( "Output will be written to file %s \n", filename );
531
  /* M = "11 22 33 44 55 66 77 11..." (hex, 10000 chars) */
532
  for (i=0;i<10000;i++) M[i] = 0x11 + (char)((i % 7)*(0x11));
533
 
534
  d = 256;
535
  L = md6_default_L;
536
  r = md6_default_r(d);
537
  key = (unsigned char *)"abcd1234";
538
  keylen = (int)strlen((char *)key);
539
 
540
  trace_md6("one_block.txt",
541
            1,                   /* print non-I/O A values */
542
            M,500*8,d,"",0,L,r
543
            );
544
  trace_md6("two_block.txt",
545
            1,                   /* print non-I/O A values */
546
            M,1000*8,d,"",0,L,r
547
            );
548
  trace_md6("six_block.txt",
549
            0,                   /* don't print non-I/O A values */
550
            M,6*512*8-24,d,"",0,L,r
551
            );
552
  printf("End of trace of md6 computation.\n\n");
553
 
554
  printf("md6_test_3: end.\n");
555
}
556
 
557
void md6_test_4()
558
{
559
  printf( "------------------------------------------------------------\n" );
560
  printf( "md6_test_4.\n" );
561
  printf( "size of md6_state is %d bytes.\n\n",sizeof(md6_state));
562
 
563
}
564
 
565
 
566
int main (int argc, char *argv[])
567
{
568
  printf("\nMD6 test routines.\n");
569
  printf("Word size w = %d\n\n",w);
570
 
571
  md6_test_3();  /* print out intermediate results for various hashes */
572
  md6_test_1();  /* simple test suite */
573
  md6_test_2();  /* timing test       */
574
  md6_test_2();  /* do timing test again...    */
575
  md6_test_4();
576
  return 0;
577
}
578
 
579
/* end of md6_test.c */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.