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

/security/nss/cmd/crmftest/testcrmf.c

http://github.com/zpao/v8monkey
C | 1710 lines | 1405 code | 144 blank | 161 comment | 291 complexity | 99f64fee1db535c070d4ca45a3c17bd9 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  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. /*
  37. * This program does 5 separate functions. By default, it does them all.
  38. * It can be told to do any subset of them.
  39. * It does them in this order:
  40. *
  41. * 1. Generate file of CRMF cert requests.
  42. * Generates 2 keys pairs, one for signing, one for encryption.
  43. * Can generate RSA or DSA (XXX - DSA is only useful for signing).
  44. * Generate a cert request for each of the two public keys.
  45. * Generate a single CRMF cert request message that requests both certs.
  46. * Leave the generated CRMF request message in file
  47. * configdir/CertReqMessages.der
  48. *
  49. * 2. Decode CRMF Request(s) Message.
  50. * Reads in the file configdir/CertReqMessages.der
  51. * (either generated by step 1 above, or user supplied).
  52. * Decodes it. NOTHING MORE. Drops these decoded results on the floor.
  53. * The CMMF response (below) contains a completely unrelated cert. :-(
  54. *
  55. * 3. CMMF "Stuff".
  56. * a) Generates a CMMF response, containing a single cert chain, as if
  57. * it was a response to a received CRMF request. But the cert is
  58. * simply a user cert from the user's local soft token, whose
  59. * nickname is given in the -p option. The CMMF response has no
  60. * relationship to the request generated above. The CMMF message
  61. * is placed in configdir/CertRepContent.der.
  62. * b) Decodes the newly generated CMMF response found in file
  63. * configdir/CertRepContent.der and discards the result. 8-/
  64. * c) Generate a CMMF Key Escrow message
  65. * needs 2 nicknames:
  66. * It takes the public and private keys for the cert identified
  67. * by -p nickname, and wraps them with a sym key that is in turn
  68. * wrapped with the pubkey in the CA cert, whose nickname is
  69. * given with the -s option.
  70. * Store the message in configdir/KeyRecRepContent.der
  71. * d) Decode the CMMF Key Escrow message generated just above.
  72. * Get it from file configdir/KeyRecRepContent.der
  73. * This is just a decoder test. Results are discarded.
  74. *
  75. * 4. Key Recovery
  76. * This code does not yet compile, and what it was intended to do
  77. * has not been fully determined.
  78. *
  79. * 5. Challenge/Response.
  80. * Haven't analyzed this code yet.
  81. *
  82. *
  83. */
  84. /* KNOWN BUGS:
  85. ** 1. generates BOTH signing and encryption cert requests, even for DSA keys.
  86. **
  87. ** 2. Does not verify the siganture in the "Proof of Posession" in the
  88. ** decoded cert requests. It only checks syntax of the POP.
  89. ** 3. CMMF "Stuff" should be broken up into separate steps, each of
  90. ** which may be optionally selected.
  91. */
  92. #include <stdio.h>
  93. #include "nspr.h"
  94. #include "nss.h"
  95. #include "crmf.h"
  96. #include "secerr.h"
  97. #include "pk11func.h"
  98. #include "key.h"
  99. #include "cmmf.h"
  100. #include "plgetopt.h"
  101. #include "secutil.h"
  102. #include "pk11pqg.h"
  103. #if 0
  104. #include "pkcs11.h"
  105. #include "secmod.h"
  106. #include "secmodi.h"
  107. #include "pqggen.h"
  108. #include "secmod.h"
  109. #include "secmodi.h"
  110. #include "pkcs11.h"
  111. #include "secitem.h"
  112. #include "secasn1.h"
  113. #include "sechash.h"
  114. #endif
  115. #define MAX_KEY_LEN 512
  116. #define PATH_LEN 150
  117. #define BUFF_SIZE 150
  118. #define UID_BITS 800
  119. #define BPB 8
  120. #define CRMF_FILE "CertReqMessages.der"
  121. PRTime notBefore;
  122. char *personalCert = NULL;
  123. char *recoveryEncrypter = NULL;
  124. char *caCertName = NULL;
  125. static secuPWData pwdata = { PW_NONE, 0 };
  126. char *configdir;
  127. PRBool doingDSA = PR_FALSE;
  128. CERTCertDBHandle *db;
  129. typedef struct {
  130. SECKEYPrivateKey *privKey;
  131. SECKEYPublicKey *pubKey;
  132. CRMFCertRequest *certReq;
  133. CRMFCertReqMsg *certReqMsg;
  134. } TESTKeyPair;
  135. void
  136. debug_test(SECItem *src, char *filePath)
  137. {
  138. PRFileDesc *fileDesc;
  139. fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  140. 0666);
  141. if (fileDesc == NULL) {
  142. printf ("Could not cretae file %s.\n", filePath);
  143. return;
  144. }
  145. PR_Write(fileDesc, src->data, src->len);
  146. }
  147. SECStatus
  148. get_serial_number(long *dest)
  149. {
  150. SECStatus rv;
  151. if (dest == NULL) {
  152. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  153. return SECFailure;
  154. }
  155. rv = PK11_GenerateRandom((unsigned char *)dest, sizeof(long));
  156. /* make serial number positive */
  157. if (*dest < 0L)
  158. *dest = - *dest;
  159. return SECSuccess;
  160. }
  161. PK11RSAGenParams *
  162. GetRSAParams(void)
  163. {
  164. PK11RSAGenParams *rsaParams;
  165. rsaParams = PORT_ZNew(PK11RSAGenParams);
  166. if (rsaParams == NULL)
  167. return NULL;
  168. rsaParams->keySizeInBits = MAX_KEY_LEN;
  169. rsaParams->pe = 0x10001;
  170. return rsaParams;
  171. }
  172. PQGParams*
  173. GetDSAParams(void)
  174. {
  175. PQGParams *params = NULL;
  176. PQGVerify *vfy = NULL;
  177. SECStatus rv;
  178. rv = PK11_PQG_ParamGen(0, &params, &vfy);
  179. if (rv != SECSuccess) {
  180. return NULL;
  181. }
  182. PK11_PQG_DestroyVerify(vfy);
  183. return params;
  184. }
  185. /* Generate a key pair, and then generate a subjectPublicKeyInfo
  186. ** for the public key in that pair. return all 3.
  187. */
  188. CERTSubjectPublicKeyInfo *
  189. GetSubjectPubKeyInfo(TESTKeyPair *pair)
  190. {
  191. CERTSubjectPublicKeyInfo *spki = NULL;
  192. SECKEYPrivateKey *privKey = NULL;
  193. SECKEYPublicKey *pubKey = NULL;
  194. PK11SlotInfo *keySlot = NULL;
  195. keySlot = PK11_GetInternalKeySlot();
  196. PK11_Authenticate(keySlot, PR_FALSE, &pwdata);
  197. if (!doingDSA) {
  198. PK11RSAGenParams *rsaParams = GetRSAParams();
  199. if (rsaParams == NULL) {
  200. PK11_FreeSlot(keySlot);
  201. return NULL;
  202. }
  203. privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN,
  204. (void*)rsaParams, &pubKey, PR_FALSE,
  205. PR_FALSE, &pwdata);
  206. } else {
  207. PQGParams *dsaParams = GetDSAParams();
  208. if (dsaParams == NULL) {
  209. PK11_FreeSlot(keySlot);
  210. return NULL;
  211. }
  212. privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN,
  213. (void*)dsaParams, &pubKey, PR_FALSE,
  214. PR_FALSE, &pwdata);
  215. }
  216. PK11_FreeSlot(keySlot);
  217. if (privKey == NULL || pubKey == NULL) {
  218. if (pubKey) {
  219. SECKEY_DestroyPublicKey(pubKey);
  220. }
  221. if (privKey) {
  222. SECKEY_DestroyPrivateKey(privKey);
  223. }
  224. return NULL;
  225. }
  226. spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
  227. pair->privKey = privKey;
  228. pair->pubKey = pubKey;
  229. return spki;
  230. }
  231. SECStatus
  232. InitPKCS11(void)
  233. {
  234. PK11SlotInfo *keySlot;
  235. PK11_SetPasswordFunc(SECU_GetModulePassword);
  236. keySlot = PK11_GetInternalKeySlot();
  237. if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) {
  238. if (SECU_ChangePW(keySlot, NULL, NULL) != SECSuccess) {
  239. printf ("Initializing the PINs failed.\n");
  240. return SECFailure;
  241. }
  242. }
  243. PK11_FreeSlot(keySlot);
  244. return SECSuccess;
  245. }
  246. void
  247. WriteItOut (void *arg, const char *buf, unsigned long len)
  248. {
  249. PRFileDesc *fileDesc = (PRFileDesc*)arg;
  250. PR_Write(fileDesc, (void*)buf, len);
  251. }
  252. CRMFCertExtCreationInfo*
  253. GetExtensions(void)
  254. {
  255. unsigned char keyUsage[4] = { 0x03, 0x02, 0x07, KU_DIGITAL_SIGNATURE };
  256. /* What are these magic numbers? */
  257. SECItem data = { 0, NULL, 0 };
  258. CRMFCertExtension *extension;
  259. CRMFCertExtCreationInfo *extInfo =
  260. PORT_ZNew(CRMFCertExtCreationInfo);
  261. data.data = keyUsage;
  262. data.len = sizeof keyUsage;
  263. extension =
  264. CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_FALSE, &data);
  265. if (extension && extInfo) {
  266. extInfo->numExtensions = 1;
  267. extInfo->extensions = PORT_ZNewArray(CRMFCertExtension*, 1);
  268. extInfo->extensions[0] = extension;
  269. }
  270. return extInfo;
  271. }
  272. void
  273. FreeExtInfo(CRMFCertExtCreationInfo *extInfo)
  274. {
  275. int i;
  276. for (i=0; i<extInfo->numExtensions; i++) {
  277. CRMF_DestroyCertExtension(extInfo->extensions[i]);
  278. }
  279. PORT_Free(extInfo->extensions);
  280. PORT_Free(extInfo);
  281. }
  282. int
  283. InjectCertName( CRMFCertRequest * certReq,
  284. CRMFCertTemplateField inTemplateField,
  285. const char * inNameString)
  286. {
  287. char * nameStr;
  288. CERTName * name;
  289. int irv = 0;
  290. nameStr = PORT_Strdup(inNameString);
  291. if (!nameStr)
  292. return 5;
  293. name = CERT_AsciiToName(nameStr);
  294. if (name == NULL) {
  295. printf ("Could not create CERTName structure from %s.\n", nameStr);
  296. irv = 5;
  297. goto finish;
  298. }
  299. irv = CRMF_CertRequestSetTemplateField(certReq, inTemplateField, (void*)name);
  300. if (irv != SECSuccess) {
  301. printf ("Could not add name to cert template\n");
  302. irv = 6;
  303. }
  304. finish:
  305. PORT_Free(nameStr);
  306. if (name)
  307. CERT_DestroyName(name);
  308. return irv;
  309. }
  310. int
  311. CreateCertRequest(TESTKeyPair *pair, long inRequestID)
  312. {
  313. CERTCertificate * caCert;
  314. CERTSubjectPublicKeyInfo *spki;
  315. CRMFCertExtCreationInfo * extInfo;
  316. CRMFCertRequest * certReq;
  317. CRMFEncryptedKey * encKey;
  318. CRMFPKIArchiveOptions * pkiArchOpt;
  319. SECAlgorithmID * algID;
  320. long serialNumber;
  321. long version = 3;
  322. SECStatus rv;
  323. CRMFValidityCreationInfo validity;
  324. unsigned char UIDbuf[UID_BITS / BPB];
  325. SECItem issuerUID = { siBuffer, NULL, 0 };
  326. SECItem subjectUID = { siBuffer, NULL, 0 };
  327. /* len in bits */
  328. issuerUID.data = UIDbuf;
  329. issuerUID.len = UID_BITS;
  330. subjectUID.data = UIDbuf;
  331. subjectUID.len = UID_BITS;
  332. pair->certReq = NULL;
  333. certReq = CRMF_CreateCertRequest(inRequestID);
  334. if (certReq == NULL) {
  335. printf ("Could not initialize a certificate request.\n");
  336. return 1;
  337. }
  338. /* set to version 3 */
  339. rv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion,
  340. (void*)(&version));
  341. if (rv != SECSuccess) {
  342. printf("Could not add the version number to the "
  343. "Certificate Request.\n");
  344. CRMF_DestroyCertRequest(certReq);
  345. return 2;
  346. }
  347. /* set serial number */
  348. if (get_serial_number(&serialNumber) != SECSuccess) {
  349. printf ("Could not generate a serial number for cert request.\n");
  350. CRMF_DestroyCertRequest(certReq);
  351. return 3;
  352. }
  353. rv = CRMF_CertRequestSetTemplateField (certReq, crmfSerialNumber,
  354. (void*)(&serialNumber));
  355. if (rv != SECSuccess) {
  356. printf ("Could not add serial number to certificate template\n.");
  357. CRMF_DestroyCertRequest(certReq);
  358. return 4;
  359. }
  360. /* Set issuer name */
  361. rv = InjectCertName(certReq, crmfIssuer,
  362. "CN=mozilla CA Shack,O=Information Systems");
  363. if (rv) {
  364. printf ("Could not add issuer to cert template\n");
  365. CRMF_DestroyCertRequest(certReq);
  366. return 5;
  367. }
  368. /* Set Subject Name */
  369. rv = InjectCertName(certReq, crmfSubject,
  370. "CN=mozilla CA Shack ID,O=Engineering,C=US");
  371. if (rv) {
  372. printf ("Could not add Subject to cert template\n");
  373. CRMF_DestroyCertRequest(certReq);
  374. return 5;
  375. }
  376. /* Set Algorithm ID */
  377. algID = PK11_CreatePBEAlgorithmID(SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC,
  378. 1, NULL);
  379. if (algID == NULL) {
  380. printf ("Couldn't create algorithm ID\n");
  381. CRMF_DestroyCertRequest(certReq);
  382. return 9;
  383. }
  384. rv = CRMF_CertRequestSetTemplateField(certReq, crmfSigningAlg, (void*)algID);
  385. SECOID_DestroyAlgorithmID(algID, PR_TRUE);
  386. if (rv != SECSuccess) {
  387. printf ("Could not add the signing algorithm to the cert template.\n");
  388. CRMF_DestroyCertRequest(certReq);
  389. return 10;
  390. }
  391. /* Set Validity Dates */
  392. validity.notBefore = &notBefore;
  393. validity.notAfter = NULL;
  394. notBefore = PR_Now();
  395. rv = CRMF_CertRequestSetTemplateField(certReq, crmfValidity,(void*)(&validity));
  396. if (rv != SECSuccess) {
  397. printf ("Could not add validity to cert template\n");
  398. CRMF_DestroyCertRequest(certReq);
  399. return 11;
  400. }
  401. /* Generate a key pair and Add the spki to the request */
  402. spki = GetSubjectPubKeyInfo(pair);
  403. if (spki == NULL) {
  404. printf ("Could not create a Subject Public Key Info to add\n");
  405. CRMF_DestroyCertRequest(certReq);
  406. return 12;
  407. }
  408. rv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, (void*)spki);
  409. SECKEY_DestroySubjectPublicKeyInfo(spki);
  410. if (rv != SECSuccess) {
  411. printf ("Could not add the public key to the template\n");
  412. CRMF_DestroyCertRequest(certReq);
  413. return 13;
  414. }
  415. /* Set the requested isser Unique ID */
  416. PK11_GenerateRandom(UIDbuf, sizeof UIDbuf);
  417. CRMF_CertRequestSetTemplateField(certReq,crmfIssuerUID, (void*)&issuerUID);
  418. /* Set the requested Subject Unique ID */
  419. PK11_GenerateRandom(UIDbuf, sizeof UIDbuf);
  420. CRMF_CertRequestSetTemplateField(certReq,crmfSubjectUID, (void*)&subjectUID);
  421. /* Add extensions - XXX need to understand these magic numbers */
  422. extInfo = GetExtensions();
  423. CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void*)extInfo);
  424. FreeExtInfo(extInfo);
  425. /* get the recipient CA's cert */
  426. caCert = CERT_FindCertByNickname(db, caCertName);
  427. if (caCert == NULL) {
  428. printf ("Could not find the certificate for %s\n", caCertName);
  429. CRMF_DestroyCertRequest(certReq);
  430. return 50;
  431. }
  432. encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(pair->privKey, caCert);
  433. CERT_DestroyCertificate(caCert);
  434. if (encKey == NULL) {
  435. printf ("Could not create Encrypted Key with Encrypted Value.\n");
  436. return 14;
  437. }
  438. pkiArchOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encKey);
  439. CRMF_DestroyEncryptedKey(encKey);
  440. if (pkiArchOpt == NULL) {
  441. printf ("Could not create PKIArchiveOptions.\n");
  442. return 15;
  443. }
  444. rv = CRMF_CertRequestSetPKIArchiveOptions(certReq, pkiArchOpt);
  445. CRMF_DestroyPKIArchiveOptions(pkiArchOpt);
  446. if (rv != SECSuccess) {
  447. printf ("Could not add the PKIArchiveControl to Cert Request.\n");
  448. return 16;
  449. }
  450. pair->certReq = certReq;
  451. return 0;
  452. }
  453. int
  454. Encode(CRMFCertReqMsg *inCertReq1, CRMFCertReqMsg *inCertReq2)
  455. {
  456. PRFileDesc *fileDesc;
  457. SECStatus rv;
  458. int irv = 0;
  459. CRMFCertReqMsg *msgArr[3];
  460. char filePath[PATH_LEN];
  461. PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE);
  462. fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  463. 0666);
  464. if (fileDesc == NULL) {
  465. printf ("Could not open file %s\n", filePath);
  466. irv = 14;
  467. goto finish;
  468. }
  469. msgArr[0] = inCertReq1;
  470. msgArr[1] = inCertReq2;
  471. msgArr[2] = NULL;
  472. rv = CRMF_EncodeCertReqMessages(msgArr, WriteItOut, (void*)fileDesc);
  473. if (rv != SECSuccess) {
  474. printf ("An error occurred while encoding.\n");
  475. irv = 15;
  476. }
  477. finish:
  478. PR_Close(fileDesc);
  479. return irv;
  480. }
  481. int
  482. AddProofOfPossession(TESTKeyPair *pair,
  483. CRMFPOPChoice inPOPChoice)
  484. {
  485. switch(inPOPChoice){
  486. case crmfSignature:
  487. CRMF_CertReqMsgSetSignaturePOP(pair->certReqMsg, pair->privKey,
  488. pair->pubKey, NULL, NULL, &pwdata);
  489. break;
  490. case crmfRAVerified:
  491. CRMF_CertReqMsgSetRAVerifiedPOP(pair->certReqMsg);
  492. break;
  493. case crmfKeyEncipherment:
  494. CRMF_CertReqMsgSetKeyEnciphermentPOP(pair->certReqMsg,
  495. crmfSubsequentMessage,
  496. crmfChallengeResp, NULL);
  497. break;
  498. case crmfKeyAgreement:
  499. {
  500. SECItem pendejo;
  501. unsigned char lame[] = { 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 };
  502. pendejo.data = lame;
  503. pendejo.len = 5;
  504. CRMF_CertReqMsgSetKeyAgreementPOP(pair->certReqMsg, crmfThisMessage,
  505. crmfNoSubseqMess, &pendejo);
  506. }
  507. break;
  508. default:
  509. return 1;
  510. }
  511. return 0;
  512. }
  513. int
  514. Decode(void)
  515. {
  516. PRFileDesc *fileDesc;
  517. CRMFCertReqMsg *certReqMsg;
  518. CRMFCertRequest *certReq;
  519. CRMFCertReqMessages *certReqMsgs;
  520. SECStatus rv;
  521. int numMsgs, i;
  522. long lame;
  523. CRMFGetValidity validity = {NULL, NULL};
  524. SECItem item = { siBuffer, NULL, 0 };
  525. char filePath[PATH_LEN];
  526. PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE);
  527. fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
  528. if (fileDesc == NULL) {
  529. printf ("Could not open file %s\n", filePath);
  530. return 214;
  531. }
  532. rv = SECU_FileToItem(&item, fileDesc);
  533. PR_Close(fileDesc);
  534. if (rv != SECSuccess) {
  535. return 215;
  536. }
  537. certReqMsgs = CRMF_CreateCertReqMessagesFromDER((char *)item.data, item.len);
  538. if (certReqMsgs == NULL) {
  539. printf ("Error decoding CertReqMessages.\n");
  540. return 202;
  541. }
  542. numMsgs = CRMF_CertReqMessagesGetNumMessages(certReqMsgs);
  543. if (numMsgs <= 0) {
  544. printf ("WARNING: The DER contained %d messages.\n", numMsgs);
  545. }
  546. for (i=0; i < numMsgs; i++) {
  547. SECStatus rv;
  548. printf("crmftest: Processing cert request %d\n", i);
  549. certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i);
  550. if (certReqMsg == NULL) {
  551. printf ("ERROR: Could not access the message at index %d of %s\n",
  552. i, filePath);
  553. }
  554. rv = CRMF_CertReqMsgGetID(certReqMsg, &lame);
  555. if (rv) {
  556. SECU_PrintError("crmftest", "CRMF_CertReqMsgGetID");
  557. }
  558. certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg);
  559. if (!certReq) {
  560. SECU_PrintError("crmftest", "CRMF_CertReqMsgGetCertRequest");
  561. }
  562. rv = CRMF_CertRequestGetCertTemplateValidity(certReq, &validity);
  563. if (rv) {
  564. SECU_PrintError("crmftest", "CRMF_CertRequestGetCertTemplateValidity");
  565. }
  566. if (!validity.notBefore) {
  567. /* We encoded a notBefore, so somthing's wrong if it's not here. */
  568. printf("ERROR: Validity period notBefore date missing.\n");
  569. }
  570. /* XXX It's all parsed now. We probably should DO SOMETHING with it.
  571. ** But nope. We just throw it all away.
  572. ** Maybe this was intended to be no more than a decoder test.
  573. */
  574. CRMF_DestroyGetValidity(&validity);
  575. CRMF_DestroyCertRequest(certReq);
  576. CRMF_DestroyCertReqMsg(certReqMsg);
  577. }
  578. CRMF_DestroyCertReqMessages(certReqMsgs);
  579. SECITEM_FreeItem(&item, PR_FALSE);
  580. return 0;
  581. }
  582. int
  583. GetBitsFromFile(const char *filePath, SECItem *item)
  584. {
  585. PRFileDesc *fileDesc;
  586. SECStatus rv;
  587. fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
  588. if (fileDesc == NULL) {
  589. printf ("Could not open file %s\n", filePath);
  590. return 14;
  591. }
  592. rv = SECU_FileToItem(item, fileDesc);
  593. PR_Close(fileDesc);
  594. if (rv != SECSuccess) {
  595. item->data = NULL;
  596. item->len = 0;
  597. return 15;
  598. }
  599. return 0;
  600. }
  601. int
  602. DecodeCMMFCertRepContent(char *derFile)
  603. {
  604. CMMFCertRepContent *certRepContent;
  605. int irv = 0;
  606. SECItem fileBits = { siBuffer, NULL, 0 };
  607. GetBitsFromFile(derFile, &fileBits);
  608. if (fileBits.data == NULL) {
  609. printf("Could not get bits from file %s\n", derFile);
  610. return 304;
  611. }
  612. certRepContent = CMMF_CreateCertRepContentFromDER(db,
  613. (char*)fileBits.data, fileBits.len);
  614. if (certRepContent == NULL) {
  615. printf ("Error while decoding %s\n", derFile);
  616. irv = 303;
  617. } else {
  618. /* That was fun. Now, let's throw it away! */
  619. CMMF_DestroyCertRepContent(certRepContent);
  620. }
  621. SECITEM_FreeItem(&fileBits, PR_FALSE);
  622. return irv;
  623. }
  624. int
  625. EncodeCMMFCertReply(const char *filePath,
  626. CERTCertificate *cert,
  627. CERTCertList *list)
  628. {
  629. int rv = 0;
  630. SECStatus srv;
  631. PRFileDesc *fileDesc = NULL;
  632. CMMFCertRepContent *certRepContent = NULL;
  633. CMMFCertResponse *certResp = NULL;
  634. CMMFCertResponse *certResponses[3];
  635. certResp = CMMF_CreateCertResponse(0xff123);
  636. CMMF_CertResponseSetPKIStatusInfoStatus(certResp, cmmfGranted);
  637. CMMF_CertResponseSetCertificate(certResp, cert);
  638. certResponses[0] = certResp;
  639. certResponses[1] = NULL;
  640. certResponses[2] = NULL;
  641. certRepContent = CMMF_CreateCertRepContent();
  642. CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1);
  643. CMMF_CertRepContentSetCAPubs(certRepContent, list);
  644. fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  645. 0666);
  646. if (fileDesc == NULL) {
  647. printf ("Could not open file %s\n", filePath);
  648. rv = 400;
  649. goto finish;
  650. }
  651. srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut,
  652. (void*)fileDesc);
  653. PR_Close(fileDesc);
  654. if (srv != SECSuccess) {
  655. printf ("CMMF_EncodeCertRepContent failed,\n");
  656. rv = 401;
  657. }
  658. finish:
  659. if (certRepContent) {
  660. CMMF_DestroyCertRepContent(certRepContent);
  661. }
  662. if (certResp) {
  663. CMMF_DestroyCertResponse(certResp);
  664. }
  665. return rv;
  666. }
  667. /* Extract the public key from the cert whose nickname is given. */
  668. int
  669. extractPubKeyFromNamedCert(const char * nickname, SECKEYPublicKey **pPubKey)
  670. {
  671. CERTCertificate *caCert = NULL;
  672. SECKEYPublicKey *caPubKey = NULL;
  673. int rv = 0;
  674. caCert = CERT_FindCertByNickname(db, (char *)nickname);
  675. if (caCert == NULL) {
  676. printf ("Could not get the certifcate for %s\n", caCertName);
  677. rv = 411;
  678. goto finish;
  679. }
  680. caPubKey = CERT_ExtractPublicKey(caCert);
  681. if (caPubKey == NULL) {
  682. printf ("Could not extract the public from the "
  683. "certificate for \n%s\n", caCertName);
  684. rv = 412;
  685. }
  686. finish:
  687. *pPubKey = caPubKey;
  688. CERT_DestroyCertificate(caCert);
  689. caCert = NULL;
  690. return rv;
  691. }
  692. int
  693. EncodeCMMFRecoveryMessage(const char * filePath,
  694. CERTCertificate *cert,
  695. CERTCertList *list)
  696. {
  697. SECKEYPublicKey *caPubKey = NULL;
  698. SECKEYPrivateKey *privKey = NULL;
  699. CMMFKeyRecRepContent *repContent = NULL;
  700. PRFileDesc *fileDesc;
  701. int rv = 0;
  702. SECStatus srv;
  703. /* Extract the public key from the cert whose nickname is given in
  704. ** the -s option.
  705. */
  706. rv = extractPubKeyFromNamedCert( caCertName, &caPubKey);
  707. if (rv)
  708. goto finish;
  709. repContent = CMMF_CreateKeyRecRepContent();
  710. if (repContent == NULL) {
  711. printf ("Could not allocate a CMMFKeyRecRepContent structure\n");
  712. rv = 407;
  713. goto finish;
  714. }
  715. srv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(repContent,
  716. cmmfGrantedWithMods);
  717. if (srv != SECSuccess) {
  718. printf ("Error trying to set PKIStatusInfo for "
  719. "CMMFKeyRecRepContent.\n");
  720. rv = 406;
  721. goto finish;
  722. }
  723. srv = CMMF_KeyRecRepContentSetNewSignCert(repContent, cert);
  724. if (srv != SECSuccess) {
  725. printf ("Error trying to set the new signing certificate for "
  726. "key recovery\n");
  727. rv = 408;
  728. goto finish;
  729. }
  730. srv = CMMF_KeyRecRepContentSetCACerts(repContent, list);
  731. if (srv != SECSuccess) {
  732. printf ("Errory trying to add the list of CA certs to the "
  733. "CMMFKeyRecRepContent structure.\n");
  734. rv = 409;
  735. goto finish;
  736. }
  737. privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
  738. if (privKey == NULL) {
  739. printf ("Could not get the private key associated with the\n"
  740. "certificate %s\n", personalCert);
  741. rv = 410;
  742. goto finish;
  743. }
  744. srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey,
  745. caPubKey);
  746. if (srv != SECSuccess) {
  747. printf ("Could not set the Certified Key Pair\n");
  748. rv = 413;
  749. goto finish;
  750. }
  751. fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  752. 0666);
  753. if (fileDesc == NULL) {
  754. printf ("Could not open file %s\n", filePath);
  755. rv = 414;
  756. goto finish;
  757. }
  758. srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut,
  759. (void*)fileDesc);
  760. PR_Close(fileDesc);
  761. if (srv != SECSuccess) {
  762. printf ("CMMF_EncodeKeyRecRepContent failed\n");
  763. rv = 415;
  764. }
  765. finish:
  766. if (privKey)
  767. SECKEY_DestroyPrivateKey(privKey);
  768. if (caPubKey)
  769. SECKEY_DestroyPublicKey(caPubKey);
  770. if (repContent)
  771. CMMF_DestroyKeyRecRepContent(repContent);
  772. return rv;
  773. }
  774. int
  775. decodeCMMFRecoveryMessage(const char * filePath)
  776. {
  777. CMMFKeyRecRepContent *repContent = NULL;
  778. int rv = 0;
  779. SECItem fileBits = { siBuffer, NULL, 0 };
  780. GetBitsFromFile(filePath, &fileBits);
  781. if (!fileBits.len) {
  782. rv = 451;
  783. goto finish;
  784. }
  785. repContent =
  786. CMMF_CreateKeyRecRepContentFromDER(db, (const char *) fileBits.data,
  787. fileBits.len);
  788. if (repContent == NULL) {
  789. printf ("ERROR: CMMF_CreateKeyRecRepContentFromDER failed on file:\n"
  790. "\t%s\n", filePath);
  791. rv = 452;
  792. }
  793. finish:
  794. if (repContent) {
  795. CMMF_DestroyKeyRecRepContent(repContent);
  796. }
  797. SECITEM_FreeItem(&fileBits, PR_FALSE);
  798. return rv;
  799. }
  800. int
  801. DoCMMFStuff(void)
  802. {
  803. CERTCertificate *cert = NULL;
  804. CERTCertList *list = NULL;
  805. int rv = 0;
  806. char filePath[PATH_LEN];
  807. /* Do common setup for the following steps.
  808. */
  809. PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, "CertRepContent.der");
  810. cert = CERT_FindCertByNickname(db, personalCert);
  811. if (cert == NULL) {
  812. printf ("Could not find the certificate for %s\n", personalCert);
  813. rv = 416;
  814. goto finish;
  815. }
  816. list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner);
  817. if (list == NULL) {
  818. printf ("Could not find the certificate chain for %s\n", personalCert);
  819. rv = 418;
  820. goto finish;
  821. }
  822. /* a) Generate the CMMF response message, using a user cert named
  823. ** by -p option, rather than a cert generated from the CRMF
  824. ** request itself. The CMMF message is placed in
  825. ** configdir/CertRepContent.der.
  826. */
  827. rv = EncodeCMMFCertReply(filePath, cert, list);
  828. if (rv != 0) {
  829. goto finish;
  830. }
  831. /* b) Decode the CMMF Cert granting message encoded just above,
  832. ** found in configdir/CertRepContent.der.
  833. ** This only tests the decoding. The decoded content is discarded.
  834. */
  835. rv = DecodeCMMFCertRepContent(filePath);
  836. if (rv != 0) {
  837. goto finish;
  838. }
  839. /* c) Generate a CMMF Key Excrow message
  840. ** It takes the public and private keys for the cert identified
  841. ** by -p nickname, and wraps them with a sym key that is in turn
  842. ** wrapped with the pubkey in the CA cert, whose nickname is
  843. ** given by the -s option.
  844. ** Store the message in configdir/KeyRecRepContent.der
  845. */
  846. PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir,
  847. "KeyRecRepContent.der");
  848. rv = EncodeCMMFRecoveryMessage(filePath, cert, list);
  849. if (rv)
  850. goto finish;
  851. /* d) Decode the CMMF Key Excrow message generated just above.
  852. ** Get it from file configdir/KeyRecRepContent.der
  853. ** This is just a decoder test. Results are discarded.
  854. */
  855. rv = decodeCMMFRecoveryMessage(filePath);
  856. finish:
  857. if (cert) {
  858. CERT_DestroyCertificate(cert);
  859. }
  860. if (list) {
  861. CERT_DestroyCertList(list);
  862. }
  863. return rv;
  864. }
  865. static CK_MECHANISM_TYPE
  866. mapWrapKeyType(KeyType keyType)
  867. {
  868. switch (keyType) {
  869. case rsaKey:
  870. return CKM_RSA_PKCS;
  871. default:
  872. break;
  873. }
  874. return CKM_INVALID_MECHANISM;
  875. }
  876. #define KNOWN_MESSAGE_LENGTH 20 /*160 bits*/
  877. int
  878. DoKeyRecovery( SECKEYPrivateKey *privKey)
  879. {
  880. #ifdef DOING_KEY_RECOVERY /* Doesn't compile yet. */
  881. SECKEYPublicKey *pubKey;
  882. PK11SlotInfo *slot;
  883. unsigned char *ciphertext;
  884. unsigned char *text_compared;
  885. SECKEYPrivateKey *unwrappedPrivKey;
  886. SECKEYPrivateKey *caPrivKey;
  887. CMMFKeyRecRepContent *keyRecRep;
  888. CMMFCertifiedKeyPair *certKeyPair;
  889. CERTCertificate *caCert;
  890. CERTCertificate *myCert;
  891. SECKEYPublicKey *caPubKey;
  892. PRFileDesc *fileDesc;
  893. CK_ULONG max_bytes_encrypted;
  894. CK_ULONG bytes_encrypted;
  895. CK_ULONG bytes_compared;
  896. CK_ULONG bytes_decrypted;
  897. CK_RV crv;
  898. CK_OBJECT_HANDLE id;
  899. CK_MECHANISM mech = { CKM_INVALID_MECHANISM, NULL, 0};
  900. SECStatus rv;
  901. SECItem fileBits;
  902. SECItem nickname;
  903. unsigned char plaintext[KNOWN_MESSAGE_LENGTH];
  904. char filePath[PATH_LEN];
  905. static const unsigned char known_message[] = { "Known Crypto Message" };
  906. /*caCert = CERT_FindCertByNickname(db, caCertName);*/
  907. myCert = CERT_FindCertByNickname(db, personalCert);
  908. if (myCert == NULL) {
  909. printf ("Could not find the certificate for %s\n", personalCert);
  910. return 700;
  911. }
  912. caCert = CERT_FindCertByNickname(db, recoveryEncrypter);
  913. if (caCert == NULL) {
  914. printf ("Could not find the certificate for %s\n", recoveryEncrypter);
  915. return 701;
  916. }
  917. caPubKey = CERT_ExtractPublicKey(caCert);
  918. pubKey = SECKEY_ConvertToPublicKey(privKey);
  919. max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey);
  920. slot = PK11_GetBestSlot(mapWrapKeyType(privKey->keyType), NULL);
  921. id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE);
  922. switch(privKey->keyType) {
  923. case rsaKey:
  924. mech.mechanism = CKM_RSA_PKCS;
  925. break;
  926. case dsaKey:
  927. mech.mechanism = CKM_DSA;
  928. break;
  929. case dhKey:
  930. mech.mechanism = CKM_DH_PKCS_DERIVE;
  931. break;
  932. default:
  933. printf ("Bad Key type in key recovery.\n");
  934. return 512;
  935. }
  936. PK11_EnterSlotMonitor(slot);
  937. crv = PK11_GETTAB(slot)->C_EncryptInit(slot->session, &mech, id);
  938. if (crv != CKR_OK) {
  939. PK11_ExitSlotMonitor(slot);
  940. PK11_FreeSlot(slot);
  941. printf ("C_EncryptInit failed in KeyRecovery\n");
  942. return 500;
  943. }
  944. ciphertext = PORT_NewArray(unsigned char, max_bytes_encrypted);
  945. if (ciphertext == NULL) {
  946. PK11_ExitSlotMonitor(slot);
  947. PK11_FreeSlot(slot);
  948. printf ("Could not allocate memory for ciphertext.\n");
  949. return 501;
  950. }
  951. bytes_encrypted = max_bytes_encrypted;
  952. crv = PK11_GETTAB(slot)->C_Encrypt(slot->session,
  953. known_message,
  954. KNOWN_MESSAGE_LENGTH,
  955. ciphertext,
  956. &bytes_encrypted);
  957. PK11_ExitSlotMonitor(slot);
  958. PK11_FreeSlot(slot);
  959. if (crv != CKR_OK) {
  960. PORT_Free(ciphertext);
  961. return 502;
  962. }
  963. /* Always use the smaller of these two values . . . */
  964. bytes_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH )
  965. ? KNOWN_MESSAGE_LENGTH
  966. : bytes_encrypted;
  967. /* If there was a failure, the plaintext */
  968. /* goes at the end, therefore . . . */
  969. text_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH )
  970. ? (ciphertext + bytes_encrypted -
  971. KNOWN_MESSAGE_LENGTH )
  972. : ciphertext;
  973. keyRecRep = CMMF_CreateKeyRecRepContent();
  974. if (keyRecRep == NULL) {
  975. PORT_Free(ciphertext);
  976. PK11_FreeSlot(slot);
  977. CMMF_DestroyKeyRecRepContent(keyRecRep);
  978. printf ("Could not allocate a CMMFKeyRecRepContent structre.\n");
  979. return 503;
  980. }
  981. rv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(keyRecRep,
  982. cmmfGranted);
  983. if (rv != SECSuccess) {
  984. PORT_Free(ciphertext);
  985. PK11_FreeSlot(slot);
  986. CMMF_DestroyKeyRecRepContent(keyRecRep);
  987. printf ("Could not set the status for the KeyRecRepContent\n");
  988. return 504;
  989. }
  990. /* The myCert here should correspond to the certificate corresponding
  991. * to the private key, but for this test any certificate will do.
  992. */
  993. rv = CMMF_KeyRecRepContentSetCertifiedKeyPair(keyRecRep, myCert,
  994. privKey, caPubKey);
  995. if (rv != SECSuccess) {
  996. PORT_Free(ciphertext);
  997. PK11_FreeSlot(slot);
  998. CMMF_DestroyKeyRecRepContent(keyRecRep);
  999. printf ("Could not set the Certified Key Pair\n");
  1000. return 505;
  1001. }
  1002. PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir,
  1003. "KeyRecRepContent.der");
  1004. fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  1005. 0666);
  1006. if (fileDesc == NULL) {
  1007. PORT_Free(ciphertext);
  1008. PK11_FreeSlot(slot);
  1009. CMMF_DestroyKeyRecRepContent(keyRecRep);
  1010. printf ("Could not open file %s\n", filePath);
  1011. return 506;
  1012. }
  1013. rv = CMMF_EncodeKeyRecRepContent(keyRecRep, WriteItOut, fileDesc);
  1014. CMMF_DestroyKeyRecRepContent(keyRecRep);
  1015. PR_Close(fileDesc);
  1016. if (rv != SECSuccess) {
  1017. PORT_Free(ciphertext);
  1018. PK11_FreeSlot(slot);
  1019. printf ("Error while encoding CMMFKeyRecRepContent\n");
  1020. return 507;
  1021. }
  1022. GetBitsFromFile(filePath, &fileBits);
  1023. if (fileBits.data == NULL) {
  1024. PORT_Free(ciphertext);
  1025. PK11_FreeSlot(slot);
  1026. printf ("Could not get the bits from file %s\n", filePath);
  1027. return 508;
  1028. }
  1029. keyRecRep =
  1030. CMMF_CreateKeyRecRepContentFromDER(db,(const char*)fileBits.data,
  1031. fileBits.len);
  1032. if (keyRecRep == NULL) {
  1033. printf ("Could not decode the KeyRecRepContent in file %s\n",
  1034. filePath);
  1035. PORT_Free(ciphertext);
  1036. PK11_FreeSlot(slot);
  1037. return 509;
  1038. }
  1039. caPrivKey = PK11_FindKeyByAnyCert(caCert, &pwdata);
  1040. if (CMMF_KeyRecRepContentGetPKIStatusInfoStatus(keyRecRep) !=
  1041. cmmfGranted) {
  1042. PORT_Free(ciphertext);
  1043. PK11_FreeSlot(slot);
  1044. CMMF_DestroyKeyRecRepContent(keyRecRep);
  1045. printf ("A bad status came back with the "
  1046. "KeyRecRepContent structure\n");
  1047. return 510;
  1048. }
  1049. #define NICKNAME "Key Recovery Test Key"
  1050. nickname.data = (unsigned char*)NICKNAME;
  1051. nickname.len = PORT_Strlen(NICKNAME);
  1052. certKeyPair = CMMF_KeyRecRepContentGetCertKeyAtIndex(keyRecRep, 0);
  1053. CMMF_DestroyKeyRecRepContent(keyRecRep);
  1054. rv = CMMF_CertifiedKeyPairUnwrapPrivKey(certKeyPair,
  1055. caPrivKey,
  1056. &nickname,
  1057. PK11_GetInternalKeySlot(),
  1058. db,
  1059. &unwrappedPrivKey, &pwdata);
  1060. CMMF_DestroyCertifiedKeyPair(certKeyPair);
  1061. if (rv != SECSuccess) {
  1062. printf ("Unwrapping the private key failed.\n");
  1063. return 511;
  1064. }
  1065. /*Now let's try to decrypt the ciphertext with the "recovered" key*/
  1066. PK11_EnterSlotMonitor(slot);
  1067. crv =
  1068. PK11_GETTAB(slot)->C_DecryptInit(unwrappedPrivKey->pkcs11Slot->session,
  1069. &mech,
  1070. unwrappedPrivKey->pkcs11ID);
  1071. if (crv != CKR_OK) {
  1072. PK11_ExitSlotMonitor(slot);
  1073. PORT_Free(ciphertext);
  1074. PK11_FreeSlot(slot);
  1075. printf ("Decrypting with the recovered key failed.\n");
  1076. return 513;
  1077. }
  1078. bytes_decrypted = KNOWN_MESSAGE_LENGTH;
  1079. crv = PK11_GETTAB(slot)->C_Decrypt(unwrappedPrivKey->pkcs11Slot->session,
  1080. ciphertext,
  1081. bytes_encrypted, plaintext,
  1082. &bytes_decrypted);
  1083. SECKEY_DestroyPrivateKey(unwrappedPrivKey);
  1084. PK11_ExitSlotMonitor(slot);
  1085. PORT_Free(ciphertext);
  1086. if (crv != CKR_OK) {
  1087. PK11_FreeSlot(slot);
  1088. printf ("Decrypting the ciphertext with recovered key failed.\n");
  1089. return 514;
  1090. }
  1091. if ((bytes_decrypted != KNOWN_MESSAGE_LENGTH) ||
  1092. (PORT_Memcmp(plaintext, known_message, KNOWN_MESSAGE_LENGTH) != 0)) {
  1093. PK11_FreeSlot(slot);
  1094. printf ("The recovered plaintext does not equal the known message:\n"
  1095. "\tKnown message: %s\n"
  1096. "\tRecovered plaintext: %s\n", known_message, plaintext);
  1097. return 515;
  1098. }
  1099. #endif
  1100. return 0;
  1101. }
  1102. int
  1103. DoChallengeResponse(SECKEYPrivateKey *privKey,
  1104. SECKEYPublicKey *pubKey)
  1105. {
  1106. CMMFPOPODecKeyChallContent *chalContent = NULL;
  1107. CMMFPOPODecKeyRespContent *respContent = NULL;
  1108. CERTCertificate *myCert = NULL;
  1109. CERTGeneralName *myGenName = NULL;
  1110. PRArenaPool *poolp = NULL;
  1111. PRFileDesc *fileDesc;
  1112. SECItem *publicValue;
  1113. SECItem *keyID;
  1114. SECKEYPrivateKey *foundPrivKey;
  1115. long *randomNums;
  1116. int numChallengesFound = 0;
  1117. int numChallengesSet = 1;
  1118. int i;
  1119. long retrieved;
  1120. SECStatus rv;
  1121. SECItem DecKeyChallBits;
  1122. char filePath[PATH_LEN];
  1123. chalContent = CMMF_CreatePOPODecKeyChallContent();
  1124. myCert = CERT_FindCertByNickname(db, personalCert);
  1125. if (myCert == NULL) {
  1126. printf ("Could not find the certificate for %s\n", personalCert);
  1127. return 900;
  1128. }
  1129. poolp = PORT_NewArena(1024);
  1130. if (poolp == NULL) {
  1131. printf("Could no allocate a new arena in DoChallengeResponse\n");
  1132. return 901;
  1133. }
  1134. myGenName = CERT_GetCertificateNames(myCert, poolp);
  1135. if (myGenName == NULL) {
  1136. printf ("Could not get the general names for %s certificate\n",
  1137. personalCert);
  1138. return 902;
  1139. }
  1140. randomNums = PORT_ArenaNewArray(poolp,long, numChallengesSet);
  1141. PK11_GenerateRandom((unsigned char *)randomNums,
  1142. numChallengesSet * sizeof(long));
  1143. for (i=0; i<numChallengesSet; i++) {
  1144. rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
  1145. randomNums[i],
  1146. myGenName,
  1147. pubKey,
  1148. &pwdata);
  1149. if (rv != SECSuccess) {
  1150. printf ("Could not set the challenge in DoChallengeResponse\n");
  1151. return 903;
  1152. }
  1153. }
  1154. PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyChallContent.der",
  1155. configdir);
  1156. fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  1157. 0666);
  1158. if (fileDesc == NULL) {
  1159. printf ("Could not open file %s\n", filePath);
  1160. return 904;
  1161. }
  1162. rv = CMMF_EncodePOPODecKeyChallContent(chalContent,WriteItOut,
  1163. (void*)fileDesc);
  1164. PR_Close(fileDesc);
  1165. CMMF_DestroyPOPODecKeyChallContent(chalContent);
  1166. if (rv != SECSuccess) {
  1167. printf ("Could not encode the POPODecKeyChallContent.\n");
  1168. return 905;
  1169. }
  1170. GetBitsFromFile(filePath, &DecKeyChallBits);
  1171. chalContent = CMMF_CreatePOPODecKeyChallContentFromDER
  1172. ((const char*)DecKeyChallBits.data, DecKeyChallBits.len);
  1173. SECITEM_FreeItem(&DecKeyChallBits, PR_FALSE);
  1174. if (chalContent == NULL) {
  1175. printf ("Could not create the POPODecKeyChallContent from DER\n");
  1176. return 906;
  1177. }
  1178. numChallengesFound =
  1179. CMMF_POPODecKeyChallContentGetNumChallenges(chalContent);
  1180. if (numChallengesFound != numChallengesSet) {
  1181. printf ("Number of Challenges Found (%d) does not equal the number "
  1182. "set (%d)\n", numChallengesFound, numChallengesSet);
  1183. return 907;
  1184. }
  1185. for (i=0; i<numChallengesSet; i++) {
  1186. publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i);
  1187. if (publicValue == NULL) {
  1188. printf("Could not get the public value for challenge at index %d\n",
  1189. i);
  1190. return 908;
  1191. }
  1192. keyID = PK11_MakeIDFromPubKey(publicValue);
  1193. if (keyID == NULL) {
  1194. printf ("Could not make the keyID from the public value\n");
  1195. return 909;
  1196. }
  1197. foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot, keyID, &pwdata);
  1198. if (foundPrivKey == NULL) {
  1199. printf ("Could not find the private key corresponding to the public"
  1200. " value.\n");
  1201. return 910;
  1202. }
  1203. rv = CMMF_POPODecKeyChallContDecryptChallenge(chalContent, i,
  1204. foundPrivKey);
  1205. if (rv != SECSuccess) {
  1206. printf ("Could not decrypt the challenge at index %d\n", i);
  1207. return 911;
  1208. }
  1209. rv = CMMF_POPODecKeyChallContentGetRandomNumber(chalContent, i,
  1210. &retrieved);
  1211. if (rv != SECSuccess) {
  1212. printf ("Could not get the random number from the challenge at "
  1213. "index %d\n", i);
  1214. return 912;
  1215. }
  1216. if (retrieved != randomNums[i]) {
  1217. printf ("Retrieved the number (%ld), expected (%ld)\n", retrieved,
  1218. randomNums[i]);
  1219. return 913;
  1220. }
  1221. }
  1222. CMMF_DestroyPOPODecKeyChallContent(chalContent);
  1223. PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyRespContent.der",
  1224. configdir);
  1225. fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
  1226. 0666);
  1227. if (fileDesc == NULL) {
  1228. printf ("Could not open file %s\n", filePath);
  1229. return 914;
  1230. }
  1231. rv = CMMF_EncodePOPODecKeyRespContent(randomNums, numChallengesSet,
  1232. WriteItOut, fileDesc);
  1233. PR_Close(fileDesc);
  1234. if (rv != 0) {
  1235. printf ("Could not encode the POPODecKeyRespContent\n");
  1236. return 915;
  1237. }
  1238. GetBitsFromFile(filePath, &DecKeyChallBits);
  1239. respContent =
  1240. CMMF_CreatePOPODecKeyRespContentFromDER((const char*)DecKeyChallBits.data,
  1241. DecKeyChallBits.len);
  1242. if (respContent == NULL) {
  1243. printf ("Could not decode the contents of the file %s\n", filePath);
  1244. return 916;
  1245. }
  1246. numChallengesFound =
  1247. CMMF_POPODecKeyRespContentGetNumResponses(respContent);
  1248. if (numChallengesFound != numChallengesSet) {
  1249. printf ("Number of responses found (%d) does not match the number "
  1250. "of challenges set (%d)\n",
  1251. numChallengesFound, numChallengesSet);
  1252. return 917;
  1253. }
  1254. for (i=0; i<numChallengesSet; i++) {
  1255. rv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &retrieved);
  1256. if (rv != SECSuccess) {
  1257. printf ("Could not retrieve the response at index %d\n", i);
  1258. return 918;
  1259. }
  1260. if (retrieved != randomNums[i]) {
  1261. printf ("Retrieved the number (%ld), expected (%ld)\n", retrieved,
  1262. randomNums[i]);
  1263. return 919;
  1264. }
  1265. }
  1266. CMMF_DestroyPOPODecKeyRespContent(respContent);
  1267. return 0;
  1268. }
  1269. int
  1270. MakeCertRequest(TESTKeyPair *pair, CRMFPOPChoice inPOPChoice, long inRequestID)
  1271. {
  1272. int irv;
  1273. /* Generate a key pair and a cert request for it. */
  1274. irv = CreateCertRequest(pair, inRequestID);
  1275. if (irv != 0 || pair->certReq == NULL) {
  1276. goto loser;
  1277. }
  1278. pair->certReqMsg = CRMF_CreateCertReqMsg();
  1279. if (!pair->certReqMsg) {
  1280. irv = 999;
  1281. goto loser;
  1282. }
  1283. /* copy certReq into certReqMsg */
  1284. CRMF_CertReqMsgSetCertRequest(pair->certReqMsg, pair->certReq);
  1285. irv = AddProofOfPossession(pair, inPOPChoice);
  1286. loser:
  1287. return irv;
  1288. }
  1289. int
  1290. DestroyPairReqAndMsg(TESTKeyPair *pair)
  1291. {
  1292. SECStatus rv = SECSuccess;
  1293. int irv = 0;
  1294. if (pair->certReq) {
  1295. rv = CRMF_DestroyCertRequest(pair->certReq);
  1296. pair->certReq = NULL;
  1297. if (rv != SECSuccess) {
  1298. printf ("Error when destroying cert request.\n");
  1299. irv = 100;
  1300. }
  1301. }
  1302. if (pair->certReqMsg) {
  1303. rv = CRMF_DestroyCertReqMsg(pair->certReqMsg);
  1304. pair->certReqMsg = NULL;
  1305. if (rv != SECSuccess) {
  1306. printf ("Error when destroying cert request msg.\n");
  1307. if (!irv)
  1308. irv = 101;
  1309. }
  1310. }
  1311. return irv;
  1312. }
  1313. int
  1314. DestroyPair(TESTKeyPair *pair)
  1315. {
  1316. int irv = 0;
  1317. if (pair->pubKey) {
  1318. SECKEY_DestroyPublicKey(pair->pubKey);
  1319. pair->pubKey = NULL;
  1320. }
  1321. if (pair->privKey) {
  1322. SECKEY_DestroyPrivateKey(pair->privKey);
  1323. pair->privKey = NULL;
  1324. }
  1325. DestroyPairReqAndMsg(pair);
  1326. return irv;
  1327. }
  1328. int
  1329. DoCRMFRequest(TESTKeyPair *signPair, TESTKeyPair *cryptPair)
  1330. {
  1331. int irv, tirv = 0;
  1332. /* Generate a key pair and a cert request for it. */
  1333. irv = MakeCertRequest(signPair, crmfSignature, 0x0f020304);
  1334. if (irv != 0 || signPair->certReq == NULL) {
  1335. goto loser;
  1336. }
  1337. if (!doingDSA) {
  1338. irv = MakeCertRequest(cryptPair, crmfKeyAgreement, 0x0f050607);
  1339. if (irv != 0 || cryptPair->certReq == NULL) {
  1340. goto loser;
  1341. }
  1342. }
  1343. /* encode the cert request messages into a unified request message.
  1344. ** leave it in a file with a fixed name. :(
  1345. */
  1346. irv = Encode(signPair->certReqMsg, cryptPair->certReqMsg);
  1347. loser:
  1348. if (signPair->certReq) {
  1349. tirv = DestroyPairReqAndMsg(signPair);
  1350. if (tirv && !irv)
  1351. irv = tirv;
  1352. }
  1353. if (cryptPair->certReq) {
  1354. tirv = DestroyPairReqAndMsg(cryptPair);
  1355. if (tirv && !irv)
  1356. irv = tirv;
  1357. }
  1358. return irv;
  1359. }
  1360. void
  1361. Usage (void)
  1362. {
  1363. printf ("Usage:\n"
  1364. "\tcrmftest -d [Database Directory] -p [Personal Cert]\n"
  1365. "\t -e [Encrypter] -s [CA Certificate] [-P password]\n\n"
  1366. "\t [crmf] [dsa] [decode] [cmmf] [recover] [challenge]\n"
  1367. "\t [-f password_file]\n"
  1368. "Database Directory\n"
  1369. "\tThis is the directory where the key3.db, cert7.db, and\n"
  1370. "\tsecmod.db files are located. This is also the directory\n"
  1371. "\twhere the program will place CRMF/CMMF der files\n"
  1372. "Personal Cert\n"
  1373. "\tThis is the certificate that already exists in the cert\n"
  1374. "\tdatabase to use while encoding the response. The private\n"
  1375. "\tkey associated with the certificate must also exist in the\n"
  1376. "\tkey database.\n"
  1377. "Encrypter\n"
  1378. "\tThis is the certificate to use when encrypting the the \n"
  1379. "\tkey recovery response. The private key for this cert\n"
  1380. "\tmust also be present in the key database.\n"
  1381. "CA Certificate\n"
  1382. "\tThis is the nickname of the certificate to use as the\n"
  1383. "\tCA when doing all of the encoding.\n");
  1384. }
  1385. #define TEST_MAKE_CRMF_REQ 0x0001
  1386. #define TEST_USE_DSA 0x0002
  1387. #define TEST_DECODE_CRMF_REQ 0x0004
  1388. #define TEST_DO_CMMF_STUFF 0x0008
  1389. #define TEST_KEY_RECOVERY 0x0010
  1390. #define TEST_CHALLENGE_RESPONSE 0x0020
  1391. SECStatus
  1392. parsePositionalParam(const char * arg, PRUint32 *flags)
  1393. {
  1394. if (!strcmp(arg, "crmf")) {
  1395. *flags |= TEST_MAKE_CRMF_REQ;
  1396. } else if (!strcmp(arg, "dsa")) {
  1397. *flags |= TEST_MAKE_CRMF_REQ | TEST_USE_DSA;
  1398. doingDSA = PR_TRUE;
  1399. } else if (!strcmp(arg, "decode")) {
  1400. *flags |= TEST_DECODE_CRMF_REQ;
  1401. } else if (!strcmp(arg, "cmmf")) {
  1402. *flags |= TEST_DO_CMMF_STUFF;
  1403. } else if (!strcmp(arg, "recover")) {
  1404. *flags |= TEST_KEY_RECOVERY;
  1405. } else if (!strcmp(arg, "challenge")) {
  1406. *flags |= TEST_CHALLENGE_RESPONSE;
  1407. } else {
  1408. printf("unknown positional paremeter: %s\n", arg);
  1409. return SECFailure;
  1410. }
  1411. return SECSuccess;
  1412. }
  1413. /* it's not clear, in some cases, whether the desired key is from
  1414. ** the sign pair or the crypt pair, so we're guessing in some places.
  1415. ** This define serves to remind us of the places where we're guessing.
  1416. */
  1417. #define WHICH_KEY cryptPair
  1418. int
  1419. main(int argc, char **argv)
  1420. {
  1421. TESTKeyPair signPair, cryptPair;
  1422. PLOptState *optstate;
  1423. PLOptStatus status;
  1424. char *password = NULL;
  1425. char *pwfile = NULL;
  1426. int irv = 0;
  1427. PRUint32 flags = 0;
  1428. SECStatus rv;
  1429. PRBool nssInit = PR_FALSE;
  1430. PRBool pArg = PR_FALSE;
  1431. PRBool eArg = PR_FALSE;
  1432. PRBool sArg = PR_FALSE;
  1433. PRBool PArg = PR_FALSE;
  1434. memset( &signPair, 0, sizeof signPair);
  1435. memset( &cryptPair, 0, sizeof cryptPair);
  1436. printf ("\ncrmftest v1.0\n");
  1437. optstate = PL_CreateOptState(argc, argv, "d:p:e:s:P:f:");
  1438. while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  1439. switch (optstate->option) {
  1440. case 'd':
  1441. configdir = PORT_Strdup(optstate->value);
  1442. rv = NSS_Init(configdir);
  1443. if (rv != SECSuccess) {
  1444. printf ("NSS_Init (-d) failed\n");
  1445. return 101;
  1446. }
  1447. nssInit = PR_TRUE;
  1448. break;
  1449. case 'p':
  1450. personalCert = PORT_Strdup(optstate->value);
  1451. if (personalCert == NULL) {
  1452. printf ("-p failed\n");
  1453. return 603;
  1454. }
  1455. pArg = PR_TRUE;
  1456. break;
  1457. case 'e':
  1458. recoveryEncrypter = PORT_Strdup(optstate->value);
  1459. if (recoveryEncrypter == NULL) {
  1460. printf ("-e failed\n");
  1461. return 602;
  1462. }
  1463. eArg = PR_TRUE;
  1464. break;
  1465. case 's':
  1466. caCertName = PORT_Strdup(optstate->value);
  1467. if (caCertName == NULL) {
  1468. printf ("-s failed\n");
  1469. return 604;
  1470. }
  1471. sArg = PR_TRUE;
  1472. break;
  1473. case 'P':
  1474. password = PORT_Strdup(optstate->value);
  1475. if (password == NULL) {
  1476. printf ("-P failed\n");
  1477. return 606;
  1478. }
  1479. pwdata.source = PW_PLAINTEXT;
  1480. pwdata.data = password;
  1481. PArg = PR_TRUE;
  1482. break;
  1483. case 'f':
  1484. pwfile = PORT_Strdup(optstate->value);
  1485. if (pwfile == NULL) {
  1486. printf ("-f failed\n");
  1487. return 607;
  1488. }
  1489. pwdata.source = PW_FROMFILE;
  1490. pwdata.data = pwfile;
  1491. break;
  1492. case 0: /* positional parameter */
  1493. rv = parsePositionalParam(optstate->value, &flags);
  1494. if (rv) {
  1495. printf ("bad positional parameter.\n");
  1496. return 605;
  1497. }
  1498. break;
  1499. default:
  1500. Usage();
  1501. return 601;
  1502. }
  1503. }
  1504. PL_DestroyOptState(optstate);
  1505. if (status == PL_OPT_BAD || !nssInit) {
  1506. Usage();
  1507. return 600;
  1508. }
  1509. if (!flags)
  1510. flags = ~ TEST_USE_DSA;
  1511. db = CERT_GetDefaultCertDB();
  1512. InitPKCS11();
  1513. if (flags & TEST_MAKE_CRMF_REQ) {
  1514. printf("Generating CRMF request\n");
  1515. irv = DoCRMFRequest(&signPair, &cryptPair);
  1516. if (irv)
  1517. goto loser;
  1518. }
  1519. if (flags & TEST_DECODE_CRMF_REQ) {
  1520. printf("Decoding CRMF request\n");
  1521. irv = Decode();
  1522. if (irv != 0) {
  1523. printf("Error while decoding\n");
  1524. goto loser;
  1525. }
  1526. }
  1527. if (flags & TEST_DO_CMMF_STUFF) {
  1528. printf("Doing CMMF Stuff\n");
  1529. if ((irv = DoCMMFStuff()) != 0) {
  1530. printf ("CMMF tests failed.\n");
  1531. goto loser;
  1532. }
  1533. }
  1534. if (flags & TEST_KEY_RECOVERY) {
  1535. /* Requires some other options be set.
  1536. ** Once we know exactly what hey are, test for them here.
  1537. */
  1538. printf("Doing Key Recovery\n");
  1539. irv = DoKeyRecovery(WHICH_KEY.privKey);
  1540. if (irv != 0) {
  1541. printf ("Error doing key recovery\n");
  1542. goto loser;
  1543. }
  1544. }
  1545. if (flags & TEST_CHALLENGE_RESPONSE) {
  1546. printf("Doing Challenge / Response\n");
  1547. irv = DoChallengeResponse(WHICH_KEY.privKey, WHICH_KEY.pubKey);
  1548. if (irv != 0) {
  1549. printf ("Error doing challenge-response\n");
  1550. goto loser;
  1551. }
  1552. }
  1553. printf ("Exiting successfully!!!\n\n");
  1554. irv = 0;
  1555. loser:
  1556. DestroyPair(&signPair);
  1557. DestroyPair(&cryptPair);
  1558. rv = NSS_Shutdown();
  1559. if (rv) {
  1560. printf("NSS_Shutdown did not shutdown cleanly!\n");
  1561. }
  1562. PORT_Free(configdir);
  1563. if (irv)
  1564. printf("crmftest returning %d\n", irv);
  1565. return irv;
  1566. }