]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c
Security-57337.40.85.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
162 if (whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportIDS){
163 CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR(""));
164 CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeIDS);
165 CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanTrue);
166 }
167 else{
168 CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR(""));
169 CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeKVS);
170 CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanTrue);
171 }
172 require_action_quiet((v2data = SOSCreateDERFromDictionary(v2Dictionary, error)), out, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("No Memory"), NULL, error));
173 CFDictionaryAddValue(pi->description, sV2DictionaryKey, v2data);
174 //SOSPeerInfoExpandV2Data(pi, error);
175 retval = true;
176 out:
177 CFReleaseNull(views);
178 CFReleaseNull(secproperties);
179 CFReleaseNull(v2data);
180 CFReleaseNull(v2Dictionary);
181 CFReleaseNull(serialNumber);
182 return retval;
183 }
184
185 void SOSPeerInfoPackV2Data(SOSPeerInfoRef pi) {
186 require(SOSPeerInfoV2SanityCheck(pi), errOut);
187 require_quiet(pi->v2Dictionary, errOut);
188 CFDataRef v2der = SOSCreateDERFromDictionary(pi->v2Dictionary, NULL);
189 CFDictionarySetValue(pi->description, sV2DictionaryKey, v2der);
190 CFReleaseNull(v2der);
191 errOut:
192 return;
193 }
194
195 bool SOSPeerInfoExpandV2Data(SOSPeerInfoRef pi, CFErrorRef *error) {
196 CFDataRef v2data = NULL;
197 bool retval = false;
198
199 require_quiet(pi, out);
200 CFReleaseNull(pi->v2Dictionary);
201 require_action_quiet((v2data = SOSPeerInfoGetV2Data(pi)), out, SOSCreateError(kSOSErrorDecodeFailure, CFSTR("No V2 Data in description"), NULL, error));
202 require_action_quiet((pi->v2Dictionary = SOSCreateDictionaryFromDER(v2data, error)), out, SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Can't expand V2 Dictionary"), NULL, error));
203 retval = true;
204 out:
205 return retval;
206 }
207
208 void SOSPeerInfoV2DictionarySetValue(SOSPeerInfoRef pi, const void *key, const void *value) {
209 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
210 if (value == NULL)
211 CFDictionaryRemoveValue(pi->v2Dictionary, key);
212 else
213 CFDictionarySetValue(pi->v2Dictionary, key, value);
214 SOSPeerInfoPackV2Data(pi);
215 errOut:
216 return;
217 }
218
219 void SOSPeerInfoV2DictionaryRemoveValue(SOSPeerInfoRef pi, const void *key) {
220 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
221 CFDictionaryRemoveValue(pi->v2Dictionary, key);
222 SOSPeerInfoPackV2Data(pi);
223 errOut:
224 return;
225 }
226
227 bool SOSPeerInfoV2DictionaryHasBoolean(SOSPeerInfoRef pi, const void *key) {
228 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
229 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
230 if(asBoolean(value,NULL) != NULL)
231 return true;
232 errOut:
233 return false;
234 }
235
236
237 bool SOSPeerInfoV2DictionaryHasString(SOSPeerInfoRef pi, const void *key) {
238 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
239 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
240 if(asString(value,NULL) != NULL)
241 return true;
242 errOut:
243 return false;
244 }
245
246 bool SOSPeerInfoV2DictionaryHasSet(SOSPeerInfoRef pi, const void *key) {
247 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
248 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
249 if(asSet(value,NULL) != NULL)
250 return true;
251 errOut:
252 return false;
253 }
254
255 bool SOSPeerInfoV2DictionaryHasData(SOSPeerInfoRef pi, const void *key) {
256 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
257 CFTypeRef value = CFDictionaryGetValue(pi->v2Dictionary, key);
258 if(asData(value,NULL) != NULL)
259 return true;
260 errOut:
261 return false;
262 }
263
264 const CFMutableStringRef SOSPeerInfoV2DictionaryCopyString(SOSPeerInfoRef pi, const void *key) {
265 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
266 CFStringRef value = asString(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
267 if(value != NULL)
268 return CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(value), value);
269 errOut:
270 return NULL;
271 }
272
273 static void SOSPeerInfoV2DictionaryWithValue(SOSPeerInfoRef pi, const void *key, void(^operation)(CFTypeRef value)) {
274 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
275 CFTypeRef value = CFRetainSafe(CFDictionaryGetValue(pi->v2Dictionary, key));
276 operation(value);
277 CFReleaseNull(value);
278 errOut:
279 return;
280 }
281
282 void SOSPeerInfoV2DictionaryWithSet(SOSPeerInfoRef pi, const void *key, void(^operation)(CFSetRef set)) {
283 SOSPeerInfoV2DictionaryWithValue(pi, key, ^(CFTypeRef value) {
284 CFSetRef set = asSet(value, NULL);
285 if (set) {
286 operation(set);
287 }
288 });
289 }
290
291 const CFMutableSetRef SOSPeerInfoV2DictionaryCopySet(SOSPeerInfoRef pi, const void *key) {
292 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
293 CFSetRef value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
294 if(value != NULL)
295 return CFSetCreateMutableCopy(kCFAllocatorDefault, CFSetGetCount(value), value);
296 errOut:
297 return NULL;
298 }
299
300 void SOSPeerInfoV2DictionaryForEachSetValue(SOSPeerInfoRef pi, const void *key, void (^action)(const void* value)) {
301 CFSetRef value = NULL;
302 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
303 value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
304
305 errOut:
306 if (value) {
307 CFSetForEach(value, action);
308 }
309 }
310
311 bool SOSPeerInfoV2DictionaryHasSetContaining(SOSPeerInfoRef pi, const void *key, const void* member) {
312 CFSetRef value = NULL;
313 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
314 value = asSet(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
315 errOut:
316 return value && CFSetContainsValue(value, member);
317 }
318
319 const CFMutableDataRef SOSPeerInfoV2DictionaryCopyData(SOSPeerInfoRef pi, const void *key) {
320 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
321 CFDataRef value = asData(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
322 if(value != NULL)
323 return CFDataCreateMutableCopy(kCFAllocatorDefault, CFDataGetLength(value), value);
324 errOut:
325 return NULL;
326 }
327
328 const CFBooleanRef SOSPeerInfoV2DictionaryCopyBoolean(SOSPeerInfoRef pi, const void *key) {
329 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
330 CFBooleanRef value = asBoolean(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
331 if(value != NULL)
332 return CFRetainSafe(value);
333 errOut:
334 return NULL;
335 }
336
337 const CFMutableDictionaryRef SOSPeerInfoV2DictionaryCopyDictionary(SOSPeerInfoRef pi, const void *key) {
338 require_quiet(SOSPeerInfoExpandV2Data(pi, NULL), errOut);
339 CFDictionaryRef value = asDictionary(CFDictionaryGetValue(pi->v2Dictionary, key), NULL);
340 if(value != NULL)
341 return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(value), value);
342 errOut:
343 return NULL;
344 }