5930b98484f38d8b4d992f6ff3cabe031a12c376
[openssl.git] / fips / cmac / fips_cmactest.c
1 /* fips_cmactest.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2005.
4  */
5 /* ====================================================================
6  * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #define OPENSSL_FIPSAPI
60
61 #include <stdio.h>
62 #include <ctype.h>
63 #include <string.h>
64 #include <openssl/bio.h>
65 #include <openssl/evp.h>
66 #include <openssl/cmac.h>
67 #include <openssl/err.h>
68 #include <openssl/bn.h>
69
70 #ifndef OPENSSL_FIPS
71
72 int main(int argc, char *argv[])
73 {
74     printf("No FIPS CMAC support\n");
75     return(0);
76 }
77
78 #else
79
80 #include <openssl/fips.h>
81 #include "fips_utl.h"
82
83 static int cmac_test(const EVP_CIPHER *cipher, FILE *out, FILE *in,
84         int mode, int Klen_counts_keys, int known_keylen);
85 static int print_cmac_gen(const EVP_CIPHER *cipher, FILE *out,
86                 unsigned char *Key, int Klen,
87                 unsigned char *Msg, int Msglen,
88                 int Tlen);
89 static int print_cmac_ver(const EVP_CIPHER *cipher, FILE *out,
90                 unsigned char *Key, int Klen,
91                 unsigned char *Msg, int Msglen,
92                 unsigned char *Mac, int Maclen,
93                 int Tlen);
94
95 int main(int argc, char **argv)
96         {
97         FILE *in = NULL, *out = NULL;
98         int mode = 0;           /* 0 => Generate, 1 => Verify */
99         int Klen_counts_keys = 0; /* 0 => Klen is size of one key
100                                      1 => Klen is amount of keys
101                                   */
102         int known_keylen = 0;   /* Only set when Klen_counts_keys = 1 */
103         const EVP_CIPHER *cipher = 0;
104         int ret = 1;
105         fips_set_error_print();
106         if(!FIPS_mode_set(1))
107                 goto end;
108
109         while (argc > 1 && argv[1][0] == '-')
110                 {
111                 switch (argv[1][1])
112                         {
113                 case 'a':
114                         {
115                         char *p = &argv[1][2];
116                         if (*p == '\0')
117                                 {
118                                 if (argc <= 2)
119                                         {
120                                         fprintf(stderr, "Option %s needs a value\n", argv[1]);
121                                         goto end;
122                                         }
123                                 argv++;
124                                 argc--;
125                                 p = &argv[1][0];
126                                 }
127                         if (!strcmp(p, "aes128"))
128                                 cipher = EVP_aes_128_cbc();
129                         else if (!strcmp(p, "aes192"))
130                                 cipher = EVP_aes_192_cbc();
131                         else if (!strcmp(p, "aes256"))
132                                 cipher = EVP_aes_256_cbc();
133                         else if (!strcmp(p, "tdea3") || !strcmp(p, "tdes3"))
134                                 {
135                                 cipher = EVP_des_ede3_cbc();
136                                 Klen_counts_keys = 1;
137                                 known_keylen = 8;
138                                 }
139                         else
140                                 {
141                                 fprintf(stderr, "Unknown algorithm %s\n", p);
142                                 goto end;
143                                 }
144                         }
145                         break;
146                 case 'g':
147                         mode = 0;
148                         break;
149                 case 'v':
150                         mode = 1;
151                         break;
152                 default:
153                         fprintf(stderr, "Unknown option %s\n", argv[1]);
154                         goto end;
155                         }
156                 argv++;
157                 argc--;
158                 }
159         if (argc == 1)
160                 in = stdin;
161         else
162                 in = fopen(argv[1], "r");
163
164         if (argc < 2)
165                 out = stdout;
166         else
167                 out = fopen(argv[2], "w");
168
169         if (!in)
170                 {
171                 fprintf(stderr, "FATAL input initialization error\n");
172                 goto end;
173                 }
174
175         if (!out)
176                 {
177                 fprintf(stderr, "FATAL output initialization error\n");
178                 goto end;
179                 }
180
181         if (!cmac_test(cipher, out, in, mode,
182                         Klen_counts_keys, known_keylen))
183                 {
184                 fprintf(stderr, "FATAL cmac file processing error\n");
185                 goto end;
186                 }
187         else
188                 ret = 0;
189
190         end:
191
192         if (in && (in != stdin))
193                 fclose(in);
194         if (out && (out != stdout))
195                 fclose(out);
196
197         return ret;
198
199         }
200
201 #define CMAC_TEST_MAXLINELEN    150000
202
203 int cmac_test(const EVP_CIPHER *cipher, FILE *out, FILE *in,
204         int mode, int Klen_counts_keys, int known_keylen)
205         {
206         char *linebuf, *olinebuf, *p, *q;
207         char *keyword, *value;
208         unsigned char **Keys = NULL, *Msg = NULL, *Mac = NULL;
209         unsigned char *Key = NULL;
210         int Count, Klen, Mlen, Tlen;
211         long Keylen, Msglen, Maclen;
212         int ret = 0;
213         int lnum = 0;
214
215         olinebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
216         linebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
217
218         if (!linebuf || !olinebuf)
219                 goto error;
220
221         Count = -1;
222         Klen = -1;
223         Mlen = -1;
224         Tlen = -1;
225
226         while (fgets(olinebuf, CMAC_TEST_MAXLINELEN, in))
227                 {
228                 lnum++;
229                 strcpy(linebuf, olinebuf);
230                 keyword = linebuf;
231                 /* Skip leading space */
232                 while (isspace((unsigned char)*keyword))
233                         keyword++;
234
235                 /* Skip comments */
236                 if (keyword[0] == '#')
237                         {
238                         if (fputs(olinebuf, out) < 0)
239                                 goto error;
240                         continue;
241                         }
242
243                 /* Look for = sign */
244                 p = strchr(linebuf, '=');
245
246                 /* If no = or starts with [ (for [L=20] line) just copy */
247                 if (!p)
248                         {
249                         if (fputs(olinebuf, out) < 0)
250                                 goto error;
251                         continue;
252                         }
253
254                 q = p - 1;
255
256                 /* Remove trailing space */
257                 while (isspace((unsigned char)*q))
258                         *q-- = 0;
259
260                 *p = 0;
261                 value = p + 1;
262
263                 /* Remove leading space from value */
264                 while (isspace((unsigned char)*value))
265                         value++;
266
267                 /* Remove trailing space from value */
268                 p = value + strlen(value) - 1;
269
270                 while (*p == '\n' || isspace((unsigned char)*p))
271                         *p-- = 0;
272
273                 if (!strcmp(keyword, "Count"))
274                         {
275                         if (Count != -1)
276                                 goto parse_error;
277                         Count = atoi(value);
278                         if (Count < 0)
279                                 goto parse_error;
280                         }
281                 else if (!strcmp(keyword, "Klen"))
282                         {
283                         if (Klen != -1)
284                                 goto parse_error;
285                         Klen = atoi(value);
286                         if (Klen < 0)
287                                 goto parse_error;
288                         if (Klen_counts_keys)
289                                 {
290                                 Keys = OPENSSL_malloc(sizeof(*Keys) * Klen);
291                                 memset(Keys, '\0', sizeof(*Keys) * Klen);
292                                 }
293                         else
294                                 {
295                                 Keys = OPENSSL_malloc(sizeof(*Keys));
296                                 memset(Keys, '\0', sizeof(*Keys));
297                                 }
298                         }
299                 else if (!strcmp(keyword, "Mlen"))
300                         {
301                         if (Mlen != -1)
302                                 goto parse_error;
303                         Mlen = atoi(value);
304                         if (Mlen < 0)
305                                 goto parse_error;
306                         }
307                 else if (!strcmp(keyword, "Tlen"))
308                         {
309                         if (Tlen != -1)
310                                 goto parse_error;
311                         Tlen = atoi(value);
312                         if (Tlen < 0)
313                                 goto parse_error;
314                         }
315                 else if (!strcmp(keyword, "Key") && !Klen_counts_keys)
316                         {
317                         if (Keys[0])
318                                 goto parse_error;
319                         Keys[0] = hex2bin_m(value, &Keylen);
320                         if (!Keys[0])
321                                 goto parse_error;
322                         }
323                 else if (!strncmp(keyword, "Key", 3) && Klen_counts_keys)
324                         {
325                         int keynum = atoi(keyword + 3);
326                         if (!keynum || keynum > Klen || Keys[keynum-1])
327                                 goto parse_error;
328                         Keys[keynum-1] = hex2bin_m(value, &Keylen);
329                         if (!Keys[keynum-1])
330                                 goto parse_error;
331                         }
332                 else if (!strcmp(keyword, "Msg"))
333                         {
334                         if (Msg)
335                                 goto parse_error;
336                         Msg = hex2bin_m(value, &Msglen);
337                         if (!Msg)
338                                 goto parse_error;
339                         }
340                 else if (!strcmp(keyword, "Mac"))
341                         {
342                         if (mode == 0)
343                                 continue;
344                         if (Mac)
345                                 goto parse_error;
346                         Mac = hex2bin_m(value, &Maclen);
347                         if (!Mac)
348                                 goto parse_error;
349                         }
350                 else if (!strcmp(keyword, "Result"))
351                         {
352                         if (mode == 1)
353                                 continue;
354                         goto parse_error;
355                         }
356                 else
357                         goto parse_error;
358
359                 fputs(olinebuf, out);
360
361                 if (Keys && Msg && (!mode || Mac) && (Tlen > 0) && (Klen > 0))
362                         {
363                         if (Klen_counts_keys)
364                                 {
365                                 int x;
366                                 Key = OPENSSL_malloc(Klen * known_keylen);
367                                 for (x = 0; x < Klen; x++)
368                                         {
369                                         memcpy(Key + x * known_keylen,
370                                                 Keys[x], known_keylen);
371                                         OPENSSL_free(Keys[x]);
372                                         }
373                                 Klen *= known_keylen;
374                                 }
375                         else
376                                 {
377                                 Key = OPENSSL_malloc(Klen);
378                                 memcpy(Key, Keys[0], Klen);
379                                 OPENSSL_free(Keys[0]);
380                                 }
381                         OPENSSL_free(Keys);
382
383                         switch(mode)
384                                 {
385                         case 0:
386                                 if (!print_cmac_gen(cipher, out,
387                                                 Key, Klen,
388                                                 Msg, Mlen,
389                                                 Tlen))
390                                         goto error;
391                                 break;
392                         case 1:
393                                 if (!print_cmac_ver(cipher, out,
394                                                 Key, Klen,
395                                                 Msg, Mlen,
396                                                 Mac, Maclen,
397                                                 Tlen))
398                                         goto error;
399                                 break;
400                                 }
401
402                         OPENSSL_free(Key);
403                         Key = NULL;
404                         OPENSSL_free(Msg);
405                         Msg = NULL;
406                         OPENSSL_free(Mac);
407                         Mac = NULL;
408                         Klen = -1;
409                         Mlen = -1;
410                         Tlen = -1;
411                         Count = -1;
412                         }
413                 }
414
415
416         ret = 1;
417
418
419         error:
420
421         if (olinebuf)
422                 OPENSSL_free(olinebuf);
423         if (linebuf)
424                 OPENSSL_free(linebuf);
425         if (Key)
426                 OPENSSL_free(Key);
427         if (Msg)
428                 OPENSSL_free(Msg);
429         if (Mac)
430                 OPENSSL_free(Mac);
431
432         return ret;
433
434         parse_error:
435
436         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
437
438         goto error;
439
440         }
441
442 static int print_cmac_gen(const EVP_CIPHER *cipher, FILE *out,
443                 unsigned char *Key, int Klen,
444                 unsigned char *Msg, int Mlen,
445                 int Tlen)
446         {
447         int rc, i;
448         size_t reslen;
449         unsigned char res[128];
450         CMAC_CTX *cmac_ctx = CMAC_CTX_new();
451
452         CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
453         CMAC_Update(cmac_ctx, Msg, Mlen);
454         if (!CMAC_Final(cmac_ctx, res, &reslen))
455                 {
456                 fputs("Error calculating CMAC\n", stderr);
457                 rc = 0;
458                 }
459         else if (Tlen > reslen)
460                 {
461                 fputs("Parameter error, Tlen > CMAC length\n", stderr);
462                 rc = 0;
463                 }
464         else
465                 {
466                 fputs("Mac = ", out);
467                 for (i = 0; i < Tlen; i++)
468                         fprintf(out, "%02x", res[i]);
469                 fputs("\n", out);
470                 rc = 1;
471                 }
472         CMAC_CTX_free(cmac_ctx);
473         return rc;
474         }
475
476 static int print_cmac_ver(const EVP_CIPHER *cipher, FILE *out,
477                 unsigned char *Key, int Klen,
478                 unsigned char *Msg, int Mlen,
479                 unsigned char *Mac, int Maclen,
480                 int Tlen)
481         {
482         int rc;
483         size_t reslen;
484         unsigned char res[128];
485         CMAC_CTX *cmac_ctx = CMAC_CTX_new();
486
487         CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
488         CMAC_Update(cmac_ctx, Msg, Mlen);
489         if (!CMAC_Final(cmac_ctx, res, &reslen))
490                 {
491                 fputs("Error calculating CMAC\n", stderr);
492                 rc = 0;
493                 }
494         else if (Tlen > reslen)
495                 {
496                 fputs("Parameter error, Tlen > CMAC length\n", stderr);
497                 rc = 0;
498                 }
499         else if (Tlen != Maclen)
500                 {
501                 fputs("Parameter error, Tlen != resulting Mac length\n", stderr);
502                 rc = 0;
503                 }
504         else
505                 {
506                 if (!memcmp(Mac, res, Maclen))
507                         fputs("Result = P\n", out);
508                 else
509                         fputs("Result = F\n", out);
510                 }
511         CMAC_CTX_free(cmac_ctx);
512         return rc;
513         }
514
515 #endif