1/* 2 * dotMacTool.cpp - .mac TP exerciser 3 */ 4 5#include <Security/Security.h> 6#include <Security/SecKeyPriv.h> 7#include <security_cdsa_utils/cuCdsaUtils.h> 8#include <security_cdsa_utils/cuFileIo.h> 9#include <security_cdsa_utils/cuPem.h> 10#include <stdlib.h> 11#include <stdio.h> 12#include <unistd.h> 13//#include <security_dotmac_tp/dotMacTp.h> 14#include <dotMacTp.h> 15#include <security_cdsa_utils/cuPrintCert.h> 16 17#include "keyPicker.h" 18#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> 19 20#define USER_DEFAULT "dmitchtest@mac.com" 21#define PWD_DEF "123456" 22 23static void usage(char **argv) 24{ 25 printf("usage: %s op [options]\n", argv[0]); 26 printf("Op:\n"); 27 printf(" g generate identity cert\n"); 28 printf(" G generate email signing cert\n"); 29 printf(" e generate email encrypting cert\n"); 30 printf(" l lookup cert (requires -f)\n"); 31 printf(" L lookup identity cert (via -u)\n"); 32 printf(" M lookup email signing cert (via -u)\n"); 33 printf(" N lookup encrypting cert (via -u)\n"); 34 printf("Options:\n"); 35 printf(" -g Generate keypair\n"); 36 printf(" -p pick key pair from existing\n"); 37 printf(" -u username Default = %s\n", USER_DEFAULT); 38 printf(" -Z password Specify password immediately\n"); 39 printf(" -z Use default password %s\n", PWD_DEF); 40 printf(" -k keychain Source/destination of keys and certs\n"); 41 printf(" -c filename Write CSR to filename\n"); 42 printf(" -C filename Use existing CSR (no keygen)\n"); 43 printf(" -f refIdFile RefId file for cert lookup\n"); 44 printf(" -n Do NOT post the CSR to the .mac server\n"); 45 printf(" -H hostname Alternate .mac server host name (default %s)\n", 46 DOT_MAC_SIGN_HOST_NAME); 47 printf(" -o outFile Write output cert or refId (if any) to outFile\n"); 48 printf(" -r Renew (default is new)\n"); 49 printf(" -M Pause for MallocDebug\n"); 50 printf(" -q Quiet\n"); 51 printf(" -v Verbose\n"); 52 printf(" -h Usage\n"); 53 exit(1); 54} 55 56static CSSM_VERSION vers = {2, 0}; 57 58static CSSM_API_MEMORY_FUNCS memFuncs = { 59 cuAppMalloc, 60 cuAppFree, 61 cuAppRealloc, 62 cuAppCalloc, 63 NULL 64 }; 65 66static CSSM_TP_HANDLE dotMacStartup() 67{ 68 CSSM_TP_HANDLE tpHand; 69 CSSM_RETURN crtn; 70 71 if(cuCssmStartup() == CSSM_FALSE) { 72 return 0; 73 } 74 crtn = CSSM_ModuleLoad(&gGuidAppleDotMacTP, 75 CSSM_KEY_HIERARCHY_NONE, 76 NULL, // eventHandler 77 NULL); // AppNotifyCallbackCtx 78 if(crtn) { 79 cuPrintError("CSSM_ModuleLoad(DotMacTP)", crtn); 80 return 0; 81 } 82 crtn = CSSM_ModuleAttach (&gGuidAppleDotMacTP, 83 &vers, 84 &memFuncs, // memFuncs 85 0, // SubserviceID 86 CSSM_SERVICE_TP, // SubserviceFlags 87 0, // AttachFlags 88 CSSM_KEY_HIERARCHY_NONE, 89 NULL, // FunctionTable 90 0, // NumFuncTable 91 NULL, // reserved 92 &tpHand); 93 if(crtn) { 94 cuPrintError("CSSM_ModuleAttach(DotMacTP)", crtn); 95 return 0; 96 } 97 else { 98 return tpHand; 99 } 100} 101 102/* print text, safely */ 103static void snDumpText( 104 const unsigned char *rcvBuf, 105 unsigned len) 106{ 107 char *cp = (char *)rcvBuf; 108 unsigned i; 109 char c; 110 111 for(i=0; i<len; i++) { 112 c = *cp++; 113 if(c == '\0') { 114 break; 115 } 116 switch(c) { 117 case '\n': 118 printf("\\n\n"); // graphic and liternal newline 119 break; 120 case '\r': 121 printf("\\r\n"); 122 break; 123 default: 124 if(isprint(c) && (c != '\n')) { 125 printf("%c", c); 126 } 127 else { 128 printf("<%02X>", ((unsigned)c) & 0xff); 129 } 130 break; 131 } 132 133 } 134} 135 136static OSStatus genKeyPair( 137 SecKeychainRef kcRef, // NULL means the default list 138 SecKeyRef *pubKey, // RETURNED 139 SecKeyRef *privKey) // RETURNED 140{ 141 OSStatus ortn; 142 143 ortn = SecKeyCreatePair(kcRef, 144 DOT_MAC_KEY_ALG, 145 DOT_MAC_KEY_SIZE, 146 0, // context handle 147 /* public key usage and attrs */ 148 CSSM_KEYUSE_ANY, 149 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, 150 /* private key usage and attrs */ 151 CSSM_KEYUSE_ANY, 152 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | 153 CSSM_KEYATTR_SENSITIVE, 154 NULL, // initial access 155 pubKey, 156 privKey); 157 if(ortn) { 158 cssmPerror("SecKeyCreatePair", ortn); 159 } 160 return ortn; 161} 162 163/* Lookup via ReferenceID, obtained from CSSM_TP_SubmitCredRequest() */ 164OSStatus doLookupViaRefId( 165 CSSM_TP_HANDLE tpHand, 166 unsigned char *refId, 167 unsigned refIdLen, 168 char *outFile, 169 bool verbose) 170{ 171 CSSM_DATA refIdData = { refIdLen, refId }; 172 sint32 EstimatedTime; 173 CSSM_BOOL ConfirmationRequired; 174 CSSM_TP_RESULT_SET_PTR resultSet = NULL; 175 CSSM_RETURN crtn; 176 177 crtn = CSSM_TP_RetrieveCredResult(tpHand, &refIdData, NULL, 178 &EstimatedTime, &ConfirmationRequired, &resultSet); 179 if(crtn) { 180 cssmPerror("CSSM_TP_RetrieveCredResult", crtn); 181 return crtn; 182 } 183 if(resultSet == NULL) { 184 printf("***CSSM_TP_RetrieveCredResult OK, but no result set\n"); 185 return -1; 186 } 187 if(resultSet->NumberOfResults != 1) { 188 printf("***CSSM_TP_RetrieveCredResult OK, NumberOfResults (%u)\n", 189 (unsigned)resultSet->NumberOfResults); 190 return -1; 191 } 192 if(resultSet->Results == NULL) { 193 printf("***CSSM_TP_RetrieveCredResult OK, but empty result set\n"); 194 return -1; 195 } 196 CSSM_DATA_PTR certData = (CSSM_DATA_PTR)resultSet->Results; 197 198 printf("...cert retrieval complete\n"); 199 if(outFile) { 200 if(!writeFile(outFile, certData->Data, certData->Length)) { 201 printf("...%lu bytes of cert data written to %s\n", 202 certData->Length, outFile); 203 } 204 else { 205 printf("***Error writing cert to %s\n", outFile); 206 crtn = ioErr; 207 } 208 } 209 else if(verbose) { 210 unsigned char *der; 211 unsigned derLen; 212 if(pemDecode(certData->Data, certData->Length, &der, &derLen)) { 213 printf("***Error PEM decoding returned cert\n"); 214 } 215 else { 216 printCert(der, derLen, CSSM_FALSE); 217 free(der); 218 } 219 } 220 return noErr; 221} 222 223/* 224* Lookup via user name, a greatly simplified form of CSSM_TP_SubmitCredRequest() 225*/ 226OSStatus doLookupViaUserName( 227 CSSM_TP_HANDLE tpHand, 228 const CSSM_OID *opOid, 229 const char *userName, 230 const char *hostName, // optional 231 char *outFile, 232 bool verbose) 233{ 234 CSSM_APPLE_DOTMAC_TP_CERT_REQUEST certReq; 235 CSSM_TP_AUTHORITY_ID tpAuthority; 236 CSSM_TP_AUTHORITY_ID *tpAuthPtr = NULL; 237 CSSM_NET_ADDRESS tpNetAddrs; 238 CSSM_TP_REQUEST_SET reqSet; 239 CSSM_FIELD policyField; 240 CSSM_DATA certData = {0, NULL}; 241 sint32 estTime; 242 CSSM_TP_CALLERAUTH_CONTEXT callerAuth; 243 244 memset(&certReq, 0, sizeof(certReq)); 245 certReq.userName.Data = (uint8 *)userName; 246 certReq.userName.Length = strlen(userName); 247 if(hostName != NULL) { 248 tpAuthority.AuthorityCert = NULL; 249 tpAuthority.AuthorityLocation = &tpNetAddrs; 250 tpNetAddrs.AddressType = CSSM_ADDR_NAME; 251 tpNetAddrs.Address.Data = (uint8 *)hostName; 252 tpNetAddrs.Address.Length = strlen(hostName); 253 tpAuthPtr = &tpAuthority; 254 }; 255 256 certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; 257 reqSet.NumberOfRequests = 1; 258 reqSet.Requests = &certReq; 259 policyField.FieldOid = *opOid; 260 policyField.FieldValue.Data = NULL; 261 policyField.FieldValue.Length = 0; 262 memset(&callerAuth, 0, sizeof(callerAuth)); 263 callerAuth.Policy.NumberOfPolicyIds = 1; 264 callerAuth.Policy.PolicyIds = &policyField; 265 266 CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest (tpHand, 267 tpAuthPtr, 268 CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP, 269 &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, 270 &callerAuth, 271 &estTime, // sint32 *EstimatedTime, 272 &certData); // CSSM_DATA_PTR ReferenceIdentifier 273 274 if(crtn) { 275 cssmPerror("CSSM_TP_SubmitCredRequest(lookup)", crtn); 276 return crtn; 277 } 278 279 printf("...cert lookup complete\n"); 280 if(outFile) { 281 if(!writeFile(outFile, certData.Data, certData.Length)) { 282 printf("...%lu bytes of cert data written to %s\n", 283 certData.Length, outFile); 284 } 285 else { 286 printf("***Error writing cert to %s\n", outFile); 287 crtn = ioErr; 288 } 289 } 290 if(verbose) { 291 /* This one returns the cert in DER format, we might revisit that */ 292 printCert(certData.Data, certData.Length, CSSM_FALSE); 293 } 294 return crtn; 295} 296 297#define FULL_EMAIL_ADDRESS 1 298 299int main(int argc, char **argv) 300{ 301 CSSM_RETURN crtn; 302 CSSM_TP_AUTHORITY_ID tpAuthority; 303 CSSM_TP_AUTHORITY_ID *tpAuthPtr = NULL; 304 CSSM_NET_ADDRESS tpNetAddrs; 305 CSSM_APPLE_DOTMAC_TP_CERT_REQUEST certReq; 306 CSSM_TP_REQUEST_SET reqSet; 307 CSSM_CSP_HANDLE cspHand = 0; 308 CSSM_X509_TYPE_VALUE_PAIR tvp; 309 char pwdBuf[1000]; 310 CSSM_TP_CALLERAUTH_CONTEXT callerAuth; 311 sint32 estTime; 312 CSSM_DATA refId = {0, NULL}; 313 OSStatus ortn; 314 SecKeyRef pubKeyRef = NULL; 315 SecKeyRef privKeyRef = NULL; 316 const CSSM_KEY *privKey = NULL; 317 const CSSM_KEY *pubKey = NULL; 318 SecKeychainRef kcRef = NULL; 319 CSSM_FIELD policyField; 320 321 /* user-spec'd variables */ 322 bool genKeys = false; 323 bool pickKeys = false; 324 char *keychainName = NULL; 325 char *csrOutName = NULL; 326 char *csrInName = NULL; 327 const char *userName = USER_DEFAULT; 328 char *password = NULL; 329 char *hostName = NULL; 330 bool doNotPost = false; 331 bool doRenew = false; 332 const CSSM_OID *opOid = NULL; 333 char *outFile = NULL; 334 bool quiet = false; 335 bool verbose = false; 336 bool lookupViaRefId = false; 337 bool lookupViaUserName = false; 338 char *refIdFile = NULL; 339 bool doPause = false; 340 341 if(argc < 2) { 342 usage(argv); 343 } 344 switch(argv[1][0]) { 345 case 'L': 346 lookupViaUserName = true; 347 /* drop thru */ 348 case 'g': 349 opOid = &CSSMOID_DOTMAC_CERT_REQ_IDENTITY; 350 break; 351 352 case 'M': 353 lookupViaUserName = true; 354 /* drop thru */ 355 case 'G': 356 opOid = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN; 357 break; 358 359 case 'N': 360 lookupViaUserName = true; 361 /* drop thru */ 362 case 'e': 363 opOid = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT; 364 break; 365 366 case 'l': 367 lookupViaRefId = true; 368 break; 369 default: 370 usage(argv); 371 } 372 373 extern char *optarg; 374 extern int optind; 375 optind = 2; 376 int arg; 377 while ((arg = getopt(argc, argv, "gpk:c:u:Z:H:nzrC:o:hf:Mqv")) != -1) { 378 switch (arg) { 379 case 'g': 380 genKeys = true; 381 break; 382 case 'p': 383 pickKeys = true; 384 break; 385 case 'u': 386 userName = optarg; 387 break; 388 case 'Z': 389 password = optarg; 390 break; 391 case 'z': 392 password = (char *)PWD_DEF; 393 break; 394 case 'k': 395 keychainName = optarg; 396 break; 397 case 'c': 398 csrOutName = optarg; 399 break; 400 case 'C': 401 csrInName = optarg; 402 break; 403 case 'H': 404 hostName = optarg; 405 break; 406 case 'n': 407 doNotPost = true; 408 break; 409 case 'r': 410 doRenew = true; 411 break; 412 case 'o': 413 outFile = optarg; 414 break; 415 case 'f': 416 refIdFile = optarg; 417 break; 418 case 'M': 419 doPause = true; 420 break; 421 case 'v': 422 verbose = true; 423 break; 424 case 'q': 425 quiet = true; 426 break; 427 case 'h': 428 usage(argv); 429 } 430 } 431 432 if(doPause) { 433 fpurge(stdin); 434 printf("Pausing for MallocDebug attach; CR to continue: "); 435 getchar(); 436 } 437 438 CSSM_TP_HANDLE tpHand = dotMacStartup(); 439 if(tpHand == 0) { 440 printf("Error attaching to the .mac TP. Check your MDS file.\n"); 441 exit(1); 442 } 443 444 if(lookupViaRefId) { 445 if(refIdFile == NULL) { 446 printf("I need a refIdFile to do a lookup.\n"); 447 usage(argv); 448 } 449 unsigned char *refId; 450 unsigned refIdLen; 451 int irtn = readFile(refIdFile, &refId, &refIdLen); 452 if(irtn) { 453 printf("***Error reading refId from %s. Aborting.\n", refIdFile); 454 exit(1); 455 } 456 ortn = doLookupViaRefId(tpHand, refId, refIdLen, outFile, verbose); 457 free(refId); 458 goto done; 459 } 460 if(lookupViaUserName) { 461 ortn = doLookupViaUserName(tpHand, opOid, userName, hostName, outFile, verbose); 462 goto done; 463 } 464 if(!pickKeys && !genKeys && (csrInName == NULL)) { 465 printf("***You must specify either the -p (pick keys) or -g (generate keys)" 466 " arguments, or provide a CSR (-C).\n"); 467 exit(1); 468 } 469 470 memset(&certReq, 0, sizeof(certReq)); 471 472 /* all of the subsequest argument are superfluous for lookupViaUserName, except for 473 * the user name itself, which has a default */ 474 if(keychainName != NULL) { 475 /* pick a keychain (optional) */ 476 ortn = SecKeychainOpen(keychainName, &kcRef); 477 if(ortn) { 478 cssmPerror("SecKeychainOpen", ortn); 479 exit(1); 480 } 481 482 /* make sure it's there since a successful SecKeychainOpen proves nothing */ 483 SecKeychainStatus kcStat; 484 ortn = SecKeychainGetStatus(kcRef, &kcStat); 485 if(ortn) { 486 cssmPerror("SecKeychainGetStatus", ortn); 487 goto done; 488 } 489 } 490 491 if(password == NULL) { 492 const char *pwdp = getpass("Enter .mac password: "); 493 if(pwdp == NULL) { 494 printf("Aboerting.\n"); 495 ortn = paramErr; 496 goto done; 497 } 498 memmove(pwdBuf, pwdp, strlen(pwdp) + 1); 499 password = pwdBuf; 500 } 501 certReq.password.Data = (uint8 *)password; 502 certReq.password.Length = strlen(password); 503 certReq.userName.Data = (uint8 *)userName; 504 certReq.userName.Length = strlen(userName); 505 506 if(csrInName) { 507 unsigned len; 508 if(readFile(csrInName, &certReq.csr.Data, &len)) { 509 printf("***Error reading CSR from %s. Aborting.\n", csrInName); 510 exit(1); 511 } 512 certReq.csr.Length = len; 513 certReq.flags |= CSSM_DOTMAC_TP_EXIST_CSR; 514 } 515 else { 516 /* 517 * All the stuff the TP needs to actually generate a CSR. 518 * 519 * Get a key pair, somehow. 520 */ 521 if(genKeys) { 522 ortn = genKeyPair(kcRef, &pubKeyRef, &privKeyRef); 523 } 524 else { 525 ortn = keyPicker(kcRef, &pubKeyRef, &privKeyRef); 526 } 527 if(ortn) { 528 printf("Can't proceed without a keypair. Aborting.\n"); 529 exit(1); 530 } 531 ortn = SecKeyGetCSSMKey(pubKeyRef, &pubKey); 532 if(ortn) { 533 cssmPerror("SecKeyGetCSSMKey", ortn); 534 goto done; 535 } 536 ortn = SecKeyGetCSSMKey(privKeyRef, &privKey); 537 if(ortn) { 538 cssmPerror("SecKeyGetCSSMKey", ortn); 539 goto done; 540 } 541 ortn = SecKeyGetCSPHandle(privKeyRef, &cspHand); 542 if(ortn) { 543 cssmPerror("SecKeyGetCSPHandle", ortn); 544 goto done; 545 } 546 547 /* CSSM_X509_TYPE_VALUE_PAIR - one pair for now */ 548 // tvp.type = CSSMOID_EmailAddress; 549 tvp.type = CSSMOID_CommonName; 550 tvp.valueType = BER_TAG_PRINTABLE_STRING; 551 #if FULL_EMAIL_ADDRESS 552 { 553 unsigned nameLen = strlen(userName); 554 tvp.value.Data = (uint8 *)malloc(nameLen + strlen("@mac.com") + 1); 555 strcpy((char *)tvp.value.Data, userName); 556 strcpy((char *)tvp.value.Data + nameLen, "@mac.com"); 557 tvp.value.Length = strlen((char *)tvp.value.Data); 558 } 559 #else 560 tvp.value.Data = (uint8 *)userName; 561 tvp.value.Length = strlen(userName); 562 #endif 563 } 564 /* set up args for CSSM_TP_SubmitCredRequest */ 565 if(hostName != NULL) { 566 tpAuthority.AuthorityCert = NULL; 567 tpAuthority.AuthorityLocation = &tpNetAddrs; 568 tpNetAddrs.AddressType = CSSM_ADDR_NAME; 569 tpNetAddrs.Address.Data = (uint8 *)hostName; 570 tpNetAddrs.Address.Length = strlen(hostName); 571 tpAuthPtr = &tpAuthority; 572 }; 573 574 certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; 575 if(!csrInName) { 576 certReq.cspHand = cspHand; 577 certReq.clHand = cuClStartup(); 578 certReq.numTypeValuePairs = 1; 579 certReq.typeValuePairs = &tvp; 580 certReq.publicKey = (CSSM_KEY_PTR)pubKey; 581 certReq.privateKey = (CSSM_KEY_PTR)privKey; 582 } 583 if(doNotPost) { 584 certReq.flags |= CSSM_DOTMAC_TP_DO_NOT_POST; 585 } 586 if(csrOutName != NULL) { 587 certReq.flags |= CSSM_DOTMAC_TP_RETURN_CSR; 588 } 589 if(doRenew) { 590 certReq.flags |= CSSM_DOTMAC_TP_SIGN_RENEW; 591 } 592 593 reqSet.NumberOfRequests = 1; 594 reqSet.Requests = &certReq; 595 596 policyField.FieldOid = *opOid; 597 policyField.FieldValue.Data = NULL; 598 policyField.FieldValue.Length = 0; 599 memset(&callerAuth, 0, sizeof(callerAuth)); 600 callerAuth.Policy.NumberOfPolicyIds = 1; 601 callerAuth.Policy.PolicyIds = &policyField; 602 if(!csrInName) { 603 ortn = SecKeyGetCredentials(privKeyRef, 604 CSSM_ACL_AUTHORIZATION_SIGN, 605 kSecCredentialTypeDefault, 606 const_cast<const CSSM_ACCESS_CREDENTIALS **>(&callerAuth.CallerCredentials)); 607 if(ortn) { 608 cssmPerror("SecKeyGetCredentials", crtn); 609 goto done; 610 } 611 } 612 613 crtn = CSSM_TP_SubmitCredRequest (tpHand, 614 tpAuthPtr, 615 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, // CSSM_TP_AUTHORITY_REQUEST_TYPE 616 &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, 617 &callerAuth, 618 &estTime, // sint32 *EstimatedTime, 619 &refId); // CSSM_DATA_PTR ReferenceIdentifier 620 switch(crtn) { 621 case CSSM_OK: 622 case CSSMERR_APPLE_DOTMAC_REQ_QUEUED: 623 { 624 /* 625 * refId should be a cert or RefId 626 */ 627 const char *itemType = "Cert"; 628 const char *statStr = "OK"; 629 if(crtn != CSSM_OK) { 630 itemType = "RefId"; 631 statStr = "Cert"; 632 } 633 if((refId.Data == NULL) || (refId.Length == 0)) { 634 printf("CSSM_TP_SubmitCredRequest returned %s but no data\n", statStr); 635 break; 636 } 637 if(crtn == CSSM_OK) { 638 printf("...cert acquisition complete\n"); 639 } 640 else { 641 printf("...Cert request QUEUED\n"); 642 } 643 if(outFile) { 644 if(!writeFile(outFile, refId.Data, refId.Length)) { 645 if(!quiet) { 646 printf("...%lu bytes of %s written to %s\n", 647 refId.Length, itemType, outFile); 648 } 649 } 650 else { 651 printf("***Error writing %s to %s\n", itemType, outFile); 652 crtn = ioErr; 653 } 654 } 655 else if(verbose) { 656 if(crtn == CSSM_OK) { 657 unsigned char *der; 658 unsigned derLen; 659 if(pemDecode(refId.Data, refId.Length, &der, &derLen)) { 660 printf("***Error PEM decoding returned cert\n"); 661 } 662 else { 663 printCert(der, derLen, CSSM_FALSE); 664 free(der); 665 } 666 } 667 else { 668 printf("RefId data:\n"); 669 snDumpText(refId.Data, refId.Length); 670 } 671 } 672 break; 673 } 674 case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT: 675 if((refId.Data == NULL) || (refId.Length == 0)) { 676 printf("CSSM_TP_SubmitCredRequest returned REDIRECT but no data\n"); 677 break; 678 } 679 printf("...cert acquisition : REDIRECTED to: "); 680 snDumpText(refId.Data, refId.Length); 681 printf("\n"); 682 break; 683 default: 684 cssmPerror("CSSM_TP_SubmitCredRequest", crtn); 685 break; 686 } 687 if(csrOutName) { 688 if((certReq.csr.Data == NULL) || (certReq.csr.Length == 0)) { 689 printf("***Asked for CSR but didn't get one\n"); 690 ortn = paramErr; 691 goto done; 692 } 693 if(writeFile(csrOutName, certReq.csr.Data, certReq.csr.Length)) { 694 printf("***Error writing CSR to %s.\n", csrOutName); 695 } 696 else { 697 printf("...%lu bytes written as CSR to %s\n", certReq.csr.Length, csrOutName); 698 } 699 } 700done: 701 /* cleanup */ 702 CSSM_ModuleDetach(tpHand); 703 if(certReq.clHand) { 704 CSSM_ModuleDetach(certReq.clHand); 705 } 706 if(kcRef) { 707 CFRelease(kcRef); 708 } 709 if(csrInName) { 710 free(certReq.csr.Data); 711 } 712 if(privKeyRef) { 713 CFRelease(privKeyRef); 714 } 715 if(pubKeyRef) { 716 CFRelease(pubKeyRef); 717 } 718 if(refId.Data) { 719 cuAppFree(refId.Data, NULL); 720 } 721 if(doPause) { 722 fpurge(stdin); 723 printf("Pausing for MallocDebug measurement; CR to continue: "); 724 getchar(); 725 } 726 727 return ortn; 728} 729