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 kAssetVersionFileName - The file name of the plist file in the asset
86 that contains the version number of this
87 OTA PKI trust asset. It is a plist that is a
88 dictionary with a single key with a single
89 key value pair that has the version number
90 of the asset. This is used to ensure against
93 kBlockKeyFileName - The file name of the asset file that contains
94 blocked keys. Any certificate with these keys
95 will be marked as not being trusted.
97 kGrayListedKeysFileName - The file name of the asset file that contains
98 gray listed keys. If a chain has any of these
99 keys, than the chain will still be approved but
100 an entry will be added to the details dictionary
101 noting that the key was gray listed
104 kEVRootsFileName - The file name of the asset file that contains
105 the list of EV OIDS and their corresponding
106 certificates. This file sets which certs will
107 be considered to be EV.
109 kCertsIndexFileName - The file name of the asset file that contains
110 a hash table of offsets into the cert table
111 file. This is used to look up anchor certs.
113 kCertsTableFileName - The file name of the asset file that contains
114 all of the anchor certificates. The
115 kCertsIndexFileName file is used to find the
116 correct offset in this file to retrieve a
117 specific anchor certificate.
119 kVersionNumberKey - The dictionary key for the kAssetVersionFileName
120 file to get the version number
122 kVersionDirectoryNamePrefix -
123 The directory name prefix for all of the
126 kPKITrustDataAssetType - The asset identifier of the OTA PKI asset
129 ========================================================================== */
132 static const NSString* kBaseAssetDirectoryPath = @"/var/OTAPKI";
134 static const NSString* kBaseAssetDirectoryPath = @"/var/Keychains";
137 static const NSString* kManifestFileName = @"manifest.data";
138 static const NSString* kAssetVersionFileName = @"AssetVersion.plist";
139 static const NSString* kAppleESCertificatesName = @"AppleESCertificates.plist";
140 static const NSString* kBlockKeyFileName = @"Blocked.plist";
141 static const NSString* kGrayListedKeysFileName = @"GrayListedKeys.plist";
142 static const NSString* kEVRootsFileName = @"EVRoots.plist";
143 static const NSString* kCertsIndexFileName = @"certsIndex.data";
144 static const NSString* kCertsTableFileName = @"certsTable.data";
145 static const NSString* kVersionNumberKey = @"VersionNumber";
146 static const NSString* kAssetDirectoryName = @"Assets";
147 static const NSString* kAssetDirectoryUser = @"_securityd";
148 static const NSString* kAssetDirectoryGroup = @"wheel";
150 static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRWXG | S_IRWXO;
152 static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
154 static const NSString* kVersionDirectoryNamePrefix = @"Version_";
155 static const NSString* kPKITrustDataAssetType =@"com.apple.MobileAsset.PKITrustServices.PKITrustData";
157 const char *kOTAPKIAssetToolActivity = "com.apple.OTAPKIAssetTool.asset-check";
159 static const UInt8 kApplePKISettingsRootCACert[] = {
160 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e,
161 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
162 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55,
163 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65,
164 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74,
165 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
166 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70,
167 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
168 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06,
169 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e,
170 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17,
171 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d,
172 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84,
173 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65,
174 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f,
175 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
176 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
177 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
178 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
179 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70,
180 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
181 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
182 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a,
183 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04,
184 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc,
185 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe,
186 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29,
187 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77,
188 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf,
189 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f,
190 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa,
191 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e,
192 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a,
193 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d,
194 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99,
195 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05,
196 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3,
197 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d,
198 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb,
199 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3,
200 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4,
201 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d,
202 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce,
203 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc,
204 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff,
205 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7,
206 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f,
207 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22,
208 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70,
209 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f,
210 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf,
211 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7,
212 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee,
213 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62,
214 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63,
215 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82,
216 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82,
217 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6,
218 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
219 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35,
220 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f,
221 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca,
222 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63,
223 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01,
224 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00,
225 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00,
226 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00,
227 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00,
228 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00,
229 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00,
230 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00,
231 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00,
232 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00,
233 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00,
234 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00,
235 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00,
236 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00,
237 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00,
238 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00,
239 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00,
240 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00,
241 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00,
242 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00,
243 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00,
244 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00,
245 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00,
246 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00,
247 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16,
248 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c,
249 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
250 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
251 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
252 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a,
253 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0,
254 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52,
255 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf,
256 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60,
257 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34,
258 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37,
259 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe,
260 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd,
261 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9,
262 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62,
263 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44,
264 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38,
265 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a,
266 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92,
267 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6,
268 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2,
269 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53,
270 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19,
271 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb,
272 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63,
273 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61,
274 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef,
275 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e,
276 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4,
277 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c,
278 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81,
279 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17,
280 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10,
281 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6,
282 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa,
283 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce,
284 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8
288 static const UInt8 kAppleTestPKISettingsRootCACert[] = {
289 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x26,
290 0xfe, 0xf8, 0xda, 0x41, 0xf3, 0x61, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
291 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04,
292 0x03, 0x0c, 0x24, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74,
293 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20,
294 0x54, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b,
295 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
296 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
297 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20,
298 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
299 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x32, 0x32, 0x32, 0x30, 0x33, 0x31, 0x34,
300 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x34, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x34, 0x36,
301 0x5a, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, 0x41, 0x70,
302 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
303 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x54, 0x45, 0x53, 0x54, 0x49,
304 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70,
305 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
306 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
307 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
308 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22,
309 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
310 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x84, 0xbe, 0xc2,
311 0x69, 0x9b, 0xec, 0xd5, 0xde, 0x72, 0xf0, 0x4f, 0x78, 0x81, 0x10, 0xa9, 0x56, 0x59, 0x77, 0x9c,
312 0x46, 0x95, 0xd7, 0xb7, 0x0b, 0x77, 0x73, 0x02, 0xce, 0xf8, 0xaa, 0x32, 0x89, 0xee, 0xbe, 0xaa,
313 0x40, 0x53, 0xf9, 0x2d, 0x96, 0x08, 0xcd, 0x2a, 0xa4, 0x61, 0xd4, 0xfd, 0x7d, 0x67, 0x2a, 0x35,
314 0xc1, 0xfc, 0x43, 0xa4, 0x9c, 0xd0, 0xbd, 0xcd, 0x82, 0x27, 0xed, 0xa1, 0x1c, 0x2d, 0x9a, 0x62,
315 0xd5, 0x99, 0xbd, 0x74, 0xaa, 0xf3, 0xce, 0x78, 0xc6, 0x47, 0x07, 0x43, 0x04, 0x5b, 0xbc, 0x27,
316 0x5e, 0x26, 0x3e, 0x77, 0x90, 0x69, 0x7a, 0xf6, 0xe0, 0x8e, 0xaa, 0xdf, 0x96, 0x12, 0x2c, 0xb2,
317 0x8b, 0xb9, 0x7e, 0x17, 0xfe, 0xde, 0x99, 0x67, 0x9b, 0x50, 0x13, 0x5c, 0x8d, 0x15, 0x26, 0x0a,
318 0x9f, 0x08, 0x2f, 0x3f, 0x7c, 0x01, 0x2c, 0x3e, 0xa1, 0xba, 0xb1, 0x25, 0x33, 0xe5, 0xd9, 0x39,
319 0x37, 0xde, 0x06, 0x3a, 0x63, 0x48, 0xa0, 0x9d, 0x3b, 0xa5, 0x72, 0x46, 0xfb, 0x6e, 0xa2, 0xd4,
320 0x74, 0xe6, 0xf1, 0xc1, 0x69, 0xc8, 0x31, 0xff, 0x58, 0x84, 0x3a, 0xc2, 0x6b, 0x9a, 0x0d, 0x19,
321 0x76, 0xe4, 0xd4, 0x4d, 0x85, 0xbc, 0x84, 0xf0, 0x07, 0x75, 0x66, 0x5f, 0xd7, 0xea, 0xab, 0x9e,
322 0x46, 0xf2, 0x8a, 0x29, 0xab, 0x73, 0x57, 0xaf, 0x95, 0x4f, 0xc7, 0xf3, 0x3b, 0x55, 0xb4, 0x26,
323 0x57, 0x68, 0xe9, 0x5a, 0x34, 0xbb, 0xa9, 0x39, 0xb3, 0x57, 0x5f, 0x25, 0x93, 0xd6, 0x34, 0xb7,
324 0xd1, 0xc4, 0xd7, 0x70, 0xed, 0x30, 0xdb, 0x21, 0xc1, 0xcc, 0xdf, 0xed, 0xec, 0x37, 0xc5, 0xdc,
325 0x0b, 0xc9, 0x85, 0x46, 0x26, 0xa7, 0x51, 0xc8, 0xdd, 0xe6, 0x47, 0xfc, 0x37, 0xd6, 0x73, 0x6f,
326 0x91, 0x3d, 0xef, 0xd8, 0xa4, 0xa5, 0x08, 0x32, 0x8c, 0xae, 0x8f, 0x57, 0xf7, 0x99, 0x48, 0xef,
327 0x81, 0x44, 0xac, 0x80, 0x42, 0x57, 0x9f, 0x64, 0x77, 0x40, 0x2a, 0xec, 0x03, 0x21, 0x79, 0x01,
328 0x0b, 0x87, 0xc3, 0x9d, 0x22, 0xc9, 0xc0, 0x69, 0xe0, 0x34, 0xff, 0x73, 0xdd, 0x1e, 0x1b, 0x0c,
329 0xe0, 0x68, 0xf0, 0x8c, 0x7a, 0x4b, 0xcd, 0x1d, 0x3f, 0x38, 0x2d, 0xe8, 0x9b, 0x91, 0xa6, 0xfe,
330 0xa8, 0x8b, 0x45, 0x1c, 0xdf, 0xaf, 0x49, 0x34, 0x48, 0x17, 0x02, 0x28, 0xdb, 0xe0, 0x6e, 0x74,
331 0x34, 0xea, 0xac, 0x6b, 0x00, 0x45, 0x89, 0xa9, 0xb5, 0x63, 0xbd, 0x2f, 0xe0, 0x58, 0x2e, 0xd3,
332 0xc2, 0x74, 0xa2, 0x37, 0x37, 0x62, 0xf6, 0x76, 0x1b, 0x3f, 0xfb, 0x98, 0x64, 0x13, 0xd6, 0x8c,
333 0xa0, 0x0c, 0xbc, 0x54, 0x00, 0xe0, 0xf8, 0x63, 0x17, 0x22, 0x44, 0x36, 0xe0, 0x28, 0xa0, 0x7d,
334 0x50, 0x9e, 0x50, 0x94, 0xea, 0xd7, 0x62, 0xab, 0x6d, 0x7a, 0x19, 0xa4, 0xa2, 0x74, 0x79, 0x5d,
335 0x15, 0x85, 0x21, 0xfe, 0x9a, 0x35, 0x76, 0x40, 0x78, 0x01, 0xe3, 0x46, 0x2f, 0x6f, 0x2d, 0x0a,
336 0x1d, 0xac, 0x2e, 0x23, 0xec, 0xb8, 0x48, 0x74, 0xbc, 0xee, 0x29, 0x72, 0xb6, 0xe7, 0x52, 0x8c,
337 0xd4, 0x1a, 0x00, 0x34, 0x75, 0x1c, 0x4b, 0x83, 0x50, 0xbb, 0x57, 0x21, 0x9b, 0xd8, 0xb4, 0x75,
338 0xf3, 0x98, 0x8a, 0x9b, 0x45, 0xa8, 0x61, 0x50, 0x10, 0xb4, 0xec, 0x91, 0x2e, 0xe7, 0xf2, 0xb8,
339 0xb9, 0x62, 0x70, 0xc2, 0x93, 0xe7, 0xd9, 0xf1, 0x02, 0x27, 0xd7, 0xec, 0xde, 0x5b, 0x42, 0xa1,
340 0x26, 0x37, 0x41, 0x32, 0x65, 0x11, 0x63, 0x38, 0xbb, 0x6f, 0x23, 0x7a, 0xa0, 0xb7, 0x24, 0xeb,
341 0xa8, 0x38, 0x8b, 0xa7, 0x73, 0xe2, 0xc8, 0x30, 0x56, 0x73, 0x6f, 0x17, 0x6e, 0x1a, 0xe5, 0x32,
342 0xff, 0xd6, 0xa2, 0x08, 0x7b, 0x6a, 0x23, 0x33, 0x9f, 0x10, 0x05, 0x71, 0xdd, 0x02, 0x03, 0x01,
343 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
344 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, 0x99, 0xc4,
345 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
346 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
347 0x16, 0x80, 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59,
348 0x99, 0xc4, 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
349 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
350 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x71, 0x10, 0x3c, 0x89, 0xd5,
351 0xc0, 0x00, 0xdc, 0x36, 0x1d, 0x93, 0xaa, 0xab, 0x4a, 0xb6, 0xfa, 0xa8, 0x5b, 0x89, 0x1c, 0xb3,
352 0x4a, 0x04, 0x2e, 0xb3, 0x25, 0x0f, 0x12, 0x07, 0x29, 0x70, 0x3d, 0x34, 0xd1, 0xdd, 0x7e, 0x30,
353 0xfd, 0xf5, 0xfa, 0x94, 0xf4, 0xcb, 0xdb, 0xac, 0x1b, 0xed, 0xe5, 0x11, 0x4a, 0xc8, 0xab, 0x26,
354 0xe2, 0x41, 0xcb, 0xa5, 0x74, 0x4b, 0xe1, 0xd2, 0xf3, 0x83, 0x1c, 0x7a, 0xcb, 0x29, 0xd9, 0xd2,
355 0xa6, 0x9d, 0x08, 0x95, 0x73, 0x63, 0xe2, 0x9c, 0xeb, 0xa5, 0x82, 0x8b, 0x6c, 0xf4, 0x64, 0x98,
356 0x03, 0x53, 0x91, 0x35, 0x04, 0x89, 0x25, 0xa0, 0x1f, 0xdc, 0x42, 0xf7, 0x59, 0x44, 0x63, 0x75,
357 0xe6, 0x49, 0x10, 0x66, 0x0f, 0x08, 0x07, 0x39, 0xc4, 0x3e, 0x1f, 0xba, 0x30, 0x42, 0xf8, 0x7a,
358 0xc8, 0xbe, 0x6f, 0xdb, 0xec, 0x16, 0xb2, 0x76, 0x84, 0x2c, 0x6e, 0x20, 0xd1, 0xbd, 0xd5, 0x90,
359 0x22, 0x0a, 0x90, 0x5c, 0x70, 0x47, 0xc9, 0x2d, 0xe3, 0x77, 0x74, 0xfd, 0xbb, 0x85, 0x1a, 0xd8,
360 0x5c, 0x38, 0x94, 0x4c, 0x83, 0x28, 0x23, 0xa5, 0x4f, 0x55, 0x5f, 0xe3, 0x42, 0x80, 0x10, 0xd4,
361 0xa5, 0x8d, 0xcf, 0x8b, 0x53, 0x69, 0x6d, 0xc5, 0x37, 0xd2, 0xfa, 0xbb, 0xc0, 0x5a, 0xab, 0x6f,
362 0x71, 0x37, 0x92, 0xd4, 0x90, 0xef, 0x5d, 0xf1, 0xc3, 0xb8, 0x64, 0x08, 0xd3, 0xba, 0x36, 0x69,
363 0x2b, 0x00, 0xed, 0xad, 0x36, 0x21, 0x38, 0xdf, 0x4a, 0xc6, 0x44, 0xc4, 0x6b, 0xd8, 0xb0, 0x7f,
364 0x67, 0x05, 0xaa, 0x6f, 0x9e, 0x8a, 0xf1, 0x81, 0x95, 0x99, 0xb9, 0x56, 0xf4, 0x73, 0xa7, 0xb4,
365 0x19, 0xb9, 0x4b, 0xb8, 0x1d, 0x10, 0xa5, 0x88, 0x7c, 0x39, 0xa3, 0x85, 0xe7, 0xba, 0x65, 0x86,
366 0xca, 0xf7, 0x0e, 0xe0, 0x0d, 0x73, 0x3f, 0xea, 0x98, 0x88, 0x58, 0x73, 0xfa, 0x68, 0x5b, 0xaa,
367 0x8c, 0xfd, 0x3e, 0x22, 0x3e, 0x92, 0xc7, 0xe2, 0x77, 0x14, 0x81, 0xe6, 0xd9, 0xdc, 0xc1, 0xe9,
368 0xc0, 0x06, 0x57, 0xb4, 0xca, 0xb6, 0x14, 0x15, 0x16, 0x80, 0x7e, 0xc5, 0x11, 0xa4, 0x05, 0x66,
369 0xad, 0x1d, 0xa3, 0xb6, 0xab, 0x2a, 0xbe, 0xd0, 0x52, 0x4e, 0x9e, 0x84, 0x61, 0x6b, 0xf4, 0x34,
370 0x23, 0x94, 0x24, 0xc6, 0xc8, 0xb0, 0x94, 0x22, 0x4c, 0x3b, 0xac, 0x85, 0xe3, 0xd4, 0xf7, 0x38,
371 0xe5, 0x9a, 0x76, 0xb3, 0x1b, 0xf0, 0xbc, 0x78, 0xc6, 0x6f, 0x11, 0xb3, 0x1a, 0x5c, 0x4f, 0x07,
372 0x52, 0x06, 0x92, 0x7a, 0x25, 0x86, 0x91, 0x71, 0x8a, 0xf4, 0x03, 0xce, 0x19, 0x0d, 0xfc, 0xde,
373 0x8f, 0xc9, 0x4e, 0x84, 0xf1, 0x17, 0x18, 0x6f, 0x37, 0x56, 0xb9, 0x76, 0x7e, 0x8f, 0xca, 0xde,
374 0xd4, 0x1b, 0x2d, 0x8d, 0xcf, 0x12, 0x9f, 0xf9, 0xb9, 0x8b, 0x82, 0x8f, 0x4d, 0xb7, 0x63, 0x26,
375 0x8d, 0xda, 0x35, 0x94, 0x18, 0xf9, 0x55, 0xca, 0x39, 0x09, 0xe9, 0x62, 0xe1, 0x00, 0xd8, 0x67,
376 0xed, 0x5e, 0x84, 0xc2, 0xe5, 0x8e, 0x46, 0x57, 0xa4, 0xa7, 0x17, 0x70, 0xcf, 0x6d, 0xdf, 0x43,
377 0x64, 0x2b, 0x36, 0xe6, 0xf3, 0xc1, 0x4c, 0x7a, 0x7e, 0x9e, 0x47, 0xc4, 0x14, 0x82, 0xbe, 0x94,
378 0x73, 0x54, 0xd0, 0x2c, 0xc2, 0x31, 0xc6, 0xd5, 0xc3, 0xd7, 0xa9, 0xef, 0x11, 0x24, 0x2f, 0xd0,
379 0x5b, 0xb8, 0x6a, 0x8e, 0x3c, 0xb7, 0x4b, 0x00, 0x9b, 0xc1, 0xca, 0x00, 0x6f, 0xd4, 0x73, 0x93,
380 0x2e, 0x39, 0x37, 0x2a, 0x73, 0x44, 0x9b, 0x1b, 0x05, 0x1a, 0x7c, 0x2f, 0xc9, 0x2b, 0x37, 0xf3,
381 0xcd, 0x8c, 0x4e, 0xc2, 0x7a, 0x6e, 0xd9, 0xd4, 0xf1, 0x8d, 0x6d, 0x07, 0x4b, 0xb5, 0x09, 0xb9,
382 0x48, 0x55, 0xac, 0xc6, 0x7e, 0xbc, 0xc6, 0x76, 0xeb, 0x5f, 0x0f
386 static NSDictionary* VerifyMessage(CFDataRef message, SecPolicyRef policy, CFDataRef cert_data)
388 NSDictionary* result = nil;
390 SecTrustRef trustRef = NULL;
391 CFDataRef payload = NULL;
392 CFArrayRef anchors = NULL;
393 OSStatus status = noErr;
394 SecCertificateRef aCertRef = NULL;
395 SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure;
397 if (NULL == message || NULL == policy || NULL == cert_data)
402 status = SecCMSVerifyCopyDataAndAttributes(message, NULL, policy, &trustRef, &payload, NULL);
403 if (noErr != status || NULL == trustRef || NULL == payload)
408 aCertRef = SecCertificateCreateWithData(NULL, cert_data);
409 if (NULL == aCertRef)
414 anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&aCertRef, 1, &kCFTypeArrayCallBacks);
420 status = SecTrustSetAnchorCertificates(trustRef, anchors);
426 status = SecTrustEvaluate(trustRef, &trust_result);
433 if (trust_result == kSecTrustResultUnspecified)
435 // Life is good and we got back the expected result.
437 NSData* property_list_data = CFBridgingRelease(payload);
439 NSPropertyListFormat format;
440 NSError* error = nil;
441 result = [NSPropertyListSerialization propertyListWithData:property_list_data options:0 format:&format error:&error];
449 CFReleaseSafe(aCertRef)
450 CFReleaseSafe(anchors);
454 /* ==========================================================================
455 Private Methods for the OTAServiceApp class
456 ========================================================================== */
457 @interface OTAServiceApp (PrivateMethods)
458 - (void)processAssets:(NSArray*)assets;
459 - (BOOL)checkAssetVersions:(NSString *)assetDir;
460 - (BOOL)validateAsset:(NSString *)assetDir;
461 - (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names;
462 - (NSDictionary *)decodeManifest:(NSData *)manifest_file_data;
463 - (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash;
464 - (BOOL)installAssetFiles:(NSString *)assetDir;
465 - (NSString*)getCurrentAssetDirectory;
469 @implementation OTAServiceApp
471 @synthesize file_list = _file_list;
472 @synthesize manifest_file_name = _manifest_file_name;
473 @synthesize asset_version_file_name = _asset_version_file_name;
474 @synthesize current_asset_version = _current_asset_version;
475 @synthesize next_asset_version = _next_asset_version;
476 @synthesize fileManager = _fileManager;
477 @synthesize current_asset_directory = _current_asset_directory;
478 @synthesize assets_directory = _assets_directory;
480 /* --------------------------------------------------------------------------
481 OTAServiceApp init:withArguments:
483 Initialize a new instance of the OTAServiceApp class
484 -------------------------------------------------------------------------- */
485 - (id)init:(int)argc withArguments:(const char**)argv
487 if ((self = [super init]))
489 _fileManager = [NSFileManager defaultManager];
491 _manifest_file_name = (NSString *)kManifestFileName;
492 _asset_version_file_name = (NSString *)kAssetVersionFileName;
493 _file_list = [NSArray arrayWithObjects:kBlockKeyFileName, kGrayListedKeysFileName,
494 kEVRootsFileName, kCertsIndexFileName, kCertsTableFileName,
495 kManifestFileName, kAssetVersionFileName, kAppleESCertificatesName, nil];
497 _current_asset_version = nil;
498 _next_asset_version = nil;
499 _assets_directory = nil;
500 _current_asset_directory = [self getCurrentAssetDirectory];
502 /* Default interval is one hour */
503 _asset_query_retry_interval = 60.0 * 60;
507 while ((ch = getopt(argc, (char * const *)argv, "d:v")) != -1 )
515 CFTimeInterval interval = strtod(optarg, &endptr);
516 if ((interval == 0 && endptr == optarg) || errno == ERANGE) {
517 syslog(LOG_ERR, "invalid argument '%s', ignoring", optarg);
519 syslog(LOG_NOTICE, "Setting query retry interval to %f seconds", interval);
520 _asset_query_retry_interval = (CFTimeInterval)interval;
525 syslog(LOG_NOTICE, "Enabling verbose logging");
535 if (stat([kBaseAssetDirectoryPath UTF8String], &info))
537 OTAPKI_LOG("OTAServiceApp.init:withArguments: stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
539 if (mkdir([kBaseAssetDirectoryPath UTF8String], kAssetDirectoryPermission))
541 OTAPKI_LOG("OTAServiceApp.init:withArguments: mkdir of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
545 if (stat([kBaseAssetDirectoryPath UTF8String], &info))
547 OTAPKI_LOG("OTAServiceApp.init:withArguments: second stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]);
552 stat([kBaseAssetDirectoryPath UTF8String], &info);
563 #if !TARGET_IPHONE_SIMULATOR
565 - (void)registerBackgroundTaskAgentJobWithDelay:(CFTimeInterval)delay
568 * ELEs are very important, so allow asset queries on any network type and
569 * construct the job so that it will fire as soon as possible, unless we are
570 * scheduling a retry after a failure.
572 xpc_object_t job = xpc_dictionary_create(NULL, NULL, 0);
575 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowStartTime, CFAbsoluteTimeGetCurrent() + delay);
577 xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowEndTime, CFAbsoluteTimeGetCurrent() + BACKGROUND_TASK_AGENT_JOB_WINDOW_MAX_TIME_FROM_NOW_SEC);
578 xpc_dictionary_set_bool(job, kBackgroundTaskAgentNetworkRequired, true);
579 xpc_dictionary_set_bool(job, kBackgroundTaskAgentCellularAllowed, true);
580 xpc_dictionary_set_bool(job, kBackgroundTaskAgentAllowedDuringRoaming, true);
581 xpc_dictionary_set_bool(job, kBackgroundTaskAgentPowerOptLevel, kBackgroundTaskAgentPowerDontCare);
585 char *desc = xpc_copy_description(job);
586 syslog(LOG_NOTICE, "Adding BTA job %s", desc);
589 #pragma GCC diagnostic push
590 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
591 BackgroundTaskAgentAddJob(kOTAPKIAssetToolActivity, job);
592 #pragma GCC diagnostic pop
597 /* --------------------------------------------------------------------------
598 OTAServiceApp checkInWithActivity
600 Check in with the XPC activity configured in OTAPKIAssetTool's launchd
601 plist. This activity will launch OTAPKIAssetTool every three days (with
602 some leeway decided by the system). At that time, we schedule a
603 BackgroundTaskAgent job to be notified immediately when the network is
604 available so we can perform an asset query.
605 -------------------------------------------------------------------------- */
606 - (void)checkInWithActivity
608 #if !TARGET_IPHONE_SIMULATOR
609 #pragma GCC diagnostic push
610 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
611 BackgroundTaskAgentInit("com.apple.OTAPKIAssetTool", dispatch_get_main_queue(), ^(const char *job_name, xpc_object_t job)
614 * We're doing real work at this point, so open a transaction so
615 * that the system (hopefully) won't kill us while we're busy
617 xpc_transaction_begin();
621 syslog(LOG_NOTICE, "BackgroundTaskAgent job %s fired", job_name);
624 int64_t job_status = xpc_dictionary_get_int64(job, kBackgroundTaskAgentJobStatus);
625 if (job_status == kBackgroundTaskAgentJobRequestError)
627 syslog(LOG_ERR, "Failed to create BTA job -- malformed job?");
629 else if (job_status == kBackgroundTaskAgentJobSatisfied)
633 syslog(LOG_NOTICE, "BTA job %s is satisfied -- performing asset query", job_name);
635 bool shouldReschedule = false;
636 if ([self run:&shouldReschedule] || !shouldReschedule)
640 syslog(LOG_NOTICE, "Unscheduling BTA job");
642 BackgroundTaskAgentRemoveJob(kOTAPKIAssetToolActivity);
646 syslog(LOG_NOTICE, "Asset query failed due to network error. Re-scheduling BTA job for another attempt in %f seconds.", _asset_query_retry_interval);
647 [self registerBackgroundTaskAgentJobWithDelay:_asset_query_retry_interval];
650 else if (job_status == kBackgroundTaskAgentJobUnsatisfied)
653 * We will receive this if the job expires before we get to do our
654 * work. We still want to check for new assets as soon as possible,
655 * so reschedule the job.
657 if (xpc_dictionary_get_bool(job, kBackgroundTaskAgentJobExpired))
659 [self registerBackgroundTaskAgentJobWithDelay:0];
663 xpc_transaction_end();
665 #pragma GCC diagnostic pop
668 xpc_activity_register(kOTAPKIAssetToolActivity, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity)
670 xpc_activity_state_t state = xpc_activity_get_state(activity);
674 xpc_object_t criteria = xpc_activity_copy_criteria(activity);
676 if (criteria != NULL)
678 char *desc = xpc_copy_description(criteria);
679 syslog(LOG_NOTICE, "Criteria for XPC activity %s: %s", kOTAPKIAssetToolActivity, desc);
684 syslog(LOG_NOTICE, "No critera for XPC activity %s", kOTAPKIAssetToolActivity);
688 if (state == XPC_ACTIVITY_STATE_CHECK_IN)
691 * The activity is already configured in the launchd plist, so there
692 * is nothing to do here
696 syslog(LOG_NOTICE, "Activity %s in check in state", kOTAPKIAssetToolActivity);
699 else if (state == XPC_ACTIVITY_STATE_RUN)
701 #if !TARGET_IPHONE_SIMULATOR
702 #pragma GCC diagnostic push
703 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
704 xpc_object_t job = BackgroundTaskAgentCopyJob(kOTAPKIAssetToolActivity);
705 #pragma GCC diagnostic pop
708 syslog(LOG_NOTICE, "Activity %s in run state. Scheduling BTA job for earliest network availability.", kOTAPKIAssetToolActivity);
709 [self registerBackgroundTaskAgentJobWithDelay:0];
713 syslog(LOG_NOTICE, "Already have a BTA job registered. Ignoring activity.");
717 * BackgroundTaskAgent doesn't exist on the iOS simulator, so we
718 * just directly try to find and download new assets.
720 xpc_transaction_begin();
721 bool shouldReschedule = false;
722 if (![self run:&shouldReschedule]) {
723 syslog(LOG_NOTICE, "Asset query failed%s.", shouldReschedule ? " due to network issue" : "");
725 xpc_transaction_end();
731 /* --------------------------------------------------------------------------
734 Run this program and leave. This program will currently run every 3 days,
735 with some leeway based on network availability. That will provide the
736 longest time from publisihing a change in the PKI trust setting asset and
737 having that asset be consumed by a device.
739 The program simnply ask the mobile asset daemon if there are any assets
740 to be processed with the PKITrustDataAssetType. If not this program
741 will just complete and will be re-run in 3 days. If there is an asset to
742 process then the asset will be process and then the program will complete.
744 Returns false if the operation failed. On return, shouldReschedule is set
745 to true if the operation failed due to a network error and the caller
746 should reschedule this operation at a more opportune time.
747 -------------------------------------------------------------------------- */
748 - (bool)run:(bool *)shouldReschedule
752 if (shouldReschedule != NULL) {
753 *shouldReschedule = false;
756 syslog(LOG_NOTICE, "OTAPKIAssetTool running");
757 if (![[MCProfileConnection sharedConnection] isOTAPKIUpdatesAllowed])
759 syslog(LOG_NOTICE, "OTAPKIAssetTool: OTAPKI updates are not allowed.");
763 ASAssetQuery *assetQuery = [[ASAssetQuery alloc] initWithAssetType:(NSString *)kPKITrustDataAssetType];
764 if (assetQuery == nil)
766 syslog(LOG_NOTICE, "OTAPKIAssetTool: Could not create the asset query.");
770 // Get the asset synchronously
771 NSError *error = nil;
772 NSArray *foundAssets = [assetQuery runQueryAndReturnError:&error];
773 if (nil != foundAssets)
775 [self processAssets:foundAssets];
779 syslog(LOG_NOTICE, "OTAPKIAssetTool: No assets returned from query: %s", [[error description] UTF8String]);
781 NSArray *networkErrorCodes = @[ @(ASErrorNetwork), @(ASErrorNetworkNoConnection), @(ASErrorNetworkTimedOut), @(ASErrorNetworkUnexpectedResponse) ];
782 if ([[error domain] isEqualToString:ASErrorDomain] && [networkErrorCodes containsObject:@([error code])])
784 syslog(LOG_NOTICE, "OTAPKIAssetTool: Query failed due to network error.");
785 if (shouldReschedule != NULL) {
786 *shouldReschedule = true;
796 /* --------------------------------------------------------------------------
797 OTAServiceApp processAssets:
799 If when run is called asset(s) are found they will be processed here.
800 -------------------------------------------------------------------------- */
801 - (void)processAssets:(NSArray*)assets
808 NSError* error = nil;
809 ASAsset* asset = nil;
810 int asset_version = 0;
812 for (asset in assets)
814 NSDictionary* asset_attributes = asset.attributes;
816 NSNumber* contentVersion = [asset_attributes objectForKey:@"ContentVersion"];
817 OTAPKI_LOG("In processAssets: about to check the ContentVersion\n");
818 if (nil != contentVersion)
820 asset_version = [contentVersion intValue];
821 int current_asset_version_number = (nil != _current_asset_version) ? [_current_asset_version intValue] : 0;
823 if (asset_version <= current_asset_version_number)
825 syslog(LOG_NOTICE, "OTAPKIAssetTool: content version %d is too small. Current asset version id %d",
826 asset_version, current_asset_version_number);
828 OTAPKI_LOG("In processAssets: content version is too small: current asset version is %d\nContent version is %d\n",
829 current_asset_version_number, asset_version);
837 syslog(LOG_NOTICE, "OTAPKIAssetTool: no suitable asset found");
842 // Check to see if the asset needs to be downloaded
843 if (asset.state == ASAssetStateNotPresent)
845 __block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
847 [asset setProgressHandler:^(NSDictionary *state, NSError *anError)
851 // An error occured. Signal the semaphore to bail
852 dispatch_semaphore_signal(sem);
854 else if ([[state objectForKey:@"Operation"] isEqualToString:(NSString *) @"OperationCompleted"])
856 // The download is complete. Signal the semaphore
857 dispatch_semaphore_signal(sem);
861 NSNumber* yesValue = [NSNumber numberWithBool:YES];
862 const id keys[] = {ASDownloadOptionAllow3G, ASDownloadOptionAllow4G, ASDownloadOptionPriority, ASDownloadOptionAllowBatteryPower};
863 const id values[] = {yesValue, yesValue, ASDownloadPriorityHigh, yesValue};
865 NSDictionary* options = [NSDictionary dictionaryWithObjects:values forKeys:keys count:(sizeof (keys) / sizeof(keys[0]))];
867 [asset beginDownloadWithOptions:options];
868 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
871 // Check to see if the asset is now available for processing
872 if ([asset state] == ASAssetStateInstalled)
874 // Get the asset data directory
875 NSString* assetDir = [[[asset localURL] URLByAppendingPathComponent:@"PKITrustData"] path];
878 // validate the asset.
879 OTAPKI_LOG("In processAssets: about to validateAsset\n");
880 if ([self validateAsset:assetDir])
882 OTAPKI_LOG("In processAssets: asset validated installing\n");
883 // The asset is valid so install the files
884 [self installAssetFiles:assetDir];
886 // Signal securityd to idle-exit at it's next opportunity
887 OTAPKI_LOG("In processAssets: notifying securityd\n");
889 (void)SecTrustOTAPKIGetUpdatedAsset(&didUpdate);
890 syslog(LOG_NOTICE, "OTAPKIAssetTool: installed new asset %d", asset_version);
894 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset %d did not validate", asset_version);
897 // regaurdless if the asset is valid. Now that it is
898 // installed, it needs to be purged to ensure that
899 // we can retrieve a new updated asset.
900 [asset purgeAndReturnError:&error];
904 syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset directory %s not found", [assetDir UTF8String]);
910 /* --------------------------------------------------------------------------
911 OTAServiceApp checkAssetVersions:
913 If when run is called asset(s) are found they will be processed here.
914 -------------------------------------------------------------------------- */
915 - (BOOL)checkAssetVersions:(NSString *)assetDir
919 OTAPKI_LOG("Entering checkAssetVersions\n");
921 if (nil == assetDir || nil == self.current_asset_version)
923 OTAPKI_LOG("checkAssetVersions: parameter error\n");
927 // first get the new version number from the downloaded asset
928 NSString* next_asset_version_path = [assetDir stringByAppendingPathComponent:self.asset_version_file_name];
929 if (![self.fileManager fileExistsAtPath:next_asset_version_path])
931 // The asset is missing the AssertVersion.plist
932 // This is an invalid asset
933 OTAPKI_LOG("checkAssetVersions: could not file asseet version file %s\n", [self.asset_version_file_name UTF8String]);
937 NSError* error = nil;
938 NSInputStream* input_stream = [NSInputStream inputStreamWithFileAtPath:next_asset_version_path];
940 NSDictionary* asset_dict = [NSPropertyListSerialization propertyListWithStream:input_stream options:0 format:nil error:&error];
941 [input_stream close];
945 OTAPKI_LOG("checkAssetVersions: error reading asset version file: %s\n", [[error localizedDescription] UTF8String]);
949 _next_asset_version = [asset_dict objectForKey:kVersionNumberKey];
950 if (nil == _next_asset_version)
952 OTAPKI_LOG("asset_dict did not have a entry with a key of kVersionNumberKey\n");
956 // Check the current asset version against the new asset version. The new asset version MUST be larger than the
957 // current asset version
958 NSInteger current_asset_version_value = [self.current_asset_version integerValue];
959 NSInteger next_asset_version_value = [self.next_asset_version integerValue];
961 if (next_asset_version_value <= current_asset_version_value)
963 OTAPKI_LOG("heckAssetVersions: assert version too small. current_asset_version_value = %d next_asset_version_value = %d\n",
964 current_asset_version_value, next_asset_version_value);
972 /* --------------------------------------------------------------------------
973 OTAServiceApp validateAsset:
975 Decode the manifest and verify the file hashes
976 -------------------------------------------------------------------------- */
977 - (BOOL)validateAsset:(NSString *)assetDir
981 OTAPKI_LOG("Enterning validateAsset\n");
983 if (![self validateDirectory:assetDir withFiles:self.file_list])
985 OTAPKI_LOG("validateAsset param\n");
989 NSString* manifest_file_path = [assetDir stringByAppendingPathComponent:self.manifest_file_name];
990 NSError* error = nil;
991 NSData* manifest_file_data = [NSData dataWithContentsOfFile:manifest_file_path options:0 error:&error];
994 OTAPKI_LOG("validateAsset: could not read manifest file. error = %s\n", [[error localizedDescription] UTF8String]);
998 NSDictionary* manifest_data = [self decodeManifest:manifest_file_data];
999 if (nil == manifest_data)
1001 OTAPKI_LOG("validateAsset: decodeManifest failed!\n");
1005 NSString* full_file_path = nil;
1007 for (NSString* file_name in self.file_list)
1009 if ([file_name isEqualToString:self.manifest_file_name])
1014 hash = [manifest_data objectForKey:file_name];
1017 OTAPKI_LOG("validateAsset: could not get hash for file %s\n", [file_name UTF8String]);
1021 full_file_path = [assetDir stringByAppendingPathComponent:file_name];
1022 if (![self checkFileHash:full_file_path hash:hash])
1024 OTAPKI_LOG("validateAsset: hash for file %s does not match\n", [file_name UTF8String]);
1029 result = [self checkAssetVersions:assetDir];
1033 /* --------------------------------------------------------------------------
1034 OTAServiceApp validateDirectory:withFiles:
1036 Ensure that a given directory has the files listed in the files_names
1038 -------------------------------------------------------------------------- */
1039 - (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names
1042 OTAPKI_LOG("Enterning validateDirectory\n");
1044 if (nil == assetDir || nil == file_names)
1046 OTAPKI_LOG("validateDirectory param error\n");
1049 NSError* error = nil;
1050 NSArray* dir_items = [self.fileManager contentsOfDirectoryAtPath:assetDir error:&error];
1053 OTAPKI_LOG("validateDirectory: Error calling contentsOfDirectoryAtPath: error = %s\n", [[error localizedDescription] UTF8String]);
1057 for (NSString* file_name in file_names)
1059 if (![dir_items containsObject:file_name])
1061 OTAPKI_LOG("validateDirectory: missing file %s\n", [file_name UTF8String]);
1069 /* --------------------------------------------------------------------------
1070 OTAServiceApp decodeManifest:
1072 Ensure that the asset manifest blob has it CMS signature verified
1073 -------------------------------------------------------------------------- */
1074 - (NSDictionary *)decodeManifest:(NSData *)manifest_file_data
1076 NSDictionary* result = nil;
1077 CFDataRef cert_data = NULL;
1078 CFDataRef message = NULL;
1079 SecPolicyRef policy = NULL;
1080 CFBooleanRef mgResult = NULL;
1082 OTAPKI_LOG("Enterning decodeManifest\n");
1084 if (nil == manifest_file_data)
1086 OTAPKI_LOG("decodeManifest: parameter error\n");
1090 message = CFBridgingRetain(manifest_file_data);
1092 policy = SecPolicyCreateOTAPKISigner();
1095 OTAPKI_LOG("decodeManifest: could not get the SecPolicyCreateOTAPKISigner policyRef\n");
1099 cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert));
1100 if (NULL == cert_data)
1102 OTAPKI_LOG("decodeManifest: could not kApplePKISettingsRootCACert data\n");
1106 result = VerifyMessage(message, policy, cert_data);
1110 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner success!\n");
1114 OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner failed! Checking to see if this is an internal build\n");
1116 // The first attempt did not work so check to see if this is running on an internal build.
1117 if (!MGIsQuestionValid(kMGQAppleInternalInstallCapability))
1119 OTAPKI_LOG("decodeManifest: kMGQAppleInternalInstallCapability had an error\n");
1123 mgResult = MGCopyAnswer(kMGQAppleInternalInstallCapability, NULL);
1125 if (NULL == mgResult || !CFEqual(mgResult, kCFBooleanTrue))
1127 OTAPKI_LOG("decodeManifest: Not an internal build");
1131 OTAPKI_LOG("decodeManifest: This is an internal build\n");
1133 CFReleaseNull(policy);
1134 CFReleaseNull(cert_data);
1136 policy = SecPolicyCreateTestOTAPKISigner();
1139 OTAPKI_LOG("decodeManifest: could not SecPolicyCreateTestOTAPKISigner policyRef\n");
1143 cert_data = CFDataCreate(kCFAllocatorDefault, kAppleTestPKISettingsRootCACert, sizeof(kAppleTestPKISettingsRootCACert));
1144 if (NULL == cert_data)
1146 OTAPKI_LOG("decodeManifest: could not kAppleTestPKISettingsRootCACert data\n");
1150 result = VerifyMessage(message, policy, cert_data);
1154 CFReleaseSafe(mgResult);
1155 CFReleaseSafe(message);
1156 CFReleaseSafe(policy);
1157 CFReleaseSafe(cert_data);
1161 /* --------------------------------------------------------------------------
1162 OTAServiceApp checkFileHash:hash:
1164 Ensure that the given asset file's hash is the same as in the manifest
1165 -------------------------------------------------------------------------- */
1166 - (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash
1169 if (nil == file_path || nil == hash)
1174 NSError* error = nil;
1175 NSData* file_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error];
1181 UInt8 buffer[CC_SHA256_DIGEST_LENGTH];
1182 memset(buffer, 0, CC_SHA256_DIGEST_LENGTH);
1183 CC_SHA256([file_data bytes], (CC_LONG)[file_data length], buffer);
1184 NSData* file_hash_data = [NSData dataWithBytesNoCopy:buffer length:CC_SHA256_DIGEST_LENGTH freeWhenDone:NO];
1186 result = [hash isEqualToData:file_hash_data];
1191 /* --------------------------------------------------------------------------
1192 OTAServiceApp installAssetFiles:
1194 Copy over the files into the /var/Keychains/Assets directory.
1195 -------------------------------------------------------------------------- */
1196 - (BOOL)installAssetFiles:(NSString *)assetDir
1200 OTAPKI_LOG("Entering installAssetFiles\n");
1202 if (nil == assetDir)
1204 OTAPKI_LOG("installAssetFiles: parameter error\n");
1208 if (nil == self.assets_directory)
1210 OTAPKI_LOG("installAssetFiles: no assets directory\n");
1214 // Create a temp directory to hold the new asset files.
1215 NSString* tempDir = [self.assets_directory stringByAppendingPathComponent:@"TempAssetDir"];
1216 NSError* error = nil;
1219 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1220 id keys[] = {NSFilePosixPermissions};
1222 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1];
1224 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]);
1225 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]);
1226 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid];
1227 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid];
1229 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1230 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions};
1232 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
1236 if (![self.fileManager createDirectoryAtPath:tempDir withIntermediateDirectories:YES
1237 attributes:attributes error:&error])
1239 OTAPKI_LOG("installAssetFiles: could not create directory %s\n", [tempDir UTF8String]);
1243 #ifndef NEW_LOCATION
1244 // Copy all of the asset files to the newly created directory
1245 for (NSString* file_name in self.file_list)
1247 NSString* download_assert_path = [assetDir stringByAppendingPathComponent:file_name];
1248 NSString* asset_path = [tempDir stringByAppendingPathComponent:file_name];
1249 if ([self.fileManager copyItemAtPath:download_assert_path toPath:asset_path error:&error])
1251 chown([asset_path UTF8String], self.uid, self.gid);
1255 [self.fileManager removeItemAtPath:tempDir error:nil];
1259 #endif // !NEW_LOCATION
1262 // Now that all of the files have been copied to the temp directory make a single call
1263 // to rename (move) the temp directory to be the correct version directory. This rename
1264 // allow for reducing a race conditions between this asset code and securityd.
1265 NSInteger new_version_value = [self.next_asset_version integerValue];
1266 NSString* new_version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)new_version_value];
1267 NSString* new_version_dir_path = [self.assets_directory stringByAppendingPathComponent:new_version_dir_name];
1268 if (![self.fileManager moveItemAtPath:tempDir toPath:new_version_dir_path error:&error])
1270 OTAPKI_LOG("installAssetFiles: could not move path %s\n", [tempDir UTF8String]);
1271 [self.fileManager removeItemAtPath:tempDir error:nil];
1279 /* --------------------------------------------------------------------------
1280 OTAServiceApp getCurrentAssetDirectory:
1282 Looks through the /var/Keychains/Assets directory to find latest asset
1283 version directory. If no assets have been downloaded then nil is returned
1284 and the current asset version is set to 0
1285 -------------------------------------------------------------------------- */
1286 - (NSString*)getCurrentAssetDirectory
1288 NSString* result = nil;
1291 OTAPKI_LOG("In getCurrentAssetDirectory\n");
1292 OTAPKI_LOG("getCurrentAssetDirectory: checking to see if %s exists\n", [kBaseAssetDirectoryPath UTF8String]);
1294 // Check to see if the base directory is there
1295 if (![self.fileManager fileExistsAtPath:(NSString *)kBaseAssetDirectoryPath isDirectory:&isDir] || !isDir)
1297 OTAPKI_LOG("getCurrentAssetDirectory: %s does not exists\n", [kBaseAssetDirectoryPath UTF8String]);
1298 // This might be fatal
1302 NSError* error = nil;
1303 NSInteger version_number = 0;
1304 NSInteger current_version_number = 0;
1306 OSStatus err = noErr;
1308 _assets_directory = [kBaseAssetDirectoryPath stringByAppendingPathComponent:(NSString *)kAssetDirectoryName];
1310 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]);
1312 if ([self.fileManager fileExistsAtPath:self.assets_directory isDirectory:&isDir] && isDir)
1314 OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]);
1315 NSDirectoryEnumerator* dirEnum = [self.fileManager enumeratorAtPath:self.assets_directory];
1316 [dirEnum skipDescendents];
1318 for (NSString* file in dirEnum)
1320 if ([file hasPrefix:(NSString *)kVersionDirectoryNamePrefix])
1322 NSString* version_str = [file substringFromIndex:[kVersionDirectoryNamePrefix length]];
1323 NSInteger aVersion_number = [version_str integerValue];
1324 if (aVersion_number > version_number)
1326 version_number = aVersion_number;
1334 id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1335 id keys[] = {NSFilePosixPermissions};
1337 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1];
1340 struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]);
1341 struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]);
1342 NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid];
1343 NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid];
1345 id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]};
1346 id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions};
1347 NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
1349 OTAPKI_LOG("getCurrentAssetDirectory: %s does NOT exists\n", [self.assets_directory UTF8String]);
1350 OTAPKI_LOG("getCurrentAssetDirectory: creating %s\n", [self.assets_directory UTF8String]);
1352 if (![self.fileManager createDirectoryAtPath:self.assets_directory withIntermediateDirectories:YES
1353 attributes:attributes error:&error])
1355 OTAPKI_LOG("getCurrentAssetDirectory: failed to create %s\n", [self.assets_directory UTF8String]);
1361 err = SecTrustGetOTAPKIAssetVersionNumber(&aVerNum);
1362 if (errSecSuccess == err && aVerNum > 0)
1364 current_version_number = aVerNum;
1367 if (version_number < current_version_number)
1369 OTAPKI_LOG("The largest OTA version number is smaller than the current version number. This means the system has a newer asset\n");
1370 version_number = current_version_number;
1374 OTAPKI_LOG("The largest OTA version number is equal to the current version number. The OTA asset is newer than the system asset\n");
1375 NSString* version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)version_number];
1376 result = [self.assets_directory stringByAppendingPathComponent:version_dir_name];
1379 OTAPKI_LOG("getCurrentAssetDirectory: setting version number to %d\n", version_number);
1380 _current_asset_version = [NSNumber numberWithInteger:version_number];