]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/Regressions/secd-81-item-acl-stress.c
Security-57740.1.18.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 #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, NULL, 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
207 static void tests(bool isPasscodeSet)
208 {
209 CFErrorRef (^okBlock)(void) = ^ {
210 return (CFErrorRef)NULL;
211 };
212
213 #if LA_CONTEXT_IMPLEMENTED
214 CFErrorRef (^errorNotInteractiveBlock)(void) = ^ {
215 return createCFError(CFSTR(""), kLAErrorNotInteractive);
216 };
217 #endif
218
219 CFArrayRef classArray = CFArrayCreateForCFTypes(kCFAllocatorDefault, kSecClassInternetPassword, kSecClassGenericPassword, kSecClassKey, kSecClassCertificate, NULL);
220 CFArrayRef protectionClassArray = CFArrayCreateForCFTypes(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAlwaysPrivate,
221 kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
222 kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, NULL);
223
224 __block uint32_t pass = 0;
225 CFArrayForEach(classArray, ^(CFTypeRef itemClass) {
226 CFArrayForEach(protectionClassArray, ^(CFTypeRef protectionClass) {
227 CFMutableDictionaryRef item = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, itemClass, NULL);
228 fillItem(item, ++pass);
229
230 LASetErrorCodeBlock(okBlock);
231 SecAccessControlRef aclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL);
232 ok(aclRef, "Create SecAccessControlRef");
233 ok(SecAccessControlSetProtection(aclRef, protectionClass, NULL), "Set protection");
234 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDecrypt, kCFBooleanTrue, NULL), "Set operation decrypt to true");
235 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDelete, kCFBooleanTrue, NULL), "Set operation delete to true");
236 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpEncrypt, kCFBooleanTrue, NULL), "Set operation encrypt to true");
237
238 LASetErrorCodeBlock(okBlock);
239 CFDictionarySetValue(item, kSecAttrAccessControl, aclRef);
240 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse);
241 #if LA_CONTEXT_IMPLEMENTED
242 ok_status(SecItemAdd(item, NULL), "add local ");
243 ok_status(SecItemCopyMatching(item, NULL), "find local");
244 ok_status(SecItemDelete(item), "delete local");
245 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local");
246 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanTrue);
247 is_status(SecItemAdd(item, NULL), errSecParam, "add sync");
248 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find sync");
249 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse);
250
251 if(isPasscodeSet) {
252 SecAccessControlRef aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protectionClass, kSecAccessControlUserPresence, NULL);
253 ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction");
254
255 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef);
256 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
257 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
258 LASetErrorCodeBlock(errorNotInteractiveBlock);
259 is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI");
260 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUISkip);
261 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "find local - acl with authentication UI");
262 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
263 LASetErrorCodeBlock(okBlock);
264 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
265 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI");
266
267 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
268 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
269 LASetErrorCodeBlock(errorNotInteractiveBlock);
270 is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI");
271 LASetErrorCodeBlock(okBlock);
272 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
273 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI");
274 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
275
276 SecAccessControlRef aclWithDeleteConstraintRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protectionClass, kSecAccessControlUserPresence, NULL);
277 ok(aclWithDeleteConstraintRef, "Create SecAccessControlRef which require UI interaction for Delete operation");
278 CFTypeRef constraint = SecAccessConstraintCreatePolicy(kCFAllocatorDefault, CFSTR("DeviceOwnerAuthentication"), NULL);
279 ok(constraint);
280 ok(SecAccessControlAddConstraintForOperation(aclWithDeleteConstraintRef, kAKSKeyOpDelete, constraint, NULL), "Add constraint for operation delete");
281 CFReleaseSafe(constraint);
282
283 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithDeleteConstraintRef);
284 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
285 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
286 LASetErrorCodeBlock(errorNotInteractiveBlock);
287 is_status(SecItemDelete(item), errSecInteractionNotAllowed, "delete local - acl with authentication UI");
288
289 if (CFEqual(protectionClass, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)) {
290 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
291 ok(changePasscode(passcode, NULL));
292 LASetErrorCodeBlock(okBlock);
293 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
294 ok(changePasscode(NULL, passcode));
295
296 CFReleaseSafe(aclWithUIRef);
297 CFReleaseSafe(aclWithDeleteConstraintRef);
298
299 aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlUserPresence, NULL);
300 ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction");
301
302 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef);
303 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
304 changePasscode(passcode, NULL);
305 ok_status(SecItemDelete(item), "delete local - AKPU");
306 changePasscode(NULL, passcode);
307
308 aclWithDeleteConstraintRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlUserPresence, NULL);
309 ok(aclWithDeleteConstraintRef, "Create SecAccessControlRef which require UI interaction for Delete operation");
310 constraint = SecAccessConstraintCreatePolicy(kCFAllocatorDefault, CFSTR("DeviceOwnerAuthentication"), NULL);
311 ok(constraint);
312 ok(SecAccessControlAddConstraintForOperation(aclWithDeleteConstraintRef, kAKSKeyOpDelete, constraint, NULL), "Add constraint for operation delete");
313 CFReleaseSafe(constraint);
314
315 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithDeleteConstraintRef);
316 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
317 changePasscode(passcode, NULL);
318 ok_status(SecItemDelete(item), "delete local - AKPU + prot odel");
319 changePasscode(NULL, passcode);
320
321 CFReleaseNull(aclWithUIRef);
322 CFReleaseNull(aclWithDeleteConstraintRef);
323 }
324 CFReleaseNull(aclWithUIRef);
325 CFReleaseNull(aclWithDeleteConstraintRef);
326 }
327 #endif
328 CFReleaseNull(item);
329 CFReleaseNull(aclRef);
330 });
331 });
332
333 CFRelease(classArray);
334 CFRelease(protectionClassArray);
335 }
336
337 int secd_81_item_acl_stress(int argc, char *const *argv)
338 {
339 #if LA_CONTEXT_IMPLEMENTED
340 secd_test_setup_temp_keychain(__FUNCTION__, ^{
341 keybag_state_t state;
342 int passcode_len=(int)strlen(passcode);
343
344 ok(kIOReturnSuccess==aks_create_bag(passcode, passcode_len, kAppleKeyStoreDeviceBag, &test_keybag), "create keybag");
345 ok(kIOReturnSuccess==aks_get_lock_state(test_keybag, &state), "get keybag state");
346 ok(!(state&keybag_state_locked), "keybag unlocked");
347 SecItemServerSetKeychainKeybag(test_keybag);
348 });
349
350 bool isPasscodeSet = true;
351 #else
352 bool isPasscodeSet = false;
353 #endif
354
355 plan_tests(isPasscodeSet?776:140);
356
357 tests(isPasscodeSet);
358
359 #if LA_CONTEXT_IMPLEMENTED
360 SecItemServerResetKeychainKeybag();
361 #endif
362
363 return 0;
364 }