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