]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/SecCMS.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / SecCMS.c
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 */
38 CFArrayRef 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
67 out:
68 if (cmsg)
69 SecCmsMessageDestroy(cmsg);
70
71 return certs;
72 }
73
74
75 CFDataRef 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
131 out:
132 if (certdata != NULL)
133 {
134 CFRelease(certdata);
135 }
136 return message;
137 }
138
139
140