2 * Copyright (c) 2003-2004,2006-2010 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 #include "OTATrustUtilities.h"
35 #include <sys/syslimits.h>
38 #include <CoreFoundation/CoreFoundation.h>
40 #include "SecFramework.h"
42 #include <sys/param.h>
44 #include <utilities/SecCFRelease.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/SecCFWrappers.h>
47 #include <Security/SecBasePriv.h>
48 #include <Security/SecFramework.h>
49 #include <dispatch/dispatch.h>
50 #include <CommonCrypto/CommonDigest.h>
52 //#define VERBOSE_LOGGING 1
56 static void TestOTALog(const char* sz
, ...)
61 FILE* fp
= fopen("/tmp/secd_OTAUtil.log", "a");
72 #define TestOTALog(sz, ...)
77 //#define NEW_LOCATION 1
80 static const char* kBaseAssertDirectory
= "/var/OTAPKI/Assets";
82 static const char* kBaseAssertDirectory
= "/var/Keychains/Assets";
85 static const char* kVersionDirectoryNamePrefix
= "Version_";
86 static const char* kNumberString
= "%d";
90 unsigned char hash
[CC_SHA1_DIGEST_LENGTH
];
93 typedef struct index_record index_record
;
96 struct _OpaqueSecOTAPKI
99 CFSetRef _blackListSet
;
100 CFSetRef _grayListSet
;
101 CFArrayRef _escrowCertificates
;
102 CFDictionaryRef _evPolicyToAnchorMapping
;
103 CFDictionaryRef _anchorLookupTable
;
104 const char* _anchorTable
;
108 CFGiblisFor(SecOTAPKI
)
110 static CF_RETURNS_RETAINED CFStringRef
SecOTAPKICopyDescription(CFTypeRef cf
)
112 SecOTAPKIRef otapkiRef
= (SecOTAPKIRef
)cf
;
113 return CFStringCreateWithFormat(kCFAllocatorDefault
,NULL
,CFSTR("<SecOTAPKIRef: version %d>"), otapkiRef
->_assetVersion
);
116 static void SecOTAPKIDestroy(CFTypeRef cf
)
118 SecOTAPKIRef otapkiref
= (SecOTAPKIRef
)cf
;
120 CFReleaseNull(otapkiref
->_blackListSet
);
121 CFReleaseNull(otapkiref
->_grayListSet
);
122 CFReleaseNull(otapkiref
->_escrowCertificates
);
124 CFReleaseNull(otapkiref
->_evPolicyToAnchorMapping
);
125 CFReleaseNull(otapkiref
->_anchorLookupTable
);
127 free((void *)otapkiref
->_anchorTable
);
130 static CFDataRef
SecOTACopyFileContents(const char *path
)
132 CFMutableDataRef data
= NULL
;
133 int fd
= open(path
, O_RDONLY
, 0666);
140 off_t fsize
= lseek(fd
, 0, SEEK_END
);
141 if (fsize
== (off_t
)-1)
146 if (fsize
> (off_t
)INT32_MAX
)
151 data
= CFDataCreateMutable(kCFAllocatorDefault
, (CFIndex
)fsize
);
157 CFDataSetLength(data
, (CFIndex
)fsize
);
158 void *buf
= CFDataGetMutableBytePtr(data
);
164 off_t total_read
= 0;
165 while (total_read
< fsize
)
169 bytes_read
= pread(fd
, buf
, (size_t)(fsize
- total_read
), total_read
);
170 if (bytes_read
== -1)
178 total_read
+= bytes_read
;
198 static Boolean
PathExists(const char* path
, size_t* pFileSize
)
200 TestOTALog("In PathExists: checking path %s\n", path
);
201 Boolean result
= false;
204 if (NULL
!= pFileSize
)
209 int stat_result
= stat(path
, &sb
);
210 result
= (stat_result
== 0);
215 TestOTALog("In PathExists: stat returned 0 for %s\n", path
);
216 if (S_ISDIR(sb
.st_mode
))
218 TestOTALog("In PathExists: %s is a directory\n", path
);
224 TestOTALog("In PathExists: %s is a file\n", path
);
226 if (NULL
!= pFileSize
)
228 *pFileSize
= (size_t)sb
.st_size
;
235 TestOTALog("In PathExists: stat returned %d for %s\n", stat_result
, path
);
236 int local_errno
= errno
;
240 TestOTALog("In PathExists: stat failed because of EACCES\n");
244 TestOTALog("In PathExists: stat failed because of EBADF (Not likely)\n");
248 TestOTALog("In PathExists: stat failed because of EFAULT (huh?)\n");
252 TestOTALog("In PathExists: stat failed because of ELOOP (huh?)\n");
256 TestOTALog("In PathExists: stat failed because of ENAMETOOLONG (huh?)\n");
260 TestOTALog("In PathExists: stat failed because of ENOENT (missing?)\n");
264 TestOTALog("In PathExists: stat failed because of ENOMEM (really?)\n");
268 TestOTALog("In PathExists: stat failed because of ENOTDIR (really?)\n");
272 TestOTALog("In PathExists: stat failed because of EOVERFLOW (really?)\n");
276 TestOTALog("In PathExists: unknown errno of %d\n", local_errno
);
280 #endif // #if VERBOSE_LOGGING
285 static int unlink_cb(const char *fpath
, const struct stat
*sb
, int typeflag
, struct FTW
*ftwbuf
)
287 int rv
= remove(fpath
);
291 static int rmrf(char *path
)
293 const char* p1
= NULL
;
294 char path_buffer
[PATH_MAX
];
295 memset(path_buffer
, 0, sizeof(path_buffer
));
297 p1
= realpath(path
, path_buffer
);
298 if (!strncmp(path
, p1
, PATH_MAX
))
300 return nftw(path
, unlink_cb
, 64, FTW_DEPTH
| FTW_PHYS
);
305 static const char* InitOTADirectory(int* pAssetVersion
)
307 TestOTALog("In InitOTADirectory\n");
308 const char* result
= NULL
;
310 char buffer
[PATH_MAX
];
314 int current_version
= 0;
315 CFIndex asset_number
= 0;
317 bool assetDirectoryExists
= PathExists(kBaseAssertDirectory
, NULL
);
318 if (assetDirectoryExists
)
320 TestOTALog("InitOTADirectory: %s exists\n", kBaseAssertDirectory
);
321 dp
= opendir (kBaseAssertDirectory
);
324 TestOTALog("InitOTADirectory: opendir sucessfully open %s\n", kBaseAssertDirectory
);
325 while ((ep
= readdir(dp
)))
327 TestOTALog("InitOTADirectory: processing name %s\n", ep
->d_name
);
328 if (strstr(ep
->d_name
, kVersionDirectoryNamePrefix
))
330 TestOTALog("InitOTADirectory: %s matches\n", ep
->d_name
);
331 memset(buffer
, 0, sizeof(buffer
));
332 snprintf(buffer
, sizeof(buffer
), "%s%s", kVersionDirectoryNamePrefix
, kNumberString
);
334 sscanf(ep
->d_name
, buffer
, &version
);
336 TestOTALog("InitOTADirectory: version = %d\n", version
);
338 if (current_version
> 0)
340 if (version
> current_version
)
342 // There is more than one Version_ directory.
343 // Delete the one with the smaller version number
344 memset(buffer
, 0, sizeof(buffer
));
345 snprintf(buffer
, sizeof(buffer
), "%s/%s%d", kBaseAssertDirectory
, kVersionDirectoryNamePrefix
, current_version
);
346 if (PathExists(buffer
, NULL
))
350 current_version
= version
;
355 current_version
= version
;
363 TestOTALog("InitOTADirectory: opendir failed to open %s\n", kBaseAssertDirectory
);
368 TestOTALog("InitOTADirectory: PathExists returned false for %s\n", kBaseAssertDirectory
);
371 memset(buffer
, 0, sizeof(buffer
));
373 if (0 == current_version
)
375 TestOTALog("InitOTADirectory: current_version = 0\n");
376 // No Assets are installed so get the Asset Verson from the AssertVersion.plist in the Security.framework
378 // Look in the resources for a AssetVerstion.plst file
380 CFDataRef assetVersionData
= SecFrameworkCopyResourceContents(CFSTR("AssetVersion"), CFSTR("plist"), NULL
);
381 if (NULL
!= assetVersionData
)
383 CFPropertyListFormat propFormat
;
384 CFDictionaryRef versionPlist
= CFPropertyListCreateWithData(kCFAllocatorDefault
, assetVersionData
, 0, &propFormat
, NULL
);
385 if (NULL
!= versionPlist
&& CFDictionaryGetTypeID() == CFGetTypeID(versionPlist
))
387 CFNumberRef versionNumber
= (CFNumberRef
)CFDictionaryGetValue(versionPlist
, (const void *)CFSTR("VersionNumber"));
388 if (NULL
!= versionNumber
)
390 CFNumberGetValue(versionNumber
, kCFNumberCFIndexType
, &asset_number
);
393 CFReleaseSafe(versionPlist
);
394 CFReleaseSafe(assetVersionData
);
397 current_version
= (int)asset_number
;
401 TestOTALog("InitOTADirectory: current_version = %d\n", current_version
);
402 snprintf(buffer
, sizeof(buffer
), "%s/%s%d", kBaseAssertDirectory
, kVersionDirectoryNamePrefix
, current_version
);
403 size_t length
= strlen(buffer
);
404 char* temp_str
= (char*)malloc(length
+ 1);
405 memset(temp_str
, 0, (length
+ 1));
406 strncpy(temp_str
, buffer
, length
);
410 if (NULL
!= pAssetVersion
)
412 *pAssetVersion
= current_version
;
417 static CFSetRef
InitializeBlackList(const char* path_ptr
)
419 CFSetRef result
= NULL
;
421 // Check to see if the EVRoots.plist file is in the asset location
422 CFDataRef xmlData
= NULL
;
423 const char* asset_path
= path_ptr
;
424 if (NULL
== asset_path
)
426 // There is no OTA asset file so use the file in the Sercurity.framework bundle
427 xmlData
= SecFrameworkCopyResourceContents(CFSTR("Blocked"), CFSTR("plist"), NULL
);
431 char file_path_buffer
[PATH_MAX
];
432 memset(file_path_buffer
, 0, PATH_MAX
);
433 snprintf(file_path_buffer
, PATH_MAX
, "%s/Blocked.plist", asset_path
);
435 xmlData
= SecOTACopyFileContents(file_path_buffer
);
439 xmlData
= SecFrameworkCopyResourceContents(CFSTR("Blocked"), CFSTR("plist"), NULL
);
443 CFPropertyListRef blackKeys
= NULL
;
446 blackKeys
= CFPropertyListCreateWithData(kCFAllocatorDefault
, xmlData
, kCFPropertyListImmutable
, NULL
, NULL
);
452 CFMutableSetRef tempSet
= NULL
;
453 if (CFGetTypeID(blackKeys
) == CFArrayGetTypeID())
455 tempSet
= CFSetCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeSetCallBacks
);
458 CFRelease(blackKeys
);
461 CFArrayRef blackKeyArray
= (CFArrayRef
)blackKeys
;
462 CFIndex num_keys
= CFArrayGetCount(blackKeyArray
);
463 for (CFIndex idx
= 0; idx
< num_keys
; idx
++)
465 CFDataRef key_data
= (CFDataRef
)CFArrayGetValueAtIndex(blackKeyArray
, idx
);
466 CFSetAddValue(tempSet
, key_data
);
471 CFRelease(blackKeys
);
479 CFRelease(blackKeys
);
485 static CFSetRef
InitializeGrayList(const char* path_ptr
)
487 CFSetRef result
= NULL
;
489 // Check to see if the EVRoots.plist file is in the asset location
490 CFDataRef xmlData
= NULL
;
491 const char* asset_path
= path_ptr
;
492 if (NULL
== asset_path
)
494 // There is no updated asset file so use the file in the Sercurity.framework bundle
495 xmlData
= SecFrameworkCopyResourceContents(CFSTR("GrayListedKeys"), CFSTR("plist"), NULL
);
499 char file_path_buffer
[PATH_MAX
];
500 memset(file_path_buffer
, 0, PATH_MAX
);
501 snprintf(file_path_buffer
, PATH_MAX
, "%s/GrayListedKeys.plist", asset_path
);
503 xmlData
= SecOTACopyFileContents(file_path_buffer
);
507 xmlData
= SecFrameworkCopyResourceContents(CFSTR("GrayListedKeys"), CFSTR("plist"), NULL
);
511 CFPropertyListRef grayKeys
= NULL
;
514 grayKeys
= CFPropertyListCreateWithData(kCFAllocatorDefault
, xmlData
, kCFPropertyListImmutable
, NULL
, NULL
);
520 CFMutableSetRef tempSet
= NULL
;
521 if (CFGetTypeID(grayKeys
) == CFArrayGetTypeID())
523 tempSet
= CFSetCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeSetCallBacks
);
529 CFArrayRef grayKeyArray
= (CFArrayRef
)grayKeys
;
530 CFIndex num_keys
= CFArrayGetCount(grayKeyArray
);
531 for (CFIndex idx
= 0; idx
< num_keys
; idx
++)
533 CFDataRef key_data
= (CFDataRef
)CFArrayGetValueAtIndex(grayKeyArray
, idx
);
534 CFSetAddValue(tempSet
, key_data
);
553 static CFDictionaryRef
InitializeEVPolicyToAnchorDigestsTable(const char* path_ptr
)
555 CFDictionaryRef result
= NULL
;
557 // Check to see if the EVRoots.plist file is in the asset location
558 CFDataRef xmlData
= NULL
;
559 const char* asset_path
= path_ptr
;
560 if (NULL
== asset_path
)
562 // There is no updated asset file so use the file in the Sercurity.framework bundle
563 xmlData
= SecFrameworkCopyResourceContents(CFSTR("EVRoots"), CFSTR("plist"), NULL
);
567 char file_path_buffer
[PATH_MAX
];
568 memset(file_path_buffer
, 0, PATH_MAX
);
569 snprintf(file_path_buffer
, PATH_MAX
, "%s/EVRoots.plist", asset_path
);
571 xmlData
= SecOTACopyFileContents(file_path_buffer
);
575 xmlData
= SecFrameworkCopyResourceContents(CFSTR("EVRoots"), CFSTR("plist"), NULL
);
579 CFPropertyListRef evroots
= NULL
;
582 evroots
= CFPropertyListCreateWithData(
583 kCFAllocatorDefault
, xmlData
, kCFPropertyListImmutable
, NULL
, NULL
);
589 if (CFGetTypeID(evroots
) == CFDictionaryGetTypeID())
591 /* @@@ Ensure that each dictionary key is a dotted list of digits,
592 each value is an NSArrayRef and each element in the array is a
595 result
= (CFDictionaryRef
)evroots
;
599 secwarning("EVRoot.plist is wrong type.");
607 static void* MapFile(const char* path
, int* out_fd
, size_t* out_file_size
)
610 void* temp_result
= NULL
;
611 if (NULL
== path
|| NULL
== out_fd
|| NULL
== out_file_size
)
620 *out_fd
= open(path
, O_RDONLY
, 0666);
627 off_t fsize
= lseek(*out_fd
, 0, SEEK_END
);
628 if (fsize
== (off_t
)-1)
633 if (fsize
> (off_t
)INT32_MAX
)
640 size_t malloc_size
= (size_t)fsize
;
642 temp_result
= malloc(malloc_size
);
643 if (NULL
== temp_result
)
650 *out_file_size
= malloc_size
;
652 off_t total_read
= 0;
653 while (total_read
< fsize
)
657 bytes_read
= pread(*out_fd
, temp_result
, (size_t)(fsize
- total_read
), total_read
);
658 if (bytes_read
== -1)
674 total_read
+= bytes_read
;
677 if (NULL
!= temp_result
)
679 result
= temp_result
;
685 static void UnMapFile(void* mapped_data
, size_t data_size
)
687 #pragma unused(mapped_data, data_size)
688 if (NULL
!= mapped_data
)
690 free((void *)mapped_data
);
695 static bool InitializeAnchorTable(const char* path_ptr
, CFDictionaryRef
* pLookupTable
, const char** ppAnchorTable
)
700 if (NULL
== pLookupTable
|| NULL
== ppAnchorTable
)
705 *pLookupTable
= NULL
;
706 *ppAnchorTable
= NULL
;;
708 // first see if there is a file at /var/db/OTA_Anchors
709 const char* dir_path
= NULL
;
710 CFDataRef cert_index_file_data
= NULL
;
711 char file_path_buffer
[PATH_MAX
];
712 CFURLRef table_data_url
= NULL
;
713 CFStringRef table_data_cstr_path
= NULL
;
714 const char* table_data_path
= NULL
;
715 const index_record
* pIndex
= NULL
;
716 size_t index_offset
= 0;
717 size_t index_data_size
= 0;
718 CFMutableDictionaryRef anchorLookupTable
= NULL
;
719 uint32_t offset_int_value
= 0;
720 CFNumberRef index_offset_value
= NULL
;
721 CFDataRef index_hash
= NULL
;
722 CFMutableArrayRef offsets
= NULL
;
723 Boolean release_offset
= false;
725 char* local_anchorTable
= NULL
;
726 size_t local_anchorTableSize
= 0;
727 int local_anchorTable_fd
= -1;
729 // ------------------------------------------------------------------------
730 // First determine if there are asset files at /var/Keychains. If there
731 // are files use them for the trust table. Otherwise, use the files in the
732 // Security.framework bundle.
734 // The anchor table file is mapped into memory. This SHOULD be OK as the
735 // size of the data is around 250K.
736 // ------------------------------------------------------------------------
739 if (NULL
!= dir_path
)
741 // There is a set of OTA asset files
742 memset(file_path_buffer
, 0, PATH_MAX
);
743 snprintf(file_path_buffer
, PATH_MAX
, "%s/certsIndex.data", dir_path
);
744 cert_index_file_data
= SecOTACopyFileContents(file_path_buffer
);
746 if (NULL
!= cert_index_file_data
)
748 memset(file_path_buffer
, 0, PATH_MAX
);
749 snprintf(file_path_buffer
, PATH_MAX
, "%s/certsTable.data", dir_path
);
750 local_anchorTable
= (char *)MapFile(file_path_buffer
, &local_anchorTable_fd
, &local_anchorTableSize
);
753 free((void *)dir_path
);
757 // Check to see if kAnchorTable was indeed set
758 if (NULL
== local_anchorTable
)
760 // local_anchorTable is still NULL so the asset in the Security framework needs to be used.
761 CFReleaseSafe(cert_index_file_data
);
762 cert_index_file_data
= SecFrameworkCopyResourceContents(CFSTR("certsIndex"), CFSTR("data"), NULL
);
763 table_data_url
= SecFrameworkCopyResourceURL(CFSTR("certsTable"), CFSTR("data"), NULL
);
764 if (NULL
!= table_data_url
)
766 table_data_cstr_path
= CFURLCopyFileSystemPath(table_data_url
, kCFURLPOSIXPathStyle
);
767 if (NULL
!= table_data_cstr_path
)
769 memset(file_path_buffer
, 0, PATH_MAX
);
770 table_data_path
= CFStringGetCStringPtr(table_data_cstr_path
, kCFStringEncodingUTF8
);
771 if (NULL
== table_data_path
)
773 if (CFStringGetCString(table_data_cstr_path
, file_path_buffer
, PATH_MAX
, kCFStringEncodingUTF8
))
775 table_data_path
= file_path_buffer
;
778 local_anchorTable
= (char *)MapFile(table_data_path
, &local_anchorTable_fd
, &local_anchorTableSize
);
779 CFReleaseSafe(table_data_cstr_path
);
782 CFReleaseSafe(table_data_url
);
785 if (NULL
== local_anchorTable
|| NULL
== cert_index_file_data
)
788 CFReleaseSafe(cert_index_file_data
);
792 // ------------------------------------------------------------------------
793 // Now that the locations of the files are known and the table file has
794 // been mapped into memory, create a dictionary that maps the SHA1 hash of
795 // normalized issuer to the offset in the mapped anchor table file which
796 // contains a index_record to the correct certificate
797 // ------------------------------------------------------------------------
798 pIndex
= (const index_record
*)CFDataGetBytePtr(cert_index_file_data
);
799 index_data_size
= CFDataGetLength(cert_index_file_data
);
801 anchorLookupTable
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
802 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
804 for (index_offset
= index_data_size
; index_offset
> 0; index_offset
-= sizeof(index_record
), pIndex
++)
806 offset_int_value
= pIndex
->offset
;
808 index_offset_value
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &offset_int_value
);
809 index_hash
= CFDataCreate(kCFAllocatorDefault
, pIndex
->hash
, CC_SHA1_DIGEST_LENGTH
);
811 // see if the dictionary already has this key
812 release_offset
= false;
813 offsets
= (CFMutableArrayRef
)CFDictionaryGetValue(anchorLookupTable
, index_hash
);
816 offsets
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
817 release_offset
= true;
821 CFArrayAppendValue(offsets
, index_offset_value
);
823 // set the key value pair in the dictionary
824 CFDictionarySetValue(anchorLookupTable
, index_hash
, offsets
);
826 CFRelease(index_offset_value
);
827 CFRelease(index_hash
);
834 CFRelease(cert_index_file_data
);
836 if (NULL
!= anchorLookupTable
&& NULL
!= local_anchorTable
)
838 *pLookupTable
= anchorLookupTable
;
839 *ppAnchorTable
= local_anchorTable
;
844 CFReleaseSafe(anchorLookupTable
);
845 if (NULL
!= local_anchorTable
)
847 UnMapFile(local_anchorTable
, local_anchorTableSize
);
848 //munmap(kAnchorTable, local_anchorTableSize);
849 local_anchorTable
= NULL
;
850 local_anchorTableSize
= 0;
857 static CFArrayRef
InitializeEscrowCertificates(const char* path_ptr
)
859 CFArrayRef result
= NULL
;
860 CFDataRef file_data
= NULL
;
862 const char* dir_path
= path_ptr
;
863 if (NULL
== dir_path
)
865 file_data
= SecFrameworkCopyResourceContents(CFSTR("AppleESCertificates"), CFSTR("plist"), NULL
);
870 memset(buffer
, 0, 1024);
871 snprintf(buffer
, 1024, "%s/AppleESCertificates.plist", dir_path
);
872 file_data
= SecOTACopyFileContents(buffer
);
875 if (NULL
!= file_data
)
877 CFPropertyListFormat propFormat
;
878 CFDictionaryRef certsDictionary
= CFPropertyListCreateWithData(kCFAllocatorDefault
, file_data
, 0, &propFormat
, NULL
);
879 if (NULL
!= certsDictionary
&& CFDictionaryGetTypeID() == CFGetTypeID((CFTypeRef
)certsDictionary
))
881 CFArrayRef certs
= (CFArrayRef
)CFDictionaryGetValue(certsDictionary
, CFSTR("ProductionEscrowKey"));
882 if (NULL
!= certs
&& CFArrayGetTypeID() == CFGetTypeID((CFTypeRef
)certs
) && CFArrayGetCount(certs
) > 0)
884 result
= CFArrayCreateCopy(kCFAllocatorDefault
, certs
);
886 CFRelease(certsDictionary
);
888 CFRelease(file_data
);
895 static SecOTAPKIRef
SecOTACreate()
897 TestOTALog("In SecOTACreate\n");
899 SecOTAPKIRef otapkiref
= NULL
;
901 otapkiref
= CFTypeAllocate(SecOTAPKI
, struct _OpaqueSecOTAPKI
, kCFAllocatorDefault
);
903 if (NULL
== otapkiref
)
908 // Mkae suer that if this routine has to bail that the clean up
909 // will do the right thing
910 otapkiref
->_blackListSet
= NULL
;
911 otapkiref
->_grayListSet
= NULL
;
912 otapkiref
->_escrowCertificates
= NULL
;
913 otapkiref
->_evPolicyToAnchorMapping
= NULL
;
914 otapkiref
->_anchorLookupTable
= NULL
;
915 otapkiref
->_anchorTable
= NULL
;
916 otapkiref
->_assetVersion
= 0;
918 // Start off by getting the correct asset directory info
919 int asset_version
= 0;
920 const char* path_ptr
= InitOTADirectory(&asset_version
);
921 otapkiref
->_assetVersion
= asset_version
;
923 TestOTALog("SecOTACreate: asset_path = %s\n", path_ptr
);
924 TestOTALog("SecOTACreate: asset_version = %d\n", asset_version
);
926 // Get the set of black listed keys
927 CFSetRef blackKeysSet
= InitializeBlackList(path_ptr
);
928 if (NULL
== blackKeysSet
)
930 CFReleaseNull(otapkiref
);
933 otapkiref
->_blackListSet
= blackKeysSet
;
935 // Get the set of gray listed keys
936 CFSetRef grayKeysSet
= InitializeGrayList(path_ptr
);
937 if (NULL
== grayKeysSet
)
939 CFReleaseNull(otapkiref
);
942 otapkiref
->_grayListSet
= grayKeysSet
;
944 CFArrayRef escrowCerts
= InitializeEscrowCertificates(path_ptr
);
945 if (NULL
== escrowCerts
)
947 CFReleaseNull(otapkiref
);
950 otapkiref
->_escrowCertificates
= escrowCerts
;
952 // Geht the mapping of EV Policy OIDs to Anchor digest
953 CFDictionaryRef evOidToAnchorDigestMap
= InitializeEVPolicyToAnchorDigestsTable(path_ptr
);
954 if (NULL
== evOidToAnchorDigestMap
)
956 CFReleaseNull(otapkiref
);
959 otapkiref
->_evPolicyToAnchorMapping
= evOidToAnchorDigestMap
;
961 CFDictionaryRef anchorLookupTable
= NULL
;
962 const char* anchorTablePtr
= NULL
;
964 if (!InitializeAnchorTable(path_ptr
, &anchorLookupTable
, &anchorTablePtr
))
966 CFReleaseSafe(anchorLookupTable
);
967 if (NULL
!= anchorTablePtr
)
969 free((void *)anchorTablePtr
);
972 CFReleaseNull(otapkiref
);
975 otapkiref
->_anchorLookupTable
= anchorLookupTable
;
976 otapkiref
->_anchorTable
= anchorTablePtr
;
980 static dispatch_once_t kInitializeOTAPKI
= 0;
981 static const char* kOTAQueueLabel
= "com.apple.security.OTAPKIQueue";
982 static dispatch_queue_t kOTAQueue
;
983 static SecOTAPKIRef kCurrentOTAPKIRef
= NULL
;
985 SecOTAPKIRef
SecOTAPKICopyCurrentOTAPKIRef()
987 __block SecOTAPKIRef result
= NULL
;
988 dispatch_once(&kInitializeOTAPKI
,
990 kOTAQueue
= dispatch_queue_create(kOTAQueueLabel
, NULL
);
991 kCurrentOTAPKIRef
= SecOTACreate();
994 dispatch_sync(kOTAQueue
,
996 result
= kCurrentOTAPKIRef
;
997 CFRetainSafe(result
);
1003 CFSetRef
SecOTAPKICopyBlackListSet(SecOTAPKIRef otapkiRef
)
1005 CFSetRef result
= NULL
;
1006 if (NULL
== otapkiRef
)
1011 result
= otapkiRef
->_blackListSet
;
1012 CFRetainSafe(result
);
1017 CFSetRef
SecOTAPKICopyGrayList(SecOTAPKIRef otapkiRef
)
1019 CFSetRef result
= NULL
;
1020 if (NULL
== otapkiRef
)
1025 result
= otapkiRef
->_grayListSet
;
1026 CFRetainSafe(result
);
1030 CFArrayRef
SecOTAPKICopyEscrowCertificates(SecOTAPKIRef otapkiRef
)
1032 CFArrayRef result
= NULL
;
1033 if (NULL
== otapkiRef
)
1038 result
= otapkiRef
->_escrowCertificates
;
1039 CFRetainSafe(result
);
1044 CFDictionaryRef
SecOTAPKICopyEVPolicyToAnchorMapping(SecOTAPKIRef otapkiRef
)
1046 CFDictionaryRef result
= NULL
;
1047 if (NULL
== otapkiRef
)
1052 result
= otapkiRef
->_evPolicyToAnchorMapping
;
1053 CFRetainSafe(result
);
1058 CFDictionaryRef
SecOTAPKICopyAnchorLookupTable(SecOTAPKIRef otapkiRef
)
1060 CFDictionaryRef result
= NULL
;
1061 if (NULL
== otapkiRef
)
1066 result
= otapkiRef
->_anchorLookupTable
;
1067 CFRetainSafe(result
);
1071 const char* SecOTAPKIGetAnchorTable(SecOTAPKIRef otapkiRef
)
1073 const char* result
= NULL
;
1074 if (NULL
== otapkiRef
)
1079 result
= otapkiRef
->_anchorTable
;
1083 int SecOTAPKIGetAssetVersion(SecOTAPKIRef otapkiRef
)
1086 if (NULL
== otapkiRef
)
1091 result
= otapkiRef
->_assetVersion
;
1095 void SecOTAPKIRefreshData()
1097 TestOTALog("In SecOTAPKIRefreshData\n");
1098 SecOTAPKIRef new_otaPKRef
= SecOTACreate();
1099 dispatch_sync(kOTAQueue
,
1101 CFReleaseSafe(kCurrentOTAPKIRef
);
1102 kCurrentOTAPKIRef
= new_otaPKRef
;
1106 CFArrayRef
SecOTAPKICopyCurrentEscrowCertificates(CFErrorRef
* error
)
1108 CFArrayRef result
= NULL
;
1110 SecOTAPKIRef otapkiref
= SecOTAPKICopyCurrentOTAPKIRef();
1111 if (NULL
== otapkiref
)
1113 SecError(errSecInternal
, error
, CFSTR("Unable to get the current OTAPKIRef"));
1117 result
= SecOTAPKICopyEscrowCertificates(otapkiref
);
1118 CFRelease(otapkiref
);
1122 SecError(errSecInternal
, error
, CFSTR("Could not get the array of escrow certificates form the current OTAPKIRef"));
1127 int SecOTAPKIGetCurrentAssetVersion(CFErrorRef
* error
)
1131 SecOTAPKIRef otapkiref
= SecOTAPKICopyCurrentOTAPKIRef();
1132 if (NULL
== otapkiref
)
1134 SecError(errSecInternal
, error
, CFSTR("Unable to get the current OTAPKIRef"));
1138 result
= otapkiref
->_assetVersion
;
1142 int SecOTAPKISignalNewAsset(CFErrorRef
* error
)
1144 TestOTALog("SecOTAPKISignalNewAsset has been called!\n");
1145 SecOTAPKIRefreshData();