1/* 2 * Copyright (c) 2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#include <AssertMacros.h> 26 27#include <Security/SecCmsDecoder.h> 28#include <Security/SecCmsMessage.h> 29#include <Security/SecCmsContentInfo.h> 30#include <Security/SecCmsSignedData.h> 31#include <Security/SecCertificate.h> 32#include <Security/SecCertificatePriv.h> 33 34 35#include <SecCMS.h> 36 37/* Designed to match the sec submodule implementation available for iOS */ 38CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { 39 SecCmsMessageRef cmsg = NULL; 40 SecCmsContentInfoRef cinfo; 41 SecCmsSignedDataRef sigd = NULL; 42 CFMutableArrayRef certs = NULL; 43 44 CSSM_DATA encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; 45 require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); 46 /* expected to be a signed data message at the top level */ 47 require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); 48 require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); 49 require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); 50 51 /* find out about signers */ 52 int nsigners = SecCmsSignedDataSignerInfoCount(sigd); 53 require(nsigners == 0, out); 54 55 CSSM_DATA_PTR *cert_datas = SecCmsSignedDataGetCertificateList(sigd); 56 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 57 CSSM_DATA_PTR cert_data; 58 if (cert_datas) while ((cert_data = *cert_datas) != NULL) { 59 SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); 60 if (cert) { 61 CFArrayAppendValue(certs, cert); 62 CFRelease(cert); 63 } 64 cert_datas++; 65 } 66 67out: 68 if (cmsg) 69 SecCmsMessageDestroy(cmsg); 70 71 return certs; 72} 73 74 75CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert) 76{ 77 static const uint8_t header[] = { 78 0x30, 0x82, 0x03, 0x6d, 0x06, 0x09, 0x2a, 0x86, 79 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 80 0x82, 0x03, 0x5e, 0x30, 0x82, 0x03, 0x5a, 0x02, 81 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 82 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 83 0x01, 0xa0, 0x82, 0x03, 0x40 84 }; 85 86 static const uint8_t trailer[] = { 87 0xa1, 0x00, 0x31, 0x00 88 }; 89 90 CFMutableDataRef message = NULL; 91 CFDataRef certdata; 92 const uint8_t *certbytes; 93 CFIndex certlen; 94 uint8_t *messagebytes; 95 uint16_t messagelen; 96 97 certdata = SecCertificateCopyData(cert); 98 require(certdata, out); 99 100 certbytes = CFDataGetBytePtr(certdata); 101 certlen = CFDataGetLength(certdata); 102 require(certlen > UINT8_MAX, out); 103 require(certlen < UINT16_MAX, out); 104 105 message = CFDataCreateMutable(kCFAllocatorDefault, 0); 106 require(message, out); 107 108 CFDataAppendBytes(message, header, sizeof(header)); 109 CFDataAppendBytes(message, certbytes, certlen); 110 CFDataAppendBytes(message, trailer, sizeof(trailer)); 111 112 messagebytes = CFDataGetMutableBytePtr(message); 113 messagelen = CFDataGetLength(message); 114 115 messagelen -= 4; 116 messagebytes[2] = messagelen >> 8; 117 messagebytes[3] = messagelen & 0xFF; 118 119 messagelen -= 15; 120 messagebytes[17] = messagelen >> 8; 121 messagebytes[18] = messagelen & 0xFF; 122 123 messagelen -= 4; 124 messagebytes[21] = messagelen >> 8; 125 messagebytes[22] = messagelen & 0xFF; 126 127 messagelen -= 26; 128 messagebytes[43] = messagelen >> 8; 129 messagebytes[44] = messagelen & 0xFF; 130 131out: 132 if (certdata != NULL) 133 { 134 CFRelease(certdata); 135 } 136 return message; 137} 138 139 140 141