/* * SecCmsSignedDataCreateCertsOnly - create a certs-only SignedData. * * cert - base certificates that will be included * include_chain - if true, include the complete cert chain for cert * * More certs and chains can be added via AddCertificate and AddCertChain. * * An error results in a return value of NULL and an error set. * * XXXX CRLs */ SecCmsSignedDataRef SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, Boolean include_chain) { SecCmsSignedDataRef sigd; void *mark; PLArenaPool *poolp; OSStatus rv; poolp = cmsg->poolp; mark = PORT_ArenaMark(poolp); sigd = SecCmsSignedDataCreate(cmsg); if (sigd == NULL) goto loser; /* no signerinfos, thus no digestAlgorithms */ /* but certs */ if (include_chain) { rv = SecCmsSignedDataAddCertChain(sigd, cert); } else { rv = SecCmsSignedDataAddCertificate(sigd, cert); } if (rv != SECSuccess) goto loser; /* RFC2630 5.2 sez: * In the degenerate case where there are no signers, the * EncapsulatedContentInfo value being "signed" is irrelevant. In this * case, the content type within the EncapsulatedContentInfo value being * "signed" should be id-data (as defined in section 4), and the content * field of the EncapsulatedContentInfo value should be omitted. */ rv = SecCmsContentInfoSetContentData(cmsg, &(sigd->contentInfo), NULL, PR_TRUE); if (rv != SECSuccess) goto loser; PORT_ArenaUnmark(poolp, mark); return sigd; loser: if (sigd) SecCmsSignedDataDestroy(sigd); PORT_ArenaRelease(poolp, mark); return NULL; }
/* * Set up a SecCmsMessageRef for a EnvelopedData creation. */ static OSStatus cmsSetupForEnvelopedData( CMSEncoderRef cmsEncoder) { ASSERT(cmsEncoder->op == EO_Encrypt); ASSERT(cmsEncoder->recipients != NULL); SecCmsContentInfoRef contentInfo = NULL; SecCmsEnvelopedDataRef envelopedData = NULL; SECOidTag algorithmTag; int keySize; OSStatus ortn; /* * Find encryption algorithm...unfortunately we need a NULL-terminated array * of SecCertificateRefs for this. */ CFIndex numCerts = CFArrayGetCount(cmsEncoder->recipients); CFIndex dex; SecCertificateRef *certArray = (SecCertificateRef *)malloc( (numCerts+1) * sizeof(SecCertificateRef)); for(dex=0; dex<numCerts; dex++) { certArray[dex] = (SecCertificateRef)CFArrayGetValueAtIndex( cmsEncoder->recipients, dex); } certArray[numCerts] = NULL; ortn = SecSMIMEFindBulkAlgForRecipients(certArray, &algorithmTag, &keySize); free(certArray); if(ortn) { CSSM_PERROR("SecSMIMEFindBulkAlgForRecipients", ortn); return ortn; } /* build chain of objects: message->envelopedData->data */ if(cmsEncoder->cmsMsg != NULL) { SecCmsMessageDestroy(cmsEncoder->cmsMsg); } cmsEncoder->cmsMsg = SecCmsMessageCreate(NULL); if(cmsEncoder->cmsMsg == NULL) { return errSecInternalComponent; } envelopedData = SecCmsEnvelopedDataCreate(cmsEncoder->cmsMsg, algorithmTag, keySize); if(envelopedData == NULL) { return errSecInternalComponent; } contentInfo = SecCmsMessageGetContentInfo(cmsEncoder->cmsMsg); ortn = SecCmsContentInfoSetContentEnvelopedData(cmsEncoder->cmsMsg, contentInfo, envelopedData); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsContentInfoSetContentEnvelopedData", ortn); return ortn; } contentInfo = SecCmsEnvelopedDataGetContentInfo(envelopedData); if(cmsEncoder->eContentType.Data != NULL) { /* Override the default ContentType of id-data */ ortn = SecCmsContentInfoSetContentOther(cmsEncoder->cmsMsg, contentInfo, NULL, /* data - provided to encoder, not here */ FALSE, /* detachedContent */ &cmsEncoder->eContentType); } else { ortn = SecCmsContentInfoSetContentData(cmsEncoder->cmsMsg, contentInfo, NULL /* data - provided to encoder, not here */, cmsEncoder->detachedContent); } if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsContentInfoSetContentData*", ortn); return ortn; } /* * create & attach recipient information, one for each recipient */ for(dex=0; dex<numCerts; dex++) { SecCmsRecipientInfoRef recipientInfo = NULL; SecCertificateRef thisRecip = (SecCertificateRef)CFArrayGetValueAtIndex( cmsEncoder->recipients, dex); recipientInfo = SecCmsRecipientInfoCreate(cmsEncoder->cmsMsg, thisRecip); ortn = SecCmsEnvelopedDataAddRecipient(envelopedData, recipientInfo); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsEnvelopedDataAddRecipient", ortn); return ortn; } } return errSecSuccess; }
/* * Set up a SecCmsMessageRef for a SignedData creation. */ static OSStatus cmsSetupForSignedData( CMSEncoderRef cmsEncoder) { ASSERT((cmsEncoder->signers != NULL) || (cmsEncoder->otherCerts != NULL)); SecCmsContentInfoRef contentInfo = NULL; SecCmsSignedDataRef signedData = NULL; OSStatus ortn; /* build chain of objects: message->signedData->data */ if(cmsEncoder->cmsMsg != NULL) { SecCmsMessageDestroy(cmsEncoder->cmsMsg); } cmsEncoder->cmsMsg = SecCmsMessageCreate(NULL); if(cmsEncoder->cmsMsg == NULL) { return errSecInternalComponent; } signedData = SecCmsSignedDataCreate(cmsEncoder->cmsMsg); if(signedData == NULL) { return errSecInternalComponent; } contentInfo = SecCmsMessageGetContentInfo(cmsEncoder->cmsMsg); ortn = SecCmsContentInfoSetContentSignedData(cmsEncoder->cmsMsg, contentInfo, signedData); if(ortn) { return cmsRtnToOSStatus(ortn); } contentInfo = SecCmsSignedDataGetContentInfo(signedData); if(cmsEncoder->eContentType.Data != NULL) { /* Override the default eContentType of id-data */ ortn = SecCmsContentInfoSetContentOther(cmsEncoder->cmsMsg, contentInfo, NULL, /* data - provided to encoder, not here */ cmsEncoder->detachedContent, &cmsEncoder->eContentType); } else { ortn = SecCmsContentInfoSetContentData(cmsEncoder->cmsMsg, contentInfo, NULL, /* data - provided to encoder, not here */ cmsEncoder->detachedContent); } if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsContentInfoSetContent*", ortn); return ortn; } /* optional 'global' (per-SignedData) certs */ if(cmsEncoder->otherCerts != NULL) { ortn = SecCmsSignedDataAddCertList(signedData, cmsEncoder->otherCerts); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignedDataAddCertList", ortn); return ortn; } } /* SignerInfos, one per signer */ CFIndex numSigners = 0; if(cmsEncoder->signers != NULL) { /* this is optional...in case we're just creating a cert bundle */ numSigners = CFArrayGetCount(cmsEncoder->signers); } CFIndex dex; SecCertificateRef ourCert = NULL; SecCmsCertChainMode chainMode = SecCmsCMCertChain; switch(cmsEncoder->chainMode) { case kCMSCertificateNone: chainMode = SecCmsCMNone; break; case kCMSCertificateSignerOnly: chainMode = SecCmsCMCertOnly; break; case kCMSCertificateChainWithRoot: chainMode = SecCmsCMCertChainWithRoot; break; default: break; } for(dex=0; dex<numSigners; dex++) { SecCmsSignerInfoRef signerInfo; SecIdentityRef ourId = (SecIdentityRef)CFArrayGetValueAtIndex(cmsEncoder->signers, dex); ortn = SecIdentityCopyCertificate(ourId, &ourCert); if(ortn) { CSSM_PERROR("SecIdentityCopyCertificate", ortn); break; } signerInfo = SecCmsSignerInfoCreate(cmsEncoder->cmsMsg, ourId, cmsEncoder->digestalgtag); if (signerInfo == NULL) { ortn = errSecInternalComponent; break; } /* we want the cert chain included for this one */ /* NOTE the usage parameter is currently unused by the SMIME lib */ ortn = SecCmsSignerInfoIncludeCerts(signerInfo, chainMode, certUsageEmailSigner); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoIncludeCerts", ortn); break; } /* other options */ if(cmsEncoder->signedAttributes & kCMSAttrSmimeCapabilities) { ortn = SecCmsSignerInfoAddSMIMECaps(signerInfo); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); break; } } if(cmsEncoder->signedAttributes & kCMSAttrSmimeEncryptionKeyPrefs) { ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, NULL); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); break; } } if(cmsEncoder->signedAttributes & kCMSAttrSmimeMSEncryptionKeyPrefs) { ortn = SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerInfo, ourCert, NULL); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddMSSMIMEEncKeyPrefs", ortn); break; } } if(cmsEncoder->signedAttributes & kCMSAttrSigningTime) { if (cmsEncoder->signingTime == 0) cmsEncoder->signingTime = CFAbsoluteTimeGetCurrent(); ortn = SecCmsSignerInfoAddSigningTime(signerInfo, cmsEncoder->signingTime); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddSigningTime", ortn); break; } } if(cmsEncoder->signedAttributes & kCMSAttrAppleCodesigningHashAgility) { ortn = SecCmsSignerInfoAddAppleCodesigningHashAgility(signerInfo, cmsEncoder->hashAgilityAttrValue); /* libsecurity_smime made a copy of the attribute value. We don't need it anymore. */ CFReleaseNull(cmsEncoder->hashAgilityAttrValue); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddAppleCodesigningHashAgility", ortn); break; } } ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignedDataAddSignerInfo", ortn); break; } CFRELEASE(ourCert); ourCert = NULL; } if(ortn) { CFRELEASE(ourCert); } return ortn; }