2 // Copyright 2016 Apple. All rights reserved.
6 * This is to fool os services to not provide the Keychain manager
7 * interface tht doens't work since we don't have unified headers
8 * between iOS and OS X. rdar://23405418/
10 #define __KEYCHAINCORE__ 1
12 #include <Foundation/Foundation.h>
13 #include <Security/Security.h>
14 #include <Security/SecItemPriv.h>
18 fail(const char *fmt, ...) __printflike(1, 2) __attribute__((noreturn));
22 fail(const char *fmt, ...)
31 static NSString *kAccessGroup1 = @"keychain-test1";
32 static NSString *kAccessGroup2 = @"keychain-test2";
41 (id)kSecClass : (id)kSecClassGenericPassword,
42 (id)kSecAttrAccessGroup : kAccessGroup1,
43 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
45 status = SecItemDelete((__bridge CFDictionaryRef)query);
46 if (status != errSecSuccess || status == errSecItemNotFound)
47 printf("cleanup ag1: %d\n", (int)status);
50 (id)kSecClass : (id)kSecClassGenericPassword,
51 (id)kSecAttrAccessGroup : kAccessGroup2,
52 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
54 status = SecItemDelete((__bridge CFDictionaryRef)query);
55 if (status != errSecSuccess || status != errSecItemNotFound)
56 printf("cleanup ag2: %d\n", (int)status);
60 isPedestrian(const char *name, OSStatus status, bool ignorePedestrianFailures)
62 if (!ignorePedestrianFailures) {
63 if (status == errSecSuccess)
68 case errSecItemNotFound:
69 case errSecDuplicateItem:
75 fail("[FAIL] %s non pedestrian error: %d", name, (int)status);
79 CreateDeleteItem(NSString *account, NSString *accessGroup, bool ignorePedestrianFailures)
81 NSDictionary *query = @{
82 (id)kSecClass : (id)kSecClassGenericPassword,
83 (id)kSecAttrLabel : @"secitemstresstest-oneItem",
84 (id)kSecAttrAccount : account,
85 (id)kSecAttrAccessGroup : accessGroup,
86 (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock,
87 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
88 (id)kSecValueData : [NSData dataWithBytes:"password" length: 8],
92 status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
93 isPedestrian("SecItemAdd", status, ignorePedestrianFailures);
96 (id)kSecClass : (id)kSecClassGenericPassword,
97 (id)kSecAttrAccount : account,
98 (id)kSecAttrAccessGroup : accessGroup,
100 NSDictionary *values = @{
101 (id)kSecAttrLabel : @"kaka",
104 status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)values);
105 isPedestrian("SecItemUpdate", status, ignorePedestrianFailures);
107 status = SecItemDelete((__bridge CFDictionaryRef)query);
108 isPedestrian("SecItemDelete", status, ignorePedestrianFailures);
111 #define CONCURRENT_RUNTIME 20
114 CreateDeleteConcurrentItems(int width)
116 dispatch_semaphore_t sema;
117 dispatch_group_t group;
118 dispatch_queue_t q, labelQueue;
121 __block unsigned long label = 0;
123 q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
124 labelQueue = dispatch_queue_create("label-queue", NULL);
125 sema = dispatch_semaphore_create(width);
126 group = dispatch_group_create();
131 while (time(NULL) - old < CONCURRENT_RUNTIME) {
134 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
136 printf("iteration: %d\n", ++iter);
138 dispatch_group_async(group, q, ^{
139 dispatch_group_t inner = dispatch_group_create();
140 if (inner == NULL) abort();
141 __block unsigned long me;
143 dispatch_sync(labelQueue, ^{
145 if (label == 0) abort();
148 dispatch_group_async(inner, q, ^{
149 dispatch_apply(number, q, ^(size_t num) {
150 NSString *account = [NSString stringWithFormat:@"account1-%lu-%lu", me, (unsigned long)num];
151 CreateDeleteItem(account, kAccessGroup1, false);
154 dispatch_group_async(inner, q, ^{
155 dispatch_apply(number, q, ^(size_t num) {
156 NSString *account = [NSString stringWithFormat:@"account2-%lu-%lu", me, (unsigned long)num];
157 CreateDeleteItem(account, kAccessGroup1, false);
160 dispatch_group_async(inner, q, ^{
161 dispatch_apply(number, q, ^(size_t num) {
162 NSString *account = [NSString stringWithFormat:@"account1-%lu-%lu", me, (unsigned long)num];
163 CreateDeleteItem(account, kAccessGroup2, false);
166 dispatch_group_async(inner, q, ^{
167 dispatch_apply(number, q, ^(size_t num) {
168 NSString *account = [NSString stringWithFormat:@"account2-%lu-%lu", me, (unsigned long)num];
169 CreateDeleteItem(account, kAccessGroup2, false);
173 dispatch_group_wait(inner, DISPATCH_TIME_FOREVER);
174 dispatch_semaphore_signal(sema);
178 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
182 CreateDeleteConcurrentSameItem(int width)
184 dispatch_semaphore_t sema;
185 dispatch_group_t group;
189 q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
190 sema = dispatch_semaphore_create(width);
191 group = dispatch_group_create();
195 while (time(NULL) - old < CONCURRENT_RUNTIME) {
198 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
200 dispatch_group_async(group, q, ^{
201 dispatch_apply(number, q, ^(size_t num) {
202 CreateDeleteItem(@"account1", kAccessGroup1, true);
205 dispatch_semaphore_signal(sema);
209 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
214 int main (int argc, const char * argv[])
219 printf("[TEST] secitemstresstest\n");
220 printf("[BEGIN] testing serial items\n");
222 CreateDeleteItem(@"account1", kAccessGroup1, false);
223 CreateDeleteItem(@"account2", kAccessGroup1, false);
224 CreateDeleteItem(@"account1", kAccessGroup2, false);
225 CreateDeleteItem(@"account2", kAccessGroup2, false);
229 printf("[BEGIN] testing concurrent items\n");
231 CreateDeleteConcurrentItems(2);
232 CreateDeleteConcurrentItems(10);
236 printf("[BEGIN] testing concurrent same item\n");
238 CreateDeleteConcurrentSameItem(2);
239 CreateDeleteConcurrentSameItem(10);
242 printf("[SUMMARY]\n");
243 printf("test completed\n");