296f1a8f03913637fe5aaf7a69c26088054f5229
[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, int mode);
84 static int print_cmac_gen(const EVP_CIPHER *cipher, FILE *out,
85                 unsigned char *Key, int Klen,
86                 unsigned char *Msg, int Msglen,
87                 int Tlen);
88 static int print_cmac_ver(const EVP_CIPHER *cipher, FILE *out,
89                 unsigned char *Key, int Klen,
90                 unsigned char *Msg, int Msglen,
91                 unsigned char *Mac, int Maclen,
92                 int Tlen);
93
94 int main(int argc, char **argv)
95         {
96         FILE *in = NULL, *out = NULL;
97         int mode = 0;           /* 0 => Generate, 1 => Verify */
98
99         int ret = 1;
100         fips_set_error_print();
101         if(!FIPS_mode_set(1))
102                 goto end;
103
104         if (argc > 1 && argv[1][0] == '-')
105                 {
106                 if (strcmp(argv[1], "-g") == 0)
107                         mode = 0;
108                 else if (strcmp(argv[1], "-v") == 0)
109                         mode = 1;
110                 else
111                         {
112                         fprintf(stderr, "Unknown option %s\n", argv[1]);
113                         goto end;
114                         }
115                 argv++;
116                 argc--;
117                 }
118         if (argc == 1)
119                 in = stdin;
120         else
121                 in = fopen(argv[1], "r");
122
123         if (argc < 2)
124                 out = stdout;
125         else
126                 out = fopen(argv[2], "w");
127
128         if (!in)
129                 {
130                 fprintf(stderr, "FATAL input initialization error\n");
131                 goto end;
132                 }
133
134         if (!out)
135                 {
136                 fprintf(stderr, "FATAL output initialization error\n");
137                 goto end;
138                 }
139
140         if (!cmac_test(EVP_aes_256_cbc(), out, in, mode))
141                 {
142                 fprintf(stderr, "FATAL cmac file processing error\n");
143                 goto end;
144                 }
145         else
146                 ret = 0;
147
148         end:
149
150         if (in && (in != stdin))
151                 fclose(in);
152         if (out && (out != stdout))
153                 fclose(out);
154
155         return ret;
156
157         }
158
159 #define CMAC_TEST_MAXLINELEN    1024
160
161 int cmac_test(const EVP_CIPHER *cipher, FILE *out, FILE *in, int mode)
162         {
163         char *linebuf, *olinebuf, *p, *q;
164         char *keyword, *value;
165         unsigned char *Key = NULL, *Msg = NULL, *Mac = NULL;
166         int Count, Klen, Mlen, Tlen;
167         long Keylen, Msglen, Maclen;
168         int ret = 0;
169         int lnum = 0;
170
171         olinebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
172         linebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
173
174         if (!linebuf || !olinebuf)
175                 goto error;
176
177         Count = -1;
178         Klen = -1;
179         Mlen = -1;
180         Tlen = -1;
181
182         while (fgets(olinebuf, CMAC_TEST_MAXLINELEN, in))
183                 {
184                 lnum++;
185                 strcpy(linebuf, olinebuf);
186                 keyword = linebuf;
187                 /* Skip leading space */
188                 while (isspace((unsigned char)*keyword))
189                         keyword++;
190
191                 /* Skip comments */
192                 if (keyword[0] == '#')
193                         {
194                         if (fputs(olinebuf, out) < 0)
195                                 goto error;
196                         continue;
197                         }
198
199                 /* Look for = sign */
200                 p = strchr(linebuf, '=');
201
202                 /* If no = or starts with [ (for [L=20] line) just copy */
203                 if (!p)
204                         {
205                         if (fputs(olinebuf, out) < 0)
206                                 goto error;
207                         continue;
208                         }
209
210                 q = p - 1;
211
212                 /* Remove trailing space */
213                 while (isspace((unsigned char)*q))
214                         *q-- = 0;
215
216                 *p = 0;
217                 value = p + 1;
218
219                 /* Remove leading space from value */
220                 while (isspace((unsigned char)*value))
221                         value++;
222
223                 /* Remove trailing space from value */
224                 p = value + strlen(value) - 1;
225
226                 while (*p == '\n' || isspace((unsigned char)*p))
227                         *p-- = 0;
228
229                 if (!strcmp(keyword, "Count"))
230                         {
231                         if (Count != -1)
232                                 goto parse_error;
233                         Count = atoi(value);
234                         if (Count < 0)
235                                 goto parse_error;
236                         }
237                 else if (!strcmp(keyword, "Klen"))
238                         {
239                         if (Klen != -1)
240                                 goto parse_error;
241                         Klen = atoi(value);
242                         if (Klen < 0)
243                                 goto parse_error;
244                         }
245                 else if (!strcmp(keyword, "Mlen"))
246                         {
247                         if (Mlen != -1)
248                                 goto parse_error;
249                         Mlen = atoi(value);
250                         if (Mlen < 0)
251                                 goto parse_error;
252                         }
253                 else if (!strcmp(keyword, "Tlen"))
254                         {
255                         if (Tlen != -1)
256                                 goto parse_error;
257                         Tlen = atoi(value);
258                         if (Tlen < 0)
259                                 goto parse_error;
260                         }
261                 else if (!strcmp(keyword, "Key"))
262                         {
263                         if (Key)
264                                 goto parse_error;
265                         Key = hex2bin_m(value, &Keylen);
266                         if (!Key)
267                                 goto parse_error;
268                         }
269                 else if (!strcmp(keyword, "Msg"))
270                         {
271                         if (Msg)
272                                 goto parse_error;
273                         Msg = hex2bin_m(value, &Msglen);
274                         if (!Msg)
275                                 goto parse_error;
276                         }
277                 else if (!strcmp(keyword, "Mac"))
278                         {
279                         if (mode == 0)
280                                 continue;
281                         if (Mac)
282                                 goto parse_error;
283                         Mac = hex2bin_m(value, &Maclen);
284                         if (!Mac)
285                                 goto parse_error;
286                         }
287                 else if (!strcmp(keyword, "Result"))
288                         {
289                         if (mode == 1)
290                                 continue;
291                         goto parse_error;
292                         }
293                 else
294                         goto parse_error;
295
296                 fputs(olinebuf, out);
297
298                 switch(mode)
299                         {
300                 case 0:
301                         if (Key && Msg && (Tlen > 0) && (Klen > 0))
302                                 {
303                                 if (!print_cmac_gen(cipher, out,
304                                                 Key, Klen,
305                                                 Msg, Mlen,
306                                                 Tlen))
307                                         goto error;
308                                 OPENSSL_free(Key);
309                                 Key = NULL;
310                                 OPENSSL_free(Msg);
311                                 Msg = NULL;
312                                 Klen = -1;
313                                 Mlen = -1;
314                                 Tlen = -1;
315                                 Count = -1;
316                                 }
317                         break;
318                 case 1:
319                         if (Key && Msg && Mac && (Tlen > 0) && (Klen > 0))
320                                 {
321                                 if (!print_cmac_ver(cipher, out,
322                                                 Key, Klen,
323                                                 Msg, Mlen,
324                                                 Mac, Maclen,
325                                                 Tlen))
326                                         goto error;
327                                 OPENSSL_free(Key);
328                                 Key = NULL;
329                                 OPENSSL_free(Msg);
330                                 Msg = NULL;
331                                 OPENSSL_free(Mac);
332                                 Mac = NULL;
333                                 Klen = -1;
334                                 Mlen = -1;
335                                 Tlen = -1;
336                                 Count = -1;
337                                 }
338                         break;
339                         }
340
341                 }
342
343
344         ret = 1;
345
346
347         error:
348
349         if (olinebuf)
350                 OPENSSL_free(olinebuf);
351         if (linebuf)
352                 OPENSSL_free(linebuf);
353         if (Key)
354                 OPENSSL_free(Key);
355         if (Msg)
356                 OPENSSL_free(Msg);
357
358         return ret;
359
360         parse_error:
361
362         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
363
364         goto error;
365
366         }
367
368 static int print_cmac_gen(const EVP_CIPHER *cipher, FILE *out,
369                 unsigned char *Key, int Klen,
370                 unsigned char *Msg, int Mlen,
371                 int Tlen)
372         {
373         int rc, i;
374         size_t reslen;
375         unsigned char res[1024];
376         CMAC_CTX *cmac_ctx = CMAC_CTX_new();
377
378         CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
379         CMAC_Update(cmac_ctx, Msg, Mlen);
380         if (!CMAC_Final(cmac_ctx, res, &reslen))
381                 {
382                 fputs("Error calculating CMAC\n", stderr);
383                 rc = 0;
384                 }
385         else if (Tlen > reslen)
386                 {
387                 fputs("Parameter error, Tlen > CMAC length\n", stderr);
388                 rc = 0;
389                 }
390         else
391                 {
392                 fputs("Mac = ", out);
393                 for (i = 0; i < Tlen; i++)
394                         fprintf(out, "%02x", res[i]);
395                 fputs("\n", out);
396                 rc = 1;
397                 }
398         CMAC_CTX_free(cmac_ctx);
399         return rc;
400         }
401
402 static int print_cmac_ver(const EVP_CIPHER *cipher, FILE *out,
403                 unsigned char *Key, int Klen,
404                 unsigned char *Msg, int Mlen,
405                 unsigned char *Mac, int Maclen,
406                 int Tlen)
407         {
408         int rc;
409         size_t reslen;
410         unsigned char res[1024];
411         CMAC_CTX *cmac_ctx = CMAC_CTX_new();
412
413         CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
414         CMAC_Update(cmac_ctx, Msg, Mlen);
415         if (!CMAC_Final(cmac_ctx, res, &reslen))
416                 {
417                 fputs("Error calculating CMAC\n", stderr);
418                 rc = 0;
419                 }
420         else if (Tlen > reslen)
421                 {
422                 fputs("Parameter error, Tlen > CMAC length\n", stderr);
423                 rc = 0;
424                 }
425         else if (Tlen != Maclen)
426                 {
427                 fputs("Parameter error, Tlen != resulting Mac length\n", stderr);
428                 rc = 0;
429                 }
430         else
431                 {
432                 if (!memcmp(Mac, res, Maclen))
433                         fputs("Result = P\n", out);
434                 else
435                         fputs("Result = F\n", out);
436                 }
437         CMAC_CTX_free(cmac_ctx);
438         return rc;
439         }
440
441 #endif