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