5 // Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
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>
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>
26 #include "secd_regressions.h"
29 #include <coreauthd_spi.h>
30 #include "SecdTestKeychainUtilities.h"
31 #if TARGET_OS_EMBEDDED
32 #include <MobileKeyBag/MobileKeyBag.h>
35 void kc_dbhandle_reset(void);
45 kAccessabilityItemAttr
,
49 extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock
)(void));
52 static keybag_handle_t test_keybag
;
53 static const char *passcode
= "password";
55 static bool changePasscode(const char *old_passcode
, const char *new_passcode
)
57 size_t old_passcode_len
= 0;
58 size_t new_passcode_len
= 0;
61 old_passcode_len
= strlen(old_passcode
);
64 new_passcode_len
= strlen(new_passcode
);
66 kern_return_t status
= aks_change_secret(test_keybag
, old_passcode
, (int)old_passcode_len
, new_passcode
, (int)new_passcode_len
, NULL
, NULL
);
71 static void WithEachString(void(^each
)(CFStringRef attr
, enum ItemAttrType atype
), ...) {
75 while((attr
= va_arg(ap
, CFStringRef
)) != NULL
) {
76 enum ItemAttrType atype
= va_arg(ap
, enum ItemAttrType
);
82 static void ItemForEachPKAttr(CFMutableDictionaryRef item
, void(^each
)(CFStringRef attr
, enum ItemAttrType atype
)) {
83 CFStringRef iclass
= CFDictionaryGetValue(item
, kSecClass
);
86 } else if (CFEqual(iclass
, kSecClassGenericPassword
)) {
88 kSecAttrAccessible
, kAccessabilityItemAttr
,
89 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
90 kSecAttrAccount
, kStringItemAttr
,
91 kSecAttrService
, kStringItemAttr
,
92 kSecAttrSynchronizable
, kBoolItemAttr
,
94 } else if (CFEqual(iclass
, kSecClassInternetPassword
)) {
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
,
107 } else if (CFEqual(iclass
, kSecClassCertificate
)) {
109 kSecAttrAccessible
, kAccessabilityItemAttr
,
110 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
111 kSecAttrCertificateType
, kNumberItemAttr
,
112 kSecAttrIssuer
, kDataItemAttr
,
113 kSecAttrSerialNumber
, kDataItemAttr
,
114 kSecAttrSynchronizable
, kBoolItemAttr
,
116 } else if (CFEqual(iclass
, kSecClassKey
)) {
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
,
130 } else if (CFEqual(iclass
, kSecClassIdentity
)) {
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
,
153 static CFErrorRef
createCFError(CFStringRef message
, CFIndex code
)
155 const void* keysPtr
[1];
156 const void* messagesPtr
[1];
158 keysPtr
[0] = kCFErrorLocalizedDescriptionKey
;
159 messagesPtr
[0] = message
;
160 return CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault
, CFSTR(kLAErrorDomain
), code
, keysPtr
, messagesPtr
, 1);
164 static void fillItem(CFMutableDictionaryRef item
, uint32_t num
)
166 ItemForEachPKAttr(item
, ^(CFStringRef attr
, enum ItemAttrType atype
) {
167 CFTypeRef value
= NULL
;
170 value
= (num
% 2 == 0 ? kCFBooleanTrue
: kCFBooleanFalse
);
173 case kNumberItemAttr
:
174 value
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &num
);
176 case kStringItemAttr
:
178 value
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("acl-stress-string-%d"), num
);
183 int len
= snprintf(buf
, sizeof(buf
), "acl-stress-data-%d", num
);
184 value
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)buf
, len
);
188 value
= NULL
; // Don't mess with dates on create.
190 case kAccessabilityItemAttr
:
192 case kAccessGroupItemAttr
:
194 CFStringRef accessGroups
[] = {
196 CFSTR("com.apple.security.sos"), // Secd internally uses this
198 value
= accessGroups
[num
% array_size(accessGroups
)];
203 CFDictionarySetValue(item
, attr
, value
);
204 CFReleaseSafe(value
);
208 static void tests(bool isPasscodeSet
)
210 CFErrorRef (^okBlock
)(void) = ^ {
211 return (CFErrorRef
)NULL
;
215 CFErrorRef (^errorNotInteractiveBlock
)(void) = ^ {
216 return createCFError(CFSTR(""), kLAErrorNotInteractive
);
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
);
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
);
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");
239 LASetErrorCodeBlock(okBlock
);
240 CFDictionarySetValue(item
, kSecAttrAccessControl
, aclRef
);
241 CFDictionarySetValue(item
, kSecAttrSynchronizable
, kCFBooleanFalse
);
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");
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
);
255 SecAccessControlRef aclWithUIRef
= SecAccessControlCreateWithFlags(kCFAllocatorDefault
, protectionClass
, kSecAccessControlUserPresence
, NULL
);
256 ok(aclWithUIRef
, "Create SecAccessControlRef which require UI interaction");
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");
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
);
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
);
283 ok(SecAccessControlAddConstraintForOperation(aclWithDeleteConstraintRef
, kAKSKeyOpDelete
, constraint
, NULL
), "Add constraint for operation delete");
284 CFReleaseSafe(constraint
);
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");
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
));
299 CFReleaseSafe(aclWithUIRef
);
300 CFReleaseSafe(aclWithDeleteConstraintRef
);
302 aclWithUIRef
= SecAccessControlCreateWithFlags(kCFAllocatorDefault
, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
, kSecAccessControlUserPresence
, NULL
);
303 ok(aclWithUIRef
, "Create SecAccessControlRef which require UI interaction");
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
);
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
);
315 ok(SecAccessControlAddConstraintForOperation(aclWithDeleteConstraintRef
, kAKSKeyOpDelete
, constraint
, NULL
), "Add constraint for operation delete");
316 CFReleaseSafe(constraint
);
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
);
324 CFReleaseNull(aclWithUIRef
);
325 CFReleaseNull(aclWithDeleteConstraintRef
);
327 CFReleaseNull(aclWithUIRef
);
328 CFReleaseNull(aclWithDeleteConstraintRef
);
332 CFReleaseNull(aclRef
);
336 CFRelease(classArray
);
337 CFRelease(protectionClassArray
);
340 int secd_81_item_acl_stress(int argc
, char *const *argv
)
343 secd_test_setup_temp_keychain(__FUNCTION__
, ^{
344 keybag_state_t state
;
345 int passcode_len
=(int)strlen(passcode
);
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
);
353 bool isPasscodeSet
= true;
355 bool isPasscodeSet
= false;
358 plan_tests(isPasscodeSet
?776:196);
360 tests(isPasscodeSet
);
363 SecItemServerResetKeychainKeybag();