]> git.saurik.com Git - apple/security.git/blob - secacltests/sec_acl_stress.c
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / secacltests / sec_acl_stress.c
1 //
2 // sec_acl_stress.c
3 // Security
4 //
5 // Created by Vratislav Kužela on 20/05/15.
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
22 #include "testlist.h"
23
24 #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
25 #define USE_KEYSTORE 1
26 #elif TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
27 #define USE_KEYSTORE 1
28 #else /* no keystore on this platform */
29 #define USE_KEYSTORE 0
30 #endif
31
32 #if USE_KEYSTORE
33 #include <coreauthd_spi.h>
34 #endif
35
36 #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
37 #include <MobileKeyBag/MobileKeyBag.h>
38 #endif
39
40 enum ItemAttrType {
41 kBoolItemAttr,
42 kNumberItemAttr,
43 kStringItemAttr,
44 kDataItemAttr,
45 kBlobItemAttr,
46 kDateItemAttr,
47 kAccessabilityItemAttr,
48 kAccessGroupItemAttr,
49 };
50
51 #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
52 CFStringRef temporaryPasscode = CFSTR("1111");
53 static bool changePasscode(CFStringRef oldPasscode, CFStringRef newPasscode)
54 {
55 CFDataRef oldPasscodeData = NULL;
56 CFDataRef newPasscodeData= NULL;
57 if (oldPasscode) {
58 oldPasscodeData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, oldPasscode, kCFStringEncodingUTF8, 0x00);
59 }
60
61 if (newPasscode) {
62 newPasscodeData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, newPasscode, kCFStringEncodingUTF8, 0x00);
63 }
64
65 int status = MKBKeyBagChangeSystemSecret(oldPasscodeData, newPasscodeData, NULL);
66
67 CFReleaseSafe(oldPasscodeData);
68 CFReleaseSafe(newPasscodeData);
69 return status == kMobileKeyBagSuccess;
70 }
71 #endif
72
73 #if !TARGET_IPHONE_SIMULATOR
74 static void WithEachString(void(^each)(CFStringRef attr, enum ItemAttrType atype), ...) {
75 va_list ap;
76 va_start(ap, each);
77 CFStringRef attr;
78 while((attr = va_arg(ap, CFStringRef)) != NULL) {
79 enum ItemAttrType atype = va_arg(ap, enum ItemAttrType);
80 each(attr, atype);
81 }
82 va_end(ap);
83 }
84
85 static void ItemForEachPKAttr(CFMutableDictionaryRef item, void(^each)(CFStringRef attr, enum ItemAttrType atype)) {
86 CFStringRef iclass = CFDictionaryGetValue(item, kSecClass);
87 if (!iclass) {
88 return;
89 } else if (CFEqual(iclass, kSecClassGenericPassword)) {
90 WithEachString(each,
91 kSecAttrAccessible, kAccessabilityItemAttr,
92 kSecAttrAccessGroup, kAccessGroupItemAttr,
93 kSecAttrAccount, kStringItemAttr,
94 kSecAttrService, kStringItemAttr,
95 kSecAttrSynchronizable, kBoolItemAttr,
96 NULL);
97 } else if (CFEqual(iclass, kSecClassInternetPassword)) {
98 WithEachString(each,
99 kSecAttrAccessible, kAccessabilityItemAttr,
100 kSecAttrAccessGroup, kAccessGroupItemAttr,
101 kSecAttrAccount, kStringItemAttr,
102 kSecAttrSecurityDomain, kStringItemAttr,
103 kSecAttrServer, kStringItemAttr,
104 kSecAttrProtocol, kNumberItemAttr,
105 kSecAttrAuthenticationType, kNumberItemAttr,
106 kSecAttrPort, kNumberItemAttr,
107 kSecAttrPath, kStringItemAttr,
108 kSecAttrSynchronizable, kBoolItemAttr,
109 NULL);
110 } else if (CFEqual(iclass, kSecClassCertificate)) {
111 WithEachString(each,
112 kSecAttrAccessible, kAccessabilityItemAttr,
113 kSecAttrAccessGroup, kAccessGroupItemAttr,
114 kSecAttrCertificateType, kNumberItemAttr,
115 kSecAttrIssuer, kDataItemAttr,
116 kSecAttrSerialNumber, kDataItemAttr,
117 kSecAttrSynchronizable, kBoolItemAttr,
118 NULL);
119 } else if (CFEqual(iclass, kSecClassKey)) {
120 WithEachString(each,
121 kSecAttrAccessible, kAccessabilityItemAttr,
122 kSecAttrAccessGroup, kAccessGroupItemAttr,
123 kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies
124 kSecAttrApplicationLabel, kDataItemAttr,
125 kSecAttrApplicationTag, kDataItemAttr,
126 kSecAttrKeyType, kNumberItemAttr,
127 kSecAttrKeySizeInBits, kNumberItemAttr,
128 kSecAttrEffectiveKeySize, kNumberItemAttr,
129 kSecAttrStartDate, kDateItemAttr,
130 kSecAttrEndDate, kDateItemAttr,
131 kSecAttrSynchronizable, kBoolItemAttr,
132 NULL);
133 } else if (CFEqual(iclass, kSecClassIdentity)) {
134 WithEachString(each,
135 kSecAttrAccessible, kAccessabilityItemAttr,
136 kSecAttrAccessGroup, kAccessGroupItemAttr,
137 kSecAttrCertificateType, kNumberItemAttr,
138 kSecAttrIssuer, kDataItemAttr,
139 kSecAttrSerialNumber, kDataItemAttr,
140 kSecAttrSynchronizable, kBoolItemAttr,
141 kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies
142 kSecAttrApplicationLabel, kDataItemAttr,
143 kSecAttrApplicationTag, kDataItemAttr,
144 kSecAttrKeyType, kNumberItemAttr,
145 kSecAttrKeySizeInBits, kNumberItemAttr,
146 kSecAttrEffectiveKeySize, kNumberItemAttr,
147 kSecAttrStartDate, kDateItemAttr,
148 kSecAttrEndDate, kDateItemAttr,
149 kSecAttrSynchronizable, kBoolItemAttr,
150 NULL);
151 }
152 }
153
154 static CFMutableDictionaryRef ItemCreate(int num) {
155 CFStringRef iclass = NULL;
156 switch (num % 4) {
157 case 0:
158 iclass = kSecClassInternetPassword;
159 break;
160 case 1:
161 iclass = kSecClassGenericPassword;
162 break;
163 case 2:
164 iclass = kSecClassKey;
165 break;
166 case 3:
167 iclass = kSecClassCertificate;
168 break;
169 }
170 return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, iclass, NULL);
171 }
172
173 static void tests(bool isPasscodeSet)
174 {
175 for (int num = 0 ; num < 8; ++num) {
176 __block CFTypeRef protection = kSecAttrAccessibleWhenUnlocked;
177 CFMutableDictionaryRef item = ItemCreate(num);
178 ItemForEachPKAttr(item, ^(CFStringRef attr, enum ItemAttrType atype) {
179 CFTypeRef value = NULL;
180 switch (atype) {
181 case kBoolItemAttr:
182 value = (num % 2 == 0 ? kCFBooleanTrue : kCFBooleanFalse);
183 CFRetain(value);
184 break;
185 case kNumberItemAttr:
186 value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
187 break;
188 case kStringItemAttr:
189 case kBlobItemAttr:
190 value = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("acl-stress-string-%d"), num);
191 break;
192 case kDataItemAttr:
193 {
194 char buf[10];
195 int len = snprintf(buf, sizeof(buf), "acl-stress-data-%d", num);
196 value = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buf, len);
197 break;
198 }
199 case kDateItemAttr:
200 value = NULL; // Don't mess with dates on create.
201 break;
202 case kAccessabilityItemAttr:
203 {
204 CFStringRef accessabilites[] = {
205 kSecAttrAccessibleWhenUnlocked,
206 kSecAttrAccessibleAfterFirstUnlock,
207 kSecAttrAccessibleAlwaysPrivate,
208 kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
209 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
210 kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate,
211 };
212 protection = accessabilites[num % array_size(accessabilites)];
213 break;
214 }
215 case kAccessGroupItemAttr:
216 {
217 CFStringRef accessGroups[] = {
218 NULL,
219 CFSTR("com.apple.security.sos"), // Secd internally uses this
220 };
221 value = accessGroups[num % array_size(accessGroups)];
222 break;
223 }
224 }
225 if (value)
226 CFDictionarySetValue(item, attr, value);
227 CFReleaseSafe(value);
228 });
229
230 SecAccessControlRef aclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL);
231 ok(aclRef, "Create SecAccessControlRef");
232 ok(SecAccessControlSetProtection(aclRef, protection, NULL), "Set protection");
233 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDecrypt, kCFBooleanTrue, NULL), "Set operation decrypt to true");
234 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDelete, kCFBooleanTrue, NULL), "Set operation delete to true");
235 ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpEncrypt, kCFBooleanTrue, NULL), "Set operation encrypt to true");
236
237 SecAccessControlRef invalidAclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL);
238 ok(invalidAclRef, "Create invalid SecAccessControlRef");
239 ok(SecAccessControlSetProtection(invalidAclRef, protection, NULL), "Set protection");
240 CFTypeRef constraint = SecAccessConstraintCreatePolicy(kCFAllocatorDefault, CFSTR("invalidPolicy"), NULL);
241 ok(constraint, "Create invalid constraint");
242 ok(SecAccessControlAddConstraintForOperation(invalidAclRef, kAKSKeyOpDecrypt, constraint, NULL), "Add invalid constraint");
243 CFReleaseSafe(constraint);
244
245 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse);
246 CFDictionarySetValue(item, kSecAttrAccessControl, invalidAclRef);
247 is_status(SecItemAdd(item, NULL), errSecParam, "do not add local with invalid acl");
248 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after add failed");
249
250 CFDictionarySetValue(item, kSecAttrAccessControl, aclRef);
251 ok_status(SecItemAdd(item, NULL), "add local ");
252 ok_status(SecItemCopyMatching(item, NULL), "find local");
253 ok_status(SecItemDelete(item), "delete local");
254 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local");
255
256 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanTrue);
257 is_status(SecItemAdd(item, NULL), errSecParam, "add sync");
258 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find sync");
259 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse);
260
261 #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
262 assert(protection);
263 SecAccessControlRef privateKeyUsageAclRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, kSecAccessControlPrivateKeyUsage, NULL);
264 ok(privateKeyUsageAclRef, "Create SecAccessControlRef for kSecAccessControlPrivateKeyUsage");
265 CFDictionarySetValue(item, kSecAttrAccessControl, privateKeyUsageAclRef);
266 is_status(SecItemAdd(item, NULL), errSecAuthFailed, "add local - kSecAccessControlPrivateKeyUsage without constraint");
267 CFReleaseNull(privateKeyUsageAclRef);
268
269 if(isPasscodeSet) {
270 privateKeyUsageAclRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, kSecAccessControlDevicePasscode | kSecAccessControlPrivateKeyUsage, NULL);
271 ok(privateKeyUsageAclRef, "Create SecAccessControlRef for kSecAccessControlPrivateKeyUsage");
272 CFDictionarySetValue(item, kSecAttrAccessControl, privateKeyUsageAclRef);
273 is_status(SecItemAdd(item, NULL), errSecAuthFailed, "add local - kSecAccessControlPrivateKeyUsage with constraint");
274 CFReleaseSafe(privateKeyUsageAclRef);
275 SecAccessControlRef aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, kSecAccessControlUserPresence, NULL);
276 ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction");
277
278 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef);
279 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
280 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
281 is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI");
282 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUISkip);
283 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "find local - acl with authentication UI");
284 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
285 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
286 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI");
287
288 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
289 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
290 is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI");
291 ok_status(SecItemDelete(item), "delete local - acl with authentication UI");
292 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI");
293 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
294 CFReleaseSafe(aclWithUIRef);
295
296 aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlUserPresence, NULL);
297 ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction");
298
299 CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef);
300 ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI");
301 changePasscode(temporaryPasscode, NULL);
302 ok_status(SecItemDelete(item), "delete local - AKPU");
303 changePasscode(NULL, temporaryPasscode);
304 CFReleaseSafe(aclWithUIRef);
305 }
306 #endif
307
308 CFDictionarySetValue(item, kSecUseAuthenticationUI, kSecUseAuthenticationUISkip);
309 is_status(SecItemAdd(item, NULL), errSecParam, "add local - invalid kSecUseAuthenticationUISkip");
310 is_status(SecItemDelete(item), errSecParam, "delete local - invalid kSecUseAuthenticationUISkip");
311
312 CFRelease(item);
313 CFReleaseSafe(aclRef);
314 CFReleaseSafe(invalidAclRef);
315 }
316 }
317 #endif
318
319 int sec_acl_stress(int argc, char *const *argv)
320 {
321 #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
322 bool removeTemporaryPasscode = false;
323 bool isPasscodeSet = false;
324 if (MKBGetDeviceLockState(NULL) == kMobileKeyBagDisabled) {
325 removeTemporaryPasscode = changePasscode(NULL, temporaryPasscode);
326 isPasscodeSet = MKBGetDeviceLockState(NULL) != kMobileKeyBagDisabled;
327 }
328
329 plan_tests(isPasscodeSet?288:168);
330 tests(isPasscodeSet);
331
332 if (removeTemporaryPasscode) {
333 changePasscode(temporaryPasscode, NULL);
334 }
335 #elif TARGET_OS_MAC && !TARGET_IPHONE_SIMULATOR
336 plan_tests(152);
337 tests(false);
338 #else
339 plan_tests(1);
340 ok(true);
341 #endif
342
343
344 return 0;
345 }