]> git.saurik.com Git - apple/security.git/blob - RegressionTests/secitemstresstest/secitemstresstest.m
Security-59754.80.3.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) {
47 printf("cleanup ag1: %d\n", (int)status);
48 }
49
50 query = @{
51 (id)kSecClass : (id)kSecClassGenericPassword,
52 (id)kSecAttrAccessGroup : kAccessGroup2,
53 (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue,
54 };
55 status = SecItemDelete((__bridge CFDictionaryRef)query);
56 if (status != errSecSuccess) {
57 printf("cleanup ag2: %d\n", (int)status);
58 }
59 }
60
61 static void
62 isPedestrian(const char *name, OSStatus status, bool ignorePedestrianFailures)
63 {
64 if (!ignorePedestrianFailures) {
65 if (status == errSecSuccess)
66 return;
67 } else {
68 switch(status) {
69 case errSecSuccess:
70 case errSecItemNotFound:
71 case errSecDuplicateItem:
72 return;
73 default:
74 break;
75 }
76 }
77 fail("[FAIL] %s non pedestrian error: %d", name, (int)status);
78 }
79
80 static void
81 CreateDeleteItem(NSString *account, NSString *accessGroup, bool ignorePedestrianFailures)
82 {
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],
91 };
92 OSStatus status;
93
94 status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
95 isPedestrian("SecItemAdd", status, ignorePedestrianFailures);
96
97 query = @{
98 (id)kSecClass : (id)kSecClassGenericPassword,
99 (id)kSecAttrAccount : account,
100 (id)kSecAttrAccessGroup : accessGroup,
101 };
102 NSDictionary *values = @{
103 (id)kSecAttrLabel : @"kaka",
104 };
105
106 status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)values);
107 isPedestrian("SecItemUpdate", status, ignorePedestrianFailures);
108
109 status = SecItemDelete((__bridge CFDictionaryRef)query);
110 isPedestrian("SecItemDelete", status, ignorePedestrianFailures);
111 }
112
113 #define CONCURRENT_RUNTIME 20
114
115 static void
116 CreateDeleteConcurrentItems(int width)
117 {
118 dispatch_semaphore_t sema;
119 dispatch_group_t group;
120 dispatch_queue_t q, labelQueue;
121 int iter = 0;
122 time_t old;
123 __block unsigned long label = 0;
124
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();
129
130
131 old = time(NULL);
132
133 while (time(NULL) - old < CONCURRENT_RUNTIME) {
134 size_t number = 10;
135
136 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
137
138 printf("iteration: %d\n", ++iter);
139
140 dispatch_group_async(group, q, ^{
141 dispatch_group_t inner = dispatch_group_create();
142 if (inner == NULL) abort();
143 __block unsigned long me;
144
145 dispatch_sync(labelQueue, ^{
146 me = label++;
147 if (label == 0) abort();
148 });
149
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);
154 });
155 });
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);
160 });
161 });
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);
166 });
167 });
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);
172 });
173 });
174
175 dispatch_group_wait(inner, DISPATCH_TIME_FOREVER);
176 dispatch_semaphore_signal(sema);
177 });
178 }
179
180 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
181 }
182
183 static void
184 CreateDeleteConcurrentSameItem(int width)
185 {
186 dispatch_semaphore_t sema;
187 dispatch_group_t group;
188 dispatch_queue_t q;
189 time_t old;
190
191 q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
192 sema = dispatch_semaphore_create(width);
193 group = dispatch_group_create();
194
195 old = time(NULL);
196
197 while (time(NULL) - old < CONCURRENT_RUNTIME) {
198 size_t number = 10;
199
200 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
201
202 dispatch_group_async(group, q, ^{
203 dispatch_apply(number, q, ^(size_t num) {
204 CreateDeleteItem(@"account1", kAccessGroup1, true);
205 });
206
207 dispatch_semaphore_signal(sema);
208 });
209 }
210
211 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
212 }
213
214
215
216 int main (int argc, const char * argv[])
217 {
218 @autoreleasepool {
219
220 Cleanup();
221 printf("[TEST] secitemstresstest\n");
222 printf("[BEGIN] testing serial items\n");
223
224 CreateDeleteItem(@"account1", kAccessGroup1, false);
225 CreateDeleteItem(@"account2", kAccessGroup1, false);
226 CreateDeleteItem(@"account1", kAccessGroup2, false);
227 CreateDeleteItem(@"account2", kAccessGroup2, false);
228 printf("[PASS]\n");
229
230 Cleanup();
231 printf("[BEGIN] testing concurrent items\n");
232
233 CreateDeleteConcurrentItems(2);
234 CreateDeleteConcurrentItems(10);
235 printf("[PASS]\n");
236
237 Cleanup();
238 printf("[BEGIN] testing concurrent same item\n");
239
240 CreateDeleteConcurrentSameItem(2);
241 CreateDeleteConcurrentSameItem(10);
242 printf("[PASS]\n");
243
244 printf("[SUMMARY]\n");
245 printf("test completed\n");
246
247 return 0;
248 }
249 }
250
251