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