8 #import "OTAServiceApp.h"
10 #import <TargetConditionals.h>
11 #import <Security/Security.h>
12 #import <Security/SecPolicyPriv.h>
13 #import <Security/SecTrustPriv.h>
16 #import <MobileAsset/MobileAsset.h>
17 #import <Security/Security.h>
18 #import <Security/SecCMS.h>
19 #import <Security/SecCmsMessage.h>
20 #import <Security/SecCmsDecoder.h>
21 #import <Security/SecCmsContentInfo.h>
22 #import <Security/SecCmsSignedData.h>
23 #import <CommonCrypto/CommonDigest.h>
24 #import <CommonCrypto/CommonDigestSPI.h>
25 #import <CommonNumerics/CommonBaseXX.h>
26 #import <ManagedConfiguration/MCProfileConnection.h>
27 #import <MobileGestalt.h>
29 #if !TARGET_IPHONE_SIMULATOR
30 #import <BackgroundTaskAgent/BackgroundTaskAgent.h>
42 #define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } }
43 #define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } }
45 //#define VERBOSE_LOGGING 1
49 static void OTAPKI_LOG(const char* sz, ...)
54 FILE* fp = fopen("/tmp/OTAPKITool.log", "a");
65 #define OTAPKI_LOG(sz, ...)
69 //#define NEW_LOCATION 1
73 /* ==========================================================================
74 The following are a set of string constants used by this program.
76 kBaseAssetDirectoryPath - This is the full path on the device that
77 will contain the Assets directory. This
78 directory was chosen because it is owned
81 kkManifestFileName - The file name of the manifest file for the
84 kAllowListFileName - The file name of the asset file that contains
85 hashes of the allowed leaf certificates whose
86 trust store root has been removed
88 kAssetVersionFileName - The file name of the plist file in the asset
89 that contains the version number of this
90 OTA PKI trust asset. It is a plist that is a
91 dictionary with a single key with a single
92 key value pair that has the version number
93 of the asset. This is used to ensure against
96 kBlockKeyFileName - The file name of the asset file that contains
97 blocked keys. Any certificate with these keys
98 will be marked as not being trusted.
100 kGrayListedKeysFileName - The file name of the asset file that contains
101 gray listed keys. If a chain has any of these
102 keys, than the chain will still be approved but
103 an entry will be added to the details dictionary
104 noting that the key was gray listed
107 kEVRootsFileName - The file name of the asset file that contains
108 the list of EV OIDS and their corresponding
109 certificates. This file sets which certs will
110 be considered to be EV.
112 kCTLogsFileName - The file name of the asset file that contains
113 the list of Certificate Transparency logs and
116 kCertsIndexFileName - The file name of the asset file that contains
117 a hash table of offsets into the cert table
118 file. This is used to look up anchor certs.
120 kCertsTableFileName - The file name of the asset file that contains
121 all of the anchor certificates. The
122 kCertsIndexFileName file is used to find the
123 correct offset in this file to retrieve a
124 specific anchor certificate.
126 kVersionNumberKey - The dictionary key for the kAssetVersionFileName
127 file to get the version number
129 kVersionDirectoryNamePrefix -
130 The directory name prefix for all of the
133 kPKITrustDataAssetType - The asset identifier of the OTA PKI asset
136 ========================================================================== */
139 static const NSString* kBaseAssetDirectoryPath = @"/var/OTAPKI";
141 static const NSString* kBaseAssetDirectoryPath = @"/var/Keychains";
144 static const NSString* kManifestFileName = @"manifest.data";
145 static const NSString* kAllowListFileName = @"Allowed.plist";
146 static const NSString* kAssetVersionFileName = @"AssetVersion.plist";
147 static const NSString* kAppleESCertificatesName = @"AppleESCertificates.plist";
148 static const NSString* kBlockKeyFileName = @"Blocked.plist";
149 static const NSString* kGrayListedKeysFileName = @"GrayListedKeys.plist";
150 static const NSString* kEVRootsFileName = @"EVRoots.plist";
151 static const NSString* kCTLogsFileName = @"TrustedCTLogs.plist";
152 static const NSString* kCertsIndexFileName = @"certsIndex.data";
153 static const NSString* kCertsTableFileName = @"certsTable.data";
154 static const NSString* kVersionNumberKey = @"VersionNumber";
155 static const NSString* kAssetDirectoryName = @"Assets";
156 static const NSString* kAssetDirectoryUser = @"_securityd";
157 static const NSString* kAssetDirectoryGroup = @"wheel";
159 static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRWXG | S_IRWXO;
161 static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
163 static const NSString* kVersionDirectoryNamePrefix = @"Version_";
164 static const NSString* kPKITrustDataAssetType =@"com.apple.MobileAsset.PKITrustServices.PKITrustData";
166 const char *kOTAPKIAssetToolActivity = "com.apple.OTAPKIAssetTool.asset-check";
167 const char *kOTAPKIAssetToolBTAJob = "com.apple.BTA.OTAPKIAssetTool.asset-check";
169 static const UInt8 kApplePKISettingsRootCACert[] = {
170 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e,
171 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
172 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55,
173 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65,
174 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74,
175 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
176 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70,
177 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
178 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06,
179 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e,
180 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17,
181 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d,
182 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84,
183 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65,
184 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f,
185 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
186 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
187 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
188 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
189 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70,
190 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
191 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
192 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a,
193 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04,
194 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc,
195 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe,
196 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29,
197 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77,
198 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf,
199 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f,
200 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa,
201 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e,
202 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a,
203 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d,
204 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99,
205 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05,
206 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3,
207 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d,
208 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb,
209 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3,
210 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4,
211 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d,
212 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce,
213 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc,
214 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff,
215 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7,
216 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f,
217 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22,
218 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70,
219 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f,
220 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf,
221 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7,
222 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee,
223 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62,
224 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63,
225 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82,
226 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82,
227 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6,
228 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
229 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35,
230 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f,
231 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca,
232 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63,
233 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01,
234 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00,
235 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00,
236 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00,
237 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00,
238 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00,
239 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00,
240 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00,
241 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00,
242 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00,
243 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00,
244 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00,
245 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00,
246 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00,
247 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00,
248 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00,
249 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00,
250 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00,
251 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00,
252 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00,
253 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00,
254 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00,
255 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00,
256 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00,
257 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16,
258 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c,
259 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
260 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
261 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
262 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a,
263 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0,
264 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52,
265 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf,
266 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60,
267 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34,
268 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37,
269 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe,
270 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd,
271 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9,
272 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62,
273 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44,
274 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38,
275 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a,
276 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92,
277 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6,
278 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2,
279 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53,
280 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19,
281 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb,
282 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63,
283 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61,
284 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef,
285 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e,
286 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4,
287 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c,
288 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81,
289 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17,
290 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10,
291 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6,
292 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa,
293 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce,
294 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8
298 static const UInt8 kAppleTestPKISettingsRootCACert[] = {
299 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x26,
300 0xfe, 0xf8, 0xda, 0x41, 0xf3, 0x61, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
301 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04,
302 0x03, 0x0c, 0x24, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74,
303 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20,
304 0x54, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b,
305 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
306 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
307 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20,
308 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
309 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x32, 0x32, 0x32, 0x30, 0x33, 0x31, 0x34,
310 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x34, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x34, 0x36,
311 0x5a, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, 0x41, 0x70,
312 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
313 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x54, 0x45, 0x53, 0x54, 0x49,
314 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70,
315 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
316 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
317 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
318 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22,
319 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
320 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x84, 0xbe, 0xc2,
321 0x69, 0x9b, 0xec, 0xd5, 0xde, 0x72, 0xf0, 0x4f, 0x78, 0x81, 0x10, 0xa9, 0x56, 0x59, 0x77, 0x9c,
322 0x46, 0x95, 0xd7, 0xb7, 0x0b, 0x77, 0x73, 0x02, 0xce, 0xf8, 0xaa, 0x32, 0x89, 0xee, 0xbe, 0xaa,
323 0x40, 0x53, 0xf9, 0x2d, 0x96, 0x08, 0xcd, 0x2a, 0xa4, 0x61, 0xd4, 0xfd, 0x7d, 0x67, 0x2a, 0x35,
324 0xc1, 0xfc, 0x43, 0xa4, 0x9c, 0xd0, 0xbd, 0xcd, 0x82, 0x27, 0xed, 0xa1, 0x1c, 0x2d, 0x9a, 0x62,
325 0xd5, 0x99, 0xbd, 0x74, 0xaa, 0xf3, 0xce, 0x78, 0xc6, 0x47, 0x07, 0x43, 0x04, 0x5b, 0xbc, 0x27,
326 0x5e, 0x26, 0x3e, 0x77, 0x90, 0x69, 0x7a, 0xf6, 0xe0, 0x8e, 0xaa, 0xdf, 0x96, 0x12, 0x2c, 0xb2,
327 0x8b, 0xb9, 0x7e, 0x17, 0xfe, 0xde, 0x99, 0x67, 0x9b, 0x50, 0x13, 0x5c, 0x8d, 0x15, 0x26, 0x0a,
328 0x9f, 0x08, 0x2f, 0x3f, 0x7c, 0x01, 0x2c, 0x3e, 0xa1, 0xba, 0xb1, 0x25, 0x33, 0xe5, 0xd9, 0x39,
329 0x37, 0xde, 0x06, 0x3a, 0x63, 0x48, 0xa0, 0x9d, 0x3b, 0xa5, 0x72, 0x46, 0xfb, 0x6e, 0xa2, 0xd4,
330 0x74, 0xe6, 0xf1, 0xc1, 0x69, 0xc8, 0x31, 0xff, 0x58, 0x84, 0x3a, 0xc2, 0x6b, 0x9a, 0x0d, 0x19,
331 0x76, 0xe4, 0xd4, 0x4d, 0x85, 0xbc, 0x84, 0xf0, 0x07, 0x75, 0x66, 0x5f, 0xd7, 0xea, 0xab, 0x9e,
332 0x46, 0xf2, 0x8a, 0x29, 0xab, 0x73, 0x57, 0xaf, 0x95, 0x4f, 0xc7, 0xf3, 0x3b, 0x55, 0xb4, 0x26,
333 0x57, 0x68, 0xe9, 0x5a, 0x34, 0xbb, 0xa9, 0x39, 0xb3, 0x57, 0x5f, 0x25, 0x93, 0xd6, 0x34, 0xb7,
334 0xd1, 0xc4, 0xd7, 0x70, 0xed, 0x30, 0xdb, 0x21, 0xc1, 0xcc, 0xdf, 0xed, 0xec, 0x37, 0xc5, 0xdc,
335 0x0b, 0xc9, 0x85, 0x46, 0x26, 0xa7, 0x51, 0xc8, 0xdd, 0xe6, 0x47, 0xfc, 0x37, 0xd6, 0x73, 0x6f,
336 0x91, 0x3d, 0xef, 0xd8, 0xa4, 0xa5, 0x08, 0x32, 0x8c, 0xae, 0x8f, 0x57, 0xf7, 0x99, 0x48, 0xef,
337 0x81, 0x44, 0xac, 0x80, 0x42, 0x57, 0x9f, 0x64, 0x77, 0x40, 0x2a, 0xec, 0x03, 0x21, 0x79, 0x01,
338 0x0b, 0x87, 0xc3, 0x9d, 0x22, 0xc9, 0xc0, 0x69, 0xe0, 0x34, 0xff, 0x73, 0xdd, 0x1e, 0x1b, 0x0c,
339 0xe0, 0x68, 0xf0, 0x8c, 0x7a, 0x4b, 0xcd, 0x1d, 0x3f, 0x38, 0x2d, 0xe8, 0x9b, 0x91, 0xa6, 0xfe,
340 0xa8, 0x8b, 0x45, 0x1c, 0xdf, 0xaf, 0x49, 0x34, 0x48, 0x17, 0x02, 0x28, 0xdb, 0xe0, 0x6e, 0x74,
341 0x34, 0xea, 0xac, 0x6b, 0x00, 0x45, 0x89, 0xa9, 0xb5, 0x63, 0xbd, 0x2f, 0xe0, 0x58, 0x2e, 0xd3,
342 0xc2, 0x74, 0xa2, 0x37, 0x37, 0x62, 0xf6, 0x76, 0x1b, 0x3f, 0xfb, 0x98, 0x64, 0x13, 0xd6, 0x8c,
343 0xa0, 0x0c, 0xbc, 0x54, 0x00, 0xe0, 0xf8, 0x63, 0x17, 0x22, 0x44, 0x36, 0xe0, 0x28, 0xa0, 0x7d,
344 0x50, 0x9e, 0x50, 0x94, 0xea, 0xd7, 0x62, 0xab, 0x6d, 0x7a, 0x19, 0xa4, 0xa2, 0x74, 0x79, 0x5d,
345 0x15, 0x85, 0x21, 0xfe, 0x9a, 0x35, 0x76, 0x40, 0x78, 0x01, 0xe3, 0x46, 0x2f, 0x6f, 0x2d, 0x0a,
346 0x1d, 0xac, 0x2e, 0x23, 0xec, 0xb8, 0x48, 0x74, 0xbc, 0xee, 0x29, 0x72, 0xb6, 0xe7, 0x52, 0x8c,
347 0xd4, 0x1a, 0x00, 0x34, 0x75, 0x1c, 0x4b, 0x83, 0x50, 0xbb, 0x57, 0x21, 0x9b, 0xd8, 0xb4, 0x75,
348 0xf3, 0x98, 0x8a, 0x9b, 0x45, 0xa8, 0x61, 0x50, 0x10, 0xb4, 0xec, 0x91, 0x2e, 0xe7, 0xf2, 0xb8,
349 0xb9, 0x62, 0x70, 0xc2, 0x93, 0xe7, 0xd9, 0xf1, 0x02, 0x27, 0xd7, 0xec, 0xde, 0x5b, 0x42, 0xa1,
350 0x26, 0x37, 0x41, 0x32, 0x65, 0x11, 0x63, 0x38, 0xbb, 0x6f, 0x23, 0x7a, 0xa0, 0xb7, 0x24, 0xeb,
351 0xa8, 0x38, 0x8b, 0xa7, 0x73, 0xe2, 0xc8, 0x30, 0x56, 0x73, 0x6f, 0x17, 0x6e, 0x1a, 0xe5, 0x32,
352 0xff, 0xd6, 0xa2, 0x08, 0x7b, 0x6a, 0x23, 0x33, 0x9f, 0x10, 0x05, 0x71, 0xdd, 0x02, 0x03, 0x01,
353 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
354 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, 0x99, 0xc4,
355 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
356 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
357 0x16, 0x80, 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59,
358 0x99, 0xc4, 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
359 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
360 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x71, 0x10, 0x3c, 0x89, 0xd5,
361 0xc0, 0x00, 0xdc, 0x36, 0x1d, 0x93, 0xaa, 0xab, 0x4a, 0xb6, 0xfa, 0xa8, 0x5b, 0x89, 0x1c, 0xb3,
362 0x4a, 0x04, 0x2e, 0xb3, 0x25, 0x0f, 0x12, 0x07, 0x29, 0x70, 0x3d, 0x34, 0xd1, 0xdd, 0x7e, 0x30,
363 0xfd, 0xf5, 0xfa, 0x94, 0xf4, 0xcb, 0xdb, 0xac, 0x1b, 0xed, 0xe5, 0x11, 0x4a, 0xc8, 0xab, 0x26,
364 0xe2, 0x41, 0xcb, 0xa5, 0x74, 0x4b, 0xe1, 0xd2, 0xf3, 0x83, 0x1c, 0x7a, 0xcb, 0x29, 0xd9, 0xd2,
365 0xa6, 0x9d, 0x08, 0x95, 0x73, 0x63, 0xe2, 0x9c, 0xeb, 0xa5, 0x82, 0x8b, 0x6c, 0xf4, 0x64, 0x98,
366 0x03, 0x53, 0x91, 0x35, 0x04, 0x89, 0x25, 0xa0, 0x1f, 0xdc, 0x42, 0xf7, 0x59, 0x44, 0x63, 0x75,
367 0xe6, 0x49, 0x10, 0x66, 0x0f, 0x08, 0x07, 0x39, 0xc4, 0x3e, 0x1f, 0xba, 0x30, 0x42, 0xf8, 0x7a,
368 0xc8, 0xbe, 0x6f, 0xdb, 0xec, 0x16, 0xb2, 0x76, 0x84, 0x2c, 0x6e, 0x20, 0xd1, 0xbd, 0xd5, 0x90,
369 0x22, 0x0a, 0x90, 0x5c, 0x70, 0x47, 0xc9, 0x2d, 0xe3, 0x77, 0x74, 0xfd, 0xbb, 0x85, 0x1a, 0xd8,
370 0x5c, 0x38, 0x94, 0x4c, 0x83, 0x28, 0x23, 0xa5, 0x4f, 0x55, 0x5f, 0xe3, 0x42, 0x80, 0x10, 0xd4,
371 0xa5, 0x8d, 0xcf, 0x8b, 0x53, 0x69, 0x6d, 0xc5, 0x37, 0xd2, 0xfa, 0xbb, 0xc0, 0x5a, 0xab, 0x6f,
372 0x71, 0x37, 0x92, 0xd4, 0x90, 0xef, 0x5d, 0xf1, 0xc3, 0xb8, 0x64, 0x08, 0xd3, 0xba, 0x36, 0x69,
373 0x2b, 0x00, 0xed, 0xad, 0x36, 0x21, 0x38, 0xdf, 0x4a, 0xc6, 0x44, 0xc4, 0x6b, 0xd8, 0xb0, 0x7f,
374 0x67, 0x05, 0xaa, 0x6f, 0x9e, 0x8a, 0xf1, 0x81, 0x95, 0x99, 0xb9, 0x56, 0xf4, 0x73, 0xa7, 0xb4,
375 0x19, 0xb9, 0x4b, 0xb8, 0x1d, 0x10, 0xa5, 0x88, 0x7c, 0x39, 0xa3, 0x85, 0xe7, 0xba, 0x65, 0x86,
376 0xca, 0xf7, 0x0e, 0xe0, 0x0d, 0x73, 0x3f, 0xea, 0x98, 0x88, 0x58, 0x73, 0xfa, 0x68, 0x5b, 0xaa,
377 0x8c, 0xfd, 0x3e, 0x22, 0x3e, 0x92, 0xc7, 0xe2, 0x77, 0x14, 0x81, 0xe6, 0xd9, 0xdc, 0xc1, 0xe9,
378 0xc0, 0x06, 0x57, 0xb4, 0xca, 0xb6, 0x14, 0x15, 0x16, 0x80, 0x7e, 0xc5, 0x11, 0xa4, 0x05, 0x66,
379 0xad, 0x1d, 0xa3, 0xb6, 0xab, 0x2a, 0xbe, 0xd0, 0x52, 0x4e, 0x9e, 0x84, 0x61, 0x6b, 0xf4, 0x34,
380 0x23, 0x94, 0x24, 0xc6, 0xc8, 0xb0, 0x94, 0x22, 0x4c, 0x3b, 0xac, 0x85, 0xe3, 0xd4, 0xf7, 0x38,
381 0xe5, 0x9a, 0x76, 0xb3, 0x1b, 0xf0, 0xbc, 0x78, 0xc6, 0x6f, 0x11, 0xb3, 0x1a, 0x5c, 0x4f, 0x07,
382 0x52, 0x06, 0x92, 0x7a, 0x25, 0x86, 0x91, 0x71, 0x8a, 0xf4, 0x03, 0xce, 0x19, 0x0d, 0xfc, 0xde,
383 0x8f, 0xc9, 0x4e, 0x84, 0xf1, 0x17, 0x18, 0x6f, 0x37, 0x56, 0xb9, 0x76, 0x7e, 0x8f, 0xca, 0xde,
384 0xd4, 0x1b, 0x2d, 0x8d, 0xcf, 0x12, 0x9f, 0xf9, 0xb9, 0x8b, 0x82, 0x8f, 0x4d, 0xb7, 0x63, 0x26,
385 0x8d, 0xda, 0x35, 0x94, 0x18, 0xf9, 0x55, 0xca, 0x39, 0x09, 0xe9, 0x62, 0xe1, 0x00, 0xd8, 0x67,
386 0xed, 0x5e, 0x84, 0xc2, 0xe5, 0x8e, 0x46, 0x57, 0xa4, 0xa7, 0x17, 0x70, 0xcf, 0x6d, 0xdf, 0x43,
387 0x64, 0x2b, 0x36, 0xe6, 0xf3, 0xc1, 0x4c, 0x7a, 0x7e, 0x9e, 0x47, 0xc4, 0x14, 0x82, 0xbe, 0x94,
388 0x73, 0x54, 0xd0, 0x2c, 0xc2, 0x31, 0xc6, 0xd5, 0xc3, 0xd7, 0xa9, 0xef, 0x11, 0x24, 0x2f, 0xd0,
389 0x5b, 0xb8, 0x6a, 0x8e, 0x3c, 0xb7, 0x4b, 0x00, 0x9b, 0xc1, 0xca, 0x00, 0x6f, 0xd4, 0x73, 0x93,
390 0x2e, 0x39, 0x37, 0x2a, 0x73, 0x44, 0x9b, 0x1b, 0x05, 0x1a, 0x7c, 0x2f, 0xc9, 0x2b, 0x37, 0xf3,
391 0xcd, 0x8c, 0x4e, 0xc2, 0x7a, 0x6e, 0xd9, 0xd4, 0xf1, 0x8d, 0x6d, 0x07, 0x4b, 0xb5, 0x09, 0xb9,
392 0x48, 0x55, 0xac, 0xc6, 0x7e, 0xbc, 0xc6, 0x76, 0xeb, 0x5f, 0x0f
396 static NSDictionary* VerifyMessage(CFDataRef message, SecPolicyRef policy, CFDataRef cert_data)
398 NSDictionary* result = nil;
400 SecTrustRef trustRef = NULL;
401 CFDataRef payload = NULL;
402 CFArrayRef anchors = NULL;
403 OSStatus status = noErr;
404 SecCertificateRef aCertRef = NULL;
405 SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure;
407 if (NULL == message || NULL == policy || NULL == cert_data)
412 status = SecCMSVerifyCopyDataAndAttributes(message, NULL, policy, &trustRef, &payload, NULL);
413 if (noErr != status || NULL == trustRef || NULL == payload)
418 aCertRef = SecCertificateCreateWithData(NULL, cert_data);
419 if (NULL == aCertRef)
424 anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&aCertRef, 1, &kCFTypeArrayCallBacks);
430 status = SecTrustSetAnchorCertificates(trustRef, anchors);
436 status = SecTrustEvaluate(trustRef, &trust_result);
443 if (trust_result == kSecTrustResultUnspecified)
445 // Life is good and we got back the expected result.
447 NSData* property_list_data = CFBridgingRelease(payload);
449 NSPropertyListFormat format;
450 NSError* error = nil;
451 result = [NSPropertyListSerialization propertyListWithData:property_list_data options:0 format:&format error:&error];
459 CFReleaseSafe(aCertRef)
460 CFReleaseSafe(anchors);
464 /* ==========================================================================
465 Private Methods for the OTAServiceApp class
466 ========================================================================== */
467 @interface OTAServiceApp (PrivateMethods)
468 - (void)processAssets:(NSArray*)assets;
469 - (BOOL)checkAssetVersions:(NSString *)assetDir;
470 - (BOOL)validateAsset:(NSString *)assetDir;
471 - (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names;
472 - (NSDictionary *)decodeManifest:(NSData *)manifest_file_data;
473 - (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash;
474 - (BOOL)installAssetFiles:(NSString *)assetDir;
475 - (NSString*)getCurrentAssetDirectory;
479 @implementation OTAServiceApp
481 @synthesize file_list = _file_list;
482 @synthesize manifest_file_name = _manifest_file_name;
483 @synthesize asset_version_file_name = _asset_version_file_name;
484 @synthesize current_asset_version = _current_asset_version;
485 @synthesize next_asset_version = _next_asset_version;
486 @synthesize fileManager = _fileManager;
487 @synthesize current_asset_directory = _current_asset_directory;
488 @synthesize assets_directory = _assets_directory;
490 /* --------------------------------------------------------------------------
491 OTAServiceApp init:withArguments:
493 Initialize a new instance of the OTAServiceApp class
494 -------------------------------------------------------------------------- */
495 - (id)init:(int)argc withArguments:(const char**)argv
497 if ((self = [super init]))
499 _fileManager = [NSFileManager defaultManager];
501 _manifest_file_name = (NSString *)kManifestFileName;
502 _asset_version_file_name = (NSString *)kAssetVersionFileName;
503 _file_list = [NSArray arrayWithObjects:kBlockKeyFileName, kGrayListedKeysFileName,
504 kEVRootsFileName, kCertsIndexFileName, kCertsTableFileName,
505 kManifestFileName, kAssetVersionFileName, kAppleESCertificatesName,
506 kAllowListFileName, kCTLogsFileName, nil];
508 _current_asset_version = nil;
509 _next_asset_version = nil;
510 _assets_directory = nil;
511 _current_asset_directory = [self getCurrentAssetDirectory];
513 /* Default interval is one hour */
514 _asset_query_retry_interval = 60.0 * 60;
518 while ((ch = getopt(argc, (char * const *)argv, "d:v")) != -1 )
526 CFTimeInterval interval = strtod(optarg, &endptr);
527 if ((interval == 0 && endptr == optarg) || errno == ERANGE) {
528 syslog(LOG_ERR, "invalid argument '%s', ignoring", optarg);
530 syslog(LOG_NOTICE, "Setting query retry interval to %f seconds", interval);
531 _asset_query_retry_interval = (CFTimeInterval)interval;
536 syslog(LOG_NOTICE, "Enabling verbose logging");
546 if (stat([kBaseAssetDirectoryPath UTF8String], &info))
548 OTAPKI_LOG("OTAServiceApp.init:withArguments: stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
550 if (mkdir([kBaseAssetDirectoryPath UTF8String], kAssetDirectoryPermission))
552 OTAPKI_LOG("OTAServiceApp.init:withArguments: mkdir of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
556 if (stat([kBaseAssetDirectoryPath UTF8String], &info))
558 OTAPKI_LOG("OTAServiceApp.init:withArguments: second stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
563 stat([kBaseAssetDirectoryPath UTF8String], &info);
574 #if !TARGET_IPHONE_SIMULATOR
576 - (void)registerBackgroundTaskAgentJobWithDelay:(CFTimeInterval)delay
579 * ELEs are very important, so allow asset queries on any network type and
580 * construct the job so that it will fire as soon as possible, unless we are
581 * scheduling a retry after a failure.
583 xpc_object_t job = xpc_dictionary_create(NULL, NULL, 0);
586 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowStartTime, CFAbsoluteTimeGetCurrent() + delay);
588 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowEndTime, CFAbsoluteTimeGetCurrent() + BACKGROUND_TASK_AGENT_JOB_WINDOW_MAX_TIME_FROM_NOW_SEC);
589 xpc_dictionary_set_bool(job, kBackgroundTaskAgentNetworkRequired, true);
590 xpc_dictionary_set_bool(job, kBackgroundTaskAgentCellularAllowed, true);
591 xpc_dictionary_set_bool(job, kBackgroundTaskAgentAllowedDuringRoaming, true);
592 xpc_dictionary_set_bool(job, kBackgroundTaskAgentPowerOptLevel, kBackgroundTaskAgentPowerDontCare);
596 char *desc = xpc_copy_description(job);
597 syslog(LOG_NOTICE, "Adding BTA job %s", desc);
600 #pragma GCC diagnostic push
601 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
602 BackgroundTaskAgentAddJob(kOTAPKIAssetToolBTAJob, job);
603 #pragma GCC diagnostic pop
608 /* --------------------------------------------------------------------------
609 OTAServiceApp checkInWithActivity
611 Check in with the XPC activity configured in OTAPKIAssetTool's launchd
612 plist. This activity will launch OTAPKIAssetTool every three days (with
613 some leeway decided by the system). At that time, we schedule a
614 BackgroundTaskAgent job to be notified immediately when the network is
615 available so we can perform an asset query.
616 -------------------------------------------------------------------------- */
617 - (void)checkInWithActivity
619 #if !TARGET_IPHONE_SIMULATOR
620 #pragma GCC diagnostic push
621 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
622 BackgroundTaskAgentInit("com.apple.OTAPKIAssetTool", dispatch_get_main_queue(), ^(const char *job_name, xpc_object_t job)
625 * We're doing real work at this point, so open a transaction so
626 * that the system (hopefully) won't kill us while we're busy
628 xpc_transaction_begin();
632 syslog(LOG_NOTICE, "BackgroundTaskAgent job %s fired", job_name);
635 int64_t job_status = xpc_dictionary_get_int64(job, kBackgroundTaskAgentJobStatus);
636 if (job_status == kBackgroundTaskAgentJobRequestError)
638 syslog(LOG_ERR, "Failed to create BTA job -- malformed job?");
640 else if (job_status == kBackgroundTaskAgentJobSatisfied)
644 syslog(LOG_NOTICE, "BTA job %s is satisfied -- performing asset query", job_name);
646 bool shouldReschedule = false;
647 if ([self run:&shouldReschedule] || !shouldReschedule)
651 syslog(LOG_NOTICE, "Unscheduling BTA job");
653 BackgroundTaskAgentRemoveJob(kOTAPKIAssetToolBTAJob);
657 syslog(LOG_NOTICE, "Asset query failed due to network error. Re-scheduling BTA job for another attempt in %f seconds.", self->_asset_query_retry_interval);
658 [self registerBackgroundTaskAgentJobWithDelay:self->_asset_query_retry_interval];
661 else if (job_status == kBackgroundTaskAgentJobUnsatisfied)
664 * We will receive this if the job expires before we get to do our
665 * work. We still want to check for new assets as soon as possible,
666 * so reschedule the job.
668 if (xpc_dictionary_get_bool(job, kBackgroundTaskAgentJobExpired))
670 [self registerBackgroundTaskAgentJobWithDelay:0];
674 xpc_transaction_end();
676 #pragma GCC diagnostic pop
679 xpc_activity_register(kOTAPKIAssetToolActivity, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity)
681 xpc_activity_state_t state = xpc_activity_get_state(activity);
685 xpc_object_t criteria = xpc_activity_copy_criteria(activity);
687 if (criteria != NULL)
689 char *desc = xpc_copy_description(criteria);
690 syslog(LOG_NOTICE, "Criteria for XPC activity %s: %s", kOTAPKIAssetToolActivity, desc);
695 syslog(LOG_NOTICE, "No critera for XPC activity %s", kOTAPKIAssetToolActivity);
699 if (state == XPC_ACTIVITY_STATE_CHECK_IN)
702 * The activity is already configured in the launchd plist, so there
703 * is nothing to do here
707 syslog(LOG_NOTICE, "Activity %s in check in state", kOTAPKIAssetToolActivity);
710 else if (state == XPC_ACTIVITY_STATE_RUN)
712 #if !TARGET_IPHONE_SIMULATOR
713 #pragma GCC diagnostic push
714 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
715 xpc_object_t job = BackgroundTaskAgentCopyJob(kOTAPKIAssetToolBTAJob);
716 #pragma GCC diagnostic pop
719 syslog(LOG_NOTICE, "Activity %s in run state. Scheduling BTA job for earliest network availability.", kOTAPKIAssetToolActivity);
720 [self registerBackgroundTaskAgentJobWithDelay:0];
722 else if (self->_verbose)
724 syslog(LOG_NOTICE, "Already have a BTA job registered. Ignoring activity.");
728 * BackgroundTaskAgent doesn't exist on the iOS simulator, so we
729 * just directly try to find and download new assets.
731 xpc_transaction_begin();
732 bool shouldReschedule = false;
733 if (![self run:&shouldReschedule]) {
734 syslog(LOG_NOTICE, "Asset query failed%s.", shouldReschedule ? " due to network issue" : "");
736 xpc_transaction_end();
742 /* --------------------------------------------------------------------------
745 Run this program and leave. This program will currently run every 3 days,
746 with some leeway based on network availability. That will provide the
747 longest time from publisihing a change in the PKI trust setting asset and
748 having that asset be consumed by a device.
750 The program simnply ask the mobile asset daemon if there are any assets
751 to be processed with the PKITrustDataAssetType. If not this program
752 will just complete and will be re-run in 3 days. If there is an asset to
753 process then the asset will be process and then the program will complete.
755 Returns false if the operation failed. On return, shouldReschedule is set
756 to true if the operation failed due to a network error and the caller
757 should reschedule this operation at a more opportune time.
758 -------------------------------------------------------------------------- */
759 - (bool)run:(bool *)shouldReschedule
763 if (shouldReschedule != NULL) {
764 *shouldReschedule = false;
767 syslog(LOG_NOTICE, "OTAPKIAssetTool running");
768 if (![[MCProfileConnection sharedConnection] isOTAPKIUpdatesAllowed])
770 syslog(LOG_NOTICE, "OTAPKIAssetTool: OTAPKI updates are not allowed.");
774 ASAssetQuery *assetQuery = [[ASAssetQuery alloc] initWithAssetType:(NSString *)kPKITrustDataAssetType];
775 if (assetQuery == nil)
777 syslog(LOG_NOTICE, "OTAPKIAssetTool: Could not create the asset query.");
781 // Get the asset synchronously
782 NSError *error = nil;
783 NSArray *foundAssets = [assetQuery runQueryAndReturnError:&error];
784 if (nil != foundAssets)
786 [self processAssets:foundAssets];
790 syslog(LOG_NOTICE, "OTAPKIAssetTool: No assets returned from query: %s", [[error description] UTF8String]);
792 NSArray *networkErrorCodes = @[ @(ASErrorNetwork), @(ASErrorNetworkNoConnection), @(ASErrorNetworkTimedOut), @(ASErrorNetworkUnexpectedResponse) ];
793 if ([[error domain] isEqualToString:ASErrorDomain] && [networkErrorCodes containsObject:@([error code])])
795 syslog(LOG_NOTICE, "OTAPKIAssetTool: Query failed due to network error.");
796 if (shouldReschedule != NULL) {
797 *shouldReschedule = true;
807 /* --------------------------------------------------------------------------
808 OTAServiceApp processAssets:
810 If when run is called asset(s) are found they will be processed here.
811 -------------------------------------------------------------------------- */
812 - (void)processAssets:(NSArray*)assets
819 NSError* error = nil;
820 ASAsset* asset = nil;
821 int asset_version = 0;
823 for (asset in assets)
825 NSDictionary* asset_attributes = asset.attributes;
827 NSNumber* contentVersion = [asset_attributes objectForKey:@"ContentVersion"];
828 OTAPKI_LOG("In processAssets: about to check the ContentVersion\n");
829 if (nil != contentVersion)
831 asset_version = [contentVersion intValue];
832 int current_asset_version_number = (nil != _current_asset_version) ? [_current_asset_version intValue] : 0;
834 if (asset_version <= current_asset_version_number)
836 syslog(LOG_NOTICE, "OTAPKIAssetTool: content version %d is too small. Current asset version id %d",
837 asset_version, current_asset_version_number);
839 OTAPKI_LOG("In processAssets: content version is too small: current asset version is %d\nContent version is %d\n",
840 current_asset_version_number, asset_version);
848 syslog(LOG_NOTICE, "OTAPKIAssetTool: no suitable asset found");
853 // Check to see if the asset needs to be downloaded
854 if (asset.state == ASAssetStateNotPresent)
856 __block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
858 [asset setProgressHandler:^(NSDictionary *state, NSError *anError)
862 // An error occured. Signal the semaphore to bail
863 dispatch_semaphore_signal(sem);
865 else if ([[state objectForKey:@"Operation"] isEqualToString:(NSString *) @"OperationCompleted"])
867 // The download is complete. Signal the semaphore
868 dispatch_semaphore_signal(sem);
872 NSNumber* yesValue = [NSNumber numberWithBool:YES];
873 const id keys[] = {ASDownloadOptionAllow3G, ASDownloadOptionAllow4G, ASDownloadOptionPriority, ASDownloadOptionAllowBatteryPower};
874 const id values[] = {yesValue, yesValue, ASDownloadPriorityHigh, yesValue};
876 NSDictionary* options = [NSDictionary dictionaryWithObjects:values forKeys:keys count:(sizeof (keys) / sizeof(keys[0]))];
878 [asset beginDownloadWithOptions:options];
879 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
882 // Check to see if the asset is now available for processing
883 if ([asset state] == ASAssetStateInstalled)
885 // Get the asset data directory
886 NSString* assetDir = [[[asset localURL] URLByAppendingPathComponent:@"PKITrustData"] path];
889 // validate the asset.
890 OTAPKI_LOG("In processAssets: about to validateAsset\n");
891 if ([self validateAsset:assetDir])
893 OTAPKI_LOG("In processAssets: asset validated installing\n");
894 // The asset is valid so install the files
895 [self installAssetFiles:assetDir];
897 // Signal securityd to idle-exit at it's next opportunity
898 OTAPKI_LOG("In processAssets: notifying securityd\n");
900 (void)SecTrustOTAPKIGetUpdatedAsset(&didUpdate);
901 syslog(LOG_NOTICE, "OTAPKIAssetTool: installed new asset %d", asset_version);
902 _current_asset_version = contentVersion;
906 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset %d did not validate", asset_version);
909 // regaurdless if the asset is valid. Now that it is
910 // installed, it needs to be purged to ensure that
911 // we can retrieve a new updated asset.
912 [asset purgeAndReturnError:&error];
916 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset directory %s not found", [assetDir UTF8String]);
922 /* --------------------------------------------------------------------------
923 OTAServiceApp checkAssetVersions:
925 If when run is called asset(s) are found they will be processed here.
926 -------------------------------------------------------------------------- */
927 - (BOOL)checkAssetVersions:(NSString *)assetDir
931 OTAPKI_LOG("Entering checkAssetVersions\n");
933 if (nil == assetDir || nil == self.current_asset_version)
935 OTAPKI_LOG("checkAssetVersions: parameter error\n");
939 // first get the new version number from the downloaded asset
940 NSString* next_asset_version_path = [assetDir stringByAppendingPathComponent:self.asset_version_file_name];
941 if (![self.fileManager fileExistsAtPath:next_asset_version_path])
943 // The asset is missing the AssertVersion.plist
944 // This is an invalid asset
945 OTAPKI_LOG("checkAssetVersions: could not file asseet version file %s\n", [self.asset_version_file_name UTF8String]);
949 NSError* error = nil;
950 NSInputStream* input_stream = [NSInputStream inputStreamWithFileAtPath:next_asset_version_path];
952 NSDictionary* asset_dict = [NSPropertyListSerialization propertyListWithStream:input_stream options:0 format:nil error:&error];
953 [input_stream close];
957 OTAPKI_LOG("checkAssetVersions: error reading asset version file: %s\n", [[error localizedDescription] UTF8String]);
961 _next_asset_version = [asset_dict objectForKey:kVersionNumberKey];
962 if (nil == _next_asset_version)
964 OTAPKI_LOG("asset_dict did not have a entry with a key of kVersionNumberKey\n");
968 // Check the current asset version against the new asset version. The new asset version MUST be larger than the
969 // current asset version
970 NSInteger current_asset_version_value = [self.current_asset_version integerValue];
971 NSInteger next_asset_version_value = [self.next_asset_version integerValue];
973 if (next_asset_version_value <= current_asset_version_value)
975 OTAPKI_LOG("heckAssetVersions: assert version too small. current_asset_version_value = %d next_asset_version_value = %d\n",
976 current_asset_version_value, next_asset_version_value);
984 /* --------------------------------------------------------------------------
985 OTAServiceApp validateAsset:
987 Decode the manifest and verify the file hashes
988 -------------------------------------------------------------------------- */
989 - (BOOL)validateAsset:(NSString *)assetDir
993 OTAPKI_LOG("Enterning validateAsset\n");
995 if (![self validateDirectory:assetDir withFiles:self.file_list])
997 OTAPKI_LOG("validateAsset param\n");
1001 NSString* manifest_file_path = [assetDir stringByAppendingPathComponent:self.manifest_file_name];
1002 NSError* error = nil;
1003 NSData* manifest_file_data = [NSData dataWithContentsOfFile:manifest_file_path options:0 error:&error];
1006 OTAPKI_LOG("validateAsset: could not read manifest file. error = %s\n", [[error localizedDescription] UTF8String]);
1010 NSDictionary* manifest_data = [self decodeManifest:manifest_file_data];
1011 if (nil == manifest_data)
1013 OTAPKI_LOG("validateAsset: decodeManifest failed!\n");
1017 NSString* full_file_path = nil;
1019 for (NSString* file_name in self.file_list)
1021 if ([file_name isEqualToString:self.manifest_file_name])
1026 hash = [manifest_data objectForKey:file_name];
1029 OTAPKI_LOG("validateAsset: could not get hash for file %s\n", [file_name UTF8String]);
1033 full_file_path = [assetDir stringByAppendingPathComponent:file_name];
1034 if (![self checkFileHash:full_file_path hash:hash])
1036 OTAPKI_LOG("validateAsset: hash for file %s does not match\n", [file_name UTF8String]);
1041 result = [self checkAssetVersions:assetDir];
1045 /* --------------------------------------------------------------------------
1046 OTAServiceApp validateDirectory:withFiles:
1048 Ensure that a given directory has the files listed in the files_names
1050 -------------------------------------------------------------------------- */
1051 - (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names
1054 OTAPKI_LOG("Enterning validateDirectory\n");
1056 if (nil == assetDir || nil == file_names)
1058 OTAPKI_LOG("validateDirectory param error\n");
1061 NSError* error = nil;
1062 NSArray* dir_items = [self.fileManager contentsOfDirectoryAtPath:assetDir error:&error];
1065 OTAPKI_LOG("validateDirectory: Error calling contentsOfDirectoryAtPath: error = %s\n", [[error localizedDescription] UTF8String]);
1069 for (NSString* file_name in file_names)
1071 if (![dir_items containsObject:file_name])
1073 OTAPKI_LOG("validateDirectory: missing file %s\n", [file_name UTF8String]);
1081 /* --------------------------------------------------------------------------
1082 OTAServiceApp decodeManifest:
1084 Ensure that the asset manifest blob has it CMS signature verified
1085 -------------------------------------------------------------------------- */
1086 - (NSDictionary *)decodeManifest:(NSData *)manifest_file_data
1088 NSDictionary* result = nil;
1089 CFDataRef cert_data = NULL;
1090 CFDataRef message = NULL;
1091 SecPolicyRef policy = NULL;
1092 CFBooleanRef mgResult = NULL;
1094 OTAPKI_LOG("Enterning decodeManifest\n");
1096 if (nil == manifest_file_data)
1098 OTAPKI_LOG("decodeManifest: parameter error\n");
1102 message = CFBridgingRetain(manifest_file_data);
1104 policy = SecPolicyCreateOTAPKISigner();
1107 OTAPKI_LOG("decodeManifest: could not get the SecPolicyCreateOTAPKISigner policyRef\n");
1111 cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert));
1112 if (NULL == cert_data)
1114 OTAPKI_LOG("decodeManifest: could not kApplePKISettingsRootCACert data\n");
1118 result = VerifyMessage(message, policy, cert_data);
1122 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner success!\n");
1126 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner failed! Checking to see if this is an internal build\n");
1128 // The first attempt did not work so check to see if this is running on an internal build.
1129 if (!MGIsQuestionValid(kMGQAppleInternalInstallCapability))
1131 OTAPKI_LOG("decodeManifest: kMGQAppleInternalInstallCapability had an error\n");
1135 mgResult = MGCopyAnswer(kMGQAppleInternalInstallCapability, NULL);
1137 if (NULL == mgResult || !CFEqual(mgResult, kCFBooleanTrue))
1139 OTAPKI_LOG("decodeManifest: Not an internal build");
1143 OTAPKI_LOG("decodeManifest: This is an internal build\n");
1145 CFReleaseNull(policy);
1146 CFReleaseNull(cert_data);
1148 policy = SecPolicyCreateTestOTAPKISigner();
1151 OTAPKI_LOG("decodeManifest: could not SecPolicyCreateTestOTAPKISigner policyRef\n");
1155 cert_data = CFDataCreate(kCFAllocatorDefault, kAppleTestPKISettingsRootCACert, sizeof(kAppleTestPKISettingsRootCACert));
1156 if (NULL == cert_data)
1158 OTAPKI_LOG("decodeManifest: could not kAppleTestPKISettingsRootCACert data\n");
1162 result = VerifyMessage(message, policy, cert_data);
1166 CFReleaseSafe(mgResult);
1167 CFReleaseSafe(message);
1168 CFReleaseSafe(policy);
1169 CFReleaseSafe(cert_data);
1173 /* --------------------------------------------------------------------------
1174 OTAServiceApp checkFileHash:hash:
1176 Ensure that the given asset file's hash is the same as in the manifest
1177 -------------------------------------------------------------------------- */
1178 - (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash
1181 if (nil == file_path || nil == hash)
1186 NSError* error = nil;
1187 NSData* file_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error];
1193 NSMutableData *digest = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
1194 uint8_t *dp = (digest) ? [digest mutableBytes] : NULL;
1200 memset(dp, 0, CC_SHA256_DIGEST_LENGTH);
1201 CCDigest(kCCDigestSHA256,
1202 (const uint8_t *)[file_data bytes],
1203 (size_t)[file_data length], dp);
1205 result = [hash isEqualToData:digest];
1210 /* --------------------------------------------------------------------------
1211 OTAServiceApp installAssetFiles:
1213 Copy over the files into the /var/Keychains/Assets directory.
1214 -------------------------------------------------------------------------- */
1215 - (BOOL)installAssetFiles:(NSString *)assetDir
1219 OTAPKI_LOG("Entering installAssetFiles\n");
1221 if (nil == assetDir)
1223 OTAPKI_LOG("installAssetFiles: parameter error\n");
1227 if (nil == self.assets_directory)
1229 OTAPKI_LOG("installAssetFiles: no assets directory\n");
1233 // Create a temp directory to hold the new asset files.
1234 NSString* tempDir = [self.assets_directory stringByAppendingPathComponent:@"TempAssetDir"];
1235 NSError* error = nil;
1238 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1239 id keys[] = {NSFilePosixPermissions};
1241 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1];
1243 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]);
1244 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]);
1245 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid];
1246 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid];
1248 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1249 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions};
1251 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
1255 if (![self.fileManager createDirectoryAtPath:tempDir withIntermediateDirectories:YES
1256 attributes:attributes error:&error])
1258 OTAPKI_LOG("installAssetFiles: could not create directory %s\n", [tempDir UTF8String]);
1262 #ifndef NEW_LOCATION
1263 // Copy all of the asset files to the newly created directory
1264 for (NSString* file_name in self.file_list)
1266 NSString* download_assert_path = [assetDir stringByAppendingPathComponent:file_name];
1267 NSString* asset_path = [tempDir stringByAppendingPathComponent:file_name];
1268 if ([self.fileManager copyItemAtPath:download_assert_path toPath:asset_path error:&error])
1270 chown([asset_path UTF8String], self.uid, self.gid);
1274 [self.fileManager removeItemAtPath:tempDir error:nil];
1278 #endif // !NEW_LOCATION
1281 // Now that all of the files have been copied to the temp directory make a single call
1282 // to rename (move) the temp directory to be the correct version directory. This rename
1283 // allow for reducing a race conditions between this asset code and securityd.
1284 NSInteger new_version_value = [self.next_asset_version integerValue];
1285 NSString* new_version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)new_version_value];
1286 NSString* new_version_dir_path = [self.assets_directory stringByAppendingPathComponent:new_version_dir_name];
1287 if (![self.fileManager moveItemAtPath:tempDir toPath:new_version_dir_path error:&error])
1289 OTAPKI_LOG("installAssetFiles: could not move path %s\n", [tempDir UTF8String]);
1290 [self.fileManager removeItemAtPath:tempDir error:nil];
1298 /* --------------------------------------------------------------------------
1299 OTAServiceApp getCurrentAssetDirectory:
1301 Looks through the /var/Keychains/Assets directory to find latest asset
1302 version directory. If no assets have been downloaded then nil is returned
1303 and the current asset version is set to 0
1304 -------------------------------------------------------------------------- */
1305 - (NSString*)getCurrentAssetDirectory
1307 NSString* result = nil;
1310 OTAPKI_LOG("In getCurrentAssetDirectory\n");
1311 OTAPKI_LOG("getCurrentAssetDirectory: checking to see if %s exists\n", [kBaseAssetDirectoryPath UTF8String]);
1313 // Check to see if the base directory is there
1314 if (![self.fileManager fileExistsAtPath:(NSString *)kBaseAssetDirectoryPath isDirectory:&isDir] || !isDir)
1316 OTAPKI_LOG("getCurrentAssetDirectory: %s does not exists\n", [kBaseAssetDirectoryPath UTF8String]);
1317 // This might be fatal
1321 NSError* error = nil;
1322 NSInteger version_number = 0;
1323 NSInteger current_version_number = 0;
1325 OSStatus err = noErr;
1327 _assets_directory = [kBaseAssetDirectoryPath stringByAppendingPathComponent:(NSString *)kAssetDirectoryName];
1329 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]);
1331 if ([self.fileManager fileExistsAtPath:self.assets_directory isDirectory:&isDir] && isDir)
1333 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]);
1334 NSDirectoryEnumerator* dirEnum = [self.fileManager enumeratorAtPath:self.assets_directory];
1335 [dirEnum skipDescendents];
1337 for (NSString* file in dirEnum)
1339 if ([file hasPrefix:(NSString *)kVersionDirectoryNamePrefix])
1341 NSString* version_str = [file substringFromIndex:[kVersionDirectoryNamePrefix length]];
1342 NSInteger aVersion_number = [version_str integerValue];
1343 if (aVersion_number > version_number)
1345 version_number = aVersion_number;
1353 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1354 id keys[] = {NSFilePosixPermissions};
1356 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1];
1359 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]);
1360 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]);
1361 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid];
1362 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid];
1364 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1365 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions};
1366 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
1368 OTAPKI_LOG("getCurrentAssetDirectory: %s does NOT exists\n", [self.assets_directory UTF8String]);
1369 OTAPKI_LOG("getCurrentAssetDirectory: creating %s\n", [self.assets_directory UTF8String]);
1371 if (![self.fileManager createDirectoryAtPath:self.assets_directory withIntermediateDirectories:YES
1372 attributes:attributes error:&error])
1374 OTAPKI_LOG("getCurrentAssetDirectory: failed to create %s\n", [self.assets_directory UTF8String]);
1380 err = SecTrustGetOTAPKIAssetVersionNumber(&aVerNum);
1381 if (errSecSuccess == err && aVerNum > 0)
1383 current_version_number = aVerNum;
1386 if (version_number < current_version_number)
1388 OTAPKI_LOG("The largest OTA version number is smaller than the current version number. This means the system has a newer asset\n");
1389 version_number = current_version_number;
1393 OTAPKI_LOG("The largest OTA version number is equal to the current version number. The OTA asset is newer than the system asset\n");
1394 NSString* version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)version_number];
1395 result = [self.assets_directory stringByAppendingPathComponent:version_dir_name];
1398 OTAPKI_LOG("getCurrentAssetDirectory: setting version number to %d\n", version_number);
1399 _current_asset_version = [NSNumber numberWithInteger:version_number];