]> git.saurik.com Git - apple/security.git/blob - RegressionTests/secitemstresstest/secitemstresstest.m
Security-59306.101.1.tar.gz
[apple/security.git] / RegressionTests / secitemstresstest / secitemstresstest.m
1 //
2 // Copyright 2016 Apple. All rights reserved.
3 //
4
5 /*
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/
9 */
10 #define __KEYCHAINCORE__ 1
11
12 #include <Foundation/Foundation.h>
13 #include <Security/Security.h>
14 #include <Security/SecItemPriv.h>
15 #include <err.h>
16
17 static void
18 fail(const char *fmt, ...) __printflike(1, 2) __attribute__((noreturn));
19
20
21 static void
22 fail(const char *fmt, ...)
23 {
24 va_list ap;
25 va_start(ap, fmt);
26 printf("[FAIL] ");
27 verrx(1, fmt, ap);
28 va_end(ap);
29 }
30
31 static NSString *kAccessGroup1 = @"keychain-test1";
32 static NSString *kAccessGroup2 = @"keychain-test2";
33
34 static void
35 Cleanup(void)
36 {
37 NSDictionary *query;
38 OSStatus status;
39
40 query = @{
41 (id)kSecClass : (id)kSecClassGenericPassword,
42 (id)kSecAttrAccessGroup : kAccessGroup1,
43 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
44 };
45 status = SecItemDelete((__bridge CFDictionaryRef)query);
46 if (status != errSecSuccess || status == errSecItemNotFound)
47 printf("cleanup ag1: %d\n", (int)status);
48
49 query = @{
50 (id)kSecClass : (id)kSecClassGenericPassword,
51 (id)kSecAttrAccessGroup : kAccessGroup2,
52 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
53 };
54 status = SecItemDelete((__bridge CFDictionaryRef)query);
55 if (status != errSecSuccess || status != errSecItemNotFound)
56 printf("cleanup ag2: %d\n", (int)status);
57 }
58
59 static void
60 isPedestrian(const char *name, OSStatus status, bool ignorePedestrianFailures)
61 {
62 if (!ignorePedestrianFailures) {
63 if (status == errSecSuccess)
64 return;
65 } else {
66 switch(status) {
67 case errSecSuccess:
68 case errSecItemNotFound:
69 case errSecDuplicateItem:
70 return;
71 default:
72 break;
73 }
74 }
75 fail("[FAIL] %s non pedestrian error: %d", name, (int)status);
76 }
77
78 static void
79 CreateDeleteItem(NSString *account, NSString *accessGroup, bool ignorePedestrianFailures)
80 {
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],
89 };
90 OSStatus status;
91
92 status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
93 isPedestrian("SecItemAdd", status, ignorePedestrianFailures);
94
95 query = @{
96 (id)kSecClass : (id)kSecClassGenericPassword,
97 (id)kSecAttrAccount : account,
98 (id)kSecAttrAccessGroup : accessGroup,
99 };
100 NSDictionary *values = @{
101 (id)kSecAttrLabel : @"kaka",
102 };
103
104 status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)values);
105 isPedestrian("SecItemUpdate", status, ignorePedestrianFailures);
106
107 status = SecItemDelete((__bridge CFDictionaryRef)query);
108 isPedestrian("SecItemDelete", status, ignorePedestrianFailures);
109 }
110
111 #define CONCURRENT_RUNTIME 20
112
113 static void
114 CreateDeleteConcurrentItems(int width)
115 {
116 dispatch_semaphore_t sema;
117 dispatch_group_t group;
118 dispatch_queue_t q, labelQueue;
119 int iter = 0;
120 time_t old;
121 __block unsigned long label = 0;
122
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();
127
128
129 old = time(NULL);
130
131 while (time(NULL) - old < CONCURRENT_RUNTIME) {
132 size_t number = 10;
133
134 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
135
136 printf("iteration: %d\n", ++iter);
137
138 dispatch_group_async(group, q, ^{
139 dispatch_group_t inner = dispatch_group_create();
140 if (inner == NULL) abort();
141 __block unsigned long me;
142
143 dispatch_sync(labelQueue, ^{
144 me = label++;
145 if (label == 0) abort();
146 });
147
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);
152 });
153 });
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);
158 });
159 });
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);
164 });
165 });
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);
170 });
171 });
172
173 dispatch_group_wait(inner, DISPATCH_TIME_FOREVER);
174 dispatch_semaphore_signal(sema);
175 });
176 }
177
178 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
179 }
180
181 static void
182 CreateDeleteConcurrentSameItem(int width)
183 {
184 dispatch_semaphore_t sema;
185 dispatch_group_t group;
186 dispatch_queue_t q;
187 time_t old;
188
189 q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
190 sema = dispatch_semaphore_create(width);
191 group = dispatch_group_create();
192
193 old = time(NULL);
194
195 while (time(NULL) - old < CONCURRENT_RUNTIME) {
196 size_t number = 10;
197
198 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
199
200 dispatch_group_async(group, q, ^{
201 dispatch_apply(number, q, ^(size_t num) {
202 CreateDeleteItem(@"account1", kAccessGroup1, true);
203 });
204
205 dispatch_semaphore_signal(sema);
206 });
207 }
208
209 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
210 }
211
212
213
214 int main (int argc, const char * argv[])
215 {
216 @autoreleasepool {
217
218 Cleanup();
219 printf("[TEST] secitemstresstest\n");
220 printf("[BEGIN] testing serial items\n");
221
222 CreateDeleteItem(@"account1", kAccessGroup1, false);
223 CreateDeleteItem(@"account2", kAccessGroup1, false);
224 CreateDeleteItem(@"account1", kAccessGroup2, false);
225 CreateDeleteItem(@"account2", kAccessGroup2, false);
226 printf("[PASS]\n");
227
228 Cleanup();
229 printf("[BEGIN] testing concurrent items\n");
230
231 CreateDeleteConcurrentItems(2);
232 CreateDeleteConcurrentItems(10);
233 printf("[PASS]\n");
234
235 Cleanup();
236 printf("[BEGIN] testing concurrent same item\n");
237
238 CreateDeleteConcurrentSameItem(2);
239 CreateDeleteConcurrentSameItem(10);
240 printf("[PASS]\n");
241
242 printf("[SUMMARY]\n");
243 printf("test completed\n");
244
245 return 0;
246 }
247 }
248
249