2 * Copyright (c) 2017 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 * Implements SecItem.c things using Obj-c.
28 #include <Security/SecBasePriv.h>
29 #include <Security/SecItem.h>
30 #include <Security/SecItemPriv.h>
31 #include <Security/SecItemInternal.h>
32 #include <utilities/SecCFRelease.h>
33 #import <utilities/debugging.h>
35 #include <os/activity.h>
37 #import <Foundation/Foundation.h>
39 OSStatus _SecItemAddAndNotifyOnSync(CFDictionaryRef attributes, CFTypeRef * CF_RETURNS_RETAINED result, void (^syncCallback)(bool didSync, CFErrorRef error)) {
40 __block SecCFDictionaryCOW attrs = { attributes };
41 OSStatus status = errSecParam;
43 os_activity_t activity = os_activity_create("_SecItemAddAndNotifyOnSync", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
44 os_activity_scope(activity);
46 status = SecOSStatusWith(^bool(CFErrorRef *statuserror) {
47 return SecItemAuthDoQuery(&attrs, NULL, SecItemAdd, statuserror, ^bool(TKTokenRef token, CFDictionaryRef authedattributes, CFDictionaryRef unused, CFDictionaryRef auth_params, CFErrorRef *autherror) {
49 syncCallback(false, NULL);
53 __block CFTypeRef raw_result = NULL;
54 __block CFErrorRef raw_error = NULL;
56 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
57 syncCallback(false, (__bridge CFErrorRef)error);
62 SecuritydXPCCallback* xpcCallback = [[SecuritydXPCCallback alloc] initWithCallback: ^void(bool didSync, NSError* error) {
63 syncCallback(didSync, (__bridge CFErrorRef) error);
66 dispatch_semaphore_t wait_for_secd = dispatch_semaphore_create(0);
67 [rpc SecItemAddAndNotifyOnSync: (__bridge NSDictionary*) authedattributes syncCallback:xpcCallback complete: ^void (NSDictionary* opDictResult, NSArray* opArrayResult, NSError* operror) {
68 raw_result = opDictResult ? CFBridgingRetain(opDictResult) :
69 opArrayResult ? CFBridgingRetain(opArrayResult) : NULL;
70 raw_error = (CFErrorRef) CFBridgingRetain(operror);
71 dispatch_semaphore_signal(wait_for_secd);
73 dispatch_semaphore_wait(wait_for_secd, DISPATCH_TIME_FOREVER);
76 *autherror = raw_error;
81 // SecItemResultProcess isn't intended to handle error cases, so bypass it.
83 ok = SecItemResultProcess(authedattributes, auth_params, token, raw_result, result, autherror);
85 CFReleaseNull(raw_result);
89 CFReleaseNull(attrs.mutable_dictionary);
94 void SecItemSetCurrentItemAcrossAllDevices(CFStringRef accessGroup,
95 CFStringRef identifier,
97 CFDataRef newCurrentItemReference,
98 CFDataRef newCurrentItemHash,
99 CFDataRef oldCurrentItemReference,
100 CFDataRef oldCurrentItemHash,
101 void (^complete)(CFErrorRef error))
103 os_activity_t activity = os_activity_create("SecItemSetCurrentItemAcrossAllDevices", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
104 os_activity_scope(activity);
107 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
108 complete((__bridge CFErrorRef) error);
110 [rpc secItemSetCurrentItemAcrossAllDevices:(__bridge NSData*)newCurrentItemReference
111 newCurrentItemHash:(__bridge NSData*)newCurrentItemHash
112 accessGroup:(__bridge NSString*)accessGroup
113 identifier:(__bridge NSString*)identifier
114 viewHint:(__bridge NSString*)viewHint
115 oldCurrentItemReference:(__bridge NSData*)oldCurrentItemReference
116 oldCurrentItemHash:(__bridge NSData*)oldCurrentItemHash
117 complete: ^ (NSError* operror) {
118 complete((__bridge CFErrorRef) operror);
123 void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup,
124 CFStringRef identifier,
125 CFStringRef viewHint,
126 bool fetchCloudValue,
127 void (^complete)(CFDataRef persistentRef, CFErrorRef error))
129 os_activity_t activity = os_activity_create("SecItemFetchCurrentItemAcrossAllDevices", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
130 os_activity_scope(activity);
133 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
134 complete(NULL, (__bridge CFErrorRef) error);
136 [rpc secItemFetchCurrentItemAcrossAllDevices:(__bridge NSString*)accessGroup
137 identifier:(__bridge NSString*)identifier
138 viewHint:(__bridge NSString*)viewHint
139 fetchCloudValue:fetchCloudValue
140 complete: ^(NSData* persistentRef, NSError* operror) {
141 complete((__bridge CFDataRef) persistentRef, (__bridge CFErrorRef) operror);
146 void _SecItemFetchDigests(NSString *itemClass, NSString *accessGroup, void (^complete)(NSArray<NSDictionary *> *, NSError *))
148 os_activity_t activity = os_activity_create("_SecItemFetchDigests", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
149 os_activity_scope(activity);
151 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
152 complete(NULL, error);
154 [rpc secItemDigest:itemClass accessGroup:accessGroup complete:complete];
157 void _SecKeychainDeleteMultiUser(NSString *musr, void (^complete)(bool, NSError *))
159 os_activity_t activity = os_activity_create("_SecKeychainDeleteMultiUser", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
160 os_activity_scope(activity);
162 NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:musr];
164 complete(false, NULL);
169 [uuid getUUIDBytes:musrUUID];
171 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
172 complete(false, error);
174 [rpc secKeychainDeleteMultiuser:[NSData dataWithBytes:musrUUID length:sizeof(uuid_t)] complete:^(bool status, NSError *error) {
175 complete(status, error);
179 void SecItemVerifyBackupIntegrity(BOOL lightweight,
180 void(^completion)(NSDictionary<NSString*, NSString*>* results, NSError* error))
183 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(true, ^(NSError *error) {
184 completion(@{@"summary" : @"XPC Error"}, error);
186 [rpc secItemVerifyBackupIntegrity:lightweight completion:completion];
190 OSStatus SecItemDeleteKeychainItemsForAppClip(CFStringRef applicationIdentifier)
192 __block OSStatus status = errSecInternal;
194 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(true, ^(NSError *error) {
195 secerror("xpc: failure to obtain XPC proxy object for app clip deletion, %@", error);
197 [rpc secItemDeleteForAppClipApplicationIdentifier:(__bridge NSString*)applicationIdentifier
198 completion:^(OSStatus xpcStatus) {
199 // Other errors turn into errSecInternal for caller
200 secnotice("xpc", "app clip deletion result: %i", (int)xpcStatus);
201 if (xpcStatus == errSecMissingEntitlement || xpcStatus == errSecSuccess) {