PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/security/nss/cmd/fipstest/fipstest.c

https://bitbucket.org/mkato/mozilla-1.9.0-win64
C | 4903 lines | 3797 code | 360 blank | 746 comment | 1445 complexity | ac6666cf55eeec83bda3ea3b4e6ec112 MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <ctype.h>
  39. #include "secitem.h"
  40. #include "blapi.h"
  41. #include "nss.h"
  42. #include "secerr.h"
  43. #include "secder.h"
  44. #include "secdig.h"
  45. #include "keythi.h"
  46. #include "ec.h"
  47. #include "hasht.h"
  48. #include "lowkeyi.h"
  49. #include "softoken.h"
  50. #if 0
  51. #include "../../lib/freebl/mpi/mpi.h"
  52. #endif
  53. #ifdef NSS_ENABLE_ECC
  54. extern SECStatus
  55. EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
  56. extern SECStatus
  57. EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
  58. const ECParams *srcParams);
  59. #endif
  60. #define ENCRYPT 1
  61. #define DECRYPT 0
  62. #define BYTE unsigned char
  63. #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
  64. #define RSA_MAX_TEST_MODULUS_BITS 4096
  65. #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
  66. #define RSA_MAX_TEST_EXPONENT_BYTES 8
  67. #define PQG_TEST_SEED_BYTES 20
  68. SECStatus
  69. hex_to_byteval(const char *c2, unsigned char *byteval)
  70. {
  71. int i;
  72. unsigned char offset;
  73. *byteval = 0;
  74. for (i=0; i<2; i++) {
  75. if (c2[i] >= '0' && c2[i] <= '9') {
  76. offset = c2[i] - '0';
  77. *byteval |= offset << 4*(1-i);
  78. } else if (c2[i] >= 'a' && c2[i] <= 'f') {
  79. offset = c2[i] - 'a';
  80. *byteval |= (offset + 10) << 4*(1-i);
  81. } else if (c2[i] >= 'A' && c2[i] <= 'F') {
  82. offset = c2[i] - 'A';
  83. *byteval |= (offset + 10) << 4*(1-i);
  84. } else {
  85. return SECFailure;
  86. }
  87. }
  88. return SECSuccess;
  89. }
  90. SECStatus
  91. byteval_to_hex(unsigned char byteval, char *c2, char a)
  92. {
  93. int i;
  94. unsigned char offset;
  95. for (i=0; i<2; i++) {
  96. offset = (byteval >> 4*(1-i)) & 0x0f;
  97. if (offset < 10) {
  98. c2[i] = '0' + offset;
  99. } else {
  100. c2[i] = a + offset - 10;
  101. }
  102. }
  103. return SECSuccess;
  104. }
  105. void
  106. to_hex_str(char *str, const unsigned char *buf, unsigned int len)
  107. {
  108. unsigned int i;
  109. for (i=0; i<len; i++) {
  110. byteval_to_hex(buf[i], &str[2*i], 'a');
  111. }
  112. str[2*len] = '\0';
  113. }
  114. void
  115. to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
  116. {
  117. unsigned int i;
  118. for (i=0; i<len; i++) {
  119. byteval_to_hex(buf[i], &str[2*i], 'A');
  120. }
  121. str[2*len] = '\0';
  122. }
  123. /*
  124. * Convert a string of hex digits (str) to an array (buf) of len bytes.
  125. * Return PR_TRUE if the hex string can fit in the byte array. Return
  126. * PR_FALSE if the hex string is empty or is too long.
  127. */
  128. PRBool
  129. from_hex_str(unsigned char *buf, unsigned int len, const char *str)
  130. {
  131. unsigned int nxdigit; /* number of hex digits in str */
  132. unsigned int i; /* index into buf */
  133. unsigned int j; /* index into str */
  134. /* count the hex digits */
  135. nxdigit = 0;
  136. for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
  137. /* empty body */
  138. }
  139. if (nxdigit == 0) {
  140. return PR_FALSE;
  141. }
  142. if (nxdigit > 2*len) {
  143. /*
  144. * The input hex string is too long, but we allow it if the
  145. * extra digits are leading 0's.
  146. */
  147. for (j = 0; j < nxdigit-2*len; j++) {
  148. if (str[j] != '0') {
  149. return PR_FALSE;
  150. }
  151. }
  152. /* skip leading 0's */
  153. str += nxdigit-2*len;
  154. nxdigit = 2*len;
  155. }
  156. for (i=0, j=0; i< len; i++) {
  157. if (2*i < 2*len-nxdigit) {
  158. /* Handle a short input as if we padded it with leading 0's. */
  159. if (2*i+1 < 2*len-nxdigit) {
  160. buf[i] = 0;
  161. } else {
  162. char tmp[2];
  163. tmp[0] = '0';
  164. tmp[1] = str[j];
  165. hex_to_byteval(tmp, &buf[i]);
  166. j++;
  167. }
  168. } else {
  169. hex_to_byteval(&str[j], &buf[i]);
  170. j += 2;
  171. }
  172. }
  173. return PR_TRUE;
  174. }
  175. SECStatus
  176. tdea_encrypt_buf(
  177. int mode,
  178. const unsigned char *key,
  179. const unsigned char *iv,
  180. unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
  181. const unsigned char *input, unsigned int inputlen)
  182. {
  183. SECStatus rv = SECFailure;
  184. DESContext *cx;
  185. unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
  186. unsigned int doublechecklen = 0;
  187. cx = DES_CreateContext(key, iv, mode, PR_TRUE);
  188. if (cx == NULL) {
  189. goto loser;
  190. }
  191. rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
  192. if (rv != SECSuccess) {
  193. goto loser;
  194. }
  195. if (*outputlen != inputlen) {
  196. goto loser;
  197. }
  198. DES_DestroyContext(cx, PR_TRUE);
  199. cx = NULL;
  200. /*
  201. * Doublecheck our result by decrypting the ciphertext and
  202. * compare the output with the input plaintext.
  203. */
  204. cx = DES_CreateContext(key, iv, mode, PR_FALSE);
  205. if (cx == NULL) {
  206. goto loser;
  207. }
  208. rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
  209. output, *outputlen);
  210. if (rv != SECSuccess) {
  211. goto loser;
  212. }
  213. if (doublechecklen != *outputlen) {
  214. goto loser;
  215. }
  216. DES_DestroyContext(cx, PR_TRUE);
  217. cx = NULL;
  218. if (memcmp(doublecheck, input, inputlen) != 0) {
  219. goto loser;
  220. }
  221. rv = SECSuccess;
  222. loser:
  223. if (cx != NULL) {
  224. DES_DestroyContext(cx, PR_TRUE);
  225. }
  226. return rv;
  227. }
  228. SECStatus
  229. tdea_decrypt_buf(
  230. int mode,
  231. const unsigned char *key,
  232. const unsigned char *iv,
  233. unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
  234. const unsigned char *input, unsigned int inputlen)
  235. {
  236. SECStatus rv = SECFailure;
  237. DESContext *cx;
  238. unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
  239. unsigned int doublechecklen = 0;
  240. cx = DES_CreateContext(key, iv, mode, PR_FALSE);
  241. if (cx == NULL) {
  242. goto loser;
  243. }
  244. rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
  245. input, inputlen);
  246. if (rv != SECSuccess) {
  247. goto loser;
  248. }
  249. if (*outputlen != inputlen) {
  250. goto loser;
  251. }
  252. DES_DestroyContext(cx, PR_TRUE);
  253. cx = NULL;
  254. /*
  255. * Doublecheck our result by encrypting the plaintext and
  256. * compare the output with the input ciphertext.
  257. */
  258. cx = DES_CreateContext(key, iv, mode, PR_TRUE);
  259. if (cx == NULL) {
  260. goto loser;
  261. }
  262. rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
  263. output, *outputlen);
  264. if (rv != SECSuccess) {
  265. goto loser;
  266. }
  267. if (doublechecklen != *outputlen) {
  268. goto loser;
  269. }
  270. DES_DestroyContext(cx, PR_TRUE);
  271. cx = NULL;
  272. if (memcmp(doublecheck, input, inputlen) != 0) {
  273. goto loser;
  274. }
  275. rv = SECSuccess;
  276. loser:
  277. if (cx != NULL) {
  278. DES_DestroyContext(cx, PR_TRUE);
  279. }
  280. return rv;
  281. }
  282. /*
  283. * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
  284. * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
  285. * and MMT have the same structure: given the key and IV (CBC mode
  286. * only), encrypt the given plaintext or decrypt the given ciphertext.
  287. * So we can handle them the same way.
  288. *
  289. * reqfn is the pathname of the REQUEST file.
  290. *
  291. * The output RESPONSE file is written to stdout.
  292. */
  293. void
  294. tdea_kat_mmt(char *reqfn)
  295. {
  296. char buf[180]; /* holds one line from the input REQUEST file.
  297. * needs to be large enough to hold the longest
  298. * line "CIPHERTEXT = <180 hex digits>\n".
  299. */
  300. FILE *req; /* input stream from the REQUEST file */
  301. FILE *resp; /* output stream to the RESPONSE file */
  302. int i, j;
  303. int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
  304. int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
  305. unsigned char key[24]; /* TDEA 3 key bundle */
  306. unsigned int numKeys = 0;
  307. unsigned char iv[8]; /* for all modes except ECB */
  308. unsigned char plaintext[8*20]; /* 1 to 20 blocks */
  309. unsigned int plaintextlen;
  310. unsigned char ciphertext[8*20]; /* 1 to 20 blocks */
  311. unsigned int ciphertextlen;
  312. SECStatus rv;
  313. req = fopen(reqfn, "r");
  314. resp = stdout;
  315. while (fgets(buf, sizeof buf, req) != NULL) {
  316. /* a comment or blank line */
  317. if (buf[0] == '#' || buf[0] == '\n') {
  318. fputs(buf, resp);
  319. continue;
  320. }
  321. /* [ENCRYPT] or [DECRYPT] */
  322. if (buf[0] == '[') {
  323. if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  324. crypt = ENCRYPT;
  325. } else {
  326. crypt = DECRYPT;
  327. }
  328. fputs(buf, resp);
  329. continue;
  330. }
  331. /* NumKeys */
  332. if (strncmp(&buf[0], "NumKeys", 7) == 0) {
  333. i = 7;
  334. while (isspace(buf[i]) || buf[i] == '=') {
  335. i++;
  336. }
  337. numKeys = buf[i];
  338. fputs(buf, resp);
  339. continue;
  340. }
  341. /* "COUNT = x" begins a new data set */
  342. if (strncmp(buf, "COUNT", 5) == 0) {
  343. /* mode defaults to ECB, if dataset has IV mode will be set CBC */
  344. mode = NSS_DES_EDE3;
  345. /* zeroize the variables for the test with this data set */
  346. memset(key, 0, sizeof key);
  347. memset(iv, 0, sizeof iv);
  348. memset(plaintext, 0, sizeof plaintext);
  349. plaintextlen = 0;
  350. memset(ciphertext, 0, sizeof ciphertext);
  351. ciphertextlen = 0;
  352. fputs(buf, resp);
  353. continue;
  354. }
  355. if (numKeys == 0) {
  356. if (strncmp(buf, "KEYs", 4) == 0) {
  357. i = 4;
  358. while (isspace(buf[i]) || buf[i] == '=') {
  359. i++;
  360. }
  361. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  362. hex_to_byteval(&buf[i], &key[j]);
  363. key[j+8] = key[j];
  364. key[j+16] = key[j];
  365. }
  366. fputs(buf, resp);
  367. continue;
  368. }
  369. } else {
  370. /* KEY1 = ... */
  371. if (strncmp(buf, "KEY1", 4) == 0) {
  372. i = 4;
  373. while (isspace(buf[i]) || buf[i] == '=') {
  374. i++;
  375. }
  376. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  377. hex_to_byteval(&buf[i], &key[j]);
  378. }
  379. fputs(buf, resp);
  380. continue;
  381. }
  382. /* KEY2 = ... */
  383. if (strncmp(buf, "KEY2", 4) == 0) {
  384. i = 4;
  385. while (isspace(buf[i]) || buf[i] == '=') {
  386. i++;
  387. }
  388. for (j=8; isxdigit(buf[i]); i+=2,j++) {
  389. hex_to_byteval(&buf[i], &key[j]);
  390. }
  391. fputs(buf, resp);
  392. continue;
  393. }
  394. /* KEY3 = ... */
  395. if (strncmp(buf, "KEY3", 4) == 0) {
  396. i = 4;
  397. while (isspace(buf[i]) || buf[i] == '=') {
  398. i++;
  399. }
  400. for (j=16; isxdigit(buf[i]); i+=2,j++) {
  401. hex_to_byteval(&buf[i], &key[j]);
  402. }
  403. fputs(buf, resp);
  404. continue;
  405. }
  406. }
  407. /* IV = ... */
  408. if (strncmp(buf, "IV", 2) == 0) {
  409. mode = NSS_DES_EDE3_CBC;
  410. i = 2;
  411. while (isspace(buf[i]) || buf[i] == '=') {
  412. i++;
  413. }
  414. for (j=0; j<sizeof iv; i+=2,j++) {
  415. hex_to_byteval(&buf[i], &iv[j]);
  416. }
  417. fputs(buf, resp);
  418. continue;
  419. }
  420. /* PLAINTEXT = ... */
  421. if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  422. /* sanity check */
  423. if (crypt != ENCRYPT) {
  424. goto loser;
  425. }
  426. i = 9;
  427. while (isspace(buf[i]) || buf[i] == '=') {
  428. i++;
  429. }
  430. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  431. hex_to_byteval(&buf[i], &plaintext[j]);
  432. }
  433. plaintextlen = j;
  434. rv = tdea_encrypt_buf(mode, key,
  435. (mode == NSS_DES_EDE3) ? NULL : iv,
  436. ciphertext, &ciphertextlen, sizeof ciphertext,
  437. plaintext, plaintextlen);
  438. if (rv != SECSuccess) {
  439. goto loser;
  440. }
  441. fputs(buf, resp);
  442. fputs("CIPHERTEXT = ", resp);
  443. to_hex_str(buf, ciphertext, ciphertextlen);
  444. fputs(buf, resp);
  445. fputc('\n', resp);
  446. continue;
  447. }
  448. /* CIPHERTEXT = ... */
  449. if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  450. /* sanity check */
  451. if (crypt != DECRYPT) {
  452. goto loser;
  453. }
  454. i = 10;
  455. while (isspace(buf[i]) || buf[i] == '=') {
  456. i++;
  457. }
  458. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  459. hex_to_byteval(&buf[i], &ciphertext[j]);
  460. }
  461. ciphertextlen = j;
  462. rv = tdea_decrypt_buf(mode, key,
  463. (mode == NSS_DES_EDE3) ? NULL : iv,
  464. plaintext, &plaintextlen, sizeof plaintext,
  465. ciphertext, ciphertextlen);
  466. if (rv != SECSuccess) {
  467. goto loser;
  468. }
  469. fputs(buf, resp);
  470. fputs("PLAINTEXT = ", resp);
  471. to_hex_str(buf, plaintext, plaintextlen);
  472. fputs(buf, resp);
  473. fputc('\n', resp);
  474. continue;
  475. }
  476. }
  477. loser:
  478. fclose(req);
  479. }
  480. /*
  481. * Set the parity bit for the given byte
  482. */
  483. BYTE odd_parity( BYTE in)
  484. {
  485. BYTE out = in;
  486. in ^= in >> 4;
  487. in ^= in >> 2;
  488. in ^= in >> 1;
  489. return (BYTE)(out ^ !(in & 1));
  490. }
  491. /*
  492. * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
  493. * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
  494. */
  495. void
  496. tdea_mct_next_keys(unsigned char *key,
  497. const unsigned char *text_2, const unsigned char *text_1,
  498. const unsigned char *text, unsigned int numKeys)
  499. {
  500. int k;
  501. /* key1[i+1] = key1[i] xor PT/CT[j] */
  502. for (k=0; k<8; k++) {
  503. key[k] ^= text[k];
  504. }
  505. /* key2 */
  506. if (numKeys == 2 || numKeys == 3) {
  507. /* key2 independent */
  508. for (k=8; k<16; k++) {
  509. /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
  510. key[k] ^= text_1[k-8];
  511. }
  512. } else {
  513. /* key2 == key 1 */
  514. for (k=8; k<16; k++) {
  515. /* key2[i+1] = KEY2[i] xor PT/CT[j] */
  516. key[k] = key[k-8];
  517. }
  518. }
  519. /* key3 */
  520. if (numKeys == 1 || numKeys == 2) {
  521. /* key3 == key 1 */
  522. for (k=16; k<24; k++) {
  523. /* key3[i+1] = KEY3[i] xor PT/CT[j] */
  524. key[k] = key[k-16];
  525. }
  526. } else {
  527. /* key3 independent */
  528. for (k=16; k<24; k++) {
  529. /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
  530. key[k] ^= text_2[k-16];
  531. }
  532. }
  533. /* set the parity bits */
  534. for (k=0; k<24; k++) {
  535. key[k] = odd_parity(key[k]);
  536. }
  537. }
  538. /*
  539. * Perform the Monte Carlo Test
  540. *
  541. * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
  542. * crypt = ENCRYPT || DECRYPT
  543. * inputtext = plaintext or Cyphertext depending on the value of crypt
  544. * inputlength is expected to be size 8 bytes
  545. * iv = needs to be set for NSS_DES_EDE3_CBC mode
  546. * resp = is the output response file.
  547. */
  548. void
  549. tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys,
  550. unsigned int crypt, unsigned char* inputtext,
  551. unsigned int inputlength, unsigned char* iv, FILE *resp) {
  552. int i, j;
  553. unsigned char outputtext_1[8]; /* PT/CT[j-1] */
  554. unsigned char outputtext_2[8]; /* PT/CT[j-2] */
  555. char buf[80]; /* holds one line from the input REQUEST file. */
  556. unsigned int outputlen;
  557. unsigned char outputtext[8];
  558. SECStatus rv;
  559. if (mode == NSS_DES_EDE3 && iv != NULL) {
  560. printf("IV must be NULL for NSS_DES_EDE3 mode");
  561. goto loser;
  562. } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
  563. printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
  564. goto loser;
  565. }
  566. /* loop 400 times */
  567. for (i=0; i<400; i++) {
  568. /* if i == 0 CV[0] = IV not necessary */
  569. /* record the count and key values and plainText */
  570. sprintf(buf, "COUNT = %d\n", i);
  571. fputs(buf, resp);
  572. /* Output KEY1[i] */
  573. fputs("KEY1 = ", resp);
  574. to_hex_str(buf, key, 8);
  575. fputs(buf, resp);
  576. fputc('\n', resp);
  577. /* Output KEY2[i] */
  578. fputs("KEY2 = ", resp);
  579. to_hex_str(buf, &key[8], 8);
  580. fputs(buf, resp);
  581. fputc('\n', resp);
  582. /* Output KEY3[i] */
  583. fputs("KEY3 = ", resp);
  584. to_hex_str(buf, &key[16], 8);
  585. fputs(buf, resp);
  586. fputc('\n', resp);
  587. if (mode == NSS_DES_EDE3_CBC) {
  588. /* Output CV[i] */
  589. fputs("IV = ", resp);
  590. to_hex_str(buf, iv, 8);
  591. fputs(buf, resp);
  592. fputc('\n', resp);
  593. }
  594. if (crypt == ENCRYPT) {
  595. /* Output PT[0] */
  596. fputs("PLAINTEXT = ", resp);
  597. } else {
  598. /* Output CT[0] */
  599. fputs("CIPHERTEXT = ", resp);
  600. }
  601. to_hex_str(buf, inputtext, inputlength);
  602. fputs(buf, resp);
  603. fputc('\n', resp);
  604. /* loop 10,000 times */
  605. for (j=0; j<10000; j++) {
  606. outputlen = 0;
  607. if (crypt == ENCRYPT) {
  608. /* inputtext == ciphertext outputtext == plaintext*/
  609. rv = tdea_encrypt_buf(mode, key,
  610. (mode == NSS_DES_EDE3) ? NULL : iv,
  611. outputtext, &outputlen, 8,
  612. inputtext, 8);
  613. } else {
  614. /* inputtext == plaintext outputtext == ciphertext */
  615. rv = tdea_decrypt_buf(mode, key,
  616. (mode == NSS_DES_EDE3) ? NULL : iv,
  617. outputtext, &outputlen, 8,
  618. inputtext, 8);
  619. }
  620. if (rv != SECSuccess) {
  621. goto loser;
  622. }
  623. if (outputlen != inputlength) {
  624. goto loser;
  625. }
  626. if (mode == NSS_DES_EDE3_CBC) {
  627. if (crypt == ENCRYPT) {
  628. if (j == 0) {
  629. /*P[j+1] = CV[0] */
  630. memcpy(inputtext, iv, 8);
  631. } else {
  632. /* p[j+1] = C[j-1] */
  633. memcpy(inputtext, outputtext_1, 8);
  634. }
  635. /* CV[j+1] = C[j] */
  636. memcpy(iv, outputtext, 8);
  637. if (j != 9999) {
  638. /* save C[j-1] */
  639. memcpy(outputtext_1, outputtext, 8);
  640. }
  641. } else { /* DECRYPT */
  642. /* CV[j+1] = C[j] */
  643. memcpy(iv, inputtext, 8);
  644. /* C[j+1] = P[j] */
  645. memcpy(inputtext, outputtext, 8);
  646. }
  647. } else {
  648. /* ECB mode PT/CT[j+1] = CT/PT[j] */
  649. memcpy(inputtext, outputtext, 8);
  650. }
  651. /* Save PT/CT[j-2] and PT/CT[j-1] */
  652. if (j==9997) memcpy(outputtext_2, outputtext, 8);
  653. if (j==9998) memcpy(outputtext_1, outputtext, 8);
  654. /* done at the end of the for(j) loop */
  655. }
  656. if (crypt == ENCRYPT) {
  657. /* Output CT[j] */
  658. fputs("CIPHERTEXT = ", resp);
  659. } else {
  660. /* Output PT[j] */
  661. fputs("PLAINTEXT = ", resp);
  662. }
  663. to_hex_str(buf, outputtext, 8);
  664. fputs(buf, resp);
  665. fputc('\n', resp);
  666. /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
  667. * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
  668. */
  669. tdea_mct_next_keys(key, outputtext_2,
  670. outputtext_1, outputtext, numKeys);
  671. if (mode == NSS_DES_EDE3_CBC) {
  672. /* taken care of in the j=9999 iteration */
  673. if (crypt == ENCRYPT) {
  674. /* P[i] = C[j-1] */
  675. /* CV[i] = C[j] */
  676. } else {
  677. /* taken care of in the j=9999 iteration */
  678. /* CV[i] = C[j] */
  679. /* C[i] = P[j] */
  680. }
  681. } else {
  682. /* ECB PT/CT[i] = PT/CT[j] */
  683. memcpy(inputtext, outputtext, 8);
  684. }
  685. /* done at the end of the for(i) loop */
  686. fputc('\n', resp);
  687. }
  688. loser:
  689. return;
  690. }
  691. /*
  692. * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
  693. * by gathering the input from the request file, and then
  694. * calling tdea_mct_test.
  695. *
  696. * reqfn is the pathname of the input REQUEST file.
  697. *
  698. * The output RESPONSE file is written to stdout.
  699. */
  700. void
  701. tdea_mct(int mode, char *reqfn)
  702. {
  703. int i, j;
  704. char buf[80]; /* holds one line from the input REQUEST file. */
  705. FILE *req; /* input stream from the REQUEST file */
  706. FILE *resp; /* output stream to the RESPONSE file */
  707. unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
  708. unsigned char key[24]; /* TDEA 3 key bundle */
  709. unsigned int numKeys = 0;
  710. unsigned char plaintext[8]; /* PT[j] */
  711. unsigned char ciphertext[8]; /* CT[j] */
  712. unsigned char iv[8];
  713. /* zeroize the variables for the test with this data set */
  714. memset(key, 0, sizeof key);
  715. memset(plaintext, 0, sizeof plaintext);
  716. memset(ciphertext, 0, sizeof ciphertext);
  717. memset(iv, 0, sizeof iv);
  718. req = fopen(reqfn, "r");
  719. resp = stdout;
  720. while (fgets(buf, sizeof buf, req) != NULL) {
  721. /* a comment or blank line */
  722. if (buf[0] == '#' || buf[0] == '\n') {
  723. fputs(buf, resp);
  724. continue;
  725. }
  726. /* [ENCRYPT] or [DECRYPT] */
  727. if (buf[0] == '[') {
  728. if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  729. crypt = ENCRYPT;
  730. } else {
  731. crypt = DECRYPT;
  732. }
  733. fputs(buf, resp);
  734. continue;
  735. }
  736. /* NumKeys */
  737. if (strncmp(&buf[0], "NumKeys", 7) == 0) {
  738. i = 7;
  739. while (isspace(buf[i]) || buf[i] == '=') {
  740. i++;
  741. }
  742. numKeys = atoi(&buf[i]);
  743. continue;
  744. }
  745. /* KEY1 = ... */
  746. if (strncmp(buf, "KEY1", 4) == 0) {
  747. i = 4;
  748. while (isspace(buf[i]) || buf[i] == '=') {
  749. i++;
  750. }
  751. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  752. hex_to_byteval(&buf[i], &key[j]);
  753. }
  754. continue;
  755. }
  756. /* KEY2 = ... */
  757. if (strncmp(buf, "KEY2", 4) == 0) {
  758. i = 4;
  759. while (isspace(buf[i]) || buf[i] == '=') {
  760. i++;
  761. }
  762. for (j=8; isxdigit(buf[i]); i+=2,j++) {
  763. hex_to_byteval(&buf[i], &key[j]);
  764. }
  765. continue;
  766. }
  767. /* KEY3 = ... */
  768. if (strncmp(buf, "KEY3", 4) == 0) {
  769. i = 4;
  770. while (isspace(buf[i]) || buf[i] == '=') {
  771. i++;
  772. }
  773. for (j=16; isxdigit(buf[i]); i+=2,j++) {
  774. hex_to_byteval(&buf[i], &key[j]);
  775. }
  776. continue;
  777. }
  778. /* IV = ... */
  779. if (strncmp(buf, "IV", 2) == 0) {
  780. i = 2;
  781. while (isspace(buf[i]) || buf[i] == '=') {
  782. i++;
  783. }
  784. for (j=0; j<sizeof iv; i+=2,j++) {
  785. hex_to_byteval(&buf[i], &iv[j]);
  786. }
  787. continue;
  788. }
  789. /* PLAINTEXT = ... */
  790. if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  791. /* sanity check */
  792. if (crypt != ENCRYPT) {
  793. goto loser;
  794. }
  795. /* PT[0] = PT */
  796. i = 9;
  797. while (isspace(buf[i]) || buf[i] == '=') {
  798. i++;
  799. }
  800. for (j=0; j<sizeof plaintext; i+=2,j++) {
  801. hex_to_byteval(&buf[i], &plaintext[j]);
  802. }
  803. /* do the Monte Carlo test */
  804. if (mode==NSS_DES_EDE3) {
  805. tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
  806. } else {
  807. tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
  808. }
  809. continue;
  810. }
  811. /* CIPHERTEXT = ... */
  812. if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  813. /* sanity check */
  814. if (crypt != DECRYPT) {
  815. goto loser;
  816. }
  817. /* CT[0] = CT */
  818. i = 10;
  819. while (isspace(buf[i]) || buf[i] == '=') {
  820. i++;
  821. }
  822. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  823. hex_to_byteval(&buf[i], &ciphertext[j]);
  824. }
  825. /* do the Monte Carlo test */
  826. if (mode==NSS_DES_EDE3) {
  827. tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
  828. } else {
  829. tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
  830. }
  831. continue;
  832. }
  833. }
  834. loser:
  835. fclose(req);
  836. }
  837. SECStatus
  838. aes_encrypt_buf(
  839. int mode,
  840. const unsigned char *key, unsigned int keysize,
  841. const unsigned char *iv,
  842. unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
  843. const unsigned char *input, unsigned int inputlen)
  844. {
  845. SECStatus rv = SECFailure;
  846. AESContext *cx;
  847. unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
  848. unsigned int doublechecklen = 0;
  849. cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
  850. if (cx == NULL) {
  851. goto loser;
  852. }
  853. rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
  854. if (rv != SECSuccess) {
  855. goto loser;
  856. }
  857. if (*outputlen != inputlen) {
  858. goto loser;
  859. }
  860. AES_DestroyContext(cx, PR_TRUE);
  861. cx = NULL;
  862. /*
  863. * Doublecheck our result by decrypting the ciphertext and
  864. * compare the output with the input plaintext.
  865. */
  866. cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
  867. if (cx == NULL) {
  868. goto loser;
  869. }
  870. rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
  871. output, *outputlen);
  872. if (rv != SECSuccess) {
  873. goto loser;
  874. }
  875. if (doublechecklen != *outputlen) {
  876. goto loser;
  877. }
  878. AES_DestroyContext(cx, PR_TRUE);
  879. cx = NULL;
  880. if (memcmp(doublecheck, input, inputlen) != 0) {
  881. goto loser;
  882. }
  883. rv = SECSuccess;
  884. loser:
  885. if (cx != NULL) {
  886. AES_DestroyContext(cx, PR_TRUE);
  887. }
  888. return rv;
  889. }
  890. SECStatus
  891. aes_decrypt_buf(
  892. int mode,
  893. const unsigned char *key, unsigned int keysize,
  894. const unsigned char *iv,
  895. unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
  896. const unsigned char *input, unsigned int inputlen)
  897. {
  898. SECStatus rv = SECFailure;
  899. AESContext *cx;
  900. unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
  901. unsigned int doublechecklen = 0;
  902. cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
  903. if (cx == NULL) {
  904. goto loser;
  905. }
  906. rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
  907. input, inputlen);
  908. if (rv != SECSuccess) {
  909. goto loser;
  910. }
  911. if (*outputlen != inputlen) {
  912. goto loser;
  913. }
  914. AES_DestroyContext(cx, PR_TRUE);
  915. cx = NULL;
  916. /*
  917. * Doublecheck our result by encrypting the plaintext and
  918. * compare the output with the input ciphertext.
  919. */
  920. cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
  921. if (cx == NULL) {
  922. goto loser;
  923. }
  924. rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
  925. output, *outputlen);
  926. if (rv != SECSuccess) {
  927. goto loser;
  928. }
  929. if (doublechecklen != *outputlen) {
  930. goto loser;
  931. }
  932. AES_DestroyContext(cx, PR_TRUE);
  933. cx = NULL;
  934. if (memcmp(doublecheck, input, inputlen) != 0) {
  935. goto loser;
  936. }
  937. rv = SECSuccess;
  938. loser:
  939. if (cx != NULL) {
  940. AES_DestroyContext(cx, PR_TRUE);
  941. }
  942. return rv;
  943. }
  944. /*
  945. * Perform the AES Known Answer Test (KAT) or Multi-block Message
  946. * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
  947. * and MMT have the same structure: given the key and IV (CBC mode
  948. * only), encrypt the given plaintext or decrypt the given ciphertext.
  949. * So we can handle them the same way.
  950. *
  951. * reqfn is the pathname of the REQUEST file.
  952. *
  953. * The output RESPONSE file is written to stdout.
  954. */
  955. void
  956. aes_kat_mmt(char *reqfn)
  957. {
  958. char buf[512]; /* holds one line from the input REQUEST file.
  959. * needs to be large enough to hold the longest
  960. * line "CIPHERTEXT = <320 hex digits>\n".
  961. */
  962. FILE *aesreq; /* input stream from the REQUEST file */
  963. FILE *aesresp; /* output stream to the RESPONSE file */
  964. int i, j;
  965. int mode; /* NSS_AES (ECB) or NSS_AES_CBC */
  966. int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
  967. unsigned char key[32]; /* 128, 192, or 256 bits */
  968. unsigned int keysize;
  969. unsigned char iv[16]; /* for all modes except ECB */
  970. unsigned char plaintext[10*16]; /* 1 to 10 blocks */
  971. unsigned int plaintextlen;
  972. unsigned char ciphertext[10*16]; /* 1 to 10 blocks */
  973. unsigned int ciphertextlen;
  974. SECStatus rv;
  975. aesreq = fopen(reqfn, "r");
  976. aesresp = stdout;
  977. while (fgets(buf, sizeof buf, aesreq) != NULL) {
  978. /* a comment or blank line */
  979. if (buf[0] == '#' || buf[0] == '\n') {
  980. fputs(buf, aesresp);
  981. continue;
  982. }
  983. /* [ENCRYPT] or [DECRYPT] */
  984. if (buf[0] == '[') {
  985. if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  986. encrypt = 1;
  987. } else {
  988. encrypt = 0;
  989. }
  990. fputs(buf, aesresp);
  991. continue;
  992. }
  993. /* "COUNT = x" begins a new data set */
  994. if (strncmp(buf, "COUNT", 5) == 0) {
  995. mode = NSS_AES;
  996. /* zeroize the variables for the test with this data set */
  997. memset(key, 0, sizeof key);
  998. keysize = 0;
  999. memset(iv, 0, sizeof iv);
  1000. memset(plaintext, 0, sizeof plaintext);
  1001. plaintextlen = 0;
  1002. memset(ciphertext, 0, sizeof ciphertext);
  1003. ciphertextlen = 0;
  1004. fputs(buf, aesresp);
  1005. continue;
  1006. }
  1007. /* KEY = ... */
  1008. if (strncmp(buf, "KEY", 3) == 0) {
  1009. i = 3;
  1010. while (isspace(buf[i]) || buf[i] == '=') {
  1011. i++;
  1012. }
  1013. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1014. hex_to_byteval(&buf[i], &key[j]);
  1015. }
  1016. keysize = j;
  1017. fputs(buf, aesresp);
  1018. continue;
  1019. }
  1020. /* IV = ... */
  1021. if (strncmp(buf, "IV", 2) == 0) {
  1022. mode = NSS_AES_CBC;
  1023. i = 2;
  1024. while (isspace(buf[i]) || buf[i] == '=') {
  1025. i++;
  1026. }
  1027. for (j=0; j<sizeof iv; i+=2,j++) {
  1028. hex_to_byteval(&buf[i], &iv[j]);
  1029. }
  1030. fputs(buf, aesresp);
  1031. continue;
  1032. }
  1033. /* PLAINTEXT = ... */
  1034. if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  1035. /* sanity check */
  1036. if (!encrypt) {
  1037. goto loser;
  1038. }
  1039. i = 9;
  1040. while (isspace(buf[i]) || buf[i] == '=') {
  1041. i++;
  1042. }
  1043. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1044. hex_to_byteval(&buf[i], &plaintext[j]);
  1045. }
  1046. plaintextlen = j;
  1047. rv = aes_encrypt_buf(mode, key, keysize,
  1048. (mode == NSS_AES) ? NULL : iv,
  1049. ciphertext, &ciphertextlen, sizeof ciphertext,
  1050. plaintext, plaintextlen);
  1051. if (rv != SECSuccess) {
  1052. goto loser;
  1053. }
  1054. fputs(buf, aesresp);
  1055. fputs("CIPHERTEXT = ", aesresp);
  1056. to_hex_str(buf, ciphertext, ciphertextlen);
  1057. fputs(buf, aesresp);
  1058. fputc('\n', aesresp);
  1059. continue;
  1060. }
  1061. /* CIPHERTEXT = ... */
  1062. if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  1063. /* sanity check */
  1064. if (encrypt) {
  1065. goto loser;
  1066. }
  1067. i = 10;
  1068. while (isspace(buf[i]) || buf[i] == '=') {
  1069. i++;
  1070. }
  1071. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1072. hex_to_byteval(&buf[i], &ciphertext[j]);
  1073. }
  1074. ciphertextlen = j;
  1075. rv = aes_decrypt_buf(mode, key, keysize,
  1076. (mode == NSS_AES) ? NULL : iv,
  1077. plaintext, &plaintextlen, sizeof plaintext,
  1078. ciphertext, ciphertextlen);
  1079. if (rv != SECSuccess) {
  1080. goto loser;
  1081. }
  1082. fputs(buf, aesresp);
  1083. fputs("PLAINTEXT = ", aesresp);
  1084. to_hex_str(buf, plaintext, plaintextlen);
  1085. fputs(buf, aesresp);
  1086. fputc('\n', aesresp);
  1087. continue;
  1088. }
  1089. }
  1090. loser:
  1091. fclose(aesreq);
  1092. }
  1093. /*
  1094. * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
  1095. * Test (MCT) in ECB and CBC modes.
  1096. */
  1097. void
  1098. aes_mct_next_key(unsigned char *key, unsigned int keysize,
  1099. const unsigned char *ciphertext_1, const unsigned char *ciphertext)
  1100. {
  1101. int k;
  1102. switch (keysize) {
  1103. case 16: /* 128-bit key */
  1104. /* Key[i+1] = Key[i] xor CT[j] */
  1105. for (k=0; k<16; k++) {
  1106. key[k] ^= ciphertext[k];
  1107. }
  1108. break;
  1109. case 24: /* 192-bit key */
  1110. /*
  1111. * Key[i+1] = Key[i] xor (last 64-bits of
  1112. * CT[j-1] || CT[j])
  1113. */
  1114. for (k=0; k<8; k++) {
  1115. key[k] ^= ciphertext_1[k+8];
  1116. }
  1117. for (k=8; k<24; k++) {
  1118. key[k] ^= ciphertext[k-8];
  1119. }
  1120. break;
  1121. case 32: /* 256-bit key */
  1122. /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
  1123. for (k=0; k<16; k++) {
  1124. key[k] ^= ciphertext_1[k];
  1125. }
  1126. for (k=16; k<32; k++) {
  1127. key[k] ^= ciphertext[k-16];
  1128. }
  1129. break;
  1130. }
  1131. }
  1132. /*
  1133. * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
  1134. * our AES code in streaming mode because the plaintext or ciphertext
  1135. * is generated block by block as we go, so we can't collect all the
  1136. * plaintext or ciphertext in one buffer and encrypt or decrypt it in
  1137. * one shot.
  1138. *
  1139. * reqfn is the pathname of the input REQUEST file.
  1140. *
  1141. * The output RESPONSE file is written to stdout.
  1142. */
  1143. void
  1144. aes_ecb_mct(char *reqfn)
  1145. {
  1146. char buf[80]; /* holds one line from the input REQUEST file.
  1147. * needs to be large enough to hold the longest
  1148. * line "KEY = <64 hex digits>\n".
  1149. */
  1150. FILE *aesreq; /* input stream from the REQUEST file */
  1151. FILE *aesresp; /* output stream to the RESPONSE file */
  1152. int i, j;
  1153. int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
  1154. unsigned char key[32]; /* 128, 192, or 256 bits */
  1155. unsigned int keysize;
  1156. unsigned char plaintext[16]; /* PT[j] */
  1157. unsigned char plaintext_1[16]; /* PT[j-1] */
  1158. unsigned char ciphertext[16]; /* CT[j] */
  1159. unsigned char ciphertext_1[16]; /* CT[j-1] */
  1160. unsigned char doublecheck[16];
  1161. unsigned int outputlen;
  1162. AESContext *cx = NULL; /* the operation being tested */
  1163. AESContext *cx2 = NULL; /* the inverse operation done in parallel
  1164. * to doublecheck our result.
  1165. */
  1166. SECStatus rv;
  1167. aesreq = fopen(reqfn, "r");
  1168. aesresp = stdout;
  1169. while (fgets(buf, sizeof buf, aesreq) != NULL) {
  1170. /* a comment or blank line */
  1171. if (buf[0] == '#' || buf[0] == '\n') {
  1172. fputs(buf, aesresp);
  1173. continue;
  1174. }
  1175. /* [ENCRYPT] or [DECRYPT] */
  1176. if (buf[0] == '[') {
  1177. if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  1178. encrypt = 1;
  1179. } else {
  1180. encrypt = 0;
  1181. }
  1182. fputs(buf, aesresp);
  1183. continue;
  1184. }
  1185. /* "COUNT = x" begins a new data set */
  1186. if (strncmp(buf, "COUNT", 5) == 0) {
  1187. /* zeroize the variables for the test with this data set */
  1188. memset(key, 0, sizeof key);
  1189. keysize = 0;
  1190. memset(plaintext, 0, sizeof plaintext);
  1191. memset(ciphertext, 0, sizeof ciphertext);
  1192. continue;
  1193. }
  1194. /* KEY = ... */
  1195. if (strncmp(buf, "KEY", 3) == 0) {
  1196. /* Key[0] = Key */
  1197. i = 3;
  1198. while (isspace(buf[i]) || buf[i] == '=') {
  1199. i++;
  1200. }
  1201. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1202. hex_to_byteval(&buf[i], &key[j]);
  1203. }
  1204. keysize = j;
  1205. continue;
  1206. }
  1207. /* PLAINTEXT = ... */
  1208. if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  1209. /* sanity check */
  1210. if (!encrypt) {
  1211. goto loser;
  1212. }
  1213. /* PT[0] = PT */
  1214. i = 9;
  1215. while (isspace(buf[i]) || buf[i] == '=') {
  1216. i++;
  1217. }
  1218. for (j=0; j<sizeof plaintext; i+=2,j++) {
  1219. hex_to_byteval(&buf[i], &plaintext[j]);
  1220. }
  1221. for (i=0; i<100; i++) {
  1222. sprintf(buf, "COUNT = %d\n", i);
  1223. fputs(buf, aesresp);
  1224. /* Output Key[i] */
  1225. fputs("KEY = ", aesresp);
  1226. to_hex_str(buf, key, keysize);
  1227. fputs(buf, aesresp);
  1228. fputc('\n', aesresp);
  1229. /* Output PT[0] */
  1230. fputs("PLAINTEXT = ", aesresp);
  1231. to_hex_str(buf, plaintext, sizeof plaintext);
  1232. fputs(buf, aesresp);
  1233. fputc('\n', aesresp);
  1234. cx = AES_CreateContext(key, NULL, NSS_AES,
  1235. PR_TRUE, keysize, 16);
  1236. if (cx == NULL) {
  1237. goto loser;
  1238. }
  1239. /*
  1240. * doublecheck our result by decrypting the result
  1241. * and comparing the output with the plaintext.
  1242. */
  1243. cx2 = AES_CreateContext(key, NULL, NSS_AES,
  1244. PR_FALSE, keysize, 16);
  1245. if (cx2 == NULL) {
  1246. goto loser;
  1247. }
  1248. for (j=0; j<1000; j++) {
  1249. /* Save CT[j-1] */
  1250. memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
  1251. /* CT[j] = AES(Key[i], PT[j]) */
  1252. outputlen = 0;
  1253. rv = AES_Encrypt(cx,
  1254. ciphertext, &outputlen, sizeof ciphertext,
  1255. plaintext, sizeof plaintext);
  1256. if (rv != SECSuccess) {
  1257. goto loser;
  1258. }
  1259. if (outputlen != sizeof plaintext) {
  1260. goto loser;
  1261. }
  1262. /* doublecheck our result */
  1263. outputlen = 0;
  1264. rv = AES_Decrypt(cx2,
  1265. doublecheck, &outputlen, sizeof doublecheck,
  1266. ciphertext, sizeof ciphertext);
  1267. if (rv != SECSuccess) {
  1268. goto loser;
  1269. }
  1270. if (outputlen != sizeof ciphertext) {
  1271. goto loser;
  1272. }
  1273. if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
  1274. goto loser;
  1275. }
  1276. /* PT[j+1] = CT[j] */
  1277. memcpy(plaintext, ciphertext, sizeof plaintext);
  1278. }
  1279. AES_DestroyContext(cx, PR_TRUE);
  1280. cx = NULL;
  1281. AES_DestroyContext(cx2, PR_TRUE);
  1282. cx2 = NULL;
  1283. /* Output CT[j] */
  1284. fputs("CIPHERTEXT = ", aesresp);
  1285. to_hex_str(buf, ciphertext, sizeof ciphertext);
  1286. fputs(buf, aesresp);
  1287. fputc('\n', aesresp);
  1288. /* Key[i+1] = Key[i] xor ... */
  1289. aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
  1290. /* PT[0] = CT[j] */
  1291. /* done at the end of the for(j) loop */
  1292. fputc('\n', aesresp);
  1293. }
  1294. continue;
  1295. }
  1296. /* CIPHERTEXT = ... */
  1297. if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  1298. /* sanity check */
  1299. if (encrypt) {
  1300. goto loser;
  1301. }
  1302. /* CT[0] = CT */
  1303. i = 10;
  1304. while (isspace(buf[i]) || buf[i] == '=') {
  1305. i++;
  1306. }
  1307. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1308. hex_to_byteval(&buf[i], &ciphertext[j]);
  1309. }
  1310. for (i=0; i<100; i++) {
  1311. sprintf(buf, "COUNT = %d\n", i);
  1312. fputs(buf, aesresp);
  1313. /* Output Key[i] */
  1314. fputs("KEY = ", aesresp);
  1315. to_hex_str(buf, key, keysize);
  1316. fputs(buf, aesresp);
  1317. fputc('\n', aesresp);
  1318. /* Output CT[0] */
  1319. fputs("CIPHERTEXT = ", aesresp);
  1320. to_hex_str(buf, ciphertext, sizeof ciphertext);
  1321. fputs(buf, aesresp);
  1322. fputc('\n', aesresp);
  1323. cx = AES_CreateContext(key, NULL, NSS_AES,
  1324. PR_FALSE, keysize, 16);
  1325. if (cx == NULL) {
  1326. goto loser;
  1327. }
  1328. /*
  1329. * doublecheck our result by encrypting the result
  1330. * and comparing the output with the ciphertext.
  1331. */
  1332. cx2 = AES_CreateContext(key, NULL, NSS_AES,
  1333. PR_TRUE, keysize, 16);
  1334. if (cx2 == NULL) {
  1335. goto loser;
  1336. }
  1337. for (j=0; j<1000; j++) {
  1338. /* Save PT[j-1] */
  1339. memcpy(plaintext_1, plaintext, sizeof plaintext);
  1340. /* PT[j] = AES(Key[i], CT[j]) */
  1341. outputlen = 0;
  1342. rv = AES_Decrypt(cx,
  1343. plaintext, &outputlen, sizeof plaintext,
  1344. ciphertext, sizeof ciphertext);
  1345. if (rv != SECSuccess) {
  1346. goto loser;
  1347. }
  1348. if (outputlen != sizeof ciphertext) {
  1349. goto loser;
  1350. }
  1351. /* doublecheck our result */
  1352. outputlen = 0;
  1353. rv = AES_Encrypt(cx2,
  1354. doublecheck, &outputlen, sizeof doublecheck,
  1355. plaintext, sizeof plaintext);
  1356. if (rv != SECSuccess) {
  1357. goto loser;
  1358. }
  1359. if (outputlen != sizeof plaintext) {
  1360. goto loser;
  1361. }
  1362. if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
  1363. goto loser;
  1364. }
  1365. /* CT[j+1] = PT[j] */
  1366. memcpy(ciphertext, plaintext, sizeof ciphertext);
  1367. }
  1368. AES_DestroyContext(cx, PR_TRUE);
  1369. cx = NULL;
  1370. AES_DestroyContext(cx2, PR_TRUE);
  1371. cx2 = NULL;
  1372. /* Output PT[j] */
  1373. fputs("PLAINTEXT = ", aesresp);
  1374. to_hex_str(buf, plaintext, sizeof plaintext);
  1375. fputs(buf, aesresp);
  1376. fputc('\n', aesresp);
  1377. /* Key[i+1] = Key[i] xor ... */
  1378. aes_mct_next_key(key, keysize, plaintext_1, plaintext);
  1379. /* CT[0] = PT[j] */
  1380. /* done at the end of the for(j) loop */
  1381. fputc('\n', aesresp);
  1382. }
  1383. continue;
  1384. }
  1385. }
  1386. loser:
  1387. if (cx != NULL) {
  1388. AES_DestroyContext(cx, PR_TRUE);
  1389. }
  1390. if (cx2 != NULL) {
  1391. AES_DestroyContext(cx2, PR_TRUE);
  1392. }
  1393. fclose(aesreq);
  1394. }
  1395. /*
  1396. * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
  1397. * our AES code in streaming mode because the plaintext or ciphertext
  1398. * is generated block by block as we go, so we can't collect all the
  1399. * plaintext or ciphertext in one buffer and encrypt or decrypt it in
  1400. * one shot.
  1401. *
  1402. * reqfn is the pathname of the input REQUEST file.
  1403. *
  1404. * The output RESPONSE file is written to stdout.
  1405. */
  1406. void
  1407. aes_cbc_mct(char *reqfn)
  1408. {
  1409. char buf[80]; /* holds one line from the input REQUEST file.
  1410. * needs to be large enough to hold the longest
  1411. * line "KEY = <64 hex digits>\n".
  1412. */
  1413. FILE *aesreq; /* input stream from the REQUEST file */
  1414. FILE *aesresp; /* output stream to the RESPONSE file */
  1415. int i, j;
  1416. int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
  1417. unsigned char key[32]; /* 128, 192, or 256 bits */
  1418. unsigned int keysize;
  1419. unsigned char iv[16];
  1420. unsigned char plaintext[16]; /* PT[j] */
  1421. unsigned char plaintext_1[16]; /* PT[j-1] */
  1422. unsigned char ciphertext[16]; /* CT[j] */
  1423. unsigned char ciphertext_1[16]; /* CT[j-1] */
  1424. unsigned char doublecheck[16];
  1425. unsigned int outputlen;
  1426. AESContext *cx = NULL; /* the operation being tested */
  1427. AESContext *cx2 = NULL; /* the inverse operation done in parallel
  1428. * to doublecheck our result.
  1429. */
  1430. SECStatus rv;
  1431. aesreq = fopen(reqfn, "r");
  1432. aesresp = stdout;
  1433. while (fgets(buf, sizeof buf, aesreq) != NULL) {
  1434. /* a comment or blank line */
  1435. if (buf[0] == '#' || buf[0] == '\n') {
  1436. fputs(buf, aesresp);
  1437. continue;
  1438. }
  1439. /* [ENCRYPT] or [DECRYPT] */
  1440. if (buf[0] == '[') {
  1441. if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  1442. encrypt = 1;
  1443. } else {
  1444. encrypt = 0;
  1445. }
  1446. fputs(buf, aesresp);
  1447. continue;
  1448. }
  1449. /* "COUNT = x" begins a new data set */
  1450. if (strncmp(buf, "COUNT", 5) == 0) {
  1451. /* zeroize the variables for the test with this data set */
  1452. memset(key, 0, sizeof key);
  1453. keysize = 0;
  1454. memset(iv, 0, sizeof iv);
  1455. memset(plaintext, 0, sizeof plaintext);
  1456. memset(ciphertext, 0, sizeof ciphertext);
  1457. continue;
  1458. }
  1459. /* KEY = ... */
  1460. if (strncmp(buf, "KEY", 3) == 0) {
  1461. /* Key[0] = Key */
  1462. i = 3;
  1463. while (isspace(buf[i]) || buf[i] == '=') {
  1464. i++;
  1465. }
  1466. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1467. hex_to_byteval(&buf[i], &key[j]);
  1468. }
  1469. keysize = j;
  1470. continue;
  1471. }
  1472. /* IV = ... */
  1473. if (strncmp(buf, "IV", 2) == 0) {
  1474. /* IV[0] = IV */
  1475. i = 2;
  1476. while (isspace(buf[i]) || buf[i] == '=') {
  1477. i++;
  1478. }
  1479. for (j=0; j<sizeof iv; i+=2,j++) {
  1480. hex_to_byteval(&buf[i], &iv[j]);
  1481. }
  1482. continue;
  1483. }
  1484. /* PLAINTEXT = ... */
  1485. if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  1486. /* sanity check */
  1487. if (!encrypt) {
  1488. goto loser;
  1489. }
  1490. /* PT[0] = PT */
  1491. i = 9;
  1492. while (isspace(buf[i]) || buf[i] == '=') {
  1493. i++;
  1494. }
  1495. for (j=0; j<sizeof plaintext; i+=2,j++) {
  1496. hex_to_byteval(&buf[i], &plaintext[j]);
  1497. }
  1498. for (i=0; i<100; i++) {
  1499. sprintf(buf, "COUNT = %d\n", i);
  1500. fputs(buf, aesresp);
  1501. /* Output Key[i] */
  1502. fputs("KEY = ", aesresp);
  1503. to_hex_str(buf, key, keysize);
  1504. fputs(buf, aesresp);
  1505. fputc('\n', aesresp);
  1506. /* Output IV[i] */
  1507. fputs("IV = ", aesresp);
  1508. to_hex_str(buf, iv, sizeof iv);
  1509. fputs(buf, aesresp);
  1510. fputc('\n', aesresp);
  1511. /* Output PT[0] */
  1512. fputs("PLAINTEXT = ", aesresp);
  1513. to_hex_str(buf, plaintext, sizeof plaintext);
  1514. fputs(buf, aesresp);
  1515. fputc('\n', aesresp);
  1516. cx = AES_CreateContext(key, iv, NSS_AES_CBC,
  1517. PR_TRUE, keysize, 16);
  1518. if (cx == NULL) {
  1519. goto loser;
  1520. }
  1521. /*
  1522. * doublecheck our result by decrypting the result
  1523. * and comparing the output with the plaintext.
  1524. */
  1525. cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
  1526. PR_FALSE, keysize, 16);
  1527. if (cx2 == NULL) {
  1528. goto loser;
  1529. }
  1530. /* CT[-1] = IV[i] */
  1531. memcpy(ciphertext, iv, sizeof ciphertext);
  1532. for (j=0; j<1000; j++) {
  1533. /* Save CT[j-1] */
  1534. memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
  1535. /*
  1536. * If ( j=0 )
  1537. * CT[j] = AES(Key[i], IV[i], PT[j])
  1538. * PT[j+1] = IV[i] (= CT[j-1])
  1539. * Else
  1540. * CT[j] = AES(Key[i], PT[j])
  1541. * PT[j+1] = CT[j-1]
  1542. */
  1543. outputlen = 0;
  1544. rv = AES_Encrypt(cx,
  1545. ciphertext, &outputlen, sizeof ciphertext,
  1546. plaintext, sizeof plaintext);
  1547. if (rv != SECSuccess) {
  1548. goto loser;
  1549. }
  1550. if (outputlen != sizeof plaintext) {
  1551. goto loser;
  1552. }
  1553. /* doublecheck our result */
  1554. outputlen = 0;
  1555. rv = AES_Decrypt(cx2,
  1556. doublecheck, &outputlen, sizeof doublecheck,
  1557. ciphertext, sizeof ciphertext);
  1558. if (rv != SECSuccess) {
  1559. goto loser;
  1560. }
  1561. if (outputlen != sizeof ciphertext) {
  1562. goto loser;
  1563. }
  1564. if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
  1565. goto loser;
  1566. }
  1567. memcpy(plaintext, ciphertext_1, sizeof plaintext);
  1568. }
  1569. AES_DestroyContext(cx, PR_TRUE);
  1570. cx = NULL;
  1571. AES_DestroyContext(cx2, PR_TRUE);
  1572. cx2 = NULL;
  1573. /* Output CT[j] */
  1574. fputs("CIPHERTEXT = ", aesresp);
  1575. to_hex_str(buf, ciphertext, sizeof ciphertext);
  1576. fputs(buf, aesresp);
  1577. fputc('\n', aesresp);
  1578. /* Key[i+1] = Key[i] xor ... */
  1579. aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
  1580. /* IV[i+1] = CT[j] */
  1581. memcpy(iv, ciphertext, sizeof iv);
  1582. /* PT[0] = CT[j-1] */
  1583. /* done at the end of the for(j) loop */
  1584. fputc('\n', aesresp);
  1585. }
  1586. continue;
  1587. }
  1588. /* CIPHERTEXT = ... */
  1589. if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  1590. /* sanity check */
  1591. if (encrypt) {
  1592. goto loser;
  1593. }
  1594. /* CT[0] = CT */
  1595. i = 10;
  1596. while (isspace(buf[i]) || buf[i] == '=') {
  1597. i++;
  1598. }
  1599. for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1600. hex_to_byteval(&buf[i], &ciphertext[j]);
  1601. }
  1602. for (i=0; i<100; i++) {
  1603. sprintf(buf, "COUNT = %d\n", i);
  1604. fputs(buf, aesresp);
  1605. /* Output Key[i] */
  1606. fputs("KEY = ", aesresp);
  1607. to_hex_str(buf, key, keysize);
  1608. fputs(buf, aesresp);
  1609. fputc('\n', aesresp);
  1610. /* Output IV[i] */
  1611. fputs("IV = ", aesresp);
  1612. to_hex_str(buf, iv, sizeof iv);
  1613. fputs(buf, aesresp);
  1614. fputc('\n', aesresp);
  1615. /* Output CT[0] */
  1616. fputs("CIPHERTEXT = ", aesresp);
  1617. to_hex_str(buf, ciphertext, sizeof ciphertext);
  1618. fputs(buf, aesresp);
  1619. fputc('\n', aesresp);
  1620. cx = AES_CreateContext(key, iv, NSS_AES_CBC,
  1621. PR_FALSE, keysize, 16);
  1622. if (cx == NULL) {
  1623. goto loser;
  1624. }
  1625. /*
  1626. * doublecheck our result by encrypting the result
  1627. * and comparing the output with the ciphertext.
  1628. */
  1629. cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
  1630. PR_TRUE, keysize, 16);
  1631. if (cx2 == NULL) {
  1632. goto loser;
  1633. }
  1634. /* PT[-1] = IV[i] */
  1635. memcpy(plaintext, iv, sizeof plaintext);
  1636. for (j=0; j<1000; j++) {
  1637. /* Save PT[j-1] */
  1638. memcpy(plaintext_1, plaintext, sizeof plaintext);
  1639. /*
  1640. * If ( j=0 )
  1641. * PT[j] = AES(Key[i], IV[i], CT[j])
  1642. * CT[j+1] = IV[i] (= PT[j-1])
  1643. * Else
  1644. * PT[j] = AES(Key[i], CT[j])
  1645. * CT[j+1] = PT[j-1]
  1646. */
  1647. outputlen = 0;
  1648. rv = AES_Decrypt(cx,
  1649. plaintext, &outputlen, sizeof plaintext,
  1650. ciphertext, sizeof ciphertext);
  1651. if (rv != SECSuccess) {
  1652. goto loser;
  1653. }
  1654. if (outputlen != sizeof ciphertext) {
  1655. goto loser;
  1656. }
  1657. /* doublecheck our result */
  1658. outputlen = 0;
  1659. rv = AES_Encrypt(cx2,
  1660. doublecheck, &outputlen, sizeof doublecheck,
  1661. plaintext, sizeof plaintext);
  1662. if (rv != SECSuccess) {
  1663. goto loser;
  1664. }
  1665. if (outputlen != sizeof plaintext) {
  1666. goto loser;
  1667. }
  1668. if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
  1669. goto loser;
  1670. }
  1671. memcpy(ciphertext, plaintext_1, sizeof ciphertext);
  1672. }
  1673. AES_DestroyContext(cx, PR_TRUE);
  1674. cx = NULL;
  1675. AES_DestroyContext(cx2, PR_TRUE);
  1676. cx2 = NULL;
  1677. /* Output PT[j] */
  1678. fputs("…

Large files files are truncated, but you can click here to view the full file