2 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <AssertMacros.h>
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>
37 /* Designed to match the sec submodule implementation available for iOS */
38 CFArrayRef
SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message
) {
39 SecCmsMessageRef cmsg
= NULL
;
40 SecCmsContentInfoRef cinfo
;
41 SecCmsSignedDataRef sigd
= NULL
;
42 CFMutableArrayRef certs
= NULL
;
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
);
51 /* find out about signers */
52 int nsigners
= SecCmsSignedDataSignerInfoCount(sigd
);
53 require(nsigners
== 0, out
);
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
);
61 CFArrayAppendValue(certs
, cert
);
69 SecCmsMessageDestroy(cmsg
);
75 CFDataRef
SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert
)
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
86 static const uint8_t trailer
[] = {
87 0xa1, 0x00, 0x31, 0x00
90 CFMutableDataRef message
= NULL
;
92 const uint8_t *certbytes
;
94 uint8_t *messagebytes
;
97 certdata
= SecCertificateCopyData(cert
);
98 require(certdata
, out
);
100 certbytes
= CFDataGetBytePtr(certdata
);
101 certlen
= CFDataGetLength(certdata
);
102 require(certlen
> UINT8_MAX
, out
);
103 require(certlen
< UINT16_MAX
, out
);
105 message
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
106 require(message
, out
);
108 CFDataAppendBytes(message
, header
, sizeof(header
));
109 CFDataAppendBytes(message
, certbytes
, certlen
);
110 CFDataAppendBytes(message
, trailer
, sizeof(trailer
));
112 messagebytes
= CFDataGetMutableBytePtr(message
);
113 messagelen
= CFDataGetLength(message
);
116 messagebytes
[2] = messagelen
>> 8;
117 messagebytes
[3] = messagelen
& 0xFF;
120 messagebytes
[17] = messagelen
>> 8;
121 messagebytes
[18] = messagelen
& 0xFF;
124 messagebytes
[21] = messagelen
>> 8;
125 messagebytes
[22] = messagelen
& 0xFF;
128 messagebytes
[43] = messagelen
>> 8;
129 messagebytes
[44] = messagelen
& 0xFF;
132 if (certdata
!= NULL
)