5 // Created by Richard Murphy on 1/26/15.
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>
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)
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");
33 // need entitlement for this:
35 #include <MobileGestalt.h>
37 static CFStringRef
SOSCopySerialNumberAsString(CFErrorRef
*error
) {
38 CFTypeRef iosAnswer
= (CFStringRef
) MGCopyAnswer(kMGQSerialNumber
, NULL
);
40 SOSCreateError(kSOSErrorAllocationFailure
, CFSTR("No Memory"), NULL
, error
);
42 return (CFStringRef
) iosAnswer
;
47 #include <CoreFoundation/CoreFoundation.h>
48 #include <IOKit/IOKitLib.h>
50 static CFStringRef
SOSCopySerialNumberAsString(CFErrorRef
*error
) {
51 CFStringRef serialNumber
= NULL
;
52 CFStringRef retval
= NULL
;
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
);
66 bool SOSPeerInfoSerialNumberIsSet(SOSPeerInfoRef pi
) {
67 CFStringRef serial
= SOSPeerInfoV2DictionaryCopyString(pi
, sSerialNumberKey
);
68 bool retval
= (serial
!= NULL
);
69 CFReleaseNull(serial
);
73 void SOSPeerInfoSetSerialNumber(SOSPeerInfoRef pi
) {
74 CFStringRef serialNumber
= SOSCopySerialNumberAsString(NULL
);
75 if(serialNumber
) SOSPeerInfoV2DictionarySetValue(pi
, sSerialNumberKey
, serialNumber
);
76 CFReleaseNull(serialNumber
);
79 const CFStringRef SOSSerialUnknown
= CFSTR("Unknown");
81 CFStringRef
SOSPeerInfoCopySerialNumber(SOSPeerInfoRef pi
) {
82 CFStringRef retval
= SOSPeerInfoV2DictionaryCopyString(pi
, sSerialNumberKey
);
83 return (retval
? retval
: CFRetain(SOSSerialUnknown
));
86 static bool SOSPeerInfoV2SanityCheck(SOSPeerInfoRef pi
) {
90 if(!SOSPeerInfoVersionHasV2Data(pi
)) {
96 static CFDataRef
SOSPeerInfoGetV2Data(SOSPeerInfoRef pi
) {
97 if(SOSPeerInfoV2SanityCheck(pi
) == false) return NULL
;
98 return asData(CFDictionaryGetValue(pi
->description
, sV2DictionaryKey
), NULL
);
101 static CFMutableDictionaryRef
SOSCreateDictionaryFromDER(CFDataRef v2Data
, CFErrorRef
*error
) {
102 CFMutableDictionaryRef retval
= NULL
;
103 CFPropertyListRef pl
= NULL
;
106 secerror("Creating raw dictionary instead of creating from DER");
107 return CFDictionaryCreateMutable(NULL
, 2, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
110 if(CFGetTypeID(v2Data
) != CFDataGetTypeID()) {
111 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Corrupted v2Data Item"), NULL
, error
);
115 const uint8_t *der_p
= CFDataGetBytePtr(v2Data
);
116 const uint8_t *der_end
= CFDataGetLength(v2Data
) + der_p
;
118 der_p
= der_decode_plist(NULL
, kCFPropertyListImmutable
, &pl
, error
, der_p
, der_end
);
120 if (der_p
== NULL
|| der_p
!= der_end
) {
121 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Format of Dictionary DER"), NULL
, error
);
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
);
134 retval
= (CFMutableDictionaryRef
) pl
;
138 CFReleaseNull(retval
);
143 static CFDataRef
SOSCreateDERFromDictionary(CFDictionaryRef di
, CFErrorRef
*error
) {
144 size_t size
= der_sizeof_plist(di
, error
);
145 if (size
== 0) return NULL
;
147 der_encode_plist(di
, error
, der
, der
+size
);
148 return CFDataCreate(kCFAllocatorDefault
, der
, size
);
152 bool SOSPeerInfoUpdateToV2(SOSPeerInfoRef pi
, CFErrorRef
*error
) {
154 CFDataRef v2data
= NULL
;
155 if(!pi
) return false;
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");
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
);
169 CFDictionaryAddValue(v2Dictionary
, sDeviceID
, CFSTR(""));
170 CFDictionaryAddValue(v2Dictionary
, sTransportType
, SOSTransportMessageTypeIDSV2
);
171 CFDictionaryAddValue(v2Dictionary
, sPreferIDS
, kCFBooleanFalse
);
172 CFDictionaryAddValue(v2Dictionary
, sPreferIDSFragmentation
, kCFBooleanTrue
);
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
);
179 CFReleaseNull(views
);
180 CFReleaseNull(secproperties
);
181 CFReleaseNull(v2data
);
182 CFReleaseNull(v2Dictionary
);
183 CFReleaseNull(serialNumber
);
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
);
197 bool SOSPeerInfoExpandV2Data(SOSPeerInfoRef pi
, CFErrorRef
*error
) {
198 CFDataRef v2data
= NULL
;
199 CFMutableDictionaryRef v2Dictionary
= NULL
;
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
;
208 CFReleaseNull(v2Dictionary
);
213 void SOSPeerInfoV2DictionarySetValue(SOSPeerInfoRef pi
, const void *key
, const void *value
) {
214 require_quiet(SOSPeerInfoExpandV2Data(pi
, NULL
), errOut
);
216 CFDictionaryRemoveValue(pi
->v2Dictionary
, key
);
218 CFDictionarySetValue(pi
->v2Dictionary
, key
, value
);
219 SOSPeerInfoPackV2Data(pi
);
224 void SOSPeerInfoV2DictionaryRemoveValue(SOSPeerInfoRef pi
, const void *key
) {
225 require_quiet(SOSPeerInfoExpandV2Data(pi
, NULL
), errOut
);
226 CFDictionaryRemoveValue(pi
->v2Dictionary
, key
);
227 SOSPeerInfoPackV2Data(pi
);
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
)
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
)
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
)
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
)
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
);
273 return CFStringCreateMutableCopy(kCFAllocatorDefault
, CFStringGetLength(value
), value
);
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
));
282 CFReleaseNull(value
);
287 void SOSPeerInfoV2DictionaryWithSet(SOSPeerInfoRef pi
, const void *key
, void(^operation
)(CFSetRef set
)) {
288 SOSPeerInfoV2DictionaryWithValue(pi
, key
, ^(CFTypeRef value
) {
289 CFSetRef set
= asSet(value
, NULL
);
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
);
300 return CFSetCreateMutableCopy(kCFAllocatorDefault
, CFSetGetCount(value
), value
);
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
);
312 CFSetForEach(value
, action
);
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
);
321 return value
&& CFSetContainsValue(value
, member
);
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
);
328 return CFDataCreateMutableCopy(kCFAllocatorDefault
, CFDataGetLength(value
), value
);
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
);
337 return CFRetainSafe(value
);
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
);
346 return CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, CFDictionaryGetCount(value
), value
);