]> git.saurik.com Git - apple/security.git/blame - keychain/SecureObjectSync/SOSCloudCircle.m
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSCloudCircle.m
CommitLineData
5c19dc3a
A
1/*
2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24//
25// SOSCloudCircle.m
26//
27
866f8763
A
28#import <Foundation/Foundation.h>
29#import <Foundation/NSXPCConnection_Private.h>
30
5c19dc3a
A
31#include <stdio.h>
32#include <AssertMacros.h>
b54c578e
A
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"
5c19dc3a 41#include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
866f8763 42#include <Security/SecureObjectSync/SOSViews.h>
b54c578e
A
43#include "keychain/SecureObjectSync/SOSControlHelper.h"
44#include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
5c19dc3a
A
45
46#include <Security/SecKeyPriv.h>
47#include <Security/SecFramework.h>
48#include <CoreFoundation/CFXPCBridge.h>
49
7fb2cbd2 50#include "keychain/securityd/SecItemServer.h"
5c19dc3a
A
51
52#include <utilities/SecDispatchRelease.h>
53#include <utilities/SecCFRelease.h>
54#include <utilities/SecCFWrappers.h>
55#include <utilities/SecXPCError.h>
56
866f8763
A
57#include <corecrypto/ccsha2.h>
58
5c19dc3a
A
59#include <utilities/debugging.h>
60
61#include <CoreFoundation/CoreFoundation.h>
62
63#include <xpc/xpc.h>
64#define MINIMIZE_INCLUDES MINIMIZE_INCLUDES
65#include <ipc/securityd_client.h>
7fb2cbd2 66#include "keychain/securityd/spi.h"
5c19dc3a 67
5c19dc3a 68#include <Security/SecuritydXPC.h>
5c19dc3a
A
69
70const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged";
71const char * kSOSCCViewMembershipChangedNotification = "com.apple.security.secureobjectsync.viewschanged";
72const char * kSOSCCInitialSyncChangedNotification = "com.apple.security.secureobjectsync.initialsyncchanged";
e0e0d90e
A
73const char * kSOSCCHoldLockForInitialSync = "com.apple.security.secureobjectsync.holdlock";
74const char * kSOSCCPeerAvailable = "com.apple.security.secureobjectsync.peeravailable";
6b200bc3 75const char * kSOSCCRecoveryKeyChanged = "com.apple.security.secureobjectsync.recoverykeychanged";
8a50f688 76const char * kSOSCCCircleOctagonKeysChangedNotification = "com.apple.security.sosoctagonbitschanged";
5c19dc3a
A
77
78#define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
79
80static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type)
81{
82 xpc_object_t value = xpc_dictionary_get_value(dictionary, key);
83
84 return value && (xpc_get_type(value) == type);
85}
86
d64be36e
A
87static void setSOSDisabledError(CFErrorRef *error) {
88 SecCFCreateErrorWithFormat(0, kSOSErrorDomain, NULL, error, NULL, CFSTR("SOS Disabled for this platform"));
89}
90
5c19dc3a 91SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error)
79b9da22 92{
d64be36e
A
93 IF_SOS_DISABLED {
94 secdebug("circleOps", "SOS disabled for this platform");
95 setSOSDisabledError(error);
96 return kSOSCCError;
97 }
98
79b9da22
A
99 SOSCCStatus retval = SOSGetCachedCircleStatus(error);
100 if(retval != kSOSNoCachedValue) {
b54c578e 101 secdebug("circleOps", "Retrieved cached circle value %d", retval);
79b9da22
A
102 return retval;
103 }
104 return SOSCCThisDeviceIsInCircleNonCached(error);
105}
106
107
108SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error)
5c19dc3a 109{
d64be36e
A
110 IF_SOS_DISABLED {
111 secdebug("circleOps", "SOS disabled for this platform");
112 setSOSDisabledError(error);
113 return kSOSCCError;
114 }
115
5c19dc3a
A
116 sec_trace_enter_api(NULL);
117 sec_trace_return_api(SOSCCStatus, ^{
118 SOSCCStatus result = kSOSCCError;
79b9da22 119
5c19dc3a 120 do_if_registered(soscc_ThisDeviceIsInCircle, error);
79b9da22 121
5c19dc3a
A
122 xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error);
123 if (message) {
124 xpc_object_t response = securityd_message_with_reply_sync(message, error);
79b9da22 125
5c19dc3a
A
126 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
127 result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult);
128 } else {
129 result = kSOSCCError;
130 }
79b9da22 131
5c19dc3a
A
132 if (result < 0) {
133 if (response && securityd_message_no_error(response, error))
134 {
135 char *desc = xpc_copy_description(response);
136 SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc);
137 free((void *)desc);
138 }
139 }
5c19dc3a 140 }
79b9da22
A
141 secnotice("circleOps", "Retrieved non-cached circle value %d", result);
142
5c19dc3a
A
143 return result;
144 }, CFSTR("SOSCCStatus=%d"))
145}
146
5c19dc3a
A
147static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
148{
149 __block bool result = false;
fa7225c8 150
5c19dc3a
A
151 secdebug("sosops","enter - operation: %d", op);
152 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
153 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
154 return result;
155 });
156 return result;
157}
158
6b200bc3
A
159static bool SecXPCDictionarySetPeerInfoData(xpc_object_t message, const char *key, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
160 bool success = false;
161 CFDataRef peerData = SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, error);
162 if (peerData) {
163 success = SecXPCDictionarySetData(message, key, peerData, error);
164 }
165 CFReleaseNull(peerData);
166 return success;
167}
168
169static bool peer_info_to_bool_error_request(enum SecXPCOperation op, SOSPeerInfoRef peerInfo, CFErrorRef* error)
170{
171 __block bool result = false;
172
173 secdebug("sosops","enter - operation: %d", op);
174 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
175 return SecXPCDictionarySetPeerInfoData(message, kSecXPCKeyPeerInfo, peerInfo, error);
176 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
177 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
178 return result;
179 });
180 return result;
181}
182
fa7225c8
A
183static CFBooleanRef cfarray_to_cfboolean_error_request(enum SecXPCOperation op, CFArrayRef views, CFErrorRef* error)
184{
185 __block bool result = false;
186
187 secdebug("sosops","enter - operation: %d", op);
188 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
189 return SecXPCDictionarySetPList(message, kSecXPCKeyArray, views, error);
190 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
191 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
192 return true;
193 });
194 return noError ? (result ? kCFBooleanTrue : kCFBooleanFalse) : NULL;
195}
196
197
6b200bc3
A
198static CFSetRef cfset_cfset_to_cfset_error_request(enum SecXPCOperation op, CFSetRef set1, CFSetRef set2, CFErrorRef* error)
199{
200 __block CFSetRef result = NULL;
201
202 secdebug("sosops","enter - operation: %d", op);
203 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
204 return SecXPCDictionarySetPList(message, kSecXPCKeySet, set1, error) && SecXPCDictionarySetPList(message, kSecXPCKeySet2, set2, error);
205 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
206 result = SecXPCDictionaryCopySet(response, kSecXPCKeyResult, error);
207 return result;
208 });
209
210 if (!noError) {
211 CFReleaseNull(result);
212 }
213 return result;
214}
215
fa7225c8 216static CF_RETURNS_RETAINED CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
5c19dc3a
A
217{
218 __block CFArrayRef result = NULL;
6b200bc3 219
5c19dc3a
A
220 secdebug("sosops","enter - operation: %d", op);
221 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
222 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
223 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
224 return result != NULL;
225 })) {
226 if (!isArray(result)) {
227 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
228 CFReleaseNull(result);
229 }
230 }
231 return result;
232}
233
6b200bc3
A
234static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
235{
236 __block CFArrayRef result = NULL;
237
238 secdebug("sosops","enter - operation: %d", op);
239 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
240 size_t length = 0;
241 const uint8_t* bytes = xpc_dictionary_get_data(response, kSecXPCKeyResult, &length);
d64be36e 242 der_decode_plist(kCFAllocatorDefault, (CFPropertyListRef*) &result, error, bytes, bytes + length);
6b200bc3
A
243
244 return result != NULL;
245 })) {
246 if (!isArray(result)) {
247 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
248 CFReleaseNull(result);
249 }
250 }
251 return result;
252}
253
5c19dc3a
A
254static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error)
255{
256 __block int result = 0;
257
258 secdebug("sosops","enter - operation: %d", op);
259 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
260 int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
261 if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) {
262 result = (int)temp_result;
263 }
264 return result;
265 });
266 return result;
267}
268
ecaf5866 269static CF_RETURNS_RETAINED SOSPeerInfoRef peer_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
5c19dc3a
A
270{
271 SOSPeerInfoRef result = NULL;
272 __block CFDataRef data = NULL;
273
274 secdebug("sosops","enter - operation: %d", op);
275 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
276 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
277 if (response && (NULL != temp_result)) {
278 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
279 }
280 return data != NULL;
281 });
282
866f8763 283 if (isData(data)) {
5c19dc3a 284 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
866f8763
A
285 } else {
286 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
5c19dc3a 287 }
866f8763 288
5c19dc3a
A
289 CFReleaseNull(data);
290 return result;
291}
292
7fb2cbd2
A
293static CFDataRef flags_to_data_error_request(enum SecXPCOperation op, uint32_t flags, CFErrorRef *error)
294{
295 __block CFDataRef result = NULL;
296
297 secdebug("sosops", "enter -- operation: %d", op);
298 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
299 xpc_dictionary_set_uint64(message, kSecXPCKeyFlags, flags);
300 return true;
301 }, ^bool(xpc_object_t response, CFErrorRef *error) {
302 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
303 if (response && (NULL != temp_result)) {
304 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
305 }
306 return result != NULL;
307 });
308
309 if (!isData(result)) {
310 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
311 return NULL;
312 }
313
314 return result;
315}
316
317
e3d460c9
A
318static CFDataRef data_to_error_request(enum SecXPCOperation op, CFErrorRef *error)
319{
320 __block CFDataRef result = NULL;
321
322 secdebug("sosops", "enter -- operation: %d", op);
e3d460c9
A
323 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
324 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
325 if (response && (NULL != temp_result)) {
326 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
327 }
328 return result != NULL;
329 });
330
331 if (!isData(result)) {
332 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
333 return NULL;
334 }
335
336 return result;
337}
338
5c19dc3a
A
339static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
340{
341 __block CFArrayRef result = NULL;
342
343 secdebug("sosops","enter - operation: %d", op);
344 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
345 xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult);
346 if (response && (NULL != encoded_array)) {
347 result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error);
348 }
349 return result != NULL;
350 });
351
352 if (!isArray(result)) {
353 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
354 CFReleaseNull(result);
355 }
356 return result;
357}
358
6b200bc3 359static CF_RETURNS_RETAINED SOSPeerInfoRef data_to_peer_info_error_request(enum SecXPCOperation op, CFDataRef secret, CFErrorRef* error)
5c19dc3a
A
360{
361 __block SOSPeerInfoRef result = false;
362 __block CFDataRef data = NULL;
363
364 secdebug("sosops", "enter - operation: %d", op);
365 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
366 xpc_object_t xsecretData = _CFXPCCreateXPCObjectFromCFObject(secret);
367 bool success = false;
368 if (xsecretData){
369 xpc_dictionary_set_value(message, kSecXPCKeyNewPublicBackupKey, xsecretData);
370 success = true;
866f8763 371 xsecretData = nil;
5c19dc3a
A
372 }
373 return success;
374 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
375 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
376 if (response && (NULL != temp_result)) {
377 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
378 }
866f8763 379 return data != NULL;
5c19dc3a
A
380 });
381
866f8763 382 if (isData(data)) {
5c19dc3a 383 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
866f8763
A
384 } else {
385 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
5c19dc3a 386 }
866f8763 387
5c19dc3a
A
388 CFReleaseNull(data);
389 return result;
390}
391
392static bool keybag_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, bool include, CFErrorRef* error)
393{
394 secdebug("sosops", "enter - operation: %d", op);
395 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
396 xpc_object_t xData = _CFXPCCreateXPCObjectFromCFObject(data);
397 bool success = false;
398 if (xData){
399 xpc_dictionary_set_value(message, kSecXPCKeyKeybag, xData);
866f8763 400 xData = nil;
5c19dc3a
A
401 success = true;
402 }
403 xpc_dictionary_set_bool(message, kSecXPCKeyIncludeV0, include);
404 return success;
405 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
406 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
407 });
408}
409
6b200bc3
A
410static bool recovery_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, CFErrorRef* error)
411{
412 secdebug("sosops", "enter - operation: %d", op);
413 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
8a50f688
A
414 xpc_object_t xData = NULL;
415 if(data) {
416 xData = _CFXPCCreateXPCObjectFromCFObject(data);
417 } else {
418 uint8_t zero = 0;
419 CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, &zero, 1);
420 xData = _CFXPCCreateXPCObjectFromCFObject(nullData);
421 CFReleaseNull(nullData);
422 }
6b200bc3
A
423 bool success = false;
424 if (xData){
425 xpc_dictionary_set_value(message, kSecXPCKeyRecoveryPublicKey, xData);
866f8763 426 xData = nil;
6b200bc3
A
427 success = true;
428 }
429 return success;
430 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
431 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
432 });
433}
5c19dc3a
A
434
435static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error)
436{
437 __block bool result = false;
438
439 secdebug("sosops", "enter - operation: %d", op);
440 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
441 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
442 if (encoded_peers)
6b200bc3 443 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
5c19dc3a
A
444 return encoded_peers != NULL;
445 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
446 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
447 return result;
448 });
449 return result;
450}
451
452static bool uint64_t_to_bool_error_request(enum SecXPCOperation op,
453 uint64_t number,
454 CFErrorRef* error)
455{
456 __block bool result = false;
b3971512 457
5c19dc3a
A
458 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
459 xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number);
460 return true;
461 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
462 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
463 return result;
464 });
e3d460c9
A
465
466 return result;
467}
468
866f8763
A
469static bool cfdata_and_int_error_request_returns_bool(enum SecXPCOperation op, CFDataRef thedata,
470 PiggyBackProtocolVersion version, CFErrorRef *error) {
fa7225c8
A
471 __block bool result = false;
472
473 sec_trace_enter_api(NULL);
474 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
475 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
476 bool success = false;
477 if (xdata) {
478 xpc_dictionary_set_value(message, kSecXPCData, xdata);
866f8763 479 xpc_dictionary_set_uint64(message, kSecXPCVersion, version);
fa7225c8 480 success = true;
866f8763 481 xdata = nil;
fa7225c8
A
482 }
483
484 return success;
485 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
486 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
487 return (bool)true;
488 });
489
490 return result;
491}
492
fa7225c8
A
493static CFDataRef cfdata_error_request_returns_cfdata(enum SecXPCOperation op, CFDataRef thedata, CFErrorRef *error) {
494 __block CFDataRef result = NULL;
495
496 sec_trace_enter_api(NULL);
497 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
498 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
499 bool success = false;
500 if (xdata) {
501 xpc_dictionary_set_value(message, kSecXPCData, xdata);
502 success = true;
866f8763 503 xdata = nil;
fa7225c8
A
504 }
505 return success;
506 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
507 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
508 if (response && (NULL != temp_result)) {
509 CFTypeRef object = _CFXPCCreateCFObjectFromXPCObject(temp_result);
6b200bc3
A
510 result = copyIfData(object, error);
511 CFReleaseNull(object);
fa7225c8
A
512 }
513 return (bool) (result != NULL);
514 });
515
516 return result;
517}
518
5c19dc3a
A
519bool SOSCCRequestToJoinCircle(CFErrorRef* error)
520{
d64be36e
A
521 IF_SOS_DISABLED {
522 secdebug("circleOps", "SOS disabled for this platform");
523 setSOSDisabledError(error);
524 return false;
525 }
526
5c19dc3a
A
527 sec_trace_enter_api(NULL);
528 sec_trace_return_bool_api(^{
529 do_if_registered(soscc_RequestToJoinCircle, error);
530
531 return simple_bool_error_request(kSecXPCOpRequestToJoin, error);
532 }, NULL)
533}
534
535bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error)
536{
d64be36e
A
537 IF_SOS_DISABLED {
538 secdebug("circleOps", "SOS disabled for this platform");
539 setSOSDisabledError(error);
540 return false;
541 }
542
5c19dc3a
A
543 sec_trace_enter_api(NULL);
544 sec_trace_return_bool_api(^{
545 do_if_registered(soscc_RequestToJoinCircleAfterRestore, error);
546
547 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error);
548 }, NULL)
549}
550
fa7225c8
A
551bool SOSCCAccountHasPublicKey(CFErrorRef *error)
552{
d64be36e
A
553 IF_SOS_DISABLED {
554 secdebug("circleOps", "SOS disabled for this platform");
555 setSOSDisabledError(error);
556 return false;
557 }
558
fa7225c8
A
559 sec_trace_enter_api(NULL);
560 sec_trace_return_bool_api(^{
561 do_if_registered(soscc_AccountHasPublicKey, error);
562
563 return simple_bool_error_request(kSecXPCOpAccountHasPublicKey, error);
564 }, NULL)
565
566}
567
5c19dc3a
A
568bool SOSCCWaitForInitialSync(CFErrorRef* error)
569{
d64be36e
A
570 IF_SOS_DISABLED {
571 secdebug("circleOps", "SOS disabled for this platform");
572 setSOSDisabledError(error);
573 return false;
574 }
575
5c19dc3a
A
576 sec_trace_enter_api(NULL);
577 sec_trace_return_bool_api(^{
578 do_if_registered(soscc_WaitForInitialSync, error);
579
580 return simple_bool_error_request(kSecXPCOpWaitForInitialSync, error);
581 }, NULL)
582}
583
5c19dc3a
A
584bool SOSCCAccountSetToNew(CFErrorRef *error)
585{
d64be36e
A
586 IF_SOS_DISABLED {
587 secdebug("circleOps", "SOS disabled for this platform");
588 setSOSDisabledError(error);
589 return false;
590 }
591
5c19dc3a
A
592 secwarning("SOSCCAccountSetToNew called");
593 sec_trace_enter_api(NULL);
594 sec_trace_return_bool_api(^{
595 do_if_registered(soscc_SetToNew, error);
596 return simple_bool_error_request(kSecXPCOpAccountSetToNew, error);
597 }, NULL)
598}
599
600bool SOSCCResetToOffering(CFErrorRef* error)
601{
d64be36e
A
602 IF_SOS_DISABLED {
603 secdebug("circleOps", "SOS disabled for this platform");
604 setSOSDisabledError(error);
605 return false;
606 }
607
5c19dc3a
A
608 secwarning("SOSCCResetToOffering called");
609 sec_trace_enter_api(NULL);
610 sec_trace_return_bool_api(^{
611 do_if_registered(soscc_ResetToOffering, error);
612
613 return simple_bool_error_request(kSecXPCOpResetToOffering, error);
614 }, NULL)
615}
616
617bool SOSCCResetToEmpty(CFErrorRef* error)
618{
d64be36e
A
619 IF_SOS_DISABLED {
620 secdebug("circleOps", "SOS disabled for this platform");
621 setSOSDisabledError(error);
622 return false;
623 }
624
5c19dc3a
A
625 secwarning("SOSCCResetToEmpty called");
626 sec_trace_enter_api(NULL);
627 sec_trace_return_bool_api(^{
628 do_if_registered(soscc_ResetToEmpty, error);
629
630 return simple_bool_error_request(kSecXPCOpResetToEmpty, error);
631 }, NULL)
632}
633
e0e0d90e
A
634bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error)
635{
d64be36e
A
636 IF_SOS_DISABLED {
637 secdebug("circleOps", "SOS disabled for this platform");
638 setSOSDisabledError(error);
639 return false;
640 }
641
e0e0d90e
A
642 sec_trace_enter_api(NULL);
643 sec_trace_return_bool_api(^{
644 do_if_registered(soscc_RemovePeersFromCircle, peers, error);
645
646 return info_array_to_bool_error_request(kSecXPCOpRemovePeersFromCircle, peers, error);
647 }, NULL)
648}
649
d64be36e 650bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
79b9da22 651{
d64be36e
A
652 IF_SOS_DISABLED {
653 secdebug("circleOps", "SOS disabled for this platform");
654 setSOSDisabledError(error);
655 return false;
656 }
79b9da22 657
79b9da22
A
658 sec_trace_enter_api(NULL);
659 sec_trace_return_bool_api(^{
d64be36e
A
660 do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
661
662 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
79b9da22
A
663 }, NULL)
664}
665
d64be36e 666bool SOSCCLoggedIntoAccount(CFErrorRef* error) {
5c19dc3a
A
667 sec_trace_enter_api(NULL);
668 sec_trace_return_bool_api(^{
d64be36e
A
669 do_if_registered(soscc_LoggedIntoAccount, error);
670
671 return simple_bool_error_request(kSecXPCOpLoggedIntoAccount, error);
5c19dc3a
A
672 }, NULL)
673}
674
675bool SOSCCLoggedOutOfAccount(CFErrorRef* error)
676{
d64be36e
A
677 IF_SOS_DISABLED {
678 secdebug("circleOps", "SOS disabled for this platform");
679 setSOSDisabledError(error);
680 return false;
681 }
682
5c19dc3a
A
683 sec_trace_enter_api(NULL);
684 sec_trace_return_bool_api(^{
685 do_if_registered(soscc_LoggedOutOfAccount, error);
686
687 return simple_bool_error_request(kSecXPCOpLoggedOutOfAccount, error);
688 }, NULL)
689}
690
691bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error)
692{
d64be36e
A
693 IF_SOS_DISABLED {
694 secdebug("circleOps", "SOS disabled for this platform");
695 setSOSDisabledError(error);
696 return false;
697 }
698
5c19dc3a
A
699 sec_trace_enter_api(NULL);
700 sec_trace_return_bool_api(^{
701 do_if_registered(soscc_BailFromCircle, limit_in_seconds, error);
b3971512 702
5c19dc3a
A
703 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error);
704 }, NULL)
705}
706
5c19dc3a
A
707CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error)
708{
d64be36e
A
709 IF_SOS_DISABLED {
710 secdebug("circleOps", "SOS disabled for this platform");
711 setSOSDisabledError(error);
712 return NULL;
713 }
714
5c19dc3a
A
715 sec_trace_enter_api(NULL);
716 sec_trace_return_api(CFArrayRef, ^{
717 do_if_registered(soscc_CopyPeerInfo, error);
718
719 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error);
720 }, CFSTR("return=%@"));
721}
722
5c19dc3a
A
723CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error)
724{
d64be36e
A
725 IF_SOS_DISABLED {
726 secdebug("circleOps", "SOS disabled for this platform");
727 setSOSDisabledError(error);
728 return NULL;
729 }
730
5c19dc3a
A
731 sec_trace_enter_api(NULL);
732 sec_trace_return_api(CFArrayRef, ^{
733 do_if_registered(soscc_CopyConcurringPeerInfo, error);
734
735 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error);
736 }, CFSTR("return=%@"));
737}
738
739CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error)
740{
d64be36e
A
741 IF_SOS_DISABLED {
742 secdebug("circleOps", "SOS disabled for this platform");
743 setSOSDisabledError(error);
744 return NULL;
745 }
746
5c19dc3a
A
747 sec_trace_enter_api(NULL);
748 sec_trace_return_api(CFArrayRef, ^{
749 do_if_registered(soscc_CopyGenerationPeerInfo, error);
750
751 return simple_array_error_request(kSecXPCOpCopyGenerationPeerInfo, error);
752 }, CFSTR("return=%@"));
753}
754
755CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error)
756{
d64be36e
A
757 IF_SOS_DISABLED {
758 secdebug("circleOps", "SOS disabled for this platform");
759 setSOSDisabledError(error);
760 return NULL;
761 }
762
5c19dc3a
A
763 sec_trace_enter_api(NULL);
764 sec_trace_return_api(CFArrayRef, ^{
765 do_if_registered(soscc_CopyApplicantPeerInfo, error);
766
767 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error);
768 }, CFSTR("return=%@"));
769}
770
771bool SOSCCValidateUserPublic(CFErrorRef* error){
d64be36e
A
772 IF_SOS_DISABLED {
773 secdebug("circleOps", "SOS disabled for this platform");
774 setSOSDisabledError(error);
775 return false;
776 }
777
5c19dc3a
A
778 sec_trace_enter_api(NULL);
779 sec_trace_return_api(bool, ^{
780 do_if_registered(soscc_ValidateUserPublic, error);
781
782 return simple_bool_error_request(kSecXPCOpValidateUserPublic, error);
783 }, NULL);
784}
785
786CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error)
787{
d64be36e
A
788 IF_SOS_DISABLED {
789 secdebug("circleOps", "SOS disabled for this platform");
790 setSOSDisabledError(error);
791 return NULL;
792 }
793
5c19dc3a
A
794 sec_trace_enter_api(NULL);
795 sec_trace_return_api(CFArrayRef, ^{
796 do_if_registered(soscc_CopyValidPeerPeerInfo, error);
797
798 return array_of_info_error_request(kSecXPCOpCopyValidPeerPeerInfo, error);
799 }, CFSTR("return=%@"));
800}
801
802CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error)
803{
d64be36e
A
804 IF_SOS_DISABLED {
805 secdebug("circleOps", "SOS disabled for this platform");
806 setSOSDisabledError(error);
807 return NULL;
808 }
809
5c19dc3a
A
810 sec_trace_enter_api(NULL);
811 sec_trace_return_api(CFArrayRef, ^{
812 do_if_registered(soscc_CopyNotValidPeerPeerInfo, error);
813
814 return array_of_info_error_request(kSecXPCOpCopyNotValidPeerPeerInfo, error);
815 }, CFSTR("return=%@"));
816}
817
818CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error)
819{
d64be36e
A
820 IF_SOS_DISABLED {
821 secdebug("circleOps", "SOS disabled for this platform");
822 setSOSDisabledError(error);
823 return NULL;
824 }
825
826 sec_trace_enter_api(NULL);
5c19dc3a
A
827 sec_trace_return_api(CFArrayRef, ^{
828 do_if_registered(soscc_CopyRetirementPeerInfo, error);
e0e0d90e 829
5c19dc3a
A
830 return array_of_info_error_request(kSecXPCOpCopyRetirementPeerInfo, error);
831 }, CFSTR("return=%@"));
832}
833
e0e0d90e
A
834CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error)
835{
d64be36e
A
836 IF_SOS_DISABLED {
837 secdebug("circleOps", "SOS disabled for this platform");
838 setSOSDisabledError(error);
839 return NULL;
840 }
841
e0e0d90e
A
842 sec_trace_enter_api(NULL);
843 sec_trace_return_api(CFArrayRef, ^{
844 do_if_registered(soscc_CopyViewUnawarePeerInfo, error);
845
846 return array_of_info_error_request(kSecXPCOpCopyViewUnawarePeerInfo, error);
847 }, CFSTR("return=%@"));
848}
849
5c19dc3a
A
850SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error)
851{
d64be36e
A
852 IF_SOS_DISABLED {
853 secdebug("circleOps", "SOS disabled for this platform");
854 setSOSDisabledError(error);
855 return NULL;
856 }
857
5c19dc3a
A
858 sec_trace_enter_api(NULL);
859 sec_trace_return_api(SOSPeerInfoRef, ^{
860 do_if_registered(soscc_CopyMyPeerInfo, error);
861
862 return peer_info_error_request(kSecXPCOpCopyMyPeerInfo, error);
863 }, CFSTR("return=%@"));
864}
865
6b200bc3 866static CFArrayRef SOSCCCopyEngineState(CFErrorRef* error)
5c19dc3a 867{
d64be36e
A
868 IF_SOS_DISABLED {
869 secdebug("circleOps", "SOS disabled for this platform");
870 setSOSDisabledError(error);
871 return NULL;
872 }
873
5c19dc3a
A
874 sec_trace_enter_api(NULL);
875 sec_trace_return_api(CFArrayRef, ^{
876 do_if_registered(soscc_CopyEngineState, error);
877
6b200bc3 878 return der_array_error_request(kSecXPCOpCopyEngineState, error);
5c19dc3a
A
879 }, CFSTR("return=%@"));
880}
881
6b200bc3
A
882CFStringRef kSOSCCEngineStatePeerIDKey = CFSTR("PeerID");
883CFStringRef kSOSCCEngineStateManifestCountKey = CFSTR("ManifestCount");
884CFStringRef kSOSCCEngineStateSyncSetKey = CFSTR("SyncSet");
885CFStringRef kSOSCCEngineStateCoderKey = CFSTR("CoderDump");
886CFStringRef kSOSCCEngineStateManifestHashKey = CFSTR("ManifestHash");
887
888void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)) {
d64be36e
A
889 IF_SOS_DISABLED {
890 secdebug("circleOps", "SOS disabled for this platform");
891 return;
892 }
893
6b200bc3
A
894
895 CFArrayForEach(states, ^(const void *value) {
896 CFDictionaryRef dict = asDictionary(value, NULL);
897 if (dict) {
898 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
899
900 CFStringRef id = asString(CFDictionaryGetValue(dict, kSOSCCEngineStatePeerIDKey), NULL);
901
902 if (id) {
903 CFStringAppendFormat(description, NULL, CFSTR("remote %@ "), id);
904 } else {
905 CFStringAppendFormat(description, NULL, CFSTR("local "));
906 }
907
908 CFSetRef viewSet = asSet(CFDictionaryGetValue(dict, kSOSCCEngineStateSyncSetKey), NULL);
909 if (viewSet) {
910 CFStringSetPerformWithDescription(viewSet, ^(CFStringRef setDescription) {
911 CFStringAppend(description, setDescription);
912 });
913 } else {
914 CFStringAppendFormat(description, NULL, CFSTR("<Missing view set!>"));
915 }
916
917 CFStringAppendFormat(description, NULL, CFSTR(" [%@]"),
918 CFDictionaryGetValue(dict, kSOSCCEngineStateManifestCountKey));
919
920 CFDataRef mainfestHash = asData(CFDictionaryGetValue(dict, kSOSCCEngineStateManifestHashKey), NULL);
921
922 if (mainfestHash) {
923 CFDataPerformWithHexString(mainfestHash, ^(CFStringRef dataString) {
924 CFStringAppendFormat(description, NULL, CFSTR(" %@"), dataString);
925 });
926 }
927
928 CFStringRef coderDescription = asString(CFDictionaryGetValue(dict, kSOSCCEngineStateCoderKey), NULL);
929 if (coderDescription) {
930 CFStringAppendFormat(description, NULL, CFSTR(" %@"), coderDescription);
931 }
932
933 block(description);
934
935 CFReleaseNull(description);
936 }
937 });
938}
939
940bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRef oneStateString)) {
d64be36e
A
941 IF_SOS_DISABLED {
942 secdebug("circleOps", "SOS disabled for this platform");
943 setSOSDisabledError(error);
944 return false;
945 }
946
6b200bc3
A
947 CFArrayRef states = SOSCCCopyEngineState(error);
948 if (states == NULL)
949 return false;
950
951 SOSCCForEachEngineStateAsStringFromArray(states, block);
952
b54c578e
A
953 CFReleaseNull(states);
954
6b200bc3
A
955 return true;
956}
957
958
5c19dc3a
A
959bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error)
960{
d64be36e
A
961 IF_SOS_DISABLED {
962 secdebug("circleOps", "SOS disabled for this platform");
963 setSOSDisabledError(error);
964 return false;
965 }
966
5c19dc3a
A
967 sec_trace_enter_api(NULL);
968 sec_trace_return_bool_api(^{
969 do_if_registered(soscc_AcceptApplicants, applicants, error);
970
971 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error);
972 }, NULL)
973}
974
975bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error)
976{
d64be36e
A
977 IF_SOS_DISABLED {
978 secdebug("circleOps", "SOS disabled for this platform");
979 setSOSDisabledError(error);
980 return false;
981 }
982
983 sec_trace_enter_api(CFSTR("applicants=%@"), applicants);
5c19dc3a
A
984 sec_trace_return_bool_api(^{
985 do_if_registered(soscc_RejectApplicants, applicants, error);
986
987 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error);
988 }, NULL)
989}
990
6b200bc3 991static CF_RETURNS_RETAINED SOSPeerInfoRef SOSSetNewPublicBackupKey(CFDataRef pubKey, CFErrorRef *error)
5c19dc3a
A
992{
993 sec_trace_enter_api(NULL);
994 sec_trace_return_api(SOSPeerInfoRef, ^{
995 do_if_registered(soscc_SetNewPublicBackupKey, pubKey, error);
996
997 return data_to_peer_info_error_request(kSecXPCOpSetNewPublicBackupKey, pubKey, error);
998 }, CFSTR("return=%@"));
999}
1000
1001SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFErrorRef *error){
d64be36e
A
1002 IF_SOS_DISABLED {
1003 secdebug("circleOps", "SOS disabled for this platform");
1004 setSOSDisabledError(error);
1005 return NULL;
1006 }
1007
ecaf5866 1008 secnotice("devRecovery", "Enter SOSCCCopyMyPeerWithNewDeviceRecoverySecret()");
5c19dc3a 1009 CFDataRef publicKeyData = SOSCopyDeviceBackupPublicKey(secret, error);
ecaf5866 1010 secnotice("devRecovery", "SOSCopyDeviceBackupPublicKey (%@)", publicKeyData);
6b200bc3 1011 SOSPeerInfoRef copiedPeer = publicKeyData ? SOSSetNewPublicBackupKey(publicKeyData, error) : NULL;
ecaf5866 1012 secnotice("devRecovery", "SOSSetNewPublicBackupKey (%@)", copiedPeer);
6b200bc3 1013 CFReleaseNull(publicKeyData);
6b200bc3 1014 return copiedPeer;
5c19dc3a
A
1015}
1016
e0e0d90e 1017bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error){
d64be36e
A
1018 IF_SOS_DISABLED {
1019 secdebug("circleOps", "SOS disabled for this platform");
1020 setSOSDisabledError(error);
1021 return false;
1022 }
1023
5c19dc3a
A
1024 sec_trace_enter_api(NULL);
1025 sec_trace_return_bool_api(^{
e0e0d90e
A
1026 do_if_registered(soscc_RegisterSingleRecoverySecret, aks_bag, forV0Only, error);
1027 return keybag_and_bool_to_bool_error_request(kSecXPCOpSetBagForAllSlices, aks_bag, forV0Only, error);
5c19dc3a
A
1028 }, NULL);
1029}
1030
1031
6b200bc3 1032bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){
d64be36e
A
1033 IF_SOS_DISABLED {
1034 secdebug("circleOps", "SOS disabled for this platform");
1035 setSOSDisabledError(error);
1036 return false;
1037 }
1038
1039 sec_trace_enter_api(NULL);
6b200bc3 1040 sec_trace_return_bool_api(^{
866f8763 1041 bool retval = false;
6b200bc3 1042 do_if_registered(soscc_RegisterRecoveryPublicKey, recovery_key, error);
8a50f688
A
1043 // NULL recovery_key is handled in recovery_and_bool_to_bool_error_request now.
1044 retval = recovery_and_bool_to_bool_error_request(kSecXPCOpRegisterRecoveryPublicKey, recovery_key, error);
866f8763 1045 return retval;
6b200bc3
A
1046 }, NULL);
1047}
1048
1049CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error){
d64be36e
A
1050 IF_SOS_DISABLED {
1051 secdebug("circleOps", "SOS disabled for this platform");
1052 setSOSDisabledError(error);
1053 return NULL;
1054 }
1055
6b200bc3
A
1056 sec_trace_enter_api(NULL);
1057 sec_trace_return_api(CFDataRef, ^{
1058 do_if_registered(soscc_CopyRecoveryPublicKey, error);
1059 return data_to_error_request(kSecXPCOpGetRecoveryPublicKey, error);
1060 }, CFSTR("return=%@"));
1061}
5c19dc3a
A
1062static bool label_and_password_to_bool_error_request(enum SecXPCOperation op,
1063 CFStringRef user_label, CFDataRef user_password,
1064 CFErrorRef* error)
1065{
1066 __block bool result = false;
1067
1068 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1069 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
1070 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
1071 });
1072 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
1073 return true;
1074 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1075 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1076 return result;
1077 });
1078
1079 return result;
1080}
1081
1082static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperation op,
1083 CFStringRef user_label, CFDataRef user_password,
d64be36e 1084 CFStringRef dsid, CFErrorRef* error)
5c19dc3a
A
1085{
1086 __block bool result = false;
1087
1088 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1089 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
1090 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
1091 });
1092 CFStringPerformWithCString(dsid, ^(const char *utr8StrDSID) {
1093 xpc_dictionary_set_string(message, kSecXPCKeyDSID, utr8StrDSID);
1094 });
1095 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
fa7225c8 1096 return true;
5c19dc3a
A
1097 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1098 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1099 return result;
1100 });
1101
1102 return result;
1103}
1104
1105bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
1106{
d64be36e
A
1107 IF_SOS_DISABLED {
1108 secdebug("circleOps", "SOS disabled for this platform");
1109 setSOSDisabledError(error);
1110 return false;
1111 }
1112
1113 secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label);
5c19dc3a
A
1114 return SOSCCSetUserCredentials(user_label, user_password, error);
1115}
1116
1117bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
1118{
d64be36e
A
1119 IF_SOS_DISABLED {
1120 secdebug("circleOps", "SOS disabled for this platform");
1121 setSOSDisabledError(error);
1122 return false;
1123 }
1124
ecaf5866 1125 secnotice("circleOps", "SOSCCSetUserCredentials for %@\n", user_label);
5c19dc3a
A
1126 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1127 sec_trace_return_bool_api(^{
1128 do_if_registered(soscc_SetUserCredentials, user_label, user_password, error);
1129
1130 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error);
1131 }, NULL)
1132}
1133
1134bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1135{
d64be36e
A
1136 IF_SOS_DISABLED {
1137 secdebug("circleOps", "SOS disabled for this platform");
1138 setSOSDisabledError(error);
1139 return false;
1140 }
1141
ecaf5866 1142 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSID for %@\n", user_label);
5c19dc3a
A
1143 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1144 sec_trace_return_bool_api(^{
1145 do_if_registered(soscc_SetUserCredentialsAndDSID, user_label, user_password, dsid, error);
6b200bc3
A
1146
1147 bool result = false;
1148 __block CFStringRef account_dsid = dsid;
1149
1150 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1151 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1152
1153 if(account_dsid == NULL){
1154 account_dsid = CFSTR("");
5c19dc3a 1155 }
d64be36e 1156 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, error);
79b9da22
A
1157 out:
1158 return result;
6b200bc3 1159
5c19dc3a
A
1160 }, NULL)
1161}
1162
ecaf5866 1163static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) {
5c19dc3a 1164 sec_trace_return_bool_api(^{
ecaf5866
A
1165 do_if_registered(soscc_TryUserCredentials, user_label, user_password, dsid, error);
1166
1167 bool result = false;
1168 __block CFStringRef account_dsid = dsid;
1169
1170 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1171 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1172
1173 if(account_dsid == NULL){
1174 account_dsid = CFSTR("");
1175 }
1176
d64be36e 1177 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, error);
ecaf5866
A
1178 out:
1179 return result;
1180
5c19dc3a 1181 }, NULL)
ecaf5866
A
1182
1183}
1184
1185bool SOSCCTryUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1186{
d64be36e
A
1187 IF_SOS_DISABLED {
1188 secdebug("circleOps", "SOS disabled for this platform");
1189 setSOSDisabledError(error);
1190 return false;
1191 }
1192
ecaf5866
A
1193 secnotice("sosops", "SOSCCTryUserCredentialsAndDSID!! %@\n", user_label);
1194 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1195 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1196 CFStringRef account_dsid = (dsid != NULL) ? dsid: CFSTR("");
1197 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, account_dsid, error);
1198out:
1199 return false;
1200}
1201
1202bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) {
d64be36e
A
1203 IF_SOS_DISABLED {
1204 secdebug("circleOps", "SOS disabled for this platform");
1205 setSOSDisabledError(error);
1206 return false;
1207 }
1208
ecaf5866 1209 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, NULL, error);
5c19dc3a
A
1210}
1211
1212
1213bool SOSCCCanAuthenticate(CFErrorRef* error) {
d64be36e
A
1214 IF_SOS_DISABLED {
1215 secdebug("circleOps", "SOS disabled for this platform");
1216 setSOSDisabledError(error);
1217 return false;
1218 }
1219
5c19dc3a
A
1220 sec_trace_enter_api(NULL);
1221 sec_trace_return_bool_api(^{
1222 do_if_registered(soscc_CanAuthenticate, error);
1223
1224 return simple_bool_error_request(kSecXPCOpCanAuthenticate, error);
1225 }, NULL)
1226}
1227
1228bool SOSCCPurgeUserCredentials(CFErrorRef* error) {
d64be36e
A
1229 IF_SOS_DISABLED {
1230 secdebug("circleOps", "SOS disabled for this platform");
1231 setSOSDisabledError(error);
1232 return false;
1233 }
1234
5c19dc3a
A
1235 sec_trace_enter_api(NULL);
1236 sec_trace_return_bool_api(^{
1237 do_if_registered(soscc_PurgeUserCredentials, error);
1238
1239 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error);
1240 }, NULL)
1241}
1242
1243enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) {
d64be36e
A
1244 IF_SOS_DISABLED {
1245 secdebug("circleOps", "SOS disabled for this platform");
1246 setSOSDisabledError(error);
1247 return kSOSDepartureReasonError;
1248 }
1249
5c19dc3a
A
1250 sec_trace_enter_api(NULL);
1251 sec_trace_return_api(enum DepartureReason, ^{
1252 do_if_registered(soscc_GetLastDepartureReason, error);
1253
1254 return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error);
1255 }, NULL)
1256}
1257
1258bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) {
d64be36e
A
1259 IF_SOS_DISABLED {
1260 secdebug("circleOps", "SOS disabled for this platform");
1261 setSOSDisabledError(error);
1262 return false;
1263 }
1264
5c19dc3a
A
1265 sec_trace_enter_api(NULL);
1266 sec_trace_return_api(bool, ^{
1267 do_if_registered(soscc_SetLastDepartureReason, reason, error);
1268 return securityd_send_sync_and_do(kSecXPCOpSetLastDepartureReason, error,
1269 ^bool(xpc_object_t message, CFErrorRef *error) {
1270 xpc_dictionary_set_int64(message, kSecXPCKeyReason, reason);
1271 return true;
1272 },
1273 ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1274 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1275 }
1276 );
1277 }, NULL)
1278}
1279
5c19dc3a 1280bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){
d64be36e
A
1281 IF_SOS_DISABLED {
1282 secdebug("circleOps", "SOS disabled for this platform");
1283 setSOSDisabledError(error);
1284 return false;
1285 }
1286
5c19dc3a
A
1287 secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration");
1288 sec_trace_enter_api(NULL);
1289 sec_trace_return_bool_api(^{
1290 do_if_registered(soscc_EnsurePeerRegistration, error);
1291
1292 return simple_bool_error_request(soscc_EnsurePeerRegistration_id, error);
1293 }, NULL)
1294}
1295
1296
6b200bc3
A
1297CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFErrorRef* error)
1298{
d64be36e
A
1299 IF_SOS_DISABLED {
1300 secdebug("circleOps", "SOS disabled for this platform");
1301 setSOSDisabledError(error);
1302 return NULL;
1303 }
1304
6b200bc3
A
1305 sec_trace_enter_api(NULL);
1306 sec_trace_return_api(CFSetRef, ^{
1307 do_if_registered(soscc_ProcessSyncWithPeers, peers, backupPeers, error);
1308
1309 return cfset_cfset_to_cfset_error_request(kSecXPCOpProcessSyncWithPeers, peers, backupPeers, error);
1310 }, NULL)
1311}
1312
1313
5c19dc3a
A
1314SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error)
1315{
d64be36e
A
1316 IF_SOS_DISABLED {
1317 secdebug("circleOps", "SOS disabled for this platform");
1318 setSOSDisabledError(error);
1319 return kSyncWithAllPeersOtherFail;
1320 }
1321
5c19dc3a
A
1322 sec_trace_enter_api(NULL);
1323 sec_trace_return_api(SyncWithAllPeersReason, ^{
1324 do_if_registered(soscc_ProcessSyncWithAllPeers, error);
1325
1326 return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error);
1327 }, NULL)
1328}
1329
1330CFStringRef SOSCCGetStatusDescription(SOSCCStatus status)
1331{
1332 switch (status) {
1333 case kSOSCCInCircle:
1334 return CFSTR("InCircle");
1335 case kSOSCCNotInCircle:
1336 return CFSTR("NotInCircle");
1337 case kSOSCCRequestPending:
1338 return CFSTR("RequestPending");
1339 case kSOSCCCircleAbsent:
1340 return CFSTR("CircleAbsent");
1341 case kSOSCCError:
1342 return CFSTR("InternalError");
1343 default:
866f8763 1344 return CFSTR("Unknown Status");
5c19dc3a
A
1345 };
1346}
1347
866f8763
A
1348
1349CFStringRef SOSCCGetViewResultDescription(SOSViewResultCode vrc)
1350{
1351 switch (vrc) {
1352 case kSOSCCGeneralViewError:
1353 return CFSTR("GeneralViewError");
1354 case kSOSCCViewMember:
1355 return CFSTR("ViewMember");
1356 case kSOSCCViewNotMember:
1357 return CFSTR("ViewNotMember");
1358 case kSOSCCViewNotQualified:
1359 return CFSTR("ViewNotQualified");
1360 case kSOSCCNoSuchView:
1361 return CFSTR("ViewUndefined");
1362 default:
1363 return CFSTR("Unknown View Status");
1364 };
1365}
1366
1367
5c19dc3a
A
1368static int64_t name_action_to_code_request(enum SecXPCOperation op, uint16_t error_result,
1369 CFStringRef name, uint64_t action, CFErrorRef *error) {
1370 __block int64_t result = error_result;
1371
1372 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1373 CFStringPerformWithCString(name, ^(const char *utf8Str) {
1374 xpc_dictionary_set_string(message, kSecXPCKeyViewName, utf8Str);
1375 });
1376 xpc_dictionary_set_int64(message, kSecXPCKeyViewActionCode, action);
1377 return true;
1378 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1379 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
1380 result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
1381 }
1382 return result != error_result;
1383 });
1384
1385 return result;
1386}
1387
1388SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) {
d64be36e
A
1389 IF_SOS_DISABLED {
1390 secdebug("circleOps", "SOS disabled for this platform");
1391 setSOSDisabledError(error);
1392 return kSOSCCGeneralViewError;
1393 }
1394
79b9da22
A
1395 if(actionCode == kSOSCCViewQuery) {
1396 uint64_t circleStat = SOSGetCachedCircleBitmask();
1397 if(circleStat & CC_STATISVALID) {
1398 SOSViewResultCode retval = kSOSCCViewNotMember;
1399 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1400 if(enabledViews) {
1401 if(CFSetContainsValue(enabledViews, view)) {
1402 retval = kSOSCCViewMember;
1403 } else {
1404 retval = kSOSCCViewNotMember;
1405 }
1406 CFReleaseNull(enabledViews);
1407 }
1408 return retval;
1409 }
1410 }
5c19dc3a
A
1411 sec_trace_enter_api(NULL);
1412 sec_trace_return_api(SOSViewResultCode, ^{
1413 do_if_registered(soscc_View, view, actionCode, error);
1414
1415 return (SOSViewResultCode) name_action_to_code_request(kSecXPCOpView, kSOSCCGeneralViewError, view, actionCode, error);
1416 }, CFSTR("SOSViewResultCode=%d"))
1417}
1418
1419
1420bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) {
d64be36e
A
1421 IF_SOS_DISABLED {
1422 secdebug("circleOps", "SOS disabled for this platform");
1423 return false;
1424 }
1425
5c19dc3a
A
1426 CFErrorRef *error = NULL;
1427 __block bool result = false;
1428
1429 sec_trace_enter_api(NULL);
1430 sec_trace_return_bool_api(^{
1431 do_if_registered(soscc_ViewSet, enabledViews, disabledViews);
1432 return securityd_send_sync_and_do(kSecXPCOpViewSet, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1433 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1434 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1435 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1436 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1437 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1438 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1439 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1440 return result;
1441 });
1442 }, NULL)
1443}
1444
866f8763
A
1445static CFStringRef copyViewNames(size_t n, CFStringRef *views) {
1446 CFMutableStringRef retval = CFStringCreateMutable(kCFAllocatorDefault, 0);
1447 CFStringAppend(retval, CFSTR("|"));
1448 for(size_t i = 0; i < n; i++) {
1449 CFStringAppend(retval, views[i]);
1450 CFStringAppend(retval, CFSTR("|"));
1451 }
1452 return retval;
1453}
5c19dc3a
A
1454
1455static bool sosIsViewSetSyncing(size_t n, CFStringRef *views) {
1456 __block bool retval = true;
866f8763 1457 CFErrorRef error = NULL;
5c19dc3a 1458
866f8763
A
1459 if(n == 0 || views == NULL) return false;
1460 CFStringRef viewString = copyViewNames(n, views);
1461
1462 SOSCCStatus cstatus = SOSCCThisDeviceIsInCircle(&error);
1463 if(cstatus != kSOSCCInCircle) {
1464 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) Error: (%@)", viewString, SOSCCGetStatusDescription(cstatus), error);
1465 retval = false;
1466 }
1467
1468 if(retval == true) {
79b9da22
A
1469 // use cached values if valid
1470 uint64_t circleStat = SOSGetCachedCircleBitmask();
1471 if(circleStat & CC_STATISVALID) {
1472 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1473 if(enabledViews) {
1474 for(size_t i = 0; i < n; i++) {
1475 if(!CFSetContainsValue(enabledViews, views[i])) {
1476 retval = false;
1477 }
1478 }
1479 CFReleaseNull(enabledViews);
1480 CFReleaseNull(viewString);
1481 return retval;
1482 }
1483 }
1484
1485 // make the individual calls otherwise.
5c19dc3a 1486 for(size_t i = 0; i < n; i++) {
866f8763
A
1487 SOSViewResultCode vstatus = SOSCCView(views[i], kSOSCCViewQuery, &error);
1488 if(vstatus != kSOSCCViewMember) {
1489 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) SOSViewResultCode(%@) Error: (%@)", views[i],
1490 SOSCCGetStatusDescription(cstatus), SOSCCGetViewResultDescription(vstatus), error);
1491 retval = false;
1492 }
5c19dc3a 1493 }
5c19dc3a 1494 }
866f8763
A
1495
1496 if(retval == true) {
1497 secnotice("viewCheck", "Checking view / circle status for %@: ENABLED", viewString);
1498 }
1499 CFReleaseNull(error);
1500 CFReleaseNull(viewString);
5c19dc3a
A
1501 return retval;
1502}
1503
1504bool SOSCCIsIcloudKeychainSyncing(void) {
d64be36e
A
1505 IF_SOS_DISABLED {
1506 secdebug("circleOps", "SOS disabled for this platform");
1507 return false; // should we lie since CKKS is syncing - or forward?
1508 }
1509
b04fe171
A
1510 CFStringRef views[] = { kSOSViewWiFi, kSOSViewAutofillPasswords, kSOSViewSafariCreditCards, kSOSViewOtherSyncable };
1511 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
5c19dc3a
A
1512}
1513
1514bool SOSCCIsSafariSyncing(void) {
d64be36e
A
1515 IF_SOS_DISABLED {
1516 secdebug("circleOps", "SOS disabled for this platform");
1517 return false;
1518 }
1519
5c19dc3a 1520 CFStringRef views[] = { kSOSViewAutofillPasswords, kSOSViewSafariCreditCards };
b04fe171 1521 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
5c19dc3a
A
1522}
1523
1524bool SOSCCIsAppleTVSyncing(void) {
d64be36e
A
1525 IF_SOS_DISABLED {
1526 secdebug("circleOps", "SOS disabled for this platform");
1527 return false;
1528 }
1529
5c19dc3a 1530 CFStringRef views[] = { kSOSViewAppleTV };
b04fe171 1531 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
5c19dc3a
A
1532}
1533
1534bool SOSCCIsHomeKitSyncing(void) {
d64be36e
A
1535 IF_SOS_DISABLED {
1536 secdebug("circleOps", "SOS disabled for this platform");
1537 return false;
1538 }
1539
5c19dc3a 1540 CFStringRef views[] = { kSOSViewHomeKit };
b04fe171 1541 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
5c19dc3a
A
1542}
1543
1544bool SOSCCIsWiFiSyncing(void) {
d64be36e
A
1545 IF_SOS_DISABLED {
1546 secdebug("circleOps", "SOS disabled for this platform");
1547 return false;
1548 }
1549
5c19dc3a 1550 CFStringRef views[] = { kSOSViewWiFi };
b04fe171 1551 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
5c19dc3a 1552}
e0e0d90e 1553
fa7225c8 1554bool SOSCCIsContinuityUnlockSyncing(void) {
d64be36e
A
1555 IF_SOS_DISABLED {
1556 secdebug("circleOps", "SOS disabled for this platform");
1557 return false;
1558 }
1559
fa7225c8 1560 CFStringRef views[] = { kSOSViewContinuityUnlock };
b04fe171 1561 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
fa7225c8
A
1562}
1563
fa7225c8 1564SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) {
d64be36e
A
1565 IF_SOS_DISABLED {
1566 secdebug("circleOps", "SOS disabled for this platform");
1567 setSOSDisabledError(error);
1568 return NULL;
1569 }
1570
fa7225c8
A
1571 secnotice("hsa2PB", "enter SOSCCCopyApplication applicant");
1572 sec_trace_enter_api(NULL);
1573
1574 sec_trace_return_api(SOSPeerInfoRef, ^{
1575 do_if_registered(soscc_CopyApplicant, error);
1576 return peer_info_error_request(kSecXPCOpCopyApplication, error);
1577 }, CFSTR("return=%@"));
1578}
1579
866f8763 1580bool SOSCCCleanupKVSKeys(CFErrorRef *error) {
d64be36e
A
1581 IF_SOS_DISABLED {
1582 secdebug("circleOps", "SOS disabled for this platform");
1583 setSOSDisabledError(error);
1584 return false;
1585 }
1586
866f8763
A
1587 secnotice("cleanup-keys", "enter SOSCCCleanupKVSKeys");
1588 sec_trace_enter_api(NULL);
1589 sec_trace_return_bool_api(^{
1590 do_if_registered(soscc_SOSCCCleanupKVSKeys, error);
1591
1592 return simple_bool_error_request(kSecXPCOpKVSKeyCleanup, error);
1593 }, NULL)
1594
1595 return false;
1596}
1597
fa7225c8 1598CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error) {
d64be36e
A
1599 IF_SOS_DISABLED {
1600 secdebug("circleOps", "SOS disabled for this platform");
1601 setSOSDisabledError(error);
1602 return NULL;
1603 }
1604
fa7225c8
A
1605 secnotice("hsa2PB", "enter SOSCCCopyCircleJoiningBlob approver");
1606 sec_trace_enter_api(NULL);
1607
1608 sec_trace_return_api(CFDataRef, ^{
1609 CFDataRef result = NULL;
1610 do_if_registered(soscc_CopyCircleJoiningBlob, applicant, error);
1611 CFDataRef piData = SOSPeerInfoCopyEncodedData(applicant, kCFAllocatorDefault, error);
1612 result = cfdata_error_request_returns_cfdata(kSecXPCOpCopyCircleJoiningBlob, piData, error);
1613 CFReleaseNull(piData);
1614 return result;
1615 }, CFSTR("return=%@"));
1616}
1617
7fb2cbd2 1618CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) {
d64be36e
A
1619 IF_SOS_DISABLED {
1620 secdebug("circleOps", "SOS disabled for this platform");
1621 setSOSDisabledError(error);
1622 return NULL;
1623 }
1624
866f8763
A
1625 secnotice("circleJoin", "enter SOSCCCopyInitialSyncData approver");
1626 sec_trace_enter_api(NULL);
1627
1628 sec_trace_return_api(CFDataRef, ^{
7fb2cbd2
A
1629 do_if_registered(soscc_CopyInitialSyncData, flags, error);
1630 return flags_to_data_error_request(kSecXPCOpCopyInitialSyncBlob, flags, error);
866f8763
A
1631 }, CFSTR("return=%@"));
1632}
1633
1634bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error) {
d64be36e
A
1635 IF_SOS_DISABLED {
1636 secdebug("circleOps", "SOS disabled for this platform");
1637 setSOSDisabledError(error);
1638 return false;
1639 }
1640
fa7225c8
A
1641 secnotice("hsa2PB", "enter SOSCCJoinWithCircleJoiningBlob applicant");
1642 sec_trace_enter_api(NULL);
1643 sec_trace_return_bool_api(^{
866f8763 1644 do_if_registered(soscc_JoinWithCircleJoiningBlob, joiningBlob, version, error);
fa7225c8 1645
866f8763 1646 return cfdata_and_int_error_request_returns_bool(kSecXPCOpJoinWithCircleJoiningBlob, joiningBlob, version, error);
fa7225c8 1647 }, NULL)
fa7225c8
A
1648}
1649
fa7225c8 1650CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) {
d64be36e
A
1651 IF_SOS_DISABLED {
1652 secdebug("circleOps", "SOS disabled for this platform");
1653 setSOSDisabledError(error);
1654 return FALSE;
1655 }
1656
fa7225c8
A
1657 secnotice("view-enabled", "enter SOSCCPeersHaveViewsEnabled");
1658 sec_trace_enter_api(NULL);
1659 sec_trace_return_api(CFBooleanRef, ^{
1660 do_if_registered(soscc_SOSCCPeersHaveViewsEnabled, viewNames, error);
1661
1662 return cfarray_to_cfboolean_error_request(kSecXPCOpPeersHaveViewsEnabled, viewNames, error);
1663 }, CFSTR("return=%@"))
1664}
1665
6b200bc3 1666bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
d64be36e
A
1667 IF_SOS_DISABLED {
1668 secdebug("circleOps", "SOS disabled for this platform");
1669 setSOSDisabledError(error);
1670 return false;
1671 }
1672
6b200bc3
A
1673 secnotice("pending-check", "enter SOSCCMessageFromPeerIsPending");
1674
1675 sec_trace_return_bool_api(^{
1676 do_if_registered(soscc_SOSCCMessageFromPeerIsPending, peer, error);
1677
1678 return peer_info_to_bool_error_request(kSecXPCOpMessageFromPeerIsPending, peer, error);
1679 }, NULL)
1680
1681}
1682
1683bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
d64be36e
A
1684 IF_SOS_DISABLED {
1685 secdebug("circleOps", "SOS disabled for this platform");
1686 setSOSDisabledError(error);
1687 return false;
1688 }
1689
6b200bc3
A
1690 sec_trace_return_bool_api(^{
1691 do_if_registered(soscc_SOSCCSendToPeerIsPending, peer, error);
1692
1693 return peer_info_to_bool_error_request(kSecXPCOpSendToPeerIsPending, peer, error);
1694 }, NULL)
866f8763
A
1695}
1696
1697/*
1698 * SecSOSStatus interfaces
1699 */
1700
1701@interface SecSOSStatus : NSObject {
1702 NSXPCConnection* _connection;
1703}
1704@property NSXPCConnection *connection;
1705@end
1706
1707@implementation SecSOSStatus
1708@synthesize connection = _connection;
1709
ecaf5866 1710- (instancetype) init
866f8763
A
1711{
1712 if ((self = [super init]) == NULL)
1713 return NULL;
6b200bc3 1714
866f8763
A
1715 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
1716 _SOSControlSetupInterface(interface);
866f8763 1717
ecaf5866 1718 self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydSOSServiceName) options:0];
b54c578e 1719 if (self.connection == NULL){
866f8763 1720 return NULL;
b54c578e 1721 }
866f8763
A
1722 self.connection.remoteObjectInterface = interface;
1723
1724 [self.connection resume];
1725
1726 return self;
1727}
1728
1729@end
1730
1731static id<SOSControlProtocol>
1732SOSCCGetStatusObject(CFErrorRef *error)
1733{
d64be36e
A
1734 IF_SOS_DISABLED {
1735 secdebug("circleOps", "SOS disabled for this platform");
1736 setSOSDisabledError(error);
1737 return nil;
1738 }
1739
866f8763
A
1740 if (gSecurityd && gSecurityd->soscc_status)
1741 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1742
1743 static SecSOSStatus *control;
1744 static dispatch_once_t onceToken;
1745 dispatch_once(&onceToken, ^{
ecaf5866 1746 control = [[SecSOSStatus alloc] init];
866f8763
A
1747 });
1748 return control.connection.remoteObjectProxy;
1749}
1750
b54c578e
A
1751
1752static id<SOSControlProtocol>
1753SOSCCGetSynchronousStatusObject(CFErrorRef *cferror) {
d64be36e
A
1754 IF_SOS_DISABLED {
1755 secdebug("circleOps", "SOS disabled for this platform");
1756 setSOSDisabledError(cferror);
1757 return nil;
1758 }
b54c578e
A
1759 if (gSecurityd && gSecurityd->soscc_status)
1760 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1761
1762 static SecSOSStatus *control;
1763 static dispatch_once_t onceToken;
1764 dispatch_once(&onceToken, ^{
1765 control = [[SecSOSStatus alloc] init];
1766 });
1767
1768 __block NSError *localError = nil;
1769 id <SOSControlProtocol> synchronousRemoteObject = [control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
1770 secnotice("ghostbust", "An error occurred on the xpc connection to setup the background session: %@", error );
1771 if(error) {
1772 localError = error;
1773 }
1774 }];
1775 if(cferror && localError) {
1776 *cferror = (__bridge CFErrorRef)(localError);
1777 }
1778 return synchronousRemoteObject;
1779}
1780
1781
1782
866f8763
A
1783void
1784SOSCCAccountGetPublicKey(void (^reply)(BOOL trusted, NSData *data, NSError *error))
1785{
1786 CFErrorRef error = NULL;
1787 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1788 if (status == NULL) {
1789 reply(false, NULL, (__bridge NSError *)error);
1790 CFReleaseNull(error);
1791 return;
1792 }
1793
1794 [status userPublicKey:reply];
1795}
1796
1797void
1798SOSCCAccountGetAccountPrivateCredential(void (^complete)(NSData *data, NSError *error))
1799{
1800 CFErrorRef error = NULL;
1801 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1802 if (status == NULL) {
1803 complete(NULL, (__bridge NSError *)error);
1804 CFReleaseNull(error);
1805 return;
1806 }
1807
1808 [status validatedStashedAccountCredential:complete];
6b200bc3 1809}
866f8763
A
1810
1811void
1812SOSCCAccountGetKeyCircleGeneration(void (^reply)(NSData *data, NSError *error))
1813{
1814 SOSCCAccountGetPublicKey(^(BOOL __unused trusted, NSData *data, NSError *error){
1815 if (data == NULL) {
1816 reply(data, error);
1817 } else {
1818 NSMutableData *digest = [NSMutableData dataWithLength:CCSHA256_OUTPUT_SIZE];
1819 ccdigest(ccsha256_di(), [data length], [data bytes], [digest mutableBytes]);
1820 reply(digest, error);
1821 }
1822 });
1823}
1824
b54c578e
A
1825NSString *
1826SOSCCCircleHash(NSError **error)
1827{
1828 CFErrorRef cferror = NULL;
1829 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&cferror);
1830 if (status == NULL) {
1831 if (error) {
1832 *error = (__bridge NSError *)cferror;
1833 }
1834 CFReleaseNull(cferror);
1835 return NULL;
1836 }
1837 __block NSString *hash = NULL;
1838 [status circleHash:^(NSString *circleHash, NSError *error) {
1839 hash = circleHash;
1840 }];
1841 return hash;
1842}
1843
1844
1845
1846void
1847SOSCCGhostBust(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1848 CFErrorRef error = NULL;
1849 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1850 if (status == NULL) {
1851 complete(false, (__bridge NSError *)error);
1852 CFReleaseNull(error);
1853 return;
1854 }
1855 secnotice("ghostbust", "API Called");
1856 [status ghostBust:options complete:^(bool ghostBusted, NSError *error) {
1857 secnotice("ghostbust", "API returned: %d", ghostBusted);
1858 complete(ghostBusted, error);
1859 }];
1860}
1861
1862void SOSCCGhostBustTriggerTimed(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1863 CFErrorRef error = NULL;
1864 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1865 if (status == NULL) {
1866 complete(false, (__bridge NSError *)error);
1867 CFReleaseNull(error);
1868 return;
1869 }
1870 secnotice("ghostbust", "API Trigger Timed Called");
1871 [status ghostBustTriggerTimed:options complete:^(bool ghostBusted, NSError *error) {
1872 secnotice("ghostbust", "API Trigger Timed returned: %d", ghostBusted);
1873 complete(ghostBusted, error);
1874 }];
1875}
1876
1877void SOSCCGhostBustInfo(void (^complete)(NSData *json, NSError *error)) {
1878 CFErrorRef error = NULL;
1879 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1880 if (status == NULL) {
1881 complete(false, (__bridge NSError *)error);
1882 CFReleaseNull(error);
1883 return;
1884 }
1885 secnotice("ghostbust", "API Info Called");
1886 [status ghostBustInfo:^(NSData *json, NSError *error) {
1887 secnotice("ghostbust", "API Info returned");
1888 complete(json, error);
1889 }];
1890}
1891
866f8763 1892