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 *kSecXPCKeyEndpoint
= "endpoint";
37 const char *kSecXPCKeyError
= "error";
38 const char *kSecXPCKeyClientToken
= "client";
39 const char *kSecXPCKeyPeerInfoArray
= "peer-infos";
40 const char *kSecXPCKeyPeerInfo
= "peer-info";
41 const char *kSecXPCKeyUserLabel
= "userlabel";
42 const char *kSecXPCKeyBackup
= "backup";
43 const char *kSecXPCKeyKeybag
= "keybag";
44 const char *kSecXPCKeyUserPassword
= "password";
45 const char *kSecXPCKeyEMCSBackup
= "emcsbackup";
46 const char *kSecXPCKeyDSID
= "dsid";
47 const char *kSecXPCKeyQuery
= "query";
48 const char *kSecXPCKeyAttributesToUpdate
= "attributesToUpdate";
49 const char *kSecXPCKeyDomain
= "domain";
50 const char *kSecXPCKeyDigest
= "digest";
51 const char *kSecXPCKeyCertificate
= "cert";
52 const char *kSecXPCKeySettings
= "settings";
53 const char *kSecXPCKeyOTAFileDirectory
= "path";
54 const char *kSecXPCLimitInMinutes
= "limitMinutes";
55 const char *kSecXPCPublicPeerId
= "publicPeerId"; // Public peer id
56 const char *kSecXPCOTRSession
= "otrsess"; // OTR session bytes
57 const char *kSecXPCData
= "data"; // Data to process
58 const char *kSecXPCOTRReady
= "otrrdy"; // OTR ready for messages
59 const char *kSecXPCKeyViewName
= "viewname";
60 const char *kSecXPCKeyViewActionCode
= "viewactioncode";
61 const char *kSecXPCKeyHSA2AutoAcceptInfo
= "autoacceptinfo";
62 const char *kSecXPCKeyString
= "cfstring";
63 const char *kSecXPCKeyArray
= "cfarray";
64 const char *kSecXPCKeySet
= "cfset";
65 const char *kSecXPCKeySet2
= "cfset2";
66 const char *kSecXPCKeyNewPublicBackupKey
= "newPublicBackupKey";
67 const char *kSecXPCKeyRecoveryPublicKey
= "RecoveryPublicKey";
68 const char *kSecXPCKeyIncludeV0
= "includeV0";
69 const char *kSecXPCKeyReason
= "reason";
70 const char *kSecXPCKeyEnabledViewsKey
= "enabledViews";
71 const char *kSecXPCKeyDisabledViewsKey
= "disabledViews";
72 const char *kSecXPCKeyEscrowLabel
= "escrow";
73 const char *kSecXPCKeyTriesLabel
= "tries";
74 const char *kSecXPCKeyFileDescriptor
= "fileDescriptor";
75 const char *kSecXPCKeyAccessGroups
= "accessGroups";
76 const char *kSecXPCKeyClasses
= "classes";
77 const char *kSecXPCKeyNormalizedIssuer
= "normIssuer";
78 const char *kSecXPCKeySerialNumber
= "serialNum";
79 const char *kSecXPCKeyBackupKeybagIdentifier
= "backupKeybagID";
80 const char *kSecXPCKeyBackupKeybagPath
= "backupKeybagPath";
81 const char *kSecXPCVersion
= "version";
82 const char *kSecXPCKeySignInAnalytics
= "signinanalytics";
84 // XPC Functions for both client and server.
88 CFStringRef
SOSCCGetOperationDescription(enum SecXPCOperation op
)
91 case kSecXPCOpAccountSetToNew
:
92 return CFSTR("AccountSetToNew");
93 case kSecXPCOpOTAGetEscrowCertificates
:
94 return CFSTR("OTAGetEscrowCertificates");
95 case kSecXPCOpOTAPKIGetNewAsset
:
96 return CFSTR("OTAPKIGetNewAsset");
97 case kSecXPCOpAcceptApplicants
:
98 return CFSTR("AcceptApplicants");
99 case kSecXPCOpApplyToARing
:
100 return CFSTR("ApplyToARing");
101 case kSecXPCOpBailFromCircle
:
102 return CFSTR("BailFromCircle");
103 case kSecXPCOpCanAuthenticate
:
104 return CFSTR("CanAuthenticate");
105 case kSecXPCOpCopyApplicantPeerInfo
:
106 return CFSTR("CopyApplicantPeerInfo");
107 case kSecXPCOpCopyConcurringPeerPeerInfo
:
108 return CFSTR("CopyConcurringPeerPeerInfo");
109 case kSecXPCOpCopyEngineState
:
110 return CFSTR("CopyEngineState");
111 case kSecXPCOpCopyGenerationPeerInfo
:
112 return CFSTR("CopyGenerationPeerInfo");
113 case kSecXPCOpCopyIncompatibilityInfo
:
114 return CFSTR("CopyIncompatibilityInfo");
115 case kSecXPCOpCopyMyPeerInfo
:
116 return CFSTR("CopyMyPeerInfo");
117 case kSecXPCOpCopyNotValidPeerPeerInfo
:
118 return CFSTR("CopyNotValidPeerPeerInfo");
119 case kSecXPCOpCopyPeerPeerInfo
:
120 return CFSTR("CopyPeerPeerInfo");
121 case kSecXPCOpCopyRetirementPeerInfo
:
122 return CFSTR("CopyRetirementPeerInfo");
123 case kSecXPCOpCopyValidPeerPeerInfo
:
124 return CFSTR("CopyValidPeerPeerInfo");
125 case kSecXPCOpCopyViewUnawarePeerInfo
:
126 return CFSTR("CopyViewUnawarePeerInfo");
127 case kSecXPCOpDeviceInCircle
:
128 return CFSTR("DeviceInCircle");
129 case kSecXPCOpEnableRing
:
130 return CFSTR("EnableRing");
131 case kSecXPCOpGetAllTheRings
:
132 return CFSTR("GetAllTheRings");
133 case kSecXPCOpGetLastDepartureReason
:
134 return CFSTR("GetLastDepartureReason");
135 case kSecXPCOpSyncWithKVSPeer
:
136 return CFSTR("SyncKVSPeer");
137 case kSecXPCOpClearKVSPeerMessage
:
138 return CFSTR("kSecXPCOpClearKVSPeerMessage");
139 case kSecXPCOpLoggedOutOfAccount
:
140 return CFSTR("LoggedOutOfAccount");
141 case kSecXPCOpProcessSyncWithAllPeers
:
142 return CFSTR("ProcessSyncWithAllPeers");
143 case kSecXPCOpProcessSyncWithPeers
:
144 return CFSTR("ProcessSyncWithPeers");
145 case kSecXPCOpProcessUnlockNotification
:
146 return CFSTR("ProcessUnlockNotification");
147 case kSecXPCOpPurgeUserCredentials
:
148 return CFSTR("PurgeUserCredentials");
149 case kSecXPCOpRejectApplicants
:
150 return CFSTR("RejectApplicants");
151 case kSecXPCOpRemoveThisDeviceFromCircle
:
152 return CFSTR("RemoveThisDeviceFromCircle");
153 case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics
:
154 return CFSTR("RemoveThisDeviceFromCircleWithAnalytics");
155 case kSecXPCOpRemovePeersFromCircle
:
156 return CFSTR("RemovePeersFromCircle");
157 case kSecXPCOpRemovePeersFromCircleWithAnalytics
:
158 return CFSTR("RemovePeersFromCircleWithAnalytics");
159 case kSecXPCOpRequestEnsureFreshParameters
:
160 return CFSTR("RequestEnsureFreshParameters");
161 case kSecXPCOpRequestToJoin
:
162 return CFSTR("RequestToJoin");
163 case kSecXPCOpRequestToJoinWithAnalytics
:
164 return CFSTR("RequestToJoinWithAnalytics");
165 case kSecXPCOpRequestToJoinAfterRestore
:
166 return CFSTR("RequestToJoinAfterRestore");
167 case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics
:
168 return CFSTR("RequestToJoinAfterRestoreWithAnalytics");
169 case kSecXPCOpResetToEmpty
:
170 return CFSTR("ResetToEmpty");
171 case kSecXPCOpResetToEmptyWithAnalytics
:
172 return CFSTR("ResetToEmptyWithAnalytics");
173 case kSecXPCOpResetToOffering
:
174 return CFSTR("ResetToOffering");
175 case kSecXPCOpRingStatus
:
176 return CFSTR("RingStatus");
177 case kSecXPCOpRollKeys
:
178 return CFSTR("RollKeys");
179 case kSecXPCOpSetBagForAllSlices
:
180 return CFSTR("SetBagForAllSlices");
181 case kSecXPCOpSetLastDepartureReason
:
182 return CFSTR("SetLastDepartureReason");
183 case kSecXPCOpSetNewPublicBackupKey
:
184 return CFSTR("SetNewPublicBackupKey");
185 case kSecXPCOpSetUserCredentials
:
186 return CFSTR("SetUserCredentials");
187 case kSecXPCOpSetUserCredentialsAndDSID
:
188 return CFSTR("SetUserCredentialsAndDSID");
189 case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics
:
190 return CFSTR("SetUserCredentialsAndDSIDWithAnalytics");
191 case kSecXPCOpTryUserCredentials
:
192 return CFSTR("TryUserCredentials");
193 case kSecXPCOpValidateUserPublic
:
194 return CFSTR("ValidateUserPublic");
196 return CFSTR("View");
197 case kSecXPCOpWithdrawlFromARing
:
198 return CFSTR("WithdrawlFromARing");
199 case sec_add_shared_web_credential_id
:
200 return CFSTR("add_shared_web_credential");
201 case sec_copy_shared_web_credential_id
:
202 return CFSTR("copy_shared_web_credential");
203 case sec_delete_all_id
:
204 return CFSTR("delete_all");
205 case sec_get_log_settings_id
:
206 return CFSTR("get_log_settings");
207 case sec_item_add_id
:
209 case sec_item_backup_copy_names_id
:
210 return CFSTR("backup_copy_names");
211 case sec_item_backup_handoff_fd_id
:
212 return CFSTR("backup_handoff_fd");
213 case sec_item_backup_restore_id
:
214 return CFSTR("backup_restore");
215 case sec_item_backup_set_confirmed_manifest_id
:
216 return CFSTR("backup_set_confirmed_manifest");
217 case sec_item_copy_matching_id
:
218 return CFSTR("copy_matching");
219 case sec_item_delete_id
:
220 return CFSTR("delete");
221 case sec_item_update_id
:
222 return CFSTR("update");
223 case sec_keychain_backup_id
:
224 return CFSTR("keychain_backup");
225 case sec_keychain_backup_syncable_id
:
226 return CFSTR("keychain_backup_syncable");
227 case sec_keychain_restore_id
:
228 return CFSTR("keychain_restore");
229 case sec_keychain_restore_syncable_id
:
230 return CFSTR("keychain_restore_syncable");
231 case sec_keychain_sync_update_message_id
:
232 return CFSTR("keychain_sync_update_message");
233 case sec_ota_pki_trust_store_version_id
:
234 return CFSTR("ota_pki_trust_store_version");
235 case sec_ota_pki_asset_version_id
:
236 return CFSTR("ota_pki_asset_version");
237 case sec_otr_session_create_remote_id
:
238 return CFSTR("otr_session_create_remote");
239 case sec_otr_session_process_packet_remote_id
:
240 return CFSTR("otr_session_process_packet_remote");
241 case sec_set_circle_log_settings_id
:
242 return CFSTR("set_circle_log_settings");
243 case sec_set_xpc_log_settings_id
:
244 return CFSTR("set_xpc_log_settings");
245 case sec_trust_evaluate_id
:
246 return CFSTR("trust_evaluate");
247 case sec_trust_store_contains_id
:
248 return CFSTR("trust_store_contains");
249 case sec_trust_store_remove_certificate_id
:
250 return CFSTR("trust_store_remove_certificate");
251 case sec_trust_store_set_trust_settings_id
:
252 return CFSTR("trust_store_set_trust_settings");
253 case sec_trust_store_copy_all_id
:
254 return CFSTR("trust_store_copy_all");
255 case sec_trust_store_copy_usage_constraints_id
:
256 return CFSTR("trust_store_copy_usage_constraints");
257 case sec_ocsp_cache_flush_id
:
258 return CFSTR("ocsp_cache_flush");
259 case soscc_EnsurePeerRegistration_id
:
260 return CFSTR("EnsurePeerRegistration");
261 case kSecXPCOpSetEscrowRecord
:
262 return CFSTR("SetEscrowRecord");
263 case kSecXPCOpGetEscrowRecord
:
264 return CFSTR("GetEscrowRecord");
265 case kSecXPCOpWhoAmI
:
266 return CFSTR("WhoAmI");
267 case kSecXPCOpTransmogrifyToSyncBubble
:
268 return CFSTR("TransmogrifyToSyncBubble");
269 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
270 return CFSTR("WrapToBackupSliceKeyBagForView");
271 case kSecXPCOpCopyAccountData
:
272 return CFSTR("CopyAccountDataFromKeychain");
273 case kSecXPCOpDeleteAccountData
:
274 return CFSTR("DeleteAccountDataFromKeychain");
275 case kSecXPCOpCopyEngineData
:
276 return CFSTR("CopyEngineDataFromKeychain");
277 case kSecXPCOpDeleteEngineData
:
278 return CFSTR("DeleteEngineDataFromKeychain");
279 case sec_item_update_token_items_id
:
280 return CFSTR("UpdateTokenItems");
281 case sec_delete_items_with_access_groups_id
:
282 return CFSTR("sec_delete_items_with_access_groups_id");
283 case kSecXPCOpPeersHaveViewsEnabled
:
284 return CFSTR("kSecXPCOpPeersHaveViewsEnabled");
285 case kSecXPCOpRegisterRecoveryPublicKey
:
286 return CFSTR("RegisterRecoveryPublicKey");
287 case kSecXPCOpGetRecoveryPublicKey
:
288 return CFSTR("GetRecoveryPublicKey");
289 case kSecXPCOpCopyBackupInformation
:
290 return CFSTR("CopyBackupInformation");
291 case kSecXPCOpMessageFromPeerIsPending
:
292 return CFSTR("MessageFromPeerIsPending");
293 case kSecXPCOpSendToPeerIsPending
:
294 return CFSTR("SendToPeerIsPending");
295 case sec_item_copy_parent_certificates_id
:
296 return CFSTR("copy_parent_certificates");
297 case sec_item_certificate_exists_id
:
298 return CFSTR("certificate_exists");
299 case kSecXPCOpBackupKeybagAdd
:
300 return CFSTR("KeybagAdd");
301 case kSecXPCOpBackupKeybagDelete
:
302 return CFSTR("KeybagDelete");
303 case kSecXPCOpKeychainControlEndpoint
:
304 return CFSTR("KeychainControlEndpoint");
305 case kSecXPCOpNetworkingAnalyticsReport
:
306 return CFSTR("NetworkingAnalyticsReport");
307 case kSecXPCOpSetCTExceptions
:
308 return CFSTR("SetCTExceptions");
309 case kSecXPCOpCopyCTExceptions
:
310 return CFSTR("CopyCTExceptions");
312 return CFSTR("Unknown xpc operation");
316 bool SecXPCDictionarySetPList(xpc_object_t message
, const char *key
, CFTypeRef object
, CFErrorRef
*error
)
319 return SecError(errSecParam
, error
, CFSTR("object for key %s is NULL"), key
);
321 size_t size
= der_sizeof_plist(object
, error
);
324 uint8_t *der
= malloc(size
);
325 uint8_t *der_end
= der
+ size
;
326 uint8_t *der_start
= der_encode_plist(object
, error
, der
, der_end
);
332 assert(der
== der_start
);
333 xpc_dictionary_set_data(message
, key
, der_start
, der_end
- der_start
);
338 bool SecXPCDictionarySetPListOptional(xpc_object_t message
, const char *key
, CFTypeRef object
, CFErrorRef
*error
) {
339 return !object
|| SecXPCDictionarySetPList(message
, key
, object
, error
);
342 bool SecXPCDictionarySetData(xpc_object_t message
, const char *key
, CFDataRef data
, CFErrorRef
*error
)
345 return SecError(errSecParam
, error
, CFSTR("data for key %s is NULL"), key
);
347 xpc_dictionary_set_data(message
, key
, CFDataGetBytePtr(data
), CFDataGetLength(data
));
351 bool SecXPCDictionarySetBool(xpc_object_t message
, const char *key
, bool value
, CFErrorRef
*error
)
353 xpc_dictionary_set_bool(message
, key
, value
);
357 bool SecXPCDictionarySetString(xpc_object_t message
, const char *key
, CFStringRef string
, CFErrorRef
*error
)
360 return SecError(errSecParam
, error
, CFSTR("string for key %s is NULL"), key
);
362 __block
bool ok
= true;
363 CFStringPerformWithCString(string
, ^(const char *utf8Str
) {
365 xpc_dictionary_set_string(message
, key
, utf8Str
);
367 ok
= SecError(errSecParam
, error
, CFSTR("failed to convert string for key %s to utf8"), key
);
372 bool SecXPCDictionarySetStringOptional(xpc_object_t message
, const char *key
, CFStringRef string
, CFErrorRef
*error
) {
373 return !string
|| SecXPCDictionarySetString(message
, key
, string
, error
);
376 bool SecXPCDictionarySetDataOptional(xpc_object_t message
, const char *key
, CFDataRef data
, CFErrorRef
*error
) {
377 return !data
|| SecXPCDictionarySetData(message
, key
, data
, error
);
380 bool SecXPCDictionarySetInt64(xpc_object_t message
, const char *key
, int64_t value
, CFErrorRef
*error
) {
381 xpc_dictionary_set_int64(message
, key
, value
);
385 bool SecXPCDictionarySetFileDescriptor(xpc_object_t message
, const char *key
, int fd
, CFErrorRef
*error
) {
386 xpc_dictionary_set_fd(message
, key
, fd
);
390 int SecXPCDictionaryDupFileDescriptor(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
391 int fd
= xpc_dictionary_dup_fd(message
, key
);
393 SecError(errSecParam
, error
, CFSTR("missing fd for key %s"), key
);
398 CFSetRef
SecXPCDictionaryCopySet(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
399 CFTypeRef obj
= SecXPCDictionaryCopyPList(message
, key
, error
);
400 CFSetRef set
= copyIfSet(obj
, error
);
402 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(obj
));
403 SecError(errSecParam
, error
, CFSTR("object for key %s not set but %@"), key
, description
);
404 CFReleaseNull(description
);
410 CFArrayRef
SecXPCDictionaryCopyArray(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
411 CFTypeRef array
= SecXPCDictionaryCopyPList(message
, key
, error
);
413 CFTypeID type_id
= CFGetTypeID(array
);
414 if (type_id
!= CFArrayGetTypeID()) {
415 CFStringRef description
= CFCopyTypeIDDescription(type_id
);
416 SecError(errSecParam
, error
, CFSTR("object for key %s not array but %@"), key
, description
);
417 CFReleaseNull(description
);
418 CFReleaseNull(array
);
421 return (CFArrayRef
)array
;
424 bool SecXPCDictionaryCopyArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*parray
, CFErrorRef
*error
) {
425 if (!xpc_dictionary_get_value(message
, key
)) {
429 *parray
= SecXPCDictionaryCopyArray(message
, key
, error
);
433 CFDataRef
SecXPCDictionaryCopyData(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
434 CFDataRef data
= NULL
;
436 const uint8_t *bytes
= xpc_dictionary_get_data(message
, key
, &size
);
438 SecError(errSecParam
, error
, CFSTR("no data for key %s"), key
);
442 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, size
);
444 SecError(errSecParam
, error
, CFSTR("failed to create data for key %s"), key
);
449 bool SecXPCDictionaryGetBool(xpc_object_t message
, const char *key
, CFErrorRef
*__unused error
) {
450 return xpc_dictionary_get_bool(message
, key
);
453 bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
454 *pvalue
= xpc_dictionary_get_double(message
, key
);
455 if (*pvalue
== NAN
) {
456 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
461 bool SecXPCDictionaryCopyDataOptional(xpc_object_t message
, const char *key
, CFDataRef
*pdata
, CFErrorRef
*error
) {
463 if (!xpc_dictionary_get_data(message
, key
, &size
)) {
467 *pdata
= SecXPCDictionaryCopyData(message
, key
, error
);
471 bool SecXPCDictionaryCopyURLOptional(xpc_object_t message
, const char *key
, CFURLRef
*purl
, CFErrorRef
*error
) {
473 if (!xpc_dictionary_get_data(message
, key
, &size
)) {
477 CFDataRef data
= SecXPCDictionaryCopyData(message
, key
, error
);
479 *purl
= CFURLCreateWithBytes(kCFAllocatorDefault
, CFDataGetBytePtr(data
), CFDataGetLength(data
), kCFStringEncodingUTF8
, NULL
);
485 CFDictionaryRef
SecXPCDictionaryCopyDictionary(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
486 CFTypeRef dict
= SecXPCDictionaryCopyPList(message
, key
, error
);
488 CFTypeID type_id
= CFGetTypeID(dict
);
489 if (type_id
!= CFDictionaryGetTypeID()) {
490 CFStringRef description
= CFCopyTypeIDDescription(type_id
);
491 SecError(errSecParam
, error
, CFSTR("object for key %s not dictionary but %@"), key
, description
);
492 CFReleaseNull(description
);
496 return (CFDictionaryRef
)dict
;
499 bool SecXPCDictionaryCopyDictionaryOptional(xpc_object_t message
, const char *key
, CFDictionaryRef
*pdictionary
, CFErrorRef
*error
) {
500 if (!xpc_dictionary_get_value(message
, key
)) {
504 *pdictionary
= SecXPCDictionaryCopyDictionary(message
, key
, error
);
508 CFTypeRef
SecXPCDictionaryCopyPList(xpc_object_t message
, const char *key
, CFErrorRef
*error
)
510 CFTypeRef cfobject
= NULL
;
512 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &size
);
514 SecError(errSecParam
, error
, CFSTR("no object for key %s"), key
);
518 const uint8_t *der_end
= der
+ size
;
519 /* use the sensitive allocator so that the dictionary is zeroized upon deallocation */
520 const uint8_t *decode_end
= der_decode_plist(SecCFAllocatorZeroize(), kCFPropertyListImmutable
,
521 &cfobject
, error
, der
, der_end
);
522 if (decode_end
!= der_end
) {
523 SecError(errSecParam
, error
, CFSTR("trailing garbage after der decoded object for key %s"), key
);
524 CFReleaseNull(cfobject
);
527 /* zeroize xpc value as it may have contained raw key material */
528 cc_clear(size
, (void *)der
);
533 bool SecXPCDictionaryCopyPListOptional(xpc_object_t message
, const char *key
, CFTypeRef
*pobject
, CFErrorRef
*error
) {
535 if (!xpc_dictionary_get_data(message
, key
, &size
)) {
539 *pobject
= SecXPCDictionaryCopyPList(message
, key
, error
);
543 CFStringRef
SecXPCDictionaryCopyString(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
544 const char *string
= xpc_dictionary_get_string(message
, key
);
546 CFStringRef result
= CFStringCreateWithCString(kCFAllocatorDefault
, string
, kCFStringEncodingUTF8
);
548 SecError(errSecAllocate
, error
, CFSTR("object for key %s failed to convert %s to CFString"), key
, string
);
552 SecError(errSecParam
, error
, CFSTR("object for key %s not string"), key
);
557 bool SecXPCDictionaryCopyStringOptional(xpc_object_t message
, const char *key
, CFStringRef
*pstring
, CFErrorRef
*error
) {
558 if (!xpc_dictionary_get_value(message
, key
)) {
562 *pstring
= SecXPCDictionaryCopyString(message
, key
, error
);
566 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
567 CFDataRef data
= NULL
;
569 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
571 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
574 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
579 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
580 CFMutableArrayRef data_array
= NULL
;
581 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
582 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
583 size_t count
= xpc_array_get_count(xpc_data_array
);
584 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
585 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
588 for (ix
= 0; ix
< count
; ++ix
) {
589 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
591 CFRelease(data_array
);
594 CFArraySetValueAtIndex(data_array
, ix
, data
);
602 bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
603 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
604 if (!xpc_data_array
) {
609 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
610 return *data_array
!= NULL
;