]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c
Security-57337.20.44.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 static bool SOSPeerInfoV2SanityCheck(SOSPeerInfoRef pi) {
80 if(!pi) {
81 return false;
82 }
83 if(!SOSPeerInfoVersionHasV2Data(pi)) {
84 return false;
85 }
86 return true;
87 }
88
89 static CFDataRef SOSPeerInfoGetV2Data(SOSPeerInfoRef pi) {
90 if(SOSPeerInfoV2SanityCheck(pi) == false) return NULL;
91 return CFDictionaryGetValue(pi->description, sV2DictionaryKey);
92 }
93
94 static CFMutableDictionaryRef SOSCreateDictionaryFromDER(CFDataRef v2Data, CFErrorRef *error) {
95 CFMutableDictionaryRef retval = NULL;
96 CFPropertyListRef pl = NULL;
97
98 if(!v2Data) {
99 secerror("Creating raw dictionary instead of creating from DER");
100 return CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
101 }
102
103 if(CFGetTypeID(v2Data) != CFDataGetTypeID()) {
104 SOSCreateError(kSOSErrorBadFormat, CFSTR("Corrupted v2Data Item"), NULL, error);
105 goto fail;
106 }
107
108 const uint8_t *der_p = CFDataGetBytePtr(v2Data);
109 const uint8_t *der_end = CFDataGetLength(v2Data) + der_p;
110
111 der_p = der_decode_plist(NULL, kCFPropertyListImmutable, &pl, error, der_p, der_end);
112
113 if (der_p == NULL || der_p != der_end) {
114 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Dictionary DER"), NULL, error);
115 goto fail;
116 }
117
118 if (CFGetTypeID(pl) != CFDictionaryGetTypeID()) {
119 CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(pl));
120 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL,
121 CFSTR("Expected dictionary got %@"), description);
122 CFReleaseSafe(description);
123 CFReleaseSafe(pl);
124 goto fail;
125 }
126
127 retval = (CFMutableDictionaryRef) pl;
128 return retval;
129
130 fail:
131 CFReleaseNull(retval);
132 return NULL;
133 }
134
135
136 static CFDataRef SOSCreateDERFromDictionary(CFDictionaryRef di, CFErrorRef *error) {
137 size_t size = der_sizeof_plist(di, error);
138 if (size == 0) return NULL;
139 uint8_t der[size];
140 der_encode_plist(di, error, der, der+size);
141 return CFDataCreate(kCFAllocatorDefault, der, size);
142 }
143
144
145 bool SOSPeerInfoUpdateToV2(SOSPeerInfoRef pi, CFErrorRef *error) {
146 bool retval = false;
147 CFDataRef v2data = NULL;
148 if(!pi) return false;
149
150 SOSPeerInfoSetVersionNumber(pi, PEERINFO_CURRENT_VERSION);
151 CFMutableDictionaryRef v2Dictionary = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
152 CFStringRef serialNumber = SOSCopySerialNumberAsString(error);
153 if(serialNumber == NULL) {
154 secnotice("signing", "serialNumber was returned NULL\n");
155 }
156 CFMutableSetRef views = SOSViewsCreateDefault(false, error);
157 CFMutableSetRef secproperties = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
158 if(serialNumber) CFDictionaryAddValue(v2Dictionary, sSerialNumberKey, serialNumber);
159 CFDictionaryAddValue(v2Dictionary, sViewsKey, views);
160 CFDictionaryAddValue(v2Dictionary, sSecurityPropertiesKey, secproperties);
161 if(whichTransportType == kSOSTransportPresent){
162 CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR(""));
163 CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeKVS);
164 CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanTrue);
165 }
166 else if (whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportIDS){
167 CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR(""));
168 CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeIDS);
169 CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanTrue);
170 }
171 require_action_quiet((v2data = SOSCreateDERFromDictionary(v2Dictionary, error)), out, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("No Memory"), NULL, error));
172 CFDictionaryAddValue(pi->description, sV2DictionaryKey, v2data);
173 //SOSPeerInfoExpandV2Data(pi, error);
174 retval = true;
175 out:
176 CFReleaseNull(views);
177 CFReleaseNull(secproperties);
178 CFReleaseNull(v2data);
179 CFReleaseNull(v2Dictionary);
180 CFReleaseNull(serialNumber);
181 return retval;
182 }
183
184 void SOSPeerInfoPackV2Data(SOSPeerInfoRef pi) {
185 require(SOSPeerInfoV2SanityCheck(pi), errOut);
186 require_quiet(pi->v2Dictionary, errOut);
187 CFDataRef v2der = SOSCreateDERFromDictionary(pi->v2Dictionary, NULL);
188 CFDictionarySetValue(pi->description, sV2DictionaryKey, v2der);
189 CFReleaseNull(v2der);
190 errOut:
191 return;
192 }
193
194 bool SOSPeerInfoExpandV2Data(SOSPeerInfoRef pi, CFErrorRef *error) {
195 CFDataRef v2data = NULL;
196 bool retval = false;
197
198 require_quiet(pi, out);
199 CFReleaseNull(pi->v2Dictionary);
200 require_action_quiet((v2data = SOSPeerInfoGetV2Data(pi)), out, SOSCreateError(kSOSErrorDecodeFailure, CFSTR("No V2 Data in description"), NULL, error));
201 require_action_quiet((pi->v2Dictionary = SOSCreateDictionaryFromDER(v2data, error)), out, SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Can't expand V2 Dictionary"), NULL, error));
202 retval = true;
203 out:
204 return retval;
205 }
206
207 void SOSPeerInfoV2DictionarySetValue(SOSPeerInfoRef pi, const void *key, const void *value) {
208 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
209 if (value == NULL)
210 CFDictionaryRemoveValue(pi->v2Dictionary, key);
211 else
212 CFDictionarySetValue(pi->v2Dictionary, key, value);
213 SOSPeerInfoPackV2Data(pi);
214 errOut:
215 return;
216 }
217
218 void SOSPeerInfoV2DictionaryRemoveValue(SOSPeerInfoRef pi, const void *key) {
219 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
220 CFDictionaryRemoveValue(pi->v2Dictionary, key);
221 SOSPeerInfoPackV2Data(pi);
222 errOut:
223 return;
224 }
225
226 bool SOSPeerInfoV2DictionaryHasBoolean(SOSPeerInfoRef pi, const void *key) {
227 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
228 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
229 if(asBoolean(value,NULL) != NULL)
230 return true;
231 errOut:
232 return false;
233 }
234
235
236 bool SOSPeerInfoV2DictionaryHasString(SOSPeerInfoRef pi, const void *key) {
237 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
238 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
239 if(asString(value,NULL) != NULL)
240 return true;
241 errOut:
242 return false;
243 }
244
245 bool SOSPeerInfoV2DictionaryHasSet(SOSPeerInfoRef pi, const void *key) {
246 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
247 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
248 if(asSet(value,NULL) != NULL)
249 return true;
250 errOut:
251 return false;
252 }
253
254 bool SOSPeerInfoV2DictionaryHasData(SOSPeerInfoRef pi, const void *key) {
255 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
256 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
257 if(asData(value,NULL) != NULL)
258 return true;
259 errOut:
260 return false;
261 }
262
263 const CFMutableStringRef SOSPeerInfoV2DictionaryCopyString(SOSPeerInfoRef pi, const void *key) {
264 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
265 CFStringRef value = asString(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
266 if(value != NULL)
267 return CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(value), value);
268 errOut:
269 return NULL;
270 }
271
272 static void SOSPeerInfoV2DictionaryWithValue(SOSPeerInfoRef pi, const void *key, void(^operation)(CFTypeRef value)) {
273 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
274 CFTypeRef value = CFRetainSafe(CFDictionaryGetValue(pi->v2Dictionary, key));
275 operation(value);
276 CFReleaseNull(value);
277 errOut:
278 return;
279 }
280
281 void SOSPeerInfoV2DictionaryWithSet(SOSPeerInfoRef pi, const void *key, void(^operation)(CFSetRef set)) {
282 SOSPeerInfoV2DictionaryWithValue(pi, key, ^(CFTypeRef value) {
283 CFSetRef set = asSet(value, NULL);
284 if (set) {
285 operation(set);
286 }
287 });
288 }
289
290 const CFMutableSetRef SOSPeerInfoV2DictionaryCopySet(SOSPeerInfoRef pi, const void *key) {
291 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
292 CFSetRef value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
293 if(value != NULL)
294 return CFSetCreateMutableCopy(kCFAllocatorDefault, CFSetGetCount(value), value);
295 errOut:
296 return NULL;
297 }
298
299 void SOSPeerInfoV2DictionaryForEachSetValue(SOSPeerInfoRef pi, const void *key, void (^action)(const void* value)) {
300 CFSetRef value = NULL;
301 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
302 value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
303
304 errOut:
305 if (value) {
306 CFSetForEach(value, action);
307 }
308 }
309
310 bool SOSPeerInfoV2DictionaryHasSetContaining(SOSPeerInfoRef pi, const void *key, const void* member) {
311 CFSetRef value = NULL;
312 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
313 value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
314 errOut:
315 return value && CFSetContainsValue(value, member);
316 }
317
318 const CFMutableDataRef SOSPeerInfoV2DictionaryCopyData(SOSPeerInfoRef pi, const void *key) {
319 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
320 CFDataRef value = asData(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
321 if(value != NULL)
322 return CFDataCreateMutableCopy(kCFAllocatorDefault, CFDataGetLength(value), value);
323 errOut:
324 return NULL;
325 }
326
327 const CFBooleanRef SOSPeerInfoV2DictionaryCopyBoolean(SOSPeerInfoRef pi, const void *key) {
328 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
329 CFBooleanRef value = asBoolean(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
330 if(value != NULL)
331 return CFRetainSafe(value);
332 errOut:
333 return NULL;
334 }
335
336 const CFMutableDictionaryRef SOSPeerInfoV2DictionaryCopyDictionary(SOSPeerInfoRef pi, const void *key) {
337 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
338 CFDictionaryRef value = asDictionary(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
339 if(value != NULL)
340 return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(value), value);
341 errOut:
342 return NULL;
343 }