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>
43 #include <coreauthd_spi.h>
45 #include "secd_regressions.h"
47 #include "SecdTestKeychainUtilities.h"
48 #include "SecKeybagSupport.h"
50 extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock
)(void));
52 static void test_item_add(void) {
54 static const UInt8 data
[] = { 0x01, 0x02, 0x03, 0x04 };
55 CFDataRef valueData
= CFDataCreate(NULL
, data
, sizeof(data
));
56 static const UInt8 oid
[] = { 0x05, 0x06, 0x07, 0x08 };
57 CFDataRef oidData
= CFDataCreate(NULL
, oid
, sizeof(oid
));
59 CFMutableDictionaryRef attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
60 kSecClass
, kSecClassGenericPassword
,
61 kSecAttrTokenID
, CFSTR("tokenid"),
62 kSecAttrService
, CFSTR("ctktest-service"),
63 kSecValueData
, valueData
,
64 kSecReturnAttributes
, kCFBooleanTrue
,
67 __block
int phase
= 0;
68 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
70 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
72 blocks
->createOrUpdateObject
= Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
75 eq_cf(CFDictionaryGetValue(at
, kSecClass
), kSecClassGenericPassword
);
76 eq_cf(CFDictionaryGetValue(at
, kSecAttrService
), CFDictionaryGetValue(attrs
, kSecAttrService
));
77 eq_cf(CFDictionaryGetValue(at
, kSecAttrTokenID
), CFSTR("tokenid"));
78 eq_cf(CFDictionaryGetValue(at
, kSecValueData
), valueData
);
79 CFDictionaryRemoveValue(at
, kSecValueData
);
80 return CFRetainSafe(oidData
);
83 blocks
->copyObjectAccessControl
= Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
85 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
86 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
87 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
88 CFDataRef acData
= SecAccessControlCopyData(ac
);
93 blocks
->copyObjectData
= Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
95 return CFRetain(valueData
);
99 CFTypeRef result
= NULL
;
100 ok_status(SecItemAdd(attrs
, &result
));
101 eq_cf(CFDictionaryGetValue(result
, kSecAttrService
), CFSTR("ctktest-service"));
102 eq_cf(CFDictionaryGetValue(result
, kSecAttrTokenID
), CFSTR("tokenid"));
103 is(CFDictionaryGetValue(result
, kSecValueData
), NULL
);
104 CFReleaseNull(result
);
109 CFDictionarySetValue(attrs
, kSecReturnData
, kCFBooleanTrue
);
110 CFDictionarySetValue(attrs
, kSecAttrService
, CFSTR("ctktest-service1"));
111 ok_status(SecItemAdd(attrs
, &result
));
112 eq_cf(CFDictionaryGetValue(result
, kSecAttrService
), CFSTR("ctktest-service1"));
113 eq_cf(CFDictionaryGetValue(result
, kSecAttrTokenID
), CFSTR("tokenid"));
114 eq_cf(CFDictionaryGetValue(result
, kSecValueData
), valueData
);
115 CFReleaseNull(result
);
120 CFDictionaryRemoveValue(attrs
, kSecReturnAttributes
);
121 CFDictionarySetValue(attrs
, kSecAttrAccount
, CFSTR("2nd"));
122 ok_status(SecItemAdd(attrs
, &result
));
123 eq_cf(result
, valueData
);
124 CFReleaseNull(result
);
128 CFRelease(valueData
);
131 static const int kItemAddTestCount
= 31;
133 static void test_item_query() {
134 static const UInt8 oid
[] = { 0x05, 0x06, 0x07, 0x08 };
135 CFDataRef oidData
= CFDataCreate(NULL
, oid
, sizeof(oid
));
136 static const UInt8 data
[] = { 0x01, 0x02, 0x03, 0x04 };
137 CFDataRef valueData
= CFDataCreate(NULL
, data
, sizeof(data
));
138 CFDataRef valueData2
= CFDataCreate(NULL
, data
, sizeof(data
) - 1);
140 __block
int phase
= 0;
141 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
143 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
145 blocks
->copyObjectData
= _Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
147 return CFRetain(valueData
);
151 // Add non-token item with the same service, to test queries returning mixed results.
152 CFMutableDictionaryRef attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
153 kSecClass
, kSecClassGenericPassword
,
154 kSecAttrService
, CFSTR("ctktest-service"),
155 kSecValueData
, valueData2
,
157 ok_status(SecItemAdd(attrs
, NULL
));
160 // Query with service.
161 CFMutableDictionaryRef query
;
162 query
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
163 kSecClass
, kSecClassGenericPassword
,
164 kSecAttrService
, CFSTR("ctktest-service"),
165 kSecReturnAttributes
, kCFBooleanTrue
,
166 kSecReturnData
, kCFBooleanTrue
,
170 CFTypeRef result
= NULL
;
171 ok_status(SecItemCopyMatching(query
, &result
));
173 is(CFGetTypeID(result
), CFDictionaryGetTypeID());
174 eq_cf(CFDictionaryGetValue(result
, kSecValueData
), valueData
);
175 is(CFGetTypeID(CFDictionaryGetValue(result
, kSecAttrAccessControl
)), SecAccessControlGetTypeID());
176 eq_cf(CFDictionaryGetValue(result
, kSecAttrService
), CFSTR("ctktest-service"));
177 CFReleaseSafe(result
);
180 CFDictionarySetValue(query
, kSecMatchLimit
, kSecMatchLimitAll
);
181 ok_status(SecItemCopyMatching(query
, &result
));
183 is(CFGetTypeID(result
), CFArrayGetTypeID());
184 is(CFArrayGetCount(result
), 2);
185 CFReleaseSafe(result
);
188 CFDictionaryRemoveValue(query
, kSecMatchLimit
);
189 CFDictionaryRemoveValue(query
, kSecReturnData
);
190 ok_status(SecItemCopyMatching(query
, &result
));
192 is(CFGetTypeID(result
), CFDictionaryGetTypeID());
193 is(CFDictionaryGetValue(result
, kSecValueData
), NULL
);
194 CFReleaseSafe(result
);
197 CFDictionaryRemoveValue(query
, kSecReturnAttributes
);
198 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
199 CFDictionarySetValue(query
, kSecAttrTokenID
, CFSTR("tokenid"));
200 ok_status(SecItemCopyMatching(query
, &result
));
202 eq_cf(result
, valueData
);
203 CFReleaseSafe(result
);
206 CFRelease(valueData
);
207 CFRelease(valueData2
);
210 static const int kItemQueryTestCount
= 21;
212 static void test_item_update() {
213 static const UInt8 data
[] = { 0x01, 0x02, 0x03, 0x04 };
214 CFDataRef valueData2
= CFDataCreate(NULL
, data
, sizeof(data
) - 1);
215 CFTypeRef result
= NULL
;
217 CFMutableDictionaryRef query
, attrs
;
220 __block
int phase
= 0;
221 __block
bool store_value
= false;
222 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
224 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
226 blocks
->createOrUpdateObject
= Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
228 eq_cf(CFDictionaryGetValue(at
, kSecValueData
), valueData2
);
230 CFDictionaryRemoveValue(at
, kSecValueData
);
232 return CFRetainSafe(objectID
);
235 blocks
->copyObjectAccessControl
= Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
237 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
238 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
239 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
240 CFDataRef acData
= SecAccessControlCopyData(ac
);
245 blocks
->copyObjectData
= Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
247 return CFRetain(valueData2
);
251 query
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
252 kSecClass
, kSecClassGenericPassword
,
253 kSecAttrTokenID
, CFSTR("tokenid"),
254 kSecAttrService
, CFSTR("ctktest-service"),
257 attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
258 kSecValueData
, valueData2
,
261 ok_status(SecItemUpdate(query
, attrs
));
265 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
266 ok_status(SecItemCopyMatching(query
, &result
));
267 eq_cf(valueData2
, result
);
273 CFDictionaryRemoveValue(query
, kSecReturnData
);
274 ok_status(SecItemUpdate(query
, attrs
));
278 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
279 ok_status(SecItemCopyMatching(query
, &result
));
280 eq_cf(valueData2
, result
);
285 CFDictionarySetValue(query
, kSecAttrService
, CFSTR("ctktest-service1"));
286 CFDictionaryRemoveValue(query
, kSecReturnData
);
287 ok_status(SecItemUpdate(query
, attrs
));
291 CFDictionarySetValue(query
, kSecMatchLimit
, kSecMatchLimitAll
);
292 CFDictionarySetValue(query
, kSecReturnData
, kCFBooleanTrue
);
293 ok_status(SecItemCopyMatching(query
, &result
));
295 is(CFGetTypeID(result
), CFArrayGetTypeID());
296 is(CFArrayGetCount(result
), 2);
297 eq_cf(CFArrayGetValueAtIndex(result
, 0), valueData2
);
298 eq_cf(CFArrayGetValueAtIndex(result
, 1), valueData2
);
302 CFRelease(valueData2
);
304 static const int kItemUpdateTestCount
= 26;
306 static void test_item_delete(void) {
308 CFMutableDictionaryRef query
;
311 __block
int phase
= 0;
312 __block CFErrorRef deleteError
= NULL
;
313 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
315 eq_cf(CFDictionaryGetValue(attributes
, kSecAttrTokenID
), CFSTR("tokenid"));
317 blocks
->copyObjectAccessControl
= _Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
319 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
320 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
321 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
322 CFDataRef acData
= SecAccessControlCopyData(ac
);
327 blocks
->deleteObject
= _Block_copy(^bool(CFDataRef objectID
, CFErrorRef
*error
) {
329 if (deleteError
!= NULL
) {
330 CFAssignRetained(*error
, deleteError
);
338 query
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
339 kSecClass
, kSecClassGenericPassword
,
340 kSecAttrTokenID
, CFSTR("tokenid"),
341 kSecAttrService
, CFSTR("ctktest-service"),
345 ok_status(SecItemDelete(query
));
349 is_status(SecItemCopyMatching(query
, &result
), errSecItemNotFound
);
353 CFDictionarySetValue(query
, kSecAttrService
, CFSTR("ctktest-service1"));
354 ok_status(SecItemCopyMatching(query
, &result
));
358 #if LA_CONTEXT_IMPLEMENTED
359 LASetErrorCodeBlock(^{ return (CFErrorRef
)NULL
; });
360 deleteError
= CFErrorCreate(NULL
, CFSTR(kTKErrorDomain
), kTKErrorCodeAuthenticationFailed
, NULL
);
361 ok_status(SecItemDelete(query
), "delete multiple token items");
362 is(phase
, 6, "connect + delete-auth-fail + copyAccess + connect + delete + delete-2nd");
364 ok_status(SecItemDelete(query
), "delete multiple token items");
365 is(phase
, 3, "connect + delete + delete");
369 is_status(SecItemCopyMatching(query
, &result
), errSecItemNotFound
);
372 is_status(SecItemDelete(query
), errSecItemNotFound
);
375 CFReleaseSafe(deleteError
);
377 #if LA_CONTEXT_IMPLEMENTED
378 static const int kItemDeleteTestCount
= 15;
380 static const int kItemDeleteTestCount
= 14;
383 static void test_key_generate(void) {
385 __block
int phase
= 0;
386 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
389 blocks
->createOrUpdateObject
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
392 CFDictionarySetValue(at
, kSecClass
, kSecClassKey
);
393 SecKeyRef publicKey
= NULL
, privateKey
= NULL
;
394 CFMutableDictionaryRef params
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
395 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
396 kSecAttrKeySizeInBits
, CFSTR("256"),
398 ok_status(SecKeyGeneratePair(params
, &publicKey
, &privateKey
));
399 CFDictionaryRef privKeyAttrs
= SecKeyCopyAttributeDictionary(privateKey
);
400 CFRelease(privateKey
);
401 CFRelease(publicKey
);
403 CFDataRef oid
= CFRetainSafe(CFDictionaryGetValue(privKeyAttrs
, kSecValueData
));
404 CFRelease(privKeyAttrs
);
408 blocks
->copyObjectAccessControl
= _Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
410 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
411 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
412 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
413 CFDataRef acData
= SecAccessControlCopyData(ac
);
418 blocks
->copyPublicKeyData
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFErrorRef
*error
) {
420 SecKeyRef privKey
= SecKeyCreateECPrivateKey(NULL
, CFDataGetBytePtr(objectID
), CFDataGetLength(objectID
), kSecKeyEncodingBytes
);
421 CFDataRef publicData
;
422 ok_status(SecKeyCopyPublicBytes(privKey
, &publicData
));
427 blocks
->copyObjectData
= _Block_copy(^CFTypeRef(CFDataRef oid
, CFErrorRef
*error
) {
433 CFDictionaryRef prk_params
= CFDictionaryCreateForCFTypes(NULL
,
434 kSecAttrIsPermanent
, kCFBooleanTrue
,
437 CFMutableDictionaryRef params
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
438 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
439 kSecAttrKeySizeInBits
, CFSTR("256"),
440 kSecAttrTokenID
, CFSTR("tokenid"),
441 kSecPrivateKeyAttrs
, prk_params
,
443 CFRelease(prk_params
);
445 SecKeyRef publicKey
= NULL
, privateKey
= NULL
;
447 ok_status(SecKeyGeneratePair(params
, &publicKey
, &privateKey
));
450 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(NULL
,
451 kSecValueRef
, privateKey
,
452 kSecReturnAttributes
, kCFBooleanTrue
,
453 kSecReturnRef
, kCFBooleanTrue
,
454 kSecReturnData
, kCFBooleanTrue
,
457 CFDictionaryRef result
= NULL
, keyAttrs
= NULL
;
458 ok_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
));
460 is(CFDictionaryGetValue(result
, kSecValueData
), NULL
);
461 eq_cf(CFDictionaryGetValue(result
, kSecAttrTokenID
), CFSTR("tokenid"));
462 keyAttrs
= SecKeyCopyAttributeDictionary((SecKeyRef
)CFDictionaryGetValue(result
, kSecValueRef
));
463 eq_cf(CFDictionaryGetValue(keyAttrs
, kSecAttrApplicationLabel
), CFDictionaryGetValue(result
, kSecAttrApplicationLabel
));
464 CFAssignRetained(keyAttrs
, SecKeyCopyAttributeDictionary(publicKey
));
465 eq_cf(CFDictionaryGetValue(keyAttrs
, kSecAttrApplicationLabel
), CFDictionaryGetValue(result
, kSecAttrApplicationLabel
));
469 CFRelease(publicKey
);
470 CFRelease(privateKey
);
475 static const int kKeyGenerateTestCount
= 14;
477 static void test_key_sign(void) {
479 static const UInt8 data
[] = { 0x01, 0x02, 0x03, 0x04 };
480 CFDataRef valueData
= CFDataCreate(NULL
, data
, sizeof(data
));
482 __block
int phase
= 0;
483 __block CFErrorRef signError
= NULL
;
484 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
487 blocks
->copyPublicKeyData
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFErrorRef
*error
) {
489 SecKeyRef privKey
= SecKeyCreateECPrivateKey(NULL
, CFDataGetBytePtr(objectID
), CFDataGetLength(objectID
), kSecKeyEncodingBytes
);
490 CFDataRef publicData
;
491 ok_status(SecKeyCopyPublicBytes(privKey
, &publicData
));
496 blocks
->copyObjectAccessControl
= _Block_copy(^CFDataRef(CFDataRef oid
, CFErrorRef
*error
) {
498 SecAccessControlRef ac
= SecAccessControlCreate(NULL
, NULL
);
499 SecAccessControlSetProtection(ac
, kSecAttrAccessibleAlways
, NULL
);
500 SecAccessControlAddConstraintForOperation(ac
, kAKSKeyOpDefaultAcl
, kCFBooleanTrue
, NULL
);
501 CFDataRef acData
= SecAccessControlCopyData(ac
);
506 blocks
->copySignature
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFIndex padding
, CFDataRef plainText
, CFErrorRef
*error
) {
508 if (signError
!= NULL
) {
509 CFAssignRetained(*error
, signError
);
513 return CFRetainSafe(valueData
);
517 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(NULL
,
518 kSecClass
, kSecClassKey
,
519 kSecReturnRef
, kCFBooleanTrue
,
522 SecKeyRef privateKey
= NULL
;
523 ok_status(SecItemCopyMatching(query
, (CFTypeRef
*)&privateKey
));
527 CFMutableDataRef sig
= CFDataCreateMutable(NULL
, 0);
528 CFDataSetLength(sig
, 256);
529 size_t sigLen
= CFDataGetLength(sig
);
530 ok_status(SecKeyRawSign(privateKey
, kSecPaddingNone
, data
, sizeof(data
), CFDataGetMutableBytePtr(sig
), &sigLen
));
532 CFDataSetLength(sig
, sigLen
);
533 is(CFDataGetLength(sig
), CFDataGetLength(valueData
));
534 eq_cf(valueData
, sig
);
536 #if LA_CONTEXT_IMPLEMENTED
538 CFDataSetLength(sig
, 256);
539 sigLen
= CFDataGetLength(sig
);
540 LASetErrorCodeBlock(^ { return (CFErrorRef
)NULL
; });
541 signError
= CFErrorCreate(NULL
, CFSTR(kTKErrorDomain
), kTKErrorCodeAuthenticationFailed
, NULL
);
542 ok_status(SecKeyRawSign(privateKey
, kSecPaddingNone
, data
, sizeof(data
), CFDataGetMutableBytePtr(sig
), &sigLen
));
545 CFDataSetLength(sig
, sigLen
);
546 is(CFDataGetLength(sig
), CFDataGetLength(valueData
));
547 eq_cf(valueData
, sig
);
550 CFReleaseSafe(signError
);
552 CFRelease(privateKey
);
555 #if LA_CONTEXT_IMPLEMENTED
556 static const int kKeySignTestCount
= 11;
558 static const int kKeySignTestCount
= 6;
561 static void test_key_generate_with_params(void) {
563 const UInt8 data
[] = "foo";
564 CFDataRef cred_ref
= CFDataCreate(NULL
, data
, 4);
565 __block
int phase
= 0;
566 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
568 eq_cf(CFDictionaryGetValue(attributes
, kSecUseOperationPrompt
), CFSTR("prompt"));
569 is(CFDictionaryGetValue(attributes
, kSecUseAuthenticationUI
), NULL
);
570 eq_cf(CFDictionaryGetValue(attributes
, kSecUseCredentialReference
), cred_ref
);
572 blocks
->createOrUpdateObject
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
574 SecCFCreateError(-4 /* kTKErrorCodeCanceledByUser */, CFSTR(kTKErrorDomain
), CFSTR(""), NULL
, error
);
579 CFDictionaryRef prk_params
= CFDictionaryCreateForCFTypes(NULL
,
580 kSecAttrIsPermanent
, kCFBooleanTrue
,
583 CFMutableDictionaryRef params
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
584 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
585 kSecAttrKeySizeInBits
, CFSTR("256"),
586 kSecAttrTokenID
, CFSTR("tokenid"),
587 kSecPrivateKeyAttrs
, prk_params
,
588 kSecUseOperationPrompt
, CFSTR("prompt"),
589 kSecUseAuthenticationUI
, kSecUseAuthenticationUIAllow
,
590 kSecUseCredentialReference
, cred_ref
,
592 CFRelease(prk_params
);
594 SecKeyRef publicKey
= NULL
, privateKey
= NULL
;
596 diag("This will produce an internal assert - on purpose");
597 is_status(SecKeyGeneratePair(params
, &publicKey
, &privateKey
), errSecUserCanceled
);
600 CFReleaseSafe(publicKey
);
601 CFReleaseSafe(privateKey
);
605 static const int kKeyGenerateWithParamsTestCount
= 5;
607 static void test_error_codes(void) {
609 CFMutableDictionaryRef attrs
= CFDictionaryCreateMutableForCFTypesWith(NULL
,
610 kSecClass
, kSecClassGenericPassword
,
611 kSecAttrTokenID
, CFSTR("tokenid"),
614 __block OSStatus ctk_error
= 0;
615 TKTokenTestSetHook(^(CFDictionaryRef attributes
, TKTokenTestBlocks
*blocks
) {
616 blocks
->createOrUpdateObject
= _Block_copy(^CFDataRef(CFDataRef objectID
, CFMutableDictionaryRef at
, CFErrorRef
*error
) {
617 SecCFCreateError(ctk_error
, CFSTR(kTKErrorDomain
), CFSTR(""), NULL
, error
);
622 ctk_error
= kTKErrorCodeBadParameter
;
623 is_status(SecItemAdd(attrs
, NULL
), errSecParam
);
625 ctk_error
= -1 /* kTKErrorCodeNotImplemented */;
626 is_status(SecItemAdd(attrs
, NULL
), errSecUnimplemented
);
628 ctk_error
= -4 /* kTKErrorCodeCanceledByUser */;
629 is_status(SecItemAdd(attrs
, NULL
), errSecUserCanceled
);
633 static const int kErrorCodesCount
= 3;
635 static void tests(void) {
636 /* custom keychain dir */
637 secd_test_setup_temp_keychain("secd_33_keychain_ctk", NULL
);
645 test_key_generate_with_params();
649 int secd_33_keychain_ctk(int argc
, char *const *argv
) {
650 plan_tests(kItemAddTestCount
+
651 kItemQueryTestCount
+
652 kItemUpdateTestCount
+
653 kItemDeleteTestCount
+
654 kKeyGenerateTestCount
+
656 kKeyGenerateWithParamsTestCount
+
658 kSecdTestSetupTestCount
);