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