2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <Security/SecuritydXPC.h>
26 #include <Security/SecCFAllocator.h>
27 #include <ipc/securityd_client.h>
28 #include <utilities/SecCFError.h>
29 #include <utilities/SecDb.h>
30 #include <utilities/SecCFWrappers.h>
31 #include <utilities/der_plist.h>
33 // TODO Shorten these string values to save ipc bandwidth.
34 const char *kSecXPCKeyOperation
= "operation";
35 const char *kSecXPCKeyResult
= "status";
36 const char *kSecXPCKeyError
= "error";
37 const char *kSecXPCKeyClientToken
= "client";
38 const char *kSecXPCKeyPeerInfoArray
= "peer-infos";
39 const char *kSecXPCKeyPeerInfo
= "peer-info";
40 const char *kSecXPCKeyUserLabel
= "userlabel";
41 const char *kSecXPCKeyBackup
= "backup";
42 const char *kSecXPCKeyKeybag
= "keybag";
43 const char *kSecXPCKeyUserPassword
= "password";
44 const char *kSecXPCKeyDSID
= "dsid";
45 const char *kSecXPCKeyQuery
= "query";
46 const char *kSecXPCKeyAttributesToUpdate
= "attributesToUpdate";
47 const char *kSecXPCKeyDomain
= "domain";
48 const char *kSecXPCKeyDigest
= "digest";
49 const char *kSecXPCKeyCertificate
= "cert";
50 const char *kSecXPCKeySettings
= "settings";
51 const char *kSecXPCKeyOTAFileDirectory
= "path";
52 const char *kSecXPCLimitInMinutes
= "limitMinutes";
53 const char *kSecXPCPublicPeerId
= "publicPeerId"; // Public peer id
54 const char *kSecXPCOTRSession
= "otrsess"; // OTR session bytes
55 const char *kSecXPCData
= "data"; // Data to process
56 const char *kSecXPCOTRReady
= "otrrdy"; // OTR ready for messages
57 const char *kSecXPCKeyDeviceID
= "deviceID";
58 const char *kSecXPCKeySendIDSMessage
= "sendIDSMessageCommand";
59 const char *kSecXPCKeyIDSMessage
= "idsMessage";
60 const char *kSecXPCKeyViewName
= "viewname";
61 const char *kSecXPCKeyViewActionCode
= "viewactioncode";
62 const char *kSecXPCKeyHSA2AutoAcceptInfo
= "autoacceptinfo";
63 const char *kSecXPCKeyString
= "cfstring";
64 const char *kSecXPCKeyArray
= "cfarray";
65 const char *kSecXPCKeySet
= "cfset";
66 const char *kSecXPCKeySet2
= "cfset2";
67 const char *kSecXPCKeyNewPublicBackupKey
= "newPublicBackupKey";
68 const char *kSecXPCKeyRecoveryPublicKey
= "RecoveryPublicKey";
69 const char *kSecXPCKeyIncludeV0
= "includeV0";
70 const char *kSecXPCKeyReason
= "reason";
71 const char *kSecXPCKeyEnabledViewsKey
= "enabledViews";
72 const char *kSecXPCKeyDisabledViewsKey
= "disabledViews";
73 const char *kSecXPCKeyEscrowLabel
= "escrow";
74 const char *kSecXPCKeyTriesLabel
= "tries";
75 const char *kSecXPCKeyFileDescriptor
= "fileDescriptor";
76 const char *kSecXPCKeyAccessGroups
= "accessGroups";
77 const char *kSecXPCKeyClasses
= "classes";
81 // XPC Functions for both client and server.
85 CFStringRef
SOSCCGetOperationDescription(enum SecXPCOperation op
)
88 case kSecXPCOpAccountSetToNew
:
89 return CFSTR("AccountSetToNew");
90 case kSecXPCOpOTAGetEscrowCertificates
:
91 return CFSTR("OTAGetEscrowCertificates");
92 case kSecXPCOpOTAPKIGetNewAsset
:
93 return CFSTR("OTAPKIGetNewAsset");
94 case kSecXPCOpSetHSA2AutoAcceptInfo
:
95 return CFSTR("SetHSA2AutoAcceptInfo");
96 case kSecXPCOpAcceptApplicants
:
97 return CFSTR("AcceptApplicants");
98 case kSecXPCOpApplyToARing
:
99 return CFSTR("ApplyToARing");
100 case kSecXPCOpBailFromCircle
:
101 return CFSTR("BailFromCircle");
102 case kSecXPCOpCanAuthenticate
:
103 return CFSTR("CanAuthenticate");
104 case kSecXPCOpCopyApplicantPeerInfo
:
105 return CFSTR("CopyApplicantPeerInfo");
106 case kSecXPCOpCopyConcurringPeerPeerInfo
:
107 return CFSTR("CopyConcurringPeerPeerInfo");
108 case kSecXPCOpCopyEngineState
:
109 return CFSTR("CopyEngineState");
110 case kSecXPCOpCopyGenerationPeerInfo
:
111 return CFSTR("CopyGenerationPeerInfo");
112 case kSecXPCOpCopyIncompatibilityInfo
:
113 return CFSTR("CopyIncompatibilityInfo");
114 case kSecXPCOpCopyMyPeerInfo
:
115 return CFSTR("CopyMyPeerInfo");
116 case kSecXPCOpCopyNotValidPeerPeerInfo
:
117 return CFSTR("CopyNotValidPeerPeerInfo");
118 case kSecXPCOpCopyPeerPeerInfo
:
119 return CFSTR("CopyPeerPeerInfo");
120 case kSecXPCOpCopyRetirementPeerInfo
:
121 return CFSTR("CopyRetirementPeerInfo");
122 case kSecXPCOpCopyValidPeerPeerInfo
:
123 return CFSTR("CopyValidPeerPeerInfo");
124 case kSecXPCOpCopyViewUnawarePeerInfo
:
125 return CFSTR("CopyViewUnawarePeerInfo");
126 case kSecXPCOpDeviceInCircle
:
127 return CFSTR("DeviceInCircle");
128 case kSecXPCOpEnableRing
:
129 return CFSTR("EnableRing");
130 case kSecXPCOpGetAllTheRings
:
131 return CFSTR("GetAllTheRings");
132 case kSecXPCOpGetLastDepartureReason
:
133 return CFSTR("GetLastDepartureReason");
134 case kSecXPCOpHandleIDSMessage
:
135 return CFSTR("HandleIDSMessage");
136 case kSecXPCOpSyncWithKVSPeer
:
137 return CFSTR("SyncKVSPeer");
138 case kSecXPCOpSyncWithIDSPeer
:
139 return CFSTR("SyncIDSPeer");
140 case kSecXPCOpIDSDeviceID
:
141 return CFSTR("IDSDeviceID");
142 case kSecXPCOpClearKVSPeerMessage
:
143 return CFSTR("kSecXPCOpClearKVSPeerMessage");
144 case kSecXPCOpLoggedOutOfAccount
:
145 return CFSTR("LoggedOutOfAccount");
146 case kSecXPCOpPingTest
:
147 return CFSTR("PingTest");
148 case kSecXPCOpProcessSyncWithAllPeers
:
149 return CFSTR("ProcessSyncWithAllPeers");
150 case kSecXPCOpProcessSyncWithPeers
:
151 return CFSTR("ProcessSyncWithPeers");
152 case kSecXPCOpProcessUnlockNotification
:
153 return CFSTR("ProcessUnlockNotification");
154 case kSecXPCOpPurgeUserCredentials
:
155 return CFSTR("PurgeUserCredentials");
156 case kSecXPCOpRejectApplicants
:
157 return CFSTR("RejectApplicants");
158 case kSecXPCOpRemoveThisDeviceFromCircle
:
159 return CFSTR("RemoveThisDeviceFromCircle");
160 case kSecXPCOpRemovePeersFromCircle
:
161 return CFSTR("RemovePeersFromCircle");
162 case kSecXPCOpRequestDeviceID
:
163 return CFSTR("RequestDeviceID");
164 case kSecXPCOpRequestEnsureFreshParameters
:
165 return CFSTR("RequestEnsureFreshParameters");
166 case kSecXPCOpRequestToJoin
:
167 return CFSTR("RequestToJoin");
168 case kSecXPCOpRequestToJoinAfterRestore
:
169 return CFSTR("RequestToJoinAfterRestore");
170 case kSecXPCOpResetToEmpty
:
171 return CFSTR("ResetToEmpty");
172 case kSecXPCOpResetToOffering
:
173 return CFSTR("ResetToOffering");
174 case kSecXPCOpRingStatus
:
175 return CFSTR("RingStatus");
176 case kSecXPCOpRollKeys
:
177 return CFSTR("RollKeys");
178 case kSecXPCOpSecurityProperty
:
179 return CFSTR("SecurityProperty");
180 case kSecXPCOpSendIDSMessage
:
181 return CFSTR("SendIDSMessage");
182 case kSecXPCOpSetBagForAllSlices
:
183 return CFSTR("SetBagForAllSlices");
184 case kSecXPCOpSetDeviceID
:
185 return CFSTR("SetDeviceID");
186 case kSecXPCOpSetLastDepartureReason
:
187 return CFSTR("SetLastDepartureReason");
188 case kSecXPCOpSetNewPublicBackupKey
:
189 return CFSTR("SetNewPublicBackupKey");
190 case kSecXPCOpSetUserCredentials
:
191 return CFSTR("SetUserCredentials");
192 case kSecXPCOpSetUserCredentialsAndDSID
:
193 return CFSTR("SetUserCredentialsAndDSID");
194 case kSecXPCOpTryUserCredentials
:
195 return CFSTR("TryUserCredentials");
196 case kSecXPCOpValidateUserPublic
:
197 return CFSTR("ValidateUserPublic");
199 return CFSTR("View");
200 case kSecXPCOpWithdrawlFromARing
:
201 return CFSTR("WithdrawlFromARing");
202 case sec_add_shared_web_credential_id
:
203 return CFSTR("add_shared_web_credential");
204 case sec_copy_shared_web_credential_id
:
205 return CFSTR("copy_shared_web_credential");
206 case sec_delete_all_id
:
207 return CFSTR("delete_all");
208 case sec_get_log_settings_id
:
209 return CFSTR("get_log_settings");
210 case sec_item_add_id
:
212 case sec_item_backup_copy_names_id
:
213 return CFSTR("backup_copy_names");
214 case sec_item_backup_handoff_fd_id
:
215 return CFSTR("backup_handoff_fd");
216 case sec_item_backup_restore_id
:
217 return CFSTR("backup_restore");
218 case sec_item_backup_set_confirmed_manifest_id
:
219 return CFSTR("backup_set_confirmed_manifest");
220 case sec_item_copy_matching_id
:
221 return CFSTR("copy_matching");
222 case sec_item_delete_id
:
223 return CFSTR("delete");
224 case sec_item_update_id
:
225 return CFSTR("update");
226 case sec_keychain_backup_id
:
227 return CFSTR("keychain_backup");
228 case sec_keychain_backup_syncable_id
:
229 return CFSTR("keychain_backup_syncable");
230 case sec_keychain_restore_id
:
231 return CFSTR("keychain_restore");
232 case sec_keychain_restore_syncable_id
:
233 return CFSTR("keychain_restore_syncable");
234 case sec_keychain_sync_update_message_id
:
235 return CFSTR("keychain_sync_update_message");
236 case sec_ota_pki_asset_version_id
:
237 return CFSTR("ota_pki_asset_version");
238 case sec_otr_session_create_remote_id
:
239 return CFSTR("otr_session_create_remote");
240 case sec_otr_session_process_packet_remote_id
:
241 return CFSTR("otr_session_process_packet_remote");
242 case sec_set_circle_log_settings_id
:
243 return CFSTR("set_circle_log_settings");
244 case sec_set_xpc_log_settings_id
:
245 return CFSTR("set_xpc_log_settings");
246 case sec_trust_evaluate_id
:
247 return CFSTR("trust_evaluate");
248 case sec_trust_store_contains_id
:
249 return CFSTR("trust_store_contains");
250 case sec_trust_store_remove_certificate_id
:
251 return CFSTR("trust_store_remove_certificate");
252 case sec_trust_store_set_trust_settings_id
:
253 return CFSTR("trust_store_set_trust_settings");
254 case sec_trust_store_copy_all_id
:
255 return CFSTR("trust_store_copy_all");
256 case sec_trust_store_copy_usage_constraints_id
:
257 return CFSTR("trust_store_copy_usage_constraints");
258 case soscc_EnsurePeerRegistration_id
:
259 return CFSTR("EnsurePeerRegistration");
260 case kSecXPCOpSetEscrowRecord
:
261 return CFSTR("SetEscrowRecord");
262 case kSecXPCOpGetEscrowRecord
:
263 return CFSTR("GetEscrowRecord");
264 case kSecXPCOpWhoAmI
:
265 return CFSTR("WhoAmI");
266 case kSecXPCOpTransmogrifyToSyncBubble
:
267 return CFSTR("TransmogrifyToSyncBubble");
268 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
269 return CFSTR("WrapToBackupSliceKeyBagForView");
270 case kSecXPCOpCopyAccountData
:
271 return CFSTR("CopyAccountDataFromKeychain");
272 case kSecXPCOpDeleteAccountData
:
273 return CFSTR("DeleteAccountDataFromKeychain");
274 case kSecXPCOpCopyEngineData
:
275 return CFSTR("CopyEngineDataFromKeychain");
276 case kSecXPCOpDeleteEngineData
:
277 return CFSTR("DeleteEngineDataFromKeychain");
278 case sec_item_update_token_items_id
:
279 return CFSTR("UpdateTokenItems");
280 case sec_delete_items_with_access_groups_id
:
281 return CFSTR("sec_delete_items_with_access_groups_id");
282 case kSecXPCOpPeersHaveViewsEnabled
:
283 return CFSTR("kSecXPCOpPeersHaveViewsEnabled");
284 case kSecXPCOpRegisterRecoveryPublicKey
:
285 return CFSTR("RegisterRecoveryPublicKey");
286 case kSecXPCOpGetRecoveryPublicKey
:
287 return CFSTR("GetRecoveryPublicKey");
288 case kSecXPCOpCopyBackupInformation
:
289 return CFSTR("CopyBackupInformation");
290 case sec_device_is_internal_id
:
291 return CFSTR("DeviceIsInternal");
292 case kSecXPCOpMessageFromPeerIsPending
:
293 return CFSTR("MessageFromPeerIsPending");
294 case kSecXPCOpSendToPeerIsPending
:
295 return CFSTR("SendToPeerIsPending");
297 return CFSTR("Unknown xpc operation");
301 bool SecXPCDictionarySetPList(xpc_object_t message
, const char *key
, CFTypeRef object
, CFErrorRef
*error
)
304 return SecError(errSecParam
, error
, CFSTR("object for key %s is NULL"), key
);
306 size_t size
= der_sizeof_plist(object
, error
);
309 uint8_t *der
= malloc(size
);
310 uint8_t *der_end
= der
+ size
;
311 uint8_t *der_start
= der_encode_plist(object
, error
, der
, der_end
);
317 assert(der
== der_start
);
318 xpc_dictionary_set_data(message
, key
, der_start
, der_end
- der_start
);
323 bool SecXPCDictionarySetPListOptional(xpc_object_t message
, const char *key
, CFTypeRef object
, CFErrorRef
*error
) {
324 return !object
|| SecXPCDictionarySetPList(message
, key
, object
, error
);
327 bool SecXPCDictionarySetData(xpc_object_t message
, const char *key
, CFDataRef data
, CFErrorRef
*error
)
330 return SecError(errSecParam
, error
, CFSTR("data for key %s is NULL"), key
);
332 xpc_dictionary_set_data(message
, key
, CFDataGetBytePtr(data
), CFDataGetLength(data
));
336 bool SecXPCDictionarySetBool(xpc_object_t message
, const char *key
, bool value
, CFErrorRef
*error
)
338 xpc_dictionary_set_bool(message
, key
, value
);
342 bool SecXPCDictionarySetString(xpc_object_t message
, const char *key
, CFStringRef string
, CFErrorRef
*error
)
345 return SecError(errSecParam
, error
, CFSTR("string for key %s is NULL"), key
);
347 __block
bool ok
= true;
348 CFStringPerformWithCString(string
, ^(const char *utf8Str
) {
350 xpc_dictionary_set_string(message
, key
, utf8Str
);
352 ok
= SecError(errSecParam
, error
, CFSTR("failed to convert string for key %s to utf8"), key
);
357 bool SecXPCDictionarySetStringOptional(xpc_object_t message
, const char *key
, CFStringRef string
, CFErrorRef
*error
) {
358 return !string
|| SecXPCDictionarySetString(message
, key
, string
, error
);
361 bool SecXPCDictionarySetDataOptional(xpc_object_t message
, const char *key
, CFDataRef data
, CFErrorRef
*error
) {
362 return !data
|| SecXPCDictionarySetData(message
, key
, data
, error
);
365 bool SecXPCDictionarySetInt64(xpc_object_t message
, const char *key
, int64_t value
, CFErrorRef
*error
) {
366 xpc_dictionary_set_int64(message
, key
, value
);
370 bool SecXPCDictionarySetFileDescriptor(xpc_object_t message
, const char *key
, int fd
, CFErrorRef
*error
) {
371 xpc_dictionary_set_fd(message
, key
, fd
);
375 int SecXPCDictionaryDupFileDescriptor(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
376 int fd
= xpc_dictionary_dup_fd(message
, key
);
378 SecError(errSecParam
, error
, CFSTR("missing fd for key %s"), key
);
383 CFSetRef
SecXPCDictionaryCopySet(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
384 CFTypeRef obj
= SecXPCDictionaryCopyPList(message
, key
, error
);
385 CFSetRef set
= copyIfSet(obj
, error
);
387 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(obj
));
388 SecError(errSecParam
, error
, CFSTR("object for key %s not set but %@"), key
, description
);
389 CFReleaseNull(description
);
395 CFArrayRef
SecXPCDictionaryCopyArray(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
396 CFTypeRef array
= SecXPCDictionaryCopyPList(message
, key
, error
);
398 CFTypeID type_id
= CFGetTypeID(array
);
399 if (type_id
!= CFArrayGetTypeID()) {
400 CFStringRef description
= CFCopyTypeIDDescription(type_id
);
401 SecError(errSecParam
, error
, CFSTR("object for key %s not array but %@"), key
, description
);
402 CFReleaseNull(description
);
403 CFReleaseNull(array
);
406 return (CFArrayRef
)array
;
409 bool SecXPCDictionaryCopyArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*parray
, CFErrorRef
*error
) {
410 if (!xpc_dictionary_get_value(message
, key
)) {
414 *parray
= SecXPCDictionaryCopyArray(message
, key
, error
);
418 CFDataRef
SecXPCDictionaryCopyData(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
419 CFDataRef data
= NULL
;
421 const uint8_t *bytes
= xpc_dictionary_get_data(message
, key
, &size
);
423 SecError(errSecParam
, error
, CFSTR("no data for key %s"), key
);
427 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, size
);
429 SecError(errSecParam
, error
, CFSTR("failed to create data for key %s"), key
);
434 bool SecXPCDictionaryGetBool(xpc_object_t message
, const char *key
, CFErrorRef
*__unused error
) {
435 return xpc_dictionary_get_bool(message
, key
);
438 bool SecXPCDictionaryCopyDataOptional(xpc_object_t message
, const char *key
, CFDataRef
*pdata
, CFErrorRef
*error
) {
440 if (!xpc_dictionary_get_data(message
, key
, &size
)) {
444 *pdata
= SecXPCDictionaryCopyData(message
, key
, error
);
448 CFDictionaryRef
SecXPCDictionaryCopyDictionary(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
449 CFTypeRef dict
= SecXPCDictionaryCopyPList(message
, key
, error
);
451 CFTypeID type_id
= CFGetTypeID(dict
);
452 if (type_id
!= CFDictionaryGetTypeID()) {
453 CFStringRef description
= CFCopyTypeIDDescription(type_id
);
454 SecError(errSecParam
, error
, CFSTR("object for key %s not dictionary but %@"), key
, description
);
455 CFReleaseNull(description
);
459 return (CFDictionaryRef
)dict
;
462 bool SecXPCDictionaryCopyDictionaryOptional(xpc_object_t message
, const char *key
, CFDictionaryRef
*pdictionary
, CFErrorRef
*error
) {
463 if (!xpc_dictionary_get_value(message
, key
)) {
467 *pdictionary
= SecXPCDictionaryCopyDictionary(message
, key
, error
);
471 CFTypeRef
SecXPCDictionaryCopyPList(xpc_object_t message
, const char *key
, CFErrorRef
*error
)
473 CFTypeRef cfobject
= NULL
;
475 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &size
);
477 SecError(errSecParam
, error
, CFSTR("no object for key %s"), key
);
481 const uint8_t *der_end
= der
+ size
;
482 /* use the sensitive allocator so that the dictionary is zeroized upon deallocation */
483 const uint8_t *decode_end
= der_decode_plist(SecCFAllocatorZeroize(), kCFPropertyListImmutable
,
484 &cfobject
, error
, der
, der_end
);
485 if (decode_end
!= der_end
) {
486 SecError(errSecParam
, error
, CFSTR("trailing garbage after der decoded object for key %s"), key
);
487 CFReleaseNull(cfobject
);
490 /* zeroize xpc value as it may have contained raw key material */
491 cc_clear(size
, (void *)der
);
496 bool SecXPCDictionaryCopyPListOptional(xpc_object_t message
, const char *key
, CFTypeRef
*pobject
, CFErrorRef
*error
) {
498 if (!xpc_dictionary_get_data(message
, key
, &size
)) {
502 *pobject
= SecXPCDictionaryCopyPList(message
, key
, error
);
506 CFStringRef
SecXPCDictionaryCopyString(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
507 const char *string
= xpc_dictionary_get_string(message
, key
);
509 CFStringRef result
= CFStringCreateWithCString(kCFAllocatorDefault
, string
, kCFStringEncodingUTF8
);
511 SecError(errSecAllocate
, error
, CFSTR("object for key %s failed to convert %s to CFString"), key
, string
);
515 SecError(errSecParam
, error
, CFSTR("object for key %s not string"), key
);
520 bool SecXPCDictionaryCopyStringOptional(xpc_object_t message
, const char *key
, CFStringRef
*pstring
, CFErrorRef
*error
) {
521 if (!xpc_dictionary_get_value(message
, key
)) {
525 *pstring
= SecXPCDictionaryCopyString(message
, key
, error
);