]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/Regressions/secd-81-item-acl-stress.m
Security-58286.51.6.tar.gz
[apple/security.git] / OSX / sec / securityd / Regressions / secd-81-item-acl-stress.m
1 //
2 // si-81-item-acl.c
3 // sec
4 //
5 // Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
6 //
7 //
8
9 #include <CoreFoundation/CoreFoundation.h>
10 #include <Security/SecCertificate.h>
11 #include <Security/SecItem.h>
12 #include <Security/SecItemPriv.h>
13 #include <Security/SecBase.h>
14 #include <utilities/array_size.h>
15 #include <utilities/SecCFWrappers.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <Security/SecAccessControl.h>
19 #include <Security/SecAccessControlPriv.h>
20 #include <libaks_acl_cf_keys.h>
21 #include <LocalAuthentication/LAPublicDefines.h>
22 #include <LocalAuthentication/LAPrivateDefines.h>
23 #include <securityd/SecItemServer.h>
24 #include <LocalAuthentication/LAPublicDefines.h>
25
26 #include "secd_regressions.h"
27
28 #if USE_KEYSTORE
29 #include <coreauthd_spi.h>
30 #include "SecdTestKeychainUtilities.h"
31 #if TARGET_OS_EMBEDDED
32 #include <MobileKeyBag/MobileKeyBag.h>
33 #endif
34
35 #endif
36
37 enum ItemAttrType {
38 kBoolItemAttr,
39 kNumberItemAttr,
40 kStringItemAttr,
41 kDataItemAttr,
42 kBlobItemAttr,
43 kDateItemAttr,
44 kAccessabilityItemAttr,
45 kAccessGroupItemAttr,
46 };
47
48 extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock)(void));
49
50 #if LA_CONTEXT_IMPLEMENTED
51 static keybag_handle_t test_keybag;
52 static const char *passcode = "password";
53
54 static bool changePasscode(const char *old_passcode, const char *new_passcode)
55 {
56 size_t old_passcode_len = 0;
57 size_t new_passcode_len = 0;
58
59 if (old_passcode)
60 old_passcode_len = strlen(old_passcode);
61
62 if (new_passcode)
63 new_passcode_len = strlen(new_passcode);
64
65 kern_return_t status = aks_change_secret(test_keybag, old_passcode, (int)old_passcode_len, new_passcode, (int)new_passcode_len, generation_noop, NULL);
66 return status == 0;
67 }
68 #endif
69
70 static void WithEachString(void(^each)(CFStringRef attr, enum ItemAttrType atype), ...) {
71 va_list ap;
72 va_start(ap, each);
73 CFStringRef attr;
74 while((attr = va_arg(ap, CFStringRef)) != NULL) {
75 enum ItemAttrType atype = va_arg(ap, enum ItemAttrType);
76 each(attr, atype);
77 }
78 va_end(ap);
79 }
80
81 static void ItemForEachPKAttr(CFMutableDictionaryRef item, void(^each)(CFStringRef attr, enum ItemAttrType atype)) {
82 CFStringRef iclass = CFDictionaryGetValue(item, kSecClass);
83 if (!iclass) {
84 return;
85 } else if (CFEqual(iclass, kSecClassGenericPassword)) {
86 WithEachString(each,
87 kSecAttrAccessible, kAccessabilityItemAttr,
88 kSecAttrAccessGroup, kAccessGroupItemAttr,
89 kSecAttrAccount, kStringItemAttr,
90 kSecAttrService, kStringItemAttr,
91 kSecAttrSynchronizable, kBoolItemAttr,
92 NULL);
93 } else if (CFEqual(iclass, kSecClassInternetPassword)) {
94 WithEachString(each,
95 kSecAttrAccessible, kAccessabilityItemAttr,
96 kSecAttrAccessGroup, kAccessGroupItemAttr,
97 kSecAttrAccount, kStringItemAttr,
98 kSecAttrSecurityDomain, kStringItemAttr,
99 kSecAttrServer, kStringItemAttr,
100 kSecAttrProtocol, kNumberItemAttr,
101 kSecAttrAuthenticationType, kNumberItemAttr,
102 kSecAttrPort, kNumberItemAttr,
103 kSecAttrPath, kStringItemAttr,
104 kSecAttrSynchronizable, kBoolItemAttr,
105 NULL);
106 } else if (CFEqual(iclass, kSecClassCertificate)) {
107 WithEachString(each,
108 kSecAttrAccessible, kAccessabilityItemAttr,
109 kSecAttrAccessGroup, kAccessGroupItemAttr,
110 kSecAttrCertificateType, kNumberItemAttr,
111 kSecAttrIssuer, kDataItemAttr,
112 kSecAttrSerialNumber, kDataItemAttr,
113 kSecAttrSynchronizable, kBoolItemAttr,
114 NULL);
115 } else if (CFEqual(iclass, kSecClassKey)) {
116 WithEachString(each,
117 kSecAttrAccessible, kAccessabilityItemAttr,
118 kSecAttrAccessGroup, kAccessGroupItemAttr,
119 kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies
120 kSecAttrApplicationLabel, kDataItemAttr,
121 kSecAttrApplicationTag, kDataItemAttr,
122 kSecAttrKeyType, kNumberItemAttr,
123 kSecAttrKeySizeInBits, kNumberItemAttr,
124 kSecAttrEffectiveKeySize, kNumberItemAttr,
125 kSecAttrStartDate, kDateItemAttr,
126 kSecAttrEndDate, kDateItemAttr,
127 kSecAttrSynchronizable, kBoolItemAttr,
128 NULL);
129 } else if (CFEqual(iclass, kSecClassIdentity)) {
130 WithEachString(each,
131 kSecAttrAccessible, kAccessabilityItemAttr,
132 kSecAttrAccessGroup, kAccessGroupItemAttr,
133 kSecAttrCertificateType, kNumberItemAttr,
134 kSecAttrIssuer, kDataItemAttr,
135 kSecAttrSerialNumber, kDataItemAttr,
136 kSecAttrSynchronizable, kBoolItemAttr,
137 kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies
138 kSecAttrApplicationLabel, kDataItemAttr,
139 kSecAttrApplicationTag, kDataItemAttr,
140 kSecAttrKeyType, kNumberItemAttr,
141 kSecAttrKeySizeInBits, kNumberItemAttr,
142 kSecAttrEffectiveKeySize, kNumberItemAttr,
143 kSecAttrStartDate, kDateItemAttr,
144 kSecAttrEndDate, kDateItemAttr,
145 kSecAttrSynchronizable, kBoolItemAttr,
146 NULL);
147 }
148 }
149
150 #if LA_CONTEXT_IMPLEMENTED
151 CF_RETURNS_RETAINED
152 static CFErrorRef createCFError(CFStringRef message, CFIndex code)
153 {
154 const void* keysPtr[1];
155 const void* messagesPtr[1];
156
157 keysPtr[0] = kCFErrorLocalizedDescriptionKey;
158 messagesPtr[0] = message;
159 return CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, CFSTR(kLAErrorDomain), code, keysPtr, messagesPtr, 1);
160 }
161 #endif
162
163 static void fillItem(CFMutableDictionaryRef item, uint32_t num)
164 {
165 ItemForEachPKAttr(item, ^(CFStringRef attr, enum ItemAttrType atype) {
166 CFTypeRef value = NULL;
167 switch (atype) {
168 case kBoolItemAttr:
169 value = (num % 2 == 0 ? kCFBooleanTrue : kCFBooleanFalse);
170 CFRetain(value);
171 break;
172 case kNumberItemAttr:
173 value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
174 break;
175 case kStringItemAttr:
176 case kBlobItemAttr:
177 value = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("acl-stress-string-%d"), num);
178 break;
179 case kDataItemAttr:
180 {
181 char buf[50];
182 int len = snprintf(buf, sizeof(buf), "acl-stress-data-%d", num);
183 value = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buf, len);
184 break;
185 }
186 case kDateItemAttr:
187 value = NULL; // Don't mess with dates on create.
188 break;
189 case kAccessabilityItemAttr:
190 { break; }
191 case kAccessGroupItemAttr:
192 {
193 CFStringRef accessGroups[] = {
194 NULL,
195 CFSTR("com.apple.security.sos"), // Secd internally uses this
196 };
197 value = accessGroups[num % array_size(accessGroups)];
198 break;
199 }
200 }
201 if (value)
202 CFDictionarySetValue(item, attr, value);
203 CFReleaseSafe(value);
204 });
205
206 CFDictionarySetValue(item, kSecValueData, (__bridge CFDataRef)[NSData dataWithBytes:"some data" length:9]);
207 }
208
209 static void tests(bool isPasscodeSet)
210 {
211 CFErrorRef (^okBlock)(void) = ^ {
212 return (CFErrorRef)NULL;
213 };
214
215 #if LA_CONTEXT_IMPLEMENTED
216 CFErrorRef (^errorNotInteractiveBlock)(void) = ^ {
217 return createCFError(CFSTR(""), kLAErrorNotInteractive);
218 };
219 #endif
220
221 CFArrayRef classArray = CFArrayCreateForCFTypes(kCFAllocatorDefault, kSecClassInternetPassword, kSecClassGenericPassword, kSecClassKey, kSecClassCertificate, NULL);
222 CFArrayRef protectionClassArray = CFArrayCreateForCFTypes(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAlwaysPrivate,
223 kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
224 kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, NULL);
225
226 __block uint32_t pass = 0;
227 CFArrayForEach(classArray, ^(CFTypeRef itemClass) {
228 CFArrayForEach(protectionClassArray, ^(CFTypeRef protectionClass) {
229 CFMutableDictionaryRef item = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, itemClass, NULL);
230 fillItem(item, ++pass);
231
232 LASetErrorCodeBlock(okBlock);
233 SecAccessControlRef aclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL);
234 ok(aclRef, "Create SecAccessControlRef");
235 ok(SecAccessControlSetProtection(aclRef, protectionClass, NULL), "Set protection");
236 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDecrypt, kCFBooleanTrue, NULL), "Set operation decrypt to true");
237 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDelete, kCFBooleanTrue, NULL), "Set operation delete to true");
238 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpEncrypt, kCFBooleanTrue, NULL), "Set operation encrypt to true");
239
240 LASetErrorCodeBlock(okBlock);
241 CFDictionarySetValue(item, kSecAttrAccessControl, aclRef);
242 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse);
243 #if LA_CONTEXT_IMPLEMENTED
244 ok_status(SecItemAdd(item, NULL), "add local ");
245 ok_status(SecItemCopyMatching(item, NULL), "find local");
246 ok_status(SecItemDelete(item), "delete local");
247 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local");
248 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanTrue);
249 is_status(SecItemAdd(item, NULL), errSecParam, "add sync");
250 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find sync");
251 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse);
252
253 if(isPasscodeSet) {
254 SecAccessControlRef aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protectionClass, kSecAccessControlUserPresence, NULL);
255 ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction");
256
257 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef);
258 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
259 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
260 LASetErrorCodeBlock(errorNotInteractiveBlock);
261 is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI");
262 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUISkip);
263 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "find local - acl with authentication UI");
264 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
265 LASetErrorCodeBlock(okBlock);
266 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
267 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI");
268
269 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
270 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
271 LASetErrorCodeBlock(errorNotInteractiveBlock);
272 is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI");
273 LASetErrorCodeBlock(okBlock);
274 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
275 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI");
276 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
277
278 SecAccessControlRef aclWithDeleteConstraintRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protectionClass, kSecAccessControlUserPresence, NULL);
279 ok(aclWithDeleteConstraintRef, "Create SecAccessControlRef which require UI interaction for Delete operation");
280 CFTypeRef constraint = SecAccessConstraintCreatePolicy(kCFAllocatorDefault, CFSTR("DeviceOwnerAuthentication"), NULL);
281 ok(constraint);
282 ok(SecAccessControlAddConstraintForOperation(aclWithDeleteConstraintRef, kAKSKeyOpDelete, constraint, NULL), "Add constraint for operation delete");
283 CFReleaseSafe(constraint);
284
285 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithDeleteConstraintRef);
286 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
287 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
288 LASetErrorCodeBlock(errorNotInteractiveBlock);
289 is_status(SecItemDelete(item), errSecInteractionNotAllowed, "delete local - acl with authentication UI");
290
291 if (CFEqual(protectionClass, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)) {
292 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
293 ok(changePasscode(passcode, NULL));
294 LASetErrorCodeBlock(okBlock);
295 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
296 ok(changePasscode(NULL, passcode));
297
298 CFReleaseSafe(aclWithUIRef);
299 CFReleaseSafe(aclWithDeleteConstraintRef);
300
301 aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlUserPresence, NULL);
302 ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction");
303
304 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef);
305 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
306 changePasscode(passcode, NULL);
307 ok_status(SecItemDelete(item), "delete local - AKPU");
308 changePasscode(NULL, passcode);
309
310 aclWithDeleteConstraintRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlUserPresence, NULL);
311 ok(aclWithDeleteConstraintRef, "Create SecAccessControlRef which require UI interaction for Delete operation");
312 constraint = SecAccessConstraintCreatePolicy(kCFAllocatorDefault, CFSTR("DeviceOwnerAuthentication"), NULL);
313 ok(constraint);
314 ok(SecAccessControlAddConstraintForOperation(aclWithDeleteConstraintRef, kAKSKeyOpDelete, constraint, NULL), "Add constraint for operation delete");
315 CFReleaseSafe(constraint);
316
317 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithDeleteConstraintRef);
318 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
319 changePasscode(passcode, NULL);
320 ok_status(SecItemDelete(item), "delete local - AKPU + prot odel");
321 changePasscode(NULL, passcode);
322
323 CFReleaseNull(aclWithUIRef);
324 CFReleaseNull(aclWithDeleteConstraintRef);
325 }
326 CFReleaseNull(aclWithUIRef);
327 CFReleaseNull(aclWithDeleteConstraintRef);
328 }
329 #endif
330 CFReleaseNull(item);
331 CFReleaseNull(aclRef);
332 });
333 });
334
335 CFRelease(classArray);
336 CFRelease(protectionClassArray);
337 }
338
339 int secd_81_item_acl_stress(int argc, char *const *argv)
340 {
341 #if LA_CONTEXT_IMPLEMENTED
342 secd_test_setup_temp_keychain(__FUNCTION__, ^{
343 keybag_state_t state;
344 int passcode_len=(int)strlen(passcode);
345
346 ok(kIOReturnSuccess==aks_create_bag(passcode, passcode_len, kAppleKeyStoreDeviceBag, &test_keybag), "create keybag");
347 ok(kIOReturnSuccess==aks_get_lock_state(test_keybag, &state), "get keybag state");
348 ok(!(state&keybag_state_locked), "keybag unlocked");
349 SecItemServerSetKeychainKeybag(test_keybag);
350 });
351
352 bool isPasscodeSet = true;
353 #else
354 bool isPasscodeSet = false;
355 #endif
356
357 plan_tests(isPasscodeSet?776:140);
358
359 tests(isPasscodeSet);
360
361 #if LA_CONTEXT_IMPLEMENTED
362 SecItemServerResetKeychainKeybag();
363 #endif
364
365 return 0;
366 }