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