1// 2// OTAServiceApp.m 3// Security 4// 5// Created by local on 2/11/13. 6// 7// 8 9 10#import "OTAServiceApp.h" 11 12#import <TargetConditionals.h> 13#import <Security/Security.h> 14#import <Security/SecPolicyPriv.h> 15#import <Security/SecTrustPriv.h> 16#import <syslog.h> 17#import <xpc/xpc.h> 18#import <MobileAsset/MobileAsset.h> 19#import <Security/Security.h> 20#import <Security/SecCMS.h> 21#import <Security/SecCmsMessage.h> 22#import <Security/SecCmsDecoder.h> 23#import <Security/SecCmsContentInfo.h> 24#import <Security/SecCmsSignedData.h> 25#import <CommonCrypto/CommonDigest.h> 26#import <CommonNumerics/CommonBaseXX.h> 27#import <ManagedConfiguration/MCProfileConnection.h> 28#import <MobileGestalt.h> 29 30#if !TARGET_IPHONE_SIMULATOR 31#import <BackgroundTaskAgent/BackgroundTaskAgent.h> 32#endif 33 34#import <sys/types.h> 35#import <pwd.h> 36#import <stdlib.h> 37#import <unistd.h> 38#import <stdio.h> 39#import <grp.h> 40#import <sys/stat.h> 41#import <syslog.h> 42 43#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } 44#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } 45 46//#define VERBOSE_LOGGING 1 47 48#if VERBOSE_LOGGING 49 50static void OTAPKI_LOG(const char* sz, ...) 51{ 52 va_list va; 53 va_start(va, sz); 54 55 FILE* fp = fopen("/tmp/OTAPKITool.log", "a"); 56 if (NULL != fp) 57 { 58 vfprintf(fp, sz, va); 59 fclose(fp); 60 } 61 va_end(va); 62} 63 64#else 65 66#define OTAPKI_LOG(sz, ...) 67 68#endif 69 70//#define NEW_LOCATION 1 71 72 73 74/* ========================================================================== 75 The following are a set of string constants used by this program. 76 77 kBaseAssetDirectoryPath - This is the full path on the device that 78 will contain the Assets directory. This 79 directory was chosen because it is owned 80 by securityd 81 82 kkManifestFileName - The file name of the manifest file for the 83 OTA PKI trust asset 84 85 kAssetVersionFileName - The file name of the plist file in the asset 86 that contains the version number of this 87 OTA PKI trust asset. It is a plist that is a 88 dictionary with a single key with a single 89 key value pair that has the version number 90 of the asset. This is used to ensure against 91 anti-replay. 92 93 kBlockKeyFileName - The file name of the asset file that contains 94 blocked keys. Any certificate with these keys 95 will be marked as not being trusted. 96 97 kGrayListedKeysFileName - The file name of the asset file that contains 98 gray listed keys. If a chain has any of these 99 keys, than the chain will still be approved but 100 an entry will be added to the details dictionary 101 noting that the key was gray listed 102 103 104 kEVRootsFileName - The file name of the asset file that contains 105 the list of EV OIDS and their corresponding 106 certificates. This file sets which certs will 107 be considered to be EV. 108 109 kCertsIndexFileName - The file name of the asset file that contains 110 a hash table of offsets into the cert table 111 file. This is used to look up anchor certs. 112 113 kCertsTableFileName - The file name of the asset file that contains 114 all of the anchor certificates. The 115 kCertsIndexFileName file is used to find the 116 correct offset in this file to retrieve a 117 specific anchor certificate. 118 119 kVersionNumberKey - The dictionary key for the kAssetVersionFileName 120 file to get the version number 121 122 kVersionDirectoryNamePrefix - 123 The directory name prefix for all of the 124 asset directorys 125 126 kPKITrustDataAssetType - The asset identifier of the OTA PKI asset 127 128 129========================================================================== */ 130 131#if NEW_LOCATION 132static const NSString* kBaseAssetDirectoryPath = @"/var/OTAPKI"; 133#else 134static const NSString* kBaseAssetDirectoryPath = @"/var/Keychains"; 135#endif 136 137static const NSString* kManifestFileName = @"manifest.data"; 138static const NSString* kAssetVersionFileName = @"AssetVersion.plist"; 139static const NSString* kAppleESCertificatesName = @"AppleESCertificates.plist"; 140static const NSString* kBlockKeyFileName = @"Blocked.plist"; 141static const NSString* kGrayListedKeysFileName = @"GrayListedKeys.plist"; 142static const NSString* kEVRootsFileName = @"EVRoots.plist"; 143static const NSString* kCertsIndexFileName = @"certsIndex.data"; 144static const NSString* kCertsTableFileName = @"certsTable.data"; 145static const NSString* kVersionNumberKey = @"VersionNumber"; 146static const NSString* kAssetDirectoryName = @"Assets"; 147static const NSString* kAssetDirectoryUser = @"_securityd"; 148static const NSString* kAssetDirectoryGroup = @"wheel"; 149#if NEW_LOCATION 150static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRWXG | S_IRWXO; 151#else 152static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 153#endif 154static const NSString* kVersionDirectoryNamePrefix = @"Version_"; 155static const NSString* kPKITrustDataAssetType =@"com.apple.MobileAsset.PKITrustServices.PKITrustData"; 156 157const char *kOTAPKIAssetToolActivity = "com.apple.OTAPKIAssetTool.asset-check"; 158 159static const UInt8 kApplePKISettingsRootCACert[] = { 160 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, 161 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 162 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 163 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 164 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 165 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 166 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 167 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 168 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 169 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 170 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 171 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, 172 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84, 173 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 174 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 175 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 176 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 177 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 178 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 179 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 180 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 181 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 182 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 183 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04, 184 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc, 185 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe, 186 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29, 187 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77, 188 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf, 189 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f, 190 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa, 191 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e, 192 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a, 193 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d, 194 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99, 195 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05, 196 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3, 197 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d, 198 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, 199 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3, 200 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4, 201 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d, 202 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce, 203 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc, 204 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff, 205 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7, 206 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f, 207 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22, 208 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70, 209 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, 210 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf, 211 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7, 212 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee, 213 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62, 214 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63, 215 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82, 216 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82, 217 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 218 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 219 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, 220 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 221 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca, 222 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 223 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, 224 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, 225 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 226 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 227 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 228 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 229 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, 230 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 231 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, 232 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 233 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 234 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 235 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 236 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 237 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 238 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 239 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 240 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 241 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, 242 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 243 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 244 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 245 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 246 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 247 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 248 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 249 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 250 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 251 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 252 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a, 253 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0, 254 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52, 255 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf, 256 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60, 257 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34, 258 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37, 259 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe, 260 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd, 261 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9, 262 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62, 263 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44, 264 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38, 265 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a, 266 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92, 267 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6, 268 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2, 269 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53, 270 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19, 271 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, 272 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63, 273 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61, 274 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef, 275 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, 276 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4, 277 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c, 278 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81, 279 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17, 280 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10, 281 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6, 282 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa, 283 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce, 284 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8 285}; 286 287 288static const UInt8 kAppleTestPKISettingsRootCACert[] = { 289 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x26, 290 0xfe, 0xf8, 0xda, 0x41, 0xf3, 0x61, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 291 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 292 0x03, 0x0c, 0x24, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 293 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 294 0x54, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 295 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 296 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 297 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 298 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 299 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x32, 0x32, 0x32, 0x30, 0x33, 0x31, 0x34, 300 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x34, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x34, 0x36, 301 0x5a, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, 0x41, 0x70, 302 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 303 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x54, 0x45, 0x53, 0x54, 0x49, 304 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 305 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 306 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 307 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 308 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 309 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 310 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x84, 0xbe, 0xc2, 311 0x69, 0x9b, 0xec, 0xd5, 0xde, 0x72, 0xf0, 0x4f, 0x78, 0x81, 0x10, 0xa9, 0x56, 0x59, 0x77, 0x9c, 312 0x46, 0x95, 0xd7, 0xb7, 0x0b, 0x77, 0x73, 0x02, 0xce, 0xf8, 0xaa, 0x32, 0x89, 0xee, 0xbe, 0xaa, 313 0x40, 0x53, 0xf9, 0x2d, 0x96, 0x08, 0xcd, 0x2a, 0xa4, 0x61, 0xd4, 0xfd, 0x7d, 0x67, 0x2a, 0x35, 314 0xc1, 0xfc, 0x43, 0xa4, 0x9c, 0xd0, 0xbd, 0xcd, 0x82, 0x27, 0xed, 0xa1, 0x1c, 0x2d, 0x9a, 0x62, 315 0xd5, 0x99, 0xbd, 0x74, 0xaa, 0xf3, 0xce, 0x78, 0xc6, 0x47, 0x07, 0x43, 0x04, 0x5b, 0xbc, 0x27, 316 0x5e, 0x26, 0x3e, 0x77, 0x90, 0x69, 0x7a, 0xf6, 0xe0, 0x8e, 0xaa, 0xdf, 0x96, 0x12, 0x2c, 0xb2, 317 0x8b, 0xb9, 0x7e, 0x17, 0xfe, 0xde, 0x99, 0x67, 0x9b, 0x50, 0x13, 0x5c, 0x8d, 0x15, 0x26, 0x0a, 318 0x9f, 0x08, 0x2f, 0x3f, 0x7c, 0x01, 0x2c, 0x3e, 0xa1, 0xba, 0xb1, 0x25, 0x33, 0xe5, 0xd9, 0x39, 319 0x37, 0xde, 0x06, 0x3a, 0x63, 0x48, 0xa0, 0x9d, 0x3b, 0xa5, 0x72, 0x46, 0xfb, 0x6e, 0xa2, 0xd4, 320 0x74, 0xe6, 0xf1, 0xc1, 0x69, 0xc8, 0x31, 0xff, 0x58, 0x84, 0x3a, 0xc2, 0x6b, 0x9a, 0x0d, 0x19, 321 0x76, 0xe4, 0xd4, 0x4d, 0x85, 0xbc, 0x84, 0xf0, 0x07, 0x75, 0x66, 0x5f, 0xd7, 0xea, 0xab, 0x9e, 322 0x46, 0xf2, 0x8a, 0x29, 0xab, 0x73, 0x57, 0xaf, 0x95, 0x4f, 0xc7, 0xf3, 0x3b, 0x55, 0xb4, 0x26, 323 0x57, 0x68, 0xe9, 0x5a, 0x34, 0xbb, 0xa9, 0x39, 0xb3, 0x57, 0x5f, 0x25, 0x93, 0xd6, 0x34, 0xb7, 324 0xd1, 0xc4, 0xd7, 0x70, 0xed, 0x30, 0xdb, 0x21, 0xc1, 0xcc, 0xdf, 0xed, 0xec, 0x37, 0xc5, 0xdc, 325 0x0b, 0xc9, 0x85, 0x46, 0x26, 0xa7, 0x51, 0xc8, 0xdd, 0xe6, 0x47, 0xfc, 0x37, 0xd6, 0x73, 0x6f, 326 0x91, 0x3d, 0xef, 0xd8, 0xa4, 0xa5, 0x08, 0x32, 0x8c, 0xae, 0x8f, 0x57, 0xf7, 0x99, 0x48, 0xef, 327 0x81, 0x44, 0xac, 0x80, 0x42, 0x57, 0x9f, 0x64, 0x77, 0x40, 0x2a, 0xec, 0x03, 0x21, 0x79, 0x01, 328 0x0b, 0x87, 0xc3, 0x9d, 0x22, 0xc9, 0xc0, 0x69, 0xe0, 0x34, 0xff, 0x73, 0xdd, 0x1e, 0x1b, 0x0c, 329 0xe0, 0x68, 0xf0, 0x8c, 0x7a, 0x4b, 0xcd, 0x1d, 0x3f, 0x38, 0x2d, 0xe8, 0x9b, 0x91, 0xa6, 0xfe, 330 0xa8, 0x8b, 0x45, 0x1c, 0xdf, 0xaf, 0x49, 0x34, 0x48, 0x17, 0x02, 0x28, 0xdb, 0xe0, 0x6e, 0x74, 331 0x34, 0xea, 0xac, 0x6b, 0x00, 0x45, 0x89, 0xa9, 0xb5, 0x63, 0xbd, 0x2f, 0xe0, 0x58, 0x2e, 0xd3, 332 0xc2, 0x74, 0xa2, 0x37, 0x37, 0x62, 0xf6, 0x76, 0x1b, 0x3f, 0xfb, 0x98, 0x64, 0x13, 0xd6, 0x8c, 333 0xa0, 0x0c, 0xbc, 0x54, 0x00, 0xe0, 0xf8, 0x63, 0x17, 0x22, 0x44, 0x36, 0xe0, 0x28, 0xa0, 0x7d, 334 0x50, 0x9e, 0x50, 0x94, 0xea, 0xd7, 0x62, 0xab, 0x6d, 0x7a, 0x19, 0xa4, 0xa2, 0x74, 0x79, 0x5d, 335 0x15, 0x85, 0x21, 0xfe, 0x9a, 0x35, 0x76, 0x40, 0x78, 0x01, 0xe3, 0x46, 0x2f, 0x6f, 0x2d, 0x0a, 336 0x1d, 0xac, 0x2e, 0x23, 0xec, 0xb8, 0x48, 0x74, 0xbc, 0xee, 0x29, 0x72, 0xb6, 0xe7, 0x52, 0x8c, 337 0xd4, 0x1a, 0x00, 0x34, 0x75, 0x1c, 0x4b, 0x83, 0x50, 0xbb, 0x57, 0x21, 0x9b, 0xd8, 0xb4, 0x75, 338 0xf3, 0x98, 0x8a, 0x9b, 0x45, 0xa8, 0x61, 0x50, 0x10, 0xb4, 0xec, 0x91, 0x2e, 0xe7, 0xf2, 0xb8, 339 0xb9, 0x62, 0x70, 0xc2, 0x93, 0xe7, 0xd9, 0xf1, 0x02, 0x27, 0xd7, 0xec, 0xde, 0x5b, 0x42, 0xa1, 340 0x26, 0x37, 0x41, 0x32, 0x65, 0x11, 0x63, 0x38, 0xbb, 0x6f, 0x23, 0x7a, 0xa0, 0xb7, 0x24, 0xeb, 341 0xa8, 0x38, 0x8b, 0xa7, 0x73, 0xe2, 0xc8, 0x30, 0x56, 0x73, 0x6f, 0x17, 0x6e, 0x1a, 0xe5, 0x32, 342 0xff, 0xd6, 0xa2, 0x08, 0x7b, 0x6a, 0x23, 0x33, 0x9f, 0x10, 0x05, 0x71, 0xdd, 0x02, 0x03, 0x01, 343 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 344 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, 0x99, 0xc4, 345 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 346 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 347 0x16, 0x80, 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, 348 0x99, 0xc4, 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 349 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 350 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x71, 0x10, 0x3c, 0x89, 0xd5, 351 0xc0, 0x00, 0xdc, 0x36, 0x1d, 0x93, 0xaa, 0xab, 0x4a, 0xb6, 0xfa, 0xa8, 0x5b, 0x89, 0x1c, 0xb3, 352 0x4a, 0x04, 0x2e, 0xb3, 0x25, 0x0f, 0x12, 0x07, 0x29, 0x70, 0x3d, 0x34, 0xd1, 0xdd, 0x7e, 0x30, 353 0xfd, 0xf5, 0xfa, 0x94, 0xf4, 0xcb, 0xdb, 0xac, 0x1b, 0xed, 0xe5, 0x11, 0x4a, 0xc8, 0xab, 0x26, 354 0xe2, 0x41, 0xcb, 0xa5, 0x74, 0x4b, 0xe1, 0xd2, 0xf3, 0x83, 0x1c, 0x7a, 0xcb, 0x29, 0xd9, 0xd2, 355 0xa6, 0x9d, 0x08, 0x95, 0x73, 0x63, 0xe2, 0x9c, 0xeb, 0xa5, 0x82, 0x8b, 0x6c, 0xf4, 0x64, 0x98, 356 0x03, 0x53, 0x91, 0x35, 0x04, 0x89, 0x25, 0xa0, 0x1f, 0xdc, 0x42, 0xf7, 0x59, 0x44, 0x63, 0x75, 357 0xe6, 0x49, 0x10, 0x66, 0x0f, 0x08, 0x07, 0x39, 0xc4, 0x3e, 0x1f, 0xba, 0x30, 0x42, 0xf8, 0x7a, 358 0xc8, 0xbe, 0x6f, 0xdb, 0xec, 0x16, 0xb2, 0x76, 0x84, 0x2c, 0x6e, 0x20, 0xd1, 0xbd, 0xd5, 0x90, 359 0x22, 0x0a, 0x90, 0x5c, 0x70, 0x47, 0xc9, 0x2d, 0xe3, 0x77, 0x74, 0xfd, 0xbb, 0x85, 0x1a, 0xd8, 360 0x5c, 0x38, 0x94, 0x4c, 0x83, 0x28, 0x23, 0xa5, 0x4f, 0x55, 0x5f, 0xe3, 0x42, 0x80, 0x10, 0xd4, 361 0xa5, 0x8d, 0xcf, 0x8b, 0x53, 0x69, 0x6d, 0xc5, 0x37, 0xd2, 0xfa, 0xbb, 0xc0, 0x5a, 0xab, 0x6f, 362 0x71, 0x37, 0x92, 0xd4, 0x90, 0xef, 0x5d, 0xf1, 0xc3, 0xb8, 0x64, 0x08, 0xd3, 0xba, 0x36, 0x69, 363 0x2b, 0x00, 0xed, 0xad, 0x36, 0x21, 0x38, 0xdf, 0x4a, 0xc6, 0x44, 0xc4, 0x6b, 0xd8, 0xb0, 0x7f, 364 0x67, 0x05, 0xaa, 0x6f, 0x9e, 0x8a, 0xf1, 0x81, 0x95, 0x99, 0xb9, 0x56, 0xf4, 0x73, 0xa7, 0xb4, 365 0x19, 0xb9, 0x4b, 0xb8, 0x1d, 0x10, 0xa5, 0x88, 0x7c, 0x39, 0xa3, 0x85, 0xe7, 0xba, 0x65, 0x86, 366 0xca, 0xf7, 0x0e, 0xe0, 0x0d, 0x73, 0x3f, 0xea, 0x98, 0x88, 0x58, 0x73, 0xfa, 0x68, 0x5b, 0xaa, 367 0x8c, 0xfd, 0x3e, 0x22, 0x3e, 0x92, 0xc7, 0xe2, 0x77, 0x14, 0x81, 0xe6, 0xd9, 0xdc, 0xc1, 0xe9, 368 0xc0, 0x06, 0x57, 0xb4, 0xca, 0xb6, 0x14, 0x15, 0x16, 0x80, 0x7e, 0xc5, 0x11, 0xa4, 0x05, 0x66, 369 0xad, 0x1d, 0xa3, 0xb6, 0xab, 0x2a, 0xbe, 0xd0, 0x52, 0x4e, 0x9e, 0x84, 0x61, 0x6b, 0xf4, 0x34, 370 0x23, 0x94, 0x24, 0xc6, 0xc8, 0xb0, 0x94, 0x22, 0x4c, 0x3b, 0xac, 0x85, 0xe3, 0xd4, 0xf7, 0x38, 371 0xe5, 0x9a, 0x76, 0xb3, 0x1b, 0xf0, 0xbc, 0x78, 0xc6, 0x6f, 0x11, 0xb3, 0x1a, 0x5c, 0x4f, 0x07, 372 0x52, 0x06, 0x92, 0x7a, 0x25, 0x86, 0x91, 0x71, 0x8a, 0xf4, 0x03, 0xce, 0x19, 0x0d, 0xfc, 0xde, 373 0x8f, 0xc9, 0x4e, 0x84, 0xf1, 0x17, 0x18, 0x6f, 0x37, 0x56, 0xb9, 0x76, 0x7e, 0x8f, 0xca, 0xde, 374 0xd4, 0x1b, 0x2d, 0x8d, 0xcf, 0x12, 0x9f, 0xf9, 0xb9, 0x8b, 0x82, 0x8f, 0x4d, 0xb7, 0x63, 0x26, 375 0x8d, 0xda, 0x35, 0x94, 0x18, 0xf9, 0x55, 0xca, 0x39, 0x09, 0xe9, 0x62, 0xe1, 0x00, 0xd8, 0x67, 376 0xed, 0x5e, 0x84, 0xc2, 0xe5, 0x8e, 0x46, 0x57, 0xa4, 0xa7, 0x17, 0x70, 0xcf, 0x6d, 0xdf, 0x43, 377 0x64, 0x2b, 0x36, 0xe6, 0xf3, 0xc1, 0x4c, 0x7a, 0x7e, 0x9e, 0x47, 0xc4, 0x14, 0x82, 0xbe, 0x94, 378 0x73, 0x54, 0xd0, 0x2c, 0xc2, 0x31, 0xc6, 0xd5, 0xc3, 0xd7, 0xa9, 0xef, 0x11, 0x24, 0x2f, 0xd0, 379 0x5b, 0xb8, 0x6a, 0x8e, 0x3c, 0xb7, 0x4b, 0x00, 0x9b, 0xc1, 0xca, 0x00, 0x6f, 0xd4, 0x73, 0x93, 380 0x2e, 0x39, 0x37, 0x2a, 0x73, 0x44, 0x9b, 0x1b, 0x05, 0x1a, 0x7c, 0x2f, 0xc9, 0x2b, 0x37, 0xf3, 381 0xcd, 0x8c, 0x4e, 0xc2, 0x7a, 0x6e, 0xd9, 0xd4, 0xf1, 0x8d, 0x6d, 0x07, 0x4b, 0xb5, 0x09, 0xb9, 382 0x48, 0x55, 0xac, 0xc6, 0x7e, 0xbc, 0xc6, 0x76, 0xeb, 0x5f, 0x0f 383 384}; 385 386static NSDictionary* VerifyMessage(CFDataRef message, SecPolicyRef policy, CFDataRef cert_data) 387{ 388 NSDictionary* result = nil; 389 390 SecTrustRef trustRef = NULL; 391 CFDataRef payload = NULL; 392 CFArrayRef anchors = NULL; 393 OSStatus status = noErr; 394 SecCertificateRef aCertRef = NULL; 395 SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure; 396 397 if (NULL == message || NULL == policy || NULL == cert_data) 398 { 399 goto out; 400 } 401 402 status = SecCMSVerifyCopyDataAndAttributes(message, NULL, policy, &trustRef, &payload, NULL); 403 if (noErr != status || NULL == trustRef || NULL == payload) 404 { 405 goto out; 406 } 407 408 aCertRef = SecCertificateCreateWithData(NULL, cert_data); 409 if (NULL == aCertRef) 410 { 411 goto out; 412 } 413 414 anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&aCertRef, 1, &kCFTypeArrayCallBacks); 415 if (NULL == anchors) 416 { 417 goto out; 418 } 419 420 status = SecTrustSetAnchorCertificates(trustRef, anchors); 421 if (noErr != status) 422 { 423 goto out; 424 } 425 426 status = SecTrustEvaluate(trustRef, &trust_result); 427 428 if (noErr != status) 429 { 430 goto out; 431 } 432 433 if (trust_result == kSecTrustResultUnspecified) 434 { 435 // Life is good and we got back the expected result. 436 437 NSData* property_list_data = CFBridgingRelease(payload); 438 439 NSPropertyListFormat format; 440 NSError* error = nil; 441 result = [NSPropertyListSerialization propertyListWithData:property_list_data options:0 format:&format error:&error]; 442 if (nil != error) 443 { 444 result = nil; 445 } 446 } 447 448out: 449 CFReleaseSafe(aCertRef) 450 CFReleaseSafe(anchors); 451 return result; 452} 453 454/* ========================================================================== 455 Private Methods for the OTAServiceApp class 456 ========================================================================== */ 457@interface OTAServiceApp (PrivateMethods) 458- (void)processAssets:(NSArray*)assets; 459- (BOOL)checkAssetVersions:(NSString *)assetDir; 460- (BOOL)validateAsset:(NSString *)assetDir; 461- (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names; 462- (NSDictionary *)decodeManifest:(NSData *)manifest_file_data; 463- (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash; 464- (BOOL)installAssetFiles:(NSString *)assetDir; 465- (NSString*)getCurrentAssetDirectory; 466 467@end 468 469@implementation OTAServiceApp 470 471@synthesize file_list = _file_list; 472@synthesize manifest_file_name = _manifest_file_name; 473@synthesize asset_version_file_name = _asset_version_file_name; 474@synthesize current_asset_version = _current_asset_version; 475@synthesize next_asset_version = _next_asset_version; 476@synthesize fileManager = _fileManager; 477@synthesize current_asset_directory = _current_asset_directory; 478@synthesize assets_directory = _assets_directory; 479 480/* -------------------------------------------------------------------------- 481 OTAServiceApp init:withArguments: 482 483 Initialize a new instance of the OTAServiceApp class 484 -------------------------------------------------------------------------- */ 485- (id)init:(int)argc withArguments:(const char**)argv 486{ 487 if ((self = [super init])) 488 { 489 _fileManager = [NSFileManager defaultManager]; 490 491 _manifest_file_name = (NSString *)kManifestFileName; 492 _asset_version_file_name = (NSString *)kAssetVersionFileName; 493 _file_list = [NSArray arrayWithObjects:kBlockKeyFileName, kGrayListedKeysFileName, 494 kEVRootsFileName, kCertsIndexFileName, kCertsTableFileName, 495 kManifestFileName, kAssetVersionFileName, kAppleESCertificatesName, nil]; 496 497 _current_asset_version = nil; 498 _next_asset_version = nil; 499 _assets_directory = nil; 500 _current_asset_directory = [self getCurrentAssetDirectory]; 501 502 /* Default interval is one hour */ 503 _asset_query_retry_interval = 60.0 * 60; 504 _verbose = false; 505 506 int ch; 507 while ((ch = getopt(argc, (char * const *)argv, "d:v")) != -1 ) 508 { 509 switch (ch) 510 { 511 case 'd': 512 { 513 char *endptr = NULL; 514 errno = 0; 515 CFTimeInterval interval = strtod(optarg, &endptr); 516 if ((interval == 0 && endptr == optarg) || errno == ERANGE) { 517 syslog(LOG_ERR, "invalid argument '%s', ignoring", optarg); 518 } else { 519 syslog(LOG_NOTICE, "Setting query retry interval to %f seconds", interval); 520 _asset_query_retry_interval = (CFTimeInterval)interval; 521 } 522 } 523 break; 524 case 'v': 525 syslog(LOG_NOTICE, "Enabling verbose logging"); 526 _verbose = true; 527 break; 528 default: 529 break; 530 } 531 } 532 533 struct stat info; 534#if NEW_LOCATION 535 if (stat([kBaseAssetDirectoryPath UTF8String], &info)) 536 { 537 OTAPKI_LOG("OTAServiceApp.init:withArguments: stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]); 538 539 if (mkdir([kBaseAssetDirectoryPath UTF8String], kAssetDirectoryPermission)) 540 { 541 OTAPKI_LOG("OTAServiceApp.init:withArguments: mkdir of %s failed\n", [kBaseAssetDirectoryPath UTF8String]); 542 } 543 else 544 { 545 if (stat([kBaseAssetDirectoryPath UTF8String], &info)) 546 { 547 OTAPKI_LOG("OTAServiceApp.init:withArguments: second stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]); 548 } 549 } 550 } 551#else 552 stat([kBaseAssetDirectoryPath UTF8String], &info); 553 554 _uid = info.st_uid; 555 _gid = info.st_gid; 556#endif 557 558 } 559 560 return self; 561} 562 563#if !TARGET_IPHONE_SIMULATOR 564 565- (void)registerBackgroundTaskAgentJobWithDelay:(CFTimeInterval)delay 566{ 567 /* 568 * ELEs are very important, so allow asset queries on any network type and 569 * construct the job so that it will fire as soon as possible, unless we are 570 * scheduling a retry after a failure. 571 */ 572 xpc_object_t job = xpc_dictionary_create(NULL, NULL, 0); 573 if (delay != 0) 574 { 575 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowStartTime, CFAbsoluteTimeGetCurrent() + delay); 576 } 577 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowEndTime, CFAbsoluteTimeGetCurrent() + BACKGROUND_TASK_AGENT_JOB_WINDOW_MAX_TIME_FROM_NOW_SEC); 578 xpc_dictionary_set_bool(job, kBackgroundTaskAgentNetworkRequired, true); 579 xpc_dictionary_set_bool(job, kBackgroundTaskAgentCellularAllowed, true); 580 xpc_dictionary_set_bool(job, kBackgroundTaskAgentAllowedDuringRoaming, true); 581 xpc_dictionary_set_bool(job, kBackgroundTaskAgentPowerOptLevel, kBackgroundTaskAgentPowerDontCare); 582 583 if (_verbose) 584 { 585 char *desc = xpc_copy_description(job); 586 syslog(LOG_NOTICE, "Adding BTA job %s", desc); 587 free(desc); 588 } 589#pragma GCC diagnostic push 590#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 591 BackgroundTaskAgentAddJob(kOTAPKIAssetToolActivity, job); 592#pragma GCC diagnostic pop 593} 594 595#endif 596 597/* -------------------------------------------------------------------------- 598 OTAServiceApp checkInWithActivity 599 600 Check in with the XPC activity configured in OTAPKIAssetTool's launchd 601 plist. This activity will launch OTAPKIAssetTool every three days (with 602 some leeway decided by the system). At that time, we schedule a 603 BackgroundTaskAgent job to be notified immediately when the network is 604 available so we can perform an asset query. 605 -------------------------------------------------------------------------- */ 606- (void)checkInWithActivity 607{ 608#if !TARGET_IPHONE_SIMULATOR 609#pragma GCC diagnostic push 610#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 611 BackgroundTaskAgentInit("com.apple.OTAPKIAssetTool", dispatch_get_main_queue(), ^(const char *job_name, xpc_object_t job) 612 { 613 /* 614 * We're doing real work at this point, so open a transaction so 615 * that the system (hopefully) won't kill us while we're busy 616 */ 617 xpc_transaction_begin(); 618 619 if (_verbose) 620 { 621 syslog(LOG_NOTICE, "BackgroundTaskAgent job %s fired", job_name); 622 } 623 624 int64_t job_status = xpc_dictionary_get_int64(job, kBackgroundTaskAgentJobStatus); 625 if (job_status == kBackgroundTaskAgentJobRequestError) 626 { 627 syslog(LOG_ERR, "Failed to create BTA job -- malformed job?"); 628 } 629 else if (job_status == kBackgroundTaskAgentJobSatisfied) 630 { 631 if (_verbose) 632 { 633 syslog(LOG_NOTICE, "BTA job %s is satisfied -- performing asset query", job_name); 634 } 635 bool shouldReschedule = false; 636 if ([self run:&shouldReschedule] || !shouldReschedule) 637 { 638 if (_verbose) 639 { 640 syslog(LOG_NOTICE, "Unscheduling BTA job"); 641 } 642 BackgroundTaskAgentRemoveJob(kOTAPKIAssetToolActivity); 643 } 644 else 645 { 646 syslog(LOG_NOTICE, "Asset query failed due to network error. Re-scheduling BTA job for another attempt in %f seconds.", _asset_query_retry_interval); 647 [self registerBackgroundTaskAgentJobWithDelay:_asset_query_retry_interval]; 648 } 649 } 650 else if (job_status == kBackgroundTaskAgentJobUnsatisfied) 651 { 652 /* 653 * We will receive this if the job expires before we get to do our 654 * work. We still want to check for new assets as soon as possible, 655 * so reschedule the job. 656 */ 657 if (xpc_dictionary_get_bool(job, kBackgroundTaskAgentJobExpired)) 658 { 659 [self registerBackgroundTaskAgentJobWithDelay:0]; 660 } 661 } 662 663 xpc_transaction_end(); 664 }); 665#pragma GCC diagnostic pop 666#endif 667 668 xpc_activity_register(kOTAPKIAssetToolActivity, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) 669 { 670 xpc_activity_state_t state = xpc_activity_get_state(activity); 671 672 if (_verbose) 673 { 674 xpc_object_t criteria = xpc_activity_copy_criteria(activity); 675 676 if (criteria != NULL) 677 { 678 char *desc = xpc_copy_description(criteria); 679 syslog(LOG_NOTICE, "Criteria for XPC activity %s: %s", kOTAPKIAssetToolActivity, desc); 680 free(desc); 681 } 682 else 683 { 684 syslog(LOG_NOTICE, "No critera for XPC activity %s", kOTAPKIAssetToolActivity); 685 } 686 } 687 688 if (state == XPC_ACTIVITY_STATE_CHECK_IN) 689 { 690 /* 691 * The activity is already configured in the launchd plist, so there 692 * is nothing to do here 693 */ 694 if (_verbose) 695 { 696 syslog(LOG_NOTICE, "Activity %s in check in state", kOTAPKIAssetToolActivity); 697 } 698 } 699 else if (state == XPC_ACTIVITY_STATE_RUN) 700 { 701#if !TARGET_IPHONE_SIMULATOR 702#pragma GCC diagnostic push 703#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 704 xpc_object_t job = BackgroundTaskAgentCopyJob(kOTAPKIAssetToolActivity); 705#pragma GCC diagnostic pop 706 if (job == NULL) 707 { 708 syslog(LOG_NOTICE, "Activity %s in run state. Scheduling BTA job for earliest network availability.", kOTAPKIAssetToolActivity); 709 [self registerBackgroundTaskAgentJobWithDelay:0]; 710 } 711 else if (_verbose) 712 { 713 syslog(LOG_NOTICE, "Already have a BTA job registered. Ignoring activity."); 714 } 715#else 716 /* 717 * BackgroundTaskAgent doesn't exist on the iOS simulator, so we 718 * just directly try to find and download new assets. 719 */ 720 xpc_transaction_begin(); 721 bool shouldReschedule = false; 722 if (![self run:&shouldReschedule]) { 723 syslog(LOG_NOTICE, "Asset query failed%s.", shouldReschedule ? " due to network issue" : ""); 724 } 725 xpc_transaction_end(); 726#endif 727 } 728 }); 729} 730 731/* -------------------------------------------------------------------------- 732 OTAServiceApp run 733 734 Run this program and leave. This program will currently run every 3 days, 735 with some leeway based on network availability. That will provide the 736 longest time from publisihing a change in the PKI trust setting asset and 737 having that asset be consumed by a device. 738 739 The program simnply ask the mobile asset daemon if there are any assets 740 to be processed with the PKITrustDataAssetType. If not this program 741 will just complete and will be re-run in 3 days. If there is an asset to 742 process then the asset will be process and then the program will complete. 743 744 Returns false if the operation failed. On return, shouldReschedule is set 745 to true if the operation failed due to a network error and the caller 746 should reschedule this operation at a more opportune time. 747 -------------------------------------------------------------------------- */ 748- (bool)run:(bool *)shouldReschedule 749{ 750 @autoreleasepool 751 { 752 if (shouldReschedule != NULL) { 753 *shouldReschedule = false; 754 } 755 756 syslog(LOG_NOTICE, "OTAPKIAssetTool running"); 757 if (![[MCProfileConnection sharedConnection] isOTAPKIUpdatesAllowed]) 758 { 759 syslog(LOG_NOTICE, "OTAPKIAssetTool: OTAPKI updates are not allowed."); 760 return false; 761 } 762 763 ASAssetQuery *assetQuery = [[ASAssetQuery alloc] initWithAssetType:(NSString *)kPKITrustDataAssetType]; 764 if (assetQuery == nil) 765 { 766 syslog(LOG_NOTICE, "OTAPKIAssetTool: Could not create the asset query."); 767 return false; 768 } 769 770 // Get the asset synchronously 771 NSError *error = nil; 772 NSArray *foundAssets = [assetQuery runQueryAndReturnError:&error]; 773 if (nil != foundAssets) 774 { 775 [self processAssets:foundAssets]; 776 } 777 else 778 { 779 syslog(LOG_NOTICE, "OTAPKIAssetTool: No assets returned from query: %s", [[error description] UTF8String]); 780 781 NSArray *networkErrorCodes = @[ @(ASErrorNetwork), @(ASErrorNetworkNoConnection), @(ASErrorNetworkTimedOut), @(ASErrorNetworkUnexpectedResponse) ]; 782 if ([[error domain] isEqualToString:ASErrorDomain] && [networkErrorCodes containsObject:@([error code])]) 783 { 784 syslog(LOG_NOTICE, "OTAPKIAssetTool: Query failed due to network error."); 785 if (shouldReschedule != NULL) { 786 *shouldReschedule = true; 787 } 788 } 789 return false; 790 } 791 792 return true; 793 } 794} 795 796/* -------------------------------------------------------------------------- 797 OTAServiceApp processAssets: 798 799 If when run is called asset(s) are found they will be processed here. 800 -------------------------------------------------------------------------- */ 801- (void)processAssets:(NSArray*)assets 802{ 803 if (nil == assets) 804 { 805 return; 806 } 807 808 NSError* error = nil; 809 ASAsset* asset = nil; 810 int asset_version = 0; 811 812 for (asset in assets) 813 { 814 NSDictionary* asset_attributes = asset.attributes; 815 816 NSNumber* contentVersion = [asset_attributes objectForKey:@"ContentVersion"]; 817 OTAPKI_LOG("In processAssets: about to check the ContentVersion\n"); 818 if (nil != contentVersion) 819 { 820 asset_version = [contentVersion intValue]; 821 int current_asset_version_number = (nil != _current_asset_version) ? [_current_asset_version intValue] : 0; 822 823 if (asset_version <= current_asset_version_number) 824 { 825 syslog(LOG_NOTICE, "OTAPKIAssetTool: content version %d is too small. Current asset version id %d", 826 asset_version, current_asset_version_number); 827 828 OTAPKI_LOG("In processAssets: content version is too small: current asset version is %d\nContent version is %d\n", 829 current_asset_version_number, asset_version); 830 asset = nil; 831 continue; 832 } 833 } 834 835 if (nil == asset) 836 { 837 syslog(LOG_NOTICE, "OTAPKIAssetTool: no suitable asset found"); 838 return; 839 } 840 841 842 // Check to see if the asset needs to be downloaded 843 if (asset.state == ASAssetStateNotPresent) 844 { 845 __block dispatch_semaphore_t sem = dispatch_semaphore_create(0); 846 847 [asset setProgressHandler:^(NSDictionary *state, NSError *anError) 848 { 849 if (error != nil) 850 { 851 // An error occured. Signal the semaphore to bail 852 dispatch_semaphore_signal(sem); 853 } 854 else if ([[state objectForKey:@"Operation"] isEqualToString:(NSString *) @"OperationCompleted"]) 855 { 856 // The download is complete. Signal the semaphore 857 dispatch_semaphore_signal(sem); 858 } 859 }]; 860 861 NSNumber* yesValue = [NSNumber numberWithBool:YES]; 862 const id keys[] = {ASDownloadOptionAllow3G, ASDownloadOptionAllow4G, ASDownloadOptionPriority, ASDownloadOptionAllowBatteryPower}; 863 const id values[] = {yesValue, yesValue, ASDownloadPriorityHigh, yesValue}; 864 865 NSDictionary* options = [NSDictionary dictionaryWithObjects:values forKeys:keys count:(sizeof (keys) / sizeof(keys[0]))]; 866 867 [asset beginDownloadWithOptions:options]; 868 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 869 } 870 871 // Check to see if the asset is now available for processing 872 if ([asset state] == ASAssetStateInstalled) 873 { 874 // Get the asset data directory 875 NSString* assetDir = [[[asset localURL] URLByAppendingPathComponent:@"PKITrustData"] path]; 876 if (nil != assetDir) 877 { 878 // validate the asset. 879 OTAPKI_LOG("In processAssets: about to validateAsset\n"); 880 if ([self validateAsset:assetDir]) 881 { 882 OTAPKI_LOG("In processAssets: asset validated installing\n"); 883 // The asset is valid so install the files 884 [self installAssetFiles:assetDir]; 885 886 // Signal securityd to idle-exit at it's next opportunity 887 OTAPKI_LOG("In processAssets: notifying securityd\n"); 888 int didUpdate = 0; 889 (void)SecTrustOTAPKIGetUpdatedAsset(&didUpdate); 890 syslog(LOG_NOTICE, "OTAPKIAssetTool: installed new asset %d", asset_version); 891 } 892 else 893 { 894 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset %d did not validate", asset_version); 895 } 896 897 // regaurdless if the asset is valid. Now that it is 898 // installed, it needs to be purged to ensure that 899 // we can retrieve a new updated asset. 900 [asset purgeAndReturnError:&error]; 901 } 902 else 903 { 904 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset directory %s not found", [assetDir UTF8String]); 905 } 906 } 907 } 908} 909 910/* -------------------------------------------------------------------------- 911 OTAServiceApp checkAssetVersions: 912 913 If when run is called asset(s) are found they will be processed here. 914 -------------------------------------------------------------------------- */ 915- (BOOL)checkAssetVersions:(NSString *)assetDir 916{ 917 BOOL result = NO; 918 919 OTAPKI_LOG("Entering checkAssetVersions\n"); 920 921 if (nil == assetDir || nil == self.current_asset_version) 922 { 923 OTAPKI_LOG("checkAssetVersions: parameter error\n"); 924 return result; 925 } 926 927 // first get the new version number from the downloaded asset 928 NSString* next_asset_version_path = [assetDir stringByAppendingPathComponent:self.asset_version_file_name]; 929 if (![self.fileManager fileExistsAtPath:next_asset_version_path]) 930 { 931 // The asset is missing the AssertVersion.plist 932 // This is an invalid asset 933 OTAPKI_LOG("checkAssetVersions: could not file asseet version file %s\n", [self.asset_version_file_name UTF8String]); 934 return result; 935 } 936 937 NSError* error = nil; 938 NSInputStream* input_stream = [NSInputStream inputStreamWithFileAtPath:next_asset_version_path]; 939 [input_stream open]; 940 NSDictionary* asset_dict = [NSPropertyListSerialization propertyListWithStream:input_stream options:0 format:nil error:&error]; 941 [input_stream close]; 942 943 if (nil != error) 944 { 945 OTAPKI_LOG("checkAssetVersions: error reading asset version file: %s\n", [[error localizedDescription] UTF8String]); 946 return result; 947 } 948 949 _next_asset_version = [asset_dict objectForKey:kVersionNumberKey]; 950 if (nil == _next_asset_version) 951 { 952 OTAPKI_LOG("asset_dict did not have a entry with a key of kVersionNumberKey\n"); 953 return result; 954 } 955 956 // Check the current asset version against the new asset version. The new asset version MUST be larger than the 957 // current asset version 958 NSInteger current_asset_version_value = [self.current_asset_version integerValue]; 959 NSInteger next_asset_version_value = [self.next_asset_version integerValue]; 960 961 if (next_asset_version_value <= current_asset_version_value) 962 { 963 OTAPKI_LOG("heckAssetVersions: assert version too small. current_asset_version_value = %d next_asset_version_value = %d\n", 964 current_asset_version_value, next_asset_version_value); 965 return result; 966 } 967 968 return YES; 969} 970 971 972/* -------------------------------------------------------------------------- 973 OTAServiceApp validateAsset: 974 975 Decode the manifest and verify the file hashes 976 -------------------------------------------------------------------------- */ 977- (BOOL)validateAsset:(NSString *)assetDir 978{ 979 BOOL result = NO; 980 981 OTAPKI_LOG("Enterning validateAsset\n"); 982 983 if (![self validateDirectory:assetDir withFiles:self.file_list]) 984 { 985 OTAPKI_LOG("validateAsset param\n"); 986 return result; 987 } 988 989 NSString* manifest_file_path = [assetDir stringByAppendingPathComponent:self.manifest_file_name]; 990 NSError* error = nil; 991 NSData* manifest_file_data = [NSData dataWithContentsOfFile:manifest_file_path options:0 error:&error]; 992 if (nil != error) 993 { 994 OTAPKI_LOG("validateAsset: could not read manifest file. error = %s\n", [[error localizedDescription] UTF8String]); 995 return result; 996 } 997 998 NSDictionary* manifest_data = [self decodeManifest:manifest_file_data]; 999 if (nil == manifest_data) 1000 { 1001 OTAPKI_LOG("validateAsset: decodeManifest failed!\n"); 1002 return result; 1003 } 1004 1005 NSString* full_file_path = nil; 1006 NSData* hash = nil; 1007 for (NSString* file_name in self.file_list) 1008 { 1009 if ([file_name isEqualToString:self.manifest_file_name]) 1010 { 1011 continue; 1012 } 1013 1014 hash = [manifest_data objectForKey:file_name]; 1015 if (nil == hash) 1016 { 1017 OTAPKI_LOG("validateAsset: could not get hash for file %s\n", [file_name UTF8String]); 1018 return result; 1019 } 1020 1021 full_file_path = [assetDir stringByAppendingPathComponent:file_name]; 1022 if (![self checkFileHash:full_file_path hash:hash]) 1023 { 1024 OTAPKI_LOG("validateAsset: hash for file %s does not match\n", [file_name UTF8String]); 1025 return result; 1026 } 1027 } 1028 1029 result = [self checkAssetVersions:assetDir]; 1030 return result; 1031} 1032 1033/* -------------------------------------------------------------------------- 1034 OTAServiceApp validateDirectory:withFiles: 1035 1036 Ensure that a given directory has the files listed in the files_names 1037 parameter 1038 -------------------------------------------------------------------------- */ 1039- (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names 1040{ 1041 BOOL result = NO; 1042 OTAPKI_LOG("Enterning validateDirectory\n"); 1043 1044 if (nil == assetDir || nil == file_names) 1045 { 1046 OTAPKI_LOG("validateDirectory param error\n"); 1047 return result; 1048 } 1049 NSError* error = nil; 1050 NSArray* dir_items = [self.fileManager contentsOfDirectoryAtPath:assetDir error:&error]; 1051 if (nil != error) 1052 { 1053 OTAPKI_LOG("validateDirectory: Error calling contentsOfDirectoryAtPath: error = %s\n", [[error localizedDescription] UTF8String]); 1054 return result; 1055 } 1056 1057 for (NSString* file_name in file_names) 1058 { 1059 if (![dir_items containsObject:file_name]) 1060 { 1061 OTAPKI_LOG("validateDirectory: missing file %s\n", [file_name UTF8String]); 1062 return result; 1063 } 1064 } 1065 1066 return YES; 1067} 1068 1069/* -------------------------------------------------------------------------- 1070 OTAServiceApp decodeManifest: 1071 1072 Ensure that the asset manifest blob has it CMS signature verified 1073 -------------------------------------------------------------------------- */ 1074- (NSDictionary *)decodeManifest:(NSData *)manifest_file_data 1075{ 1076 NSDictionary* result = nil; 1077 CFDataRef cert_data = NULL; 1078 CFDataRef message = NULL; 1079 SecPolicyRef policy = NULL; 1080 CFBooleanRef mgResult = NULL; 1081 1082 OTAPKI_LOG("Enterning decodeManifest\n"); 1083 1084 if (nil == manifest_file_data) 1085 { 1086 OTAPKI_LOG("decodeManifest: parameter error\n"); 1087 goto out; 1088 } 1089 1090 message = CFBridgingRetain(manifest_file_data); 1091 1092 policy = SecPolicyCreateOTAPKISigner(); 1093 if (NULL == policy) 1094 { 1095 OTAPKI_LOG("decodeManifest: could not get the SecPolicyCreateOTAPKISigner policyRef\n"); 1096 goto out; 1097 } 1098 1099 cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert)); 1100 if (NULL == cert_data) 1101 { 1102 OTAPKI_LOG("decodeManifest: could not kApplePKISettingsRootCACert data\n"); 1103 goto out; 1104 } 1105 1106 result = VerifyMessage(message, policy, cert_data); 1107 1108 if (NULL != result) 1109 { 1110 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner success!\n"); 1111 goto out; 1112 } 1113 1114 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner failed! Checking to see if this is an internal build\n"); 1115 1116 // The first attempt did not work so check to see if this is running on an internal build. 1117 if (!MGIsQuestionValid(kMGQAppleInternalInstallCapability)) 1118 { 1119 OTAPKI_LOG("decodeManifest: kMGQAppleInternalInstallCapability had an error\n"); 1120 goto out; 1121 } 1122 1123 mgResult = MGCopyAnswer(kMGQAppleInternalInstallCapability, NULL); 1124 1125 if (NULL == mgResult || !CFEqual(mgResult, kCFBooleanTrue)) 1126 { 1127 OTAPKI_LOG("decodeManifest: Not an internal build"); 1128 goto out; 1129 } 1130 1131 OTAPKI_LOG("decodeManifest: This is an internal build\n"); 1132 1133 CFReleaseNull(policy); 1134 CFReleaseNull(cert_data); 1135 1136 policy = SecPolicyCreateTestOTAPKISigner(); 1137 if (NULL == policy) 1138 { 1139 OTAPKI_LOG("decodeManifest: could not SecPolicyCreateTestOTAPKISigner policyRef\n"); 1140 goto out; 1141 } 1142 1143 cert_data = CFDataCreate(kCFAllocatorDefault, kAppleTestPKISettingsRootCACert, sizeof(kAppleTestPKISettingsRootCACert)); 1144 if (NULL == cert_data) 1145 { 1146 OTAPKI_LOG("decodeManifest: could not kAppleTestPKISettingsRootCACert data\n"); 1147 goto out; 1148 } 1149 1150 result = VerifyMessage(message, policy, cert_data); 1151 1152out: 1153 1154 CFReleaseSafe(mgResult); 1155 CFReleaseSafe(message); 1156 CFReleaseSafe(policy); 1157 CFReleaseSafe(cert_data); 1158 return result; 1159} 1160 1161/* -------------------------------------------------------------------------- 1162 OTAServiceApp checkFileHash:hash: 1163 1164 Ensure that the given asset file's hash is the same as in the manifest 1165 -------------------------------------------------------------------------- */ 1166- (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash 1167{ 1168 BOOL result = NO; 1169 if (nil == file_path || nil == hash) 1170 { 1171 return result; 1172 } 1173 1174 NSError* error = nil; 1175 NSData* file_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error]; 1176 if (nil != error) 1177 { 1178 return result; 1179 } 1180 1181 UInt8 buffer[CC_SHA256_DIGEST_LENGTH]; 1182 memset(buffer, 0, CC_SHA256_DIGEST_LENGTH); 1183 CC_SHA256([file_data bytes], (CC_LONG)[file_data length], buffer); 1184 NSData* file_hash_data = [NSData dataWithBytesNoCopy:buffer length:CC_SHA256_DIGEST_LENGTH freeWhenDone:NO]; 1185 1186 result = [hash isEqualToData:file_hash_data]; 1187 1188 return result; 1189} 1190 1191/* -------------------------------------------------------------------------- 1192 OTAServiceApp installAssetFiles: 1193 1194 Copy over the files into the /var/Keychains/Assets directory. 1195 -------------------------------------------------------------------------- */ 1196- (BOOL)installAssetFiles:(NSString *)assetDir 1197{ 1198 BOOL result = NO; 1199 1200 OTAPKI_LOG("Entering installAssetFiles\n"); 1201 1202 if (nil == assetDir) 1203 { 1204 OTAPKI_LOG("installAssetFiles: parameter error\n"); 1205 return result; 1206 } 1207 1208 if (nil == self.assets_directory) 1209 { 1210 OTAPKI_LOG("installAssetFiles: no assets directory\n"); 1211 return result; 1212 } 1213 1214 // Create a temp directory to hold the new asset files. 1215 NSString* tempDir = [self.assets_directory stringByAppendingPathComponent:@"TempAssetDir"]; 1216 NSError* error = nil; 1217 1218#if NEW_LOCATION 1219 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; 1220 id keys[] = {NSFilePosixPermissions}; 1221 1222 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1]; 1223#else 1224 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]); 1225 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]); 1226 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid]; 1227 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid]; 1228 1229 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; 1230 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions}; 1231 1232 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3]; 1233#endif 1234 1235 1236 if (![self.fileManager createDirectoryAtPath:tempDir withIntermediateDirectories:YES 1237 attributes:attributes error:&error]) 1238 { 1239 OTAPKI_LOG("installAssetFiles: could not create directory %s\n", [tempDir UTF8String]); 1240 return result; 1241 } 1242 1243#ifndef NEW_LOCATION 1244 // Copy all of the asset files to the newly created directory 1245 for (NSString* file_name in self.file_list) 1246 { 1247 NSString* download_assert_path = [assetDir stringByAppendingPathComponent:file_name]; 1248 NSString* asset_path = [tempDir stringByAppendingPathComponent:file_name]; 1249 if ([self.fileManager copyItemAtPath:download_assert_path toPath:asset_path error:&error]) 1250 { 1251 chown([asset_path UTF8String], self.uid, self.gid); 1252 } 1253 else 1254 { 1255 [self.fileManager removeItemAtPath:tempDir error:nil]; 1256 return result; 1257 } 1258 } 1259#endif // !NEW_LOCATION 1260 1261 1262 // Now that all of the files have been copied to the temp directory make a single call 1263 // to rename (move) the temp directory to be the correct version directory. This rename 1264 // allow for reducing a race conditions between this asset code and securityd. 1265 NSInteger new_version_value = [self.next_asset_version integerValue]; 1266 NSString* new_version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)new_version_value]; 1267 NSString* new_version_dir_path = [self.assets_directory stringByAppendingPathComponent:new_version_dir_name]; 1268 if (![self.fileManager moveItemAtPath:tempDir toPath:new_version_dir_path error:&error]) 1269 { 1270 OTAPKI_LOG("installAssetFiles: could not move path %s\n", [tempDir UTF8String]); 1271 [self.fileManager removeItemAtPath:tempDir error:nil]; 1272 return result; 1273 } 1274 1275 result = YES; 1276 return result; 1277} 1278 1279/* -------------------------------------------------------------------------- 1280 OTAServiceApp getCurrentAssetDirectory: 1281 1282 Looks through the /var/Keychains/Assets directory to find latest asset 1283 version directory. If no assets have been downloaded then nil is returned 1284 and the current asset version is set to 0 1285 -------------------------------------------------------------------------- */ 1286- (NSString*)getCurrentAssetDirectory 1287{ 1288 NSString* result = nil; 1289 BOOL isDir = NO; 1290 1291 OTAPKI_LOG("In getCurrentAssetDirectory\n"); 1292 OTAPKI_LOG("getCurrentAssetDirectory: checking to see if %s exists\n", [kBaseAssetDirectoryPath UTF8String]); 1293 1294 // Check to see if the base directory is there 1295 if (![self.fileManager fileExistsAtPath:(NSString *)kBaseAssetDirectoryPath isDirectory:&isDir] || !isDir) 1296 { 1297 OTAPKI_LOG("getCurrentAssetDirectory: %s does not exists\n", [kBaseAssetDirectoryPath UTF8String]); 1298 // This might be fatal 1299 return result; 1300 } 1301 1302 NSError* error = nil; 1303 NSInteger version_number = 0; 1304 NSInteger current_version_number = 0; 1305 int aVerNum = 0; 1306 OSStatus err = noErr; 1307 1308 _assets_directory = [kBaseAssetDirectoryPath stringByAppendingPathComponent:(NSString *)kAssetDirectoryName]; 1309 1310 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]); 1311 1312 if ([self.fileManager fileExistsAtPath:self.assets_directory isDirectory:&isDir] && isDir) 1313 { 1314 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]); 1315 NSDirectoryEnumerator* dirEnum = [self.fileManager enumeratorAtPath:self.assets_directory]; 1316 [dirEnum skipDescendents]; 1317 1318 for (NSString* file in dirEnum) 1319 { 1320 if ([file hasPrefix:(NSString *)kVersionDirectoryNamePrefix]) 1321 { 1322 NSString* version_str = [file substringFromIndex:[kVersionDirectoryNamePrefix length]]; 1323 NSInteger aVersion_number = [version_str integerValue]; 1324 if (aVersion_number > version_number) 1325 { 1326 version_number = aVersion_number; 1327 } 1328 } 1329 } 1330 } 1331 else 1332 { 1333#if NEW_LOCATION 1334 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; 1335 id keys[] = {NSFilePosixPermissions}; 1336 1337 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1]; 1338#else 1339 1340 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]); 1341 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]); 1342 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid]; 1343 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid]; 1344 1345 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; 1346 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions}; 1347 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3]; 1348#endif 1349 OTAPKI_LOG("getCurrentAssetDirectory: %s does NOT exists\n", [self.assets_directory UTF8String]); 1350 OTAPKI_LOG("getCurrentAssetDirectory: creating %s\n", [self.assets_directory UTF8String]); 1351 1352 if (![self.fileManager createDirectoryAtPath:self.assets_directory withIntermediateDirectories:YES 1353 attributes:attributes error:&error]) 1354 { 1355 OTAPKI_LOG("getCurrentAssetDirectory: failed to create %s\n", [self.assets_directory UTF8String]); 1356 return result; 1357 } 1358 1359 } 1360 1361 err = SecTrustGetOTAPKIAssetVersionNumber(&aVerNum); 1362 if (errSecSuccess == err && aVerNum > 0) 1363 { 1364 current_version_number = aVerNum; 1365 } 1366 1367 if (version_number < current_version_number) 1368 { 1369 OTAPKI_LOG("The largest OTA version number is smaller than the current version number. This means the system has a newer asset\n"); 1370 version_number = current_version_number; 1371 } 1372 else 1373 { 1374 OTAPKI_LOG("The largest OTA version number is equal to the current version number. The OTA asset is newer than the system asset\n"); 1375 NSString* version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)version_number]; 1376 result = [self.assets_directory stringByAppendingPathComponent:version_dir_name]; 1377 } 1378 1379 OTAPKI_LOG("getCurrentAssetDirectory: setting version number to %d\n", version_number); 1380 _current_asset_version = [NSNumber numberWithInteger:version_number]; 1381 return result; 1382} 1383 1384@end 1385