X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_smime/lib/SecCMS.c?ds=sidebyside diff --git a/OSX/libsecurity_smime/lib/SecCMS.c b/OSX/libsecurity_smime/lib/SecCMS.c new file mode 100644 index 00000000..bcb2552a --- /dev/null +++ b/OSX/libsecurity_smime/lib/SecCMS.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include +#include +#include +#include +#include +#include + + +#include + +/* Designed to match the sec submodule implementation available for iOS */ +CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + CFMutableArrayRef certs = NULL; + + CSSM_DATA encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); + /* expected to be a signed data message at the top level */ + require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); + require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + /* find out about signers */ + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require(nsigners == 0, out); + + CSSM_DATA_PTR *cert_datas = SecCmsSignedDataGetCertificateList(sigd); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CSSM_DATA_PTR cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + CFArrayAppendValue(certs, cert); + CFRelease(cert); + } + cert_datas++; + } + +out: + if (cmsg) + SecCmsMessageDestroy(cmsg); + + return certs; +} + + +CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert) +{ + static const uint8_t header[] = { + 0x30, 0x82, 0x03, 0x6d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, + 0x82, 0x03, 0x5e, 0x30, 0x82, 0x03, 0x5a, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x01, 0xa0, 0x82, 0x03, 0x40 + }; + + static const uint8_t trailer[] = { + 0xa1, 0x00, 0x31, 0x00 + }; + + CFMutableDataRef message = NULL; + CFDataRef certdata; + const uint8_t *certbytes; + CFIndex certlen; + uint8_t *messagebytes; + uint16_t messagelen; + + certdata = SecCertificateCopyData(cert); + require(certdata, out); + + certbytes = CFDataGetBytePtr(certdata); + certlen = CFDataGetLength(certdata); + require(certlen > UINT8_MAX, out); + require(certlen < UINT16_MAX, out); + + message = CFDataCreateMutable(kCFAllocatorDefault, 0); + require(message, out); + + CFDataAppendBytes(message, header, sizeof(header)); + CFDataAppendBytes(message, certbytes, certlen); + CFDataAppendBytes(message, trailer, sizeof(trailer)); + + messagebytes = CFDataGetMutableBytePtr(message); + messagelen = CFDataGetLength(message); + + messagelen -= 4; + messagebytes[2] = messagelen >> 8; + messagebytes[3] = messagelen & 0xFF; + + messagelen -= 15; + messagebytes[17] = messagelen >> 8; + messagebytes[18] = messagelen & 0xFF; + + messagelen -= 4; + messagebytes[21] = messagelen >> 8; + messagebytes[22] = messagelen & 0xFF; + + messagelen -= 26; + messagebytes[43] = messagelen >> 8; + messagebytes[44] = messagelen & 0xFF; + +out: + if (certdata != NULL) + { + CFRelease(certdata); + } + return message; +} + + +