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