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