2 * Copyright (c) 2011,2013-2014 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@
29 * Copyright (c) 2007-2009,2013-2014 Apple Inc. All Rights Reserved.
32 #include <TargetConditionals.h>
33 #include <CoreFoundation/CoreFoundation.h>
34 #include <Security/Security.h>
35 #include <Security/SecKeyPriv.h>
37 #include <Security/SecItem.h>
38 #include <Security/SecKey.h>
41 #include <Security/SecCertificate.h>
42 #include <Security/SecCertificateInternal.h>
43 #include <Security/SecKey.h>
44 #include <Security/SecKeyPriv.h>
45 #include <Security/SecItem.h>
46 #include <Security/SecAsn1Types.h>
47 #include <Security/oidsalg.h>
48 #include <Security/SecureTransport.h>
49 #include <Security/SecRandom.h>
50 #include <CommonCrypto/CommonDigest.h>
51 #include <libDER/libDER.h>
57 #include "keychain_regressions.h"
58 #include "utilities/SecCFRelease.h"
62 static void testdigestandsignalg(SecKeyRef privKey
, SecKeyRef pubKey
, const SecAsn1AlgId
*algId
) {
63 uint8_t dataToDigest
[256];
64 size_t dataToDigestLen
= sizeof(dataToDigest
);
65 size_t sigLen
= SecKeyGetSize(privKey
, kSecKeySignatureSize
);
69 oid
.length
= algId
->algorithm
.Length
;
70 oid
.data
= algId
->algorithm
.Data
;
72 /* Get the oid in decimal for display purposes. */
73 CFStringRef oidStr
= SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault
, &oid
);
75 CFStringGetCString(oidStr
, oidBuf
, sizeof(oidBuf
), kCFStringEncodingUTF8
);
82 ok_status(status
= SecKeyDigestAndSign(privKey
, algId
, dataToDigest
, dataToDigestLen
,
84 "digest and sign %s with %ld bit RSA key", oidBuf
, sigLen
* 8);
86 skip("SecKeyDigestAndSign failed", 3, status
== errSecSuccess
);
88 /* Verify the signature we just made. */
89 ok_status(SecKeyDigestAndVerify(pubKey
, algId
, dataToDigest
, dataToDigestLen
,
90 sig
, sigLen
), "digest and verify");
91 /* Invalidate the signature. */
93 is_status(SecKeyDigestAndVerify(pubKey
, algId
, dataToDigest
, dataToDigestLen
,
94 sig
, sigLen
), errSSLCrypto
, "digest and verify bad sig");
96 dataToDigest
[0] ^= 0xff;
97 is_status(SecKeyDigestAndVerify(pubKey
, algId
, dataToDigest
, dataToDigestLen
,
98 sig
, sigLen
), errSSLCrypto
, "digest and verify bad digest");
102 static void testdigestandsign(SecKeyRef privKey
, SecKeyRef pubKey
) {
103 static const SecAsn1Oid
*oids
[] = {
104 &CSSMOID_ECDSA_WithSHA1
,
106 &CSSMOID_ECDSA_WithSHA224
,
107 &CSSMOID_ECDSA_WithSHA256
,
108 &CSSMOID_ECDSA_WithSHA384
,
109 &CSSMOID_ECDSA_WithSHA512
,
114 SecAsn1AlgId algId
= {};
115 for (ix
= 0; ix
< sizeof(oids
) / sizeof(*oids
); ++ix
) {
117 algId
.algorithm
= *oids
[ix
];
119 algId
.algorithm
.Length
= 0;
120 algId
.algorithm
.Data
= NULL
;
123 testdigestandsignalg(privKey
, pubKey
, &algId
);
129 #if !TARGET_OS_IPHONE
130 /* This is part of Security.framework on iOS */
133 // kSecKeyKeySizeInBits = 0, // already exists on osx
134 kSecKeySignatureSize
= 101,
135 kSecKeyEncryptedDataSize
= 102,
136 // More might belong here, but we aren't settled on how
137 // to take into account padding and/or digest types.
141 size_t SecKeyGetSize(SecKeyRef key
, int whichSize
)
143 /* SecKeyGetBlockSize return the signature size on OS X -- smh */
144 size_t result
= SecKeyGetBlockSize(key
);
146 result
= (result
- 2)/2 - 3;
148 /* in this test, this is always an ECDSA key */
150 case kSecKeyEncryptedDataSize
:
153 case kSecKeySignatureSize
:
154 result
= (result
>= 66 ? 9 : 8) + 2 * result
;
156 case kSecKeyKeySizeInBits
:
161 if (whichSize
== kSecKeyKeySizeInBits
)
170 static void testkeygen(size_t keySizeInBits
) {
171 SecKeyRef pubKey
= NULL
, privKey
= NULL
;
172 size_t keySizeInBytes
= (keySizeInBits
+ 7) / 8;
175 kzib
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &keySizeInBits
);
176 CFMutableDictionaryRef kgp
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
177 CFDictionaryAddValue(kgp
, kSecAttrKeyType
, kSecAttrKeyTypeEC
);
178 CFDictionaryAddValue(kgp
, kSecAttrKeySizeInBits
, kzib
);
181 ok_status(status
= SecKeyGeneratePair(kgp
, &pubKey
, &privKey
),
182 "Generate %ld bit (%ld byte) EC keypair", keySizeInBits
,
188 skip("keygen failed", 8, status
== errSecSuccess
);
189 ok(pubKey
, "pubkey returned");
190 ok(privKey
, "privKey returned");
191 is(SecKeyGetSize(pubKey
, kSecKeyKeySizeInBits
), (size_t) keySizeInBits
, "public key size is ok");
192 is(SecKeyGetSize(privKey
, kSecKeyKeySizeInBits
), (size_t) keySizeInBits
, "private key size is ok");
194 /* Sign something. */
195 uint8_t something
[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
196 uint8_t sig
[8+2*keySizeInBytes
];
197 size_t sigLen
= sizeof(sig
);
198 ok_status(SecKeyRawSign(privKey
, kSecPaddingNone
,
199 something
, sizeof(something
), sig
, &sigLen
), "sign something");
200 ok_status(SecKeyRawVerify(pubKey
, kSecPaddingNone
,
201 something
, sizeof(something
), sig
, sigLen
), "verify sig on something");
204 testdigestandsign(privKey
, pubKey
);
207 const void *privkeys
[] = {
210 const void *privvalues
[] = {
213 CFDictionaryRef privitem
= CFDictionaryCreate(NULL
, privkeys
, privvalues
,
214 sizeof(privkeys
) / sizeof(*privkeys
), NULL
, NULL
);
216 ok_status(SecItemAdd(privitem
, NULL
), "add private key");
218 ok_status(SecItemDelete(privitem
), "delete private key");
219 CFReleaseNull(privitem
);
221 const void *pubkeys
[] = {
224 const void *pubvalues
[] = {
227 CFDictionaryRef pubitem
= CFDictionaryCreate(NULL
, pubkeys
, pubvalues
,
228 sizeof(pubkeys
) / sizeof(*pubkeys
), NULL
, NULL
);
230 ok_status(SecItemAdd(pubitem
, NULL
), "add public key");
232 ok_status(SecItemDelete(pubitem
), "delete public key");
233 CFReleaseNull(pubitem
);
236 CFReleaseNull(pubKey
);
237 CFReleaseNull(privKey
);
242 static void testkeygen2(size_t keySizeInBits
) {
243 SecKeyRef pubKey
= NULL
, privKey
= NULL
;
244 size_t keySizeInBytes
= (keySizeInBits
+ 7) / 8;
247 CFUUIDRef ourUUID
= CFUUIDCreate(kCFAllocatorDefault
);
248 CFStringRef uuidString
= CFUUIDCreateString(kCFAllocatorDefault
, ourUUID
);
249 CFMutableStringRef publicName
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, uuidString
);
250 CFMutableStringRef privateName
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, uuidString
);
252 CFReleaseNull(ourUUID
);
253 CFReleaseNull(uuidString
);
255 CFStringAppend(publicName
, CFSTR("-Public-41"));
256 CFStringAppend(privateName
, CFSTR("-Private-41"));
258 CFMutableDictionaryRef pubd
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
259 CFMutableDictionaryRef privd
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
260 CFDictionaryAddValue(pubd
, kSecAttrLabel
, publicName
);
261 CFDictionaryAddValue(privd
, kSecAttrLabel
, privateName
);
263 kzib
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &keySizeInBits
);
264 CFMutableDictionaryRef kgp
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
265 CFDictionaryAddValue(kgp
, kSecAttrKeyType
, kSecAttrKeyTypeEC
);
266 CFDictionaryAddValue(kgp
, kSecAttrKeySizeInBits
, kzib
);
267 CFDictionaryAddValue(kgp
, kSecAttrIsPermanent
, kCFBooleanTrue
);
268 CFDictionaryAddValue(kgp
, kSecPublicKeyAttrs
, pubd
);
269 CFDictionaryAddValue(kgp
, kSecPrivateKeyAttrs
, privd
);
272 ok_status(status
= SecKeyGeneratePair(kgp
, &pubKey
, &privKey
),
273 "Generate %ld bit (%ld byte) persistent RSA keypair",
274 keySizeInBits
, keySizeInBytes
);
279 skip("keygen failed", 8, status
== errSecSuccess
);
280 ok(pubKey
, "pubkey returned");
281 ok(privKey
, "privKey returned");
282 is(SecKeyGetSize(pubKey
, kSecKeyKeySizeInBits
), (size_t) keySizeInBits
, "public key size is ok");
283 is(SecKeyGetSize(privKey
, kSecKeyKeySizeInBits
), (size_t) keySizeInBits
, "private key size is ok");
285 SecKeyRef pubKey2
, privKey2
;
286 CFDictionaryAddValue(pubd
, kSecClass
, kSecClassKey
);
287 CFDictionaryAddValue(pubd
, kSecReturnRef
, kCFBooleanTrue
);
288 CFDictionaryAddValue(privd
, kSecClass
, kSecClassKey
);
289 CFDictionaryAddValue(privd
, kSecReturnRef
, kCFBooleanTrue
);
290 CFDictionaryAddValue(privd
, kSecAttrCanSign
, kCFBooleanTrue
);
291 ok_status(SecItemCopyMatching(pubd
, (CFTypeRef
*)&pubKey2
),
292 "retrieve pub key by label");
293 ok(pubKey2
, "got valid object");
294 ok_status(SecItemCopyMatching(privd
, (CFTypeRef
*)&privKey2
),
295 "retrieve priv key by label and kSecAttrCanSign");
296 ok(privKey2
, "got valid object");
298 /* Sign something. */
299 uint8_t something
[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
300 size_t sigLen
= SecKeyGetSize(privKey2
, kSecKeySignatureSize
);
302 ok_status(SecKeyRawSign(privKey2
, kSecPaddingPKCS1
,
303 something
, sizeof(something
), sig
, &sigLen
), "sign something");
304 ok_status(SecKeyRawVerify(pubKey2
, kSecPaddingPKCS1
,
305 something
, sizeof(something
), sig
, sigLen
), "verify sig on something");
308 CFReleaseNull(pubKey2
);
309 CFReleaseNull(privKey2
);
312 /* delete from keychain - note: do it before releasing publicName and privateName
313 because pubd and privd have no retain/release callbacks */
314 ok_status(SecItemDelete(pubd
), "delete generated pub key");
315 ok_status(SecItemDelete(privd
), "delete generated priv key");
318 CFReleaseNull(pubKey
);
319 CFReleaseNull(privKey
);
321 CFReleaseNull(publicName
);
322 CFReleaseNull(privateName
);
330 const uint8_t EC_P256_KeyDER
[]={
331 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1,
332 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23,
333 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8,
334 0xeb, 0xf3, 0x88, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7,
335 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d,
336 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f,
337 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97,
338 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07,
339 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04,
342 // Open SSL Private Key
343 const uint8_t EC_P256_KeyDER_priv
[]={
344 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1,
345 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23,
346 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8,
347 0xeb, 0xf3, 0x88, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
348 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7,
349 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d,
350 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f,
351 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97,
352 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07,
353 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04,
356 // Open SSL Public Key
357 const uint8_t EC_P256_KeyDER_pub
[]={
358 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
359 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
360 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7, 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a,
361 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d, 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79,
362 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f, 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00,
363 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97, 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad,
364 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07, 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63,
365 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04, 0xc7};
368 const uint8_t EC_P256_SigDER
[]={
369 0x30, 0x45, 0x02, 0x20, 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53,
370 0xb3, 0x62, 0x6f, 0x32, 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9,
371 0x17, 0x67, 0x03, 0x73, 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3,
372 0x02, 0x21, 0x00, 0xd6, 0x23, 0xaf, 0xd9, 0x7d, 0x72, 0xba, 0x3b, 0x90,
373 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d, 0xbb, 0xb4, 0x0f, 0x67, 0x26,
374 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, 0xe0, 0x45, 0xd5, 0x6b};
376 const uint8_t EC_P256_SigRaw
[]= {
377 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53, 0xb3, 0x62, 0x6f, 0x32,
378 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, 0x17, 0x67, 0x03, 0x73,
379 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3, 0xd6, 0x23, 0xaf, 0xd9,
380 0x7d, 0x72, 0xba, 0x3b, 0x90, 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d,
381 0xbb, 0xb4, 0x0f, 0x67, 0x26, 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d,
382 0xe0, 0x45, 0xd5, 0x6b};
384 const uint8_t EC_SigDigest
[24] = "012345678912345678901234";
386 static void testsignformat(void)
388 SecKeyRef pkey
= NULL
;
389 SecKeyRef pubkey
= NULL
;
390 CFArrayRef KeyArrayPub
=NULL
;
391 CFArrayRef KeyArrayPriv
=NULL
;
392 uint8_t EC_signature_DER
[72];
393 uint8_t EC_signature_RAW
[64];
394 size_t EC_signature_DER_size
=sizeof(EC_signature_DER
);
395 size_t EC_signature_RAW_size
=sizeof(EC_signature_RAW
);
398 // Key import for iOS
400 ok((pkey
= SecKeyCreateECPrivateKey(kCFAllocatorDefault
,
401 EC_P256_KeyDER
, sizeof(EC_P256_KeyDER
),
402 kSecKeyEncodingPkcs1
)) != NULL
, "import privkey");
403 CFDataRef pubdata
= NULL
;
404 ok_status(SecKeyCopyPublicBytes(pkey
, &pubdata
), "pub key from priv key");
406 ok((pubkey
= SecKeyCreateECPublicKey(kCFAllocatorDefault
,
407 CFDataGetBytePtr(pubdata
), CFDataGetLength(pubdata
),
408 kSecKeyEncodingBytes
))!=NULL
,
410 CFReleaseNull(pubdata
);
413 // Key import for MacOS
416 SecExternalFormat sef
=kSecFormatOpenSSL
;
417 SecExternalItemType seit
;
420 DER_key
= CFDataCreate(kCFAllocatorDefault
, EC_P256_KeyDER_pub
, sizeof(EC_P256_KeyDER_pub
));
421 seit
=kSecItemTypePublicKey
;
422 ok_status(SecItemImport(DER_key
,NULL
,&sef
,&seit
,0,NULL
,NULL
,&KeyArrayPub
), "Import DER key");
423 ok((!(KeyArrayPub
==NULL
) && CFArrayGetCount(KeyArrayPub
)==1), "One key imported");
424 pubkey
=(SecKeyRef
)CFArrayGetValueAtIndex(KeyArrayPub
,0);
425 CFReleaseNull(DER_key
);
428 DER_key
= CFDataCreate(kCFAllocatorDefault
, EC_P256_KeyDER_priv
, sizeof(EC_P256_KeyDER_priv
));
429 seit
=kSecItemTypePrivateKey
;
430 ok_status(SecItemImport(DER_key
,NULL
,&sef
,&seit
,0,NULL
,NULL
,&KeyArrayPriv
), "Import DER key");
431 ok((!(KeyArrayPriv
==NULL
) && CFArrayGetCount(KeyArrayPriv
)==1), "One key imported");
432 pkey
=(SecKeyRef
)CFArrayGetValueAtIndex(KeyArrayPriv
,0);
433 CFReleaseNull(DER_key
);
437 // Verify fixed signature
438 ok_status(SecKeyRawVerify(pubkey
, kSecPaddingPKCS1
,
439 EC_SigDigest
, sizeof(EC_SigDigest
), EC_P256_SigDER
, sizeof(EC_P256_SigDER
)), "verify DER sig on something");
441 ok_status(SecKeyRawVerify(pubkey
, kSecPaddingSigRaw
,
442 EC_SigDigest
, sizeof(EC_SigDigest
), EC_P256_SigRaw
, sizeof(EC_P256_SigRaw
)), "verify RAW sig on something");
444 // Verify signature with mismatching format
445 ok_status(!SecKeyRawVerify(pubkey
, kSecPaddingSigRaw
,
446 EC_SigDigest
, sizeof(EC_SigDigest
), EC_P256_SigDER
, sizeof(EC_P256_SigDER
)), "verify DER sig with RAW option");
448 ok_status(!SecKeyRawVerify(pubkey
, kSecPaddingPKCS1
,
449 EC_SigDigest
, sizeof(EC_SigDigest
), EC_P256_SigRaw
, sizeof(EC_P256_SigRaw
)), "verify RAW sig with DER something");
451 // Sign something in each format
452 ok_status(SecKeyRawSign(pkey
, kSecPaddingPKCS1
,
453 EC_SigDigest
, sizeof(EC_SigDigest
), EC_signature_DER
, &EC_signature_DER_size
), "sign DER sig on something");
455 ok_status(SecKeyRawSign(pkey
, kSecPaddingSigRaw
,
456 EC_SigDigest
, sizeof(EC_SigDigest
), EC_signature_RAW
, &EC_signature_RAW_size
), "sign RAW sig on something");
458 // Verify expecting that verification does the right thing.
459 ok_status(SecKeyRawVerify(pubkey
, kSecPaddingPKCS1
,
460 EC_SigDigest
, sizeof(EC_SigDigest
), EC_signature_DER
, EC_signature_DER_size
), "verify DER sig on something");
462 ok_status(SecKeyRawVerify(pubkey
, kSecPaddingSigRaw
,
463 EC_SigDigest
, sizeof(EC_SigDigest
), EC_signature_RAW
, EC_signature_RAW_size
), "verify RAW sig on something");
465 CFReleaseNull(KeyArrayPub
);
466 CFReleaseNull(KeyArrayPriv
);
470 /* Test basic add delete update copy matching stuff. */
471 static void tests(void)
493 int kc_41_sececkey(int argc
, char *const *argv
)