1 /********************************************************************\
2  *
3  *      FILE:     mactest.c
4  *
5  *      CONTENTS: test file for sample C-implementation of
6  *                RIPEMD160-MAC and RIPEMD128-MAC
7  *        * command line arguments:
8  *           filename keyfilename -- compute MAC of file binary read using
9  *                                   key in keyfilename (hexadecimal format)
10  *           -sstring  -- print string & MAC for default key
11  *           -t        -- perform time trial
12  *           -x        -- execute standard test suite, ASCII input
13  *        * for linkage with rmd128mc.c: define RMDsize as 128
14  *          for linkage with rmd160mc.c: define RMDsize as 160 (default)
15  *      TARGET:   any computer with an ANSI C compiler
16  *
17  *      AUTHOR:   Antoon Bosselaers, ESAT-COSIC
18  *      DATE:     26 March 1998
19  *      VERSION:  1.0
20  *
21  *      Copyright (c) Katholieke Universiteit Leuven
22  *      1998, All Rights Reserved
23  *
24 \********************************************************************/
25 #ifndef RMDsize
26 #define RMDsize 160
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include <string.h>
33 #if RMDsize == 128
34 #include "rmd128mc.h"
35 #elif RMDsize == 160
36 #include "rmd160mc.h"
37 #endif
38 
39 #define TEST_BLOCK_SIZE 8000
40 #define TEST_BLOCKS 1250
41 #define TEST_BYTES ((long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS)
42 
43 /********************************************************************/
44 
RMDMAC(byte * key,byte * message)45 byte *RMDMAC(byte *key, byte *message)
46 /*
47  * returns RMDMAC(key, message)
48  * message should be a string terminated by '\0'
49  */
50 {
51    dword         MDbuf[RMDsize/32];   /* contains (A, B, C, D(, E))   */
52    static byte   rmdmac[RMDsize/8];   /* for final mac-value          */
53    dword         X[16];               /* current 16-word chunk        */
54    unsigned int  i;                   /* counter                      */
55    dword         length;              /* length in bytes of message   */
56    dword         nbytes;              /* # of bytes not yet processed */
57    dword        *MDK;                 /* pointer to expanded key      */
58 
59    /* key setup */
60    MDK = MDMACsetup(key);
61 
62    /* initialize */
63    MDMACinit(MDK, MDbuf);
64    length = (dword)strlen((char *)message);
65 
66    /* process message in 16-word chunks */
67    for (nbytes=length; nbytes > 63; nbytes-=64) {
68       for (i=0; i<16; i++) {
69          X[i] = BYTES_TO_DWORD(message);
70          message += 4;
71       }
72       compress(MDK, MDbuf, X);
73    }                                    /* length mod 64 bytes left */
74 
75    /* finish: */
76    MDMACfinish(MDK, MDbuf, message, length, 0);
77 
78    for (i=0; i<RMDsize/8; i+=4) {
79       rmdmac[i]   =  MDbuf[i>>2];         /* implicit cast to byte  */
80       rmdmac[i+1] = (MDbuf[i>>2] >>  8);  /*  extracts the 8 least  */
81       rmdmac[i+2] = (MDbuf[i>>2] >> 16);  /*  significant bits.     */
82       rmdmac[i+3] = (MDbuf[i>>2] >> 24);
83    }
84 
85    return (byte *)rmdmac;
86 }
87 
88 /********************************************************************/
89 
RMDMACbinary(byte * key,char * fname)90 byte *RMDMACbinary(byte *key, char *fname)
91 /*
92  * returns RMDMAC(key, message in file fname)
93  * fname is read as binary data.
94  */
95 {
96    FILE         *mf;                  /* pointer to file <fname>      */
97    byte          data[1024];          /* contains current mess. block */
98    dword         nbytes;              /* length of this block         */
99    dword         MDbuf[RMDsize/32];   /* contains (A, B, C, D(, E))   */
100    static byte   rmdmac[RMDsize/8];   /* for final mac-value          */
101    dword         X[16];               /* current 16-word chunk        */
102    unsigned int  i, j;                /* counters                     */
103    dword         length[2];           /* length in bytes of message   */
104    dword         offset;              /* # of unprocessed bytes at    */
105                                       /*          call of MDMACfinish */
106    dword        *MDK;                 /* pointer to expanded key      */
107 
108    /* key setup */
109    MDK = MDMACsetup(key);
110 
111    /* initialize */
112    if ((mf = fopen(fname, "rb")) == NULL) {
113       fprintf(stderr, "\nRMDbinary: cannot open file \"%s\".\n",
114               fname);
115       exit(1);
116    }
117    MDMACinit(MDK, MDbuf);
118    length[0] = 0;
119    length[1] = 0;
120 
121    while ((nbytes = fread(data, 1, 1024, mf)) != 0) {
122       /* process all complete blocks */
123       for (i=0; i<(nbytes>>6); i++) {
124          for (j=0; j<16; j++)
125             X[j] = BYTES_TO_DWORD(data+64*i+4*j);
126          compress(MDK, MDbuf, X);
127       }
128       /* update length[] */
129       if (length[0] + nbytes < length[0])
130          length[1]++;                  /* overflow to msb of length */
131       length[0] += nbytes;
132    }
133 
134    /* finish: */
135    offset = length[0] & 0x3C0;   /* extract bytes 6 to 10 inclusive */
136    MDMACfinish(MDK, MDbuf, data+offset, length[0], length[1]);
137 
138    for (i=0; i<RMDsize/8; i+=4) {
139       rmdmac[i]   =  MDbuf[i>>2];
140       rmdmac[i+1] = (MDbuf[i>>2] >>  8);
141       rmdmac[i+2] = (MDbuf[i>>2] >> 16);
142       rmdmac[i+3] = (MDbuf[i>>2] >> 24);
143    }
144 
145    fclose(mf);
146 
147    return (byte *)rmdmac;
148 }
149 
150 /***********************************************************************/
151 
RMDMACreadkey(char * fname)152 byte *RMDMACreadkey(char *fname)
153 /*
154  * reads 128-bit MAC key from fname
155  * key should be given in hexadecimal format
156  */
157 {
158    FILE         *file;
159    unsigned int  i, temp;
160    static byte   key[16];
161 
162    if ( (file = fopen(fname, "r")) == NULL ) {
163       fprintf(stderr, "RMDMACreadkey: cannot open file \"%s\".\n", fname);
164       exit(1);
165    }
166 
167    for (i=0;i < 16;i++) {
168       if (fscanf(file, "%02x", &temp) == EOF)
169          fprintf(stderr, "RMDMACreadkey: EOF encountered before read was "
170                          "completed in \"%s\".\n", fname);
171       key[i] = (byte)temp;
172    }
173 
174    fclose(file);
175 
176    return key;
177 }
178 
179 /********************************************************************/
180 
speedtest(void)181 void speedtest(void)
182 /*
183  * A time trial routine, to measure the speed of RIPEMD160/128-MAC.
184  * Measures processor time required to process TEST_BLOCKS times
185  *  a message of TEST_BLOCK_SIZE characters.
186  */
187 {
188    clock_t      t0, t1;
189    byte        *data;
190    byte         rmdmac[RMDsize/8];
191    dword        X[16];
192    dword        MDbuf[RMDsize/32];
193    unsigned int i, j, k;
194    byte         MDMACkey[16];
195    dword       *MDK;
196 
197    srand(time(NULL));
198 
199    /* pick a random key and perform key setup */
200    for (i=0; i<16; i++)
201       MDMACkey[i] = (byte)(rand() >> 7);
202    MDK = MDMACsetup(MDMACkey);
203 
204    /* allocate and initialize test data */
205    if ((data = (byte*)malloc(TEST_BLOCK_SIZE)) == NULL) {
206       fprintf(stderr, "speedtest: allocation error\n");
207       exit(1);
208    }
209    for (i=0; i<TEST_BLOCK_SIZE; i++)
210       data[i] = (byte)(rand() >> 7);
211 
212    /* start timer */
213    printf("\n\nRIPEMD-%uMAC time trial. Processing %ld characters...\n",
214           RMDsize, TEST_BYTES);
215    t0 = clock();
216 
217    /* process data */
218    MDMACinit(MDK, MDbuf);
219    for (i=0; i<TEST_BLOCKS; i++) {
220       for (j=0; j<TEST_BLOCK_SIZE; j+=64) {
221          for (k=0; k<16; k++)
222             X[k] = BYTES_TO_DWORD(data+j+4*k);
223          compress(MDK, MDbuf, X);
224       }
225    }
226    MDMACfinish(MDK, MDbuf, data, TEST_BYTES, 0);
227 
228    /* stop timer, get time difference */
229    t1 = clock();
230    printf("\nTest input processed in %g seconds.\n",
231           (double)(t1-t0)/(double)CLOCKS_PER_SEC);
232    printf("Characters processed per second: %g\n",
233           (double)CLOCKS_PER_SEC*TEST_BYTES/((double)t1-t0));
234 
235    for (i=0; i<RMDsize/8; i+=4) {
236       rmdmac[i]   =  MDbuf[i>>2];
237       rmdmac[i+1] = (MDbuf[i>>2] >>  8);
238       rmdmac[i+2] = (MDbuf[i>>2] >> 16);
239       rmdmac[i+3] = (MDbuf[i>>2] >> 24);
240    }
241    printf("\nMAC: ");
242    for (i=0; i<RMDsize/8; i++)
243       printf("%02x", rmdmac[i]);
244    printf("\n");
245 
246    free(data);
247    return;
248 }
249 
250 /********************************************************************/
251 
RMDMAConemillion(byte * key)252 void RMDMAConemillion(byte *key)
253 /*
254  * returns RMDMAC() of message consisting of 1 million 'a' characters
255  */
256 {
257    dword         MDbuf[RMDsize/32];   /* contains (A, B, C, D(, E)) */
258    static byte   rmdmac[RMDsize/8];   /* for final mac-value        */
259    dword         X[16];               /* current 16-word chunk      */
260    unsigned int  i;                   /* counter                    */
261    dword        *MDK;                 /* pointer to expanded key    */
262 
263    /* key setup */
264    MDK = MDMACsetup(key);
265 
266    MDMACinit(MDK, MDbuf);
267    memcpy(X, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 32);
268    memcpy(X+8, X, 32);
269    for (i=15625; i>0; i--)
270       compress(MDK, MDbuf, X);
271    MDMACfinish(MDK, MDbuf, NULL, 1000000UL, 0);
272    for (i=0; i<RMDsize/8; i+=4) {
273       rmdmac[i]   =  MDbuf[i>>2];
274       rmdmac[i+1] = (MDbuf[i>>2] >>  8);
275       rmdmac[i+2] = (MDbuf[i>>2] >> 16);
276       rmdmac[i+3] = (MDbuf[i>>2] >> 24);
277    }
278    printf("\n* message: 1 million times \"a\"\n  MAC: ");
279    for (i=0; i<RMDsize/8; i++)
280       printf("%02x", rmdmac[i]);
281 
282 }
283 
284 /********************************************************************/
285 
RMDMACstring(byte * key,char * message,char * print)286 void RMDMACstring(byte *key, char *message, char *print)
287 {
288    unsigned int  i;
289    byte         *rmdmac;
290 
291    rmdmac = RMDMAC(key, (byte *)message);
292    printf("\n* message: %s\n  MAC: ", print);
293    for (i=0; i<RMDsize/8; i++)
294       printf("%02x", rmdmac[i]);
295 }
296 
297 /********************************************************************/
298 
testsuite(byte * key)299 void testsuite (byte *key)
300 /*
301  *   standard test suite
302  */
303 {
304    unsigned int i;
305 
306    printf("\n\nRIPEMD-%uMAC test suite results (ASCII):\n", RMDsize);
307 
308    printf("\nkey = ");
309    for (i=0; i<16; i++)
310       printf("%02x", key[i]);
311    printf("\n");
312 
313    RMDMACstring(key, "", "\"\" (empty string)");
314    RMDMACstring(key, "a", "\"a\"");
315    RMDMACstring(key, "abc", "\"abc\"");
316    RMDMACstring(key, "message digest", "\"message digest\"");
317    RMDMACstring(key, "abcdefghijklmnopqrstuvwxyz", "\"abcdefghijklmnopqrstuvwxyz\"");
318    RMDMACstring(key, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
319              "\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"");
320    RMDMACstring(key, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
321              "\"A...Za...z0...9\"");
322    RMDMACstring(key, "1234567890123456789012345678901234567890"
323              "1234567890123456789012345678901234567890",
324              "8 times \"1234567890\"");
325    RMDMAConemillion(key);
326    printf("\n");
327 
328    return;
329 }
330 
331 /********************************************************************/
332 
main(int argc,char * argv[])333 main (int argc, char *argv[])
334 /*
335  *  main program. calls one or more of the test routines depending
336  *  on command line arguments. see the header of this file.
337  *
338  */
339 {
340   unsigned int   i, j;
341   byte          *rmdmac, *key;
342   byte Ktest1[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
343                      0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
344   byte Ktest2[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
345                      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
346 
347    if (argc == 1) {
348       printf("For each command line argument in turn:\n");
349       printf("  filename keyfilename -- compute MAC of file binary read using\n"
350              "                          key in keyfilename (hexadecimal format)\n");
351       printf("  -sstring             -- print string & MAC for default key\n");
352       printf("  -t                   -- perform time trial\n");
353       printf("  -x                   -- execute standard test suite, ASCII input\n");
354       return 0;
355    }
356 
357    MDMACconstT();
358    for (i = 1; i < argc; i++) {
359       if (argv[i][0] == '-' && argv[i][1] == 's') {
360          printf("\n\ndefault key = ");
361          for (j=0; j<16; j++)
362             printf("%02x", Ktest1[j]);
363          printf("\nmessage: %s", argv[i]+2);
364          rmdmac = RMDMAC(Ktest1, (byte *)argv[i] + 2);
365          printf("\nMAC: ");
366          for (j=0; j<RMDsize/8; j++)
367             printf("%02x", rmdmac[j]);
368          printf("\n");
369       }
370       else if (strcmp (argv[i], "-t") == 0)
371          speedtest ();
372       else if (strcmp (argv[i], "-x") == 0) {
373          testsuite (Ktest1);
374          testsuite (Ktest2);
375       }
376       else {
377          key = RMDMACreadkey(argv[i+1]);
378          printf("\n\nkey = ");
379          for (j=0; j<16; j++)
380             printf("%02x", key[j]);
381          rmdmac = RMDMACbinary(key, argv[i]);
382          printf("\nmessagefile (binary): %s", argv[i]);
383          printf("\nMAC: ");
384          for (j=0; j<RMDsize/8; j++)
385             printf("%02x", rmdmac[j]);
386          printf("\n");
387          i++;  /* one extra input was used for the key file */
388       }
389    }
390    printf("\n");
391 
392    return 0;
393 }
394 
395 /********************** end of file mactest.c ***********************/
396 
397