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) {
47 printf("cleanup ag1: %d\n", (int)status);
51 (id)kSecClass : (id)kSecClassGenericPassword,
52 (id)kSecAttrAccessGroup : kAccessGroup2,
53 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
55 status = SecItemDelete((__bridge CFDictionaryRef)query);
56 if (status != errSecSuccess) {
57 printf("cleanup ag2: %d\n", (int)status);
62 isPedestrian(const char *name, OSStatus status, bool ignorePedestrianFailures)
64 if (!ignorePedestrianFailures) {
65 if (status == errSecSuccess)
70 case errSecItemNotFound:
71 case errSecDuplicateItem:
77 fail("[FAIL] %s non pedestrian error: %d", name, (int)status);
81 CreateDeleteItem(NSString *account, NSString *accessGroup, bool ignorePedestrianFailures)
83 NSDictionary *query = @{
84 (id)kSecClass : (id)kSecClassGenericPassword,
85 (id)kSecAttrLabel : @"secitemstresstest-oneItem",
86 (id)kSecAttrAccount : account,
87 (id)kSecAttrAccessGroup : accessGroup,
88 (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock,
89 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
90 (id)kSecValueData : [NSData dataWithBytes:"password" length: 8],
94 status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
95 isPedestrian("SecItemAdd", status, ignorePedestrianFailures);
98 (id)kSecClass : (id)kSecClassGenericPassword,
99 (id)kSecAttrAccount : account,
100 (id)kSecAttrAccessGroup : accessGroup,
102 NSDictionary *values = @{
103 (id)kSecAttrLabel : @"kaka",
106 status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)values);
107 isPedestrian("SecItemUpdate", status, ignorePedestrianFailures);
109 status = SecItemDelete((__bridge CFDictionaryRef)query);
110 isPedestrian("SecItemDelete", status, ignorePedestrianFailures);
113 #define CONCURRENT_RUNTIME 20
116 CreateDeleteConcurrentItems(int width)
118 dispatch_semaphore_t sema;
119 dispatch_group_t group;
120 dispatch_queue_t q, labelQueue;
123 __block unsigned long label = 0;
125 q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
126 labelQueue = dispatch_queue_create("label-queue", NULL);
127 sema = dispatch_semaphore_create(width);
128 group = dispatch_group_create();
133 while (time(NULL) - old < CONCURRENT_RUNTIME) {
136 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
138 printf("iteration: %d\n", ++iter);
140 dispatch_group_async(group, q, ^{
141 dispatch_group_t inner = dispatch_group_create();
142 if (inner == NULL) abort();
143 __block unsigned long me;
145 dispatch_sync(labelQueue, ^{
147 if (label == 0) abort();
150 dispatch_group_async(inner, q, ^{
151 dispatch_apply(number, q, ^(size_t num) {
152 NSString *account = [NSString stringWithFormat:@"account1-%lu-%lu", me, (unsigned long)num];
153 CreateDeleteItem(account, kAccessGroup1, false);
156 dispatch_group_async(inner, q, ^{
157 dispatch_apply(number, q, ^(size_t num) {
158 NSString *account = [NSString stringWithFormat:@"account2-%lu-%lu", me, (unsigned long)num];
159 CreateDeleteItem(account, kAccessGroup1, false);
162 dispatch_group_async(inner, q, ^{
163 dispatch_apply(number, q, ^(size_t num) {
164 NSString *account = [NSString stringWithFormat:@"account1-%lu-%lu", me, (unsigned long)num];
165 CreateDeleteItem(account, kAccessGroup2, false);
168 dispatch_group_async(inner, q, ^{
169 dispatch_apply(number, q, ^(size_t num) {
170 NSString *account = [NSString stringWithFormat:@"account2-%lu-%lu", me, (unsigned long)num];
171 CreateDeleteItem(account, kAccessGroup2, false);
175 dispatch_group_wait(inner, DISPATCH_TIME_FOREVER);
176 dispatch_semaphore_signal(sema);
180 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
184 CreateDeleteConcurrentSameItem(int width)
186 dispatch_semaphore_t sema;
187 dispatch_group_t group;
191 q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
192 sema = dispatch_semaphore_create(width);
193 group = dispatch_group_create();
197 while (time(NULL) - old < CONCURRENT_RUNTIME) {
200 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
202 dispatch_group_async(group, q, ^{
203 dispatch_apply(number, q, ^(size_t num) {
204 CreateDeleteItem(@"account1", kAccessGroup1, true);
207 dispatch_semaphore_signal(sema);
211 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
216 int main (int argc, const char * argv[])
221 printf("[TEST] secitemstresstest\n");
222 printf("[BEGIN] testing serial items\n");
224 CreateDeleteItem(@"account1", kAccessGroup1, false);
225 CreateDeleteItem(@"account2", kAccessGroup1, false);
226 CreateDeleteItem(@"account1", kAccessGroup2, false);
227 CreateDeleteItem(@"account2", kAccessGroup2, false);
231 printf("[BEGIN] testing concurrent items\n");
233 CreateDeleteConcurrentItems(2);
234 CreateDeleteConcurrentItems(10);
238 printf("[BEGIN] testing concurrent same item\n");
240 CreateDeleteConcurrentSameItem(2);
241 CreateDeleteConcurrentSameItem(10);
244 printf("[SUMMARY]\n");
245 printf("test completed\n");