+++ /dev/null
-/*
- * cmstool.cpp - manipulate CMS messages, CMSEncoder/CMSDecoder version
- */
-
-#include <Security/Security.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <utilLib/common.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <security_cdsa_utils/cuPrintCert.h>
-#include <clAppUtils/identPicker.h>
-#include <clAppUtils/sslAppUtils.h>
-#include <security_cdsa_utils/cuOidParser.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
-
-#include <Security/SecTrustPriv.h> /* SecTrustGetCssmResultCode */
-#include <Security/SecIdentityPriv.h> /* SecIdentityCreateWithCertificate */
-#include <Security/CMSEncoder.h>
-#include <Security/CMSDecoder.h>
-#include <Security/CMSPrivate.h>
-
-#include <Security/SecCertificate.h>
-#include <Security/oidsattr.h>
-
-#define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); }
-
-static SecKeychainRef keychain_open(const char *name);
-
-static void usage(char **argv)
-{
- printf("Usage: %s cmd [option ...]\n", argv[0]);
- printf("cmd values:\n");
- printf(" sign -- create signedData\n");
- printf(" envel -- create envelopedData\n");
- printf(" signEnv -- create nested EnvelopedData(signedData(data))\n");
- printf(" certs -- create certs-only CMS msg\n");
- printf(" parse -- parse a CMS message file\n");
- printf("Input/output options:\n");
- printf(" -i infile\n");
- printf(" -o outfile\n");
- printf(" -D detachedContent -- detached content (parse only)\n");
- printf(" -d detached -- infile contains detached content (sign only)\n");
- printf(" -f certFileBase -- dump all certs to certFileBase\n");
- printf("Signer and recipient options:\n");
- printf(" -k keychain -- Keychain to search for certs\n");
- printf(" -p -- Use identity picker\n");
- printf(" -r recipient -- add recipient (via email address) of enveloped data\n");
- printf(" -R recipCertFile -- add recipient (via cert from file) of enveloped data\n");
- printf(" -S signerEmail -- add signer email address\n");
- printf(" -C cert -- add (general) signedData cert\n");
- printf("Misc. options:\n");
- printf(" -e eContentType -- a(uthData)|r(keyData)\n");
- printf(" -m -- multi updates; default is one-shot\n");
- printf(" -1 (one) -- custom encoder/decoder\n");
- printf(" -2 -- fetch SecCmsMessageRef\n");
- printf(" -c -- parse signer certs\n");
- printf(" -a [ceEt] -- Signed Attributes: c=SmimeCaps,\n");
- printf(" e=EncrPrefs, E=MSEncrPrefs, t=signingTime\n");
- printf(" -A anchorFile -- Verify certs using specified anchor cert\n");
- printf(" -M -- Do SecTrustEvaluate manually\n");
- printf(" -t certChainMode -- none|signer|chain|chainWithRoot; default is chain\n");
- printf(" -l -- loop & pause for malloc debug\n");
- printf(" -q -- quiet\n");
- printf(" -Z -- silent, no output at all except for errors\n");
- printf("Verification options:\n");
- printf(" -v sign|encr|signEnv -- verify message is signed/encrypted/both\n");
- printf(" -s numSigners -- verify msg has specified number of signers\n");
- printf(" -E eContentType -- verify a(authData)|r(keyData)|d(data)\n");
- printf(" -N numCerts -- verify number of certs\n");
- exit(1);
-}
-
-/* high level op */
-typedef enum {
- CTO_Sign,
- CTO_Envelop,
- CTO_SignEnvelop,
- CTO_CertsOnly,
- CTO_Parse
-} CT_Op;
-
-/* to verify */
-typedef enum {
- CTV_None,
- CTV_Sign,
- CTV_Envelop,
- CTV_SignEnvelop
-} CT_Vfy;
-
-/* additional OIDS to specify as eContentType */
-#define OID_PKINIT 0x2B, 6, 1, 5, 2, 3
-#define OID_PKINIT_LEN 6
-
-static const uint8 OID_PKINIT_AUTH_DATA[] = {OID_PKINIT, 1};
-static const uint8 OID_PKINIT_DH_KEY_DATA[] = {OID_PKINIT, 2};
-static const uint8 OID_PKINIT_RKEY_DATA[] = {OID_PKINIT, 3};
-static const uint8 OID_PKINIT_KP_CLIENTAUTH[] = {OID_PKINIT, 3};
-static const uint8 OID_PKINIT_KPKDC[] = {OID_PKINIT, 5};
-
-static const CSSM_OID CSSMOID_PKINIT_AUTH_DATA =
- {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_AUTH_DATA};
-static const CSSM_OID CSSMOID_PKINIT_DH_KEY_DATA =
- {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_DH_KEY_DATA};
-static const CSSM_OID CSSMOID_PKINIT_RKEY_DATA =
- {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_RKEY_DATA};
-static const CSSM_OID CSSMOID_PKINIT_KP_CLIENTAUTH =
- {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_KP_CLIENTAUTH};
-static const CSSM_OID CSSMOID_PKINIT_KPKDC =
- {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_KPKDC};
-
-/*
- * Find a cert in specified keychain or keychain list matching specified
- * email address. We happen to know that the email address is stored with the
- * kSecAlias attribute.
- */
-static OSStatus findCert(
- const char *emailAddress,
- CFTypeRef kcArArray, // kc, array, or even NULL
- SecCertificateRef *cert)
-{
- OSStatus ortn;
- SecKeychainSearchRef srch;
- SecKeychainAttributeList attrList;
- SecKeychainAttribute attr;
-
- attr.tag = kSecAlias;
- attr.length = strlen(emailAddress);
- attr.data = (void *)emailAddress;
- attrList.count = 1;
- attrList.attr = &attr;
-
- ortn = SecKeychainSearchCreateFromAttributes(kcArArray,
- kSecCertificateItemClass,
- &attrList,
- &srch);
- if(ortn) {
- cssmPerror("SecKeychainSearchCreateFromAttributes", ortn);
- return ortn;
- }
-
- ortn = SecKeychainSearchCopyNext(srch, (SecKeychainItemRef *)cert);
- if(ortn) {
- printf("***No certs found matching recipient %s. Aborting.\n",
- emailAddress);
- return ortn;
- }
- CFRelease(srch);
- return noErr;
-}
-
-/* create a SecCertificateRef from a file */
-static SecCertificateRef readCertFile(
- const char *fileName)
-{
- unsigned char *certData = NULL;
- unsigned certDataLen;
- SecCertificateRef rtnCert = NULL;
-
- if(readFile(fileName, &certData, &certDataLen)) {
- printf("***Error reading %s. Aborting.\n", fileName);
- return NULL;
- }
- CSSM_DATA cssmCert = {certDataLen, (uint8 *)certData};
- OSStatus ortn = SecCertificateCreateFromData(&cssmCert,
- CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER,
- &rtnCert);
- if(ortn) {
- cssmPerror("SecCertificateCreateFromData", ortn);
- printf("***Error creating cert fromn %s. Aborting.\n", fileName);
- }
- free(certData);
- return rtnCert;
-}
-
-static int dumpCertFiles(
- CFArrayRef allCerts,
- const char *fileBase,
- bool quiet)
-{
- char fileName[200];
-
- if(allCerts == NULL) {
- printf("...no certs to write.\n");
- return 0;
- }
- CFIndex numCerts = CFArrayGetCount(allCerts);
- if(numCerts == 0) {
- printf("...no certs to write.\n");
- return 0;
- }
- for(CFIndex dex=0; dex<numCerts; dex++) {
- SecCertificateRef secCert =
- (SecCertificateRef)CFArrayGetValueAtIndex(allCerts, dex);
- CSSM_DATA certData;
- OSStatus ortn;
-
- ortn = SecCertificateGetData(secCert, &certData);
- if(ortn) {
- cssmPerror("SecCertificateGetData", ortn);
- return -1;
- }
- sprintf(fileName, "%s_%u.cer", fileBase, (unsigned)dex);
- if(writeFile(fileName, certData.Data, certData.Length)) {
- printf("***Error writing cert data to %s. Aborting.\n", fileName);
- return 1;
- }
- else if(!quiet) {
- printf("...wrote %u bytes to %s.\n",
- (unsigned)certData.Length, fileName);
- }
- }
- return 0;
-}
-
-/*
- * Do a random number of random-sized updates on a CMSEncoder.
- */
-static OSStatus updateEncoder(
- CMSEncoderRef cmsEncoder,
- const unsigned char *inData,
- unsigned inDataLen)
-{
- unsigned toMove = inDataLen;
- unsigned thisMove;
-
- while(toMove != 0) {
- thisMove = genRand(1, toMove);
- OSStatus ortn = CMSEncoderUpdateContent(cmsEncoder, inData, thisMove);
- if(ortn) {
- cssmPerror("CMSEncoderUpdateContent", ortn);
- return ortn;
- }
- toMove -= thisMove;
- inData += thisMove;
- }
- return noErr;
-}
-
-/*
- * Do a random number of random-sized updates on a CMSDecoder.
- */
-static OSStatus updateDecoder(
- CMSDecoderRef cmsDecoder,
- const unsigned char *inData,
- unsigned inDataLen)
-{
- unsigned toMove = inDataLen;
- unsigned thisMove;
-
- while(toMove != 0) {
- thisMove = genRand(1, toMove);
- OSStatus ortn = CMSDecoderUpdateMessage(cmsDecoder, inData, thisMove);
- if(ortn) {
- cssmPerror("CMSDecoderUpdateMessage", ortn);
- return ortn;
- }
- toMove -= thisMove;
- inData += thisMove;
- }
- return noErr;
-}
-
-#define TRUST_STRING_MAX 128
-
-static OSStatus evalSecTrust(
- SecTrustRef secTrust,
- CFMutableArrayRef anchorArray, // optional
- char *trustStr, // caller-mallocd, TRUST_STRING_MAX chars
- bool quiet)
-{
- OSStatus ortn;
- SecTrustResultType secTrustResult;
-
- if(anchorArray) {
- ortn = SecTrustSetAnchorCertificates(secTrust, anchorArray);
- if(ortn) {
- /* should never happen */
- cssmPerror("SecTrustSetAnchorCertificates", ortn);
- return ortn;
- }
- }
- ortn = SecTrustEvaluate(secTrust, &secTrustResult);
- if(ortn) {
- /* should never happen */
- cssmPerror("SecTrustEvaluate", ortn);
- return ortn;
- }
- switch(secTrustResult) {
- case kSecTrustResultUnspecified:
- /* cert chain valid, no special UserTrust assignments */
- case kSecTrustResultProceed:
- /* cert chain valid AND user explicitly trusts this */
- sprintf(trustStr, "Successful\n");
- return noErr;
- case kSecTrustResultDeny:
- case kSecTrustResultConfirm:
- /*
- * Cert chain may well have verified OK, but user has flagged
- * one of these certs as untrustable.
- */
- sprintf(trustStr, "Not trusted per user-specified Trust level\n");
- /* bogus return code I know */
- return errSecInvalidTrustSetting;
- default:
- {
- /* get low-level TP error */
- OSStatus tpStatus;
- ortn = SecTrustGetCssmResultCode(secTrust, &tpStatus);
- if(ortn) {
- cssmPerror("SecTrustGetCssmResultCode", ortn);
- return ortn;
- }
- switch(tpStatus) {
- case CSSMERR_TP_INVALID_ANCHOR_CERT:
- sprintf(trustStr, "Untrusted root\n");
- break;
- case CSSMERR_TP_NOT_TRUSTED:
- /* no root, not even in implicit SSL roots */
- sprintf(trustStr, "No root cert found\n");
- break;
- case CSSMERR_TP_CERT_EXPIRED:
- sprintf(trustStr, "Expired cert\n");
- break;
- case CSSMERR_TP_CERT_NOT_VALID_YET:
- sprintf(trustStr, "Cert not valid yet\n");
- break;
- default:
- sprintf(trustStr, "Other cert failure (%s)",
- cssmErrToStr(tpStatus));
- break;
- }
- return tpStatus;
- }
- } /* SecTrustEvaluate error */
- /* NOT REACHED */
-}
-
-static OSStatus doParse(
- const unsigned char *data,
- unsigned dataLen,
- const unsigned char *detachedContent,
- unsigned detachedContentLen,
- bool multiUpdate,
- CT_Vfy vfyOp,
- const CSSM_OID *eContentVfy, // optional to verify
- int numSignersVfy, // optional (>=0) to verify
- int numCertsVfy, // optionjal (>= 0) to verify
- bool parseSignerCert,
- const char *certFileBase, // optionally write certs here
- bool customDecoder, // invoke CMSDecoderSetDecoder()
- bool manTrustEval, // evaluate SecTrust ourself
- CFMutableArrayRef anchorArray, // optional, and only for manTrustEval
- bool quiet,
- CFDataRef *outData) // RETURNED
-{
- if((data == NULL) || (dataLen == 0)) {
- fprintf(stderr, "***Parse requires input file. Aborting.\n");
- return paramErr;
- }
-
- CMSDecoderRef cmsDecoder;
- size_t numSigners;
- Boolean isEncrypted;
- CFArrayRef allCerts = NULL;
- unsigned signerDex;
- SecPolicyRef policy = NULL;
- SecPolicySearchRef policySearch = NULL;
- CFIndex numCerts = 0;
- int addDetachedAfterDecode = 0;
- SecArenaPoolRef arena = NULL;
-
- /*
- * Four different return codes:
- * -- ortn used for function returns; if nonzero, bail immediately and goto errOut
- * -- ourRtn is manually set per the output of CMSDecoderCopySignerStatus and
- * evalSecTrust
- * -- trustRtn is the output of manual SecTrustEvaluate (via evalSecTrust())
- * -- vfyErr indicates mismatch in caller-specified error params
- *
- * All four have to be zero fgor us to return zero.
- */
- OSStatus ourRtn = noErr;
- OSStatus ortn = noErr;
- OSStatus trustRtn = noErr;
- int vfyErr = 0;
-
- ortn = CMSDecoderCreate(&cmsDecoder);
- if(ortn) {
- cssmPerror("CMSDecoderCreate", ortn);
- return ortn;
- }
-
- /* subsequent errors to errOut: */
-
- if(detachedContent != NULL) {
- /*
- * We can add detached content either before or after the
- * update/finalize; to test and verify, flip a coin to decide
- * when to do it.
- */
- addDetachedAfterDecode = genRand(0, 1);
- if(!addDetachedAfterDecode) {
- CFDataRef cfDetach = CFDataCreate(NULL, detachedContent, detachedContentLen);
- ortn = CMSDecoderSetDetachedContent(cmsDecoder, cfDetach);
- CFRelease(cfDetach);
- if(ortn) {
- cssmPerror("CMSDecoderSetDetachedContent", ortn);
- goto errOut;
- }
- }
- }
-
- if(customDecoder) {
- /* Create a decoder; we don't have to free it, but we do have to free the
- * arena pool */
- SecCmsDecoderRef coder = NULL;
-
- ortn = SecArenaPoolCreate(1024, &arena);
- if(ortn) {
- cssmPerror("SecArenaPoolCreate", ortn);
- goto errOut;
- }
- ortn = SecCmsDecoderCreate(arena,
- NULL, NULL, NULL, NULL, NULL, NULL, &coder);
- if(ortn) {
- cssmPerror("SecCmsDecoderCreate", ortn);
- goto errOut;
- }
- ortn = CMSDecoderSetDecoder(cmsDecoder, coder);
- if(ortn) {
- cssmPerror("CMSDecoderSetDecoder", ortn);
- goto errOut;
- }
- else if(!quiet) {
- printf("...set up custom SecCmsDecoderRef\n");
- }
- }
- if(multiUpdate) {
- ortn = updateDecoder(cmsDecoder, data, dataLen);
- if(ortn) {
- goto errOut;
- }
- }
- else {
- ortn = CMSDecoderUpdateMessage(cmsDecoder, data, dataLen);
- if(ortn) {
- cssmPerror("CMSDecoderUpdateMessage", ortn);
- goto errOut;
- }
- }
- ortn = CMSDecoderFinalizeMessage(cmsDecoder);
- if(ortn) {
- cssmPerror("CMSDecoderFinalizeMessage", ortn);
- goto errOut;
- }
- if(addDetachedAfterDecode) {
- CFDataRef cfDetach = CFDataCreate(NULL, detachedContent, detachedContentLen);
- ortn = CMSDecoderSetDetachedContent(cmsDecoder, cfDetach);
- CFRelease(cfDetach);
- if(ortn) {
- cssmPerror("CMSDecoderSetDetachedContent", ortn);
- goto errOut;
- }
- }
- ortn = CMSDecoderGetNumSigners(cmsDecoder, &numSigners);
- if(ortn) {
- cssmPerror("CMSDecoderGetNumSigners", ortn);
- goto errOut;
- }
- ortn = CMSDecoderIsContentEncrypted(cmsDecoder, &isEncrypted);
- if(ortn) {
- cssmPerror("CMSDecoderIsContentEncrypted", ortn);
- goto errOut;
- }
- ortn = CMSDecoderCopyAllCerts(cmsDecoder, &allCerts);
- if(ortn) {
- cssmPerror("CMSDecoderCopyAllCerts", ortn);
- goto errOut;
- }
- if(allCerts) {
- numCerts = CFArrayGetCount(allCerts);
- }
-
- /* optional verify of expected message type */
- switch(vfyOp) {
- case CTV_None:
- break;
- case CTV_Sign:
- if((numSigners == 0) && (allCerts == NULL)) {
- fprintf(stderr, "***Expected SignedData, but no signersFound\n");
- vfyErr = 1;
- /* but keep going */
- }
- if(isEncrypted) {
- fprintf(stderr, "***Expected SignedData, but msg IS encrypted\n");
- vfyErr = 1;
- }
- break;
- case CTV_SignEnvelop:
- if(numSigners == 0) {
- fprintf(stderr, "***Expected Signed&Enveloped, but no signersFound\n");
- vfyErr = 1;
- }
- if(!isEncrypted) {
- fprintf(stderr, "***Expected Signed&Enveloped, but msg not encrypted\n");
- vfyErr = 1;
- }
- break;
- case CTV_Envelop:
- if(numSigners != 0) {
- fprintf(stderr, "***Expected EnvelopedData, but signers found\n");
- vfyErr = 1;
- }
- if(!isEncrypted) {
- fprintf(stderr, "***Expected EnvelopedData, but msg not encrypted\n");
- vfyErr = 1;
- }
- break;
- }
-
- if(numSignersVfy >= 0) {
- if((unsigned)numSignersVfy != numSigners) {
- fprintf(stderr, "***Expected %d signers; found %lu\n",
- numSignersVfy, numSigners);
- vfyErr = 1;
- }
- }
- if(numCertsVfy >= 0) {
- if((int)numCerts != numCertsVfy) {
- fprintf(stderr, "***Expected %d certs; found %d\n",
- numCertsVfy, (int)numCerts);
- vfyErr = 1;
- }
- }
- if(!quiet) {
- fprintf(stderr, "=== CMS message info ===\n");
- fprintf(stderr, " Num Signers : %lu\n", (unsigned long)numSigners);
- fprintf(stderr, " Encrypted : %s\n", isEncrypted ? "true" : "false");
- fprintf(stderr, " Num Certs : %lu\n",
- allCerts ? (unsigned long)CFArrayGetCount(allCerts) : 0);
- }
-
- if((certFileBase != NULL) & (allCerts != NULL)) {
- dumpCertFiles(allCerts, certFileBase, quiet);
- }
-
-
- if(numSigners) {
- CSSM_OID eContentType = {0, NULL};
- CFDataRef eContentData = NULL;
- OidParser oidParser;
- char str[OID_PARSER_STRING_SIZE];
-
- ortn = CMSDecoderCopyEncapsulatedContentType(cmsDecoder, &eContentData);
- if(ortn) {
- cssmPerror("CMSDecoderCopyEncapsulatedContentType", ortn);
- goto errOut;
- }
- if(eContentData != NULL) {
- eContentType.Data = (uint8 *)CFDataGetBytePtr(eContentData);
- eContentType.Length = CFDataGetLength(eContentData);
- }
- if(!quiet) {
- /* can't use stderr - oidparser is fixed w/stdout */
- printf(" eContentType : ");
- if(eContentType.Data == NULL) {
- printf("***NONE FOUND***\n");
- }
- else if(eContentType.Length == 0) {
- printf("***EMPTY***\n");
- }
- else {
- oidParser.oidParse(eContentType.Data, eContentType.Length, str);
- printf("%s\n", str);
- }
- }
-
- if(eContentVfy != NULL) {
- if(eContentType.Data == NULL) {
- fprintf(stderr, "***Tried to verify eContentType, but none found\n");
- vfyErr = 1;
- }
- else if(!appCompareCssmData(eContentVfy, &eContentType)) {
- fprintf(stderr, "***eContentType verify error\n");
- fprintf(stderr, " Expected: ");
- oidParser.oidParse(eContentVfy->Data, eContentVfy->Length, str);
- printf("%s\n", str);
- fprintf(stderr, " Found : ");
- oidParser.oidParse(eContentType.Data, eContentType.Length, str);
- printf("%s\n", str);
- vfyErr = 1;
- }
- }
- CFRELEASE(eContentData);
-
- /* get a policy for cert evaluation */
- ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
- &CSSMOID_APPLE_X509_BASIC,
- NULL,
- &policySearch);
- if(ortn) {
- cssmPerror("SecPolicySearchCreate", ortn);
- goto errOut;
- }
- ortn = SecPolicySearchCopyNext(policySearch, &policy);
- if(ortn) {
- cssmPerror("SecPolicySearchCopyNext", ortn);
- goto errOut;
- }
- }
- for(signerDex=0; signerDex<numSigners; signerDex++) {
- CMSSignerStatus signerStatus = kCMSSignerInvalidIndex;
- SecCertificateRef signerCert;
- CFStringRef signerEmailAddress;
- SecTrustRef secTrust;
- OSStatus certVerifyResultCode;
- char trustStr[TRUST_STRING_MAX];
-
- ortn = CMSDecoderCopySignerStatus(cmsDecoder, signerDex,
- policy,
- manTrustEval ? FALSE : TRUE, /* evaluateSecTrust */
- &signerStatus,
- &secTrust,
- &certVerifyResultCode);
- if(ortn) {
- cssmPerror("CMSDecoderCopySignerStatus", ortn);
- goto errOut;
- }
- if(ourRtn == noErr) {
- if((signerStatus != kCMSSignerValid) ||
- (certVerifyResultCode != CSSM_OK)) {
- ourRtn = -1;
- }
- }
- ortn = CMSDecoderCopySignerEmailAddress(cmsDecoder, signerDex,
- &signerEmailAddress);
- if(ortn) {
- cssmPerror("CMSDecoderCopySignerEmailAddress", ortn);
- goto errOut;
- }
- ortn = CMSDecoderCopySignerCert(cmsDecoder, signerDex,
- &signerCert);
- if(ortn) {
- cssmPerror("CMSDecoderCopySignerCertificate", ortn);
- goto errOut;
- }
- if(manTrustEval) {
- trustRtn = evalSecTrust(secTrust, anchorArray, trustStr, quiet);
- }
-
- /* display nothing here if quiet true and status is copacetic */
- if(!quiet || (signerStatus != kCMSSignerValid) || (trustRtn != noErr)) {
- fprintf(stderr, " Signer %u:\n", signerDex);
- fprintf(stderr, " signerStatus : ");
- switch(signerStatus) {
- case kCMSSignerUnsigned:
- fprintf(stderr, "kCMSSignerUnsigned\n"); break;
- case kCMSSignerValid:
- fprintf(stderr, "kCMSSignerValid\n"); break;
- case kCMSSignerNeedsDetachedContent:
- fprintf(stderr, "kCMSSignerNeedsDetachedContent\n"); break;
- case kCMSSignerInvalidSignature:
- fprintf(stderr, "kCMSSignerInvalidSignature\n"); break;
- case kCMSSignerInvalidCert:
- fprintf(stderr, "kCMSSignerInvalidCert\n"); break;
- case kCMSSignerInvalidIndex:
- fprintf(stderr, "kCMSSignerInvalidIndex\n"); break;
- }
- if(manTrustEval) {
- fprintf(stderr, " Trust Eval : %s\n", trustStr);
- }
- fprintf(stderr, " emailAddrs : ");
- if(signerEmailAddress == NULL) {
- fprintf(stderr, "<<none found>>\n");
- }
- else {
- char emailStr[1000];
- if(!CFStringGetCString(signerEmailAddress,
- emailStr, 1000, kCFStringEncodingASCII)) {
- fprintf(stderr, "<<<Error converting email address to C string>>>\n");
- }
- else {
- fprintf(stderr, "%s\n", emailStr);
- }
- }
-
- fprintf(stderr, " vfyResult : %s\n",
- certVerifyResultCode ?
- cssmErrToStr(certVerifyResultCode) : "Success");
-
- /* TBD: optionally manually verify the SecTrust object */
-
- if(parseSignerCert) {
-
- if(signerCert == NULL) {
- fprintf(stderr, " <<<Unable to obtain signer cert>>>\n");
- }
- else {
- CSSM_DATA certData;
- ortn = SecCertificateGetData(signerCert, &certData);
- if(ortn) {
- fprintf(stderr, " <<<Unable to obtain signer cert>>>\n");
- cssmPerror("SecCertificateGetData", ortn);
- }
- else {
- printf("========== Signer Cert==========\n\n");
- printCert(certData.Data, certData.Length, CSSM_FALSE);
- printf("========== End Signer Cert==========\n\n");
- }
- }
- } /* parseSignerCert */
- } /* displaying per-signer info */
-
- CFRELEASE(signerCert);
- signerCert = NULL;
- CFRELEASE(signerEmailAddress);
- signerEmailAddress = NULL;
- CFRELEASE(secTrust);
- secTrust = NULL;
- } /* for signerDex */
-
- if(ortn == noErr) {
- ortn = CMSDecoderCopyContent(cmsDecoder, outData);
- if(ortn) {
- cssmPerror("CMSDecoderCopyContent", ortn);
- }
- }
-
-errOut:
- CFRelease(cmsDecoder);
- if(arena != NULL) {
- SecArenaPoolFree(arena, false);
- }
-
- CFRELEASE(allCerts);
- CFRELEASE(policySearch);
- CFRELEASE(policy);
- if(ourRtn) {
- return ourRtn;
- }
- else if(trustRtn) {
- return trustRtn;
- }
- else if(vfyErr) {
- return vfyErr;
- }
- else {
- return ortn;
- }
-}
-
-static OSStatus doSign(
- CFTypeRef signerOrArray,
- const unsigned char *inData,
- unsigned inDataLen,
- bool multiUpdate,
- bool detachedContent,
- const CSSM_OID *eContentType, // OPTIONAL
- CMSSignedAttributes attrs,
- CFTypeRef otherCerts, // OPTIONAL
- bool customCoder,
- bool getCmsMsg,
- CMSCertificateChainMode chainMode,
- bool quiet,
- CFDataRef *outData) // RETURNED
-{
- if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) {
- fprintf(stderr, "***Sign requires input file. Aborting.\n");
- return paramErr;
- }
- if(signerOrArray == NULL) {
- fprintf(stderr, "***Sign requires a signing identity. Aborting.\n");
- return paramErr;
- }
-
- OSStatus ortn;
- CMSEncoderRef cmsEncoder = NULL;
- SecCmsMessageRef msg = NULL; /* for optional CMSEncoderGetCmsMessage */
- SecArenaPoolRef arena = NULL;
- CSSM_DATA encoderOut = {0, NULL};
-
- if(multiUpdate || otherCerts || getCmsMsg || customCoder ||
- (chainMode != kCMSCertificateChain)) {
- /* one-shot encode doesn't support otherCerts or chainOptions*/
-
- ortn = CMSEncoderCreate(&cmsEncoder);
- if(ortn) {
- cssmPerror("CMSEncoderCreate", ortn);
- return ortn;
- }
- /* subsequent errors to errOut: */
- if(signerOrArray != NULL) {
- ortn = CMSEncoderAddSigners(cmsEncoder, signerOrArray);
- if(ortn) {
- goto errOut;
- }
- }
- if(eContentType) {
- ortn = CMSEncoderSetEncapsulatedContentType(cmsEncoder, eContentType);
- if(ortn) {
- goto errOut;
- }
- }
- if(detachedContent) {
- ortn = CMSEncoderSetHasDetachedContent(cmsEncoder, detachedContent);
- if(ortn) {
- goto errOut;
- }
- }
- if(otherCerts) {
- ortn = CMSEncoderAddSupportingCerts(cmsEncoder, otherCerts);
- if(ortn) {
- goto errOut;
- }
- }
- if(attrs) {
- ortn = CMSEncoderAddSignedAttributes(cmsEncoder, attrs);
- if(ortn) {
- goto errOut;
- }
- }
- if(chainMode != kCMSCertificateChain) {
- ortn = CMSEncoderSetCertificateChainMode(cmsEncoder, chainMode);
- if(ortn) {
- goto errOut;
- }
- }
- if(getCmsMsg || customCoder) {
- /*
- * We just want to trigger the state transition
- * that we know should happen. We also might need
- * the msg to create a custom coder.
- */
- ortn = CMSEncoderGetCmsMessage(cmsEncoder, &msg);
- if(ortn) {
- cssmPerror("CMSEncoderGetCmsMessage", ortn);
- goto errOut;
- }
- }
-
- if(customCoder) {
- SecCmsEncoderRef coder = NULL;
- ortn = SecArenaPoolCreate(1024, &arena);
- if(ortn) {
- cssmPerror("SecArenaPoolCreate", ortn);
- goto errOut;
- }
- ortn = SecCmsEncoderCreate(msg,
- NULL, NULL, // no callback
- &encoderOut, // data goes here
- arena,
- NULL, NULL, // no password callback (right?)
- NULL, NULL, // decrypt key callback
- NULL, NULL, // detached digests
- &coder);
- if(ortn) {
- cssmPerror("SecCmsEncoderCreate", ortn);
- goto errOut;
- }
- ortn = CMSEncoderSetEncoder(cmsEncoder, coder);
- if(ortn) {
- cssmPerror("CMSEncoderSetEncoder", ortn);
- goto errOut;
- }
- else if(!quiet) {
- printf("...set up custom SecCmsEncoderRef\n");
- }
- }
- /* random number of random-sized updates */
- ortn = updateEncoder(cmsEncoder, inData, inDataLen);
- if(ortn) {
- goto errOut;
- }
-
- ortn = CMSEncoderCopyEncodedContent(cmsEncoder, outData);
- if(ortn) {
- cssmPerror("CMSEncoderCopyEncodedContent", ortn);
- }
- if(customCoder) {
- /* we have the data right here */
- *outData = CFDataCreate(NULL,
- (const UInt8 *)encoderOut.Data, encoderOut.Length);
- }
- }
- else {
- ortn = CMSEncode(signerOrArray,
- NULL, /* recipients */
- eContentType,
- detachedContent,
- attrs,
- inData, inDataLen,
- outData);
- if(ortn) {
- printf("***CMSEncode returned %ld\n", (long)ortn);
- cssmPerror("CMSEncode", ortn);
- }
- }
-errOut:
- if(cmsEncoder) {
- CFRelease(cmsEncoder);
- }
- if(arena) {
- SecArenaPoolFree(arena, false);
- }
- return ortn;
-}
-
-static OSStatus doEncrypt(
- CFTypeRef recipOrArray,
- const unsigned char *inData,
- unsigned inDataLen,
- bool multiUpdate,
- CFDataRef *outData) // RETURNED
-{
- if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) {
- fprintf(stderr, "***Encrypt requires input file. Aborting.\n");
- return paramErr;
- }
- if(recipOrArray == NULL) {
- fprintf(stderr, "***Encrypt requires a recipient certificate. Aborting.\n");
- return paramErr;
- }
-
- OSStatus ortn;
- CMSEncoderRef cmsEncoder = NULL;
-
- if(multiUpdate) {
- ortn = CMSEncoderCreate(&cmsEncoder);
- if(ortn) {
- cssmPerror("CMSEncoderCreate", ortn);
- return ortn;
- }
- /* subsequent errors to errOut: */
- ortn = CMSEncoderAddRecipients(cmsEncoder, recipOrArray);
- if(ortn) {
- goto errOut;
- }
-
- /* random number of random-sized updates */
- ortn = updateEncoder(cmsEncoder, inData, inDataLen);
- if(ortn) {
- goto errOut;
- }
- ortn = CMSEncoderCopyEncodedContent(cmsEncoder, outData);
- if(ortn) {
- cssmPerror("CMSEncoderCopyEncodedContent", ortn);
- }
- }
- else {
- /* one-shot */
- ortn = CMSEncode(NULL, /* signers */
- recipOrArray,
- NULL, /* eContentType */
- FALSE, /* detachedContent */
- kCMSAttrNone,
- inData, inDataLen,
- outData);
- if(ortn) {
- printf("***CMSEncode returned %ld\n", (long)ortn);
- cssmPerror("CMSEncode", ortn);
- }
- }
-errOut:
- if(cmsEncoder) {
- CFRelease(cmsEncoder);
- }
- return ortn;
-}
-
-/* create nested message: msg = EnvelopedData(SignedData(inData)) */
-static OSStatus doSignEncrypt(
- CFTypeRef recipOrArray, // encryption recipients
- CFTypeRef signerOrArray, // signers
- const CSSM_OID *eContentType, // OPTIONAL - for signedData
- CMSSignedAttributes attrs,
- const unsigned char *inData,
- unsigned inDataLen,
- bool multiUpdate,
- CFTypeRef otherCerts, // OPTIONAL
- CFDataRef *outData) // RETURNED
-{
- if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) {
- fprintf(stderr, "***Sign/Encrypt requires input file. Aborting.\n");
- return paramErr;
- }
- if(recipOrArray == NULL) {
- fprintf(stderr, "***Sign/Encrypt requires a recipient certificate. Aborting.\n");
- return paramErr;
- }
- if(signerOrArray == NULL) {
- fprintf(stderr, "***Sign/Encrypt requires a signer Identity. Aborting.\n");
- return paramErr;
- }
-
- OSStatus ortn;
- CMSEncoderRef cmsEncoder = NULL;
-
- if(multiUpdate || otherCerts) {
- ortn = CMSEncoderCreate(&cmsEncoder);
- if(ortn) {
- cssmPerror("CMSEncoderCreate", ortn);
- return ortn;
- }
- /* subsequent errors to errOut: */
- ortn = CMSEncoderAddRecipients(cmsEncoder, recipOrArray);
- if(ortn) {
- goto errOut;
- }
- ortn = CMSEncoderAddSigners(cmsEncoder, signerOrArray);
- if(ortn) {
- goto errOut;
- }
- if(eContentType) {
- ortn = CMSEncoderSetEncapsulatedContentType(cmsEncoder, eContentType);
- if(ortn) {
- goto errOut;
- }
- }
- if(otherCerts) {
- ortn = CMSEncoderAddSupportingCerts(cmsEncoder, otherCerts);
- if(ortn) {
- goto errOut;
- }
- }
- if(attrs) {
- ortn = CMSEncoderAddSignedAttributes(cmsEncoder, attrs);
- if(ortn) {
- goto errOut;
- }
- }
-
- /* random number of random-sized updates */
- ortn = updateEncoder(cmsEncoder, inData, inDataLen);
- if(ortn) {
- goto errOut;
- }
- ortn = CMSEncoderCopyEncodedContent(cmsEncoder, outData);
- if(ortn) {
- cssmPerror("CMSEncoderCopyEncodedContent", ortn);
- }
- }
- else {
- ortn = CMSEncode(signerOrArray,
- recipOrArray,
- eContentType,
- FALSE, /* detachedContent */
- attrs,
- inData, inDataLen,
- outData);
- if(ortn) {
- printf("***CMSEncode returned %ld\n", (long)ortn);
- cssmPerror("CMSEncode", ortn);
- }
- }
-
-errOut:
- if(cmsEncoder) {
- CFRelease(cmsEncoder);
- }
- return ortn;
-}
-
-/*
- * Create a CMS message containing only certs.
- */
-static OSStatus makeCertBag(
- CFTypeRef certsOrArray,
- CFDataRef *outData)
-{
- if(certsOrArray == NULL) {
- printf("***Need some certs to generate this type of message.\n");
- return -1;
- }
-
- OSStatus ortn;
- CMSEncoderRef cmsEncoder = NULL;
-
- ortn = CMSEncoderCreate(&cmsEncoder);
- if(ortn) {
- cssmPerror("CMSEncoderCreate", ortn);
- return ortn;
- }
- /* subsequent errors to errOut: */
- ortn = CMSEncoderAddSupportingCerts(cmsEncoder, certsOrArray);
- if(ortn) {
- goto errOut;
- }
- ortn = CMSEncoderCopyEncodedContent(cmsEncoder, outData);
- if(ortn) {
- cssmPerror("CMSEncoderCopyEncodedContent", ortn);
- }
-errOut:
- CFRelease(cmsEncoder);
- return ortn;
-}
-
-/*
- * Support maintanance of single item or array of them.
- *
- * Given new incoming 'newThing':
- * if both *thingArray and *currThing are NULL
- * *currThing = newThing;
- * done;
- * create *thingArray;
- * add *currThing to *thingArray if present;
- * add newThing to *thingArray;
- */
-static void addThing(
- CFTypeRef newThing,
- CFTypeRef *currThing,
- CFMutableArrayRef *thingArray)
-{
- if((*currThing == NULL) && (*thingArray == NULL)) {
- /* first occurrence of a thing */
- *currThing = newThing;
- return;
- }
-
- /* at least two things - prepare array */
- if(*thingArray == NULL) {
- *thingArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- }
- if(*currThing != NULL) {
- /* move current thing to array */
- CFArrayAppendValue(*thingArray, *currThing);
- CFRelease(*currThing);
- *currThing = NULL;
- }
- CFArrayAppendValue(*thingArray, newThing);
- CFRelease(newThing);
-}
-
-int main(int argc, char **argv)
-{
- if(argc < 2) {
- usage(argv);
- }
-
- CT_Op op;
- bool needId = false;
- if(!strcmp(argv[1], "sign")) {
- op = CTO_Sign;
- needId = true;
- }
- else if(!strcmp(argv[1], "envel")) {
- op = CTO_Envelop;
- }
- else if(!strcmp(argv[1], "signEnv")) {
- op = CTO_SignEnvelop;
- needId = true;
- }
- else if(!strcmp(argv[1], "certs")) {
- op = CTO_CertsOnly;
- }
- else if(!strcmp(argv[1], "parse")) {
- op = CTO_Parse;
- }
- else {
- fprintf(stderr, "***Unrecognized cmd.\n");
- usage(argv);
- }
-
- extern int optind;
- extern char *optarg;
- int arg;
- OSStatus ortn;
-
- /* optional args */
- char *inFileName = NULL;
- char *outFileName = NULL;
- bool detachedContent = false;
- char *detachedFile = NULL;
- bool useIdPicker = false;
- bool quiet = false;
- bool silent = false;
- bool parseSignerCert = false;
- const CSSM_OID *eContentType = NULL;
- bool multiUpdate = false;
- bool loopPause = false;
- char *certFileBase = NULL;
- CMSSignedAttributes signedAttrs = 0;
- char *anchorFile = NULL;
- bool manTrustEval = false;
- CMSCertificateChainMode chainMode = kCMSCertificateChain;
-
- /* for verification, usually in quiet/script mode */
- CT_Vfy vfyOp = CTV_None;
- const CSSM_OID *eContentVfy = NULL;
- int numSignersVfy = -1;
- int numCertsVfy = -1;
-
- /* for verifying functions in CMSPrivate.h */
- bool customCoder = false;
- bool fetchSecCmsMsg = false;
-
- /*
- * Signer/recipient items and arrays - use one item if possible,
- * else array (to test both paths)
- */
- SecIdentityRef signerId = NULL;
- CFMutableArrayRef signerArray = NULL;
- SecCertificateRef recipCert = NULL;
- CFMutableArrayRef recipArray = NULL;
- SecCertificateRef generalCert = NULL;
- CFMutableArrayRef generalCertArray = NULL;
- SecKeychainRef kcRef = NULL;
- CFMutableArrayRef anchorArray = NULL;
-
- optind = 2;
- while ((arg = getopt(argc, argv, "i:o:k:pr:R:dD:e:mlqcv:s:E:S:C:f:N:a:A:M12t:Z")) != -1) {
- switch (arg) {
- case 'i':
- inFileName = optarg;
- break;
- case 'o':
- outFileName = optarg;
- break;
- case 'k':
- kcRef = keychain_open(optarg);
- if(!kcRef) {
- // cssmPerror("SecKeychainOpen", ortn);
- exit(1);
- }
- break;
- case 'p':
- useIdPicker = true;
- break;
- case 'r':
- {
- SecCertificateRef newCert = NULL;
- char *recipient = optarg;
- ortn = findCert(recipient, kcRef, &newCert);
- if(ortn) {
- exit(1);
- }
- addThing(newCert, (CFTypeRef *)&recipCert, &recipArray);
- break;
- }
- case 'R':
- {
- SecCertificateRef certRef = readCertFile(optarg);
- if(certRef == NULL) {
- exit(1);
- }
- addThing(certRef, (CFTypeRef *)&recipCert, &recipArray);
- break;
- }
- case 'S':
- {
- SecIdentityRef newId = NULL;
- SecCertificateRef newCert = NULL;
- char *signerEmail = optarg;
-
- /*
- * first find the cert, optionally in the keychain already
- * specified via -k
- */
- ortn = findCert(signerEmail, kcRef, &newCert);
- if(ortn) {
- exit(1);
- }
-
- /* map cert to an identity */
- ortn = SecIdentityCreateWithCertificate(kcRef, newCert, &newId);
- if(ortn) {
- cssmPerror("SecIdentityCreateWithCertificate", ortn);
- exit(1);
- }
-
- addThing(newId, (CFTypeRef *)&signerId, &signerArray);
- CFRelease(newCert);
- break;
- }
- case 'C':
- {
- SecCertificateRef newCert = readCertFile(optarg);
- if(newCert == NULL) {
- exit(1);
- }
- addThing(newCert, (CFTypeRef *)&generalCert, &generalCertArray);
- break;
- }
- case 'c':
- parseSignerCert = true;
- break;
- case 'v':
- if(!strcmp(optarg, "sign")) {
- vfyOp = CTV_Sign;
- }
- else if(!strcmp(optarg, "encr")) {
- vfyOp = CTV_Envelop;
- }
- else if(!strcmp(optarg, "signEnv")) {
- vfyOp = CTV_SignEnvelop;
- }
- else {
- usage(argv);
- }
- break;
- case 'e':
- switch(optarg[0]) {
- case 'a':
- eContentType = &CSSMOID_PKINIT_AUTH_DATA;
- break;
- case 'r':
- eContentType = &CSSMOID_PKINIT_RKEY_DATA;
- break;
- default:
- usage(argv);
- }
- break;
- case 'E':
- switch(optarg[0]) {
- case 'a':
- eContentVfy = &CSSMOID_PKINIT_AUTH_DATA;
- break;
- case 'r':
- eContentVfy = &CSSMOID_PKINIT_RKEY_DATA;
- break;
- case 'd':
- eContentVfy = &CSSMOID_PKCS7_Data;
- break;
- default:
- usage(argv);
- }
- break;
- case 'd':
- if(op != CTO_Sign) {
- printf("-d only valid for op sign\n");
- exit(1);
- }
- detachedContent = true;
- break;
- case 'D':
- if(op != CTO_Parse) {
- printf("-D only valid for op sign\n");
- exit(1);
- }
- detachedFile = optarg;
- break;
- case 'l':
- loopPause = true;
- break;
- case 'm':
- multiUpdate = true;
- break;
- case 's':
- numSignersVfy = atoi(optarg);
- break;
- case 'f':
- certFileBase = optarg;
- break;
- case 'N':
- numCertsVfy = atoi(optarg);
- break;
- case '1':
- customCoder = true;
- break;
- case '2':
- fetchSecCmsMsg = true;
- break;
- case 'a':
- for(; *optarg; optarg++) {
- switch(*optarg) {
- case 'c':
- signedAttrs |= kCMSAttrSmimeCapabilities;
- break;
- case 'e':
- signedAttrs |= kCMSAttrSmimeEncryptionKeyPrefs;
- break;
- case 'E':
- signedAttrs |= kCMSAttrSmimeMSEncryptionKeyPrefs;
- break;
- case 't':
- signedAttrs |= kCMSAttrSigningTime;
- break;
- default:
- usage(argv);
- }
- }
- break;
- case 'A':
- anchorFile = optarg;
- break;
- case 'M':
- manTrustEval = true;
- break;
- case 't':
- if(!strcmp(optarg, "none")) {
- chainMode = kCMSCertificateNone;
- }
- else if(!strcmp(optarg, "signer")) {
- chainMode = kCMSCertificateSignerOnly;
- }
- else if(!strcmp(optarg, "chain")) {
- chainMode = kCMSCertificateChain;
- }
- else if(!strcmp(optarg, "chainWithRoot")) {
- chainMode = kCMSCertificateChainWithRoot;
- }
- else {
- printf("***Bogus cert chain spec***\n");
- usage(argv);
- }
- break;
- case 'q':
- quiet = true;
- break;
- case 'Z':
- quiet = true;
- silent = true;
- break;
- default:
- case '?':
- usage(argv);
- }
- }
- if(optind != argc) {
- /* getopt does not return '?' */
- usage(argv);
- }
-
- unsigned char *inData = NULL;
- unsigned inDataLen = 0;
- unsigned char *detachedData = NULL;
- unsigned detachedDataLen = 0;
- CFDataRef outData = NULL;
- CFIndex byteCount = 0;
- if(!silent) {
- testStartBanner((char *)"newCmsTool", argc, argv);
- }
-
- if(inFileName) {
- if(readFile(inFileName, &inData, &inDataLen)) {
- fprintf(stderr, "***Error reading infile %s. Aborting.\n", inFileName);
- exit(1);
- }
- }
- if(detachedFile) {
- if(readFile(detachedFile, &detachedData, &detachedDataLen)) {
- fprintf(stderr, "***Error reading detachedFile %s. Aborting.\n", detachedFile);
- exit(1);
- }
- }
-
- /* signer IDs */
- if(useIdPicker) {
- ortn = sslSimpleIdentPicker(kcRef, &signerId);
- if(ortn) {
- fprintf(stderr, "***Error obtaining identity via picker. Aborting.\n");
- exit(1);
- }
- }
- if(anchorFile) {
- SecCertificateRef secCert = readCertFile(anchorFile);
- if(secCert == NULL) {
- exit(1);
- }
- anchorArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- CFArrayAppendValue(anchorArray, secCert);
- CFRelease(secCert);
- }
-
- /*
- * In order for signed blobs to contain a full cert chain, and to find
- * certs matching a specific recipient cert email address, the keychain
- * containing intermediates must be in the user's keychain search list
- * (or, alternatively, the intermedaite certs must be added manually).
- * To alleviate the burden on test scripts, we'll ensure that an optionally
- * specified keychain is in factin the search list when we sign a message
- * here.
- * Careful - make sure to ALWAYS restore the search list!
- */
- CFArrayRef originalSearchList = NULL;
- if(kcRef != NULL) {
- ortn = SecKeychainCopySearchList(&originalSearchList);
- if(ortn) {
- cssmPerror("SecKeychainCopySearchList", ortn);
- exit(1);
- }
- CFMutableArrayRef newList = CFArrayCreateMutableCopy(
- NULL, 0, originalSearchList);
- CFArrayAppendValue(newList, kcRef);
- ortn = SecKeychainSetSearchList(newList);
- if(ortn) {
- cssmPerror("SecKeychainSetSearchList", ortn);
- exit(1);
- }
- /* DO NOT EXIT WITHOUT RESTORING TO originalSearchList */
- }
- do {
- switch(op) {
- case CTO_Sign:
- ortn = doSign((signerArray != NULL) ?
- (CFTypeRef)signerArray : (CFTypeRef)signerId,
- inData, inDataLen,
- multiUpdate, detachedContent, eContentType, signedAttrs,
- (generalCertArray != NULL) ?
- (CFTypeRef)generalCertArray : (CFTypeRef)generalCert,
- customCoder, fetchSecCmsMsg, chainMode, quiet,
- &outData);
- break;
- case CTO_Envelop:
- ortn = doEncrypt(recipArray ?
- (CFTypeRef)recipArray : (CFTypeRef)recipCert,
- inData, inDataLen,
- multiUpdate, &outData);
- break;
- case CTO_SignEnvelop:
- ortn = doSignEncrypt(recipArray ?
- (CFTypeRef)recipArray : (CFTypeRef)recipCert,
- signerArray ?
- (CFTypeRef)signerArray : (CFTypeRef)signerId,
- eContentType, signedAttrs,
- inData, inDataLen, multiUpdate,
- (generalCertArray != NULL) ?
- (CFTypeRef)generalCertArray : (CFTypeRef)generalCert,
- &outData);
- break;
- case CTO_CertsOnly:
- ortn = makeCertBag((generalCertArray != NULL) ?
- (CFTypeRef)generalCertArray : (CFTypeRef)generalCert,
- &outData);
- break;
- case CTO_Parse:
- ortn = doParse(inData, inDataLen,
- detachedData, detachedDataLen,
- multiUpdate,
- vfyOp, eContentVfy, numSignersVfy, numCertsVfy,
- parseSignerCert, certFileBase, customCoder,
- manTrustEval, anchorArray,
- quiet, &outData);
- break;
- }
-
- if(loopPause) {
- if(outData) {
- printf("...generated %u bytes of data.\n",
- (unsigned)CFDataGetLength(outData));
- }
- fpurge(stdin);
- printf("q to quit, anything else to loop again: ");
- char resp = getchar();
- if(resp == 'q') {
- break;
- }
- else {
- CFRELEASE(outData);
- outData = NULL;
- }
- }
- } while (loopPause);
-
- if(originalSearchList) {
- ortn = SecKeychainSetSearchList(originalSearchList);
- if(ortn) {
- cssmPerror("SecKeychainSetSearchList", ortn);
- /* keep going */
- }
- }
-
- if(ortn) {
- goto errOut;
- }
-
- byteCount = outData ? CFDataGetLength(outData) : 0;
- if(outData && outFileName) {
- if(writeFile(outFileName, CFDataGetBytePtr(outData), byteCount)) {
- fprintf(stderr, "***Error writing to %s.\n", outFileName);
- ortn = -1;
- }
- else {
- if(!quiet) {
- fprintf(stderr, "...wrote %u bytes to %s.\n",
- (unsigned)byteCount, outFileName);
- }
- }
- }
- else if(byteCount) {
- fprintf(stderr, "...generated %u bytes but no place to write it.\n",
- (unsigned)byteCount);
- }
- else if(outFileName) {
- fprintf(stderr, "...nothing to write to file %s.\n", outFileName);
- /* assume this is an error, caller wanted something */
- ortn = -1;
- }
-errOut:
- return ortn;
-}
-
-/*
- From SecurityTool/keychain_utilites.cpp
- This properly supports dynamic keychains, i.e. smartcards
-*/
-
-SecKeychainRef keychain_open(const char *name)
-{
- SecKeychainRef keychain = NULL;
- OSStatus result;
-
-// check_obsolete_keychain(name);
- if (name && name[0] != '/')
- {
- CFArrayRef dynamic = NULL;
- result = SecKeychainCopyDomainSearchList(
- kSecPreferencesDomainDynamic, &dynamic);
- if (result)
- {
- // cssmPerror("SecKeychainOpen", ortn);
- // sec_error("SecKeychainCopyDomainSearchList %s: %s",
- // name, sec_errstr(result));
- cssmPerror("SecKeychainCopyDomainSearchList", result);
- return NULL;
- }
- else
- {
- uint32_t i;
- uint32_t count = dynamic ? CFArrayGetCount(dynamic) : 0;
-
- for (i = 0; i < count; ++i)
- {
- char pathName[PATH_MAX];
- UInt32 ioPathLength = sizeof(pathName);
- bzero(pathName, ioPathLength);
- keychain = (SecKeychainRef)CFArrayGetValueAtIndex(dynamic, i);
- result = SecKeychainGetPath(keychain, &ioPathLength, pathName);
- if (result)
- {
- // sec_error("SecKeychainGetPath %s: %s", name, sec_errstr(result));
- cssmPerror("SecKeychainCopyDomainSearchList", result);
- return NULL;
- }
- if (!strncmp(pathName, name, ioPathLength))
- {
- CFRetain(keychain);
- CFRelease(dynamic);
- return keychain;
- }
- }
- CFRelease(dynamic);
- }
- }
-
- result = SecKeychainOpen(name, &keychain);
- if (result)
- {
- // sec_error("SecKeychainOpen %s: %s", name, sec_errstr(result));
- cssmPerror("SecKeychainOpen", result);
- }
-
- return keychain;
-}
-