]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/cmstool/testSubjects/ptext1.txt
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / cmstool / testSubjects / ptext1.txt
1 /*
2 * cmstool.cpp - manipluate CMS messages, intended to be an alternate for the
3 * currently useless cms command in /usr/bin/security
4 */
5
6 #include <Security/Security.h>
7 #include <utilLib/fileIo.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <utilLib/common.h>
13 #include <security_cdsa_utils/cuFileIo.h>
14 #include <security_cdsa_utils/cuPrintCert.h>
15 #include <clAppUtils/identPicker.h>
16 #include <clAppUtils/sslAppUtils.h>
17 #include <security_cdsa_utils/cuOidParser.h>
18 #include <CoreFoundation/CoreFoundation.h>
19 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
20 #include <Security/SecCmsEncoder.h>
21 #include <Security/SecCmsDecoder.h>
22 #include <Security/SecCmsEncryptedData.h>
23 #include <Security/SecCmsEnvelopedData.h>
24 #include <Security/SecCmsMessage.h>
25 #include <Security/SecCmsRecipientInfo.h>
26 #include <Security/SecCmsSignedData.h>
27 #include <Security/SecCmsSignerInfo.h>
28 #include <Security/SecCmsContentInfo.h>
29 #include <Security/SecTrustPriv.h>
30 #include <Security/SecKeychainItemPriv.h>
31 #include <Security/SecCertificate.h>
32 #include <Security/SecSMIME.h>
33
34 static void usage(char **argv)
35 {
36 printf("Usage: %s cmd [option ...]\n", argv[0]);
37 printf("cmd values:\n");
38 printf(" sign -- create signedData\n");
39 printf(" envel -- create envelopedData\n");
40 printf(" parse -- parse a CMS message file\n");
41 printf("Options:\n");
42 printf(" -i infile\n");
43 printf(" -o outfile\n");
44 printf(" -k keychain -- Keychain to search for certs\n");
45 printf(" -p -- Use identity picker\n");
46 printf(" -r recipient -- specify recipient of enveloped data\n");
47 printf(" -c -- parse signer cert\n");
48 printf(" -q -- quiet\n");
49 exit(1);
50 }
51
52 typedef enum {
53 CTO_Sign,
54 CTO_Envelop,
55 CTO_Parse
56 } CT_Op;
57
58 /*
59 * Find a cert in specified keychain or keychain list matching specified
60 * email address. We happen to knopw that the email address is stored with the
61 * kSecAliasItemAttr attribute.
62 */
63 static OSStatus findCert(
64 const char *emailAddress,
65 CFTypeRef kcArArray, // kc, array, or even NULL
66 SecCertificateRef *cert)
67 {
68 OSStatus ortn;
69 SecKeychainSearchRef srch;
70 SecKeychainAttributeList attrList;
71 SecKeychainAttribute attr;
72
73 attr.tag = kSecAliasItemAttr;
74 attr.length = strlen(emailAddress);
75 attr.data = (void *)emailAddress;
76 attrList.count = 1;
77 attrList.attr = &attr;
78
79 ortn = SecKeychainSearchCreateFromAttributes(kcArArray,
80 kSecCertificateItemClass,
81 &attrList,
82 &srch);
83 if(ortn) {
84 cssmPerror("SecKeychainSearchCreateFromAttributes", ortn);
85 return ortn;
86 }
87
88 ortn = SecKeychainSearchCopyNext(srch, (SecKeychainItemRef *)cert);
89 if(ortn) {
90 printf("***No certs founmd matching recipient %s. Aborting.\n");
91 return ortn;
92 }
93 CFRelease(srch);
94 return noErr;
95 }
96
97 static void evalSecTrust(
98 SecTrustRef secTrust)
99 {
100 OSStatus ortn;
101 SecTrustResultType secTrustResult;
102
103 ortn = SecTrustEvaluate(secTrust, &secTrustResult);
104 if(ortn) {
105 /* should never happen */
106 cssmPerror("SecTrustEvaluate", ortn);
107 return;
108 }
109 switch(secTrustResult) {
110 case kSecTrustResultUnspecified:
111 /* cert chain valid, no special UserTrust assignments */
112 case kSecTrustResultProceed:
113 /* cert chain valid AND user explicitly trusts this */
114 fprintf(stderr, "Successful\n");
115 return;
116 case kSecTrustResultDeny:
117 case kSecTrustResultConfirm:
118 /*
119 * Cert chain may well have verified OK, but user has flagged
120 * one of these certs as untrustable.
121 */
122 printf("Not trusted per user-specified Trust level\n");
123 return;
124 default:
125 {
126 /* get low-level TP error */
127 OSStatus tpStatus;
128 ortn = SecTrustGetCssmResultCode(secTrust, &tpStatus);
129 if(ortn) {
130 cssmPerror("SecTrustGetCssmResultCode", ortn);
131 return;
132 }
133 switch(tpStatus) {
134 case CSSMERR_TP_INVALID_ANCHOR_CERT:
135 fprintf(stderr, "Untrusted root\n");
136 return;
137 case CSSMERR_TP_NOT_TRUSTED:
138 /* no root, not even in implicit SSL roots */
139 fprintf(stderr, "No root cert found\n");
140 return;
141 case CSSMERR_TP_CERT_EXPIRED:
142 fprintf(stderr, "Expired cert\n");
143 return;
144 case CSSMERR_TP_CERT_NOT_VALID_YET:
145 fprintf(stderr, "Cert not valid yet\n");
146 break;
147 default:
148 printf("Other cert failure: ");
149 cssmPerror("", tpStatus);
150 return;
151 }
152 }
153 } /* SecTrustEvaluate error */
154
155 }
156 static OSStatus parseSignedData(
157 SecCmsSignedDataRef signedData,
158 bool parseSignerCert)
159 {
160 Boolean b;
161 b = SecCmsSignedDataHasDigests(signedData);
162 printf(" has digests : %s\n", b ? "true" : "false");
163
164 SecTrustRef secTrust = NULL;
165 OSStatus ortn;
166 SecPolicyRef policy = NULL;
167 SecPolicySearchRef policySearch = NULL;
168
169 ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
170 &CSSMOID_APPLE_X509_BASIC,
171 NULL,
172 &policySearch);
173 if(ortn) {
174 cssmPerror("SecPolicySearchCreate", ortn);
175 return ortn;
176 }
177 ortn = SecPolicySearchCopyNext(policySearch, &policy);
178 if(ortn) {
179 cssmPerror("SecPolicySearchCopyNext", ortn);
180 return ortn;
181 }
182
183 int numSigners = SecCmsSignedDataSignerInfoCount(signedData);
184 printf(" num signers : %d\n", numSigners);
185 for(int dex=0; dex<numSigners; dex++) {
186 fprintf(stderr, " signer %d :\n", dex);
187 Boolean b = SecCmsSignedDataHasDigests(signedData);
188 fprintf(stderr, " vfy status : ");
189 if(b) {
190 ortn = SecCmsSignedDataVerifySignerInfo(signedData, dex, NULL,
191 policy, &secTrust);
192 if(ortn) {
193 fprintf(stderr, "vfSignerInfo() returned %d\n", (int)ortn);
194 fprintf(stderr, " vfy status : ");
195 }
196 if(secTrust == NULL) {
197 fprintf(stderr, "***NO SecTrust available!\n");
198 }
199 else {
200 evalSecTrust(secTrust);
201 }
202 }
203 else {
204 fprintf(stderr, "<<SecCmsSignedDataHasDigests returned false>>\n");
205 }
206 SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, dex);
207 CFStringRef emailAddrs = SecCmsSignerInfoGetSignerCommonName(signerInfo);
208 char emailStr[1000];
209 fprintf(stderr, " signer : ");
210 if(emailAddrs == NULL) {
211 printf("<<SecCmsSignerInfoGetSignerCommonName returned NULL)>>\n");
212 }
213 else {
214 if(!CFStringGetCString(emailAddrs, emailStr, 1000, kCFStringEncodingASCII)) {
215 printf("*** Error converting email address to C string\n");
216 }
217 else {
218 printf("%s\n", emailStr);
219 }
220 }
221 if(parseSignerCert) {
222 SecCertificateRef signer;
223 signer = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL);
224 if(signer) {
225 CSSM_DATA certData;
226 ortn = SecCertificateGetData(signer, &certData);
227 if(ortn) {
228 fprintf(stderr, "***Error getting signing cert data***\n");
229 cssmPerror("SecCertificateGetData", ortn);
230 }
231 else {
232 printf("========== Signer Cert==========\n\n");
233 printCert(certData.Data, certData.Length, CSSM_FALSE);
234 printf("========== End Signer Cert==========\n\n");
235 }
236 }
237 else {
238 fprintf(stderr, "***Error getting signing cert ***\n");
239 }
240 }
241 }
242 return ortn;
243 }
244
245 static OSStatus doParse(
246 const unsigned char *data,
247 unsigned dataLen,
248 bool parseSignerCert,
249 unsigned char **outData, // mallocd and RETURNED
250 unsigned *outDataLen) // RETURNED
251 {
252 if((data == NULL) || (dataLen == 0)) {
253 printf("***Parse requires input file. Aborting.\n");
254 return paramErr;
255 }
256
257 SecArenaPoolRef arena = NULL;
258 SecArenaPoolCreate(1024, &arena);
259 SecCmsMessageRef cmsMsg = NULL;
260 SecCmsDecoderRef decoder;
261 OSStatus ortn;
262
263 ortn = SecCmsDecoderCreate(arena, NULL, NULL, NULL, NULL, NULL, NULL, &decoder);
264 if(ortn) {
265 cssmPerror("SecCmsDecoderCreate", ortn);
266 return ortn;
267 }
268 ortn = SecCmsDecoderUpdate(decoder, data, dataLen);
269 if(ortn) {
270 cssmPerror("SecCmsDecoderUpdate", ortn);
271 return ortn;
272 }
273 ortn = SecCmsDecoderFinish(decoder, &cmsMsg);
274 if(ortn) {
275 cssmPerror("SecCmsDecoderFinish", ortn);
276 return ortn;
277 }
278
279 Boolean b = SecCmsMessageIsSigned(cmsMsg);
280 printf("=== CMS message info ===\n");
281 printf(" Signed : %s\n", b ? "true" : "false");
282 b = SecCmsMessageIsEncrypted(cmsMsg);
283 printf(" Encrypted : %s\n", b ? "true" : "false");
284 b = SecCmsMessageContainsCertsOrCrls(cmsMsg);
285 printf(" certs/crls : %s\n", b ? "present" : "not present");
286 int numContentInfos = SecCmsMessageContentLevelCount(cmsMsg);
287 printf(" Num ContentInfos : %d\n", numContentInfos);
288
289 OidParser oidParser;
290 for(int dex=0; dex<numContentInfos; dex++) {
291 SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsMsg, dex);
292 printf(" Content Info %d :\n", dex);
293 CSSM_OID *typeOid = SecCmsContentInfoGetContentTypeOID(ci);
294 printf(" OID Tag : ");
295 if(typeOid == NULL) {
296 printf("***NONE FOUND***]n");
297 }
298 else if(typeOid->Length == 0) {
299 printf("***EMPTY***\n");
300 }
301 else {
302 char str[OID_PARSER_STRING_SIZE];
303 oidParser.oidParse(typeOid->Data, typeOid->Length, str);
304 printf("%s\n", str);
305 }
306 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
307 switch(tag) {
308 case SEC_OID_PKCS7_SIGNED_DATA:
309 {
310 SecCmsSignedDataRef sd =
311 (SecCmsSignedDataRef) SecCmsContentInfoGetContent(ci);
312 parseSignedData(sd, parseSignerCert);
313 break;
314 }
315 case SEC_OID_PKCS7_DATA:
316 case SEC_OID_PKCS7_ENVELOPED_DATA:
317 case SEC_OID_PKCS7_ENCRYPTED_DATA:
318 break;
319 default:
320 printf(" other content type TBD\n");
321 }
322 }
323 if(outData) {
324 CSSM_DATA_PTR odata = SecCmsMessageGetContent(cmsMsg);
325 if(odata == NULL) {
326 printf("***No inner content available\n");
327 }
328 else {
329 *outData = (unsigned char *)malloc(odata->Length);
330 memmove(*outData, odata->Data, odata->Length);
331 *outDataLen = odata->Length;
332 }
333 }
334 if(arena) {
335 SecArenaPoolFree(arena, false);
336 }
337 /* free decoder? cmsMsg? */
338 return noErr;
339 }
340
341 /*
342 * Common encode routine.
343 */
344 #if 0
345 /* the simple way, when 3655861 is fixed */
346 static OSStatus encodeCms(
347 SecCmsMessageRef cmsMsg,
348 const unsigned char *inData, // add in this
349 unsigned inDataLen,
350 unsigned char **outData, // mallocd and RETURNED
351 unsigned *outDataLen) // RETURNED
352 {
353 SecArenaPoolRef arena = NULL;
354 SecArenaPoolCreate(1024, &arena);
355 CSSM_DATA cdataIn = {inDataLen, (uint8 *)inData};
356 CSSM_DATA cdataOut = {0, NULL};
357
358 OSStatus ortn = SecCmsMessageEncode(cmsMsg, &cdataIn, arena, &cdataOut);
359 if((ortn == noErr) && (cdataOut.Length != 0)) {
360 *outData = (unsigned char *)malloc(cdataOut.Length);
361 memmove(*outData, cdataOut.Data, cdataOut.Length);
362 *outDataLen = cdataOut.Length;
363 }
364 else {
365 *outData = NULL;
366 *outDataLen = 0;
367 }
368 SecArenaPoolFree(arena, false);
369 return ortn;
370 }
371
372 #else
373
374 static OSStatus encodeCms(
375 SecCmsMessageRef cmsMsg,
376 const unsigned char *inData, // add in this
377 unsigned inDataLen,
378 unsigned char **outData, // mallocd and RETURNED
379 unsigned *outDataLen) // RETURNED
380 {
381 SecArenaPoolRef arena = NULL;
382 SecArenaPoolCreate(1024, &arena);
383 SecCmsEncoderRef cmsEnc = NULL;
384 CSSM_DATA output = { 0, NULL };
385 OSStatus ortn;
386
387 ortn = SecCmsEncoderCreate(cmsMsg,
388 NULL, NULL, // no callback
389 &output, arena, // data goes here
390 NULL, NULL, // no password callback (right?)
391 NULL, NULL, // decrypt key callback
392 NULL, NULL, // detached digests
393 &cmsEnc);
394 if(ortn) {
395 cssmPerror("SecKeychainItemCopyKeychain", ortn);
396 goto errOut;
397 }
398 ortn = SecCmsEncoderUpdate(cmsEnc, (char *)inData, inDataLen);
399 if(ortn) {
400 cssmPerror("SecCmsEncoderUpdate", ortn);
401 goto errOut;
402 }
403 ortn = SecCmsEncoderFinish(cmsEnc);
404 if(ortn) {
405 cssmPerror("SecCMsEncoderFinish", ortn);
406 goto errOut;
407 }
408
409 /* Did we get any data? */
410 if(output.Length) {
411 *outData = (unsigned char *)malloc(output.Length);
412 memmove(*outData, output.Data, output.Length);
413 *outDataLen = output.Length;
414 }
415 else {
416 *outData = NULL;
417 *outDataLen = 0;
418 }
419 errOut:
420 if(arena) {
421 SecArenaPoolFree(arena, false);
422 }
423 return ortn;
424 }
425
426 #endif
427
428 static OSStatus doSign(
429 SecIdentityRef signerId,
430 const unsigned char *inData,
431 unsigned inDataLen,
432 unsigned char **outData, // mallocd and RETURNED
433 unsigned *outDataLen) // RETURNED
434 {
435 if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) {
436 printf("***Sign requires input file. Aborting.\n");
437 return paramErr;
438 }
439 if(signerId == NULL) {
440 printf("***Sign requires a signing identity. Aborting.\n");
441 return paramErr;
442 }
443
444 SecCmsMessageRef cmsMsg = NULL;
445 SecCmsContentInfoRef contentInfo = NULL;
446 SecCmsSignedDataRef signedData = NULL;
447 SecCertificateRef ourCert = NULL;
448 SecCmsSignerInfoRef signerInfo;
449 OSStatus ortn;
450 SecKeychainRef ourKc = NULL;
451
452 ortn = SecIdentityCopyCertificate(signerId, &ourCert);
453 if(ortn) {
454 cssmPerror("SecIdentityCopyCertificate", ortn);
455 return ortn;
456 }
457 ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)ourCert, &ourKc);
458 if(ortn) {
459 cssmPerror("SecKeychainItemCopyKeychain", ortn);
460 goto errOut;
461 }
462
463 // build chain of objects: message->signedData->data
464 cmsMsg = SecCmsMessageCreate(NULL);
465 if(cmsMsg == NULL) {
466 printf("***Error creating SecCmsMessageRef\n");
467 ortn = -1;
468 goto errOut;
469 }
470 signedData = SecCmsSignedDataCreate(cmsMsg);
471 if(signedData == NULL) {
472 printf("***Error creating SecCmsSignedDataRef\n");
473 ortn = -1;
474 goto errOut;
475 }
476 contentInfo = SecCmsMessageGetContentInfo(cmsMsg);
477 ortn = SecCmsContentInfoSetContentSignedData(cmsMsg, contentInfo, signedData);
478 if(ortn) {
479 cssmPerror("SecCmsContentInfoSetContentSignedData", ortn);
480 goto errOut;
481 }
482 contentInfo = SecCmsSignedDataGetContentInfo(signedData);
483 ortn = SecCmsContentInfoSetContentData(cmsMsg, contentInfo, NULL /* data */, false);
484 if(ortn) {
485 cssmPerror("SecCmsContentInfoSetContentData", ortn);
486 goto errOut;
487 }
488
489 /*
490 * create & attach signer information
491 */
492 signerInfo = SecCmsSignerInfoCreate(cmsMsg, signerId, SEC_OID_SHA1);
493 if (signerInfo == NULL) {
494 printf("***Error on SecCmsSignerInfoCreate\n");
495 ortn = -1;
496 goto errOut;
497 }
498 /* we want the cert chain included for this one */
499 /* FIXME - what's the significance of the usage? */
500 ortn = SecCmsSignerInfoIncludeCerts(signerInfo, SecCmsCMCertChain, certUsageEmailSigner);
501 if(ortn) {
502 cssmPerror("SecCmsSignerInfoIncludeCerts", ortn);
503 goto errOut;
504 }
505
506 /* other options go here - signing time, etc. */
507
508 ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc);
509 if(ortn) {
510 cssmPerror("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn);
511 goto errOut;
512 }
513 ortn = SecCmsSignedDataAddCertificate(signedData, ourCert);
514 if(ortn) {
515 cssmPerror("SecCmsSignedDataAddCertificate", ortn);
516 goto errOut;
517 }
518
519 ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo);
520 if(ortn) {
521 cssmPerror("SecCmsSignedDataAddSignerInfo", ortn);
522 goto errOut;
523 }
524
525 /* go */
526 ortn = encodeCms(cmsMsg, inData, inDataLen, outData, outDataLen);
527 errOut:
528 /* free resources */
529 if(cmsMsg) {
530 SecCmsMessageDestroy(cmsMsg);
531 }
532 if(ourCert) {
533 CFRelease(ourCert);
534 }
535 if(ourKc) {
536 CFRelease(ourKc);
537 }
538 return ortn;
539 }
540
541 static OSStatus doEncrypt(
542 SecCertificateRef recipCert, // eventually more than one
543 const unsigned char *inData,
544 unsigned inDataLen,
545 unsigned char **outData, // mallocd and RETURNED
546 unsigned *outDataLen) // RETURNED
547 {
548 if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) {
549 printf("***Sign requires input file. Aborting.\n");
550 return paramErr;
551 }
552 if(recipCert == NULL) {
553 printf("***Encrypt requires a recipient certificate. Aborting.\n");
554 return paramErr;
555 }
556
557 SecCmsMessageRef cmsMsg = NULL;
558 SecCmsContentInfoRef contentInfo = NULL;
559 SecCmsEnvelopedDataRef envelopedData = NULL;
560 SecCmsRecipientInfoRef recipientInfo = NULL;
561 OSStatus ortn;
562 SecCertificateRef allCerts[2] = { recipCert, NULL};
563
564 SECOidTag algorithmTag;
565 int keySize;
566
567 ortn = SecSMIMEFindBulkAlgForRecipients(allCerts, &algorithmTag, &keySize);
568 if(ortn) {
569 cssmPerror("SecSMIMEFindBulkAlgForRecipients", ortn);
570 return ortn;
571 }
572
573 // build chain of objects: message->envelopedData->data
574 cmsMsg = SecCmsMessageCreate(NULL);
575 if(cmsMsg == NULL) {
576 printf("***Error creating SecCmsMessageRef\n");
577 ortn = -1;
578 goto errOut;
579 }
580 envelopedData = SecCmsEnvelopedDataCreate(cmsMsg, algorithmTag, keySize);
581 if(envelopedData == NULL) {
582 printf("***Error creating SecCmsEnvelopedDataRef\n");
583 ortn = -1;
584 goto errOut;
585 }
586 contentInfo = SecCmsMessageGetContentInfo(cmsMsg);
587 ortn = SecCmsContentInfoSetContentEnvelopedData(cmsMsg, contentInfo, envelopedData);
588 if(ortn) {
589 cssmPerror("SecCmsContentInfoSetContentEnvelopedData", ortn);
590 goto errOut;
591 }
592 contentInfo = SecCmsEnvelopedDataGetContentInfo(envelopedData);
593 ortn = SecCmsContentInfoSetContentData(cmsMsg, contentInfo, NULL /* data */, false);
594 if(ortn) {
595 cssmPerror("SecCmsContentInfoSetContentData", ortn);
596 goto errOut;
597 }
598
599 /*
600 * create & attach recipient information
601 */
602 recipientInfo = SecCmsRecipientInfoCreate(cmsMsg, recipCert);
603 ortn = SecCmsEnvelopedDataAddRecipient(envelopedData, recipientInfo);
604 if(ortn) {
605 cssmPerror("SecCmsEnvelopedDataAddRecipient", ortn);
606 goto errOut;
607 }
608
609
610 /* go */
611 ortn = encodeCms(cmsMsg, inData, inDataLen, outData, outDataLen);
612 errOut:
613 /* free resources */
614 if(cmsMsg) {
615 SecCmsMessageDestroy(cmsMsg);
616 }
617 return ortn;
618 }
619
620 int main(int argc, char **argv)
621 {
622 if(argc < 2) {
623 usage(argv);
624 }
625
626 CT_Op op;
627 bool needId = false;
628 if(!strcmp(argv[1], "sign")) {
629 op = CTO_Sign;
630 needId = true;
631 }
632 else if(!strcmp(argv[1], "envel")) {
633 op = CTO_Envelop;
634 }
635 else if(!strcmp(argv[1], "parse")) {
636 op = CTO_Parse;
637 }
638 else {
639 printf("***Unrecognized cmd.\n");
640 usage(argv);
641 }
642
643 extern int optind;
644 extern char *optarg;
645 int arg;
646 int ourRtn = 0;
647
648 /* optional args */
649 const char *keychainName = NULL;
650 char *inFileName = NULL;
651 char *outFileName = NULL;
652 bool useIdPicker = false;
653 char *recipient = NULL;
654 bool quiet = false;
655 bool parseSignerCert = false;
656
657 optind = 2;
658 while ((arg = getopt(argc, argv, "i:o:k:pr:qc")) != -1) {
659 switch (arg) {
660 case 'i':
661 inFileName = optarg;
662 break;
663 case 'o':
664 outFileName = optarg;
665 break;
666 case 'k':
667 keychainName = optarg;
668 break;
669 case 'p':
670 useIdPicker = true;
671 break;
672 case 'r':
673 recipient = optarg;
674 break;
675 case 'c':
676 parseSignerCert = true;
677 break;
678 case 'q':
679 quiet = true;
680 break;
681 default:
682 case '?':
683 usage(argv);
684 }
685 }
686 if(optind != argc) {
687 /* getopt does not return '?' */
688 usage(argv);
689 }
690
691 SecIdentityRef idRef = NULL;
692 SecKeychainRef kcRef = NULL;
693 SecCertificateRef recipientCert;
694 unsigned char *inData = NULL;
695 unsigned inDataLen = 0;
696 unsigned char *outData = NULL;
697 unsigned outDataLen = 0;
698 OSStatus ortn;
699
700 if(inFileName) {
701 if(readFile(inFileName, &inData, &inDataLen)) {
702 printf("***Error reading infile %s. Aborting.\n", inFileName);
703 exit(1);
704 }
705 }
706 if(keychainName) {
707 ortn = SecKeychainOpen(keychainName, &kcRef);
708 if(ortn) {
709 cssmPerror("SecKeychainOpen", ortn);
710 exit(1);
711 }
712 }
713 if(useIdPicker) {
714 ortn = sslSimpleIdentPicker(kcRef, &idRef);
715 if(ortn) {
716 printf("Error obtaining idenity via picker. Aborting.\n");
717 exit(1);
718 }
719 }
720 else if(needId) {
721 /* use first identity in specified keychain */
722 CFArrayRef array = sslKcRefToCertArray(kcRef, CSSM_FALSE, CSSM_FALSE, NULL);
723 if(array == NULL) {
724 printf("***Error finding a signing cert. Aborting.\n");
725 exit(1);
726 }
727 idRef = (SecIdentityRef)CFArrayGetValueAtIndex(array, 0);
728 if(idRef == NULL) {
729 printf("***No identities found. Aborting.\n");
730 exit(1);
731 }
732 CFRetain(idRef);
733 CFRelease(array);
734 }
735 if(recipient) {
736 ortn = findCert(recipient, kcRef, &recipientCert);
737 if(ortn) {
738 exit(1);
739 }
740 }
741
742 switch(op) {
743 case CTO_Sign:
744 ortn = doSign(idRef, inData, inDataLen, &outData, &outDataLen);
745 break;
746 case CTO_Envelop:
747 ortn = doEncrypt(recipientCert, inData, inDataLen, &outData, &outDataLen);
748 break;
749 case CTO_Parse:
750 ortn = doParse(inData, inDataLen, parseSignerCert, &outData, &outDataLen);
751 break;
752 }
753 if(ortn) {
754 goto errOut;
755 }
756 if(outData && outFileName) {
757 if(writeFile(outFileName, outData, outDataLen)) {
758 printf("***Error writing to %s.\n", outFileName);
759 }
760 else {
761 printf("...wrote %lu bytes to %s.\n", outDataLen, outFileName);
762 }
763 }
764 else if(outData) {
765 printf("...generated %lu bytes but no place to write it.\n", outDataLen);
766 }
767 else if(outFileName) {
768 printf("...nothing to write to file %s.\n", outFileName);
769 }
770 errOut:
771 return ourRtn;
772 }