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