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