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