OTATrustUtilities.c [plain text]
#include "OTATrustUtilities.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/syslimits.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <CoreFoundation/CoreFoundation.h>
#include <ftw.h>
#include "SecFramework.h"
#include <pthread.h>
#include <sys/param.h>
#include <stdlib.h>
#include <utilities/SecCFRelease.h>
#include <utilities/SecCFError.h>
#include <utilities/SecCFWrappers.h>
#include <Security/SecBasePriv.h>
#include <Security/SecFramework.h>
#include <dispatch/dispatch.h>
#include <CommonCrypto/CommonDigest.h>
#if VERBOSE_LOGGING
static void TestOTALog(const char* sz, ...)
{
va_list va;
va_start(va, sz);
FILE* fp = fopen("/tmp/secd_OTAUtil.log", "a");
if (NULL != fp)
{
vfprintf(fp, sz, va);
fclose(fp);
}
va_end(va);
}
#else
#define TestOTALog(sz, ...)
#endif
#if NEW_LOCATION
static const char* kBaseAssertDirectory = "/var/OTAPKI/Assets";
#else
static const char* kBaseAssertDirectory = "/var/Keychains/Assets";
#endif
static const char* kVersionDirectoryNamePrefix = "Version_";
static const char* kNumberString = "%d";
struct index_record
{
unsigned char hash[CC_SHA1_DIGEST_LENGTH];
uint32_t offset;
};
typedef struct index_record index_record;
struct _OpaqueSecOTAPKI
{
CFRuntimeBase _base;
CFSetRef _blackListSet;
CFSetRef _grayListSet;
CFArrayRef _escrowCertificates;
CFDictionaryRef _evPolicyToAnchorMapping;
CFDictionaryRef _anchorLookupTable;
const char* _anchorTable;
int _assetVersion;
};
CFGiblisFor(SecOTAPKI)
static CF_RETURNS_RETAINED CFStringRef SecOTAPKICopyDescription(CFTypeRef cf)
{
SecOTAPKIRef otapkiRef = (SecOTAPKIRef)cf;
return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecOTAPKIRef: version %d>"), otapkiRef->_assetVersion);
}
static void SecOTAPKIDestroy(CFTypeRef cf)
{
SecOTAPKIRef otapkiref = (SecOTAPKIRef)cf;
CFReleaseNull(otapkiref->_blackListSet);
CFReleaseNull(otapkiref->_grayListSet);
CFReleaseNull(otapkiref->_escrowCertificates);
CFReleaseNull(otapkiref->_evPolicyToAnchorMapping);
CFReleaseNull(otapkiref->_anchorLookupTable);
free((void *)otapkiref->_anchorTable);
}
static CFDataRef SecOTACopyFileContents(const char *path)
{
CFMutableDataRef data = NULL;
int fd = open(path, O_RDONLY, 0666);
if (fd == -1)
{
goto badFile;
}
off_t fsize = lseek(fd, 0, SEEK_END);
if (fsize == (off_t)-1)
{
goto badFile;
}
if (fsize > (off_t)INT32_MAX)
{
goto badFile;
}
data = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)fsize);
if (NULL == data)
{
goto badFile;
}
CFDataSetLength(data, (CFIndex)fsize);
void *buf = CFDataGetMutableBytePtr(data);
if (NULL == buf)
{
goto badFile;
}
off_t total_read = 0;
while (total_read < fsize)
{
ssize_t bytes_read;
bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read);
if (bytes_read == -1)
{
goto badFile;
}
if (bytes_read == 0)
{
goto badFile;
}
total_read += bytes_read;
}
close(fd);
return data;
badFile:
if (fd != -1)
{
close(fd);
}
if (data)
{
CFRelease(data);
}
return NULL;
}
static Boolean PathExists(const char* path, size_t* pFileSize)
{
TestOTALog("In PathExists: checking path %s\n", path);
Boolean result = false;
struct stat sb;
if (NULL != pFileSize)
{
*pFileSize = 0;
}
int stat_result = stat(path, &sb);
result = (stat_result == 0);
if (result)
{
TestOTALog("In PathExists: stat returned 0 for %s\n", path);
if (S_ISDIR(sb.st_mode))
{
TestOTALog("In PathExists: %s is a directory\n", path);
;
}
else
{
TestOTALog("In PathExists: %s is a file\n", path);
if (NULL != pFileSize)
{
*pFileSize = (size_t)sb.st_size;
}
}
}
#if VERBOSE_LOGGING
else
{
TestOTALog("In PathExists: stat returned %d for %s\n", stat_result, path);
int local_errno = errno;
switch(local_errno)
{
case EACCES:
TestOTALog("In PathExists: stat failed because of EACCES\n");
break;
case EBADF:
TestOTALog("In PathExists: stat failed because of EBADF (Not likely)\n");
break;
case EFAULT:
TestOTALog("In PathExists: stat failed because of EFAULT (huh?)\n");
break;
case ELOOP:
TestOTALog("In PathExists: stat failed because of ELOOP (huh?)\n");
break;
case ENAMETOOLONG:
TestOTALog("In PathExists: stat failed because of ENAMETOOLONG (huh?)\n");
break;
case ENOENT:
TestOTALog("In PathExists: stat failed because of ENOENT (missing?)\n");
break;
case ENOMEM:
TestOTALog("In PathExists: stat failed because of ENOMEM (really?)\n");
break;
case ENOTDIR:
TestOTALog("In PathExists: stat failed because of ENOTDIR (really?)\n");
break;
case EOVERFLOW:
TestOTALog("In PathExists: stat failed because of EOVERFLOW (really?)\n");
break;
default:
TestOTALog("In PathExists: unknown errno of %d\n", local_errno);
break;
}
}
#endif // #if VERBOSE_LOGGING
return result;
}
static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
{
int rv = remove(fpath);
return rv;
}
static int rmrf(char *path)
{
const char* p1 = NULL;
char path_buffer[PATH_MAX];
memset(path_buffer, 0, sizeof(path_buffer));
p1 = realpath(path, path_buffer);
if (!strncmp(path, p1, PATH_MAX))
{
return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
}
return -1;
}
static const char* InitOTADirectory(int* pAssetVersion)
{
TestOTALog("In InitOTADirectory\n");
const char* result = NULL;
char buffer[PATH_MAX];
DIR *dp;
struct dirent *ep;
int version = 0;
int current_version = 0;
CFIndex asset_number = 0;
bool assetDirectoryExists = PathExists(kBaseAssertDirectory, NULL);
if (assetDirectoryExists)
{
TestOTALog("InitOTADirectory: %s exists\n", kBaseAssertDirectory);
dp = opendir (kBaseAssertDirectory);
if (NULL != dp)
{
TestOTALog("InitOTADirectory: opendir sucessfully open %s\n", kBaseAssertDirectory);
while ((ep = readdir(dp)))
{
TestOTALog("InitOTADirectory: processing name %s\n", ep->d_name);
if (strstr(ep->d_name, kVersionDirectoryNamePrefix))
{
TestOTALog("InitOTADirectory: %s matches\n", ep->d_name);
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), "%s%s", kVersionDirectoryNamePrefix, kNumberString);
sscanf(ep->d_name, buffer, &version);
TestOTALog("InitOTADirectory: version = %d\n", version);
if (current_version > 0)
{
if (version > current_version)
{
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), "%s/%s%d", kBaseAssertDirectory, kVersionDirectoryNamePrefix, current_version);
if (PathExists(buffer, NULL))
{
rmrf(buffer);
}
current_version = version;
}
}
else
{
current_version = version;
}
}
}
closedir(dp);
}
else
{
TestOTALog("InitOTADirectory: opendir failed to open %s\n", kBaseAssertDirectory);
}
}
else
{
TestOTALog("InitOTADirectory: PathExists returned false for %s\n", kBaseAssertDirectory);
}
memset(buffer, 0, sizeof(buffer));
if (0 == current_version)
{
TestOTALog("InitOTADirectory: current_version = 0\n");
CFDataRef assetVersionData = SecFrameworkCopyResourceContents(CFSTR("AssetVersion"), CFSTR("plist"), NULL);
if (NULL != assetVersionData)
{
CFPropertyListFormat propFormat;
CFDictionaryRef versionPlist = CFPropertyListCreateWithData(kCFAllocatorDefault, assetVersionData, 0, &propFormat, NULL);
if (NULL != versionPlist && CFDictionaryGetTypeID() == CFGetTypeID(versionPlist))
{
CFNumberRef versionNumber = (CFNumberRef)CFDictionaryGetValue(versionPlist, (const void *)CFSTR("VersionNumber"));
if (NULL != versionNumber)
{
CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &asset_number);
}
}
CFReleaseSafe(versionPlist);
CFReleaseSafe(assetVersionData);
}
current_version = (int)asset_number;
}
else
{
TestOTALog("InitOTADirectory: current_version = %d\n", current_version);
snprintf(buffer, sizeof(buffer), "%s/%s%d", kBaseAssertDirectory, kVersionDirectoryNamePrefix, current_version);
size_t length = strlen(buffer);
char* temp_str = (char*)malloc(length + 1);
memset(temp_str, 0, (length + 1));
strncpy(temp_str, buffer, length);
result = temp_str;
}
if (NULL != pAssetVersion)
{
*pAssetVersion = current_version;
}
return result;
}
static CFSetRef InitializeBlackList(const char* path_ptr)
{
CFSetRef result = NULL;
CFDataRef xmlData = NULL;
const char* asset_path = path_ptr;
if (NULL == asset_path)
{
xmlData = SecFrameworkCopyResourceContents(CFSTR("Blocked"), CFSTR("plist"), NULL);
}
else
{
char file_path_buffer[PATH_MAX];
memset(file_path_buffer, 0, PATH_MAX);
snprintf(file_path_buffer, PATH_MAX, "%s/Blocked.plist", asset_path);
xmlData = SecOTACopyFileContents(file_path_buffer);
if (NULL == xmlData)
{
xmlData = SecFrameworkCopyResourceContents(CFSTR("Blocked"), CFSTR("plist"), NULL);
}
}
CFPropertyListRef blackKeys = NULL;
if (xmlData)
{
blackKeys = CFPropertyListCreateWithData(kCFAllocatorDefault, xmlData, kCFPropertyListImmutable, NULL, NULL);
CFRelease(xmlData);
}
if (blackKeys)
{
CFMutableSetRef tempSet = NULL;
if (CFGetTypeID(blackKeys) == CFArrayGetTypeID())
{
tempSet = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
if (NULL == tempSet)
{
CFRelease(blackKeys);
return result;
}
CFArrayRef blackKeyArray = (CFArrayRef)blackKeys;
CFIndex num_keys = CFArrayGetCount(blackKeyArray);
for (CFIndex idx = 0; idx < num_keys; idx++)
{
CFDataRef key_data = (CFDataRef)CFArrayGetValueAtIndex(blackKeyArray, idx);
CFSetAddValue(tempSet, key_data);
}
}
else
{
CFRelease(blackKeys);
return result;
}
if (NULL != tempSet)
{
result = tempSet;
}
CFRelease(blackKeys);
}
return result;
}
static CFSetRef InitializeGrayList(const char* path_ptr)
{
CFSetRef result = NULL;
CFDataRef xmlData = NULL;
const char* asset_path = path_ptr;
if (NULL == asset_path)
{
xmlData = SecFrameworkCopyResourceContents(CFSTR("GrayListedKeys"), CFSTR("plist"), NULL);
}
else
{
char file_path_buffer[PATH_MAX];
memset(file_path_buffer, 0, PATH_MAX);
snprintf(file_path_buffer, PATH_MAX, "%s/GrayListedKeys.plist", asset_path);
xmlData = SecOTACopyFileContents(file_path_buffer);
if (NULL == xmlData)
{
xmlData = SecFrameworkCopyResourceContents(CFSTR("GrayListedKeys"), CFSTR("plist"), NULL);
}
}
CFPropertyListRef grayKeys = NULL;
if (xmlData)
{
grayKeys = CFPropertyListCreateWithData(kCFAllocatorDefault, xmlData, kCFPropertyListImmutable, NULL, NULL);
CFRelease(xmlData);
}
if (grayKeys)
{
CFMutableSetRef tempSet = NULL;
if (CFGetTypeID(grayKeys) == CFArrayGetTypeID())
{
tempSet = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
if (NULL == tempSet)
{
CFRelease(grayKeys);
return result;
}
CFArrayRef grayKeyArray = (CFArrayRef)grayKeys;
CFIndex num_keys = CFArrayGetCount(grayKeyArray);
for (CFIndex idx = 0; idx < num_keys; idx++)
{
CFDataRef key_data = (CFDataRef)CFArrayGetValueAtIndex(grayKeyArray, idx);
CFSetAddValue(tempSet, key_data);
}
}
else
{
CFRelease(grayKeys);
return result;
}
if (NULL != tempSet)
{
result = tempSet;
}
CFRelease(grayKeys);
}
return result;
}
static CFDictionaryRef InitializeEVPolicyToAnchorDigestsTable(const char* path_ptr)
{
CFDictionaryRef result = NULL;
CFDataRef xmlData = NULL;
const char* asset_path = path_ptr;
if (NULL == asset_path)
{
xmlData = SecFrameworkCopyResourceContents(CFSTR("EVRoots"), CFSTR("plist"), NULL);
}
else
{
char file_path_buffer[PATH_MAX];
memset(file_path_buffer, 0, PATH_MAX);
snprintf(file_path_buffer, PATH_MAX, "%s/EVRoots.plist", asset_path);
xmlData = SecOTACopyFileContents(file_path_buffer);
if (NULL == xmlData)
{
xmlData = SecFrameworkCopyResourceContents(CFSTR("EVRoots"), CFSTR("plist"), NULL);
}
}
CFPropertyListRef evroots = NULL;
if (xmlData)
{
evroots = CFPropertyListCreateWithData(
kCFAllocatorDefault, xmlData, kCFPropertyListImmutable, NULL, NULL);
CFRelease(xmlData);
}
if (evroots)
{
if (CFGetTypeID(evroots) == CFDictionaryGetTypeID())
{
result = (CFDictionaryRef)evroots;
}
else
{
secwarning("EVRoot.plist is wrong type.");
CFRelease(evroots);
}
}
return result;
}
static void* MapFile(const char* path, int* out_fd, size_t* out_file_size)
{
void* result = NULL;
void* temp_result = NULL;
if (NULL == path || NULL == out_fd || NULL == out_file_size)
{
return result;
}
*out_fd = -1;
*out_file_size = 0;
*out_fd = open(path, O_RDONLY, 0666);
if (*out_fd == -1)
{
return result;
}
off_t fsize = lseek(*out_fd, 0, SEEK_END);
if (fsize == (off_t)-1)
{
return result;
}
if (fsize > (off_t)INT32_MAX)
{
close(*out_fd);
*out_fd = -1;
return result;
}
size_t malloc_size = (size_t)fsize;
temp_result = malloc(malloc_size);
if (NULL == temp_result)
{
close(*out_fd);
*out_fd = -1;
return result;
}
*out_file_size = malloc_size;
off_t total_read = 0;
while (total_read < fsize)
{
ssize_t bytes_read;
bytes_read = pread(*out_fd, temp_result, (size_t)(fsize - total_read), total_read);
if (bytes_read == -1)
{
free(temp_result);
temp_result = NULL;
close(*out_fd);
*out_fd = -1;
return result;
}
if (bytes_read == 0)
{
free(temp_result);
temp_result = NULL;
close(*out_fd);
*out_fd = -1;
return result;
}
total_read += bytes_read;
}
if (NULL != temp_result)
{
result = temp_result;
}
return result;
}
static void UnMapFile(void* mapped_data, size_t data_size)
{
#pragma unused(mapped_data, data_size)
if (NULL != mapped_data)
{
free((void *)mapped_data);
mapped_data = NULL;
}
}
static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookupTable, const char** ppAnchorTable)
{
bool result = false;
if (NULL == pLookupTable || NULL == ppAnchorTable)
{
return result;
}
*pLookupTable = NULL;
*ppAnchorTable = NULL;;
const char* dir_path = NULL;
CFDataRef cert_index_file_data = NULL;
char file_path_buffer[PATH_MAX];
CFURLRef table_data_url = NULL;
CFStringRef table_data_cstr_path = NULL;
const char* table_data_path = NULL;
const index_record* pIndex = NULL;
size_t index_offset = 0;
size_t index_data_size = 0;
CFMutableDictionaryRef anchorLookupTable = NULL;
uint32_t offset_int_value = 0;
CFNumberRef index_offset_value = NULL;
CFDataRef index_hash = NULL;
CFMutableArrayRef offsets = NULL;
Boolean release_offset = false;
char* local_anchorTable = NULL;
size_t local_anchorTableSize = 0;
int local_anchorTable_fd = -1;
dir_path = path_ptr;
if (NULL != dir_path)
{
memset(file_path_buffer, 0, PATH_MAX);
snprintf(file_path_buffer, PATH_MAX, "%s/certsIndex.data", dir_path);
cert_index_file_data = SecOTACopyFileContents(file_path_buffer);
if (NULL != cert_index_file_data)
{
memset(file_path_buffer, 0, PATH_MAX);
snprintf(file_path_buffer, PATH_MAX, "%s/certsTable.data", dir_path);
local_anchorTable = (char *)MapFile(file_path_buffer, &local_anchorTable_fd, &local_anchorTableSize);
}
free((void *)dir_path);
dir_path = NULL;
}
if (NULL == local_anchorTable)
{
CFReleaseSafe(cert_index_file_data);
cert_index_file_data = SecFrameworkCopyResourceContents(CFSTR("certsIndex"), CFSTR("data"), NULL);
table_data_url = SecFrameworkCopyResourceURL(CFSTR("certsTable"), CFSTR("data"), NULL);
if (NULL != table_data_url)
{
table_data_cstr_path = CFURLCopyFileSystemPath(table_data_url, kCFURLPOSIXPathStyle);
if (NULL != table_data_cstr_path)
{
memset(file_path_buffer, 0, PATH_MAX);
table_data_path = CFStringGetCStringPtr(table_data_cstr_path, kCFStringEncodingUTF8);
if (NULL == table_data_path)
{
if (CFStringGetCString(table_data_cstr_path, file_path_buffer, PATH_MAX, kCFStringEncodingUTF8))
{
table_data_path = file_path_buffer;
}
}
local_anchorTable = (char *)MapFile(table_data_path, &local_anchorTable_fd, &local_anchorTableSize);
CFReleaseSafe(table_data_cstr_path);
}
}
CFReleaseSafe(table_data_url);
}
if (NULL == local_anchorTable || NULL == cert_index_file_data)
{
CFReleaseSafe(cert_index_file_data);
return result;
}
pIndex = (const index_record*)CFDataGetBytePtr(cert_index_file_data);
index_data_size = CFDataGetLength(cert_index_file_data);
anchorLookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
for (index_offset = index_data_size; index_offset > 0; index_offset -= sizeof(index_record), pIndex++)
{
offset_int_value = pIndex->offset;
index_offset_value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &offset_int_value);
index_hash = CFDataCreate(kCFAllocatorDefault, pIndex->hash, CC_SHA1_DIGEST_LENGTH);
release_offset = false;
offsets = (CFMutableArrayRef)CFDictionaryGetValue(anchorLookupTable, index_hash);
if (NULL == offsets)
{
offsets = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
release_offset = true;
}
CFArrayAppendValue(offsets, index_offset_value);
CFDictionarySetValue(anchorLookupTable, index_hash, offsets);
CFRelease(index_offset_value);
CFRelease(index_hash);
if (release_offset)
{
CFRelease(offsets);
}
}
CFRelease(cert_index_file_data);
if (NULL != anchorLookupTable && NULL != local_anchorTable)
{
*pLookupTable = anchorLookupTable;
*ppAnchorTable = local_anchorTable;
result = true;
}
else
{
CFReleaseSafe(anchorLookupTable);
if (NULL != local_anchorTable)
{
UnMapFile(local_anchorTable, local_anchorTableSize);
local_anchorTable = NULL;
local_anchorTableSize = 0;
}
}
return result;
}
static CFArrayRef InitializeEscrowCertificates(const char* path_ptr)
{
CFArrayRef result = NULL;
CFDataRef file_data = NULL;
const char* dir_path = path_ptr;
if (NULL == dir_path)
{
file_data = SecFrameworkCopyResourceContents(CFSTR("AppleESCertificates"), CFSTR("plist"), NULL);
}
else
{
char buffer[1024];
memset(buffer, 0, 1024);
snprintf(buffer, 1024, "%s/AppleESCertificates.plist", dir_path);
file_data = SecOTACopyFileContents(buffer);
}
if (NULL != file_data)
{
CFPropertyListFormat propFormat;
CFDictionaryRef certsDictionary = CFPropertyListCreateWithData(kCFAllocatorDefault, file_data, 0, &propFormat, NULL);
if (NULL != certsDictionary && CFDictionaryGetTypeID() == CFGetTypeID((CFTypeRef)certsDictionary))
{
CFArrayRef certs = (CFArrayRef)CFDictionaryGetValue(certsDictionary, CFSTR("ProductionEscrowKey"));
if (NULL != certs && CFArrayGetTypeID() == CFGetTypeID((CFTypeRef)certs) && CFArrayGetCount(certs) > 0)
{
result = CFArrayCreateCopy(kCFAllocatorDefault, certs);
}
CFRelease(certsDictionary);
}
CFRelease(file_data);
}
return result;
}
static SecOTAPKIRef SecOTACreate()
{
TestOTALog("In SecOTACreate\n");
SecOTAPKIRef otapkiref = NULL;
otapkiref = CFTypeAllocate(SecOTAPKI, struct _OpaqueSecOTAPKI , kCFAllocatorDefault);
if (NULL == otapkiref)
{
return otapkiref;
}
otapkiref->_blackListSet = NULL;
otapkiref->_grayListSet = NULL;
otapkiref->_escrowCertificates = NULL;
otapkiref->_evPolicyToAnchorMapping = NULL;
otapkiref->_anchorLookupTable = NULL;
otapkiref->_anchorTable = NULL;
otapkiref->_assetVersion = 0;
int asset_version = 0;
const char* path_ptr = InitOTADirectory(&asset_version);
otapkiref->_assetVersion = asset_version;
TestOTALog("SecOTACreate: asset_path = %s\n", path_ptr);
TestOTALog("SecOTACreate: asset_version = %d\n", asset_version);
CFSetRef blackKeysSet = InitializeBlackList(path_ptr);
if (NULL == blackKeysSet)
{
CFReleaseNull(otapkiref);
return otapkiref;
}
otapkiref->_blackListSet = blackKeysSet;
CFSetRef grayKeysSet = InitializeGrayList(path_ptr);
if (NULL == grayKeysSet)
{
CFReleaseNull(otapkiref);
return otapkiref;
}
otapkiref->_grayListSet = grayKeysSet;
CFArrayRef escrowCerts = InitializeEscrowCertificates(path_ptr);
if (NULL == escrowCerts)
{
CFReleaseNull(otapkiref);
return otapkiref;
}
otapkiref->_escrowCertificates = escrowCerts;
CFDictionaryRef evOidToAnchorDigestMap = InitializeEVPolicyToAnchorDigestsTable(path_ptr);
if (NULL == evOidToAnchorDigestMap)
{
CFReleaseNull(otapkiref);
return otapkiref;
}
otapkiref->_evPolicyToAnchorMapping = evOidToAnchorDigestMap;
CFDictionaryRef anchorLookupTable = NULL;
const char* anchorTablePtr = NULL;
if (!InitializeAnchorTable(path_ptr, &anchorLookupTable, &anchorTablePtr))
{
CFReleaseSafe(anchorLookupTable);
if (NULL != anchorTablePtr)
{
free((void *)anchorTablePtr);
}
CFReleaseNull(otapkiref);
return otapkiref;
}
otapkiref->_anchorLookupTable = anchorLookupTable;
otapkiref->_anchorTable = anchorTablePtr;
return otapkiref;
}
static dispatch_once_t kInitializeOTAPKI = 0;
static const char* kOTAQueueLabel = "com.apple.security.OTAPKIQueue";
static dispatch_queue_t kOTAQueue;
static SecOTAPKIRef kCurrentOTAPKIRef = NULL;
SecOTAPKIRef SecOTAPKICopyCurrentOTAPKIRef()
{
__block SecOTAPKIRef result = NULL;
dispatch_once(&kInitializeOTAPKI,
^{
kOTAQueue = dispatch_queue_create(kOTAQueueLabel, NULL);
kCurrentOTAPKIRef = SecOTACreate();
});
dispatch_sync(kOTAQueue,
^{
result = kCurrentOTAPKIRef;
CFRetainSafe(result);
});
return result;
}
CFSetRef SecOTAPKICopyBlackListSet(SecOTAPKIRef otapkiRef)
{
CFSetRef result = NULL;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_blackListSet;
CFRetainSafe(result);
return result;
}
CFSetRef SecOTAPKICopyGrayList(SecOTAPKIRef otapkiRef)
{
CFSetRef result = NULL;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_grayListSet;
CFRetainSafe(result);
return result;
}
CFArrayRef SecOTAPKICopyEscrowCertificates(SecOTAPKIRef otapkiRef)
{
CFArrayRef result = NULL;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_escrowCertificates;
CFRetainSafe(result);
return result;
}
CFDictionaryRef SecOTAPKICopyEVPolicyToAnchorMapping(SecOTAPKIRef otapkiRef)
{
CFDictionaryRef result = NULL;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_evPolicyToAnchorMapping;
CFRetainSafe(result);
return result;
}
CFDictionaryRef SecOTAPKICopyAnchorLookupTable(SecOTAPKIRef otapkiRef)
{
CFDictionaryRef result = NULL;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_anchorLookupTable;
CFRetainSafe(result);
return result;
}
const char* SecOTAPKIGetAnchorTable(SecOTAPKIRef otapkiRef)
{
const char* result = NULL;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_anchorTable;
return result;
}
int SecOTAPKIGetAssetVersion(SecOTAPKIRef otapkiRef)
{
int result = 0;
if (NULL == otapkiRef)
{
return result;
}
result = otapkiRef->_assetVersion;
return result;
}
void SecOTAPKIRefreshData()
{
TestOTALog("In SecOTAPKIRefreshData\n");
SecOTAPKIRef new_otaPKRef = SecOTACreate();
dispatch_sync(kOTAQueue,
^{
CFReleaseSafe(kCurrentOTAPKIRef);
kCurrentOTAPKIRef = new_otaPKRef;
});
}
CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(CFErrorRef* error)
{
CFArrayRef result = NULL;
SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
if (NULL == otapkiref)
{
SecError(errSecInternal, error, CFSTR("Unable to get the current OTAPKIRef"));
return result;
}
result = SecOTAPKICopyEscrowCertificates(otapkiref);
CFRelease(otapkiref);
if (NULL == result)
{
SecError(errSecInternal, error, CFSTR("Could not get the array of escrow certificates form the current OTAPKIRef"));
}
return result;
}
int SecOTAPKIGetCurrentAssetVersion(CFErrorRef* error)
{
int result = 0;
SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
if (NULL == otapkiref)
{
SecError(errSecInternal, error, CFSTR("Unable to get the current OTAPKIRef"));
return result;
}
result = otapkiref->_assetVersion;
return result;
}
int SecOTAPKISignalNewAsset(CFErrorRef* error)
{
TestOTALog("SecOTAPKISignalNewAsset has been called!\n");
SecOTAPKIRefreshData();
return 1;
}