Fix warnings.
[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_algtest_init();
106
107         while (argc > 1 && argv[1][0] == '-')
108                 {
109                 switch (argv[1][1])
110                         {
111                 case 'a':
112                         {
113                         char *p = &argv[1][2];
114                         if (*p == '\0')
115                                 {
116                                 if (argc <= 2)
117                                         {
118                                         fprintf(stderr, "Option %s needs a value\n", argv[1]);
119                                         goto end;
120                                         }
121                                 argv++;
122                                 argc--;
123                                 p = &argv[1][0];
124                                 }
125                         if (!strcmp(p, "aes128"))
126                                 cipher = EVP_aes_128_cbc();
127                         else if (!strcmp(p, "aes192"))
128                                 cipher = EVP_aes_192_cbc();
129                         else if (!strcmp(p, "aes256"))
130                                 cipher = EVP_aes_256_cbc();
131                         else if (!strcmp(p, "tdea3") || !strcmp(p, "tdes3"))
132                                 {
133                                 cipher = EVP_des_ede3_cbc();
134                                 Klen_counts_keys = 1;
135                                 known_keylen = 8;
136                                 }
137                         else
138                                 {
139                                 fprintf(stderr, "Unknown algorithm %s\n", p);
140                                 goto end;
141                                 }
142                         }
143                         break;
144                 case 'g':
145                         mode = 0;
146                         break;
147                 case 'v':
148                         mode = 1;
149                         break;
150                 default:
151                         fprintf(stderr, "Unknown option %s\n", argv[1]);
152                         goto end;
153                         }
154                 argv++;
155                 argc--;
156                 }
157         if (argc == 1)
158                 in = stdin;
159         else
160                 in = fopen(argv[1], "r");
161
162         if (argc < 2)
163                 out = stdout;
164         else
165                 out = fopen(argv[2], "w");
166
167         if (!in)
168                 {
169                 fprintf(stderr, "FATAL input initialization error\n");
170                 goto end;
171                 }
172
173         if (!out)
174                 {
175                 fprintf(stderr, "FATAL output initialization error\n");
176                 goto end;
177                 }
178
179         if (!cmac_test(cipher, out, in, mode,
180                         Klen_counts_keys, known_keylen))
181                 {
182                 fprintf(stderr, "FATAL cmac file processing error\n");
183                 goto end;
184                 }
185         else
186                 ret = 0;
187
188         end:
189
190         if (in && (in != stdin))
191                 fclose(in);
192         if (out && (out != stdout))
193                 fclose(out);
194
195         return ret;
196
197         }
198
199 #define CMAC_TEST_MAXLINELEN    150000
200
201 int cmac_test(const EVP_CIPHER *cipher, FILE *out, FILE *in,
202         int mode, int Klen_counts_keys, int known_keylen)
203         {
204         char *linebuf, *olinebuf, *p, *q;
205         char *keyword, *value;
206         unsigned char **Keys = NULL, *Msg = NULL, *Mac = NULL;
207         unsigned char *Key = NULL;
208         int Count, Klen, Mlen, Tlen;
209         long Keylen, Msglen, Maclen;
210         int ret = 0;
211         int lnum = 0;
212
213         olinebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
214         linebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
215
216         if (!linebuf || !olinebuf)
217                 goto error;
218
219         Count = -1;
220         Klen = -1;
221         Mlen = -1;
222         Tlen = -1;
223
224         while (fgets(olinebuf, CMAC_TEST_MAXLINELEN, in))
225                 {
226                 lnum++;
227                 strcpy(linebuf, olinebuf);
228                 keyword = linebuf;
229                 /* Skip leading space */
230                 while (isspace((unsigned char)*keyword))
231                         keyword++;
232
233                 /* Skip comments */
234                 if (keyword[0] == '#')
235                         {
236                         if (fputs(olinebuf, out) < 0)
237                                 goto error;
238                         continue;
239                         }
240
241                 /* Look for = sign */
242                 p = strchr(linebuf, '=');
243
244                 /* If no = or starts with [ (for [L=20] line) just copy */
245                 if (!p)
246                         {
247                         if (fputs(olinebuf, out) < 0)
248                                 goto error;
249                         continue;
250                         }
251
252                 q = p - 1;
253
254                 /* Remove trailing space */
255                 while (isspace((unsigned char)*q))
256                         *q-- = 0;
257
258                 *p = 0;
259                 value = p + 1;
260
261                 /* Remove leading space from value */
262                 while (isspace((unsigned char)*value))
263                         value++;
264
265                 /* Remove trailing space from value */
266                 p = value + strlen(value) - 1;
267
268                 while (*p == '\n' || isspace((unsigned char)*p))
269                         *p-- = 0;
270
271                 if (!strcmp(keyword, "Count"))
272                         {
273                         if (Count != -1)
274                                 goto parse_error;
275                         Count = atoi(value);
276                         if (Count < 0)
277                                 goto parse_error;
278                         }
279                 else if (!strcmp(keyword, "Klen"))
280                         {
281                         if (Klen != -1)
282                                 goto parse_error;
283                         Klen = atoi(value);
284                         if (Klen < 0)
285                                 goto parse_error;
286                         if (Klen_counts_keys)
287                                 {
288                                 Keys = OPENSSL_malloc(sizeof(*Keys) * Klen);
289                                 memset(Keys, '\0', sizeof(*Keys) * Klen);
290                                 }
291                         else
292                                 {
293                                 Keys = OPENSSL_malloc(sizeof(*Keys));
294                                 memset(Keys, '\0', sizeof(*Keys));
295                                 }
296                         }
297                 else if (!strcmp(keyword, "Mlen"))
298                         {
299                         if (Mlen != -1)
300                                 goto parse_error;
301                         Mlen = atoi(value);
302                         if (Mlen < 0)
303                                 goto parse_error;
304                         }
305                 else if (!strcmp(keyword, "Tlen"))
306                         {
307                         if (Tlen != -1)
308                                 goto parse_error;
309                         Tlen = atoi(value);
310                         if (Tlen < 0)
311                                 goto parse_error;
312                         }
313                 else if (!strcmp(keyword, "Key") && !Klen_counts_keys)
314                         {
315                         if (Keys[0])
316                                 goto parse_error;
317                         Keys[0] = hex2bin_m(value, &Keylen);
318                         if (!Keys[0])
319                                 goto parse_error;
320                         }
321                 else if (!strncmp(keyword, "Key", 3) && Klen_counts_keys)
322                         {
323                         int keynum = atoi(keyword + 3);
324                         if (!keynum || keynum > Klen || Keys[keynum-1])
325                                 goto parse_error;
326                         Keys[keynum-1] = hex2bin_m(value, &Keylen);
327                         if (!Keys[keynum-1])
328                                 goto parse_error;
329                         }
330                 else if (!strcmp(keyword, "Msg"))
331                         {
332                         if (Msg)
333                                 goto parse_error;
334                         Msg = hex2bin_m(value, &Msglen);
335                         if (!Msg)
336                                 goto parse_error;
337                         }
338                 else if (!strcmp(keyword, "Mac"))
339                         {
340                         if (mode == 0)
341                                 continue;
342                         if (Mac)
343                                 goto parse_error;
344                         Mac = hex2bin_m(value, &Maclen);
345                         if (!Mac)
346                                 goto parse_error;
347                         }
348                 else if (!strcmp(keyword, "Result"))
349                         {
350                         if (mode == 1)
351                                 continue;
352                         goto parse_error;
353                         }
354                 else
355                         goto parse_error;
356
357                 fputs(olinebuf, out);
358
359                 if (Keys && Msg && (!mode || Mac) && (Tlen > 0) && (Klen > 0))
360                         {
361                         if (Klen_counts_keys)
362                                 {
363                                 int x;
364                                 Key = OPENSSL_malloc(Klen * known_keylen);
365                                 for (x = 0; x < Klen; x++)
366                                         {
367                                         memcpy(Key + x * known_keylen,
368                                                 Keys[x], known_keylen);
369                                         OPENSSL_free(Keys[x]);
370                                         }
371                                 Klen *= known_keylen;
372                                 }
373                         else
374                                 {
375                                 Key = OPENSSL_malloc(Klen);
376                                 memcpy(Key, Keys[0], Klen);
377                                 OPENSSL_free(Keys[0]);
378                                 }
379                         OPENSSL_free(Keys);
380
381                         switch(mode)
382                                 {
383                         case 0:
384                                 if (!print_cmac_gen(cipher, out,
385                                                 Key, Klen,
386                                                 Msg, Mlen,
387                                                 Tlen))
388                                         goto error;
389                                 break;
390                         case 1:
391                                 if (!print_cmac_ver(cipher, out,
392                                                 Key, Klen,
393                                                 Msg, Mlen,
394                                                 Mac, Maclen,
395                                                 Tlen))
396                                         goto error;
397                                 break;
398                                 }
399
400                         OPENSSL_free(Key);
401                         Key = NULL;
402                         OPENSSL_free(Msg);
403                         Msg = NULL;
404                         OPENSSL_free(Mac);
405                         Mac = NULL;
406                         Klen = -1;
407                         Mlen = -1;
408                         Tlen = -1;
409                         Count = -1;
410                         }
411                 }
412
413
414         ret = 1;
415
416
417         error:
418
419         if (olinebuf)
420                 OPENSSL_free(olinebuf);
421         if (linebuf)
422                 OPENSSL_free(linebuf);
423         if (Key)
424                 OPENSSL_free(Key);
425         if (Msg)
426                 OPENSSL_free(Msg);
427         if (Mac)
428                 OPENSSL_free(Mac);
429
430         return ret;
431
432         parse_error:
433
434         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
435
436         goto error;
437
438         }
439
440 static int print_cmac_gen(const EVP_CIPHER *cipher, FILE *out,
441                 unsigned char *Key, int Klen,
442                 unsigned char *Msg, int Mlen,
443                 int Tlen)
444         {
445         int rc, i;
446         size_t reslen;
447         unsigned char res[128];
448         CMAC_CTX *cmac_ctx = CMAC_CTX_new();
449
450         CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
451         CMAC_Update(cmac_ctx, Msg, Mlen);
452         if (!CMAC_Final(cmac_ctx, res, &reslen))
453                 {
454                 fputs("Error calculating CMAC\n", stderr);
455                 rc = 0;
456                 }
457         else if (Tlen > (int)reslen)
458                 {
459                 fputs("Parameter error, Tlen > CMAC length\n", stderr);
460                 rc = 0;
461                 }
462         else
463                 {
464                 fputs("Mac = ", out);
465                 for (i = 0; i < Tlen; i++)
466                         fprintf(out, "%02x", res[i]);
467                 fputs(RESP_EOL, out);
468                 rc = 1;
469                 }
470         CMAC_CTX_free(cmac_ctx);
471         return rc;
472         }
473
474 static int print_cmac_ver(const EVP_CIPHER *cipher, FILE *out,
475                 unsigned char *Key, int Klen,
476                 unsigned char *Msg, int Mlen,
477                 unsigned char *Mac, int Maclen,
478                 int Tlen)
479         {
480         int rc = 1;
481         size_t reslen;
482         unsigned char res[128];
483         CMAC_CTX *cmac_ctx = CMAC_CTX_new();
484
485         CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
486         CMAC_Update(cmac_ctx, Msg, Mlen);
487         if (!CMAC_Final(cmac_ctx, res, &reslen))
488                 {
489                 fputs("Error calculating CMAC\n", stderr);
490                 rc = 0;
491                 }
492         else if (Tlen > (int)reslen)
493                 {
494                 fputs("Parameter error, Tlen > CMAC length\n", stderr);
495                 rc = 0;
496                 }
497         else if (Tlen != Maclen)
498                 {
499                 fputs("Parameter error, Tlen != resulting Mac length\n", stderr);
500                 rc = 0;
501                 }
502         else
503                 {
504                 if (!memcmp(Mac, res, Maclen))
505                         fputs("Result = P" RESP_EOL, out);
506                 else
507                         fputs("Result = F" RESP_EOL, out);
508                 }
509         CMAC_CTX_free(cmac_ctx);
510         return rc;
511         }
512
513 #endif