fips_cmactest.c 11 KB

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