]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/SecCMS.c
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / SecCMS.c
1 /*
2 * Copyright (c) 2014-2016 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_asn1/secasn1.h>
28
29 #include <Security/SecCmsBase.h>
30 #include <Security/SecCmsMessage.h>
31 #include <Security/SecCmsSignedData.h>
32 #include <Security/SecCmsContentInfo.h>
33 #include <Security/SecCmsSignerInfo.h>
34 #include <Security/SecCertificate.h>
35 #include <Security/SecCertificatePriv.h>
36 #include <Security/SecCmsDecoder.h>
37 #include <Security/SecCmsEncoder.h>
38 #include <Security/SecCmsDigestContext.h>
39 #include <secitem.h>
40 #include <cmslocal.h>
41
42 #include "cmstpriv.h"
43 #include "cmspriv.h"
44
45 #include <SecCMS.h>
46
47 CFTypeRef kSecCMSSignDigest = CFSTR("kSecCMSSignDigest");
48 CFTypeRef kSecCMSSignDetached = CFSTR("kSecCMSSignDetached");
49 CFTypeRef kSecCMSCertChainMode = CFSTR("kSecCMSCertChainMode");
50 CFTypeRef kSecCMSAdditionalCerts = CFSTR("kSecCMSAdditionalCerts");
51 CFTypeRef kSecCMSSignedAttributes = CFSTR("kSecCMSSignedAttributes");
52 CFTypeRef kSecCMSSignDate = CFSTR("kSecCMSSignDate");
53 CFTypeRef kSecCMSAllCerts = CFSTR("kSecCMSAllCerts");
54
55 CFTypeRef kSecCMSSignHashAlgorithm = CFSTR("kSecCMSSignHashAlgorithm");
56 CFTypeRef kSecCMSHashingAlgorithmSHA1 = CFSTR("kSecCMSHashingAlgorithmSHA1");
57 CFTypeRef kSecCMSHashingAlgorithmSHA256 = CFSTR("kSecCMSHashingAlgorithmSHA256");
58 CFTypeRef kSecCMSHashingAlgorithmSHA384 = CFSTR("kSecCMSHashingAlgorithmSHA384");
59 CFTypeRef kSecCMSHashingAlgorithmSHA512 = CFSTR("kSecCMSHashingAlgorithmSHA512");
60
61 static SecCmsAttribute *
62 make_attr(PLArenaPool *poolp, SecAsn1Item *type, SecAsn1Item *value, bool encoded)
63 {
64 SecAsn1Item * copiedvalue;
65 SecCmsAttribute *attr = (SecCmsAttribute *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsAttribute));
66 if (attr == NULL)
67 goto loser;
68
69 if (SECITEM_CopyItem(poolp, &(attr->type), type) != SECSuccess)
70 goto loser;
71
72 if (value != NULL) {
73 if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, value->Length)) == NULL)
74 goto loser;
75
76 if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess)
77 goto loser;
78
79 if (SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess)
80 goto loser;
81 }
82
83 attr->encoded = encoded;
84
85 loser:
86 return attr;
87 }
88
89 static void
90 signerinfo_add_auth_attr(SecCmsSignerInfoRef signerinfo, /*SECOidTag oidtag*/
91 SecAsn1Item *oid, SecAsn1Item *value, bool encoded)
92 {
93 PLArenaPool *poolp = signerinfo->cmsg->poolp;
94 PORT_Assert (poolp != NULL);
95 void *mark = PORT_ArenaMark (poolp);
96
97 SecCmsAttribute *attr = make_attr(poolp, oid, value, encoded);
98 if (!attr || SecCmsAttributeArrayAddAttr(poolp, &(signerinfo->authAttr), attr) != SECSuccess)
99 goto loser;
100
101 PORT_ArenaUnmark (poolp, mark);
102 return;
103
104 loser:
105 PORT_Assert (mark != NULL);
106 PORT_ArenaRelease (poolp, mark);
107 return;
108 }
109
110 static void sign_all_attributes(const void *key, const void *value, void *context)
111 {
112 SecAsn1Item oid = { CFDataGetLength(key), (uint8_t*)CFDataGetBytePtr(key) },
113 oid_value = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) };
114
115 signerinfo_add_auth_attr((SecCmsSignerInfoRef)context, &oid, &oid_value, true);
116 }
117
118 static OSStatus SecCMSSignDataOrDigestAndAttributes(SecIdentityRef identity,
119 CFDataRef data, bool detached, bool data_is_digest, SECOidTag sign_algorithm,
120 CFMutableDataRef signed_data, CFDictionaryRef signed_attributes, SecCmsCertChainMode chainMode, CFArrayRef additional_certs)
121 {
122 SecCmsMessageRef cmsg = NULL;
123 SecCmsContentInfoRef cinfo;
124 SecCmsSignedDataRef sigd = NULL;
125 SecCmsSignerInfoRef signerinfo;
126 OSStatus status = errSecParam;
127 PLArenaPool *arena = NULL;
128
129 require(!data_is_digest || detached /* if digest, must be detached */, out);
130
131 require(cmsg = SecCmsMessageCreate(NULL), out);
132 require(sigd = SecCmsSignedDataCreate(cmsg), out);
133 require(cinfo = SecCmsMessageGetContentInfo(cmsg), out);
134 require_noerr(SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), out);
135 require(cinfo = SecCmsSignedDataGetContentInfo(sigd), out);
136 require_noerr(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, detached), out);
137 require(signerinfo = SecCmsSignerInfoCreate(cmsg, identity, sign_algorithm), out);
138 if (additional_certs)
139 require_noerr(SecCmsSignedDataAddCertList(sigd, additional_certs), out);
140 require_noerr(SecCmsSignerInfoIncludeCerts(signerinfo, chainMode, certUsageAnyCA), out);
141 require_noerr(SecCmsSignerInfoAddSigningTime(signerinfo, CFAbsoluteTimeGetCurrent()), out);
142
143 if (signed_attributes)
144 CFDictionaryApplyFunction(signed_attributes, sign_all_attributes, signerinfo);
145
146 SecAsn1Item input = {};
147 if (data) {
148 input.Length = CFDataGetLength(data);
149 input.Data = (uint8_t*)CFDataGetBytePtr(data);
150 }
151
152 CSSM_DATA cssm_signed_data = {0, NULL};
153 // make an encoder context
154 if ((arena = PORT_NewArena(1024)) == NULL) {
155 goto out;
156 }
157 if (data_is_digest) {
158 require_noerr(SecCmsSignedDataSetDigestValue(sigd, sign_algorithm, &input), out);
159 require_noerr(SecCmsMessageEncode(cmsg, NULL, (SecArenaPoolRef)arena, &cssm_signed_data), out);
160 }
161 else
162 require_noerr(SecCmsMessageEncode(cmsg,(data && input.Length) ? &input : NULL,
163 (SecArenaPoolRef)arena, &cssm_signed_data), out);
164
165 if (signed_data && cssm_signed_data.Data) {
166 CFDataAppendBytes(signed_data, cssm_signed_data.Data, cssm_signed_data.Length);
167 }
168
169 status = errSecSuccess;
170 out:
171 if (arena) PORT_FreeArena(arena, PR_FALSE);
172 if (cmsg) SecCmsMessageDestroy(cmsg);
173 return status;
174 }
175
176 OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data,
177 CFDictionaryRef parameters, CFDictionaryRef signed_attributes,
178 CFMutableDataRef signed_data)
179 {
180 bool is_digest = false, is_detached = false;
181 CFStringRef algorithm_name = NULL;
182 SecCmsCertChainMode chain_mode = SecCmsCMCertChain;
183 CFArrayRef additional_certs = NULL;
184
185 if (parameters) {
186 is_digest = CFDictionaryGetValueIfPresent(parameters,
187 kSecCMSSignDigest, NULL);
188 is_detached = CFDictionaryGetValueIfPresent(parameters,
189 kSecCMSSignDetached, NULL);
190 algorithm_name = CFDictionaryGetValue(parameters,
191 kSecCMSSignHashAlgorithm);
192
193 CFTypeRef chain_mode_param = CFDictionaryGetValue(parameters, kSecCMSCertChainMode);
194 if (chain_mode_param && (CFGetTypeID(chain_mode_param) == CFStringGetTypeID()))
195 chain_mode = CFStringGetIntValue(chain_mode_param);
196
197 CFTypeRef additional_certs_param = CFDictionaryGetValue(parameters, kSecCMSAdditionalCerts);
198 if (additional_certs_param && (CFGetTypeID(additional_certs_param) == CFArrayGetTypeID()))
199 additional_certs = (CFArrayRef)additional_certs_param;
200 }
201
202 SECOidTag algorithm = SEC_OID_SHA1;
203 if (algorithm_name) {
204 if (CFEqual(kSecCMSHashingAlgorithmSHA1, algorithm_name)) {
205 algorithm = SEC_OID_SHA1;
206 } else if (CFEqual(kSecCMSHashingAlgorithmSHA256, algorithm_name)) {
207 algorithm = SEC_OID_SHA256;
208 } else if (CFEqual(kSecCMSHashingAlgorithmSHA384, algorithm_name)) {
209 algorithm = SEC_OID_SHA384;
210 } else if (CFEqual(kSecCMSHashingAlgorithmSHA512, algorithm_name)) {
211 algorithm = SEC_OID_SHA512;
212 } else {
213 // signing with MD5 is no longer allowed
214 algorithm = SEC_OID_UNKNOWN;
215 }
216 }
217
218 return SecCMSSignDataOrDigestAndAttributes(identity, data,
219 is_detached, is_digest, algorithm,
220 signed_data, signed_attributes, chain_mode, additional_certs);
221 }
222
223 static OSStatus
224 SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd,
225 SecCmsDigestContextRef digestContext)
226 {
227 SecAsn1Item * *digests;
228
229 PLArenaPool *arena = NULL;
230
231 if ((arena = PORT_NewArena(1024)) == NULL)
232 goto loser;
233
234 if (SecCmsDigestContextFinishMultiple(digestContext, (SecArenaPoolRef)arena, &digests) != SECSuccess)
235 goto loser;
236
237 SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(sigd);
238 if(digestAlgorithms == NULL) {
239 goto loser;
240 }
241
242 if (SecCmsSignedDataSetDigests(sigd, digestAlgorithms, digests) != SECSuccess)
243 goto loser;
244
245 return 0;
246 loser:
247 if (arena)
248 PORT_FreeArena(arena, PR_FALSE);
249 return PORT_GetError();
250 }
251
252 static CFMutableArrayRef copy_signed_attribute_values(SecCmsAttribute *attr)
253 {
254 CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
255 SecAsn1Item **item = attr->values;
256 if (item) while (*item) {
257 CFDataRef asn1data = CFDataCreate(kCFAllocatorDefault, (*item)->Data, (*item)->Length);
258 if (asn1data) {
259 CFArrayAppendValue(array, asn1data);
260 CFRelease(asn1data);
261 }
262 item++;
263 }
264 return array;
265 }
266
267 static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef detached_contents,
268 CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certs,
269 CFDataRef *attached_contents, CFDictionaryRef *signed_attributes)
270 {
271 SecCmsMessageRef cmsg = NULL;
272 SecCmsContentInfoRef cinfo;
273 SecCmsSignedDataRef sigd = NULL;
274 OSStatus status = errSecParam;
275
276 SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) };
277 require_noerr_action_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg),
278 out, status = errSecDecode);
279 /* expected to be a signed data message at the top level */
280 require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 0), out);
281 require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out);
282 require_quiet(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out);
283
284 if (detached_contents)
285 {
286 require_quiet(!SecCmsSignedDataHasDigests(sigd), out);
287 SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd);
288 SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs);
289 SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(detached_contents), CFDataGetLength(detached_contents));
290 SecCmsSignedDataSetDigestContext(sigd, digcx);
291 }
292
293 if (additional_certs)
294 require_noerr_quiet(SecCmsSignedDataAddCertList(sigd, additional_certs), out);
295
296 if (policy) { /* if no policy is given skip verification */
297 /* find out about signers */
298 int nsigners = SecCmsSignedDataSignerInfoCount(sigd);
299 require_quiet(nsigners == 1, out);
300 require_noerr_action_quiet(SecCmsSignedDataVerifySignerInfo(sigd, 0, NULL, policy, trustref),
301 out, status = errSecAuthFailed);
302 }
303
304 status = errSecSuccess;
305
306 if (attached_contents) {
307 const SecAsn1Item *content = SecCmsMessageGetContent(cmsg);
308 if (content)
309 *attached_contents = CFDataCreate(kCFAllocatorDefault, content->Data, content->Length);
310 else
311 *attached_contents = NULL;
312 }
313
314 if (signed_attributes) {
315 CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault,
316 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
317 require_quiet(attrs, out);
318 SecCmsAttribute **signed_attrs = sigd->signerInfos[0]->authAttr;
319 if (signed_attrs) while (*signed_attrs) {
320 CFDataRef type = CFDataCreate(kCFAllocatorDefault, (*signed_attrs)->type.Data, (*signed_attrs)->type.Length);
321 if (type) {
322 CFMutableArrayRef attr = copy_signed_attribute_values(*signed_attrs);
323 if (attr) {
324 CFMutableArrayRef existing_attrs = (CFMutableArrayRef)CFDictionaryGetValue(attrs, type);
325 if (existing_attrs) {
326 CFIndex count = CFArrayGetCount(attr);
327 if (count)
328 CFArrayAppendArray(existing_attrs, attr, CFRangeMake(0, count));
329 } else
330 CFDictionarySetValue(attrs, type, attr);
331 CFRelease(attr);
332 }
333 CFRelease(type);
334 }
335 signed_attrs++;
336 }
337 CFMutableArrayRef certs = NULL;
338
339 SecAsn1Item **cert_datas = SecCmsSignedDataGetCertificateList(sigd);
340 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
341 SecAsn1Item *cert_data;
342 if (cert_datas) while ((cert_data = *cert_datas) != NULL) {
343 SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length);
344 if (cert) {
345 CFArrayAppendValue(certs, cert);
346 CFRelease(cert);
347 }
348 cert_datas++;
349 }
350
351 CFDictionaryAddValue(attrs, kSecCMSAllCerts, certs);
352
353 /* Add "cooked" values separately */
354 CFAbsoluteTime signing_time;
355 if (errSecSuccess == SecCmsSignerInfoGetSigningTime(sigd->signerInfos[0], &signing_time)) {
356 CFDateRef signing_date = CFDateCreate(kCFAllocatorDefault, signing_time);
357 if (signing_date){
358 CFDictionarySetValue(attrs, kSecCMSSignDate, signing_date);
359 if (signing_date) CFRelease(signing_date);
360 }
361 }
362
363 *signed_attributes = attrs;
364 if (certs) CFRelease(certs);
365 }
366
367
368 out:
369 if (cmsg) SecCmsMessageDestroy(cmsg);
370 return status;
371 }
372
373 OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents,
374 CFTypeRef policy, SecTrustRef *trustref,
375 CFDataRef *attached_contents, CFDictionaryRef *signed_attributes)
376 {
377 OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, signed_attributes);
378
379 return status;
380 }
381
382 OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents,
383 CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates,
384 CFDataRef *attached_contents, CFDictionaryRef *message_attributes)
385 {
386 CFDictionaryRef signed_attributes = NULL;
387 OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, additional_certificates, attached_contents, &signed_attributes);
388 if (!status && signed_attributes && message_attributes) {
389 *message_attributes = CFDictionaryCreate(kCFAllocatorDefault, &kSecCMSSignedAttributes, (const void **)&signed_attributes, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
390 }
391 if (signed_attributes) CFRelease(signed_attributes);
392
393 return status;
394 }
395
396 OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents,
397 CFTypeRef policy, SecTrustRef *trustref,
398 CFDataRef *attached_contents) {
399 return SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, NULL);
400 }
401
402 /* Designed to match the sec submodule implementation available for iOS */
403 CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) {
404 SecCmsMessageRef cmsg = NULL;
405 SecCmsContentInfoRef cinfo;
406 SecCmsSignedDataRef sigd = NULL;
407 CFMutableArrayRef certs = NULL;
408
409 CSSM_DATA encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) };
410 require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out);
411 /* expected to be a signed data message at the top level */
412 require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out);
413 require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out);
414 require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out);
415
416 /* find out about signers */
417 int nsigners = SecCmsSignedDataSignerInfoCount(sigd);
418 require(nsigners == 0, out);
419
420 CSSM_DATA_PTR *cert_datas = SecCmsSignedDataGetCertificateList(sigd);
421 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
422 CSSM_DATA_PTR cert_data;
423 if (cert_datas) while ((cert_data = *cert_datas) != NULL) {
424 SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length);
425 if (cert) {
426 CFArrayAppendValue(certs, cert);
427 CFRelease(cert);
428 }
429 cert_datas++;
430 }
431
432 out:
433 if (cmsg)
434 SecCmsMessageDestroy(cmsg);
435
436 return certs;
437 }
438
439
440 extern const SecAsn1Template SecCmsMessageTemplate[];
441
442 CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof) {
443 OSStatus status = errSecParam;
444 SecCmsMessageRef cmsg = NULL;
445 SecCmsContentInfoRef cinfo;
446 SecCmsSignedDataRef sigd = NULL;
447 CFMutableDataRef cert_only_signed_data = NULL;
448 CFArrayRef cert_array = NULL;
449 CFIndex cert_array_count = 0;
450 SecCertificateRef cert = NULL;
451
452 require(cert_or_array_thereof, out);
453
454 require(cmsg = SecCmsMessageCreate(NULL), out);
455 require(sigd = SecCmsSignedDataCreate(cmsg), out);
456 require_noerr(SecCmsContentInfoSetContentData(cmsg, &(sigd->contentInfo), NULL, PR_TRUE), out);
457 require(cinfo = SecCmsMessageGetContentInfo(cmsg), out);
458 require_noerr(SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), out);
459 long version = SEC_CMS_SIGNED_DATA_VERSION_BASIC;
460 require(SEC_ASN1EncodeInteger(cmsg->poolp, &(sigd->version), version), out);
461
462 if (CFGetTypeID(cert_or_array_thereof) == SecCertificateGetTypeID()) {
463 cert_array = CFArrayCreate(kCFAllocatorDefault, &cert_or_array_thereof, 1, &kCFTypeArrayCallBacks);
464 } else if (CFGetTypeID(cert_or_array_thereof) == CFArrayGetTypeID()) {
465 cert_array = CFArrayCreateCopy(kCFAllocatorDefault, (CFArrayRef)cert_or_array_thereof);
466 }
467
468 require(cert_array, out);
469 cert_array_count = CFArrayGetCount(cert_array);
470 require(cert_array_count > 0, out);
471
472 sigd->rawCerts = (SecAsn1Item * *)PORT_ArenaAlloc(cmsg->poolp, (cert_array_count + 1) * sizeof(SecAsn1Item *));
473 require(sigd->rawCerts, out);
474 CFIndex ix;
475 for (ix = 0; ix < cert_array_count; ix++) {
476 cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, ix);
477 require(cert, out);
478
479 sigd->rawCerts[ix] = PORT_ArenaZAlloc(cmsg->poolp, sizeof(SecAsn1Item));
480 SecAsn1Item cert_data = { SecCertificateGetLength(cert),
481 (uint8_t *)SecCertificateGetBytePtr(cert) };
482 *(sigd->rawCerts[ix]) = cert_data;
483 }
484 sigd->rawCerts[ix] = NULL;
485
486 /* this is a SET OF, so we need to sort them guys - we have the DER already, though */
487 if (cert_array_count > 1)
488 SecCmsArraySort((void **)sigd->rawCerts, SecCmsUtilDERCompare, NULL, NULL);
489
490 cert_only_signed_data = CFDataCreateMutable(kCFAllocatorDefault, 0);
491 SecAsn1Item cert_only_signed_data_item = {};
492 require_quiet(SEC_ASN1EncodeItem(cmsg->poolp, &cert_only_signed_data_item,
493 cmsg, SecCmsMessageTemplate), out);
494 CFDataAppendBytes(cert_only_signed_data, cert_only_signed_data_item.Data,
495 cert_only_signed_data_item.Length);
496
497 status = errSecSuccess;
498 out:
499 if (cert_array) { CFRelease(cert_array); }
500 if (status && cert_only_signed_data) { CFRelease(cert_only_signed_data); }
501 if (cmsg) SecCmsMessageDestroy(cmsg);
502 return cert_only_signed_data;
503 }
504
505 CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert)
506 {
507 static const uint8_t header[] = {
508 0x30, 0x82, 0x03, 0x6d, 0x06, 0x09, 0x2a, 0x86,
509 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0,
510 0x82, 0x03, 0x5e, 0x30, 0x82, 0x03, 0x5a, 0x02,
511 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09,
512 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
513 0x01, 0xa0, 0x82, 0x03, 0x40
514 };
515
516 static const uint8_t trailer[] = {
517 0xa1, 0x00, 0x31, 0x00
518 };
519
520 CFMutableDataRef message = NULL;
521 CFDataRef certdata;
522 const uint8_t *certbytes;
523 CFIndex certlen;
524 uint8_t *messagebytes;
525 uint16_t messagelen;
526
527 certdata = SecCertificateCopyData(cert);
528 require(certdata, out);
529
530 certbytes = CFDataGetBytePtr(certdata);
531 certlen = CFDataGetLength(certdata);
532 require(certlen > UINT8_MAX, out);
533 require(certlen < UINT16_MAX, out);
534
535 message = CFDataCreateMutable(kCFAllocatorDefault, 0);
536 require(message, out);
537
538 CFDataAppendBytes(message, header, sizeof(header));
539 CFDataAppendBytes(message, certbytes, certlen);
540 CFDataAppendBytes(message, trailer, sizeof(trailer));
541
542 messagebytes = CFDataGetMutableBytePtr(message);
543 messagelen = CFDataGetLength(message);
544
545 messagelen -= 4;
546 messagebytes[2] = messagelen >> 8;
547 messagebytes[3] = messagelen & 0xFF;
548
549 messagelen -= 15;
550 messagebytes[17] = messagelen >> 8;
551 messagebytes[18] = messagelen & 0xFF;
552
553 messagelen -= 4;
554 messagebytes[21] = messagelen >> 8;
555 messagebytes[22] = messagelen & 0xFF;
556
557 messagelen -= 26;
558 messagebytes[43] = messagelen >> 8;
559 messagebytes[44] = messagelen & 0xFF;
560
561 out:
562 if (certdata != NULL)
563 {
564 CFRelease(certdata);
565 }
566 return message;
567 }