5 // Created by local on 2/11/13.
10 #import "OTAServiceApp.h"
12 #import <TargetConditionals.h>
13 #import <Security/Security.h>
14 #import <Security/SecPolicyPriv.h>
15 #import <Security/SecTrustPriv.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>
30 #if !TARGET_IPHONE_SIMULATOR
31 #import <BackgroundTaskAgent/BackgroundTaskAgent.h>
43 #define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } }
44 #define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } }
46 //#define VERBOSE_LOGGING 1
50 static void OTAPKI_LOG(const char* sz, ...)
55 FILE* fp = fopen("/tmp/OTAPKITool.log", "a");
66 #define OTAPKI_LOG(sz, ...)
70 //#define NEW_LOCATION 1
74 /* ==========================================================================
75 The following are a set of string constants used by this program.
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
82 kkManifestFileName - The file name of the manifest file for the
85 kAllowListFileName - The file name of the asset file that contains
86 hashes of the allowed leaf certificates whose
87 trust store root has been removed
89 kAssetVersionFileName - The file name of the plist file in the asset
90 that contains the version number of this
91 OTA PKI trust asset. It is a plist that is a
92 dictionary with a single key with a single
93 key value pair that has the version number
94 of the asset. This is used to ensure against
97 kBlockKeyFileName - The file name of the asset file that contains
98 blocked keys. Any certificate with these keys
99 will be marked as not being trusted.
101 kGrayListedKeysFileName - The file name of the asset file that contains
102 gray listed keys. If a chain has any of these
103 keys, than the chain will still be approved but
104 an entry will be added to the details dictionary
105 noting that the key was gray listed
108 kEVRootsFileName - The file name of the asset file that contains
109 the list of EV OIDS and their corresponding
110 certificates. This file sets which certs will
111 be considered to be EV.
113 kCTLogsFileName - The file name of the asset file that contains
114 the list of Certificate Transparency logs and
117 kCertsIndexFileName - The file name of the asset file that contains
118 a hash table of offsets into the cert table
119 file. This is used to look up anchor certs.
121 kCertsTableFileName - The file name of the asset file that contains
122 all of the anchor certificates. The
123 kCertsIndexFileName file is used to find the
124 correct offset in this file to retrieve a
125 specific anchor certificate.
127 kVersionNumberKey - The dictionary key for the kAssetVersionFileName
128 file to get the version number
130 kVersionDirectoryNamePrefix -
131 The directory name prefix for all of the
134 kPKITrustDataAssetType - The asset identifier of the OTA PKI asset
137 ========================================================================== */
140 static const NSString* kBaseAssetDirectoryPath = @"/var/OTAPKI";
142 static const NSString* kBaseAssetDirectoryPath = @"/var/Keychains";
145 static const NSString* kManifestFileName = @"manifest.data";
146 static const NSString* kAllowListFileName = @"Allowed.plist";
147 static const NSString* kAssetVersionFileName = @"AssetVersion.plist";
148 static const NSString* kAppleESCertificatesName = @"AppleESCertificates.plist";
149 static const NSString* kBlockKeyFileName = @"Blocked.plist";
150 static const NSString* kGrayListedKeysFileName = @"GrayListedKeys.plist";
151 static const NSString* kEVRootsFileName = @"EVRoots.plist";
152 static const NSString* kCTLogsFileName = @"TrustedCTLogs.plist";
153 static const NSString* kCertsIndexFileName = @"certsIndex.data";
154 static const NSString* kCertsTableFileName = @"certsTable.data";
155 static const NSString* kVersionNumberKey = @"VersionNumber";
156 static const NSString* kAssetDirectoryName = @"Assets";
157 static const NSString* kAssetDirectoryUser = @"_securityd";
158 static const NSString* kAssetDirectoryGroup = @"wheel";
160 static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRWXG | S_IRWXO;
162 static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
164 static const NSString* kVersionDirectoryNamePrefix = @"Version_";
165 static const NSString* kPKITrustDataAssetType =@"com.apple.MobileAsset.PKITrustServices.PKITrustData";
167 const char *kOTAPKIAssetToolActivity = "com.apple.OTAPKIAssetTool.asset-check";
168 const char *kOTAPKIAssetToolBTAJob = "com.apple.BTA.OTAPKIAssetTool.asset-check";
170 static const UInt8 kApplePKISettingsRootCACert[] = {
171 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e,
172 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
173 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55,
174 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65,
175 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74,
176 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
177 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70,
178 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
179 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06,
180 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e,
181 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17,
182 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d,
183 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84,
184 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65,
185 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f,
186 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
187 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
188 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
189 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
190 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70,
191 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
192 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
193 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a,
194 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04,
195 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc,
196 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe,
197 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29,
198 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77,
199 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf,
200 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f,
201 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa,
202 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e,
203 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a,
204 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d,
205 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99,
206 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05,
207 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3,
208 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d,
209 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb,
210 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3,
211 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4,
212 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d,
213 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce,
214 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc,
215 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff,
216 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7,
217 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f,
218 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22,
219 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70,
220 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f,
221 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf,
222 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7,
223 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee,
224 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62,
225 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63,
226 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82,
227 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82,
228 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6,
229 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
230 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35,
231 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f,
232 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca,
233 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63,
234 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01,
235 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00,
236 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00,
237 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00,
238 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00,
239 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00,
240 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00,
241 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00,
242 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00,
243 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00,
244 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00,
245 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00,
246 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00,
247 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00,
248 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00,
249 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00,
250 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00,
251 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00,
252 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00,
253 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00,
254 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00,
255 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00,
256 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00,
257 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00,
258 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16,
259 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c,
260 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
261 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
262 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
263 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a,
264 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0,
265 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52,
266 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf,
267 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60,
268 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34,
269 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37,
270 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe,
271 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd,
272 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9,
273 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62,
274 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44,
275 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38,
276 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a,
277 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92,
278 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6,
279 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2,
280 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53,
281 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19,
282 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb,
283 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63,
284 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61,
285 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef,
286 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e,
287 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4,
288 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c,
289 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81,
290 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17,
291 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10,
292 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6,
293 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa,
294 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce,
295 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8
299 static const UInt8 kAppleTestPKISettingsRootCACert[] = {
300 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x26,
301 0xfe, 0xf8, 0xda, 0x41, 0xf3, 0x61, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
302 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04,
303 0x03, 0x0c, 0x24, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74,
304 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20,
305 0x54, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b,
306 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
307 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
308 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20,
309 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
310 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x32, 0x32, 0x32, 0x30, 0x33, 0x31, 0x34,
311 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x34, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x34, 0x36,
312 0x5a, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, 0x41, 0x70,
313 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
314 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x54, 0x45, 0x53, 0x54, 0x49,
315 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70,
316 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
317 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
318 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
319 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22,
320 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
321 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x84, 0xbe, 0xc2,
322 0x69, 0x9b, 0xec, 0xd5, 0xde, 0x72, 0xf0, 0x4f, 0x78, 0x81, 0x10, 0xa9, 0x56, 0x59, 0x77, 0x9c,
323 0x46, 0x95, 0xd7, 0xb7, 0x0b, 0x77, 0x73, 0x02, 0xce, 0xf8, 0xaa, 0x32, 0x89, 0xee, 0xbe, 0xaa,
324 0x40, 0x53, 0xf9, 0x2d, 0x96, 0x08, 0xcd, 0x2a, 0xa4, 0x61, 0xd4, 0xfd, 0x7d, 0x67, 0x2a, 0x35,
325 0xc1, 0xfc, 0x43, 0xa4, 0x9c, 0xd0, 0xbd, 0xcd, 0x82, 0x27, 0xed, 0xa1, 0x1c, 0x2d, 0x9a, 0x62,
326 0xd5, 0x99, 0xbd, 0x74, 0xaa, 0xf3, 0xce, 0x78, 0xc6, 0x47, 0x07, 0x43, 0x04, 0x5b, 0xbc, 0x27,
327 0x5e, 0x26, 0x3e, 0x77, 0x90, 0x69, 0x7a, 0xf6, 0xe0, 0x8e, 0xaa, 0xdf, 0x96, 0x12, 0x2c, 0xb2,
328 0x8b, 0xb9, 0x7e, 0x17, 0xfe, 0xde, 0x99, 0x67, 0x9b, 0x50, 0x13, 0x5c, 0x8d, 0x15, 0x26, 0x0a,
329 0x9f, 0x08, 0x2f, 0x3f, 0x7c, 0x01, 0x2c, 0x3e, 0xa1, 0xba, 0xb1, 0x25, 0x33, 0xe5, 0xd9, 0x39,
330 0x37, 0xde, 0x06, 0x3a, 0x63, 0x48, 0xa0, 0x9d, 0x3b, 0xa5, 0x72, 0x46, 0xfb, 0x6e, 0xa2, 0xd4,
331 0x74, 0xe6, 0xf1, 0xc1, 0x69, 0xc8, 0x31, 0xff, 0x58, 0x84, 0x3a, 0xc2, 0x6b, 0x9a, 0x0d, 0x19,
332 0x76, 0xe4, 0xd4, 0x4d, 0x85, 0xbc, 0x84, 0xf0, 0x07, 0x75, 0x66, 0x5f, 0xd7, 0xea, 0xab, 0x9e,
333 0x46, 0xf2, 0x8a, 0x29, 0xab, 0x73, 0x57, 0xaf, 0x95, 0x4f, 0xc7, 0xf3, 0x3b, 0x55, 0xb4, 0x26,
334 0x57, 0x68, 0xe9, 0x5a, 0x34, 0xbb, 0xa9, 0x39, 0xb3, 0x57, 0x5f, 0x25, 0x93, 0xd6, 0x34, 0xb7,
335 0xd1, 0xc4, 0xd7, 0x70, 0xed, 0x30, 0xdb, 0x21, 0xc1, 0xcc, 0xdf, 0xed, 0xec, 0x37, 0xc5, 0xdc,
336 0x0b, 0xc9, 0x85, 0x46, 0x26, 0xa7, 0x51, 0xc8, 0xdd, 0xe6, 0x47, 0xfc, 0x37, 0xd6, 0x73, 0x6f,
337 0x91, 0x3d, 0xef, 0xd8, 0xa4, 0xa5, 0x08, 0x32, 0x8c, 0xae, 0x8f, 0x57, 0xf7, 0x99, 0x48, 0xef,
338 0x81, 0x44, 0xac, 0x80, 0x42, 0x57, 0x9f, 0x64, 0x77, 0x40, 0x2a, 0xec, 0x03, 0x21, 0x79, 0x01,
339 0x0b, 0x87, 0xc3, 0x9d, 0x22, 0xc9, 0xc0, 0x69, 0xe0, 0x34, 0xff, 0x73, 0xdd, 0x1e, 0x1b, 0x0c,
340 0xe0, 0x68, 0xf0, 0x8c, 0x7a, 0x4b, 0xcd, 0x1d, 0x3f, 0x38, 0x2d, 0xe8, 0x9b, 0x91, 0xa6, 0xfe,
341 0xa8, 0x8b, 0x45, 0x1c, 0xdf, 0xaf, 0x49, 0x34, 0x48, 0x17, 0x02, 0x28, 0xdb, 0xe0, 0x6e, 0x74,
342 0x34, 0xea, 0xac, 0x6b, 0x00, 0x45, 0x89, 0xa9, 0xb5, 0x63, 0xbd, 0x2f, 0xe0, 0x58, 0x2e, 0xd3,
343 0xc2, 0x74, 0xa2, 0x37, 0x37, 0x62, 0xf6, 0x76, 0x1b, 0x3f, 0xfb, 0x98, 0x64, 0x13, 0xd6, 0x8c,
344 0xa0, 0x0c, 0xbc, 0x54, 0x00, 0xe0, 0xf8, 0x63, 0x17, 0x22, 0x44, 0x36, 0xe0, 0x28, 0xa0, 0x7d,
345 0x50, 0x9e, 0x50, 0x94, 0xea, 0xd7, 0x62, 0xab, 0x6d, 0x7a, 0x19, 0xa4, 0xa2, 0x74, 0x79, 0x5d,
346 0x15, 0x85, 0x21, 0xfe, 0x9a, 0x35, 0x76, 0x40, 0x78, 0x01, 0xe3, 0x46, 0x2f, 0x6f, 0x2d, 0x0a,
347 0x1d, 0xac, 0x2e, 0x23, 0xec, 0xb8, 0x48, 0x74, 0xbc, 0xee, 0x29, 0x72, 0xb6, 0xe7, 0x52, 0x8c,
348 0xd4, 0x1a, 0x00, 0x34, 0x75, 0x1c, 0x4b, 0x83, 0x50, 0xbb, 0x57, 0x21, 0x9b, 0xd8, 0xb4, 0x75,
349 0xf3, 0x98, 0x8a, 0x9b, 0x45, 0xa8, 0x61, 0x50, 0x10, 0xb4, 0xec, 0x91, 0x2e, 0xe7, 0xf2, 0xb8,
350 0xb9, 0x62, 0x70, 0xc2, 0x93, 0xe7, 0xd9, 0xf1, 0x02, 0x27, 0xd7, 0xec, 0xde, 0x5b, 0x42, 0xa1,
351 0x26, 0x37, 0x41, 0x32, 0x65, 0x11, 0x63, 0x38, 0xbb, 0x6f, 0x23, 0x7a, 0xa0, 0xb7, 0x24, 0xeb,
352 0xa8, 0x38, 0x8b, 0xa7, 0x73, 0xe2, 0xc8, 0x30, 0x56, 0x73, 0x6f, 0x17, 0x6e, 0x1a, 0xe5, 0x32,
353 0xff, 0xd6, 0xa2, 0x08, 0x7b, 0x6a, 0x23, 0x33, 0x9f, 0x10, 0x05, 0x71, 0xdd, 0x02, 0x03, 0x01,
354 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
355 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, 0x99, 0xc4,
356 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
357 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
358 0x16, 0x80, 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59,
359 0x99, 0xc4, 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
360 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
361 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x71, 0x10, 0x3c, 0x89, 0xd5,
362 0xc0, 0x00, 0xdc, 0x36, 0x1d, 0x93, 0xaa, 0xab, 0x4a, 0xb6, 0xfa, 0xa8, 0x5b, 0x89, 0x1c, 0xb3,
363 0x4a, 0x04, 0x2e, 0xb3, 0x25, 0x0f, 0x12, 0x07, 0x29, 0x70, 0x3d, 0x34, 0xd1, 0xdd, 0x7e, 0x30,
364 0xfd, 0xf5, 0xfa, 0x94, 0xf4, 0xcb, 0xdb, 0xac, 0x1b, 0xed, 0xe5, 0x11, 0x4a, 0xc8, 0xab, 0x26,
365 0xe2, 0x41, 0xcb, 0xa5, 0x74, 0x4b, 0xe1, 0xd2, 0xf3, 0x83, 0x1c, 0x7a, 0xcb, 0x29, 0xd9, 0xd2,
366 0xa6, 0x9d, 0x08, 0x95, 0x73, 0x63, 0xe2, 0x9c, 0xeb, 0xa5, 0x82, 0x8b, 0x6c, 0xf4, 0x64, 0x98,
367 0x03, 0x53, 0x91, 0x35, 0x04, 0x89, 0x25, 0xa0, 0x1f, 0xdc, 0x42, 0xf7, 0x59, 0x44, 0x63, 0x75,
368 0xe6, 0x49, 0x10, 0x66, 0x0f, 0x08, 0x07, 0x39, 0xc4, 0x3e, 0x1f, 0xba, 0x30, 0x42, 0xf8, 0x7a,
369 0xc8, 0xbe, 0x6f, 0xdb, 0xec, 0x16, 0xb2, 0x76, 0x84, 0x2c, 0x6e, 0x20, 0xd1, 0xbd, 0xd5, 0x90,
370 0x22, 0x0a, 0x90, 0x5c, 0x70, 0x47, 0xc9, 0x2d, 0xe3, 0x77, 0x74, 0xfd, 0xbb, 0x85, 0x1a, 0xd8,
371 0x5c, 0x38, 0x94, 0x4c, 0x83, 0x28, 0x23, 0xa5, 0x4f, 0x55, 0x5f, 0xe3, 0x42, 0x80, 0x10, 0xd4,
372 0xa5, 0x8d, 0xcf, 0x8b, 0x53, 0x69, 0x6d, 0xc5, 0x37, 0xd2, 0xfa, 0xbb, 0xc0, 0x5a, 0xab, 0x6f,
373 0x71, 0x37, 0x92, 0xd4, 0x90, 0xef, 0x5d, 0xf1, 0xc3, 0xb8, 0x64, 0x08, 0xd3, 0xba, 0x36, 0x69,
374 0x2b, 0x00, 0xed, 0xad, 0x36, 0x21, 0x38, 0xdf, 0x4a, 0xc6, 0x44, 0xc4, 0x6b, 0xd8, 0xb0, 0x7f,
375 0x67, 0x05, 0xaa, 0x6f, 0x9e, 0x8a, 0xf1, 0x81, 0x95, 0x99, 0xb9, 0x56, 0xf4, 0x73, 0xa7, 0xb4,
376 0x19, 0xb9, 0x4b, 0xb8, 0x1d, 0x10, 0xa5, 0x88, 0x7c, 0x39, 0xa3, 0x85, 0xe7, 0xba, 0x65, 0x86,
377 0xca, 0xf7, 0x0e, 0xe0, 0x0d, 0x73, 0x3f, 0xea, 0x98, 0x88, 0x58, 0x73, 0xfa, 0x68, 0x5b, 0xaa,
378 0x8c, 0xfd, 0x3e, 0x22, 0x3e, 0x92, 0xc7, 0xe2, 0x77, 0x14, 0x81, 0xe6, 0xd9, 0xdc, 0xc1, 0xe9,
379 0xc0, 0x06, 0x57, 0xb4, 0xca, 0xb6, 0x14, 0x15, 0x16, 0x80, 0x7e, 0xc5, 0x11, 0xa4, 0x05, 0x66,
380 0xad, 0x1d, 0xa3, 0xb6, 0xab, 0x2a, 0xbe, 0xd0, 0x52, 0x4e, 0x9e, 0x84, 0x61, 0x6b, 0xf4, 0x34,
381 0x23, 0x94, 0x24, 0xc6, 0xc8, 0xb0, 0x94, 0x22, 0x4c, 0x3b, 0xac, 0x85, 0xe3, 0xd4, 0xf7, 0x38,
382 0xe5, 0x9a, 0x76, 0xb3, 0x1b, 0xf0, 0xbc, 0x78, 0xc6, 0x6f, 0x11, 0xb3, 0x1a, 0x5c, 0x4f, 0x07,
383 0x52, 0x06, 0x92, 0x7a, 0x25, 0x86, 0x91, 0x71, 0x8a, 0xf4, 0x03, 0xce, 0x19, 0x0d, 0xfc, 0xde,
384 0x8f, 0xc9, 0x4e, 0x84, 0xf1, 0x17, 0x18, 0x6f, 0x37, 0x56, 0xb9, 0x76, 0x7e, 0x8f, 0xca, 0xde,
385 0xd4, 0x1b, 0x2d, 0x8d, 0xcf, 0x12, 0x9f, 0xf9, 0xb9, 0x8b, 0x82, 0x8f, 0x4d, 0xb7, 0x63, 0x26,
386 0x8d, 0xda, 0x35, 0x94, 0x18, 0xf9, 0x55, 0xca, 0x39, 0x09, 0xe9, 0x62, 0xe1, 0x00, 0xd8, 0x67,
387 0xed, 0x5e, 0x84, 0xc2, 0xe5, 0x8e, 0x46, 0x57, 0xa4, 0xa7, 0x17, 0x70, 0xcf, 0x6d, 0xdf, 0x43,
388 0x64, 0x2b, 0x36, 0xe6, 0xf3, 0xc1, 0x4c, 0x7a, 0x7e, 0x9e, 0x47, 0xc4, 0x14, 0x82, 0xbe, 0x94,
389 0x73, 0x54, 0xd0, 0x2c, 0xc2, 0x31, 0xc6, 0xd5, 0xc3, 0xd7, 0xa9, 0xef, 0x11, 0x24, 0x2f, 0xd0,
390 0x5b, 0xb8, 0x6a, 0x8e, 0x3c, 0xb7, 0x4b, 0x00, 0x9b, 0xc1, 0xca, 0x00, 0x6f, 0xd4, 0x73, 0x93,
391 0x2e, 0x39, 0x37, 0x2a, 0x73, 0x44, 0x9b, 0x1b, 0x05, 0x1a, 0x7c, 0x2f, 0xc9, 0x2b, 0x37, 0xf3,
392 0xcd, 0x8c, 0x4e, 0xc2, 0x7a, 0x6e, 0xd9, 0xd4, 0xf1, 0x8d, 0x6d, 0x07, 0x4b, 0xb5, 0x09, 0xb9,
393 0x48, 0x55, 0xac, 0xc6, 0x7e, 0xbc, 0xc6, 0x76, 0xeb, 0x5f, 0x0f
397 static NSDictionary* VerifyMessage(CFDataRef message, SecPolicyRef policy, CFDataRef cert_data)
399 NSDictionary* result = nil;
401 SecTrustRef trustRef = NULL;
402 CFDataRef payload = NULL;
403 CFArrayRef anchors = NULL;
404 OSStatus status = noErr;
405 SecCertificateRef aCertRef = NULL;
406 SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure;
408 if (NULL == message || NULL == policy || NULL == cert_data)
413 status = SecCMSVerifyCopyDataAndAttributes(message, NULL, policy, &trustRef, &payload, NULL);
414 if (noErr != status || NULL == trustRef || NULL == payload)
419 aCertRef = SecCertificateCreateWithData(NULL, cert_data);
420 if (NULL == aCertRef)
425 anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&aCertRef, 1, &kCFTypeArrayCallBacks);
431 status = SecTrustSetAnchorCertificates(trustRef, anchors);
437 status = SecTrustEvaluate(trustRef, &trust_result);
444 if (trust_result == kSecTrustResultUnspecified)
446 // Life is good and we got back the expected result.
448 NSData* property_list_data = CFBridgingRelease(payload);
450 NSPropertyListFormat format;
451 NSError* error = nil;
452 result = [NSPropertyListSerialization propertyListWithData:property_list_data options:0 format:&format error:&error];
460 CFReleaseSafe(aCertRef)
461 CFReleaseSafe(anchors);
465 /* ==========================================================================
466 Private Methods for the OTAServiceApp class
467 ========================================================================== */
468 @interface OTAServiceApp (PrivateMethods)
469 - (void)processAssets:(NSArray*)assets;
470 - (BOOL)checkAssetVersions:(NSString *)assetDir;
471 - (BOOL)validateAsset:(NSString *)assetDir;
472 - (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names;
473 - (NSDictionary *)decodeManifest:(NSData *)manifest_file_data;
474 - (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash;
475 - (BOOL)installAssetFiles:(NSString *)assetDir;
476 - (NSString*)getCurrentAssetDirectory;
480 @implementation OTAServiceApp
482 @synthesize file_list = _file_list;
483 @synthesize manifest_file_name = _manifest_file_name;
484 @synthesize asset_version_file_name = _asset_version_file_name;
485 @synthesize current_asset_version = _current_asset_version;
486 @synthesize next_asset_version = _next_asset_version;
487 @synthesize fileManager = _fileManager;
488 @synthesize current_asset_directory = _current_asset_directory;
489 @synthesize assets_directory = _assets_directory;
491 /* --------------------------------------------------------------------------
492 OTAServiceApp init:withArguments:
494 Initialize a new instance of the OTAServiceApp class
495 -------------------------------------------------------------------------- */
496 - (id)init:(int)argc withArguments:(const char**)argv
498 if ((self = [super init]))
500 _fileManager = [NSFileManager defaultManager];
502 _manifest_file_name = (NSString *)kManifestFileName;
503 _asset_version_file_name = (NSString *)kAssetVersionFileName;
504 _file_list = [NSArray arrayWithObjects:kBlockKeyFileName, kGrayListedKeysFileName,
505 kEVRootsFileName, kCertsIndexFileName, kCertsTableFileName,
506 kManifestFileName, kAssetVersionFileName, kAppleESCertificatesName,
507 kAllowListFileName, kCTLogsFileName, nil];
509 _current_asset_version = nil;
510 _next_asset_version = nil;
511 _assets_directory = nil;
512 _current_asset_directory = [self getCurrentAssetDirectory];
514 /* Default interval is one hour */
515 _asset_query_retry_interval = 60.0 * 60;
519 while ((ch = getopt(argc, (char * const *)argv, "d:v")) != -1 )
527 CFTimeInterval interval = strtod(optarg, &endptr);
528 if ((interval == 0 && endptr == optarg) || errno == ERANGE) {
529 syslog(LOG_ERR, "invalid argument '%s', ignoring", optarg);
531 syslog(LOG_NOTICE, "Setting query retry interval to %f seconds", interval);
532 _asset_query_retry_interval = (CFTimeInterval)interval;
537 syslog(LOG_NOTICE, "Enabling verbose logging");
547 if (stat([kBaseAssetDirectoryPath UTF8String], &info))
549 OTAPKI_LOG("OTAServiceApp.init:withArguments: stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
551 if (mkdir([kBaseAssetDirectoryPath UTF8String], kAssetDirectoryPermission))
553 OTAPKI_LOG("OTAServiceApp.init:withArguments: mkdir of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
557 if (stat([kBaseAssetDirectoryPath UTF8String], &info))
559 OTAPKI_LOG("OTAServiceApp.init:withArguments: second stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
564 stat([kBaseAssetDirectoryPath UTF8String], &info);
575 #if !TARGET_IPHONE_SIMULATOR
577 - (void)registerBackgroundTaskAgentJobWithDelay:(CFTimeInterval)delay
580 * ELEs are very important, so allow asset queries on any network type and
581 * construct the job so that it will fire as soon as possible, unless we are
582 * scheduling a retry after a failure.
584 xpc_object_t job = xpc_dictionary_create(NULL, NULL, 0);
587 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowStartTime, CFAbsoluteTimeGetCurrent() + delay);
589 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowEndTime, CFAbsoluteTimeGetCurrent() + BACKGROUND_TASK_AGENT_JOB_WINDOW_MAX_TIME_FROM_NOW_SEC);
590 xpc_dictionary_set_bool(job, kBackgroundTaskAgentNetworkRequired, true);
591 xpc_dictionary_set_bool(job, kBackgroundTaskAgentCellularAllowed, true);
592 xpc_dictionary_set_bool(job, kBackgroundTaskAgentAllowedDuringRoaming, true);
593 xpc_dictionary_set_bool(job, kBackgroundTaskAgentPowerOptLevel, kBackgroundTaskAgentPowerDontCare);
597 char *desc = xpc_copy_description(job);
598 syslog(LOG_NOTICE, "Adding BTA job %s", desc);
601 #pragma GCC diagnostic push
602 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
603 BackgroundTaskAgentAddJob(kOTAPKIAssetToolBTAJob, job);
604 #pragma GCC diagnostic pop
609 /* --------------------------------------------------------------------------
610 OTAServiceApp checkInWithActivity
612 Check in with the XPC activity configured in OTAPKIAssetTool's launchd
613 plist. This activity will launch OTAPKIAssetTool every three days (with
614 some leeway decided by the system). At that time, we schedule a
615 BackgroundTaskAgent job to be notified immediately when the network is
616 available so we can perform an asset query.
617 -------------------------------------------------------------------------- */
618 - (void)checkInWithActivity
620 #if !TARGET_IPHONE_SIMULATOR
621 #pragma GCC diagnostic push
622 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
623 BackgroundTaskAgentInit("com.apple.OTAPKIAssetTool", dispatch_get_main_queue(), ^(const char *job_name, xpc_object_t job)
626 * We're doing real work at this point, so open a transaction so
627 * that the system (hopefully) won't kill us while we're busy
629 xpc_transaction_begin();
633 syslog(LOG_NOTICE, "BackgroundTaskAgent job %s fired", job_name);
636 int64_t job_status = xpc_dictionary_get_int64(job, kBackgroundTaskAgentJobStatus);
637 if (job_status == kBackgroundTaskAgentJobRequestError)
639 syslog(LOG_ERR, "Failed to create BTA job -- malformed job?");
641 else if (job_status == kBackgroundTaskAgentJobSatisfied)
645 syslog(LOG_NOTICE, "BTA job %s is satisfied -- performing asset query", job_name);
647 bool shouldReschedule = false;
648 if ([self run:&shouldReschedule] || !shouldReschedule)
652 syslog(LOG_NOTICE, "Unscheduling BTA job");
654 BackgroundTaskAgentRemoveJob(kOTAPKIAssetToolBTAJob);
658 syslog(LOG_NOTICE, "Asset query failed due to network error. Re-scheduling BTA job for another attempt in %f seconds.", _asset_query_retry_interval);
659 [self registerBackgroundTaskAgentJobWithDelay:_asset_query_retry_interval];
662 else if (job_status == kBackgroundTaskAgentJobUnsatisfied)
665 * We will receive this if the job expires before we get to do our
666 * work. We still want to check for new assets as soon as possible,
667 * so reschedule the job.
669 if (xpc_dictionary_get_bool(job, kBackgroundTaskAgentJobExpired))
671 [self registerBackgroundTaskAgentJobWithDelay:0];
675 xpc_transaction_end();
677 #pragma GCC diagnostic pop
680 xpc_activity_register(kOTAPKIAssetToolActivity, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity)
682 xpc_activity_state_t state = xpc_activity_get_state(activity);
686 xpc_object_t criteria = xpc_activity_copy_criteria(activity);
688 if (criteria != NULL)
690 char *desc = xpc_copy_description(criteria);
691 syslog(LOG_NOTICE, "Criteria for XPC activity %s: %s", kOTAPKIAssetToolActivity, desc);
696 syslog(LOG_NOTICE, "No critera for XPC activity %s", kOTAPKIAssetToolActivity);
700 if (state == XPC_ACTIVITY_STATE_CHECK_IN)
703 * The activity is already configured in the launchd plist, so there
704 * is nothing to do here
708 syslog(LOG_NOTICE, "Activity %s in check in state", kOTAPKIAssetToolActivity);
711 else if (state == XPC_ACTIVITY_STATE_RUN)
713 #if !TARGET_IPHONE_SIMULATOR
714 #pragma GCC diagnostic push
715 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
716 xpc_object_t job = BackgroundTaskAgentCopyJob(kOTAPKIAssetToolBTAJob);
717 #pragma GCC diagnostic pop
720 syslog(LOG_NOTICE, "Activity %s in run state. Scheduling BTA job for earliest network availability.", kOTAPKIAssetToolActivity);
721 [self registerBackgroundTaskAgentJobWithDelay:0];
725 syslog(LOG_NOTICE, "Already have a BTA job registered. Ignoring activity.");
729 * BackgroundTaskAgent doesn't exist on the iOS simulator, so we
730 * just directly try to find and download new assets.
732 xpc_transaction_begin();
733 bool shouldReschedule = false;
734 if (![self run:&shouldReschedule]) {
735 syslog(LOG_NOTICE, "Asset query failed%s.", shouldReschedule ? " due to network issue" : "");
737 xpc_transaction_end();
743 /* --------------------------------------------------------------------------
746 Run this program and leave. This program will currently run every 3 days,
747 with some leeway based on network availability. That will provide the
748 longest time from publisihing a change in the PKI trust setting asset and
749 having that asset be consumed by a device.
751 The program simnply ask the mobile asset daemon if there are any assets
752 to be processed with the PKITrustDataAssetType. If not this program
753 will just complete and will be re-run in 3 days. If there is an asset to
754 process then the asset will be process and then the program will complete.
756 Returns false if the operation failed. On return, shouldReschedule is set
757 to true if the operation failed due to a network error and the caller
758 should reschedule this operation at a more opportune time.
759 -------------------------------------------------------------------------- */
760 - (bool)run:(bool *)shouldReschedule
764 if (shouldReschedule != NULL) {
765 *shouldReschedule = false;
768 syslog(LOG_NOTICE, "OTAPKIAssetTool running");
769 if (![[MCProfileConnection sharedConnection] isOTAPKIUpdatesAllowed])
771 syslog(LOG_NOTICE, "OTAPKIAssetTool: OTAPKI updates are not allowed.");
775 ASAssetQuery *assetQuery = [[ASAssetQuery alloc] initWithAssetType:(NSString *)kPKITrustDataAssetType];
776 if (assetQuery == nil)
778 syslog(LOG_NOTICE, "OTAPKIAssetTool: Could not create the asset query.");
782 // Get the asset synchronously
783 NSError *error = nil;
784 NSArray *foundAssets = [assetQuery runQueryAndReturnError:&error];
785 if (nil != foundAssets)
787 [self processAssets:foundAssets];
791 syslog(LOG_NOTICE, "OTAPKIAssetTool: No assets returned from query: %s", [[error description] UTF8String]);
793 NSArray *networkErrorCodes = @[ @(ASErrorNetwork), @(ASErrorNetworkNoConnection), @(ASErrorNetworkTimedOut), @(ASErrorNetworkUnexpectedResponse) ];
794 if ([[error domain] isEqualToString:ASErrorDomain] && [networkErrorCodes containsObject:@([error code])])
796 syslog(LOG_NOTICE, "OTAPKIAssetTool: Query failed due to network error.");
797 if (shouldReschedule != NULL) {
798 *shouldReschedule = true;
808 /* --------------------------------------------------------------------------
809 OTAServiceApp processAssets:
811 If when run is called asset(s) are found they will be processed here.
812 -------------------------------------------------------------------------- */
813 - (void)processAssets:(NSArray*)assets
820 NSError* error = nil;
821 ASAsset* asset = nil;
822 int asset_version = 0;
824 for (asset in assets)
826 NSDictionary* asset_attributes = asset.attributes;
828 NSNumber* contentVersion = [asset_attributes objectForKey:@"ContentVersion"];
829 OTAPKI_LOG("In processAssets: about to check the ContentVersion\n");
830 if (nil != contentVersion)
832 asset_version = [contentVersion intValue];
833 int current_asset_version_number = (nil != _current_asset_version) ? [_current_asset_version intValue] : 0;
835 if (asset_version <= current_asset_version_number)
837 syslog(LOG_NOTICE, "OTAPKIAssetTool: content version %d is too small. Current asset version id %d",
838 asset_version, current_asset_version_number);
840 OTAPKI_LOG("In processAssets: content version is too small: current asset version is %d\nContent version is %d\n",
841 current_asset_version_number, asset_version);
849 syslog(LOG_NOTICE, "OTAPKIAssetTool: no suitable asset found");
854 // Check to see if the asset needs to be downloaded
855 if (asset.state == ASAssetStateNotPresent)
857 __block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
859 [asset setProgressHandler:^(NSDictionary *state, NSError *anError)
863 // An error occured. Signal the semaphore to bail
864 dispatch_semaphore_signal(sem);
866 else if ([[state objectForKey:@"Operation"] isEqualToString:(NSString *) @"OperationCompleted"])
868 // The download is complete. Signal the semaphore
869 dispatch_semaphore_signal(sem);
873 NSNumber* yesValue = [NSNumber numberWithBool:YES];
874 const id keys[] = {ASDownloadOptionAllow3G, ASDownloadOptionAllow4G, ASDownloadOptionPriority, ASDownloadOptionAllowBatteryPower};
875 const id values[] = {yesValue, yesValue, ASDownloadPriorityHigh, yesValue};
877 NSDictionary* options = [NSDictionary dictionaryWithObjects:values forKeys:keys count:(sizeof (keys) / sizeof(keys[0]))];
879 [asset beginDownloadWithOptions:options];
880 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
883 // Check to see if the asset is now available for processing
884 if ([asset state] == ASAssetStateInstalled)
886 // Get the asset data directory
887 NSString* assetDir = [[[asset localURL] URLByAppendingPathComponent:@"PKITrustData"] path];
890 // validate the asset.
891 OTAPKI_LOG("In processAssets: about to validateAsset\n");
892 if ([self validateAsset:assetDir])
894 OTAPKI_LOG("In processAssets: asset validated installing\n");
895 // The asset is valid so install the files
896 [self installAssetFiles:assetDir];
898 // Signal securityd to idle-exit at it's next opportunity
899 OTAPKI_LOG("In processAssets: notifying securityd\n");
901 (void)SecTrustOTAPKIGetUpdatedAsset(&didUpdate);
902 syslog(LOG_NOTICE, "OTAPKIAssetTool: installed new asset %d", asset_version);
903 _current_asset_version = contentVersion;
907 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset %d did not validate", asset_version);
910 // regaurdless if the asset is valid. Now that it is
911 // installed, it needs to be purged to ensure that
912 // we can retrieve a new updated asset.
913 [asset purgeAndReturnError:&error];
917 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset directory %s not found", [assetDir UTF8String]);
923 /* --------------------------------------------------------------------------
924 OTAServiceApp checkAssetVersions:
926 If when run is called asset(s) are found they will be processed here.
927 -------------------------------------------------------------------------- */
928 - (BOOL)checkAssetVersions:(NSString *)assetDir
932 OTAPKI_LOG("Entering checkAssetVersions\n");
934 if (nil == assetDir || nil == self.current_asset_version)
936 OTAPKI_LOG("checkAssetVersions: parameter error\n");
940 // first get the new version number from the downloaded asset
941 NSString* next_asset_version_path = [assetDir stringByAppendingPathComponent:self.asset_version_file_name];
942 if (![self.fileManager fileExistsAtPath:next_asset_version_path])
944 // The asset is missing the AssertVersion.plist
945 // This is an invalid asset
946 OTAPKI_LOG("checkAssetVersions: could not file asseet version file %s\n", [self.asset_version_file_name UTF8String]);
950 NSError* error = nil;
951 NSInputStream* input_stream = [NSInputStream inputStreamWithFileAtPath:next_asset_version_path];
953 NSDictionary* asset_dict = [NSPropertyListSerialization propertyListWithStream:input_stream options:0 format:nil error:&error];
954 [input_stream close];
958 OTAPKI_LOG("checkAssetVersions: error reading asset version file: %s\n", [[error localizedDescription] UTF8String]);
962 _next_asset_version = [asset_dict objectForKey:kVersionNumberKey];
963 if (nil == _next_asset_version)
965 OTAPKI_LOG("asset_dict did not have a entry with a key of kVersionNumberKey\n");
969 // Check the current asset version against the new asset version. The new asset version MUST be larger than the
970 // current asset version
971 NSInteger current_asset_version_value = [self.current_asset_version integerValue];
972 NSInteger next_asset_version_value = [self.next_asset_version integerValue];
974 if (next_asset_version_value <= current_asset_version_value)
976 OTAPKI_LOG("heckAssetVersions: assert version too small. current_asset_version_value = %d next_asset_version_value = %d\n",
977 current_asset_version_value, next_asset_version_value);
985 /* --------------------------------------------------------------------------
986 OTAServiceApp validateAsset:
988 Decode the manifest and verify the file hashes
989 -------------------------------------------------------------------------- */
990 - (BOOL)validateAsset:(NSString *)assetDir
994 OTAPKI_LOG("Enterning validateAsset\n");
996 if (![self validateDirectory:assetDir withFiles:self.file_list])
998 OTAPKI_LOG("validateAsset param\n");
1002 NSString* manifest_file_path = [assetDir stringByAppendingPathComponent:self.manifest_file_name];
1003 NSError* error = nil;
1004 NSData* manifest_file_data = [NSData dataWithContentsOfFile:manifest_file_path options:0 error:&error];
1007 OTAPKI_LOG("validateAsset: could not read manifest file. error = %s\n", [[error localizedDescription] UTF8String]);
1011 NSDictionary* manifest_data = [self decodeManifest:manifest_file_data];
1012 if (nil == manifest_data)
1014 OTAPKI_LOG("validateAsset: decodeManifest failed!\n");
1018 NSString* full_file_path = nil;
1020 for (NSString* file_name in self.file_list)
1022 if ([file_name isEqualToString:self.manifest_file_name])
1027 hash = [manifest_data objectForKey:file_name];
1030 OTAPKI_LOG("validateAsset: could not get hash for file %s\n", [file_name UTF8String]);
1034 full_file_path = [assetDir stringByAppendingPathComponent:file_name];
1035 if (![self checkFileHash:full_file_path hash:hash])
1037 OTAPKI_LOG("validateAsset: hash for file %s does not match\n", [file_name UTF8String]);
1042 result = [self checkAssetVersions:assetDir];
1046 /* --------------------------------------------------------------------------
1047 OTAServiceApp validateDirectory:withFiles:
1049 Ensure that a given directory has the files listed in the files_names
1051 -------------------------------------------------------------------------- */
1052 - (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names
1055 OTAPKI_LOG("Enterning validateDirectory\n");
1057 if (nil == assetDir || nil == file_names)
1059 OTAPKI_LOG("validateDirectory param error\n");
1062 NSError* error = nil;
1063 NSArray* dir_items = [self.fileManager contentsOfDirectoryAtPath:assetDir error:&error];
1066 OTAPKI_LOG("validateDirectory: Error calling contentsOfDirectoryAtPath: error = %s\n", [[error localizedDescription] UTF8String]);
1070 for (NSString* file_name in file_names)
1072 if (![dir_items containsObject:file_name])
1074 OTAPKI_LOG("validateDirectory: missing file %s\n", [file_name UTF8String]);
1082 /* --------------------------------------------------------------------------
1083 OTAServiceApp decodeManifest:
1085 Ensure that the asset manifest blob has it CMS signature verified
1086 -------------------------------------------------------------------------- */
1087 - (NSDictionary *)decodeManifest:(NSData *)manifest_file_data
1089 NSDictionary* result = nil;
1090 CFDataRef cert_data = NULL;
1091 CFDataRef message = NULL;
1092 SecPolicyRef policy = NULL;
1093 CFBooleanRef mgResult = NULL;
1095 OTAPKI_LOG("Enterning decodeManifest\n");
1097 if (nil == manifest_file_data)
1099 OTAPKI_LOG("decodeManifest: parameter error\n");
1103 message = CFBridgingRetain(manifest_file_data);
1105 policy = SecPolicyCreateOTAPKISigner();
1108 OTAPKI_LOG("decodeManifest: could not get the SecPolicyCreateOTAPKISigner policyRef\n");
1112 cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert));
1113 if (NULL == cert_data)
1115 OTAPKI_LOG("decodeManifest: could not kApplePKISettingsRootCACert data\n");
1119 result = VerifyMessage(message, policy, cert_data);
1123 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner success!\n");
1127 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner failed! Checking to see if this is an internal build\n");
1129 // The first attempt did not work so check to see if this is running on an internal build.
1130 if (!MGIsQuestionValid(kMGQAppleInternalInstallCapability))
1132 OTAPKI_LOG("decodeManifest: kMGQAppleInternalInstallCapability had an error\n");
1136 mgResult = MGCopyAnswer(kMGQAppleInternalInstallCapability, NULL);
1138 if (NULL == mgResult || !CFEqual(mgResult, kCFBooleanTrue))
1140 OTAPKI_LOG("decodeManifest: Not an internal build");
1144 OTAPKI_LOG("decodeManifest: This is an internal build\n");
1146 CFReleaseNull(policy);
1147 CFReleaseNull(cert_data);
1149 policy = SecPolicyCreateTestOTAPKISigner();
1152 OTAPKI_LOG("decodeManifest: could not SecPolicyCreateTestOTAPKISigner policyRef\n");
1156 cert_data = CFDataCreate(kCFAllocatorDefault, kAppleTestPKISettingsRootCACert, sizeof(kAppleTestPKISettingsRootCACert));
1157 if (NULL == cert_data)
1159 OTAPKI_LOG("decodeManifest: could not kAppleTestPKISettingsRootCACert data\n");
1163 result = VerifyMessage(message, policy, cert_data);
1167 CFReleaseSafe(mgResult);
1168 CFReleaseSafe(message);
1169 CFReleaseSafe(policy);
1170 CFReleaseSafe(cert_data);
1174 /* --------------------------------------------------------------------------
1175 OTAServiceApp checkFileHash:hash:
1177 Ensure that the given asset file's hash is the same as in the manifest
1178 -------------------------------------------------------------------------- */
1179 - (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash
1182 if (nil == file_path || nil == hash)
1187 NSError* error = nil;
1188 NSData* file_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error];
1194 UInt8 buffer[CC_SHA256_DIGEST_LENGTH];
1195 memset(buffer, 0, CC_SHA256_DIGEST_LENGTH);
1196 CC_SHA256([file_data bytes], (CC_LONG)[file_data length], buffer);
1197 NSData* file_hash_data = [NSData dataWithBytesNoCopy:buffer length:CC_SHA256_DIGEST_LENGTH freeWhenDone:NO];
1199 result = [hash isEqualToData:file_hash_data];
1204 /* --------------------------------------------------------------------------
1205 OTAServiceApp installAssetFiles:
1207 Copy over the files into the /var/Keychains/Assets directory.
1208 -------------------------------------------------------------------------- */
1209 - (BOOL)installAssetFiles:(NSString *)assetDir
1213 OTAPKI_LOG("Entering installAssetFiles\n");
1215 if (nil == assetDir)
1217 OTAPKI_LOG("installAssetFiles: parameter error\n");
1221 if (nil == self.assets_directory)
1223 OTAPKI_LOG("installAssetFiles: no assets directory\n");
1227 // Create a temp directory to hold the new asset files.
1228 NSString* tempDir = [self.assets_directory stringByAppendingPathComponent:@"TempAssetDir"];
1229 NSError* error = nil;
1232 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1233 id keys[] = {NSFilePosixPermissions};
1235 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1];
1237 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]);
1238 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]);
1239 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid];
1240 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid];
1242 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1243 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions};
1245 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
1249 if (![self.fileManager createDirectoryAtPath:tempDir withIntermediateDirectories:YES
1250 attributes:attributes error:&error])
1252 OTAPKI_LOG("installAssetFiles: could not create directory %s\n", [tempDir UTF8String]);
1256 #ifndef NEW_LOCATION
1257 // Copy all of the asset files to the newly created directory
1258 for (NSString* file_name in self.file_list)
1260 NSString* download_assert_path = [assetDir stringByAppendingPathComponent:file_name];
1261 NSString* asset_path = [tempDir stringByAppendingPathComponent:file_name];
1262 if ([self.fileManager copyItemAtPath:download_assert_path toPath:asset_path error:&error])
1264 chown([asset_path UTF8String], self.uid, self.gid);
1268 [self.fileManager removeItemAtPath:tempDir error:nil];
1272 #endif // !NEW_LOCATION
1275 // Now that all of the files have been copied to the temp directory make a single call
1276 // to rename (move) the temp directory to be the correct version directory. This rename
1277 // allow for reducing a race conditions between this asset code and securityd.
1278 NSInteger new_version_value = [self.next_asset_version integerValue];
1279 NSString* new_version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)new_version_value];
1280 NSString* new_version_dir_path = [self.assets_directory stringByAppendingPathComponent:new_version_dir_name];
1281 if (![self.fileManager moveItemAtPath:tempDir toPath:new_version_dir_path error:&error])
1283 OTAPKI_LOG("installAssetFiles: could not move path %s\n", [tempDir UTF8String]);
1284 [self.fileManager removeItemAtPath:tempDir error:nil];
1292 /* --------------------------------------------------------------------------
1293 OTAServiceApp getCurrentAssetDirectory:
1295 Looks through the /var/Keychains/Assets directory to find latest asset
1296 version directory. If no assets have been downloaded then nil is returned
1297 and the current asset version is set to 0
1298 -------------------------------------------------------------------------- */
1299 - (NSString*)getCurrentAssetDirectory
1301 NSString* result = nil;
1304 OTAPKI_LOG("In getCurrentAssetDirectory\n");
1305 OTAPKI_LOG("getCurrentAssetDirectory: checking to see if %s exists\n", [kBaseAssetDirectoryPath UTF8String]);
1307 // Check to see if the base directory is there
1308 if (![self.fileManager fileExistsAtPath:(NSString *)kBaseAssetDirectoryPath isDirectory:&isDir] || !isDir)
1310 OTAPKI_LOG("getCurrentAssetDirectory: %s does not exists\n", [kBaseAssetDirectoryPath UTF8String]);
1311 // This might be fatal
1315 NSError* error = nil;
1316 NSInteger version_number = 0;
1317 NSInteger current_version_number = 0;
1319 OSStatus err = noErr;
1321 _assets_directory = [kBaseAssetDirectoryPath stringByAppendingPathComponent:(NSString *)kAssetDirectoryName];
1323 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]);
1325 if ([self.fileManager fileExistsAtPath:self.assets_directory isDirectory:&isDir] && isDir)
1327 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]);
1328 NSDirectoryEnumerator* dirEnum = [self.fileManager enumeratorAtPath:self.assets_directory];
1329 [dirEnum skipDescendents];
1331 for (NSString* file in dirEnum)
1333 if ([file hasPrefix:(NSString *)kVersionDirectoryNamePrefix])
1335 NSString* version_str = [file substringFromIndex:[kVersionDirectoryNamePrefix length]];
1336 NSInteger aVersion_number = [version_str integerValue];
1337 if (aVersion_number > version_number)
1339 version_number = aVersion_number;
1347 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1348 id keys[] = {NSFilePosixPermissions};
1350 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1];
1353 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]);
1354 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]);
1355 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid];
1356 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid];
1358 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1359 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions};
1360 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
1362 OTAPKI_LOG("getCurrentAssetDirectory: %s does NOT exists\n", [self.assets_directory UTF8String]);
1363 OTAPKI_LOG("getCurrentAssetDirectory: creating %s\n", [self.assets_directory UTF8String]);
1365 if (![self.fileManager createDirectoryAtPath:self.assets_directory withIntermediateDirectories:YES
1366 attributes:attributes error:&error])
1368 OTAPKI_LOG("getCurrentAssetDirectory: failed to create %s\n", [self.assets_directory UTF8String]);
1374 err = SecTrustGetOTAPKIAssetVersionNumber(&aVerNum);
1375 if (errSecSuccess == err && aVerNum > 0)
1377 current_version_number = aVerNum;
1380 if (version_number < current_version_number)
1382 OTAPKI_LOG("The largest OTA version number is smaller than the current version number. This means the system has a newer asset\n");
1383 version_number = current_version_number;
1387 OTAPKI_LOG("The largest OTA version number is equal to the current version number. The OTA asset is newer than the system asset\n");
1388 NSString* version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)version_number];
1389 result = [self.assets_directory stringByAppendingPathComponent:version_dir_name];
1392 OTAPKI_LOG("getCurrentAssetDirectory: setting version number to %d\n", version_number);
1393 _current_asset_version = [NSNumber numberWithInteger:version_number];