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