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