]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c
Security-57336.10.29.tar.gz
[apple/security.git] / OSX / sec / securityd / Regressions / secd-33-keychain-ctk.c
1 /*
2 * Copyright (c) 2015 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/SecFramework.h>
27 #include <Security/SecBase.h>
28 #include <Security/SecItem.h>
29 #include <Security/SecItemPriv.h>
30 #include <Security/SecKey.h>
31 #include <Security/SecKeyPriv.h>
32 #include <Security/SecECKey.h>
33 #include <Security/SecAccessControl.h>
34 #include <Security/SecAccessControlPriv.h>
35 #include <Security/SecInternal.h>
36 #include <utilities/SecFileLocations.h>
37 #include <utilities/SecCFWrappers.h>
38 #include <utilities/SecCFError.h>
39
40 #include <libaks_acl_cf_keys.h>
41
42 #include <ctkclient_test.h>
43
44 #include "secd_regressions.h"
45
46 #include "SecdTestKeychainUtilities.h"
47 #include "SecKeybagSupport.h"
48
49 extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock)(void));
50
51 static void test_item_add(void) {
52
53 static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
54 CFDataRef valueData = CFDataCreate(NULL, data, sizeof(data));
55 static const UInt8 oid[] = { 0x05, 0x06, 0x07, 0x08 };
56 CFDataRef oidData = CFDataCreate(NULL, oid, sizeof(oid));
57
58 CFMutableDictionaryRef attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
59 kSecClass, kSecClassGenericPassword,
60 kSecAttrTokenID, CFSTR("tokenid"),
61 kSecAttrService, CFSTR("ctktest-service"),
62 kSecValueData, valueData,
63 kSecReturnAttributes, kCFBooleanTrue,
64 NULL);
65 // Setup token hook.
66 __block int phase = 0;
67 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
68 phase++;
69 eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
70
71 blocks->createOrUpdateObject = Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
72 phase++;
73 is(objectID, NULL);
74 eq_cf(CFDictionaryGetValue(at, kSecClass), kSecClassGenericPassword);
75 eq_cf(CFDictionaryGetValue(at, kSecAttrService), CFDictionaryGetValue(attrs, kSecAttrService));
76 eq_cf(CFDictionaryGetValue(at, kSecAttrTokenID), CFSTR("tokenid"));
77 eq_cf(CFDictionaryGetValue(at, kSecValueData), valueData);
78 CFDictionaryRemoveValue(at, kSecValueData);
79 return CFRetainSafe(oidData);
80 });
81
82 blocks->copyObjectAccessControl = Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
83 phase++;
84 SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
85 SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
86 SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
87 CFDataRef acData = SecAccessControlCopyData(ac);
88 CFRelease(ac);
89 return acData;
90 });
91
92 blocks->copyObjectData = Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
93 phase++;
94 return CFRetain(valueData);
95 });
96 });
97
98 CFTypeRef result = NULL;
99 ok_status(SecItemAdd(attrs, &result));
100 eq_cf(CFDictionaryGetValue(result, kSecAttrService), CFSTR("ctktest-service"));
101 eq_cf(CFDictionaryGetValue(result, kSecAttrTokenID), CFSTR("tokenid"));
102 is(CFDictionaryGetValue(result, kSecValueData), NULL);
103 CFReleaseNull(result);
104
105 is(phase, 3);
106
107 phase = 0;
108 CFDictionarySetValue(attrs, kSecReturnData, kCFBooleanTrue);
109 CFDictionarySetValue(attrs, kSecAttrService, CFSTR("ctktest-service1"));
110 ok_status(SecItemAdd(attrs, &result));
111 eq_cf(CFDictionaryGetValue(result, kSecAttrService), CFSTR("ctktest-service1"));
112 eq_cf(CFDictionaryGetValue(result, kSecAttrTokenID), CFSTR("tokenid"));
113 eq_cf(CFDictionaryGetValue(result, kSecValueData), valueData);
114 CFReleaseNull(result);
115
116 is(phase, 4);
117
118 phase = 0;
119 CFDictionaryRemoveValue(attrs, kSecReturnAttributes);
120 CFDictionarySetValue(attrs, kSecAttrAccount, CFSTR("2nd"));
121 ok_status(SecItemAdd(attrs, &result));
122 eq_cf(result, valueData);
123 CFReleaseNull(result);
124 is(phase, 4);
125
126 CFRelease(attrs);
127 CFRelease(valueData);
128 CFRelease(oidData);
129 }
130 static const int kItemAddTestCount = 31;
131
132 static void test_item_query() {
133 static const UInt8 oid[] = { 0x05, 0x06, 0x07, 0x08 };
134 CFDataRef oidData = CFDataCreate(NULL, oid, sizeof(oid));
135 static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
136 CFDataRef valueData = CFDataCreate(NULL, data, sizeof(data));
137 CFDataRef valueData2 = CFDataCreate(NULL, data, sizeof(data) - 1);
138
139 __block int phase = 0;
140 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
141 phase++;
142 eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
143
144 blocks->copyObjectData = _Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
145 phase++;
146 return CFRetain(valueData);
147 });
148 });
149
150 // Add non-token item with the same service, to test queries returning mixed results.
151 CFMutableDictionaryRef attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
152 kSecClass, kSecClassGenericPassword,
153 kSecAttrService, CFSTR("ctktest-service"),
154 kSecValueData, valueData2,
155 NULL);
156 ok_status(SecItemAdd(attrs, NULL));
157 CFRelease(attrs);
158
159 // Query with service.
160 CFMutableDictionaryRef query;
161 query = CFDictionaryCreateMutableForCFTypesWith(NULL,
162 kSecClass, kSecClassGenericPassword,
163 kSecAttrService, CFSTR("ctktest-service"),
164 kSecReturnAttributes, kCFBooleanTrue,
165 kSecReturnData, kCFBooleanTrue,
166 NULL);
167
168 phase = 0;
169 CFTypeRef result = NULL;
170 ok_status(SecItemCopyMatching(query, &result));
171 is(phase, 2);
172 is(CFGetTypeID(result), CFDictionaryGetTypeID());
173 eq_cf(CFDictionaryGetValue(result, kSecValueData), valueData);
174 is(CFGetTypeID(CFDictionaryGetValue(result, kSecAttrAccessControl)), SecAccessControlGetTypeID());
175 eq_cf(CFDictionaryGetValue(result, kSecAttrService), CFSTR("ctktest-service"));
176 CFReleaseSafe(result);
177
178 phase = 0;
179 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
180 ok_status(SecItemCopyMatching(query, &result));
181 is(phase, 2);
182 is(CFGetTypeID(result), CFArrayGetTypeID());
183 is(CFArrayGetCount(result), 2);
184 CFReleaseSafe(result);
185
186 phase = 0;
187 CFDictionaryRemoveValue(query, kSecMatchLimit);
188 CFDictionaryRemoveValue(query, kSecReturnData);
189 ok_status(SecItemCopyMatching(query, &result));
190 is(phase, 0);
191 is(CFGetTypeID(result), CFDictionaryGetTypeID());
192 is(CFDictionaryGetValue(result, kSecValueData), NULL);
193 CFReleaseSafe(result);
194
195 phase = 0;
196 CFDictionaryRemoveValue(query, kSecReturnAttributes);
197 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
198 CFDictionarySetValue(query, kSecAttrTokenID, CFSTR("tokenid"));
199 ok_status(SecItemCopyMatching(query, &result));
200 is(phase, 2);
201 eq_cf(result, valueData);
202 CFReleaseSafe(result);
203
204 CFRelease(query);
205 CFRelease(valueData);
206 CFRelease(valueData2);
207 CFRelease(oidData);
208 }
209 static const int kItemQueryTestCount = 21;
210
211 static void test_item_update() {
212 static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
213 CFDataRef valueData2 = CFDataCreate(NULL, data, sizeof(data) - 1);
214 CFTypeRef result = NULL;
215
216 CFMutableDictionaryRef query, attrs;
217
218 // Setup token hook.
219 __block int phase = 0;
220 __block bool store_value = false;
221 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
222 phase++;
223 eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
224
225 blocks->createOrUpdateObject = Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
226 phase++;
227 eq_cf(CFDictionaryGetValue(at, kSecValueData), valueData2);
228 if (!store_value) {
229 CFDictionaryRemoveValue(at, kSecValueData);
230 }
231 return CFRetainSafe(objectID);
232 });
233
234 blocks->copyObjectAccessControl = Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
235 phase++;
236 SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
237 SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
238 SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
239 CFDataRef acData = SecAccessControlCopyData(ac);
240 CFRelease(ac);
241 return acData;
242 });
243
244 blocks->copyObjectData = Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
245 phase++;
246 return CFRetain(valueData2);
247 });
248 });
249
250 query = CFDictionaryCreateMutableForCFTypesWith(NULL,
251 kSecClass, kSecClassGenericPassword,
252 kSecAttrTokenID, CFSTR("tokenid"),
253 kSecAttrService, CFSTR("ctktest-service"),
254 NULL);
255
256 attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
257 kSecValueData, valueData2,
258 NULL);
259
260 ok_status(SecItemUpdate(query, attrs));
261 is(phase, 3);
262
263 phase = 0;
264 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
265 ok_status(SecItemCopyMatching(query, &result));
266 eq_cf(valueData2, result);
267 CFRelease(result);
268 is(phase, 2);
269
270 phase = 0;
271 store_value = true;
272 CFDictionaryRemoveValue(query, kSecReturnData);
273 ok_status(SecItemUpdate(query, attrs));
274 is(phase, 3);
275
276 phase = 0;
277 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
278 ok_status(SecItemCopyMatching(query, &result));
279 eq_cf(valueData2, result);
280 CFRelease(result);
281 is(phase, 0);
282
283 phase = 0;
284 CFDictionarySetValue(query, kSecAttrService, CFSTR("ctktest-service1"));
285 CFDictionaryRemoveValue(query, kSecReturnData);
286 ok_status(SecItemUpdate(query, attrs));
287 is(phase, 5);
288
289 phase = 0;
290 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
291 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
292 ok_status(SecItemCopyMatching(query, &result));
293 is(phase, 0);
294 is(CFGetTypeID(result), CFArrayGetTypeID());
295 is(CFArrayGetCount(result), 2);
296 eq_cf(CFArrayGetValueAtIndex(result, 0), valueData2);
297 eq_cf(CFArrayGetValueAtIndex(result, 1), valueData2);
298
299 CFRelease(query);
300 CFRelease(attrs);
301 CFRelease(valueData2);
302 }
303 static const int kItemUpdateTestCount = 26;
304
305 static void test_item_delete(void) {
306
307 CFMutableDictionaryRef query;
308 CFTypeRef result;
309
310 __block int phase = 0;
311 __block CFErrorRef deleteError = NULL;
312 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
313 phase++;
314 eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
315
316 blocks->copyObjectAccessControl = _Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
317 phase++;
318 SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
319 SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
320 SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
321 CFDataRef acData = SecAccessControlCopyData(ac);
322 CFRelease(ac);
323 return acData;
324 });
325
326 blocks->deleteObject = _Block_copy(^bool(CFDataRef objectID, CFErrorRef *error) {
327 phase++;
328 if (deleteError != NULL) {
329 CFAssignRetained(*error, deleteError);
330 deleteError = NULL;
331 return false;
332 }
333 return true;
334 });
335 });
336
337 query = CFDictionaryCreateMutableForCFTypesWith(NULL,
338 kSecClass, kSecClassGenericPassword,
339 kSecAttrTokenID, CFSTR("tokenid"),
340 kSecAttrService, CFSTR("ctktest-service"),
341 NULL);
342
343 phase = 0;
344 ok_status(SecItemDelete(query));
345 is(phase, 2);
346
347 phase = 0;
348 is_status(SecItemCopyMatching(query, &result), errSecItemNotFound);
349 is(phase, 0);
350
351 phase = 0;
352 CFDictionarySetValue(query, kSecAttrService, CFSTR("ctktest-service1"));
353 ok_status(SecItemCopyMatching(query, &result));
354 is(phase, 0);
355
356 phase = 0;
357 #if USE_KEYSTORE
358 LASetErrorCodeBlock(^{ return (CFErrorRef)NULL; });
359 deleteError = CFErrorCreate(NULL, CFSTR(kTKErrorDomain), kTKErrorCodeAuthenticationFailed, NULL);
360 ok_status(SecItemDelete(query), "delete multiple token items");
361 is(phase, 6, "connect + delete-auth-fail + copyAccess + connect + delete + delete-2nd");
362 #else
363 ok_status(SecItemDelete(query), "delete multiple token items");
364 is(phase, 3, "connect + delete + delete");
365 #endif
366
367 phase = 0;
368 is_status(SecItemCopyMatching(query, &result), errSecItemNotFound);
369 is(phase, 0);
370
371 is_status(SecItemDelete(query), errSecItemNotFound);
372
373 CFRelease(query);
374 CFReleaseSafe(deleteError);
375 }
376 #if USE_KEYSTORE
377 static const int kItemDeleteTestCount = 15;
378 #else
379 static const int kItemDeleteTestCount = 14;
380 #endif
381
382 static void test_key_generate(void) {
383
384 __block int phase = 0;
385 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
386 phase++;
387
388 blocks->createOrUpdateObject = _Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
389 phase++;
390 is(objectID, NULL);
391 CFDictionarySetValue(at, kSecClass, kSecClassKey);
392 SecKeyRef publicKey = NULL, privateKey = NULL;
393 CFMutableDictionaryRef params = CFDictionaryCreateMutableForCFTypesWith(NULL,
394 kSecAttrKeyType, kSecAttrKeyTypeEC,
395 kSecAttrKeySizeInBits, CFSTR("256"),
396 NULL);
397 ok_status(SecKeyGeneratePair(params, &publicKey, &privateKey));
398 CFDictionaryRef privKeyAttrs = SecKeyCopyAttributeDictionary(privateKey);
399 CFRelease(privateKey);
400 CFRelease(publicKey);
401 CFRelease(params);
402 CFDataRef oid = CFRetainSafe(CFDictionaryGetValue(privKeyAttrs, kSecValueData));
403 CFRelease(privKeyAttrs);
404 return oid;
405 });
406
407 blocks->copyObjectAccessControl = _Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
408 phase++;
409 SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
410 SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
411 SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
412 CFDataRef acData = SecAccessControlCopyData(ac);
413 CFRelease(ac);
414 return acData;
415 });
416
417 blocks->copyPublicKeyData = _Block_copy(^CFDataRef(CFDataRef objectID, CFErrorRef *error) {
418 phase++;
419 SecKeyRef privKey = SecKeyCreateECPrivateKey(NULL, CFDataGetBytePtr(objectID), CFDataGetLength(objectID), kSecKeyEncodingBytes);
420 CFDataRef publicData;
421 ok_status(SecKeyCopyPublicBytes(privKey, &publicData));
422 CFRelease(privKey);
423 return publicData;
424 });
425
426 blocks->copyObjectData = _Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
427 phase++;
428 return kCFNull;
429 });
430 });
431
432 CFDictionaryRef prk_params = CFDictionaryCreateForCFTypes(NULL,
433 kSecAttrIsPermanent, kCFBooleanTrue,
434 NULL);
435
436 CFMutableDictionaryRef params = CFDictionaryCreateMutableForCFTypesWith(NULL,
437 kSecAttrKeyType, kSecAttrKeyTypeEC,
438 kSecAttrKeySizeInBits, CFSTR("256"),
439 kSecAttrTokenID, CFSTR("tokenid"),
440 kSecPrivateKeyAttrs, prk_params,
441 NULL);
442 CFRelease(prk_params);
443
444 SecKeyRef publicKey = NULL, privateKey = NULL;
445 phase = 0;
446 ok_status(SecKeyGeneratePair(params, &publicKey, &privateKey));
447 is(phase, 5);
448
449 CFDictionaryRef query = CFDictionaryCreateForCFTypes(NULL,
450 kSecValueRef, privateKey,
451 kSecReturnAttributes, kCFBooleanTrue,
452 kSecReturnRef, kCFBooleanTrue,
453 kSecReturnData, kCFBooleanTrue,
454 NULL);
455 phase = 0;
456 CFDictionaryRef result = NULL, keyAttrs = NULL;
457 ok_status(SecItemCopyMatching(query, (CFTypeRef *)&result));
458 is(phase, 3);
459 is(CFDictionaryGetValue(result, kSecValueData), NULL);
460 eq_cf(CFDictionaryGetValue(result, kSecAttrTokenID), CFSTR("tokenid"));
461 keyAttrs = SecKeyCopyAttributeDictionary((SecKeyRef)CFDictionaryGetValue(result, kSecValueRef));
462 eq_cf(CFDictionaryGetValue(keyAttrs, kSecAttrApplicationLabel), CFDictionaryGetValue(result, kSecAttrApplicationLabel));
463 CFAssignRetained(keyAttrs, SecKeyCopyAttributeDictionary(publicKey));
464 eq_cf(CFDictionaryGetValue(keyAttrs, kSecAttrApplicationLabel), CFDictionaryGetValue(result, kSecAttrApplicationLabel));
465
466 CFRelease(result);
467 CFRelease(keyAttrs);
468 CFRelease(publicKey);
469 CFRelease(privateKey);
470
471 CFRelease(query);
472 CFRelease(params);
473 }
474 static const int kKeyGenerateTestCount = 14;
475
476 static void test_key_sign(void) {
477
478 static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
479 CFDataRef valueData = CFDataCreate(NULL, data, sizeof(data));
480
481 __block int phase = 0;
482 __block CFErrorRef signError = NULL;
483 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
484 phase++;
485
486 blocks->copyPublicKeyData = _Block_copy(^CFDataRef(CFDataRef objectID, CFErrorRef *error) {
487 phase++;
488 SecKeyRef privKey = SecKeyCreateECPrivateKey(NULL, CFDataGetBytePtr(objectID), CFDataGetLength(objectID), kSecKeyEncodingBytes);
489 CFDataRef publicData;
490 ok_status(SecKeyCopyPublicBytes(privKey, &publicData));
491 CFRelease(privKey);
492 return publicData;
493 });
494
495 blocks->copyObjectAccessControl = _Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
496 phase++;
497 SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
498 SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
499 SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
500 CFDataRef acData = SecAccessControlCopyData(ac);
501 CFRelease(ac);
502 return acData;
503 });
504
505 blocks->copySignature = _Block_copy(^CFDataRef(CFDataRef objectID, CFIndex padding, CFDataRef plainText, CFErrorRef *error) {
506 phase++;
507 if (signError != NULL) {
508 CFAssignRetained(*error, signError);
509 signError = NULL;
510 return NULL;
511 }
512 return CFRetainSafe(valueData);
513 });
514 });
515
516 CFDictionaryRef query = CFDictionaryCreateForCFTypes(NULL,
517 kSecClass, kSecClassKey,
518 kSecReturnRef, kCFBooleanTrue,
519 NULL);
520 phase = 0;
521 SecKeyRef privateKey = NULL;
522 ok_status(SecItemCopyMatching(query, (CFTypeRef *)&privateKey));
523 is(phase, 1);
524
525 phase = 0;
526 CFMutableDataRef sig = CFDataCreateMutable(NULL, 0);
527 CFDataSetLength(sig, 256);
528 size_t sigLen = CFDataGetLength(sig);
529 ok_status(SecKeyRawSign(privateKey, kSecPaddingNone, data, sizeof(data), CFDataGetMutableBytePtr(sig), &sigLen));
530 is(phase, 1);
531 CFDataSetLength(sig, sigLen);
532 is(CFDataGetLength(sig), CFDataGetLength(valueData));
533 eq_cf(valueData, sig);
534
535 #if USE_KEYSTORE
536 phase = 0;
537 CFDataSetLength(sig, 256);
538 sigLen = CFDataGetLength(sig);
539 LASetErrorCodeBlock(^ { return (CFErrorRef)NULL; });
540 signError = CFErrorCreate(NULL, CFSTR(kTKErrorDomain), kTKErrorCodeAuthenticationFailed, NULL);
541 ok_status(SecKeyRawSign(privateKey, kSecPaddingNone, data, sizeof(data), CFDataGetMutableBytePtr(sig), &sigLen));
542 is(phase, 4);
543 is(signError, NULL);
544 CFDataSetLength(sig, sigLen);
545 is(CFDataGetLength(sig), CFDataGetLength(valueData));
546 eq_cf(valueData, sig);
547 #endif
548
549 CFReleaseSafe(signError);
550 CFRelease(sig);
551 CFRelease(privateKey);
552 CFRelease(query);
553 }
554 #if USE_KEYSTORE
555 static const int kKeySignTestCount = 11;
556 #else
557 static const int kKeySignTestCount = 5;
558 #endif
559
560 static void test_key_generate_with_params(void) {
561
562 const UInt8 data[] = "foo";
563 CFDataRef cred_ref = CFDataCreate(NULL, data, 4);
564 __block int phase = 0;
565 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
566 phase++;
567 eq_cf(CFDictionaryGetValue(attributes, kSecUseOperationPrompt), CFSTR("prompt"));
568 is(CFDictionaryGetValue(attributes, kSecUseAuthenticationUI), NULL);
569 eq_cf(CFDictionaryGetValue(attributes, kSecUseCredentialReference), cred_ref);
570
571 blocks->createOrUpdateObject = _Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
572 phase++;
573 SecCFCreateError(-4 /* kTKErrorCodeCanceledByUser */, CFSTR(kTKErrorDomain), CFSTR(""), NULL, error);
574 return NULL;
575 });
576 });
577
578 CFDictionaryRef prk_params = CFDictionaryCreateForCFTypes(NULL,
579 kSecAttrIsPermanent, kCFBooleanTrue,
580 NULL);
581
582 CFMutableDictionaryRef params = CFDictionaryCreateMutableForCFTypesWith(NULL,
583 kSecAttrKeyType, kSecAttrKeyTypeEC,
584 kSecAttrKeySizeInBits, CFSTR("256"),
585 kSecAttrTokenID, CFSTR("tokenid"),
586 kSecPrivateKeyAttrs, prk_params,
587 kSecUseOperationPrompt, CFSTR("prompt"),
588 kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow,
589 kSecUseCredentialReference, cred_ref,
590 NULL);
591 CFRelease(prk_params);
592
593 SecKeyRef publicKey = NULL, privateKey = NULL;
594 phase = 0;
595 is_status(SecKeyGeneratePair(params, &publicKey, &privateKey), errSecUserCanceled);
596 is(phase, 2);
597
598 CFReleaseSafe(publicKey);
599 CFReleaseSafe(privateKey);
600 CFRelease(params);
601 CFRelease(cred_ref);
602 }
603 static const int kKeyGenerateWithParamsTestCount = 5;
604
605 static void test_error_codes(void) {
606
607 CFMutableDictionaryRef attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
608 kSecClass, kSecClassGenericPassword,
609 kSecAttrTokenID, CFSTR("tokenid"),
610 NULL);
611 // Setup token hook.
612 __block OSStatus ctk_error = 0;
613 TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
614 blocks->createOrUpdateObject = _Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
615 SecCFCreateError(ctk_error, CFSTR(kTKErrorDomain), CFSTR(""), NULL, error);
616 return NULL;
617 });
618 });
619
620 ctk_error = kTKErrorCodeBadParameter;
621 is_status(SecItemAdd(attrs, NULL), errSecParam);
622
623 ctk_error = -1 /* kTKErrorCodeNotImplemented */;
624 is_status(SecItemAdd(attrs, NULL), errSecUnimplemented);
625
626 ctk_error = -4 /* kTKErrorCodeCanceledByUser */;
627 is_status(SecItemAdd(attrs, NULL), errSecUserCanceled);
628
629 CFRelease(attrs);
630 }
631 static const int kErrorCodesCount = 3;
632
633 static void tests(void) {
634 /* custom keychain dir */
635 secd_test_setup_temp_keychain("secd_33_keychain_ctk", NULL);
636
637 test_item_add();
638 test_item_query();
639 test_item_update();
640 test_item_delete();
641 test_key_generate();
642 test_key_sign();
643 test_key_generate_with_params();
644 test_error_codes();
645 }
646
647 int secd_33_keychain_ctk(int argc, char *const *argv) {
648 plan_tests(kItemAddTestCount +
649 kItemQueryTestCount +
650 kItemUpdateTestCount +
651 kItemDeleteTestCount +
652 kKeyGenerateTestCount +
653 kKeySignTestCount +
654 kKeyGenerateWithParamsTestCount +
655 kErrorCodesCount +
656 kSecdTestSetupTestCount);
657 tests();
658
659 return 0;
660 }