]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecItem.m
Security-59306.101.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
34 #include <os/activity.h>
35
36 #import <Foundation/Foundation.h>
37
38 OSStatus _SecItemAddAndNotifyOnSync(CFDictionaryRef attributes, CFTypeRef * CF_RETURNS_RETAINED result, void (^syncCallback)(bool didSync, CFErrorRef error)) {
39 __block SecCFDictionaryCOW attrs = { attributes };
40 OSStatus status = errSecParam;
41
42 os_activity_t activity = os_activity_create("_SecItemAddAndNotifyOnSync", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
43 os_activity_scope(activity);
44
45 status = SecOSStatusWith(^bool(CFErrorRef *statuserror) {
46 return SecItemAuthDoQuery(&attrs, NULL, SecItemAdd, statuserror, ^bool(TKTokenRef token, CFDictionaryRef authedattributes, CFDictionaryRef unused, CFDictionaryRef auth_params, CFErrorRef *autherror) {
47 if (token != NULL) {
48 syncCallback(false, NULL);
49 return false;
50 }
51
52 __block CFTypeRef raw_result = NULL;
53 __block CFErrorRef raw_error = NULL;
54
55 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
56 syncCallback(false, (__bridge CFErrorRef)error);
57 });
58 if (rpc == NULL) {
59 return false;
60 }
61 SecuritydXPCCallback* xpcCallback = [[SecuritydXPCCallback alloc] initWithCallback: ^void(bool didSync, NSError* error) {
62 syncCallback(didSync, (__bridge CFErrorRef) error);
63 }];
64
65 dispatch_semaphore_t wait_for_secd = dispatch_semaphore_create(0);
66 [rpc SecItemAddAndNotifyOnSync: (__bridge NSDictionary*) authedattributes syncCallback:xpcCallback complete: ^void (NSDictionary* opDictResult, NSArray* opArrayResult, NSError* operror) {
67 raw_result = opDictResult ? CFBridgingRetain(opDictResult) :
68 opArrayResult ? CFBridgingRetain(opArrayResult) : NULL;
69 raw_error = (CFErrorRef) CFBridgingRetain(operror);
70 dispatch_semaphore_signal(wait_for_secd);
71 }];
72 dispatch_semaphore_wait(wait_for_secd, DISPATCH_TIME_FOREVER);
73
74 if(autherror) {
75 *autherror = raw_error;
76 }
77
78 bool ok = false;
79
80 // SecItemResultProcess isn't intended to handle error cases, so bypass it.
81 if(!raw_error) {
82 ok = SecItemResultProcess(authedattributes, auth_params, token, raw_result, result, autherror);
83 }
84 CFReleaseNull(raw_result);
85 return ok;
86 });
87 });
88 CFReleaseNull(attrs.mutable_dictionary);
89
90 return status;
91 }
92
93 void SecItemSetCurrentItemAcrossAllDevices(CFStringRef accessGroup,
94 CFStringRef identifier,
95 CFStringRef viewHint,
96 CFDataRef newCurrentItemReference,
97 CFDataRef newCurrentItemHash,
98 CFDataRef oldCurrentItemReference,
99 CFDataRef oldCurrentItemHash,
100 void (^complete)(CFErrorRef error))
101 {
102 os_activity_t activity = os_activity_create("SecItemSetCurrentItemAcrossAllDevices", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
103 os_activity_scope(activity);
104
105 @autoreleasepool {
106 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
107 complete((__bridge CFErrorRef) error);
108 });
109 [rpc secItemSetCurrentItemAcrossAllDevices:(__bridge NSData*)newCurrentItemReference
110 newCurrentItemHash:(__bridge NSData*)newCurrentItemHash
111 accessGroup:(__bridge NSString*)accessGroup
112 identifier:(__bridge NSString*)identifier
113 viewHint:(__bridge NSString*)viewHint
114 oldCurrentItemReference:(__bridge NSData*)oldCurrentItemReference
115 oldCurrentItemHash:(__bridge NSData*)oldCurrentItemHash
116 complete: ^ (NSError* operror) {
117 complete((__bridge CFErrorRef) operror);
118 }];
119 }
120 }
121
122 void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup,
123 CFStringRef identifier,
124 CFStringRef viewHint,
125 bool fetchCloudValue,
126 void (^complete)(CFDataRef persistentRef, CFErrorRef error))
127 {
128 os_activity_t activity = os_activity_create("SecItemFetchCurrentItemAcrossAllDevices", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
129 os_activity_scope(activity);
130
131 @autoreleasepool {
132 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
133 complete(NULL, (__bridge CFErrorRef) error);
134 });
135 [rpc secItemFetchCurrentItemAcrossAllDevices:(__bridge NSString*)accessGroup
136 identifier:(__bridge NSString*)identifier
137 viewHint:(__bridge NSString*)viewHint
138 fetchCloudValue:fetchCloudValue
139 complete: ^(NSData* persistentRef, NSError* operror) {
140 complete((__bridge CFDataRef) persistentRef, (__bridge CFErrorRef) operror);
141 }];
142 }
143 }
144
145 void _SecItemFetchDigests(NSString *itemClass, NSString *accessGroup, void (^complete)(NSArray<NSDictionary *> *, NSError *))
146 {
147 os_activity_t activity = os_activity_create("_SecItemFetchDigests", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
148 os_activity_scope(activity);
149
150 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
151 complete(NULL, error);
152 });
153 [rpc secItemDigest:itemClass accessGroup:accessGroup complete:complete];
154 }
155
156 void _SecKeychainDeleteMultiUser(NSString *musr, void (^complete)(bool, NSError *))
157 {
158 os_activity_t activity = os_activity_create("_SecKeychainDeleteMultiUser", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
159 os_activity_scope(activity);
160
161 NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:musr];
162 if (uuid == NULL) {
163 complete(false, NULL);
164 return;
165 }
166
167 uuid_t musrUUID;
168 [uuid getUUIDBytes:musrUUID];
169
170 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
171 complete(false, error);
172 });
173 [rpc secKeychainDeleteMultiuser:[NSData dataWithBytes:musrUUID length:sizeof(uuid_t)] complete:^(bool status, NSError *error) {
174 complete(status, error);
175 }];
176 }
177
178 void SecItemVerifyBackupIntegrity(BOOL lightweight,
179 void(^completion)(NSDictionary<NSString*, NSString*>* results, NSError* error))
180 {
181 @autoreleasepool {
182 id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
183 completion(@{@"summary" : @"XPC Error"}, error);
184 });
185 [rpc secItemVerifyBackupIntegrity:lightweight completion:completion];
186 }
187 }