]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_manifest/lib/AppleManifest.cpp
Security-59306.101.1.tar.gz
[apple/security.git] / OSX / libsecurity_manifest / lib / AppleManifest.cpp
1 #include "AppleManifest.h"
2 #include <CoreFoundation/CoreFoundation.h>
3 #include <Security/SecCmsContentInfo.h>
4 #include <Security/SecCmsDecoder.h>
5 #include <Security/SecCmsEncoder.h>
6 #include <Security/SecCmsMessage.h>
7 #include <Security/SecCmsSignedData.h>
8 #include <Security/SecCmsSignerInfo.h>
9
10
11 /*
12 * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved.
13 *
14 * @APPLE_LICENSE_HEADER_START@
15 *
16 * This file contains Original Code and/or Modifications of Original Code
17 * as defined in and that are subject to the Apple Public Source License
18 * Version 2.0 (the 'License'). You may not use this file except in
19 * compliance with the License. Please obtain a copy of the License at
20 * http://www.opensource.apple.com/apsl/ and read it before using this
21 * file.
22 *
23 * The Original Code and all software distributed under the License are
24 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
25 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
26 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
28 * Please see the License for the specific language governing rights and
29 * limitations under the License.
30 *
31 * @APPLE_LICENSE_HEADER_END@
32 */
33
34
35
36 const int kLengthLength = 8;
37
38
39
40 static void ConvertUInt64ToBytes (UInt64 length, UInt8* bytes)
41 {
42 int i;
43 for (i = kLengthLength - 1; i >= 0; i--)
44 {
45 bytes[i] = length & 0xFF;
46 length >>= 8;
47 }
48 }
49
50
51
52 static void WriteLengthAndUpdate (CFMutableDataRef data, UInt64 length, CFIndex location)
53 {
54 // back patch the length of the list
55 secinfo ("manifest", "Length was %lld, patched at location %lld", length, (UInt64) location);
56
57 UInt8 lengthBytes[kLengthLength];
58 ConvertUInt64ToBytes (length, lengthBytes);
59
60 CFRange range = {location, kLengthLength};
61 CFDataReplaceBytes (data, range, lengthBytes, kLengthLength);
62 }
63
64
65
66 static CFIndex GetCurrentLengthAndExtend (CFMutableDataRef data)
67 {
68 CFIndex currentIndex = CFDataGetLength (data);
69 CFDataIncreaseLength (data, kLengthLength);
70 return currentIndex;
71 }
72
73
74
75 static void AppendUInt16 (CFMutableDataRef data, UInt16 num)
76 {
77 UInt8 n[2];
78 n[0] = num >> 8;
79 n[1] = num & 0xFF;
80 CFDataAppendBytes (data, n, sizeof (n));
81 }
82
83
84
85 static void AppendUInt32 (CFMutableDataRef data, UInt32 num)
86 {
87 UInt8 n[4];
88 n[0] = (num >> 24) & 0xFF;
89 n[1] = (num >> 16) & 0xFF;
90 n[2] = (num >> 8) & 0xFF;
91 n[3] = num & 0xFF;
92 CFDataAppendBytes (data, n, sizeof (n));
93 }
94
95
96
97 static void AppendUInt64 (CFMutableDataRef data, UInt64 num)
98 {
99 UInt8 n[8];
100 n[0] = (num >> 56) & 0xFF;
101 n[1] = (num >> 48) & 0xFF;
102 n[2] = (num >> 40) & 0xFF;
103 n[3] = (num >> 32) & 0xFF;
104 n[4] = (num >> 24) & 0xFF;
105 n[5] = (num >> 16) & 0xFF;
106 n[6] = (num >> 8) & 0xFF;
107 n[7] = num & 0xFF;
108
109 CFDataAppendBytes (data, n, sizeof (n));
110 }
111
112
113
114 static void WriteFileSystemItemHeader (CFMutableDataRef data, const FileSystemEntryItem *fsi)
115 {
116 // write the name
117 const char* name = fsi->GetName ();
118 secinfo ("manifest", "\tAdding header for %s", name);
119 uint16_t len = (uint16_t)strlen (name);
120 AppendUInt16 (data, len);
121 CFDataAppendBytes (data, (UInt8*) name, len);
122 AppendUInt32 (data, fsi->GetUID ());
123 AppendUInt32 (data, fsi->GetGID ());
124 AppendUInt32 (data, fsi->GetMode ());
125 }
126
127
128
129 AppleManifest::AppleManifest ()
130 {
131 }
132
133
134
135 AppleManifest::~AppleManifest ()
136 {
137 // release our interest in the signers
138 int signerCount = (int)mSignerList.size ();
139
140 int i;
141 for (i = 0; i < signerCount; ++i)
142 {
143 CFRelease (mSignerList[i]);
144 }
145 }
146
147
148
149 void AppleManifest::AddDirectoryToManifest (CFMutableDataRef manifest, ManifestDirectoryItem* directory)
150 {
151 secinfo ("manifest", "Adding directory %s to manifest", directory->GetName ());
152
153 CFIndex currentIndex = GetCurrentLengthAndExtend (manifest);
154 AppendUInt16 (manifest, (UInt16) kManifestDirectoryItemType);
155
156 WriteFileSystemItemHeader (manifest, directory);
157
158 AddManifestItemListToManifest (manifest, directory->GetItemList ());
159
160 WriteLengthAndUpdate (manifest, CFDataGetLength (manifest) - currentIndex, currentIndex);
161 }
162
163
164
165 void AppleManifest::AddFileToManifest (CFMutableDataRef manifest, ManifestFileItem* file)
166 {
167 CFIndex currentIndex = GetCurrentLengthAndExtend (manifest);
168 AppendUInt16 (manifest, (UInt16) kManifestFileItemType);
169
170 WriteFileSystemItemHeader (manifest, file);
171
172 int numForks = file->GetNumberOfForks ();
173 AppendUInt16 (manifest, (UInt16) numForks);
174
175 int i;
176 // write the file lengths
177 for (i = 0; i < numForks; ++i)
178 {
179 size_t length;
180 length = file->GetForkLength (i);
181 AppendUInt64 (manifest, length);
182 }
183
184 // write the digests
185 for (i = 0; i < numForks; ++i)
186 {
187 void* sha1Digest;
188 size_t size;
189 file->GetItemRepresentation (i, sha1Digest, size);
190 CFDataAppendBytes (manifest, (UInt8*) sha1Digest, size);
191 }
192
193 WriteLengthAndUpdate (manifest, CFDataGetLength (manifest) - currentIndex, currentIndex);
194 }
195
196
197
198 void AppleManifest::AddSymLinkToManifest (CFMutableDataRef manifest, ManifestSymLinkItem* file)
199 {
200 CFIndex currentIndex = GetCurrentLengthAndExtend (manifest);
201 AppendUInt16 (manifest, (UInt16) kManifestSymLinkItemType);
202
203 WriteFileSystemItemHeader (manifest, file);
204
205 const SHA1Digest* digest = file->GetDigest ();
206 CFDataAppendBytes (manifest, (const UInt8*) digest, kSHA1DigestSize);
207
208 WriteLengthAndUpdate (manifest, CFDataGetLength (manifest) - currentIndex, currentIndex);
209 }
210
211
212
213 void AppleManifest::AddOtherToManifest (CFMutableDataRef manifest, ManifestOtherItem* other)
214 {
215 CFIndex currentIndex = GetCurrentLengthAndExtend (manifest);
216 AppendUInt16 (manifest, (UInt16) kManifestSymLinkItemType);
217
218 WriteFileSystemItemHeader (manifest, other);
219
220 WriteLengthAndUpdate (manifest, CFDataGetLength (manifest) - currentIndex, currentIndex);
221 }
222
223
224
225 void AppleManifest::AddDataBlobToManifest (CFMutableDataRef manifest, ManifestDataBlobItem* item)
226 {
227 CFIndex currentIndex = GetCurrentLengthAndExtend (manifest);
228 AppendUInt16 (manifest, (UInt16) kManifestDataBlobItemType);
229
230 AppendUInt64 (manifest, (UInt64) item->GetLength ());
231 const SHA1Digest* sha1Digest = item->GetDigest ();
232 CFDataAppendBytes (manifest, (UInt8*) sha1Digest, sizeof (SHA1Digest));
233
234 WriteLengthAndUpdate (manifest, CFDataGetLength (manifest) - currentIndex, currentIndex);
235 }
236
237
238
239 void AppleManifest::AddManifestItemListToManifest (CFMutableDataRef data, ManifestItemList &itemList)
240 {
241 // save the current position
242 CFIndex currentIndex = GetCurrentLengthAndExtend (data);
243
244 unsigned i;
245 for (i = 0; i < itemList.size (); ++i)
246 {
247 ManifestItem* item = itemList[i];
248
249 switch (item->GetItemType ())
250 {
251 case kManifestDataBlobItemType:
252 {
253 AddDataBlobToManifest (data, static_cast<ManifestDataBlobItem*>(item));
254 break;
255 }
256
257 case kManifestFileItemType:
258 {
259 AddFileToManifest (data, static_cast<ManifestFileItem*>(item));
260 break;
261 }
262
263 case kManifestDirectoryItemType:
264 {
265 AddDirectoryToManifest (data, static_cast<ManifestDirectoryItem*>(item));
266 break;
267 }
268
269 case kManifestSymLinkItemType:
270 {
271 AddSymLinkToManifest (data, static_cast<ManifestSymLinkItem*>(item));
272 break;
273 }
274
275 case kManifestOtherType:
276 {
277 AddOtherToManifest (data, static_cast<ManifestOtherItem*>(item));
278 break;
279 }
280 }
281 }
282
283 WriteLengthAndUpdate (data, CFDataGetLength (data) - currentIndex, currentIndex);
284 }
285
286
287
288 static const unsigned char gManifestHeader[] = {0x2F, 0xAA, 0x05, 0xB3, 0x64, 0x0E, 0x9D, 0x27}; // why these numbers? These were picked at random
289 static const unsigned char gManifestVersion[] = {0x01, 0x00, 0x00, 0x00};
290
291
292
293 void AppleManifest::CreateManifest (CFMutableDataRef manifest, ManifestInternal& internalManifest)
294 {
295 // create the manifest header
296 CFDataAppendBytes (manifest, (UInt8*) gManifestHeader, sizeof (gManifestHeader));
297 CFDataAppendBytes (manifest, (UInt8*) gManifestVersion, sizeof (gManifestVersion));
298 AddManifestItemListToManifest (manifest, internalManifest.GetItemList ());
299 }
300
301
302
303 void AppleManifest::AddSignersToCmsMessage (SecCmsMessageRef cmsMessage, SecCmsSignedDataRef signedData)
304 {
305 // add signers for each of our signers
306 int numSigners = (int)mSignerList.size ();
307
308 int i;
309 for (i = 0; i < numSigners; ++i)
310 {
311 SecIdentityRef id = mSignerList[i];
312 SecCmsSignerInfoRef signerInfo = SecCmsSignerInfoCreate (cmsMessage, id, SEC_OID_SHA1);
313 if (signerInfo == NULL)
314 {
315 SecCmsMessageDestroy (cmsMessage);
316 MacOSError::throwMe (errSecManifestCMSFailure);
317 }
318
319 int result = SecCmsSignerInfoIncludeCerts (signerInfo, SecCmsCMCertChain, certUsageObjectSigner);
320 if (result != 0)
321 {
322 SecCmsMessageDestroy (cmsMessage);
323 MacOSError::throwMe (errSecManifestCMSFailure);
324 }
325
326 SecCmsSignedDataAddSignerInfo (signedData, signerInfo);
327 }
328 }
329
330
331
332 CFDataRef AppleManifest::Export (ManifestInternal& manifest)
333 {
334 // there had better be at least one signer
335 if (mSignerList.size () == 0)
336 {
337 secinfo ("manifest", "No signers found");
338 MacOSError::throwMe (errSecManifestNoSigners);
339 }
340
341 // create a CFMutableDataRef to hold the manifest object
342 CFMutableDataRef data = CFDataCreateMutable (kCFAllocatorDefault, 0);
343
344 // make the manifest
345 CreateManifest (data, manifest);
346
347 // make the PKCS #7 wrapper
348 SecCmsMessageRef cmsMessage;
349 cmsMessage = SecCmsMessageCreate (NULL);
350 if (cmsMessage == NULL) // did something go wrong?
351 {
352 MacOSError::throwMe (errSecManifestCMSFailure);
353 }
354
355 // create a signed data holder
356 SecCmsSignedDataRef signedData;
357 signedData = SecCmsSignedDataCreate (cmsMessage);
358 if (signedData == NULL)
359 {
360 SecCmsMessageDestroy (cmsMessage);
361 MacOSError::throwMe (errSecManifestCMSFailure);
362 }
363
364 // link the signed data and the CMS message
365 SecCmsContentInfoRef contentInfo = SecCmsMessageGetContentInfo (cmsMessage);
366
367 int result = SecCmsContentInfoSetContentSignedData (cmsMessage, contentInfo, signedData);
368 if (result != 0)
369 {
370 SecCmsMessageDestroy (cmsMessage);
371 MacOSError::throwMe (errSecManifestCMSFailure);
372 }
373
374 // attach the content information from the signature to the data
375 contentInfo = SecCmsSignedDataGetContentInfo (signedData);
376 result = SecCmsContentInfoSetContentData (cmsMessage, contentInfo, NULL, false);
377 if (result != 0)
378 {
379 SecCmsMessageDestroy (cmsMessage);
380 MacOSError::throwMe (errSecManifestCMSFailure);
381 }
382
383 AddSignersToCmsMessage (cmsMessage, signedData);
384
385 // make an encoder context
386 SecArenaPoolRef arena;
387 result = SecArenaPoolCreate(1024, &arena);
388 if (result)
389 {
390 MacOSError::throwMe (errSecManifestCMSFailure);
391 }
392
393 CSSM_DATA finalMessage = {0, NULL};
394 SecCmsEncoderRef encoderContext;
395 result = SecCmsEncoderCreate (cmsMessage, NULL, NULL, &finalMessage, arena, NULL, NULL, NULL, NULL, NULL, NULL, &encoderContext);
396 if (result)
397 {
398 MacOSError::throwMe (errSecManifestCMSFailure);
399 }
400
401 result = SecCmsEncoderUpdate (encoderContext, CFDataGetBytePtr (data), CFDataGetLength (data));
402 if (result != 0)
403 {
404 SecCmsMessageDestroy (cmsMessage);
405 MacOSError::throwMe (errSecManifestCMSFailure);
406 }
407
408 result = SecCmsEncoderFinish (encoderContext);
409 if (result != 0)
410 {
411 MacOSError::throwMe (errSecManifestCMSFailure);
412 }
413
414 // create a CFData from the results
415 CFDataRef retData = CFDataCreate (kCFAllocatorDefault, (UInt8*) finalMessage.Data, finalMessage.Length);
416
417 SecArenaPoolFree(arena, false);
418 SecCmsMessageDestroy (cmsMessage);
419
420 CFRelease (data);
421
422 return retData;
423 }
424
425
426
427 static u_int64_t ReconstructUInt64 (uint32& finger, const uint8* data)
428 {
429 unsigned i;
430 u_int64_t r = 0;
431
432 for (i = 0; i < sizeof (u_int64_t); ++i)
433 {
434 r = (r << 8) | data[finger++];
435 }
436
437 return r;
438 }
439
440
441
442 static u_int32_t ReconstructUInt32 (uint32& finger, const uint8* data)
443 {
444 unsigned i;
445 u_int32_t r = 0;
446
447 for (i = 0; i < sizeof (u_int32_t); ++i)
448 {
449 r = (r << 8) | data[finger++];
450 }
451
452 return r;
453 }
454
455
456
457 static u_int16_t ReconstructUInt16 (uint32& finger, const uint8* data)
458 {
459 unsigned i;
460 u_int16_t r = 0;
461
462 for (i = 0; i < sizeof (u_int16_t); ++i)
463 {
464 r = (r << 8) | data[finger++];
465 }
466
467 return r;
468 }
469
470
471
472 static void ReconstructFileSystemHeader (uint32& finger, const uint8* data, FileSystemEntryItem* item)
473 {
474 // get the number of bytes for the name
475 u_int16_t length = ReconstructUInt16 (finger, data);
476 std::vector<char> name(length + 1);
477
478 // make a c-string for the name
479 memcpy (name.data(), data + finger, length);
480 name[length] = 0;
481
482 secinfo ("manifest", " File item name is %s", name.data());
483 item->SetName (name.data());
484
485 finger += length;
486
487 uid_t uid = (uid_t) ReconstructUInt32 (finger, data);
488 gid_t gid = (gid_t) ReconstructUInt32 (finger, data);
489 mode_t mode = (mode_t) ReconstructUInt32 (finger, data);
490
491 secinfo ("manifest", " File item uid is %d", uid);
492 secinfo ("manifest", " File item gid is %d", gid);
493 secinfo ("manifest", " File item mode is %d", mode);
494
495 item->SetUID (uid);
496 item->SetGID (gid);
497 item->SetMode (mode);
498 }
499
500
501
502 static void ParseItemHeader (uint32 &finger, const uint8* data, ManifestItemType &itemType, u_int64_t &end)
503 {
504 u_int64_t start = finger;
505 u_int64_t length = ReconstructUInt64 (finger, data);
506 itemType = (ManifestItemType) ReconstructUInt16 (finger, data);
507 end = start + length;
508 }
509
510
511
512 void AppleManifest::ReconstructDataBlob (uint32 &finger, const uint8* data, ManifestDataBlobItem*& item)
513 {
514 secinfo ("manifest", "Reconstructing data blob.");
515 item = new ManifestDataBlobItem ();
516 u_int64_t length = ReconstructUInt64 (finger, data);
517 item->SetLength ((size_t)length);
518 item->SetDigest ((SHA1Digest*) (data + finger));
519 finger += kSHA1DigestSize;
520 }
521
522
523
524 void AppleManifest::ReconstructDirectory (uint32 &finger, const uint8* data, ManifestDirectoryItem*& directory)
525 {
526 // make the directory
527 secinfo ("manifest", "Reconstructing directory.");
528 directory = new ManifestDirectoryItem ();
529 ReconstructFileSystemHeader (finger, data, directory);
530
531 ReconstructManifestItemList (finger, data, directory->GetItemList ());
532 }
533
534
535
536 void AppleManifest::ReconstructFile (uint32& finger, const uint8* data, ManifestFileItem *& file)
537 {
538 secinfo ("manifest", "Reconstructing file.");
539 // make the file
540 file = new ManifestFileItem ();
541 ReconstructFileSystemHeader (finger, data, file);
542
543 u_int16_t numForks = ReconstructUInt16 (finger, data);
544 file->SetNumberOfForks (numForks);
545
546 // reconstruct the lengths
547 u_int16_t n;
548 for (n = 0; n < numForks; ++n)
549 {
550 u_int64_t length = ReconstructUInt64 (finger, data);
551 file->SetForkLength (n, (size_t) length);
552 }
553
554 // reconstruct the digests
555 for (n = 0; n < numForks; ++n)
556 {
557 file->SetItemRepresentation (n, data + finger, kSHA1DigestSize);
558 finger += kSHA1DigestSize;
559 }
560 }
561
562
563
564 void AppleManifest::ReconstructSymLink (uint32& finger, const uint8* data, ManifestSymLinkItem*& file)
565 {
566 secinfo ("manifest", "Reconstructing symlink.");
567 file = new ManifestSymLinkItem ();
568 ReconstructFileSystemHeader (finger, data, file);
569
570 file->SetDigest ((const SHA1Digest*) (data + finger));
571 finger += kSHA1DigestSize;
572 }
573
574
575
576 void AppleManifest::ReconstructOther (uint32& finger, const uint8* data, ManifestOtherItem*& other)
577 {
578 secinfo ("manifest", "Reconstructing other.");
579 other = new ManifestOtherItem ();
580 ReconstructFileSystemHeader (finger, data, other);
581 }
582
583
584
585 void AppleManifest::ReconstructManifestItemList (uint32 &finger, const uint8* data, ManifestItemList &itemList)
586 {
587 uint32 start = finger;
588 uint64_t length = ReconstructUInt64 (finger, data);
589 uint32 end = (uint32)(start + length);
590
591 if (length > UINT32_MAX || (length + (uint64_t)start) > (uint64_t)UINT32_MAX)
592 MacOSError::throwMe (errSecManifestDamaged);
593
594 while (finger < end)
595 {
596 u_int64_t itemEnd;
597 ManifestItemType itemType;
598 ParseItemHeader (finger, data, itemType, itemEnd);
599
600 switch (itemType)
601 {
602 case kManifestFileItemType:
603 {
604 ManifestFileItem* file;
605 ReconstructFile (finger, data, file);
606 itemList.push_back (file);
607 }
608 break;
609
610 case kManifestDirectoryItemType:
611 {
612 ManifestDirectoryItem* directory;
613 ReconstructDirectory (finger, data, directory);
614 itemList.push_back (directory);
615 }
616 break;
617
618 case kManifestSymLinkItemType:
619 {
620 ManifestSymLinkItem* symLink;
621 ReconstructSymLink (finger, data, symLink);
622 itemList.push_back (symLink);
623 }
624 break;
625
626 case kManifestOtherType:
627 {
628 ManifestOtherItem* other;
629 ReconstructOther (finger, data, other);
630 itemList.push_back (other);
631 }
632 break;
633
634 case kManifestDataBlobItemType:
635 {
636 ManifestDataBlobItem* item;
637 ReconstructDataBlob (finger, data, item);
638 itemList.push_back (item);
639 }
640 break;
641 }
642
643 if (finger != itemEnd)
644 {
645 MacOSError::throwMe (errSecManifestDamaged);
646 }
647 }
648 }
649
650
651
652 void AppleManifest::ReconstructManifest (uint8* data, uint32 length, ManifestInternal& manifest)
653 {
654 uint32 finger = 0;
655
656 // make sure the passed-in header starts with our magic number
657 if (memcmp (data, gManifestHeader, sizeof (gManifestHeader)) != 0)
658 {
659 MacOSError::throwMe (errSecManifestDamaged);
660 }
661
662 finger += sizeof (gManifestHeader);
663
664 // for now, the version had better be 0x01000000
665 if (memcmp (data + finger, gManifestVersion, sizeof (gManifestVersion)) != 0)
666 {
667 MacOSError::throwMe (errSecManifestDamaged);
668 }
669
670 finger += sizeof (gManifestVersion);
671
672 ReconstructManifestItemList (finger, data, manifest.GetItemList ());
673 }
674
675
676
677 SecCmsMessageRef AppleManifest::GetCmsMessageFromData (CFDataRef data)
678 {
679 // setup decoding
680 SecCmsDecoderRef decoderContext;
681 int result = SecCmsDecoderCreate (NULL, NULL, NULL, NULL, NULL, NULL, NULL, &decoderContext);
682 if (result)
683 {
684 MacOSError::throwMe (errSecManifestCMSFailure);
685 }
686
687 result = SecCmsDecoderUpdate (decoderContext, CFDataGetBytePtr (data), CFDataGetLength (data));
688 if (result)
689 {
690 SecCmsDecoderDestroy(decoderContext);
691 MacOSError::throwMe (errSecManifestCMSFailure);
692 }
693
694 SecCmsMessageRef message;
695 result = SecCmsDecoderFinish (decoderContext, &message);
696 if (result)
697 {
698 MacOSError::throwMe (errSecManifestCMSFailure);
699 }
700
701 return message;
702 }
703
704
705
706 void AppleManifest::Verify (CFDataRef data, SecManifestTrustSetupCallback setupCallback, void* setupContext,
707 SecManifestTrustEvaluateCallback evaluateCallback, void* evaluateContext,
708 SecPolicyRef policy, ManifestInternal *manifest)
709 {
710 SecCmsMessageRef cmsMessage = NULL;
711
712 try
713 {
714 cmsMessage = GetCmsMessageFromData (data);
715
716 SecPolicySearchRef search;
717 OSStatus result;
718
719 SecPolicyRef originalPolicy = policy;
720
721 if (policy == NULL)
722 {
723 // get a basic SecPolicy
724 result = SecPolicySearchCreate (CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &search);
725 MacOSError::check (result);
726
727 result = SecPolicySearchCopyNext (search, &policy);
728 if (result != errSecSuccess)
729 {
730 MacOSError::throwMe (errSecManifestNoPolicy);
731 }
732
733 CFRelease (search);
734 }
735
736 // process the results
737 int contentLevelCount = SecCmsMessageContentLevelCount (cmsMessage);
738 SecCmsSignedDataRef signedData;
739
740 int i = 0;
741 while (i < contentLevelCount)
742 {
743 SecCmsContentInfoRef contentInfo = SecCmsMessageContentLevel (cmsMessage, i++);
744 SECOidTag contentTypeTag = SecCmsContentInfoGetContentTypeTag (contentInfo);
745
746 if (contentTypeTag != SEC_OID_PKCS7_SIGNED_DATA)
747 {
748 continue;
749 }
750
751 signedData = (SecCmsSignedDataRef) SecCmsContentInfoGetContent (contentInfo);
752 if (signedData == NULL)
753 {
754 MacOSError::throwMe (errSecManifestDidNotVerify);
755 }
756
757 // import the certificates found in the cms message
758 result = SecCmsSignedDataImportCerts (signedData, NULL, certUsageObjectSigner, true);
759 if (result != 0)
760 {
761 MacOSError::throwMe (result);
762 }
763
764 int numberOfSigners = SecCmsSignedDataSignerInfoCount (signedData);
765 int j;
766
767 if (numberOfSigners == 0) // no signers? This is a possible attack
768 {
769 MacOSError::throwMe (errSecManifestNoSignersFound);
770 }
771
772 for (j = 0; j < numberOfSigners; ++j)
773 {
774 SecTrustResultType resultType;
775 SecTrustRef trustRef = NULL;
776
777 try
778 {
779 result = SecCmsSignedDataVerifySignerInfo (signedData, j, NULL, policy, &trustRef);
780
781 if (result != 0)
782 {
783 MacOSError::throwMe (result);
784 }
785
786 SecManifestTrustCallbackResult tcResult = setupCallback (trustRef, setupContext);
787 switch (tcResult)
788 {
789 case kSecManifestDoNotVerify:
790 continue;
791
792 case kSecManifestSignerVerified:
793 continue;
794
795 case kSecManifestFailed:
796 MacOSError::throwMe (errSecManifestDidNotVerify);
797
798 case kSecManifestContinue:
799 break;
800 }
801
802 result = SecTrustEvaluate (trustRef, &resultType);
803 if (result != errSecSuccess)
804 {
805 MacOSError::throwMe (result);
806 }
807
808 if (resultType != kSecTrustResultProceed)
809 {
810 if (evaluateCallback (trustRef, resultType, evaluateContext) != kSecManifestSignerVerified)
811 {
812 MacOSError::throwMe (errSecManifestDidNotVerify);
813 }
814 }
815
816 CFRelease (trustRef);
817 }
818 catch (...)
819 {
820 if (trustRef != NULL)
821 {
822 CFRelease (trustRef);
823 }
824
825 throw;
826 }
827 }
828 }
829
830 if (manifest != NULL)
831 {
832 CSSM_DATA_PTR message = SecCmsMessageGetContent (cmsMessage);
833 ReconstructManifest (message->Data, (uint32)message->Length, *manifest);
834 }
835
836 SecCmsMessageDestroy (cmsMessage);
837 if (originalPolicy == NULL)
838 {
839 CFRelease (policy);
840 }
841 }
842 catch (...)
843 {
844 if (cmsMessage != NULL)
845 {
846 SecCmsMessageDestroy (cmsMessage);
847 }
848
849 throw;
850 }
851 }
852
853
854
855 void AppleManifest::AddSigner (SecIdentityRef identityRef)
856 {
857 CFRetain (identityRef);
858 mSignerList.push_back (identityRef);
859 }
860