2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
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>
40 #include <libaks_acl_cf_keys.h>
42 #include <ctkclient_test.h>
44 #include "secd_regressions.h"
46 #include "SecdTestKeychainUtilities.h"
47 #include "SecKeybagSupport.h"
49 extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock
)(void));
51 static void test_item_add(void) {
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
));
58 CFMutableDictionaryRef attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
59 kSecClass
, kSecClassGenericPassword
,
60 kSecAttrTokenID
, CFSTR("tokenid"),
61 kSecAttrService
, CFSTR("ctktest-service"),
62 kSecValueData
, valueData
,
63 kSecReturnAttributes
, kCFBooleanTrue
,
66 __block
int phase
= 0;
67 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
69 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
71 blocks
->createOrUpdateObject
= Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
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
);
82 blocks
->copyObjectAccessControl
= Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
84 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
85 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
86 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
87 CFDataRef acData
= SecAccessControlCopyData(ac
);
92 blocks
->copyObjectData
= Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
94 return CFRetain(valueData
);
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
);
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
);
119 CFDictionaryRemoveValue(attrs
, kSecReturnAttributes
);
120 CFDictionarySetValue(attrs
, kSecAttrAccount
, CFSTR("2nd"));
121 ok_status(SecItemAdd(attrs
, &result
));
122 eq_cf(result
, valueData
);
123 CFReleaseNull(result
);
127 CFRelease(valueData
);
130 static const int kItemAddTestCount
= 31;
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);
139 __block
int phase
= 0;
140 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
142 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
144 blocks
->copyObjectData
= _Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
146 return CFRetain(valueData
);
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
,
156 ok_status(SecItemAdd(attrs
, NULL
));
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
,
169 CFTypeRef result
= NULL
;
170 ok_status(SecItemCopyMatching(query
, &result
));
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
);
179 CFDictionarySetValue(query
, kSecMatchLimit
, kSecMatchLimitAll
);
180 ok_status(SecItemCopyMatching(query
, &result
));
182 is(CFGetTypeID(result
), CFArrayGetTypeID());
183 is(CFArrayGetCount(result
), 2);
184 CFReleaseSafe(result
);
187 CFDictionaryRemoveValue(query
, kSecMatchLimit
);
188 CFDictionaryRemoveValue(query
, kSecReturnData
);
189 ok_status(SecItemCopyMatching(query
, &result
));
191 is(CFGetTypeID(result
), CFDictionaryGetTypeID());
192 is(CFDictionaryGetValue(result
, kSecValueData
), NULL
);
193 CFReleaseSafe(result
);
196 CFDictionaryRemoveValue(query
, kSecReturnAttributes
);
197 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
198 CFDictionarySetValue(query
, kSecAttrTokenID
, CFSTR("tokenid"));
199 ok_status(SecItemCopyMatching(query
, &result
));
201 eq_cf(result
, valueData
);
202 CFReleaseSafe(result
);
205 CFRelease(valueData
);
206 CFRelease(valueData2
);
209 static const int kItemQueryTestCount
= 21;
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
;
216 CFMutableDictionaryRef query
, attrs
;
219 __block
int phase
= 0;
220 __block
bool store_value
= false;
221 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
223 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
225 blocks
->createOrUpdateObject
= Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
227 eq_cf(CFDictionaryGetValue(at
, kSecValueData
), valueData2
);
229 CFDictionaryRemoveValue(at
, kSecValueData
);
231 return CFRetainSafe(objectID
);
234 blocks
->copyObjectAccessControl
= Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
236 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
237 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
238 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
239 CFDataRef acData
= SecAccessControlCopyData(ac
);
244 blocks
->copyObjectData
= Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
246 return CFRetain(valueData2
);
250 query
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
251 kSecClass
, kSecClassGenericPassword
,
252 kSecAttrTokenID
, CFSTR("tokenid"),
253 kSecAttrService
, CFSTR("ctktest-service"),
256 attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
257 kSecValueData
, valueData2
,
260 ok_status(SecItemUpdate(query
, attrs
));
264 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
265 ok_status(SecItemCopyMatching(query
, &result
));
266 eq_cf(valueData2
, result
);
272 CFDictionaryRemoveValue(query
, kSecReturnData
);
273 ok_status(SecItemUpdate(query
, attrs
));
277 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
278 ok_status(SecItemCopyMatching(query
, &result
));
279 eq_cf(valueData2
, result
);
284 CFDictionarySetValue(query
, kSecAttrService
, CFSTR("ctktest-service1"));
285 CFDictionaryRemoveValue(query
, kSecReturnData
);
286 ok_status(SecItemUpdate(query
, attrs
));
290 CFDictionarySetValue(query
, kSecMatchLimit
, kSecMatchLimitAll
);
291 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
292 ok_status(SecItemCopyMatching(query
, &result
));
294 is(CFGetTypeID(result
), CFArrayGetTypeID());
295 is(CFArrayGetCount(result
), 2);
296 eq_cf(CFArrayGetValueAtIndex(result
, 0), valueData2
);
297 eq_cf(CFArrayGetValueAtIndex(result
, 1), valueData2
);
301 CFRelease(valueData2
);
303 static const int kItemUpdateTestCount
= 26;
305 static void test_item_delete(void) {
307 CFMutableDictionaryRef query
;
310 __block
int phase
= 0;
311 __block CFErrorRef deleteError
= NULL
;
312 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
314 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
316 blocks
->copyObjectAccessControl
= _Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
318 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
319 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
320 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
321 CFDataRef acData
= SecAccessControlCopyData(ac
);
326 blocks
->deleteObject
= _Block_copy(^bool(CFDataRef objectID
, CFErrorRef
*error
) {
328 if (deleteError
!= NULL
) {
329 CFAssignRetained(*error
, deleteError
);
337 query
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
338 kSecClass
, kSecClassGenericPassword
,
339 kSecAttrTokenID
, CFSTR("tokenid"),
340 kSecAttrService
, CFSTR("ctktest-service"),
344 ok_status(SecItemDelete(query
));
348 is_status(SecItemCopyMatching(query
, &result
), errSecItemNotFound
);
352 CFDictionarySetValue(query
, kSecAttrService
, CFSTR("ctktest-service1"));
353 ok_status(SecItemCopyMatching(query
, &result
));
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");
363 ok_status(SecItemDelete(query
), "delete multiple token items");
364 is(phase
, 3, "connect + delete + delete");
368 is_status(SecItemCopyMatching(query
, &result
), errSecItemNotFound
);
371 is_status(SecItemDelete(query
), errSecItemNotFound
);
374 CFReleaseSafe(deleteError
);
377 static const int kItemDeleteTestCount
= 15;
379 static const int kItemDeleteTestCount
= 14;
382 static void test_key_generate(void) {
384 __block
int phase
= 0;
385 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
388 blocks
->createOrUpdateObject
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
391 CFDictionarySetValue(at
, kSecClass
, kSecClassKey
);
392 SecKeyRef publicKey
= NULL
, privateKey
= NULL
;
393 CFMutableDictionaryRef params
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
394 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
395 kSecAttrKeySizeInBits
, CFSTR("256"),
397 ok_status(SecKeyGeneratePair(params
, &publicKey
, &privateKey
));
398 CFDictionaryRef privKeyAttrs
= SecKeyCopyAttributeDictionary(privateKey
);
399 CFRelease(privateKey
);
400 CFRelease(publicKey
);
402 CFDataRef oid
= CFRetainSafe(CFDictionaryGetValue(privKeyAttrs
, kSecValueData
));
403 CFRelease(privKeyAttrs
);
407 blocks
->copyObjectAccessControl
= _Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
409 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
410 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
411 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
412 CFDataRef acData
= SecAccessControlCopyData(ac
);
417 blocks
->copyPublicKeyData
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFErrorRef
*error
) {
419 SecKeyRef privKey
= SecKeyCreateECPrivateKey(NULL
, CFDataGetBytePtr(objectID
), CFDataGetLength(objectID
), kSecKeyEncodingBytes
);
420 CFDataRef publicData
;
421 ok_status(SecKeyCopyPublicBytes(privKey
, &publicData
));
426 blocks
->copyObjectData
= _Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
432 CFDictionaryRef prk_params
= CFDictionaryCreateForCFTypes(NULL
,
433 kSecAttrIsPermanent
, kCFBooleanTrue
,
436 CFMutableDictionaryRef params
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
437 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
438 kSecAttrKeySizeInBits
, CFSTR("256"),
439 kSecAttrTokenID
, CFSTR("tokenid"),
440 kSecPrivateKeyAttrs
, prk_params
,
442 CFRelease(prk_params
);
444 SecKeyRef publicKey
= NULL
, privateKey
= NULL
;
446 ok_status(SecKeyGeneratePair(params
, &publicKey
, &privateKey
));
449 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(NULL
,
450 kSecValueRef
, privateKey
,
451 kSecReturnAttributes
, kCFBooleanTrue
,
452 kSecReturnRef
, kCFBooleanTrue
,
453 kSecReturnData
, kCFBooleanTrue
,
456 CFDictionaryRef result
= NULL
, keyAttrs
= NULL
;
457 ok_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
));
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
));
468 CFRelease(publicKey
);
469 CFRelease(privateKey
);
474 static const int kKeyGenerateTestCount
= 14;
476 static void test_key_sign(void) {
478 static const UInt8 data
[] = { 0x01, 0x02, 0x03, 0x04 };
479 CFDataRef valueData
= CFDataCreate(NULL
, data
, sizeof(data
));
481 __block
int phase
= 0;
482 __block CFErrorRef signError
= NULL
;
483 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
486 blocks
->copyPublicKeyData
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFErrorRef
*error
) {
488 SecKeyRef privKey
= SecKeyCreateECPrivateKey(NULL
, CFDataGetBytePtr(objectID
), CFDataGetLength(objectID
), kSecKeyEncodingBytes
);
489 CFDataRef publicData
;
490 ok_status(SecKeyCopyPublicBytes(privKey
, &publicData
));
495 blocks
->copyObjectAccessControl
= _Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
497 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
498 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
499 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
500 CFDataRef acData
= SecAccessControlCopyData(ac
);
505 blocks
->copySignature
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFIndex padding
, CFDataRef plainText
, CFErrorRef
*error
) {
507 if (signError
!= NULL
) {
508 CFAssignRetained(*error
, signError
);
512 return CFRetainSafe(valueData
);
516 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(NULL
,
517 kSecClass
, kSecClassKey
,
518 kSecReturnRef
, kCFBooleanTrue
,
521 SecKeyRef privateKey
= NULL
;
522 ok_status(SecItemCopyMatching(query
, (CFTypeRef
*)&privateKey
));
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
));
531 CFDataSetLength(sig
, sigLen
);
532 is(CFDataGetLength(sig
), CFDataGetLength(valueData
));
533 eq_cf(valueData
, sig
);
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
));
544 CFDataSetLength(sig
, sigLen
);
545 is(CFDataGetLength(sig
), CFDataGetLength(valueData
));
546 eq_cf(valueData
, sig
);
549 CFReleaseSafe(signError
);
551 CFRelease(privateKey
);
555 static const int kKeySignTestCount
= 11;
557 static const int kKeySignTestCount
= 5;
560 static void test_key_generate_with_params(void) {
562 const UInt8 data
[] = "foo";
563 CFDataRef cred_ref
= CFDataCreate(NULL
, data
, 4);
564 __block
int phase
= 0;
565 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
567 eq_cf(CFDictionaryGetValue(attributes
, kSecUseOperationPrompt
), CFSTR("prompt"));
568 is(CFDictionaryGetValue(attributes
, kSecUseAuthenticationUI
), NULL
);
569 eq_cf(CFDictionaryGetValue(attributes
, kSecUseCredentialReference
), cred_ref
);
571 blocks
->createOrUpdateObject
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
573 SecCFCreateError(-4 /* kTKErrorCodeCanceledByUser */, CFSTR(kTKErrorDomain
), CFSTR(""), NULL
, error
);
578 CFDictionaryRef prk_params
= CFDictionaryCreateForCFTypes(NULL
,
579 kSecAttrIsPermanent
, kCFBooleanTrue
,
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
,
591 CFRelease(prk_params
);
593 SecKeyRef publicKey
= NULL
, privateKey
= NULL
;
595 is_status(SecKeyGeneratePair(params
, &publicKey
, &privateKey
), errSecUserCanceled
);
598 CFReleaseSafe(publicKey
);
599 CFReleaseSafe(privateKey
);
603 static const int kKeyGenerateWithParamsTestCount
= 5;
605 static void test_error_codes(void) {
607 CFMutableDictionaryRef attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
608 kSecClass
, kSecClassGenericPassword
,
609 kSecAttrTokenID
, CFSTR("tokenid"),
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
);
620 ctk_error
= kTKErrorCodeBadParameter
;
621 is_status(SecItemAdd(attrs
, NULL
), errSecParam
);
623 ctk_error
= -1 /* kTKErrorCodeNotImplemented */;
624 is_status(SecItemAdd(attrs
, NULL
), errSecUnimplemented
);
626 ctk_error
= -4 /* kTKErrorCodeCanceledByUser */;
627 is_status(SecItemAdd(attrs
, NULL
), errSecUserCanceled
);
631 static const int kErrorCodesCount
= 3;
633 static void tests(void) {
634 /* custom keychain dir */
635 secd_test_setup_temp_keychain("secd_33_keychain_ctk", NULL
);
643 test_key_generate_with_params();
647 int secd_33_keychain_ctk(int argc
, char *const *argv
) {
648 plan_tests(kItemAddTestCount
+
649 kItemQueryTestCount
+
650 kItemUpdateTestCount
+
651 kItemDeleteTestCount
+
652 kKeyGenerateTestCount
+
654 kKeyGenerateWithParamsTestCount
+
656 kSecdTestSetupTestCount
);