2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <AssertMacros.h>
26 #include <TargetConditionals.h>
28 #include <Security/SecureObjectSync/SOSPeerInfo.h>
29 #include <Security/SecureObjectSync/SOSPeerInfoInternal.h>
30 #include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
31 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
32 #include <Security/SecureObjectSync/SOSCircle.h>
33 #include <Security/SecureObjectSync/SOSAccountPriv.h>
34 #include <Security/SecureObjectSync/SOSInternal.h>
35 #include <ipc/securityd_client.h>
37 #include <CoreFoundation/CFArray.h>
38 #include <dispatch/dispatch.h>
43 #include <utilities/SecCFWrappers.h>
44 #include <utilities/SecCFRelease.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/SecXPCError.h>
48 #include <utilities/der_plist.h>
49 #include <utilities/der_plist_internal.h>
50 #include <corecrypto/ccder.h>
51 #include <utilities/der_date.h>
53 #include <corecrypto/ccdigest.h>
54 #include <corecrypto/ccsha2.h>
57 #include <CoreFoundation/CoreFoundation.h>
58 #include <CoreFoundation/CFDate.h>
62 #if TARGET_OS_IPHONE || TARGET_OS_EMBEDDED
63 #include <MobileGestalt.h>
66 #include <Security/SecBase64.h>
67 #include <Security/SecKeyPriv.h>
68 #include <Security/SecOTR.h>
69 #include <Security/SecuritydXPC.h>
71 CFGiblisWithHashFor(SOSPeerInfo
);
74 const CFStringRef kPIUserDefinedDeviceNameKey
= CFSTR("ComputerName");
75 const CFStringRef kPIDeviceModelNameKey
= CFSTR("ModelName");
76 const CFStringRef kPIMessageProtocolVersionKey
= CFSTR("MessageProtocolVersion");
77 const CFStringRef kPIOSVersionKey
= CFSTR("OSVersion");
79 // Description Dictionary Entries
80 static CFStringRef sPublicKeyKey
= CFSTR("PublicSigningKey");
81 const CFStringRef sGestaltKey
= CFSTR("DeviceGestalt");
82 const CFStringRef sVersionKey
= CFSTR("ConflictVersion");
83 static CFStringRef sCloudIdentityKey
= CFSTR("CloudIdentity");
84 static CFStringRef sApplicationDate
= CFSTR("ApplicationDate");
85 static CFStringRef sApplicationUsig
= CFSTR("ApplicationUsig");
86 static CFStringRef sRetirementDate
= CFSTR("RetirementDate");
89 CFStringRef kSOSPeerInfoDescriptionKey
= CFSTR("SOSPeerInfoDescription");
90 CFStringRef kSOSPeerInfoSignatureKey
= CFSTR("SOSPeerInfoSignature");
91 CFStringRef kSOSPeerInfoNameKey
= CFSTR("SOSPeerInfoName");
93 //Peer Info V2 Dictionary IDS keys
94 CFStringRef sPreferIDS
= CFSTR("PreferIDS");
95 CFStringRef sPreferIDSFragmentation
= CFSTR("PreferIDFragmentation");
96 CFStringRef sPreferIDSACKModel
= CFSTR("PreferIDSAckModel");
97 CFStringRef sTransportType
= CFSTR("TransportType");
98 CFStringRef sDeviceID
= CFSTR("DeviceID");
100 const CFStringRef peerIDLengthKey
= CFSTR("idLength");
102 SOSPeerInfoRef
SOSPeerInfoAllocate(CFAllocatorRef allocator
) {
103 return CFTypeAllocate(SOSPeerInfo
, struct __OpaqueSOSPeerInfo
, allocator
);
106 SecKeyRef
SOSPeerInfoCopyPubKey(SOSPeerInfoRef peer
, CFErrorRef
* error
) {
107 SecKeyRef result
= NULL
;
109 CFDataRef pubKeyBytes
= asData(CFDictionaryGetValue(peer
->description
, sPublicKeyKey
), error
);
110 require_quiet(pubKeyBytes
, fail
);
112 CFAllocatorRef allocator
= CFGetAllocator(peer
);
113 result
= SecKeyCreateFromPublicData(allocator
, kSecECDSAAlgorithmID
, pubKeyBytes
);
115 require_quiet(SecAllocationError(result
, error
, CFSTR("Failed to create public key from data %@"), pubKeyBytes
), fail
);
121 CFDataRef
SOSPeerInfoGetAutoAcceptInfo(SOSPeerInfoRef peer
) {
122 CFDataRef pubKeyBytes
= NULL
;
124 pubKeyBytes
= CFDictionaryGetValue(peer
->description
, sPublicKeyKey
);
125 if (!pubKeyBytes
|| CFGetTypeID(pubKeyBytes
) != CFDataGetTypeID()) {
132 static bool SOSDescriptionHash(SOSPeerInfoRef peer
, const struct ccdigest_info
*di
, void *hashresult
, CFErrorRef
*error
) {
133 ccdigest_di_decl(di
, ctx
);
134 ccdigest_init(di
, ctx
);
136 if(!SOSPeerInfoUpdateDigestWithDescription(peer
, di
, ctx_p
, error
)) return false;
137 ccdigest_final(di
, ctx
, hashresult
);
143 static CFDataRef
sosCopySignedHash(SecKeyRef privkey
, const struct ccdigest_info
*di
, uint8_t *hbuf
) {
145 size_t siglen
= SIGLEN
;
147 if((stat
= SecKeyRawSign(privkey
, kSecPaddingNone
, hbuf
, di
->output_size
, sig
, &siglen
)) != 0) {
150 return CFDataCreate(NULL
, sig
, (CFIndex
)siglen
);
153 static bool sosVerifyHash(SecKeyRef pubkey
, const struct ccdigest_info
*di
, uint8_t *hbuf
, CFDataRef signature
) {
154 return SecKeyRawVerify(pubkey
, kSecPaddingNone
, hbuf
, di
->output_size
,
155 CFDataGetBytePtr(signature
), CFDataGetLength(signature
)) == errSecSuccess
;
158 bool SOSPeerInfoSign(SecKeyRef privKey
, SOSPeerInfoRef peer
, CFErrorRef
*error
) {
160 const struct ccdigest_info
*di
= ccsha256_di();
161 uint8_t hbuf
[di
->output_size
];
162 CFDataRef newSignature
= NULL
;
164 require_action_quiet(SOSDescriptionHash(peer
, di
, hbuf
, error
), fail
,
165 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Failed to hash description for peer"), NULL
, error
));
167 newSignature
= sosCopySignedHash(privKey
, di
, hbuf
);
168 require_action_quiet(newSignature
, fail
, SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Failed to sign peerinfo for peer"), NULL
, error
));
170 CFReleaseNull(peer
->signature
);
171 peer
->signature
= newSignature
;
176 CFReleaseNull(newSignature
);
180 // Return true (1) if the signature verifies.
181 bool SOSPeerInfoVerify(SOSPeerInfoRef peer
, CFErrorRef
*error
) {
183 const struct ccdigest_info
*di
= ccsha256_di();
184 uint8_t hbuf
[di
->output_size
];
186 SecKeyRef pubKey
= SOSPeerInfoCopyPubKey(peer
, error
);
187 require_quiet(pubKey
, error_out
);
189 require_quiet(SOSDescriptionHash(peer
, di
, hbuf
, error
), error_out
);
191 require_action_quiet(sosVerifyHash(pubKey
, di
, hbuf
, peer
->signature
), error_out
,
192 SOSErrorCreate(kSOSErrorBadSignature
, error
, NULL
,
193 CFSTR("Signature didn't verify for %@"), peer
));
197 CFReleaseNull(pubKey
);
201 void SOSPeerInfoSetVersionNumber(SOSPeerInfoRef pi
, int version
) {
202 pi
->version
= version
;
203 CFNumberRef versionNumber
= CFNumberCreateWithCFIndex(NULL
, pi
->version
);
204 CFDictionarySetValue(pi
->description
, sVersionKey
, versionNumber
);
205 CFReleaseNull(versionNumber
);
208 static SOSPeerInfoRef
SOSPeerInfoCreate_Internal(CFAllocatorRef allocator
,
209 CFDictionaryRef gestalt
, CFDataRef backup_key
,
210 CFStringRef IDSID
, CFStringRef transportType
, CFBooleanRef preferIDS
,
211 CFBooleanRef preferFragmentation
, CFBooleanRef preferAckModel
,
212 CFSetRef enabledViews
,
213 SecKeyRef signingKey
, CFErrorRef
* error
,
214 void (^ description_modifier
)(CFMutableDictionaryRef description
)) {
215 SOSPeerInfoRef pi
= CFTypeAllocate(SOSPeerInfo
, struct __OpaqueSOSPeerInfo
, allocator
);
216 pi
->gestalt
= gestalt
;
217 CFRetain(pi
->gestalt
);
219 pi
->version
= SOSPeerInfoGetPeerProtocolVersion(pi
);
220 CFDataRef publicBytes
= NULL
;
221 CFNumberRef versionNumber
= NULL
;
223 SecKeyRef publicKey
= SecKeyCreatePublicFromPrivate(signingKey
);
224 if (publicKey
== NULL
) {
225 SOSCreateError(kSOSErrorBadKey
, CFSTR("Unable to get public"), NULL
, error
);
230 OSStatus result
= SecKeyCopyPublicBytes(publicKey
, &publicBytes
);
232 if (result
!= errSecSuccess
) {
233 SOSCreateError(kSOSErrorBadKey
, CFSTR("Failed to export public bytes"), NULL
, error
);
238 pi
->signature
= CFDataCreateMutable(allocator
, 0);
240 versionNumber
= CFNumberCreateWithCFIndex(NULL
, pi
->version
);
242 pi
->description
= CFDictionaryCreateMutableForCFTypesWith(allocator
,
243 sVersionKey
, versionNumber
,
244 sPublicKeyKey
, publicBytes
,
245 sGestaltKey
, pi
->gestalt
,
249 description_modifier(pi
->description
);
252 pi
->id
= SOSCopyIDOfKey(publicKey
, error
);
253 CFReleaseNull(publicKey
);
255 require_quiet(pi
->id
, exit
);
257 // ================ V2 Additions Start
259 if(!SOSPeerInfoUpdateToV2(pi
, error
)) {
264 // V2DictionarySetValue handles NULL as remove
265 if (backup_key
!= NULL
) SOSPeerInfoV2DictionarySetValue(pi
, sBackupKeyKey
, backup_key
);
266 SOSPeerInfoV2DictionarySetValue(pi
, sDeviceID
, IDSID
);
267 SOSPeerInfoV2DictionarySetValue(pi
, sTransportType
, transportType
);
268 SOSPeerInfoV2DictionarySetValue(pi
, sPreferIDS
, preferIDS
);
269 SOSPeerInfoV2DictionarySetValue(pi
, sPreferIDSFragmentation
, preferFragmentation
);
270 SOSPeerInfoV2DictionarySetValue(pi
, sPreferIDSACKModel
, preferAckModel
);
271 SOSPeerInfoV2DictionarySetValue(pi
, sViewsKey
, enabledViews
);
273 // ================ V2 Additions End
275 if (!SOSPeerInfoSign(signingKey
, pi
, error
)) {
281 CFReleaseNull(versionNumber
);
282 CFReleaseNull(publicBytes
);
286 SOSPeerInfoRef
SOSPeerInfoCreate(CFAllocatorRef allocator
, CFDictionaryRef gestalt
, CFDataRef backup_key
, SecKeyRef signingKey
, CFErrorRef
* error
) {
287 return SOSPeerInfoCreate_Internal(allocator
, gestalt
, backup_key
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, signingKey
, error
, ^(CFMutableDictionaryRef description
) {});
290 SOSPeerInfoRef
SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator
, CFDictionaryRef gestalt
, CFDataRef backup_key
,
291 CFStringRef IDSID
, CFStringRef transportType
, CFBooleanRef preferIDS
,
292 CFBooleanRef preferFragmentation
, CFBooleanRef preferAckModel
, CFSetRef enabledViews
, SecKeyRef signingKey
, CFErrorRef
* error
)
294 return SOSPeerInfoCreate_Internal(allocator
, gestalt
, backup_key
, IDSID
, transportType
, preferIDS
, preferFragmentation
, preferAckModel
, enabledViews
, signingKey
, error
, ^(CFMutableDictionaryRef description
) {});
298 SOSPeerInfoRef
SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator
, CFDictionaryRef gestalt
, SecKeyRef signingKey
, CFErrorRef
* error
) {
299 return SOSPeerInfoCreate_Internal(allocator
, gestalt
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, signingKey
, error
, ^(CFMutableDictionaryRef description
) {
300 CFDictionarySetValue(description
, sCloudIdentityKey
, kCFBooleanTrue
);
306 SOSPeerInfoRef
SOSPeerInfoCreateCopy(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFErrorRef
* error
) {
307 if(!toCopy
) return NULL
;
308 SOSPeerInfoRef pi
= CFTypeAllocate(SOSPeerInfo
, struct __OpaqueSOSPeerInfo
, allocator
);
310 pi
->description
= CFDictionaryCreateMutableCopy(allocator
, 0, toCopy
->description
);
311 pi
->signature
= CFDataCreateCopy(allocator
, toCopy
->signature
);
313 pi
->gestalt
= CFDictionaryCreateCopy(allocator
, toCopy
->gestalt
);
314 pi
->id
= CFStringCreateCopy(allocator
, toCopy
->id
);
316 pi
->version
= toCopy
->version
;
317 if(!SOSPeerInfoVersionHasV2Data(pi
)) SOSPeerInfoExpandV2Data(pi
, error
);
323 bool SOSPeerInfoVersionIsCurrent(SOSPeerInfoRef pi
) {
324 return pi
->version
>= PEERINFO_CURRENT_VERSION
;
327 bool SOSPeerInfoVersionHasV2Data(SOSPeerInfoRef pi
) {
328 return pi
->version
>= kSOSPeerV2BaseVersion
;
331 SOSPeerInfoRef
SOSPeerInfoCreateCurrentCopy(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
,
332 CFStringRef IDSID
, CFStringRef transportType
, CFBooleanRef preferIDS
, CFBooleanRef preferFragmentation
, CFBooleanRef preferAckModel
, CFSetRef enabledViews
,
333 SecKeyRef signingKey
, CFErrorRef
* error
) {
335 SOSPeerInfoRef pi
= SOSPeerInfoCreateCopy(allocator
, toCopy
, error
);
336 if(!SOSPeerInfoVersionHasV2Data(pi
)) SOSPeerInfoUpdateToV2(pi
, error
);
338 //SOSPeerInfoSetSerialNumber(pi);
341 SOSPeerInfoV2DictionarySetValue(pi
, sDeviceID
, IDSID
);
344 SOSPeerInfoV2DictionarySetValue(pi
, sTransportType
, transportType
);
347 SOSPeerInfoV2DictionarySetValue(pi
, sPreferIDS
, preferIDS
);
349 if (preferFragmentation
) {
350 SOSPeerInfoV2DictionarySetValue(pi
, sPreferIDSFragmentation
, preferFragmentation
);
352 if (preferAckModel
) {
353 SOSPeerInfoV2DictionarySetValue(pi
, sPreferIDSACKModel
, preferAckModel
);
356 SOSPeerInfoV2DictionarySetValue(pi
, sViewsKey
, enabledViews
);
359 if(!SOSPeerInfoSign(signingKey
, pi
, error
)) {
367 static SOSPeerInfoRef
SOSPeerInfoCopyWithModification(CFAllocatorRef allocator
, SOSPeerInfoRef original
,
368 SecKeyRef signingKey
, CFErrorRef
*error
,
369 bool (^modification
)(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
)) {
371 SOSPeerInfoRef result
= NULL
;
372 SOSPeerInfoRef copy
= SOSPeerInfoCreateCopy(allocator
, original
, error
);
374 require_quiet(modification(copy
, error
), fail
);
376 require_quiet(SOSPeerInfoSign(signingKey
, copy
, error
), fail
);
378 CFTransferRetained(result
, copy
);
386 SOSPeerInfoRef
SOSPeerInfoCopyWithGestaltUpdate(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFDictionaryRef gestalt
, SecKeyRef signingKey
, CFErrorRef
* error
) {
387 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
388 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
389 if(!gestalt
|| !peerToModify
) return false;
390 CFRetainAssign(peerToModify
->gestalt
, gestalt
);
391 CFDictionarySetValue(peerToModify
->description
, sGestaltKey
, peerToModify
->gestalt
);
398 SOSPeerInfoRef
SOSPeerInfoCopyWithBackupKeyUpdate(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFDataRef backupKey
, SecKeyRef signingKey
, CFErrorRef
*error
) {
399 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
400 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
401 if (backupKey
!= NULL
)
402 SOSPeerInfoV2DictionarySetValue(peerToModify
, sBackupKeyKey
, backupKey
);
404 SOSPeerInfoV2DictionaryRemoveValue(peerToModify
, sBackupKeyKey
);
409 static CFDictionaryRef
SOSPeerInfoUpdateAndCopyRecord(SOSPeerInfoRef peer
, CFStringRef dsid
, CFDictionaryRef escrowRecord
){
411 CFMutableDictionaryRef existingEscrowRecords
= SOSPeerInfoCopyEscrowRecord(peer
);
413 if(escrowRecord
== NULL
&& existingEscrowRecords
!= NULL
)
415 CFDictionaryRemoveValue(existingEscrowRecords
, dsid
);
416 return existingEscrowRecords
;
419 if(existingEscrowRecords
== NULL
)
420 existingEscrowRecords
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
422 CFDictionarySetValue(existingEscrowRecords
, dsid
, escrowRecord
);
424 return existingEscrowRecords
;
428 SOSPeerInfoRef
SOSPeerInfoCopyWithEscrowRecordUpdate(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFStringRef dsid
, CFDictionaryRef escrowRecord
, SecKeyRef signingKey
, CFErrorRef
*error
) {
429 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
430 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
432 CFDictionaryRef updatedEscrowRecords
= SOSPeerInfoUpdateAndCopyRecord(peerToModify
, dsid
, escrowRecord
);
433 SOSPeerInfoV2DictionarySetValue(peerToModify
, sEscrowRecord
, updatedEscrowRecords
);
434 CFReleaseNull(updatedEscrowRecords
);
439 SOSPeerInfoRef
SOSPeerInfoCopyWithReplacedEscrowRecords(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFDictionaryRef escrowRecords
, SecKeyRef signingKey
, CFErrorRef
*error
) {
440 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
441 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
442 if(escrowRecords
!= NULL
)
443 SOSPeerInfoV2DictionarySetValue(peerToModify
, sEscrowRecord
, escrowRecords
);
449 CFDataRef
SOSPeerInfoCopyBackupKey(SOSPeerInfoRef peer
) {
450 return SOSPeerInfoV2DictionaryCopyData(peer
, sBackupKeyKey
);
453 CFMutableDictionaryRef
SOSPeerInfoCopyEscrowRecord(SOSPeerInfoRef peer
){
454 return SOSPeerInfoV2DictionaryCopyDictionary(peer
, sEscrowRecord
);
457 bool SOSPeerInfoHasBackupKey(SOSPeerInfoRef peer
) {
458 CFDataRef bk
= SOSPeerInfoCopyBackupKey(peer
);
459 bool success
= bk
!= NULL
;
464 SOSPeerInfoRef
SOSPeerInfoCopyWithViewsChange(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
,
465 SOSViewActionCode action
, CFStringRef viewname
, SOSViewResultCode
*retval
,
466 SecKeyRef signingKey
, CFErrorRef
* error
) {
467 SOSPeerInfoRef pi
= SOSPeerInfoCreateCopy(allocator
, toCopy
, error
);
468 if(action
== kSOSCCViewEnable
) {
469 *retval
= SOSViewsEnable(pi
, viewname
, error
);
470 require((kSOSCCViewMember
== *retval
), exit
);
471 } else if(action
== kSOSCCViewDisable
) {
472 *retval
= SOSViewsDisable(pi
, viewname
, error
);
473 require((kSOSCCViewNotMember
== *retval
), exit
);
476 require_action_quiet(SOSPeerInfoSign(signingKey
, pi
, error
), exit
, *retval
= kSOSCCGeneralViewError
);
485 CFStringRef sPingKey
= CFSTR("Ping");
487 SOSPeerInfoRef
SOSPeerInfoCopyWithPing(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, SecKeyRef signingKey
, CFErrorRef
* error
) {
488 SOSPeerInfoRef pi
= SOSPeerInfoCreateCopy(allocator
, toCopy
, error
);
489 CFDataRef ping
= CFDataCreateWithRandomBytes(8);
490 SOSPeerInfoV2DictionarySetValue(pi
, sPingKey
, ping
);
491 SecKeyRef pub_key
= SOSPeerInfoCopyPubKey(pi
, error
);
492 require_quiet(pub_key
, exit
);
493 pi
->id
= SOSCopyIDOfKey(pub_key
, error
);
494 require_quiet(pi
->id
, exit
);
495 require_action_quiet(SOSPeerInfoSign(signingKey
, pi
, error
), exit
, CFReleaseNull(pi
));
498 CFReleaseNull(pub_key
);
503 SOSViewResultCode
SOSPeerInfoViewStatus(SOSPeerInfoRef pi
, CFStringRef view
, CFErrorRef
*error
) {
504 return SOSViewsQuery(pi
, view
, error
);
508 SOSPeerInfoRef
SOSPeerInfoCopyWithSecurityPropertyChange(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
,
509 SOSSecurityPropertyActionCode action
, CFStringRef property
, SOSSecurityPropertyResultCode
*retval
,
510 SecKeyRef signingKey
, CFErrorRef
* error
) {
511 SOSPeerInfoRef pi
= SOSPeerInfoCreateCopy(allocator
, toCopy
, error
);
512 if(action
== kSOSCCSecurityPropertyEnable
) {
513 *retval
= SOSSecurityPropertyEnable(pi
, property
, error
);
514 require((kSOSCCSecurityPropertyValid
== *retval
), exit
);
515 } else if(action
== kSOSCCSecurityPropertyDisable
) {
516 *retval
= SOSSecurityPropertyDisable(pi
, property
, error
);
517 require((kSOSCCSecurityPropertyNotValid
== *retval
), exit
);
520 require_action_quiet(SOSPeerInfoSign(signingKey
, pi
, error
), exit
, *retval
= kSOSCCGeneralViewError
);
528 SOSViewResultCode
SOSPeerInfoSecurityPropertyStatus(SOSPeerInfoRef pi
, CFStringRef property
, CFErrorRef
*error
) {
529 return SOSSecurityPropertyQuery(pi
, property
, error
);
534 static void SOSPeerInfoDestroy(CFTypeRef aObj
) {
535 SOSPeerInfoRef pi
= (SOSPeerInfoRef
) aObj
;
538 CFReleaseNull(pi
->description
);
539 CFReleaseNull(pi
->signature
);
540 CFReleaseNull(pi
->gestalt
);
541 CFReleaseNull(pi
->id
);
542 if(pi
->v2Dictionary
) CFReleaseNull(pi
->v2Dictionary
);
545 static Boolean
SOSPeerInfoCompare(CFTypeRef lhs
, CFTypeRef rhs
) {
546 SOSPeerInfoRef lpeer
= (SOSPeerInfoRef
) lhs
;
547 SOSPeerInfoRef rpeer
= (SOSPeerInfoRef
) rhs
;
548 if(!lpeer
|| !rpeer
) return false;
549 return CFEqualSafe(lpeer
->description
, rpeer
->description
) && CFEqualSafe(lpeer
->signature
, rpeer
->signature
);
553 CFComparisonResult
SOSPeerInfoCompareByID(const void *val1
, const void *val2
, void *context
) {
554 // The code below is necessary but not sufficient; not returning a CFComparisonResult
555 // It probably is OK to say that a NULL is < <non-NULL>
556 if (val1
== NULL
|| val2
== NULL
) {
557 ptrdiff_t dv
= val1
- val2
;
558 return dv
< 0 ? kCFCompareLessThan
: dv
== 0 ? kCFCompareEqualTo
: kCFCompareGreaterThan
;
561 CFStringRef v1
= SOSPeerInfoGetPeerID((SOSPeerInfoRef
) val1
);
562 CFStringRef v2
= SOSPeerInfoGetPeerID((SOSPeerInfoRef
) val2
);
563 if (v1
== NULL
|| v2
== NULL
) {
564 ptrdiff_t dv
= (const void *)v1
- (const void *)v2
;
565 return dv
< 0 ? kCFCompareLessThan
: dv
== 0 ? kCFCompareEqualTo
: kCFCompareGreaterThan
;
568 return CFStringCompare(v1
, v2
, 0);
571 static CFHashCode
SOSPeerInfoHash(CFTypeRef cf
) {
572 SOSPeerInfoRef peer
= (SOSPeerInfoRef
) cf
;
574 return CFHash(peer
->description
) ^ CFHash(peer
->signature
);
578 static char boolToChars(bool val
, char truechar
, char falsechar
) {
579 return val
? truechar
: falsechar
;
582 static CFStringRef
isKnown(CFStringRef ref
) {
583 return ref
? ref
: CFSTR("Unknown ");
586 static CFStringRef
copyDescriptionWithFormatOptions(CFTypeRef aObj
, CFDictionaryRef formatOptions
){
588 SOSPeerInfoRef pi
= (SOSPeerInfoRef
) aObj
;
591 CFStringRef description
= NULL
;
592 // Get the format options we care about:
593 bool retired
= SOSPeerInfoIsRetirementTicket(pi
);
594 bool selfValid
= SOSPeerInfoVerify(pi
, NULL
);
595 bool backingUp
= SOSPeerInfoHasBackupKey(pi
);
596 bool isKVS
= SOSPeerInfoKVSOnly(pi
);
597 CFStringRef osVersion
= CFDictionaryGetValue(pi
->gestalt
, kPIOSVersionKey
);
598 CFStringRef tmp
= SOSPeerInfoV2DictionaryCopyString(pi
, sDeviceID
);
599 CFStringRef deviceID
= CFStringCreateTruncatedCopy(tmp
, 8);
601 CFStringRef serialNum
= SOSPeerInfoCopySerialNumber(pi
);
602 CFStringRef peerID
= CFStringCreateTruncatedCopy(SOSPeerInfoGetPeerID(pi
), 8);
604 // Calculate the truncated length
606 CFStringRef objectPrefix
= CFStringCreateWithFormat(kCFAllocatorDefault
, formatOptions
, CFSTR("PI@%p"), pi
);
608 description
= CFStringCreateWithFormat(kCFAllocatorDefault
, formatOptions
,
609 CFSTR("<%@: [name: %20@] [%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]"),
611 isKnown(SOSPeerInfoGetPeerName(pi
)),
614 boolToChars(selfValid
, 'S', 's'),
615 boolToChars(retired
, 'R', 'r'),
616 boolToChars(backingUp
, 'B', 'b'),
617 boolToChars(isKVS
, 'K', 'I'),
619 isKnown(SOSPeerInfoGetPeerDeviceType(pi
)), isKnown(peerID
),
620 isKnown(osVersion
), isKnown(deviceID
), isKnown(serialNum
));
623 CFReleaseNull(peerID
);
624 CFReleaseNull(deviceID
);
625 CFReleaseNull(serialNum
);
626 CFReleaseNull(objectPrefix
);
631 static CFStringRef
SOSPeerInfoCopyFormatDescription(CFTypeRef aObj
, CFDictionaryRef formatOptions
) {
633 CFStringRef description
= NULL
;
635 description
= copyDescriptionWithFormatOptions(aObj
, formatOptions
);
640 void SOSPeerInfoLogState(char *category
, SOSPeerInfoRef pi
, SecKeyRef pubKey
, CFStringRef myPID
, char sigchr
) {
642 bool appValid
= SOSPeerInfoApplicationVerify(pi
, pubKey
, NULL
);
643 bool retired
= SOSPeerInfoIsRetirementTicket(pi
);
644 bool selfValid
= SOSPeerInfoVerify(pi
, NULL
);
645 bool backingUp
= SOSPeerInfoHasBackupKey(pi
);
646 bool isMe
= CFEqualSafe(SOSPeerInfoGetPeerID(pi
), myPID
) == true;
647 bool isKVS
= SOSPeerInfoKVSOnly(pi
);
648 CFStringRef osVersion
= CFDictionaryGetValue(pi
->gestalt
, kPIOSVersionKey
);
649 CFStringRef tmp
= SOSPeerInfoV2DictionaryCopyString(pi
, sDeviceID
);
650 CFStringRef deviceID
= CFStringCreateTruncatedCopy(tmp
, 8);
652 CFStringRef serialNum
= SOSPeerInfoCopySerialNumber(pi
);
653 CFStringRef peerID
= CFStringCreateTruncatedCopy(SOSPeerInfoGetPeerID(pi
), 8);
655 secnotice(category
, "PI: [name: %-20@] [%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]", isKnown(SOSPeerInfoGetPeerName(pi
)),
656 boolToChars(isMe
, 'M', 'm'),
657 boolToChars(appValid
, 'A', 'a'),
658 boolToChars(selfValid
, 'S', 's'),
659 boolToChars(retired
, 'R', 'r'),
660 boolToChars(backingUp
, 'B', 'b'),
661 boolToChars(isKVS
, 'K', 'I'),
663 isKnown(SOSPeerInfoGetPeerDeviceType(pi
)), isKnown(peerID
),
664 isKnown(osVersion
), isKnown(deviceID
), isKnown(serialNum
));
666 CFReleaseNull(peerID
);
667 CFReleaseNull(deviceID
);
668 CFReleaseNull(serialNum
);
671 CFDictionaryRef
SOSPeerInfoCopyPeerGestalt(SOSPeerInfoRef pi
) {
672 CFRetain(pi
->gestalt
);
676 CFDictionaryRef
SOSPeerGetGestalt(SOSPeerInfoRef pi
){
680 CFStringRef
SOSPeerInfoGetPeerName(SOSPeerInfoRef peer
) {
681 return SOSPeerInfoLookupGestaltValue(peer
, kPIUserDefinedDeviceNameKey
);
684 CFStringRef
SOSPeerInfoGetPeerDeviceType(SOSPeerInfoRef peer
) {
685 return SOSPeerInfoLookupGestaltValue(peer
, kPIDeviceModelNameKey
);
688 CFIndex
SOSPeerInfoGetPeerProtocolVersion(SOSPeerInfoRef peer
) {
689 CFIndex version
= PEERINFO_CURRENT_VERSION
;
690 CFTypeRef val
= SOSPeerInfoLookupGestaltValue(peer
, kPIMessageProtocolVersionKey
);
691 if (val
&& CFGetTypeID(val
) == CFNumberGetTypeID())
692 CFNumberGetValue(val
, kCFNumberCFIndexType
, &version
);
696 CFTypeRef
SOSPeerInfoLookupGestaltValue(SOSPeerInfoRef pi
, CFStringRef key
) {
697 return CFDictionaryGetValue(pi
->gestalt
, key
);
700 CFStringRef
SOSPeerInfoGetPeerID(SOSPeerInfoRef pi
) {
701 return pi
? pi
->id
: NULL
;
704 bool SOSPeerInfoPeerIDEqual(SOSPeerInfoRef pi
, CFStringRef myPeerID
) {
705 return CFEqualSafe(myPeerID
, SOSPeerInfoGetPeerID(pi
));
708 CFIndex
SOSPeerInfoGetVersion(SOSPeerInfoRef pi
) {
712 bool SOSPeerInfoUpdateDigestWithPublicKeyBytes(SOSPeerInfoRef peer
, const struct ccdigest_info
*di
,
713 ccdigest_ctx_t ctx
, CFErrorRef
*error
) {
714 CFDataRef pubKeyBytes
= CFDictionaryGetValue(peer
->description
, sPublicKeyKey
);
717 SOSCreateErrorWithFormat(kSOSErrorEncodeFailure
, NULL
, error
, NULL
, CFSTR("Digest failed – no public key"));
721 ccdigest_update(di
, ctx
, CFDataGetLength(pubKeyBytes
), CFDataGetBytePtr(pubKeyBytes
));
726 bool SOSPeerInfoUpdateDigestWithDescription(SOSPeerInfoRef peer
, const struct ccdigest_info
*di
,
727 ccdigest_ctx_t ctx
, CFErrorRef
*error
) {
728 if(SOSPeerInfoVersionHasV2Data(peer
)) SOSPeerInfoPackV2Data(peer
);
729 size_t description_size
= der_sizeof_plist(peer
->description
, error
);
730 uint8_t data_begin
[description_size
];
731 uint8_t *data_end
= data_begin
+ description_size
;
732 uint8_t *encoded
= der_encode_plist(peer
->description
, error
, data_begin
, data_end
);
735 SOSCreateErrorWithFormat(kSOSErrorEncodeFailure
, NULL
, error
, NULL
, CFSTR("Description encode failed"));
739 ccdigest_update(di
, ctx
, description_size
, data_begin
);
745 static CFDataRef
sosCreateDate() {
746 CFDateRef now
= CFDateCreate(NULL
, CFAbsoluteTimeGetCurrent());
747 size_t bufsiz
= der_sizeof_date(now
, NULL
);
749 der_encode_date(now
, NULL
, buf
, buf
+bufsiz
);
751 return CFDataCreate(NULL
, buf
, bufsiz
);
754 static CFDateRef
sosCreateCFDate(CFDataRef sosdate
) {
756 der_decode_date(NULL
, 0, &date
, NULL
, CFDataGetBytePtr(sosdate
),
757 CFDataGetBytePtr(sosdate
) + CFDataGetLength(sosdate
));
761 static bool sospeer_application_hash(SOSPeerInfoRef pi
, const struct ccdigest_info
*di
, uint8_t *hbuf
) {
762 CFDataRef appdate
= asData(CFDictionaryGetValue(pi
->description
, sApplicationDate
), NULL
);
763 if(!appdate
) return false;
764 ccdigest_di_decl(di
, ctx
);
765 ccdigest_init(di
, ctx
);
766 ccdigest_update(di
, ctx
, CFDataGetLength(appdate
), CFDataGetBytePtr(appdate
));
767 if (!SOSPeerInfoUpdateDigestWithPublicKeyBytes(pi
, di
, ctx
, NULL
)) return false;
768 ccdigest_final(di
, ctx
, hbuf
);
772 SOSPeerInfoRef
SOSPeerInfoCopyAsApplication(SOSPeerInfoRef original
, SecKeyRef userkey
, SecKeyRef peerkey
, CFErrorRef
*error
) {
773 SOSPeerInfoRef result
= NULL
;
774 SOSPeerInfoRef pi
= SOSPeerInfoCreateCopy(kCFAllocatorDefault
, original
, error
);
776 const struct ccdigest_info
*di
= ccsha256_di();
777 uint8_t hbuf
[di
->output_size
];
778 CFDataRef usersig
= NULL
;
780 CFDataRef creationDate
= sosCreateDate();
781 CFDictionarySetValue(pi
->description
, sApplicationDate
, creationDate
);
782 CFReleaseNull(creationDate
);
784 // Create User Application Signature
785 require_action_quiet(sospeer_application_hash(pi
, di
, hbuf
), fail
,
786 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Failed to create hash for peer applicant"), NULL
, error
));
788 usersig
= sosCopySignedHash(userkey
, di
, hbuf
);
789 require_action_quiet(usersig
, fail
,
790 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Failed to sign public key hash for peer"), NULL
, error
));
792 CFDictionarySetValue(pi
->description
, sApplicationUsig
, usersig
);
794 require_quiet(SOSPeerInfoSign(peerkey
, pi
, error
), fail
);
800 CFReleaseNull(usersig
);
805 bool SOSPeerInfoApplicationVerify(SOSPeerInfoRef pi
, SecKeyRef userkey
, CFErrorRef
*error
) {
806 const struct ccdigest_info
*di
= ccsha256_di();
807 uint8_t hbuf
[di
->output_size
];
810 CFDataRef usig
= CFDictionaryGetValue(pi
->description
, sApplicationUsig
);
811 require_action_quiet(usig
, exit
,
812 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Peer is not an applicant"), NULL
, error
));
813 // Verify User Application Signature
814 require_action_quiet(sospeer_application_hash(pi
, di
, hbuf
), exit
,
815 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Failed to create hash for peer applicant"), NULL
, error
));
816 require_action_quiet(sosVerifyHash(userkey
, di
, hbuf
, usig
), exit
,
817 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("user signature of public key hash fails to verify"), NULL
, error
));
819 result
= SOSPeerInfoVerify(pi
, error
);
826 static CF_RETURNS_RETAINED CFDateRef
sosPeerInfoGetDate(SOSPeerInfoRef pi
, CFStringRef entry
) {
828 CFDataRef sosdate
= CFDictionaryGetValue(pi
->description
, entry
);
829 if(!sosdate
) return NULL
;
830 CFDateRef date
= sosCreateCFDate(sosdate
);
835 CF_RETURNS_RETAINED CFDateRef
SOSPeerInfoGetApplicationDate(SOSPeerInfoRef pi
) {
836 return sosPeerInfoGetDate(pi
, sApplicationDate
);
839 CF_RETURNS_RETAINED CFDateRef
SOSPeerInfoGetRetirementDate(SOSPeerInfoRef pi
) {
840 return sosPeerInfoGetDate(pi
, sRetirementDate
);
849 CFStringRef
SOSPeerGestaltGetName(CFDictionaryRef gestalt
) {
850 CFStringRef name
= SOSPeerGestaltGetAnswer(gestalt
, kPIUserDefinedDeviceNameKey
);
851 return isString(name
) ? name
: NULL
;
854 CFTypeRef
SOSPeerGestaltGetAnswer(CFDictionaryRef gestalt
, CFStringRef question
) {
855 return gestalt
? CFDictionaryGetValue(gestalt
, question
) : NULL
;
863 SOSPeerInfoRef
SOSPeerInfoCreateRetirementTicket(CFAllocatorRef allocator
, SecKeyRef privKey
, SOSPeerInfoRef peer
, CFErrorRef
*error
) {
865 SOSPeerInfoRef pi
= SOSPeerInfoCreateCopy(allocator
, peer
, error
);
869 // Fill out Resignation Date
870 CFDataRef resignationDate
= sosCreateDate();
871 CFDictionaryAddValue(pi
->description
, sRetirementDate
, resignationDate
);
872 CFReleaseNull(resignationDate
);
874 require(SOSPeerInfoSign(privKey
, pi
, error
), fail
);
883 CFStringRef
SOSPeerInfoInspectRetirementTicket(SOSPeerInfoRef pi
, CFErrorRef
*error
) {
884 CFStringRef retval
= NULL
;
885 CFDateRef now
= CFDateCreate(NULL
, CFAbsoluteTimeGetCurrent());
886 CFDateRef retirement
= NULL
;
888 require_quiet(SOSPeerInfoVerify(pi
, error
), err
);
890 retirement
= sosCreateCFDate(CFDictionaryGetValue(pi
->description
, sRetirementDate
));
891 require_action_quiet(retirement
, err
,
892 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Peer is not retired"), NULL
, error
));
894 require_action_quiet(CFDateCompare(now
, retirement
, NULL
) == kCFCompareGreaterThan
, err
,
895 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Retirement date is after current date"), NULL
, error
));
897 retval
= SOSPeerInfoGetPeerID(pi
);
901 CFReleaseNull(retirement
);
905 bool SOSPeerInfoRetireRetirementTicket(size_t max_seconds
, SOSPeerInfoRef pi
) {
906 CFDateRef now
= CFDateCreate(NULL
, CFAbsoluteTimeGetCurrent());
907 CFDateRef retirement
= sosCreateCFDate(CFDictionaryGetValue(pi
->description
, sRetirementDate
));
908 CFTimeInterval timediff
= CFDateGetTimeIntervalSinceDate(now
, retirement
); // diff in seconds
910 CFReleaseNull(retirement
);
911 if(timediff
> (max_seconds
)) return true;
915 bool SOSPeerInfoIsRetirementTicket(SOSPeerInfoRef pi
) {
916 CFDataRef flag
= CFDictionaryGetValue(pi
->description
, sRetirementDate
);
920 bool SOSPeerInfoIsCloudIdentity(SOSPeerInfoRef pi
) {
921 CFTypeRef value
= CFDictionaryGetValue(pi
->description
, sCloudIdentityKey
);
922 return CFEqualSafe(value
, kCFBooleanTrue
);
925 SOSPeerInfoRef
SOSPeerInfoUpgradeSignatures(CFAllocatorRef allocator
, SecKeyRef privKey
, SecKeyRef peerKey
, SOSPeerInfoRef peer
, CFErrorRef
*error
) {
926 SecKeyRef pubKey
= SecKeyCreatePublicFromPrivate(privKey
);
927 SOSPeerInfoRef retval
= NULL
;
929 retval
= SOSPeerInfoCopyAsApplication(peer
, privKey
, peerKey
, error
);
930 CFReleaseNull(pubKey
);
934 CFBooleanRef
SOSPeerInfoCopyIDSPreference(SOSPeerInfoRef peer
){
935 CFBooleanRef preference
= (CFBooleanRef
)SOSPeerInfoV2DictionaryCopyBoolean(peer
, sPreferIDS
);
936 return (preference
? preference
: CFRetain(kCFBooleanFalse
));
940 SOSPeerInfoRef
SOSPeerInfoSetIDSPreference(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFBooleanRef preference
, SecKeyRef signingKey
, CFErrorRef
*error
){
941 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
942 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
943 SOSPeerInfoV2DictionarySetValue(peerToModify
, sPreferIDS
, preference
);
948 CFBooleanRef
SOSPeerInfoCopyIDSFragmentationPreference(SOSPeerInfoRef peer
){
949 CFBooleanRef preference
= (CFBooleanRef
)SOSPeerInfoV2DictionaryCopyBoolean(peer
, sPreferIDSFragmentation
);
950 return (preference
? preference
: CFRetain(kCFBooleanFalse
));
953 CFBooleanRef
SOSPeerInfoCopyIDSACKModelPreference(SOSPeerInfoRef peer
){
954 CFBooleanRef preference
= (CFBooleanRef
)SOSPeerInfoV2DictionaryCopyBoolean(peer
, sPreferIDSACKModel
);
955 return (preference
? preference
: CFRetain(kCFBooleanFalse
));
958 SOSPeerInfoRef
SOSPeerInfoSetIDSFragmentationPreference(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFBooleanRef preference
, SecKeyRef signingKey
, CFErrorRef
*error
){
959 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
960 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
961 SOSPeerInfoV2DictionarySetValue(peerToModify
, sPreferIDSFragmentation
, preference
);
966 SOSPeerInfoRef
SOSPeerInfoSetIDSACKModelPreference(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFBooleanRef preference
, SecKeyRef signingKey
, CFErrorRef
*error
){
967 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
968 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
969 SOSPeerInfoV2DictionarySetValue(peerToModify
, sPreferIDSACKModel
, preference
);
974 bool SOSPeerInfoTransportTypeIs(SOSPeerInfoRef pi
, CFStringRef transportType
) {
975 return SOSPeerInfoV2DictionaryHasStringValue(pi
, sTransportType
, transportType
);
978 CFStringRef
SOSPeerInfoCopyTransportType(SOSPeerInfoRef peer
){
979 CFStringRef transportType
= (CFStringRef
)SOSPeerInfoV2DictionaryCopyString(peer
, sTransportType
);
980 return (transportType
? transportType
: CFRetain(SOSTransportMessageTypeKVS
));
983 SOSPeerInfoRef
SOSPeerInfoSetTransportType(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFStringRef transportType
, SecKeyRef signingKey
, CFErrorRef
*error
){
985 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
986 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
987 SOSPeerInfoV2DictionarySetValue(peerToModify
, sTransportType
, transportType
);
992 bool SOSPeerInfoKVSOnly(SOSPeerInfoRef pi
) {
993 CFStringRef transportType
= SOSPeerInfoCopyTransportType(pi
);
994 bool retval
= CFEqualSafe(transportType
, SOSTransportMessageTypeKVS
);
995 CFReleaseNull(transportType
);
999 bool SOSPeerInfoHasDeviceID(SOSPeerInfoRef peer
) {
1000 return SOSPeerInfoV2DictionaryHasString(peer
, sDeviceID
);
1003 CFStringRef
SOSPeerInfoCopyDeviceID(SOSPeerInfoRef peer
){
1004 return (CFStringRef
)SOSPeerInfoV2DictionaryCopyString(peer
, sDeviceID
);
1007 SOSPeerInfoRef
SOSPeerInfoSetDeviceID(CFAllocatorRef allocator
, SOSPeerInfoRef toCopy
, CFStringRef IDS
, SecKeyRef signingKey
, CFErrorRef
*error
){
1009 return SOSPeerInfoCopyWithModification(allocator
, toCopy
, signingKey
, error
,
1010 ^bool(SOSPeerInfoRef peerToModify
, CFErrorRef
*error
) {
1011 SOSPeerInfoV2DictionarySetValue(peerToModify
, sDeviceID
, IDS
);
1016 bool SOSPeerInfoShouldUseIDSTransport(SOSPeerInfoRef myPeer
, SOSPeerInfoRef theirPeer
){
1017 return SOSPeerInfoHasDeviceID(myPeer
) && SOSPeerInfoTransportTypeIs(myPeer
, SOSTransportMessageTypeIDSV2
) &&
1018 SOSPeerInfoHasDeviceID(theirPeer
) && SOSPeerInfoTransportTypeIs(theirPeer
, SOSTransportMessageTypeIDSV2
);
1021 bool SOSPeerInfoShouldUseIDSMessageFragmentation(SOSPeerInfoRef myPeer
, SOSPeerInfoRef theirPeer
){
1023 bool success
= false;
1025 CFBooleanRef myPreference
= SOSPeerInfoCopyIDSFragmentationPreference(myPeer
);
1027 CFBooleanRef theirPreference
= SOSPeerInfoCopyIDSFragmentationPreference(theirPeer
);
1028 secnotice("IDS Transport", "mypreference: %@, theirpreference: %@", myPreference
, theirPreference
);
1029 if((myPreference
== kCFBooleanTrue
&& theirPreference
== kCFBooleanTrue
))
1032 CFReleaseNull(myPreference
);
1033 CFReleaseNull(theirPreference
);
1037 bool SOSPeerInfoShouldUseACKModel(SOSPeerInfoRef myPeer
, SOSPeerInfoRef theirPeer
){
1038 bool success
= false;
1040 CFBooleanRef myPreference
= SOSPeerInfoCopyIDSACKModelPreference(myPeer
);
1042 CFBooleanRef theirPreference
= SOSPeerInfoCopyIDSACKModelPreference(theirPeer
);
1043 secnotice("IDS Transport", "mypreference: %@, theirpreference: %@", myPreference
, theirPreference
);
1044 if((myPreference
== kCFBooleanTrue
&& theirPreference
== kCFBooleanTrue
))
1047 CFReleaseNull(myPreference
);
1048 CFReleaseNull(theirPreference
);
1053 SOSPeerInfoDeviceClass
SOSPeerInfoGetClass(SOSPeerInfoRef pi
) {
1054 static CFDictionaryRef devID2Class
= NULL
;
1055 static dispatch_once_t onceToken
= 0;
1057 dispatch_once(&onceToken
, ^{
1058 CFNumberRef cfSOSPeerInfo_macOS
= CFNumberCreateWithCFIndex(kCFAllocatorDefault
, SOSPeerInfo_macOS
);
1059 CFNumberRef cfSOSPeerInfo_iOS
= CFNumberCreateWithCFIndex(kCFAllocatorDefault
, SOSPeerInfo_iOS
);
1060 CFNumberRef cfSOSPeerInfo_iCloud
= CFNumberCreateWithCFIndex(kCFAllocatorDefault
, SOSPeerInfo_iCloud
);
1061 // CFNumberRef cfSOSPeerInfo_watchOS = CFNumberCreateWithCFIndex(kCFAllocatorDefault, SOSPeerInfo_watchOS);
1062 // CFNumberRef cfSOSPeerInfo_tvOS = CFNumberCreateWithCFIndex(kCFAllocatorDefault, SOSPeerInfo_tvOS);
1064 devID2Class
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
1065 CFSTR("Mac Pro"), cfSOSPeerInfo_macOS
,
1066 CFSTR("MacBook"), cfSOSPeerInfo_macOS
,
1067 CFSTR("MacBook Pro"), cfSOSPeerInfo_macOS
,
1068 CFSTR("iCloud"), cfSOSPeerInfo_iCloud
,
1069 CFSTR("iMac"), cfSOSPeerInfo_macOS
,
1070 CFSTR("iPad"), cfSOSPeerInfo_iOS
,
1071 CFSTR("iPhone"), cfSOSPeerInfo_iOS
,
1072 CFSTR("iPod touch"), cfSOSPeerInfo_iOS
,
1074 CFReleaseNull(cfSOSPeerInfo_macOS
);
1075 CFReleaseNull(cfSOSPeerInfo_iOS
);
1076 CFReleaseNull(cfSOSPeerInfo_iCloud
);
1078 SOSPeerInfoDeviceClass retval
= SOSPeerInfo_unknown
;
1079 CFStringRef dt
= SOSPeerInfoGetPeerDeviceType(pi
);
1080 require_quiet(dt
, errOut
);
1081 CFNumberRef classNum
= CFDictionaryGetValue(devID2Class
, dt
);
1082 require_quiet(classNum
, errOut
);
1084 require_quiet(CFNumberGetValue(classNum
, kCFNumberCFIndexType
, &tmp
), errOut
);
1085 retval
= (SOSPeerInfoDeviceClass
) tmp
;