/security/nss/cmd/rsapoptst/rsapoptst.c

http://github.com/zpao/v8monkey · C · 550 lines · 449 code · 52 blank · 49 comment · 88 complexity · 33152c45f35a53577453f776a7ac9e53 MD5 · raw 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. * Portions created by the Red Hat, Inc. are Copyright (C) 2010
  21. * the Red Hat, Inc.. All Rights Reserved.
  22. *
  23. * Contributor(s):
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include "plgetopt.h"
  41. #include "nss.h"
  42. #include "secutil.h"
  43. #include "pk11table.h"
  44. #include "secmodt.h"
  45. #include "pk11pub.h"
  46. struct test_args {
  47. char *arg;
  48. int mask_value;
  49. char *description;
  50. };
  51. static const struct test_args test_array[] = {
  52. {"all", 0x1f, "run all the tests" },
  53. {"e_n_p", 0x01, "public exponent, modulus, prime1"},
  54. {"d_n_q", 0x02, "private exponent, modulus, prime2"},
  55. {"d_p_q", 0x04, "private exponent, prime1, prime2"},
  56. {"e_d_q", 0x08, "public exponent, private exponent, prime2"},
  57. {"e_d_n", 0x10, "public exponent, private exponent, moduls"}
  58. };
  59. static const int test_array_size =
  60. (sizeof(test_array)/sizeof(struct test_args));
  61. static void Usage(char *progName)
  62. {
  63. int i;
  64. #define PRINTUSAGE(subject, option, predicate) \
  65. fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
  66. fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n "
  67. "Test creating RSA private keys from Partial components\n",
  68. progName);
  69. PRINTUSAGE("", "-k", "key size (in bit)");
  70. PRINTUSAGE("", "-e", "rsa public exponent");
  71. PRINTUSAGE("", "-r", "number times to repeat the test");
  72. PRINTUSAGE("", "-t", "run the specified tests");
  73. for (i=0; i < test_array_size; i++) {
  74. PRINTUSAGE("", test_array[i].arg, test_array[i].description);
  75. }
  76. fprintf(stderr,"\n");
  77. }
  78. /*
  79. * Test the RSA populate command to see that it can really build
  80. * keys from it's components.
  81. */
  82. const static CK_ATTRIBUTE rsaTemplate[] = {
  83. {CKA_CLASS, NULL, 0 },
  84. {CKA_KEY_TYPE, NULL, 0 },
  85. {CKA_TOKEN, NULL, 0 },
  86. {CKA_SENSITIVE, NULL, 0 },
  87. {CKA_PRIVATE, NULL, 0 },
  88. {CKA_MODULUS, NULL, 0 },
  89. {CKA_PUBLIC_EXPONENT, NULL, 0 },
  90. {CKA_PRIVATE_EXPONENT, NULL, 0 },
  91. {CKA_PRIME_1, NULL, 0 },
  92. {CKA_PRIME_2, NULL, 0 },
  93. {CKA_EXPONENT_1, NULL, 0 },
  94. {CKA_EXPONENT_2, NULL, 0 },
  95. {CKA_COEFFICIENT, NULL, 0 },
  96. };
  97. #define RSA_SIZE (sizeof(rsaTemplate))
  98. #define RSA_ATTRIBUTES (sizeof(rsaTemplate)/sizeof(CK_ATTRIBUTE))
  99. static void
  100. resetTemplate(CK_ATTRIBUTE *attribute, int start, int end)
  101. {
  102. int i;
  103. for (i=start; i < end; i++) {
  104. if (attribute[i].pValue) {
  105. PORT_Free(attribute[i].pValue);
  106. }
  107. attribute[i].pValue = NULL;
  108. attribute[i].ulValueLen = 0;
  109. }
  110. }
  111. static SECStatus
  112. copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
  113. int offset, CK_ATTRIBUTE_TYPE attrType)
  114. {
  115. SECItem attributeItem = {0, 0, 0};
  116. SECStatus rv;
  117. rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem);
  118. if (rv != SECSuccess) {
  119. return rv;
  120. }
  121. template[offset].type = attrType;
  122. template[offset].pValue = attributeItem.data;
  123. template[offset].ulValueLen = attributeItem.len;
  124. return SECSuccess;
  125. }
  126. static SECStatus
  127. readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
  128. int start, int end)
  129. {
  130. int i;
  131. SECStatus rv;
  132. for (i=start; i < end; i++) {
  133. rv = copyAttribute(objType, object, template, i, template[i].type);
  134. if (rv != SECSuccess) {
  135. goto fail;
  136. }
  137. }
  138. return SECSuccess;
  139. fail:
  140. resetTemplate(template, start, i);
  141. return rv;
  142. }
  143. #define ATTR_STRING(x) getNameFromAttribute(x)
  144. void
  145. dumpTemplate(CK_ATTRIBUTE *template, int start, int end)
  146. {
  147. int i,j;
  148. for (i=0; i < end; i++) {
  149. unsigned char cval;
  150. CK_ULONG ulval;
  151. unsigned char *cpval;
  152. fprintf(stderr, "%s:", ATTR_STRING(template[i].type));
  153. switch (template[i].ulValueLen) {
  154. case 1:
  155. cval =*(unsigned char *)template[i].pValue;
  156. switch(cval) {
  157. case 0: fprintf(stderr, " false"); break;
  158. case 1: fprintf(stderr, " true"); break;
  159. default:
  160. fprintf(stderr, " %d (=0x%02x,'%c')",cval,cval,cval);
  161. break;
  162. }
  163. break;
  164. case sizeof(CK_ULONG):
  165. ulval = *(CK_ULONG *)template[i].pValue;
  166. fprintf(stderr," %ld (=0x%04lx)", ulval, ulval);
  167. break;
  168. default:
  169. cpval = (unsigned char *)template[i].pValue;
  170. for (j=0; j < template[i].ulValueLen; j++) {
  171. if ((j % 16) == 0) fprintf(stderr, "\n ");
  172. fprintf(stderr," %02x",cpval[j]);
  173. }
  174. break;
  175. }
  176. fprintf(stderr,"\n");
  177. }
  178. }
  179. PRBool
  180. rsaKeysAreEqual(PK11ObjectType srcType, void *src,
  181. PK11ObjectType destType, void *dest)
  182. {
  183. CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES];
  184. CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES];
  185. PRBool areEqual = PR_TRUE;
  186. SECStatus rv;
  187. int i;
  188. memcpy(srcTemplate, rsaTemplate, RSA_SIZE);
  189. memcpy(destTemplate, rsaTemplate, RSA_SIZE);
  190. rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES);
  191. if (rv != SECSuccess) {
  192. printf("Could read source key\n");
  193. return PR_FALSE;
  194. }
  195. readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
  196. if (rv != SECSuccess) {
  197. printf("Could read dest key\n");
  198. return PR_FALSE;
  199. }
  200. for (i=0; i < RSA_ATTRIBUTES; i++) {
  201. if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) {
  202. printf("key->%s not equal src_len = %ld, dest_len=%ld\n",
  203. ATTR_STRING(srcTemplate[i].type),
  204. srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen);
  205. areEqual = 0;
  206. } else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue,
  207. destTemplate[i].ulValueLen) != 0) {
  208. printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type));
  209. areEqual = 0;
  210. }
  211. }
  212. if (!areEqual) {
  213. fprintf(stderr, "original key:\n");
  214. dumpTemplate(srcTemplate,0, RSA_ATTRIBUTES);
  215. fprintf(stderr, "created key:\n");
  216. dumpTemplate(destTemplate,0, RSA_ATTRIBUTES);
  217. }
  218. return areEqual;
  219. }
  220. static int exp_exp_prime_fail_count = 0;
  221. static int
  222. doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
  223. int mask, void *pwarg)
  224. {
  225. SECKEYPrivateKey *rsaPrivKey;
  226. SECKEYPublicKey *rsaPubKey;
  227. PK11GenericObject *tstPrivKey;
  228. CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES];
  229. int tstHeaderCount;
  230. PK11SlotInfo *slot = NULL;
  231. PK11RSAGenParams rsaParams;
  232. CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
  233. CK_KEY_TYPE key_type = CKK_RSA;
  234. CK_BBOOL ck_false = CK_FALSE;
  235. int failed = 0;
  236. rsaParams.pe = exponent;
  237. rsaParams.keySizeInBits = keySize;
  238. slot = PK11_GetInternalSlot();
  239. if (slot == NULL) {
  240. fprintf(stderr, "Couldn't get the internal slot for the test \n");
  241. return -1;
  242. }
  243. rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
  244. &rsaParams, &rsaPubKey, PR_FALSE,
  245. PR_FALSE, pwarg);
  246. if (rsaPrivKey == NULL) {
  247. fprintf(stderr, "RSA Key Gen failed");
  248. PK11_FreeSlot(slot);
  249. return -1;
  250. }
  251. memcpy(tstTemplate, rsaTemplate, RSA_SIZE);
  252. tstTemplate[0].pValue = &obj_class;
  253. tstTemplate[0].ulValueLen = sizeof(obj_class);
  254. tstTemplate[1].pValue = &key_type;
  255. tstTemplate[1].ulValueLen = sizeof(key_type);
  256. tstTemplate[2].pValue = &ck_false;
  257. tstTemplate[2].ulValueLen = sizeof(ck_false);
  258. tstTemplate[3].pValue = &ck_false;
  259. tstTemplate[3].ulValueLen = sizeof(ck_false);
  260. tstTemplate[4].pValue = &ck_false;
  261. tstTemplate[4].ulValueLen = sizeof(ck_false);
  262. tstHeaderCount = 5;
  263. if (mask & 1) {
  264. printf("%s\n",test_array[1].description);
  265. resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
  266. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  267. tstHeaderCount, CKA_PUBLIC_EXPONENT);
  268. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  269. tstHeaderCount+1, CKA_MODULUS);
  270. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  271. tstHeaderCount+2, CKA_PRIME_1);
  272. tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
  273. tstHeaderCount+3, PR_FALSE);
  274. if (tstPrivKey == NULL) {
  275. fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
  276. failed = 1;
  277. } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
  278. PK11_TypeGeneric, tstPrivKey)) {
  279. fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
  280. failed = 1;
  281. }
  282. if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
  283. }
  284. if (mask & 2) {
  285. printf("%s\n",test_array[2].description);
  286. /* test the basic2 case, public exponent, modulus, prime2 */
  287. resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
  288. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  289. tstHeaderCount, CKA_PUBLIC_EXPONENT);
  290. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  291. tstHeaderCount+1, CKA_MODULUS);
  292. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  293. tstHeaderCount+2, CKA_PRIME_2);
  294. /* test with q in the prime1 position */
  295. tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
  296. tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
  297. tstHeaderCount+3, PR_FALSE);
  298. if (tstPrivKey == NULL) {
  299. fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
  300. failed = 1;
  301. } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
  302. PK11_TypeGeneric, tstPrivKey)) {
  303. fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
  304. failed = 1;
  305. }
  306. if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
  307. }
  308. if (mask & 4) {
  309. printf("%s\n",test_array[3].description);
  310. /* test the medium case, private exponent, prime1, prime2 */
  311. resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
  312. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  313. tstHeaderCount, CKA_PRIVATE_EXPONENT);
  314. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  315. tstHeaderCount+1, CKA_PRIME_1);
  316. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  317. tstHeaderCount+2, CKA_PRIME_2);
  318. /* test with p & q swapped. Underlying code should swap these back */
  319. tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
  320. tstTemplate[tstHeaderCount+1].type = CKA_PRIME_2;
  321. tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
  322. tstHeaderCount+3, PR_FALSE);
  323. if (tstPrivKey == NULL) {
  324. fprintf(stderr, "RSA Populate failed: privExp p q\n");
  325. failed = 1;
  326. } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
  327. PK11_TypeGeneric, tstPrivKey)) {
  328. fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
  329. failed = 1;
  330. }
  331. if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
  332. }
  333. if (mask & 8) {
  334. printf("%s\n",test_array[4].description);
  335. /* test the advanced case, public exponent, private exponent, prime2 */
  336. resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
  337. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  338. tstHeaderCount, CKA_PRIVATE_EXPONENT);
  339. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  340. tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
  341. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  342. tstHeaderCount+2, CKA_PRIME_2);
  343. tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
  344. tstHeaderCount+3, PR_FALSE);
  345. if (tstPrivKey == NULL) {
  346. fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
  347. fprintf(stderr, " this is expected periodically. It means we\n");
  348. fprintf(stderr, " had more than one key that meets the "
  349. "specification\n");
  350. exp_exp_prime_fail_count++;
  351. } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
  352. PK11_TypeGeneric, tstPrivKey)) {
  353. fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
  354. failed = 1;
  355. }
  356. if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
  357. }
  358. if (mask & 16) {
  359. printf("%s\n",test_array[5].description);
  360. /* test the advanced case2, public exponent, private exponent, modulus
  361. */
  362. resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
  363. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  364. tstHeaderCount, CKA_PRIVATE_EXPONENT);
  365. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  366. tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
  367. copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
  368. tstHeaderCount+2, CKA_MODULUS);
  369. tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
  370. tstHeaderCount+3, PR_FALSE);
  371. if (tstPrivKey == NULL) {
  372. fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
  373. failed = 1;
  374. } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
  375. PK11_TypeGeneric, tstPrivKey)) {
  376. fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
  377. failed = 1;
  378. }
  379. if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
  380. }
  381. PK11_FreeSlot(slot);
  382. return failed ? -1 : 0;
  383. }
  384. /* populate options */
  385. enum {
  386. opt_Exponent = 0,
  387. opt_KeySize,
  388. opt_Repeat,
  389. opt_Tests
  390. };
  391. static secuCommandFlag populate_options[] =
  392. {
  393. { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
  394. { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE },
  395. { /* opt_Repeat */ 'r', PR_TRUE, 0, PR_FALSE },
  396. { /* opt_Tests */ 't', PR_TRUE, 0, PR_FALSE },
  397. };
  398. int
  399. is_delimiter(char c)
  400. {
  401. if ((c=='+') || (c==',') || (c=='|')) {
  402. return 1;
  403. }
  404. return 0;
  405. }
  406. int
  407. parse_tests(char *test_string)
  408. {
  409. int mask = 0;
  410. int i;
  411. while (*test_string) {
  412. if (is_delimiter(*test_string)) {
  413. test_string++;
  414. }
  415. for (i=0; i < test_array_size; i++) {
  416. char *arg = test_array[i].arg;
  417. int len = strlen(arg);
  418. if (strncmp(test_string,arg,len) == 0) {
  419. test_string += len;
  420. mask |= test_array[i].mask_value;
  421. break;
  422. }
  423. }
  424. if (i == test_array_size) {
  425. break;
  426. }
  427. }
  428. return mask;
  429. }
  430. int main(int argc, char **argv)
  431. {
  432. unsigned int keySize = 1024;
  433. unsigned long exponent = 65537;
  434. int i, repeat = 1, ret = 0;
  435. SECStatus rv = SECFailure;
  436. secuCommand populateArgs;
  437. char *progName;
  438. int mask = 0xff;
  439. populateArgs.numCommands = 0;
  440. populateArgs.numOptions = sizeof(populate_options) /
  441. sizeof(secuCommandFlag);
  442. populateArgs.commands = NULL;
  443. populateArgs.options = populate_options;
  444. progName = strrchr(argv[0], '/');
  445. if (!progName)
  446. progName = strrchr(argv[0], '\\');
  447. progName = progName ? progName+1 : argv[0];
  448. rv = NSS_NoDB_Init(NULL);
  449. if (rv != SECSuccess) {
  450. SECU_PrintPRandOSError(progName);
  451. return -1;
  452. }
  453. rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs);
  454. if (rv == SECFailure) {
  455. fprintf(stderr, "%s: command line parsing error!\n", progName);
  456. Usage(progName);
  457. return -1;
  458. }
  459. rv = SECFailure;
  460. if (populateArgs.options[opt_KeySize].activated) {
  461. keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg);
  462. }
  463. if (populateArgs.options[opt_Repeat].activated) {
  464. repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg);
  465. }
  466. if (populateArgs.options[opt_Exponent].activated) {
  467. exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg);
  468. }
  469. if (populateArgs.options[opt_Tests].activated) {
  470. char * test_string = populateArgs.options[opt_Tests].arg;
  471. mask = PORT_Atoi(test_string);
  472. if (mask == 0) {
  473. mask = parse_tests(test_string);
  474. }
  475. if (mask == 0) {
  476. Usage(progName);
  477. return -1;
  478. }
  479. }
  480. exp_exp_prime_fail_count = 0;
  481. for (i=0; i < repeat; i++) {
  482. printf("Running RSA Populate test run %d\n",i);
  483. ret = doRSAPopulateTest(keySize, exponent, mask, NULL);
  484. if (ret != 0) {
  485. i++;
  486. break;
  487. }
  488. }
  489. if (ret != 0) {
  490. fprintf(stderr,"RSA Populate test round %d: FAILED\n",i);
  491. }
  492. if (repeat > 1) {
  493. printf(" pub priv prime test: %d failures out of %d runs (%f %%)\n",
  494. exp_exp_prime_fail_count, i,
  495. (((double)exp_exp_prime_fail_count) * 100.0)/(double) i);
  496. }
  497. return ret;
  498. }