]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_manifest/lib/AppleManifest.cpp
Security-59754.80.3.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
595 while (finger < end)
596 {
597 u_int64_t itemEnd;
598 ManifestItemType itemType;
599 ParseItemHeader (finger, data, itemType, itemEnd);
600
601 switch (itemType)
602 {
603 case kManifestFileItemType:
604 {
605 ManifestFileItem* file;
606 ReconstructFile (finger, data, file);
607 itemList.push_back (file);
608 }
609 break;
610
611 case kManifestDirectoryItemType:
612 {
613 ManifestDirectoryItem* directory;
614 ReconstructDirectory (finger, data, directory);
615 itemList.push_back (directory);
616 }
617 break;
618
619 case kManifestSymLinkItemType:
620 {
621 ManifestSymLinkItem* symLink;
622 ReconstructSymLink (finger, data, symLink);
623 itemList.push_back (symLink);
624 }
625 break;
626
627 case kManifestOtherType:
628 {
629 ManifestOtherItem* other;
630 ReconstructOther (finger, data, other);
631 itemList.push_back (other);
632 }
633 break;
634
635 case kManifestDataBlobItemType:
636 {
637 ManifestDataBlobItem* item;
638 ReconstructDataBlob (finger, data, item);
639 itemList.push_back (item);
640 }
641 break;
642 }
643
644 if (finger != itemEnd)
645 {
646 MacOSError::throwMe (errSecManifestDamaged);
647 }
648 }
649 }
650
651
652
653 void AppleManifest::ReconstructManifest (uint8* data, uint32 length, ManifestInternal& manifest)
654 {
655 uint32 finger = 0;
656
657 // make sure the passed-in header starts with our magic number
658 if (memcmp (data, gManifestHeader, sizeof (gManifestHeader)) != 0)
659 {
660 MacOSError::throwMe (errSecManifestDamaged);
661 }
662
663 finger += sizeof (gManifestHeader);
664
665 // for now, the version had better be 0x01000000
666 if (memcmp (data + finger, gManifestVersion, sizeof (gManifestVersion)) != 0)
667 {
668 MacOSError::throwMe (errSecManifestDamaged);
669 }
670
671 finger += sizeof (gManifestVersion);
672
673 ReconstructManifestItemList (finger, data, manifest.GetItemList ());
674 }
675
676
677
678 SecCmsMessageRef AppleManifest::GetCmsMessageFromData (CFDataRef data)
679 {
680 // setup decoding
681 SecCmsDecoderRef decoderContext;
682 int result = SecCmsDecoderCreate (NULL, NULL, NULL, NULL, NULL, NULL, NULL, &decoderContext);
683 if (result)
684 {
685 MacOSError::throwMe (errSecManifestCMSFailure);
686 }
687
688 result = SecCmsDecoderUpdate (decoderContext, CFDataGetBytePtr (data), CFDataGetLength (data));
689 if (result)
690 {
691 SecCmsDecoderDestroy(decoderContext);
692 MacOSError::throwMe (errSecManifestCMSFailure);
693 }
694
695 SecCmsMessageRef message;
696 result = SecCmsDecoderFinish (decoderContext, &message);
697 if (result)
698 {
699 MacOSError::throwMe (errSecManifestCMSFailure);
700 }
701
702 return message;
703 }
704
705
706
707 void AppleManifest::Verify (CFDataRef data, SecManifestTrustSetupCallback setupCallback, void* setupContext,
708 SecManifestTrustEvaluateCallback evaluateCallback, void* evaluateContext,
709 SecPolicyRef policy, ManifestInternal *manifest)
710 {
711 SecCmsMessageRef cmsMessage = NULL;
712
713 try
714 {
715 cmsMessage = GetCmsMessageFromData (data);
716
717 SecPolicySearchRef search;
718 OSStatus result;
719
720 SecPolicyRef originalPolicy = policy;
721
722 if (policy == NULL)
723 {
724 // get a basic SecPolicy
725 result = SecPolicySearchCreate (CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &search);
726 MacOSError::check (result);
727
728 result = SecPolicySearchCopyNext (search, &policy);
729 if (result != errSecSuccess)
730 {
731 MacOSError::throwMe (errSecManifestNoPolicy);
732 }
733
734 CFRelease (search);
735 }
736
737 // process the results
738 int contentLevelCount = SecCmsMessageContentLevelCount (cmsMessage);
739 SecCmsSignedDataRef signedData;
740
741 int i = 0;
742 while (i < contentLevelCount)
743 {
744 SecCmsContentInfoRef contentInfo = SecCmsMessageContentLevel (cmsMessage, i++);
745 SECOidTag contentTypeTag = SecCmsContentInfoGetContentTypeTag (contentInfo);
746
747 if (contentTypeTag != SEC_OID_PKCS7_SIGNED_DATA)
748 {
749 continue;
750 }
751
752 signedData = (SecCmsSignedDataRef) SecCmsContentInfoGetContent (contentInfo);
753 if (signedData == NULL)
754 {
755 MacOSError::throwMe (errSecManifestDidNotVerify);
756 }
757
758 // import the certificates found in the cms message
759 result = SecCmsSignedDataImportCerts (signedData, NULL, certUsageObjectSigner, true);
760 if (result != 0)
761 {
762 MacOSError::throwMe (result);
763 }
764
765 int numberOfSigners = SecCmsSignedDataSignerInfoCount (signedData);
766 int j;
767
768 if (numberOfSigners == 0) // no signers? This is a possible attack
769 {
770 MacOSError::throwMe (errSecManifestNoSignersFound);
771 }
772
773 for (j = 0; j < numberOfSigners; ++j)
774 {
775 SecTrustResultType resultType;
776 SecTrustRef trustRef = NULL;
777
778 try
779 {
780 result = SecCmsSignedDataVerifySignerInfo (signedData, j, NULL, policy, &trustRef);
781
782 if (result != 0)
783 {
784 MacOSError::throwMe (result);
785 }
786
787 SecManifestTrustCallbackResult tcResult = setupCallback (trustRef, setupContext);
788 switch (tcResult)
789 {
790 case kSecManifestDoNotVerify:
791 continue;
792
793 case kSecManifestSignerVerified:
794 continue;
795
796 case kSecManifestFailed:
797 MacOSError::throwMe (errSecManifestDidNotVerify);
798
799 case kSecManifestContinue:
800 break;
801 }
802
803 result = SecTrustEvaluate (trustRef, &resultType);
804 if (result != errSecSuccess)
805 {
806 MacOSError::throwMe (result);
807 }
808
809 if (resultType != kSecTrustResultProceed)
810 {
811 if (evaluateCallback (trustRef, resultType, evaluateContext) != kSecManifestSignerVerified)
812 {
813 MacOSError::throwMe (errSecManifestDidNotVerify);
814 }
815 }
816
817 CFRelease (trustRef);
818 }
819 catch (...)
820 {
821 if (trustRef != NULL)
822 {
823 CFRelease (trustRef);
824 }
825
826 throw;
827 }
828 }
829 }
830
831 if (manifest != NULL)
832 {
833 CSSM_DATA_PTR message = SecCmsMessageGetContent (cmsMessage);
834 ReconstructManifest (message->Data, (uint32)message->Length, *manifest);
835 }
836
837 SecCmsMessageDestroy (cmsMessage);
838 if (originalPolicy == NULL)
839 {
840 CFRelease (policy);
841 }
842 }
843 catch (...)
844 {
845 if (cmsMessage != NULL)
846 {
847 SecCmsMessageDestroy (cmsMessage);
848 }
849
850 throw;
851 }
852 }
853
854
855
856 void AppleManifest::AddSigner (SecIdentityRef identityRef)
857 {
858 CFRetain (identityRef);
859 mSignerList.push_back (identityRef);
860 }
861