]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-12-item-stress.c
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-12-item-stress.c
1 /*
2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include <CoreFoundation/CoreFoundation.h>
26 #include <Security/SecCertificate.h>
27 #include <Security/SecItem.h>
28 #include <Security/SecItemPriv.h>
29 #include <Security/SecBase.h>
30 #include <utilities/array_size.h>
31 #include <utilities/SecCFWrappers.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34
35 #include "Security_regressions.h"
36
37 #if 0
38 static void persistentRefIs(CFDataRef pref, CFDataRef data) {
39 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
40 CFTypeRef result = NULL;
41 CFDictionaryAddValue(dict, kSecValuePersistentRef, pref);
42 CFDictionaryAddValue(dict, kSecReturnData, kCFBooleanTrue);
43 ok_status(SecItemCopyMatching(dict, &result), "lookup item data by persistent ref");
44 ok(CFEqual(data, result), "result %@ equals expected data %@", result, data);
45 CFReleaseNull(result);
46 CFReleaseNull(dict);
47 }
48 #endif
49
50 enum ItemAttrType {
51 kBoolItemAttr,
52 kNumberItemAttr,
53 kStringItemAttr,
54 kDataItemAttr,
55 kBlobItemAttr,
56 kDateItemAttr,
57 kAccessabilityItemAttr,
58 kAccessGroupItemAttr,
59 };
60
61 static void WithEachString(void(^each)(CFStringRef attr, enum ItemAttrType atype), ...) {
62 va_list ap;
63 va_start(ap, each);
64 CFStringRef attr;
65 while((attr = va_arg(ap, CFStringRef)) != NULL) {
66 enum ItemAttrType atype = va_arg(ap, enum ItemAttrType);
67 each(attr, atype);
68 }
69 va_end(ap);
70 }
71
72 #if 0
73 static void ItemForEachAttr(CFMutableDictionaryRef item, void(^each)(CFStringRef attr, enum ItemAttrType atype)) {
74 CFStringRef iclass = CFDictionaryGetValue(item, kSecClass);
75 if (!iclass) {
76 return;
77 } else if (CFEqual(iclass, kSecClassGenericPassword)) {
78 WithEachString(each,
79 kSecAttrAccessible, kAccessabilityItemAttr,
80 kSecAttrAccessGroup, kAccessGroupItemAttr,
81 kSecAttrCreationDate, kDateItemAttr,
82 kSecAttrModificationDate, kDateItemAttr,
83 kSecAttrDescription, kStringItemAttr,
84 kSecAttrComment, kStringItemAttr,
85 kSecAttrCreator, kNumberItemAttr,
86 kSecAttrType, kNumberItemAttr,
87 kSecAttrLabel, kStringItemAttr,
88 kSecAttrIsInvisible, kBoolItemAttr,
89 kSecAttrIsNegative, kBoolItemAttr,
90 kSecAttrAccount, kStringItemAttr,
91 kSecAttrService, kStringItemAttr,
92 kSecAttrGeneric, kDataItemAttr,
93 kSecAttrSynchronizable, kBoolItemAttr,
94 NULL);
95 } else if (CFEqual(iclass, kSecClassInternetPassword)) {
96 WithEachString(each,
97 kSecAttrAccessible, kAccessabilityItemAttr,
98 kSecAttrAccessGroup, kAccessGroupItemAttr,
99 kSecAttrCreationDate, kDateItemAttr,
100 kSecAttrModificationDate, kDateItemAttr,
101 kSecAttrDescription, kStringItemAttr,
102 kSecAttrComment, kStringItemAttr,
103 kSecAttrCreator, kNumberItemAttr,
104 kSecAttrType, kNumberItemAttr,
105 kSecAttrLabel, kStringItemAttr,
106 kSecAttrIsInvisible, kBoolItemAttr,
107 kSecAttrIsNegative, kBoolItemAttr,
108 kSecAttrAccount, kStringItemAttr,
109 kSecAttrSecurityDomain, kStringItemAttr,
110 kSecAttrServer, kStringItemAttr,
111 kSecAttrProtocol, kNumberItemAttr,
112 kSecAttrAuthenticationType, kNumberItemAttr,
113 kSecAttrPort, kNumberItemAttr,
114 kSecAttrPath, kStringItemAttr,
115 kSecAttrSynchronizable, kBoolItemAttr,
116 NULL);
117 } else if (CFEqual(iclass, kSecClassCertificate)) {
118 WithEachString(each,
119 kSecAttrAccessible, kAccessabilityItemAttr,
120 kSecAttrAccessGroup, kAccessGroupItemAttr,
121 kSecAttrCertificateType, kNumberItemAttr,
122 kSecAttrCertificateEncoding, kNumberItemAttr,
123 kSecAttrLabel, kStringItemAttr,
124 kSecAttrSubject, kDataItemAttr,
125 kSecAttrIssuer, kDataItemAttr,
126 kSecAttrSerialNumber, kDataItemAttr,
127 kSecAttrSubjectKeyID, kDataItemAttr,
128 kSecAttrPublicKeyHash, kDataItemAttr,
129 kSecAttrSynchronizable, kBoolItemAttr,
130 NULL);
131 } else if (CFEqual(iclass, kSecClassKey)) {
132 WithEachString(each,
133 kSecAttrAccessible, kAccessabilityItemAttr,
134 kSecAttrAccessGroup, kAccessGroupItemAttr,
135 kSecAttrKeyClass, kStringItemAttr, // Might be Number on replies
136 kSecAttrLabel, kStringItemAttr,
137 kSecAttrApplicationLabel, kDataItemAttr,
138 kSecAttrIsPermanent, kBoolItemAttr,
139 kSecAttrApplicationTag, kDataItemAttr,
140 kSecAttrKeyType, kNumberItemAttr,
141 kSecAttrKeySizeInBits, kNumberItemAttr,
142 kSecAttrEffectiveKeySize, kNumberItemAttr,
143 kSecAttrCanEncrypt, kBoolItemAttr,
144 kSecAttrCanDecrypt, kBoolItemAttr,
145 kSecAttrCanDerive, kBoolItemAttr,
146 kSecAttrCanSign, kBoolItemAttr,
147 kSecAttrCanVerify, kBoolItemAttr,
148 kSecAttrCanWrap, kBoolItemAttr,
149 kSecAttrCanUnwrap, kBoolItemAttr,
150 kSecAttrStartDate, kDateItemAttr,
151 kSecAttrEndDate, kDateItemAttr,
152 kSecAttrSynchronizable, kBoolItemAttr,
153 NULL);
154 } else if (CFEqual(iclass, kSecClassIdentity)) {
155 WithEachString(each,
156 kSecAttrAccessible, kAccessabilityItemAttr,
157 kSecAttrAccessGroup, kAccessGroupItemAttr,
158 kSecAttrCertificateType, kNumberItemAttr,
159 kSecAttrCertificateEncoding, kNumberItemAttr,
160 kSecAttrLabel, kStringItemAttr,
161 kSecAttrSubject, kDataItemAttr,
162 kSecAttrIssuer, kDataItemAttr,
163 kSecAttrSerialNumber, kDataItemAttr,
164 kSecAttrSubjectKeyID, kDataItemAttr,
165 kSecAttrPublicKeyHash, kDataItemAttr,
166 kSecAttrKeyClass, kStringItemAttr, // Might be Number on replies
167 kSecAttrApplicationLabel, kDataItemAttr,
168 kSecAttrIsPermanent, kBoolItemAttr,
169 kSecAttrApplicationTag, kDataItemAttr,
170 kSecAttrKeyType, kNumberItemAttr,
171 kSecAttrKeySizeInBits, kNumberItemAttr,
172 kSecAttrEffectiveKeySize, kNumberItemAttr,
173 kSecAttrCanEncrypt, kBoolItemAttr,
174 kSecAttrCanDecrypt, kBoolItemAttr,
175 kSecAttrCanDerive, kBoolItemAttr,
176 kSecAttrCanSign, kBoolItemAttr,
177 kSecAttrCanVerify, kBoolItemAttr,
178 kSecAttrCanWrap, kBoolItemAttr,
179 kSecAttrCanUnwrap, kBoolItemAttr,
180 kSecAttrStartDate, kDateItemAttr,
181 kSecAttrEndDate, kDateItemAttr,
182 kSecAttrSynchronizable, kBoolItemAttr,
183 NULL);
184 }
185 }
186 #endif
187
188 static void ItemForEachPKAttr(CFMutableDictionaryRef item, void(^each)(CFStringRef attr, enum ItemAttrType atype)) {
189 CFStringRef iclass = CFDictionaryGetValue(item, kSecClass);
190 if (!iclass) {
191 return;
192 } else if (CFEqual(iclass, kSecClassGenericPassword)) {
193 WithEachString(each,
194 kSecAttrAccessGroup, kAccessGroupItemAttr,
195 kSecAttrAccount, kStringItemAttr,
196 kSecAttrService, kStringItemAttr,
197 kSecAttrSynchronizable, kBoolItemAttr,
198 NULL);
199 } else if (CFEqual(iclass, kSecClassInternetPassword)) {
200 WithEachString(each,
201 kSecAttrAccessGroup, kAccessGroupItemAttr,
202 kSecAttrAccount, kStringItemAttr,
203 kSecAttrSecurityDomain, kStringItemAttr,
204 kSecAttrServer, kStringItemAttr,
205 kSecAttrProtocol, kNumberItemAttr,
206 kSecAttrAuthenticationType, kNumberItemAttr,
207 kSecAttrPort, kNumberItemAttr,
208 kSecAttrPath, kStringItemAttr,
209 kSecAttrSynchronizable, kBoolItemAttr,
210 NULL);
211 } else if (CFEqual(iclass, kSecClassCertificate)) {
212 WithEachString(each,
213 kSecAttrAccessGroup, kAccessGroupItemAttr,
214 kSecAttrCertificateType, kNumberItemAttr,
215 kSecAttrIssuer, kDataItemAttr,
216 kSecAttrSerialNumber, kDataItemAttr,
217 kSecAttrSynchronizable, kBoolItemAttr,
218 NULL);
219 } else if (CFEqual(iclass, kSecClassKey)) {
220 WithEachString(each,
221 kSecAttrAccessGroup, kAccessGroupItemAttr,
222 kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies
223 kSecAttrApplicationLabel, kDataItemAttr,
224 kSecAttrApplicationTag, kDataItemAttr,
225 kSecAttrKeyType, kNumberItemAttr,
226 kSecAttrKeySizeInBits, kNumberItemAttr,
227 kSecAttrEffectiveKeySize, kNumberItemAttr,
228 kSecAttrStartDate, kDateItemAttr,
229 kSecAttrEndDate, kDateItemAttr,
230 kSecAttrSynchronizable, kBoolItemAttr,
231 NULL);
232 } else if (CFEqual(iclass, kSecClassIdentity)) {
233 WithEachString(each,
234 kSecAttrAccessGroup, kAccessGroupItemAttr,
235 kSecAttrCertificateType, kNumberItemAttr,
236 kSecAttrIssuer, kDataItemAttr,
237 kSecAttrSerialNumber, kDataItemAttr,
238 kSecAttrSynchronizable, kBoolItemAttr,
239 kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies
240 kSecAttrApplicationLabel, kDataItemAttr,
241 kSecAttrApplicationTag, kDataItemAttr,
242 kSecAttrKeyType, kNumberItemAttr,
243 kSecAttrKeySizeInBits, kNumberItemAttr,
244 kSecAttrEffectiveKeySize, kNumberItemAttr,
245 kSecAttrStartDate, kDateItemAttr,
246 kSecAttrEndDate, kDateItemAttr,
247 kSecAttrSynchronizable, kBoolItemAttr,
248 NULL);
249 }
250 }
251
252 static CFMutableDictionaryRef ItemCreate(int num) {
253 CFStringRef iclass = NULL;
254 switch (num % 4) {
255 case 0:
256 iclass = kSecClassInternetPassword;
257 break;
258 case 1:
259 iclass = kSecClassGenericPassword;
260 break;
261 case 2:
262 iclass = kSecClassKey;
263 break;
264 case 3:
265 iclass = kSecClassCertificate;
266 break;
267 }
268 return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, iclass, NULL);
269 }
270
271 /* Test add api in all it's variants. */
272 static void tests(void)
273 {
274 for (int num = 0 ; num < 8; ++num) {
275 CFMutableDictionaryRef item = ItemCreate(num);
276 ItemForEachPKAttr(item, ^(CFStringRef attr, enum ItemAttrType atype) {
277 CFTypeRef value = NULL;
278 switch (atype) {
279 case kBoolItemAttr:
280 value = (num % 2 == 0 ? kCFBooleanTrue : kCFBooleanFalse);
281 CFRetain(value);
282 break;
283 case kNumberItemAttr:
284 value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
285 break;
286 case kStringItemAttr:
287 case kBlobItemAttr:
288 value = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("string-%d"), num);
289 break;
290 case kDataItemAttr:
291 {
292 char buf[10];
293 int len = snprintf(buf, sizeof(buf), "data-%d", num);
294 value = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buf, len);
295 break;
296 }
297 case kDateItemAttr:
298 value = NULL; // Don't mess with dates on create.
299 break;
300 case kAccessabilityItemAttr:
301 {
302 CFStringRef accessabilites[] = {
303 kSecAttrAccessibleWhenUnlocked,
304 kSecAttrAccessibleAfterFirstUnlock,
305 kSecAttrAccessibleAlways,
306 kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
307 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
308 kSecAttrAccessibleAlwaysThisDeviceOnly,
309 };
310 value = accessabilites[num % array_size(accessabilites)];
311 break;
312 }
313 case kAccessGroupItemAttr:
314 {
315 CFStringRef accessGroups[] = {
316 NULL,
317 #if 0
318 #if NO_SERVER
319 CFSTR("test"),
320 CFSTR("apple"),
321 CFSTR("lockdown-identities"),
322 #else
323 CFSTR("sync"),
324 #endif
325 CFSTR("com.apple.security.sos"), // Secd internally uses this
326
327 CFSTR("com.apple.security.regressions"), // SecurityTestApp is in this group.
328 #endif
329 };
330 value = accessGroups[num % array_size(accessGroups)];
331 break;
332 }
333 }
334 if (value)
335 CFDictionarySetValue(item, attr, value);
336 CFReleaseSafe(value);
337 });
338
339 CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanTrue);
340 ok_status(SecItemAdd(item, NULL), "add sync");
341
342 // No tombstones by default per rdar://14680869, so explicitly add one
343 CFDictionarySetValue(item, kSecUseTombstones, kCFBooleanTrue);
344 ok_status(SecItemDelete(item), "delete sync");
345
346 CFDictionarySetValue(item, kSecAttrTombstone, kCFBooleanTrue);
347 ok_status(SecItemCopyMatching(item, NULL), "find tombstone after delete sync");
348 ok_status(SecItemDelete(item), "delete sync tombstone");
349 CFDictionaryRemoveValue(item, kSecAttrTombstone);
350
351 ok_status(SecItemAdd(item, NULL), "add sync again");
352
353 CFDictionarySetValue(item, kSecUseTombstones, kCFBooleanFalse);
354 ok_status(SecItemDelete(item), "delete sync without leaving a tombstone behind");
355 CFDictionaryRemoveValue(item, kSecUseTombstones);
356
357 CFDictionarySetValue(item, kSecAttrTombstone, kCFBooleanTrue);
358 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find tombstone after delete sync with kSecUseTombstones=false");
359
360 CFDictionaryRemoveValue(item, kSecAttrSynchronizable);
361 ok_status(SecItemAdd(item, NULL), "add local");
362 ok_status(SecItemDelete(item), "delete local");
363
364 CFDictionarySetValue(item, kSecAttrTombstone, kCFBooleanTrue);
365 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find tombstone after delete local");
366 is_status(SecItemDelete(item), errSecItemNotFound, "do not delete tombstone after delete local");
367 CFDictionaryRemoveValue(item, kSecAttrTombstone);
368
369 ok_status(SecItemAdd(item, NULL), "add local again");
370
371 CFDictionarySetValue(item, kSecUseTombstones, kCFBooleanTrue);
372 ok_status(SecItemDelete(item), "delete local and leave a tombstone behind");
373 CFDictionaryRemoveValue(item, kSecUseTombstones);
374
375 CFDictionarySetValue(item, kSecAttrTombstone, kCFBooleanTrue);
376 ok_status(SecItemCopyMatching(item, NULL), "find tombstone after delete sync with kSecUseTombstones=true");
377
378 CFDictionarySetValue(item, kSecUseTombstones, kCFBooleanTrue);
379 ok_status(SecItemDelete(item), "delete local tombstone kSecUseTombstones=true");
380 CFDictionaryRemoveValue(item, kSecUseTombstones);
381
382 ok_status(SecItemCopyMatching(item, NULL), "find tombstone after delete local tombstone with kSecUseTombstones=true");
383 ok_status(SecItemDelete(item), "delete local tombstone");
384 is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find tombstone after delete local");
385
386 CFRelease(item);
387 }
388 }
389
390 int si_12_item_stress(int argc, char *const *argv)
391 {
392 plan_tests(144);
393
394 tests();
395
396 return 0;
397 }