]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSPeerInfoV2.c
1 //
2 // SOSPeerInfoV2.c
3 // sec
4 //
5 // Created by Richard Murphy on 1/26/15.
6 //
7 //
8
9 #include <AssertMacros.h>
10 #include "SOSPeerInfoV2.h"
11 #include <Security/SecureObjectSync/SOSInternal.h>
12 #include <Security/SecureObjectSync/SOSAccountPriv.h>
13 #include <utilities/der_plist.h>
14 #include <utilities/der_plist_internal.h>
15 #include <corecrypto/ccder.h>
16 #include <utilities/der_date.h>
17
18
19 // Description Dictionary Entries Added for V2
20 CFStringRef sV2DictionaryKey = CFSTR("V2DictionaryData"); // CFData wrapper for V2 extensions
21 CFStringRef sViewsKey = CFSTR("Views"); // Array of View labels
22 CFStringRef sSerialNumberKey = CFSTR("SerialNumber");
23 CFStringRef sViewsPending = CFSTR("ViewsPending"); // Array of View labels (pending)
24
25 CFStringRef sSecurityPropertiesKey = CFSTR("SecurityProperties");
26 CFStringRef kSOSHsaCrKeyDictionary = CFSTR("HSADictionary");
27 CFStringRef sRingState = CFSTR("RingState");
28 CFStringRef sBackupKeyKey = CFSTR("BackupKey");
29 CFStringRef sEscrowRecord = CFSTR("EscrowRecord");
30
31 #if TARGET_OS_IPHONE
32
33 // need entitlement for this:
34
35 #include <MobileGestalt.h>
36
37 static CFStringRef SOSCopySerialNumberAsString(CFErrorRef *error) {
38 CFTypeRef iosAnswer = (CFStringRef) MGCopyAnswer(kMGQSerialNumber, NULL);
39 if(!iosAnswer) {
40 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("No Memory"), NULL, error);
41 }
42 return (CFStringRef) iosAnswer;
43 }
44
45 #else
46
47 #include <CoreFoundation/CoreFoundation.h>
48 #include <IOKit/IOKitLib.h>
49
50 static CFStringRef SOSCopySerialNumberAsString(CFErrorRef *error) {
51 CFStringRef serialNumber = NULL;
52 CFStringRef retval = NULL;
53
54 io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
55 require_action_quiet(platformExpert, errOut, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("No Memory"), NULL, error));
56 serialNumber = IORegistryEntryCreateCFProperty(platformExpert, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0);
57 if(serialNumber) retval = CFStringCreateCopy(kCFAllocatorDefault, serialNumber);
58 IOObjectRelease(platformExpert);
59 CFReleaseNull(serialNumber);
60 errOut:
61 return retval;
62 }
63
64 #endif
65
66 bool SOSPeerInfoSerialNumberIsSet(SOSPeerInfoRef pi) {
67 CFStringRef serial = SOSPeerInfoV2DictionaryCopyString(pi, sSerialNumberKey);
68 bool retval = (serial != NULL);
69 CFReleaseNull(serial);
70 return retval;
71 }
72
73 void SOSPeerInfoSetSerialNumber(SOSPeerInfoRef pi) {
74 CFStringRef serialNumber = SOSCopySerialNumberAsString(NULL);
75 if(serialNumber) SOSPeerInfoV2DictionarySetValue(pi, sSerialNumberKey, serialNumber);
76 CFReleaseNull(serialNumber);
77 }
78
79 const CFStringRef SOSSerialUnknown = CFSTR("Unknown");
80
81 CFStringRef SOSPeerInfoCopySerialNumber(SOSPeerInfoRef pi) {
82 CFStringRef retval = SOSPeerInfoV2DictionaryCopyString(pi, sSerialNumberKey);
83 return (retval ? retval : CFRetain(SOSSerialUnknown));
84 }
85
86 static bool SOSPeerInfoV2SanityCheck(SOSPeerInfoRef pi) {
87 if(!pi) {
88 return false;
89 }
90 if(!SOSPeerInfoVersionHasV2Data(pi)) {
91 return false;
92 }
93 return true;
94 }
95
96 static CFDataRef SOSPeerInfoGetV2Data(SOSPeerInfoRef pi) {
97 if(SOSPeerInfoV2SanityCheck(pi) == false) return NULL;
98 return asData(CFDictionaryGetValue(pi->description, sV2DictionaryKey), NULL);
99 }
100
101 static CFMutableDictionaryRef SOSCreateDictionaryFromDER(CFDataRef v2Data, CFErrorRef *error) {
102 CFMutableDictionaryRef retval = NULL;
103 CFPropertyListRef pl = NULL;
104
105 if(!v2Data) {
106 secerror("Creating raw dictionary instead of creating from DER");
107 return CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
108 }
109
110 if(CFGetTypeID(v2Data) != CFDataGetTypeID()) {
111 SOSCreateError(kSOSErrorBadFormat, CFSTR("Corrupted v2Data Item"), NULL, error);
112 goto fail;
113 }
114
115 const uint8_t *der_p = CFDataGetBytePtr(v2Data);
116 const uint8_t *der_end = CFDataGetLength(v2Data) + der_p;
117
118 der_p = der_decode_plist(NULL, kCFPropertyListImmutable, &pl, error, der_p, der_end);
119
120 if (der_p == NULL || der_p != der_end) {
121 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Dictionary DER"), NULL, error);
122 goto fail;
123 }
124
125 if (CFGetTypeID(pl) != CFDictionaryGetTypeID()) {
126 CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(pl));
127 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL,
128 CFSTR("Expected dictionary got %@"), description);
129 CFReleaseSafe(description);
130 CFReleaseSafe(pl);
131 goto fail;
132 }
133
134 retval = (CFMutableDictionaryRef) pl;
135 return retval;
136
137 fail:
138 CFReleaseNull(retval);
139 return NULL;
140 }
141
142
143 static CFDataRef SOSCreateDERFromDictionary(CFDictionaryRef di, CFErrorRef *error) {
144 size_t size = der_sizeof_plist(di, error);
145 if (size == 0) return NULL;
146 uint8_t der[size];
147 der_encode_plist(di, error, der, der+size);
148 return CFDataCreate(kCFAllocatorDefault, der, size);
149 }
150
151
152 bool SOSPeerInfoUpdateToV2(SOSPeerInfoRef pi, CFErrorRef *error) {
153 bool retval = false;
154 CFDataRef v2data = NULL;
155 if(!pi) return false;
156
157 SOSPeerInfoSetVersionNumber(pi, PEERINFO_CURRENT_VERSION);
158 CFMutableDictionaryRef v2Dictionary = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
159 CFStringRef serialNumber = SOSCopySerialNumberAsString(error);
160 if(serialNumber == NULL) {
161 secnotice("signing", "serialNumber was returned NULL\n");
162 }
163 CFMutableSetRef views = SOSViewCopyViewSet(kViewSetDefault);
164 CFMutableSetRef secproperties = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
165 if(serialNumber) CFDictionaryAddValue(v2Dictionary, sSerialNumberKey, serialNumber);
166 CFDictionaryAddValue(v2Dictionary, sViewsKey, views);
167 CFDictionaryAddValue(v2Dictionary, sSecurityPropertiesKey, secproperties);
168
169 CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR(""));
170 CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeIDSV2);
171 CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanFalse);
172 CFDictionaryAddValue(v2Dictionary, sPreferIDSFragmentation, kCFBooleanTrue);
173
174 require_action_quiet((v2data = SOSCreateDERFromDictionary(v2Dictionary, error)), out, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("No Memory"), NULL, error));
175 CFDictionaryAddValue(pi->description, sV2DictionaryKey, v2data);
176 SOSPeerInfoExpandV2Data(pi, error);
177 retval = true;
178 out:
179 CFReleaseNull(views);
180 CFReleaseNull(secproperties);
181 CFReleaseNull(v2data);
182 CFReleaseNull(v2Dictionary);
183 CFReleaseNull(serialNumber);
184 return retval;
185 }
186
187 void SOSPeerInfoPackV2Data(SOSPeerInfoRef pi) {
188 require(SOSPeerInfoV2SanityCheck(pi), errOut);
189 require_quiet(pi->v2Dictionary, errOut);
190 CFDataRef v2der = SOSCreateDERFromDictionary(pi->v2Dictionary, NULL);
191 CFDictionarySetValue(pi->description, sV2DictionaryKey, v2der);
192 CFReleaseNull(v2der);
193 errOut:
194 return;
195 }
196
197 bool SOSPeerInfoExpandV2Data(SOSPeerInfoRef pi, CFErrorRef *error) {
198 CFDataRef v2data = NULL;
199 CFMutableDictionaryRef v2Dictionary = NULL;
200
201 require_action_quiet((v2data = SOSPeerInfoGetV2Data(pi)), out, SOSCreateError(kSOSErrorDecodeFailure, CFSTR("No V2 Data in description"), NULL, error));
202 require_action_quiet((v2Dictionary = SOSCreateDictionaryFromDER(v2data, error)), out, SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Can't expand V2 Dictionary"), NULL, error));
203 CFReleaseNull(pi->v2Dictionary);
204 pi->v2Dictionary = v2Dictionary;
205 return true;
206
207 out:
208 CFReleaseNull(v2Dictionary);
209 return false;
210
211 }
212
213 void SOSPeerInfoV2DictionarySetValue(SOSPeerInfoRef pi, const void *key, const void *value) {
214 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
215 if (value == NULL)
216 CFDictionaryRemoveValue(pi->v2Dictionary, key);
217 else
218 CFDictionarySetValue(pi->v2Dictionary, key, value);
219 SOSPeerInfoPackV2Data(pi);
220 errOut:
221 return;
222 }
223
224 void SOSPeerInfoV2DictionaryRemoveValue(SOSPeerInfoRef pi, const void *key) {
225 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
226 CFDictionaryRemoveValue(pi->v2Dictionary, key);
227 SOSPeerInfoPackV2Data(pi);
228 errOut:
229 return;
230 }
231
232 bool SOSPeerInfoV2DictionaryHasBoolean(SOSPeerInfoRef pi, const void *key) {
233 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
234 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
235 if(asBoolean(value,NULL) != NULL)
236 return true;
237 errOut:
238 return false;
239 }
240
241
242 bool SOSPeerInfoV2DictionaryHasString(SOSPeerInfoRef pi, const void *key) {
243 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
244 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
245 if(asString(value,NULL) != NULL)
246 return true;
247 errOut:
248 return false;
249 }
250
251 bool SOSPeerInfoV2DictionaryHasSet(SOSPeerInfoRef pi, const void *key) {
252 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
253 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
254 if(asSet(value,NULL) != NULL)
255 return true;
256 errOut:
257 return false;
258 }
259
260 bool SOSPeerInfoV2DictionaryHasData(SOSPeerInfoRef pi, const void *key) {
261 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
262 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
263 if(asData(value,NULL) != NULL)
264 return true;
265 errOut:
266 return false;
267 }
268
269 const CFMutableStringRef SOSPeerInfoV2DictionaryCopyString(SOSPeerInfoRef pi, const void *key) {
270 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
271 CFStringRef value = asString(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
272 if(value != NULL)
273 return CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(value), value);
274 errOut:
275 return NULL;
276 }
277
278 static void SOSPeerInfoV2DictionaryWithValue(SOSPeerInfoRef pi, const void *key, void(^operation)(CFTypeRef value)) {
279 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
280 CFTypeRef value = CFRetainSafe(CFDictionaryGetValue(pi->v2Dictionary, key));
281 operation(value);
282 CFReleaseNull(value);
283 errOut:
284 return;
285 }
286
287 void SOSPeerInfoV2DictionaryWithSet(SOSPeerInfoRef pi, const void *key, void(^operation)(CFSetRef set)) {
288 SOSPeerInfoV2DictionaryWithValue(pi, key, ^(CFTypeRef value) {
289 CFSetRef set = asSet(value, NULL);
290 if (set) {
291 operation(set);
292 }
293 });
294 }
295
296 const CFMutableSetRef SOSPeerInfoV2DictionaryCopySet(SOSPeerInfoRef pi, const void *key) {
297 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
298 CFSetRef value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
299 if(value != NULL)
300 return CFSetCreateMutableCopy(kCFAllocatorDefault, CFSetGetCount(value), value);
301 errOut:
302 return NULL;
303 }
304
305 void SOSPeerInfoV2DictionaryForEachSetValue(SOSPeerInfoRef pi, const void *key, void (^action)(const void* value)) {
306 CFSetRef value = NULL;
307 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
308 value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
309
310 errOut:
311 if (value) {
312 CFSetForEach(value, action);
313 }
314 }
315
316 bool SOSPeerInfoV2DictionaryHasSetContaining(SOSPeerInfoRef pi, const void *key, const void* member) {
317 CFSetRef value = NULL;
318 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
319 value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
320 errOut:
321 return value && CFSetContainsValue(value, member);
322 }
323
324 const CFMutableDataRef SOSPeerInfoV2DictionaryCopyData(SOSPeerInfoRef pi, const void *key) {
325 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
326 CFDataRef value = asData(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
327 if(value != NULL)
328 return CFDataCreateMutableCopy(kCFAllocatorDefault, CFDataGetLength(value), value);
329 errOut:
330 return NULL;
331 }
332
333 const CFBooleanRef SOSPeerInfoV2DictionaryCopyBoolean(SOSPeerInfoRef pi, const void *key) {
334 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
335 CFBooleanRef value = asBoolean(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
336 if(value != NULL)
337 return CFRetainSafe(value);
338 errOut:
339 return NULL;
340 }
341
342 const CFMutableDictionaryRef SOSPeerInfoV2DictionaryCopyDictionary(SOSPeerInfoRef pi, const void *key) {
343 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
344 CFDictionaryRef value = asDictionary(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
345 if(value != NULL)
346 return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(value), value);
347 errOut:
348 return NULL;
349 }