]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecItem.m
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / sec / Security / SecItem.m
1 /*
2 * Copyright (c) 2017 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 * Implements SecItem.c things using Obj-c.
26 */
27
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>
34
35 #include <os/activity.h>
36
37 #import <Foundation/Foundation.h>
38
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;
42
43 os_activity_t activity = os_activity_create("_SecItemAddAndNotifyOnSync", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
44 os_activity_scope(activity);
45
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) {
48 if (token != NULL) {
49 syncCallback(false, NULL);
50 return false;
51 }
52
53 __block CFTypeRef raw_result = NULL;
54 __block CFErrorRef raw_error = NULL;
55
56 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
57 syncCallback(false, (__bridge CFErrorRef)error);
58 });
59 if (rpc == NULL) {
60 return false;
61 }
62 SecuritydXPCCallback* xpcCallback = [[SecuritydXPCCallback alloc] initWithCallback: ^void(bool didSync, NSError* error) {
63 syncCallback(didSync, (__bridge CFErrorRef) error);
64 }];
65
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);
72 }];
73 dispatch_semaphore_wait(wait_for_secd, DISPATCH_TIME_FOREVER);
74
75 if(autherror) {
76 *autherror = raw_error;
77 }
78
79 bool ok = false;
80
81 // SecItemResultProcess isn't intended to handle error cases, so bypass it.
82 if(!raw_error) {
83 ok = SecItemResultProcess(authedattributes, auth_params, token, raw_result, result, autherror);
84 }
85 CFReleaseNull(raw_result);
86 return ok;
87 });
88 });
89 CFReleaseNull(attrs.mutable_dictionary);
90
91 return status;
92 }
93
94 void SecItemSetCurrentItemAcrossAllDevices(CFStringRef accessGroup,
95 CFStringRef identifier,
96 CFStringRef viewHint,
97 CFDataRef newCurrentItemReference,
98 CFDataRef newCurrentItemHash,
99 CFDataRef oldCurrentItemReference,
100 CFDataRef oldCurrentItemHash,
101 void (^complete)(CFErrorRef error))
102 {
103 os_activity_t activity = os_activity_create("SecItemSetCurrentItemAcrossAllDevices", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
104 os_activity_scope(activity);
105
106 @autoreleasepool {
107 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
108 complete((__bridge CFErrorRef) error);
109 });
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);
119 }];
120 }
121 }
122
123 void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup,
124 CFStringRef identifier,
125 CFStringRef viewHint,
126 bool fetchCloudValue,
127 void (^complete)(CFDataRef persistentRef, CFErrorRef error))
128 {
129 os_activity_t activity = os_activity_create("SecItemFetchCurrentItemAcrossAllDevices", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
130 os_activity_scope(activity);
131
132 @autoreleasepool {
133 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
134 complete(NULL, (__bridge CFErrorRef) error);
135 });
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);
142 }];
143 }
144 }
145
146 void _SecItemFetchDigests(NSString *itemClass, NSString *accessGroup, void (^complete)(NSArray<NSDictionary *> *, NSError *))
147 {
148 os_activity_t activity = os_activity_create("_SecItemFetchDigests", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
149 os_activity_scope(activity);
150
151 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
152 complete(NULL, error);
153 });
154 [rpc secItemDigest:itemClass accessGroup:accessGroup complete:complete];
155 }
156
157 void _SecKeychainDeleteMultiUser(NSString *musr, void (^complete)(bool, NSError *))
158 {
159 os_activity_t activity = os_activity_create("_SecKeychainDeleteMultiUser", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
160 os_activity_scope(activity);
161
162 NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:musr];
163 if (uuid == NULL) {
164 complete(false, NULL);
165 return;
166 }
167
168 uuid_t musrUUID;
169 [uuid getUUIDBytes:musrUUID];
170
171 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
172 complete(false, error);
173 });
174 [rpc secKeychainDeleteMultiuser:[NSData dataWithBytes:musrUUID length:sizeof(uuid_t)] complete:^(bool status, NSError *error) {
175 complete(status, error);
176 }];
177 }
178
179 void SecItemVerifyBackupIntegrity(BOOL lightweight,
180 void(^completion)(NSDictionary<NSString*, NSString*>* results, NSError* error))
181 {
182 @autoreleasepool {
183 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(true, ^(NSError *error) {
184 completion(@{@"summary" : @"XPC Error"}, error);
185 });
186 [rpc secItemVerifyBackupIntegrity:lightweight completion:completion];
187 }
188 }
189
190 OSStatus SecItemDeleteKeychainItemsForAppClip(CFStringRef applicationIdentifier)
191 {
192 __block OSStatus status = errSecInternal;
193 @autoreleasepool {
194 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(true, ^(NSError *error) {
195 secerror("xpc: failure to obtain XPC proxy object for app clip deletion, %@", error);
196 });
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) {
202 status = xpcStatus;
203 }
204 }];
205 }
206 return status;
207 }