2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
5 /* ====================================================================
6 * Copyright (c) 2005 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
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).
59 #define OPENSSL_FIPSAPI
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>
72 int main(int argc, char *argv[])
74 printf("No FIPS CMAC support\n");
80 #include <openssl/fips.h>
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,
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,
95 int main(int argc, char **argv)
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
102 int known_keylen = 0; /* Only set when Klen_counts_keys = 1 */
103 const EVP_CIPHER *cipher = 0;
107 while (argc > 1 && argv[1][0] == '-')
113 char *p = &argv[1][2];
118 fprintf(stderr, "Option %s needs a value\n", argv[1]);
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"))
133 cipher = EVP_des_ede3_cbc();
134 Klen_counts_keys = 1;
139 fprintf(stderr, "Unknown algorithm %s\n", p);
151 fprintf(stderr, "Unknown option %s\n", argv[1]);
160 in = fopen(argv[1], "r");
165 out = fopen(argv[2], "w");
169 fprintf(stderr, "FATAL input initialization error\n");
175 fprintf(stderr, "FATAL output initialization error\n");
179 if (!cmac_test(cipher, out, in, mode,
180 Klen_counts_keys, known_keylen))
182 fprintf(stderr, "FATAL cmac file processing error\n");
190 if (in && (in != stdin))
192 if (out && (out != stdout))
199 #define CMAC_TEST_MAXLINELEN 150000
201 int cmac_test(const EVP_CIPHER *cipher, FILE *out, FILE *in,
202 int mode, int Klen_counts_keys, int known_keylen)
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;
213 olinebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
214 linebuf = OPENSSL_malloc(CMAC_TEST_MAXLINELEN);
216 if (!linebuf || !olinebuf)
224 while (fgets(olinebuf, CMAC_TEST_MAXLINELEN, in))
227 strcpy(linebuf, olinebuf);
229 /* Skip leading space */
230 while (isspace((unsigned char)*keyword))
234 if (keyword[0] == '#')
236 if (fputs(olinebuf, out) < 0)
241 /* Look for = sign */
242 p = strchr(linebuf, '=');
244 /* If no = or starts with [ (for [L=20] line) just copy */
247 if (fputs(olinebuf, out) < 0)
254 /* Remove trailing space */
255 while (isspace((unsigned char)*q))
261 /* Remove leading space from value */
262 while (isspace((unsigned char)*value))
265 /* Remove trailing space from value */
266 p = value + strlen(value) - 1;
268 while (*p == '\n' || isspace((unsigned char)*p))
271 if (!strcmp(keyword, "Count"))
279 else if (!strcmp(keyword, "Klen"))
286 if (Klen_counts_keys)
288 Keys = OPENSSL_malloc(sizeof(*Keys) * Klen);
289 memset(Keys, '\0', sizeof(*Keys) * Klen);
293 Keys = OPENSSL_malloc(sizeof(*Keys));
294 memset(Keys, '\0', sizeof(*Keys));
297 else if (!strcmp(keyword, "Mlen"))
305 else if (!strcmp(keyword, "Tlen"))
313 else if (!strcmp(keyword, "Key") && !Klen_counts_keys)
317 Keys[0] = hex2bin_m(value, &Keylen);
321 else if (!strncmp(keyword, "Key", 3) && Klen_counts_keys)
323 int keynum = atoi(keyword + 3);
324 if (!keynum || keynum > Klen || Keys[keynum-1])
326 Keys[keynum-1] = hex2bin_m(value, &Keylen);
330 else if (!strcmp(keyword, "Msg"))
334 Msg = hex2bin_m(value, &Msglen);
338 else if (!strcmp(keyword, "Mac"))
344 Mac = hex2bin_m(value, &Maclen);
348 else if (!strcmp(keyword, "Result"))
357 fputs(olinebuf, out);
359 if (Keys && Msg && (!mode || Mac) && (Tlen > 0) && (Klen > 0))
361 if (Klen_counts_keys)
364 Key = OPENSSL_malloc(Klen * known_keylen);
365 for (x = 0; x < Klen; x++)
367 memcpy(Key + x * known_keylen,
368 Keys[x], known_keylen);
369 OPENSSL_free(Keys[x]);
371 Klen *= known_keylen;
375 Key = OPENSSL_malloc(Klen);
376 memcpy(Key, Keys[0], Klen);
377 OPENSSL_free(Keys[0]);
384 if (!print_cmac_gen(cipher, out,
391 if (!print_cmac_ver(cipher, out,
420 OPENSSL_free(olinebuf);
422 OPENSSL_free(linebuf);
434 fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
440 static int print_cmac_gen(const EVP_CIPHER *cipher, FILE *out,
441 unsigned char *Key, int Klen,
442 unsigned char *Msg, int Mlen,
447 unsigned char res[128];
448 CMAC_CTX *cmac_ctx = CMAC_CTX_new();
450 CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
451 CMAC_Update(cmac_ctx, Msg, Mlen);
452 if (!CMAC_Final(cmac_ctx, res, &reslen))
454 fputs("Error calculating CMAC\n", stderr);
457 else if (Tlen > (int)reslen)
459 fputs("Parameter error, Tlen > CMAC length\n", stderr);
464 fputs("Mac = ", out);
465 for (i = 0; i < Tlen; i++)
466 fprintf(out, "%02x", res[i]);
470 CMAC_CTX_free(cmac_ctx);
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,
482 unsigned char res[128];
483 CMAC_CTX *cmac_ctx = CMAC_CTX_new();
485 CMAC_Init(cmac_ctx, Key, Klen, cipher, 0);
486 CMAC_Update(cmac_ctx, Msg, Mlen);
487 if (!CMAC_Final(cmac_ctx, res, &reslen))
489 fputs("Error calculating CMAC\n", stderr);
492 else if (Tlen > (int)reslen)
494 fputs("Parameter error, Tlen > CMAC length\n", stderr);
497 else if (Tlen != Maclen)
499 fputs("Parameter error, Tlen != resulting Mac length\n", stderr);
504 if (!memcmp(Mac, res, Maclen))
505 fputs("Result = P\n", out);
507 fputs("Result = F\n", out);
509 CMAC_CTX_free(cmac_ctx);