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@
28 #import <Foundation/Foundation.h>
29 #import <Foundation/NSXPCConnection_Private.h>
32 #include <AssertMacros.h>
33 #include "keychain/SecureObjectSync/SOSCloudCircle.h"
34 #include "keychain/SecureObjectSync/SOSCloudCircleInternal.h"
35 #include "keychain/SecureObjectSync/SOSCircle.h"
36 #include "keychain/SecureObjectSync/SOSAccount.h"
37 #include "keychain/SecureObjectSync/SOSFullPeerInfo.h"
38 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
39 #include "keychain/SecureObjectSync/SOSInternal.h"
40 #include "keychain/SecureObjectSync/SOSRing.h"
41 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
42 #include <Security/SecureObjectSync/SOSViews.h>
43 #include "keychain/SecureObjectSync/SOSControlHelper.h"
44 #include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
46 #include <Security/SecKeyPriv.h>
47 #include <Security/SecFramework.h>
48 #include <CoreFoundation/CFXPCBridge.h>
50 #include "keychain/securityd/SecItemServer.h"
52 #include <utilities/SecDispatchRelease.h>
53 #include <utilities/SecCFRelease.h>
54 #include <utilities/SecCFWrappers.h>
55 #include <utilities/SecXPCError.h>
57 #include <corecrypto/ccsha2.h>
59 #include <utilities/debugging.h>
61 #include <CoreFoundation/CoreFoundation.h>
64 #define MINIMIZE_INCLUDES MINIMIZE_INCLUDES
65 #include <ipc/securityd_client.h>
66 #include "keychain/securityd/spi.h"
68 #include <Security/SecuritydXPC.h>
70 const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged";
71 const char * kSOSCCViewMembershipChangedNotification = "com.apple.security.secureobjectsync.viewschanged";
72 const char * kSOSCCInitialSyncChangedNotification = "com.apple.security.secureobjectsync.initialsyncchanged";
73 const char * kSOSCCHoldLockForInitialSync = "com.apple.security.secureobjectsync.holdlock";
74 const char * kSOSCCPeerAvailable = "com.apple.security.secureobjectsync.peeravailable";
75 const char * kSOSCCRecoveryKeyChanged = "com.apple.security.secureobjectsync.recoverykeychanged";
76 const char * kSOSCCCircleOctagonKeysChangedNotification = "com.apple.security.sosoctagonbitschanged";
78 #define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
80 static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type)
82 xpc_object_t value = xpc_dictionary_get_value(dictionary, key);
84 return value && (xpc_get_type(value) == type);
87 SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error)
89 SOSCCStatus retval = SOSGetCachedCircleStatus(error);
90 if(retval != kSOSNoCachedValue) {
91 secdebug("circleOps", "Retrieved cached circle value %d", retval);
94 return SOSCCThisDeviceIsInCircleNonCached(error);
98 SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error)
100 sec_trace_enter_api(NULL);
101 sec_trace_return_api(SOSCCStatus, ^{
102 SOSCCStatus result = kSOSCCError;
104 do_if_registered(soscc_ThisDeviceIsInCircle, error);
106 xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error);
108 xpc_object_t response = securityd_message_with_reply_sync(message, error);
110 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
111 result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult);
113 result = kSOSCCError;
117 if (response && securityd_message_no_error(response, error))
119 char *desc = xpc_copy_description(response);
120 SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc);
125 secnotice("circleOps", "Retrieved non-cached circle value %d", result);
128 }, CFSTR("SOSCCStatus=%d"))
131 static bool sfsigninanalytics_bool_error_request(enum SecXPCOperation op, CFDataRef parentEvent, CFErrorRef* error)
133 __block bool result = false;
135 secdebug("sosops","enter - operation: %d", op);
136 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
137 return SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
138 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
139 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
145 static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
147 __block bool result = false;
149 secdebug("sosops","enter - operation: %d", op);
150 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
151 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
157 static bool SecXPCDictionarySetPeerInfoData(xpc_object_t message, const char *key, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
158 bool success = false;
159 CFDataRef peerData = SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, error);
161 success = SecXPCDictionarySetData(message, key, peerData, error);
163 CFReleaseNull(peerData);
167 static bool peer_info_to_bool_error_request(enum SecXPCOperation op, SOSPeerInfoRef peerInfo, CFErrorRef* error)
169 __block bool result = false;
171 secdebug("sosops","enter - operation: %d", op);
172 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
173 return SecXPCDictionarySetPeerInfoData(message, kSecXPCKeyPeerInfo, peerInfo, error);
174 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
175 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
181 static CFBooleanRef cfarray_to_cfboolean_error_request(enum SecXPCOperation op, CFArrayRef views, CFErrorRef* error)
183 __block bool result = false;
185 secdebug("sosops","enter - operation: %d", op);
186 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
187 return SecXPCDictionarySetPList(message, kSecXPCKeyArray, views, error);
188 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
189 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
192 return noError ? (result ? kCFBooleanTrue : kCFBooleanFalse) : NULL;
196 static CFSetRef cfset_cfset_to_cfset_error_request(enum SecXPCOperation op, CFSetRef set1, CFSetRef set2, CFErrorRef* error)
198 __block CFSetRef result = NULL;
200 secdebug("sosops","enter - operation: %d", op);
201 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
202 return SecXPCDictionarySetPList(message, kSecXPCKeySet, set1, error) && SecXPCDictionarySetPList(message, kSecXPCKeySet2, set2, error);
203 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
204 result = SecXPCDictionaryCopySet(response, kSecXPCKeyResult, error);
209 CFReleaseNull(result);
214 static CF_RETURNS_RETAINED CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
216 __block CFArrayRef result = NULL;
218 secdebug("sosops","enter - operation: %d", op);
219 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
220 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
221 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
222 return result != NULL;
224 if (!isArray(result)) {
225 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
226 CFReleaseNull(result);
232 static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
234 __block CFArrayRef result = NULL;
236 secdebug("sosops","enter - operation: %d", op);
237 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
239 const uint8_t* bytes = xpc_dictionary_get_data(response, kSecXPCKeyResult, &length);
240 der_decode_plist(kCFAllocatorDefault, 0, (CFPropertyListRef*) &result, error, bytes, bytes + length);
242 return result != NULL;
244 if (!isArray(result)) {
245 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
246 CFReleaseNull(result);
252 static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error)
254 __block int result = 0;
256 secdebug("sosops","enter - operation: %d", op);
257 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
258 int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
259 if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) {
260 result = (int)temp_result;
267 static CF_RETURNS_RETAINED SOSPeerInfoRef peer_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
269 SOSPeerInfoRef result = NULL;
270 __block CFDataRef data = NULL;
272 secdebug("sosops","enter - operation: %d", op);
273 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
274 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
275 if (response && (NULL != temp_result)) {
276 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
282 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
284 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
291 static CFDataRef flags_to_data_error_request(enum SecXPCOperation op, uint32_t flags, CFErrorRef *error)
293 __block CFDataRef result = NULL;
295 secdebug("sosops", "enter -- operation: %d", op);
296 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
297 xpc_dictionary_set_uint64(message, kSecXPCKeyFlags, flags);
299 }, ^bool(xpc_object_t response, CFErrorRef *error) {
300 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
301 if (response && (NULL != temp_result)) {
302 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
304 return result != NULL;
307 if (!isData(result)) {
308 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
316 static CFDataRef data_to_error_request(enum SecXPCOperation op, CFErrorRef *error)
318 __block CFDataRef result = NULL;
320 secdebug("sosops", "enter -- operation: %d", op);
321 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
322 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
323 if (response && (NULL != temp_result)) {
324 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
326 return result != NULL;
329 if (!isData(result)) {
330 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
337 static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
339 __block CFArrayRef result = NULL;
341 secdebug("sosops","enter - operation: %d", op);
342 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
343 xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult);
344 if (response && (NULL != encoded_array)) {
345 result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error);
347 return result != NULL;
350 if (!isArray(result)) {
351 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
352 CFReleaseNull(result);
357 static CF_RETURNS_RETAINED SOSPeerInfoRef data_to_peer_info_error_request(enum SecXPCOperation op, CFDataRef secret, CFErrorRef* error)
359 __block SOSPeerInfoRef result = false;
360 __block CFDataRef data = NULL;
362 secdebug("sosops", "enter - operation: %d", op);
363 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
364 xpc_object_t xsecretData = _CFXPCCreateXPCObjectFromCFObject(secret);
365 bool success = false;
367 xpc_dictionary_set_value(message, kSecXPCKeyNewPublicBackupKey, xsecretData);
372 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
373 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
374 if (response && (NULL != temp_result)) {
375 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
381 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
383 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
390 static bool keybag_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, bool include, CFErrorRef* error)
392 secdebug("sosops", "enter - operation: %d", op);
393 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
394 xpc_object_t xData = _CFXPCCreateXPCObjectFromCFObject(data);
395 bool success = false;
397 xpc_dictionary_set_value(message, kSecXPCKeyKeybag, xData);
401 xpc_dictionary_set_bool(message, kSecXPCKeyIncludeV0, include);
403 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
404 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
408 static bool recovery_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, CFErrorRef* error)
410 secdebug("sosops", "enter - operation: %d", op);
411 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
412 xpc_object_t xData = NULL;
414 xData = _CFXPCCreateXPCObjectFromCFObject(data);
417 CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, &zero, 1);
418 xData = _CFXPCCreateXPCObjectFromCFObject(nullData);
419 CFReleaseNull(nullData);
421 bool success = false;
423 xpc_dictionary_set_value(message, kSecXPCKeyRecoveryPublicKey, xData);
428 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
429 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
433 static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error)
435 __block bool result = false;
437 secdebug("sosops", "enter - operation: %d", op);
438 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
439 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
441 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
442 return encoded_peers != NULL;
443 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
444 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
450 static bool info_array_data_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFDataRef parentEvent, CFErrorRef* error)
452 __block bool result = false;
454 secdebug("sosops", "enter - operation: %d", op);
455 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
456 SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
457 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
459 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
460 return encoded_peers != NULL;
461 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
462 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
468 static bool uint64_t_to_bool_error_request(enum SecXPCOperation op,
472 __block bool result = false;
474 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
475 xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number);
477 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
478 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
485 static bool cfdata_and_int_error_request_returns_bool(enum SecXPCOperation op, CFDataRef thedata,
486 PiggyBackProtocolVersion version, CFErrorRef *error) {
487 __block bool result = false;
489 sec_trace_enter_api(NULL);
490 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
491 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
492 bool success = false;
494 xpc_dictionary_set_value(message, kSecXPCData, xdata);
495 xpc_dictionary_set_uint64(message, kSecXPCVersion, version);
501 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
502 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
509 static CFDataRef cfdata_error_request_returns_cfdata(enum SecXPCOperation op, CFDataRef thedata, CFErrorRef *error) {
510 __block CFDataRef result = NULL;
512 sec_trace_enter_api(NULL);
513 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
514 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
515 bool success = false;
517 xpc_dictionary_set_value(message, kSecXPCData, xdata);
522 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
523 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
524 if (response && (NULL != temp_result)) {
525 CFTypeRef object = _CFXPCCreateCFObjectFromXPCObject(temp_result);
526 result = copyIfData(object, error);
527 CFReleaseNull(object);
529 return (bool) (result != NULL);
535 bool SOSCCRequestToJoinCircle(CFErrorRef* error)
537 sec_trace_enter_api(NULL);
538 sec_trace_return_bool_api(^{
539 do_if_registered(soscc_RequestToJoinCircle, error);
541 return simple_bool_error_request(kSecXPCOpRequestToJoin, error);
545 bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
547 sec_trace_enter_api(NULL);
548 sec_trace_return_bool_api(^{
549 do_if_registered(soscc_RequestToJoinCircleWithAnalytics, parentEvent, error);
551 return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinWithAnalytics, parentEvent, error);
555 bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error)
557 sec_trace_enter_api(NULL);
558 sec_trace_return_bool_api(^{
559 do_if_registered(soscc_RequestToJoinCircleAfterRestore, error);
561 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error);
565 bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
567 sec_trace_enter_api(NULL);
568 sec_trace_return_bool_api(^{
569 do_if_registered(soscc_RequestToJoinCircleAfterRestoreWithAnalytics, parentEvent, error);
571 return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, parentEvent, error);
575 bool SOSCCAccountHasPublicKey(CFErrorRef *error)
577 sec_trace_enter_api(NULL);
578 sec_trace_return_bool_api(^{
579 do_if_registered(soscc_AccountHasPublicKey, error);
581 return simple_bool_error_request(kSecXPCOpAccountHasPublicKey, error);
586 bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
588 sec_trace_enter_api(NULL);
589 sec_trace_return_bool_api(^{
590 do_if_registered(soscc_WaitForInitialSyncWithAnalytics, parentEvent, error);
592 return sfsigninanalytics_bool_error_request(kSecXPCOpWaitForInitialSyncWithAnalytics, parentEvent, error);
596 bool SOSCCWaitForInitialSync(CFErrorRef* error)
598 sec_trace_enter_api(NULL);
599 sec_trace_return_bool_api(^{
600 do_if_registered(soscc_WaitForInitialSync, error);
602 return simple_bool_error_request(kSecXPCOpWaitForInitialSync, error);
606 bool SOSCCAccountSetToNew(CFErrorRef *error)
608 secwarning("SOSCCAccountSetToNew called");
609 sec_trace_enter_api(NULL);
610 sec_trace_return_bool_api(^{
611 do_if_registered(soscc_SetToNew, error);
612 return simple_bool_error_request(kSecXPCOpAccountSetToNew, error);
616 bool SOSCCResetToOffering(CFErrorRef* error)
618 secwarning("SOSCCResetToOffering called");
619 sec_trace_enter_api(NULL);
620 sec_trace_return_bool_api(^{
621 do_if_registered(soscc_ResetToOffering, error);
623 return simple_bool_error_request(kSecXPCOpResetToOffering, error);
627 bool SOSCCResetToEmpty(CFErrorRef* error)
629 secwarning("SOSCCResetToEmpty called");
630 sec_trace_enter_api(NULL);
631 sec_trace_return_bool_api(^{
632 do_if_registered(soscc_ResetToEmpty, error);
634 return simple_bool_error_request(kSecXPCOpResetToEmpty, error);
638 bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
640 secwarning("SOSCCResetToEmptyWithAnalytics called");
641 sec_trace_enter_api(NULL);
642 sec_trace_return_bool_api(^{
643 do_if_registered(soscc_ResetToEmptyWithAnalytics, parentEvent, error);
645 return sfsigninanalytics_bool_error_request(kSecXPCOpResetToEmptyWithAnalytics, parentEvent, error);
648 bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error)
650 sec_trace_enter_api(NULL);
651 sec_trace_return_bool_api(^{
652 do_if_registered(soscc_RemovePeersFromCircle, peers, error);
654 return info_array_to_bool_error_request(kSecXPCOpRemovePeersFromCircle, peers, error);
658 bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error)
660 sec_trace_enter_api(NULL);
661 sec_trace_return_bool_api(^{
662 do_if_registered(soscc_RemovePeersFromCircleWithAnalytics, peers, parentEvent, error);
664 return info_array_data_to_bool_error_request(kSecXPCOpRemovePeersFromCircleWithAnalytics, peers, parentEvent, error);
668 bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
670 sec_trace_enter_api(NULL);
671 sec_trace_return_bool_api(^{
672 do_if_registered(soscc_RemoveThisDeviceFromCircleWithAnalytics, parentEvent, error);
674 return sfsigninanalytics_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, parentEvent, error);
678 bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
680 sec_trace_enter_api(NULL);
681 sec_trace_return_bool_api(^{
682 do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
684 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
688 bool SOSCCLoggedOutOfAccount(CFErrorRef* error)
690 sec_trace_enter_api(NULL);
691 sec_trace_return_bool_api(^{
692 do_if_registered(soscc_LoggedOutOfAccount, error);
694 return simple_bool_error_request(kSecXPCOpLoggedOutOfAccount, error);
698 bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error)
700 sec_trace_enter_api(NULL);
701 sec_trace_return_bool_api(^{
702 do_if_registered(soscc_BailFromCircle, limit_in_seconds, error);
704 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error);
708 CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error)
710 sec_trace_enter_api(NULL);
711 sec_trace_return_api(CFArrayRef, ^{
712 do_if_registered(soscc_CopyPeerInfo, error);
714 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error);
715 }, CFSTR("return=%@"));
718 CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error)
720 sec_trace_enter_api(NULL);
721 sec_trace_return_api(CFArrayRef, ^{
722 do_if_registered(soscc_CopyConcurringPeerInfo, error);
724 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error);
725 }, CFSTR("return=%@"));
728 CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error)
730 sec_trace_enter_api(NULL);
731 sec_trace_return_api(CFArrayRef, ^{
732 do_if_registered(soscc_CopyGenerationPeerInfo, error);
734 return simple_array_error_request(kSecXPCOpCopyGenerationPeerInfo, error);
735 }, CFSTR("return=%@"));
738 CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error)
740 sec_trace_enter_api(NULL);
741 sec_trace_return_api(CFArrayRef, ^{
742 do_if_registered(soscc_CopyApplicantPeerInfo, error);
744 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error);
745 }, CFSTR("return=%@"));
748 bool SOSCCValidateUserPublic(CFErrorRef* error){
749 sec_trace_enter_api(NULL);
750 sec_trace_return_api(bool, ^{
751 do_if_registered(soscc_ValidateUserPublic, error);
753 return simple_bool_error_request(kSecXPCOpValidateUserPublic, error);
757 CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error)
759 sec_trace_enter_api(NULL);
760 sec_trace_return_api(CFArrayRef, ^{
761 do_if_registered(soscc_CopyValidPeerPeerInfo, error);
763 return array_of_info_error_request(kSecXPCOpCopyValidPeerPeerInfo, error);
764 }, CFSTR("return=%@"));
767 CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error)
769 sec_trace_enter_api(NULL);
770 sec_trace_return_api(CFArrayRef, ^{
771 do_if_registered(soscc_CopyNotValidPeerPeerInfo, error);
773 return array_of_info_error_request(kSecXPCOpCopyNotValidPeerPeerInfo, error);
774 }, CFSTR("return=%@"));
777 CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error)
779 sec_trace_enter_api(NULL);
780 sec_trace_return_api(CFArrayRef, ^{
781 do_if_registered(soscc_CopyRetirementPeerInfo, error);
783 return array_of_info_error_request(kSecXPCOpCopyRetirementPeerInfo, error);
784 }, CFSTR("return=%@"));
787 CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error)
789 sec_trace_enter_api(NULL);
790 sec_trace_return_api(CFArrayRef, ^{
791 do_if_registered(soscc_CopyViewUnawarePeerInfo, error);
793 return array_of_info_error_request(kSecXPCOpCopyViewUnawarePeerInfo, error);
794 }, CFSTR("return=%@"));
797 SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error)
799 sec_trace_enter_api(NULL);
800 sec_trace_return_api(SOSPeerInfoRef, ^{
801 do_if_registered(soscc_CopyMyPeerInfo, error);
803 return peer_info_error_request(kSecXPCOpCopyMyPeerInfo, error);
804 }, CFSTR("return=%@"));
807 static CFArrayRef SOSCCCopyEngineState(CFErrorRef* error)
809 sec_trace_enter_api(NULL);
810 sec_trace_return_api(CFArrayRef, ^{
811 do_if_registered(soscc_CopyEngineState, error);
813 return der_array_error_request(kSecXPCOpCopyEngineState, error);
814 }, CFSTR("return=%@"));
817 CFStringRef kSOSCCEngineStatePeerIDKey = CFSTR("PeerID");
818 CFStringRef kSOSCCEngineStateManifestCountKey = CFSTR("ManifestCount");
819 CFStringRef kSOSCCEngineStateSyncSetKey = CFSTR("SyncSet");
820 CFStringRef kSOSCCEngineStateCoderKey = CFSTR("CoderDump");
821 CFStringRef kSOSCCEngineStateManifestHashKey = CFSTR("ManifestHash");
823 void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)) {
825 CFArrayForEach(states, ^(const void *value) {
826 CFDictionaryRef dict = asDictionary(value, NULL);
828 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
830 CFStringRef id = asString(CFDictionaryGetValue(dict, kSOSCCEngineStatePeerIDKey), NULL);
833 CFStringAppendFormat(description, NULL, CFSTR("remote %@ "), id);
835 CFStringAppendFormat(description, NULL, CFSTR("local "));
838 CFSetRef viewSet = asSet(CFDictionaryGetValue(dict, kSOSCCEngineStateSyncSetKey), NULL);
840 CFStringSetPerformWithDescription(viewSet, ^(CFStringRef setDescription) {
841 CFStringAppend(description, setDescription);
844 CFStringAppendFormat(description, NULL, CFSTR("<Missing view set!>"));
847 CFStringAppendFormat(description, NULL, CFSTR(" [%@]"),
848 CFDictionaryGetValue(dict, kSOSCCEngineStateManifestCountKey));
850 CFDataRef mainfestHash = asData(CFDictionaryGetValue(dict, kSOSCCEngineStateManifestHashKey), NULL);
853 CFDataPerformWithHexString(mainfestHash, ^(CFStringRef dataString) {
854 CFStringAppendFormat(description, NULL, CFSTR(" %@"), dataString);
858 CFStringRef coderDescription = asString(CFDictionaryGetValue(dict, kSOSCCEngineStateCoderKey), NULL);
859 if (coderDescription) {
860 CFStringAppendFormat(description, NULL, CFSTR(" %@"), coderDescription);
865 CFReleaseNull(description);
870 bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRef oneStateString)) {
871 CFArrayRef states = SOSCCCopyEngineState(error);
875 SOSCCForEachEngineStateAsStringFromArray(states, block);
877 CFReleaseNull(states);
883 bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error)
885 sec_trace_enter_api(NULL);
886 sec_trace_return_bool_api(^{
887 do_if_registered(soscc_AcceptApplicants, applicants, error);
889 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error);
893 bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error)
895 sec_trace_enter_api(CFSTR("applicants=%@"), applicants);
896 sec_trace_return_bool_api(^{
897 do_if_registered(soscc_RejectApplicants, applicants, error);
899 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error);
903 static CF_RETURNS_RETAINED SOSPeerInfoRef SOSSetNewPublicBackupKey(CFDataRef pubKey, CFErrorRef *error)
905 sec_trace_enter_api(NULL);
906 sec_trace_return_api(SOSPeerInfoRef, ^{
907 do_if_registered(soscc_SetNewPublicBackupKey, pubKey, error);
909 return data_to_peer_info_error_request(kSecXPCOpSetNewPublicBackupKey, pubKey, error);
910 }, CFSTR("return=%@"));
913 SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFErrorRef *error){
914 secnotice("devRecovery", "Enter SOSCCCopyMyPeerWithNewDeviceRecoverySecret()");
915 CFDataRef publicKeyData = SOSCopyDeviceBackupPublicKey(secret, error);
916 secnotice("devRecovery", "SOSCopyDeviceBackupPublicKey (%@)", publicKeyData);
917 SOSPeerInfoRef copiedPeer = publicKeyData ? SOSSetNewPublicBackupKey(publicKeyData, error) : NULL;
918 secnotice("devRecovery", "SOSSetNewPublicBackupKey (%@)", copiedPeer);
919 CFReleaseNull(publicKeyData);
923 bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error){
924 sec_trace_enter_api(NULL);
925 sec_trace_return_bool_api(^{
926 do_if_registered(soscc_RegisterSingleRecoverySecret, aks_bag, forV0Only, error);
927 return keybag_and_bool_to_bool_error_request(kSecXPCOpSetBagForAllSlices, aks_bag, forV0Only, error);
932 bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){
933 sec_trace_enter_api(NULL);
934 sec_trace_return_bool_api(^{
936 do_if_registered(soscc_RegisterRecoveryPublicKey, recovery_key, error);
937 // NULL recovery_key is handled in recovery_and_bool_to_bool_error_request now.
938 retval = recovery_and_bool_to_bool_error_request(kSecXPCOpRegisterRecoveryPublicKey, recovery_key, error);
943 CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error){
944 sec_trace_enter_api(NULL);
945 sec_trace_return_api(CFDataRef, ^{
946 do_if_registered(soscc_CopyRecoveryPublicKey, error);
947 return data_to_error_request(kSecXPCOpGetRecoveryPublicKey, error);
948 }, CFSTR("return=%@"));
950 static bool label_and_password_to_bool_error_request(enum SecXPCOperation op,
951 CFStringRef user_label, CFDataRef user_password,
954 __block bool result = false;
956 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
957 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
958 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
960 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
962 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
963 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
970 static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperation op,
971 CFStringRef user_label, CFDataRef user_password,
972 CFStringRef dsid, CFDataRef parentEvent, CFErrorRef* error)
974 __block bool result = false;
976 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
977 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
978 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
980 CFStringPerformWithCString(dsid, ^(const char *utr8StrDSID) {
981 xpc_dictionary_set_string(message, kSecXPCKeyDSID, utr8StrDSID);
983 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
985 SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
988 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
989 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
996 bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
998 secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label);
999 return SOSCCSetUserCredentials(user_label, user_password, error);
1002 bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
1004 secnotice("circleOps", "SOSCCSetUserCredentials for %@\n", user_label);
1005 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1006 sec_trace_return_bool_api(^{
1007 do_if_registered(soscc_SetUserCredentials, user_label, user_password, error);
1009 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error);
1013 bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1015 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSID for %@\n", user_label);
1016 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1017 sec_trace_return_bool_api(^{
1018 do_if_registered(soscc_SetUserCredentialsAndDSID, user_label, user_password, dsid, error);
1020 bool result = false;
1021 __block CFStringRef account_dsid = dsid;
1023 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1024 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1026 if(account_dsid == NULL){
1027 account_dsid = CFSTR("");
1029 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, nil, error);
1036 bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error)
1038 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSIDWithAnalytics for %@\n", user_label);
1039 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1040 sec_trace_return_bool_api(^{
1041 do_if_registered(soscc_SetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, dsid, parentEvent, error);
1043 bool result = false;
1044 __block CFStringRef account_dsid = dsid;
1046 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1047 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1049 if(account_dsid == NULL){
1050 account_dsid = CFSTR("");
1052 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, account_dsid, parentEvent, error);
1059 static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) {
1060 sec_trace_return_bool_api(^{
1061 do_if_registered(soscc_TryUserCredentials, user_label, user_password, dsid, error);
1063 bool result = false;
1064 __block CFStringRef account_dsid = dsid;
1066 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1067 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1069 if(account_dsid == NULL){
1070 account_dsid = CFSTR("");
1073 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, nil, error);
1081 bool SOSCCTryUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1083 secnotice("sosops", "SOSCCTryUserCredentialsAndDSID!! %@\n", user_label);
1084 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1085 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1086 CFStringRef account_dsid = (dsid != NULL) ? dsid: CFSTR("");
1087 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, account_dsid, error);
1092 bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) {
1093 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, NULL, error);
1097 bool SOSCCCanAuthenticate(CFErrorRef* error) {
1098 sec_trace_enter_api(NULL);
1099 sec_trace_return_bool_api(^{
1100 do_if_registered(soscc_CanAuthenticate, error);
1102 return simple_bool_error_request(kSecXPCOpCanAuthenticate, error);
1106 bool SOSCCPurgeUserCredentials(CFErrorRef* error) {
1107 sec_trace_enter_api(NULL);
1108 sec_trace_return_bool_api(^{
1109 do_if_registered(soscc_PurgeUserCredentials, error);
1111 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error);
1115 enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) {
1116 sec_trace_enter_api(NULL);
1117 sec_trace_return_api(enum DepartureReason, ^{
1118 do_if_registered(soscc_GetLastDepartureReason, error);
1120 return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error);
1124 bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) {
1125 sec_trace_enter_api(NULL);
1126 sec_trace_return_api(bool, ^{
1127 do_if_registered(soscc_SetLastDepartureReason, reason, error);
1128 return securityd_send_sync_and_do(kSecXPCOpSetLastDepartureReason, error,
1129 ^bool(xpc_object_t message, CFErrorRef *error) {
1130 xpc_dictionary_set_int64(message, kSecXPCKeyReason, reason);
1133 ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1134 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1140 bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){
1141 secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration");
1142 sec_trace_enter_api(NULL);
1143 sec_trace_return_bool_api(^{
1144 do_if_registered(soscc_EnsurePeerRegistration, error);
1146 return simple_bool_error_request(soscc_EnsurePeerRegistration_id, error);
1151 CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFErrorRef* error)
1153 sec_trace_enter_api(NULL);
1154 sec_trace_return_api(CFSetRef, ^{
1155 do_if_registered(soscc_ProcessSyncWithPeers, peers, backupPeers, error);
1157 return cfset_cfset_to_cfset_error_request(kSecXPCOpProcessSyncWithPeers, peers, backupPeers, error);
1162 SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error)
1164 sec_trace_enter_api(NULL);
1165 sec_trace_return_api(SyncWithAllPeersReason, ^{
1166 do_if_registered(soscc_ProcessSyncWithAllPeers, error);
1168 return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error);
1172 CFStringRef SOSCCGetStatusDescription(SOSCCStatus status)
1175 case kSOSCCInCircle:
1176 return CFSTR("InCircle");
1177 case kSOSCCNotInCircle:
1178 return CFSTR("NotInCircle");
1179 case kSOSCCRequestPending:
1180 return CFSTR("RequestPending");
1181 case kSOSCCCircleAbsent:
1182 return CFSTR("CircleAbsent");
1184 return CFSTR("InternalError");
1186 return CFSTR("Unknown Status");
1191 CFStringRef SOSCCGetViewResultDescription(SOSViewResultCode vrc)
1194 case kSOSCCGeneralViewError:
1195 return CFSTR("GeneralViewError");
1196 case kSOSCCViewMember:
1197 return CFSTR("ViewMember");
1198 case kSOSCCViewNotMember:
1199 return CFSTR("ViewNotMember");
1200 case kSOSCCViewNotQualified:
1201 return CFSTR("ViewNotQualified");
1202 case kSOSCCNoSuchView:
1203 return CFSTR("ViewUndefined");
1205 return CFSTR("Unknown View Status");
1210 static int64_t name_action_to_code_request(enum SecXPCOperation op, uint16_t error_result,
1211 CFStringRef name, uint64_t action, CFErrorRef *error) {
1212 __block int64_t result = error_result;
1214 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1215 CFStringPerformWithCString(name, ^(const char *utf8Str) {
1216 xpc_dictionary_set_string(message, kSecXPCKeyViewName, utf8Str);
1218 xpc_dictionary_set_int64(message, kSecXPCKeyViewActionCode, action);
1220 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1221 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
1222 result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
1224 return result != error_result;
1230 SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) {
1231 if(actionCode == kSOSCCViewQuery) {
1232 uint64_t circleStat = SOSGetCachedCircleBitmask();
1233 if(circleStat & CC_STATISVALID) {
1234 SOSViewResultCode retval = kSOSCCViewNotMember;
1235 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1237 if(CFSetContainsValue(enabledViews, view)) {
1238 retval = kSOSCCViewMember;
1240 retval = kSOSCCViewNotMember;
1242 CFReleaseNull(enabledViews);
1247 sec_trace_enter_api(NULL);
1248 sec_trace_return_api(SOSViewResultCode, ^{
1249 do_if_registered(soscc_View, view, actionCode, error);
1251 return (SOSViewResultCode) name_action_to_code_request(kSecXPCOpView, kSOSCCGeneralViewError, view, actionCode, error);
1252 }, CFSTR("SOSViewResultCode=%d"))
1256 bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) {
1257 CFErrorRef *error = NULL;
1258 __block bool result = false;
1260 sec_trace_enter_api(NULL);
1261 sec_trace_return_bool_api(^{
1262 do_if_registered(soscc_ViewSet, enabledViews, disabledViews);
1263 return securityd_send_sync_and_do(kSecXPCOpViewSet, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1264 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1265 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1266 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1267 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1268 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1269 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1270 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1276 bool SOSCCViewSetWithAnalytics(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) {
1277 CFErrorRef *error = NULL;
1278 __block bool result = false;
1280 sec_trace_enter_api(NULL);
1281 sec_trace_return_bool_api(^{
1282 do_if_registered(soscc_ViewSetWithAnalytics, enabledViews, disabledViews, parentEvent);
1283 return securityd_send_sync_and_do(kSecXPCOpViewSetWithAnalytics, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1284 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1285 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1286 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1287 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1288 if(parentEvent) SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
1289 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1290 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1291 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1297 static CFStringRef copyViewNames(size_t n, CFStringRef *views) {
1298 CFMutableStringRef retval = CFStringCreateMutable(kCFAllocatorDefault, 0);
1299 CFStringAppend(retval, CFSTR("|"));
1300 for(size_t i = 0; i < n; i++) {
1301 CFStringAppend(retval, views[i]);
1302 CFStringAppend(retval, CFSTR("|"));
1307 static bool sosIsViewSetSyncing(size_t n, CFStringRef *views) {
1308 __block bool retval = true;
1309 CFErrorRef error = NULL;
1311 if(n == 0 || views == NULL) return false;
1312 CFStringRef viewString = copyViewNames(n, views);
1314 SOSCCStatus cstatus = SOSCCThisDeviceIsInCircle(&error);
1315 if(cstatus != kSOSCCInCircle) {
1316 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) Error: (%@)", viewString, SOSCCGetStatusDescription(cstatus), error);
1320 if(retval == true) {
1321 // use cached values if valid
1322 uint64_t circleStat = SOSGetCachedCircleBitmask();
1323 if(circleStat & CC_STATISVALID) {
1324 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1326 for(size_t i = 0; i < n; i++) {
1327 if(!CFSetContainsValue(enabledViews, views[i])) {
1331 CFReleaseNull(enabledViews);
1332 CFReleaseNull(viewString);
1337 // make the individual calls otherwise.
1338 for(size_t i = 0; i < n; i++) {
1339 SOSViewResultCode vstatus = SOSCCView(views[i], kSOSCCViewQuery, &error);
1340 if(vstatus != kSOSCCViewMember) {
1341 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) SOSViewResultCode(%@) Error: (%@)", views[i],
1342 SOSCCGetStatusDescription(cstatus), SOSCCGetViewResultDescription(vstatus), error);
1348 if(retval == true) {
1349 secnotice("viewCheck", "Checking view / circle status for %@: ENABLED", viewString);
1351 CFReleaseNull(error);
1352 CFReleaseNull(viewString);
1356 bool SOSCCIsIcloudKeychainSyncing(void) {
1357 CFStringRef views[] = { kSOSViewWiFi, kSOSViewAutofillPasswords, kSOSViewSafariCreditCards, kSOSViewOtherSyncable };
1358 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1361 bool SOSCCIsSafariSyncing(void) {
1362 CFStringRef views[] = { kSOSViewAutofillPasswords, kSOSViewSafariCreditCards };
1363 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1366 bool SOSCCIsAppleTVSyncing(void) {
1367 CFStringRef views[] = { kSOSViewAppleTV };
1368 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1371 bool SOSCCIsHomeKitSyncing(void) {
1372 CFStringRef views[] = { kSOSViewHomeKit };
1373 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1376 bool SOSCCIsWiFiSyncing(void) {
1377 CFStringRef views[] = { kSOSViewWiFi };
1378 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1381 bool SOSCCIsContinuityUnlockSyncing(void) {
1382 CFStringRef views[] = { kSOSViewContinuityUnlock };
1383 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1386 SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) {
1387 secnotice("hsa2PB", "enter SOSCCCopyApplication applicant");
1388 sec_trace_enter_api(NULL);
1390 sec_trace_return_api(SOSPeerInfoRef, ^{
1391 do_if_registered(soscc_CopyApplicant, error);
1392 return peer_info_error_request(kSecXPCOpCopyApplication, error);
1393 }, CFSTR("return=%@"));
1396 bool SOSCCCleanupKVSKeys(CFErrorRef *error) {
1397 secnotice("cleanup-keys", "enter SOSCCCleanupKVSKeys");
1398 sec_trace_enter_api(NULL);
1399 sec_trace_return_bool_api(^{
1400 do_if_registered(soscc_SOSCCCleanupKVSKeys, error);
1402 return simple_bool_error_request(kSecXPCOpKVSKeyCleanup, error);
1408 CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error) {
1409 secnotice("hsa2PB", "enter SOSCCCopyCircleJoiningBlob approver");
1410 sec_trace_enter_api(NULL);
1412 sec_trace_return_api(CFDataRef, ^{
1413 CFDataRef result = NULL;
1414 do_if_registered(soscc_CopyCircleJoiningBlob, applicant, error);
1415 CFDataRef piData = SOSPeerInfoCopyEncodedData(applicant, kCFAllocatorDefault, error);
1416 result = cfdata_error_request_returns_cfdata(kSecXPCOpCopyCircleJoiningBlob, piData, error);
1417 CFReleaseNull(piData);
1419 }, CFSTR("return=%@"));
1422 CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) {
1423 secnotice("circleJoin", "enter SOSCCCopyInitialSyncData approver");
1424 sec_trace_enter_api(NULL);
1426 sec_trace_return_api(CFDataRef, ^{
1427 do_if_registered(soscc_CopyInitialSyncData, flags, error);
1428 return flags_to_data_error_request(kSecXPCOpCopyInitialSyncBlob, flags, error);
1429 }, CFSTR("return=%@"));
1432 bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error) {
1433 secnotice("hsa2PB", "enter SOSCCJoinWithCircleJoiningBlob applicant");
1434 sec_trace_enter_api(NULL);
1435 sec_trace_return_bool_api(^{
1436 do_if_registered(soscc_JoinWithCircleJoiningBlob, joiningBlob, version, error);
1438 return cfdata_and_int_error_request_returns_bool(kSecXPCOpJoinWithCircleJoiningBlob, joiningBlob, version, error);
1442 CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) {
1443 secnotice("view-enabled", "enter SOSCCPeersHaveViewsEnabled");
1444 sec_trace_enter_api(NULL);
1445 sec_trace_return_api(CFBooleanRef, ^{
1446 do_if_registered(soscc_SOSCCPeersHaveViewsEnabled, viewNames, error);
1448 return cfarray_to_cfboolean_error_request(kSecXPCOpPeersHaveViewsEnabled, viewNames, error);
1449 }, CFSTR("return=%@"))
1452 bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
1453 secnotice("pending-check", "enter SOSCCMessageFromPeerIsPending");
1455 sec_trace_return_bool_api(^{
1456 do_if_registered(soscc_SOSCCMessageFromPeerIsPending, peer, error);
1458 return peer_info_to_bool_error_request(kSecXPCOpMessageFromPeerIsPending, peer, error);
1463 bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
1464 sec_trace_return_bool_api(^{
1465 do_if_registered(soscc_SOSCCSendToPeerIsPending, peer, error);
1467 return peer_info_to_bool_error_request(kSecXPCOpSendToPeerIsPending, peer, error);
1472 * SecSOSStatus interfaces
1475 @interface SecSOSStatus : NSObject {
1476 NSXPCConnection* _connection;
1478 @property NSXPCConnection *connection;
1481 @implementation SecSOSStatus
1482 @synthesize connection = _connection;
1484 - (instancetype) init
1486 if ((self = [super init]) == NULL)
1489 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
1490 _SOSControlSetupInterface(interface);
1492 self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydSOSServiceName) options:0];
1493 if (self.connection == NULL){
1496 self.connection.remoteObjectInterface = interface;
1498 [self.connection resume];
1505 static id<SOSControlProtocol>
1506 SOSCCGetStatusObject(CFErrorRef *error)
1508 if (gSecurityd && gSecurityd->soscc_status)
1509 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1511 static SecSOSStatus *control;
1512 static dispatch_once_t onceToken;
1513 dispatch_once(&onceToken, ^{
1514 control = [[SecSOSStatus alloc] init];
1516 return control.connection.remoteObjectProxy;
1520 static id<SOSControlProtocol>
1521 SOSCCGetSynchronousStatusObject(CFErrorRef *cferror) {
1522 if (gSecurityd && gSecurityd->soscc_status)
1523 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1525 static SecSOSStatus *control;
1526 static dispatch_once_t onceToken;
1527 dispatch_once(&onceToken, ^{
1528 control = [[SecSOSStatus alloc] init];
1531 __block NSError *localError = nil;
1532 id <SOSControlProtocol> synchronousRemoteObject = [control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
1533 secnotice("ghostbust", "An error occurred on the xpc connection to setup the background session: %@", error );
1538 if(cferror && localError) {
1539 *cferror = (__bridge CFErrorRef)(localError);
1541 return synchronousRemoteObject;
1547 SOSCCAccountGetPublicKey(void (^reply)(BOOL trusted, NSData *data, NSError *error))
1549 CFErrorRef error = NULL;
1550 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1551 if (status == NULL) {
1552 reply(false, NULL, (__bridge NSError *)error);
1553 CFReleaseNull(error);
1557 [status userPublicKey:reply];
1561 SOSCCAccountGetAccountPrivateCredential(void (^complete)(NSData *data, NSError *error))
1563 CFErrorRef error = NULL;
1564 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1565 if (status == NULL) {
1566 complete(NULL, (__bridge NSError *)error);
1567 CFReleaseNull(error);
1571 [status validatedStashedAccountCredential:complete];
1575 SOSCCAccountGetKeyCircleGeneration(void (^reply)(NSData *data, NSError *error))
1577 SOSCCAccountGetPublicKey(^(BOOL __unused trusted, NSData *data, NSError *error){
1581 NSMutableData *digest = [NSMutableData dataWithLength:CCSHA256_OUTPUT_SIZE];
1582 ccdigest(ccsha256_di(), [data length], [data bytes], [digest mutableBytes]);
1583 reply(digest, error);
1589 SOSCCCircleHash(NSError **error)
1591 CFErrorRef cferror = NULL;
1592 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&cferror);
1593 if (status == NULL) {
1595 *error = (__bridge NSError *)cferror;
1597 CFReleaseNull(cferror);
1600 __block NSString *hash = NULL;
1601 [status circleHash:^(NSString *circleHash, NSError *error) {
1610 SOSCCGhostBust(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1611 CFErrorRef error = NULL;
1612 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1613 if (status == NULL) {
1614 complete(false, (__bridge NSError *)error);
1615 CFReleaseNull(error);
1618 secnotice("ghostbust", "API Called");
1619 [status ghostBust:options complete:^(bool ghostBusted, NSError *error) {
1620 secnotice("ghostbust", "API returned: %d", ghostBusted);
1621 complete(ghostBusted, error);
1625 void SOSCCGhostBustTriggerTimed(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1626 CFErrorRef error = NULL;
1627 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1628 if (status == NULL) {
1629 complete(false, (__bridge NSError *)error);
1630 CFReleaseNull(error);
1633 secnotice("ghostbust", "API Trigger Timed Called");
1634 [status ghostBustTriggerTimed:options complete:^(bool ghostBusted, NSError *error) {
1635 secnotice("ghostbust", "API Trigger Timed returned: %d", ghostBusted);
1636 complete(ghostBusted, error);
1640 void SOSCCGhostBustInfo(void (^complete)(NSData *json, NSError *error)) {
1641 CFErrorRef error = NULL;
1642 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1643 if (status == NULL) {
1644 complete(false, (__bridge NSError *)error);
1645 CFReleaseNull(error);
1648 secnotice("ghostbust", "API Info Called");
1649 [status ghostBustInfo:^(NSData *json, NSError *error) {
1650 secnotice("ghostbust", "API Info returned");
1651 complete(json, error);