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.
34 * This is to fool os services to not provide the Keychain manager
35 * interface that doens't work since we don't have unified headers
36 * between iOS and OS X. rdar://23405418/
38 #define __KEYCHAINCORE__ 1
39 #import <Foundation/Foundation.h>
41 #include <TargetConditionals.h>
42 #include <CoreFoundation/CoreFoundation.h>
43 #include <Security/Security.h>
44 #include <Security/SecKeyPriv.h>
45 #include <Security/SecItemPriv.h>
47 #include <Security/SecItem.h>
48 #include <Security/SecKey.h>
51 #include <Security/SecCertificate.h>
52 #include <Security/SecCertificateInternal.h>
53 #include <Security/SecKey.h>
54 #include <Security/SecKeyPriv.h>
55 #include <Security/SecItem.h>
56 #include <Security/SecAsn1Types.h>
57 #include <Security/oidsalg.h>
58 #include <Security/SecureTransport.h>
59 #include <Security/SecRandom.h>
60 #include <CommonCrypto/CommonDigest.h>
61 #include <libDER/libDER.h>
67 #include "keychain_regressions.h"
68 #include "utilities/SecCFRelease.h"
69 #include "utilities/array_size.h"
73 static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) {
74 uint8_t dataToDigest[256];
75 size_t dataToDigestLen = sizeof(dataToDigest);
76 size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize);
80 oid.length = algId->algorithm.Length;
81 oid.data = algId->algorithm.Data;
83 /* Get the oid in decimal for display purposes. */
84 CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid);
86 CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8);
93 ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen,
95 "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8);
97 skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess);
99 /* Verify the signature we just made. */
100 ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
101 sig, sigLen), "digest and verify");
102 /* Invalidate the signature. */
104 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
105 sig, sigLen), errSSLCrypto, "digest and verify bad sig");
107 dataToDigest[0] ^= 0xff;
108 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
109 sig, sigLen), errSSLCrypto, "digest and verify bad digest");
113 static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) {
114 static const SecAsn1Oid *oids[] = {
115 &CSSMOID_ECDSA_WithSHA1,
117 &CSSMOID_ECDSA_WithSHA224,
118 &CSSMOID_ECDSA_WithSHA256,
119 &CSSMOID_ECDSA_WithSHA384,
120 &CSSMOID_ECDSA_WithSHA512,
125 SecAsn1AlgId algId = {};
126 for (ix = 0; ix < sizeof(oids) / sizeof(*oids); ++ix) {
128 algId.algorithm = *oids[ix];
130 algId.algorithm.Length = 0;
131 algId.algorithm.Data = NULL;
134 testdigestandsignalg(privKey, pubKey, &algId);
140 #if !TARGET_OS_IPHONE
141 /* This is part of Security.framework on iOS */
144 // kSecKeyKeySizeInBits = 0, // already exists on osx
145 kSecKeySignatureSize = 101,
146 kSecKeyEncryptedDataSize = 102,
147 // More might belong here, but we aren't settled on how
148 // to take into account padding and/or digest types.
152 size_t SecKeyGetSize(SecKeyRef key, int whichSize)
154 /* SecKeyGetBlockSize return the signature size on OS X -- smh */
155 size_t result = SecKeyGetBlockSize(key);
157 result = (result - 2)/2 - 3;
159 /* in this test, this is always an ECDSA key */
161 case kSecKeyEncryptedDataSize:
164 case kSecKeySignatureSize:
165 result = (result >= 66 ? 9 : 8) + 2 * result;
167 case kSecKeyKeySizeInBits:
172 if (whichSize == kSecKeyKeySizeInBits)
181 static void testkeygen(size_t keySizeInBits) {
182 SecKeyRef pubKey = NULL, privKey = NULL;
183 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
186 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits);
187 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
188 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
189 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
192 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
193 "Generate %ld bit (%ld byte) EC keypair", keySizeInBits,
199 skip("keygen failed", 8, status == errSecSuccess);
200 ok(pubKey, "pubkey returned");
201 ok(privKey, "privKey returned");
202 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
203 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
205 /* Sign something. */
206 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
207 uint8_t sig[8+2*keySizeInBytes];
208 size_t sigLen = sizeof(sig);
209 ok_status(SecKeyRawSign(privKey, kSecPaddingNone,
210 something, sizeof(something), sig, &sigLen), "sign something");
211 ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone,
212 something, sizeof(something), sig, sigLen), "verify sig on something");
215 testdigestandsign(privKey, pubKey);
218 const void *privkeys[] = {
221 const void *privvalues[] = {
224 CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
225 sizeof(privkeys) / sizeof(*privkeys), NULL, NULL);
227 ok_status(SecItemAdd(privitem, NULL), "add private key");
229 ok_status(SecItemDelete(privitem), "delete private key");
230 CFReleaseNull(privitem);
232 const void *pubkeys[] = {
235 const void *pubvalues[] = {
238 CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues,
239 sizeof(pubkeys) / sizeof(*pubkeys), NULL, NULL);
241 ok_status(SecItemAdd(pubitem, NULL), "add public key");
243 ok_status(SecItemDelete(pubitem), "delete public key");
244 CFReleaseNull(pubitem);
247 CFReleaseNull(pubKey);
248 CFReleaseNull(privKey);
253 static void testkeygen2(size_t keySizeInBits) {
254 SecKeyRef pubKey = NULL, privKey = NULL;
255 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
258 CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
259 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
260 CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
261 CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
263 CFReleaseNull(ourUUID);
264 CFReleaseNull(uuidString);
266 CFStringAppend(publicName, CFSTR("-Public-41"));
267 CFStringAppend(privateName, CFSTR("-Private-41"));
269 CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
270 CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
271 CFDictionaryAddValue(pubd, kSecAttrLabel, publicName);
272 CFDictionaryAddValue(privd, kSecAttrLabel, privateName);
274 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits);
275 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
276 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
277 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
278 CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue);
279 CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd);
280 CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd);
283 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
284 "Generate %ld bit (%ld byte) persistent RSA keypair",
285 keySizeInBits, keySizeInBytes);
290 skip("keygen failed", 8, status == errSecSuccess);
291 ok(pubKey, "pubkey returned");
292 ok(privKey, "privKey returned");
293 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
294 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
296 SecKeyRef pubKey2, privKey2;
297 CFDictionaryAddValue(pubd, kSecClass, kSecClassKey);
298 CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue);
299 CFDictionaryAddValue(privd, kSecClass, kSecClassKey);
300 CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue);
301 CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue);
302 ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2),
303 "retrieve pub key by label");
304 ok(pubKey2, "got valid object");
305 ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2),
306 "retrieve priv key by label and kSecAttrCanSign");
307 ok(privKey2, "got valid object");
309 /* Sign something. */
310 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
311 size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize);
313 ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1,
314 something, sizeof(something), sig, &sigLen), "sign something");
315 ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1,
316 something, sizeof(something), sig, sigLen), "verify sig on something");
319 CFReleaseNull(pubKey2);
320 CFReleaseNull(privKey2);
323 /* delete from keychain - note: do it before releasing publicName and privateName
324 because pubd and privd have no retain/release callbacks */
325 ok_status(SecItemDelete(pubd), "delete generated pub key");
326 ok_status(SecItemDelete(privd), "delete generated priv key");
329 CFReleaseNull(pubKey);
330 CFReleaseNull(privKey);
332 CFReleaseNull(publicName);
333 CFReleaseNull(privateName);
341 const uint8_t EC_P256_KeyDER[]={
342 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1,
343 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23,
344 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8,
345 0xeb, 0xf3, 0x88, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7,
346 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d,
347 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f,
348 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97,
349 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07,
350 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04,
353 // Open SSL Private Key
354 const uint8_t EC_P256_KeyDER_priv[]={
355 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1,
356 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23,
357 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8,
358 0xeb, 0xf3, 0x88, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
359 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7,
360 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d,
361 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f,
362 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97,
363 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07,
364 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04,
367 // Open SSL Public Key
368 const uint8_t EC_P256_KeyDER_pub[]={
369 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
370 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
371 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7, 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a,
372 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d, 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79,
373 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f, 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00,
374 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97, 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad,
375 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07, 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63,
376 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04, 0xc7};
379 const uint8_t EC_P256_SigDER[]={
380 0x30, 0x45, 0x02, 0x20, 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53,
381 0xb3, 0x62, 0x6f, 0x32, 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9,
382 0x17, 0x67, 0x03, 0x73, 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3,
383 0x02, 0x21, 0x00, 0xd6, 0x23, 0xaf, 0xd9, 0x7d, 0x72, 0xba, 0x3b, 0x90,
384 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d, 0xbb, 0xb4, 0x0f, 0x67, 0x26,
385 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, 0xe0, 0x45, 0xd5, 0x6b};
387 const uint8_t EC_P256_SigRaw[]= {
388 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53, 0xb3, 0x62, 0x6f, 0x32,
389 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, 0x17, 0x67, 0x03, 0x73,
390 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3, 0xd6, 0x23, 0xaf, 0xd9,
391 0x7d, 0x72, 0xba, 0x3b, 0x90, 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d,
392 0xbb, 0xb4, 0x0f, 0x67, 0x26, 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d,
393 0xe0, 0x45, 0xd5, 0x6b};
395 const uint8_t EC_SigDigest[24] = "012345678912345678901234";
397 /* r is 72 bytes longer than it should be */
398 const uint8_t EC_P256_SigDER_LargeInt[]={
399 0x30, 0x81, 0x8D, 0x02, 0x68,
400 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53,
405 0xb3, 0x62, 0x6f, 0x32, 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, 0x17, 0x67, 0x03, 0x73,
406 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3,
408 0x00, 0xd6, 0x23, 0xaf, 0xd9, 0x7d, 0x72, 0xba, 0x3b, 0x90, 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1,
409 0x0d, 0xbb, 0xb4, 0x0f, 0x67, 0x26, 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, 0xe0, 0x45, 0xd5,
412 static void testsignformat(void)
414 SecKeyRef pkey = NULL;
415 SecKeyRef pubkey = NULL;
416 CFArrayRef KeyArrayPub=NULL;
417 CFArrayRef KeyArrayPriv=NULL;
418 uint8_t EC_signature_DER[72];
419 uint8_t EC_signature_RAW[64];
420 size_t EC_signature_DER_size=sizeof(EC_signature_DER);
421 size_t EC_signature_RAW_size=sizeof(EC_signature_RAW);
424 // Key import for iOS
426 ok((pkey = SecKeyCreateECPrivateKey(kCFAllocatorDefault,
427 EC_P256_KeyDER, sizeof(EC_P256_KeyDER),
428 kSecKeyEncodingPkcs1)) != NULL, "import privkey");
429 CFDataRef pubdata = NULL;
430 ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key");
432 ok((pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault,
433 CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata),
434 kSecKeyEncodingBytes))!=NULL,
436 CFReleaseNull(pubdata);
439 // Key import for MacOS
442 SecExternalFormat sef=kSecFormatOpenSSL;
443 SecExternalItemType seit;
446 DER_key = CFDataCreate(kCFAllocatorDefault, EC_P256_KeyDER_pub, sizeof(EC_P256_KeyDER_pub));
447 seit=kSecItemTypePublicKey;
448 ok_status(SecItemImport(DER_key,NULL,&sef,&seit,0,NULL,NULL,&KeyArrayPub), "Import DER key");
449 ok((!(KeyArrayPub==NULL) && CFArrayGetCount(KeyArrayPub)==1), "One key imported");
450 pubkey=(SecKeyRef)CFArrayGetValueAtIndex(KeyArrayPub,0);
451 CFReleaseNull(DER_key);
454 DER_key = CFDataCreate(kCFAllocatorDefault, EC_P256_KeyDER_priv, sizeof(EC_P256_KeyDER_priv));
455 seit=kSecItemTypePrivateKey;
456 ok_status(SecItemImport(DER_key,NULL,&sef,&seit,0,NULL,NULL,&KeyArrayPriv), "Import DER key");
457 ok((!(KeyArrayPriv==NULL) && CFArrayGetCount(KeyArrayPriv)==1), "One key imported");
458 pkey=(SecKeyRef)CFArrayGetValueAtIndex(KeyArrayPriv,0);
459 CFReleaseNull(DER_key);
463 // Verify fixed signature
464 ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1,
465 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER, sizeof(EC_P256_SigDER)), "verify DER sig on something");
467 ok_status(SecKeyRawVerify(pubkey, kSecPaddingSigRaw,
468 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig on something");
470 // Verify signature with mismatching format
471 ok_status(!SecKeyRawVerify(pubkey, kSecPaddingSigRaw,
472 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER, sizeof(EC_P256_SigDER)), "verify DER sig with RAW option");
474 ok_status(!SecKeyRawVerify(pubkey, kSecPaddingPKCS1,
475 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig with DER something");
477 // Sign something in each format
478 ok_status(SecKeyRawSign(pkey, kSecPaddingPKCS1,
479 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_DER, &EC_signature_DER_size), "sign DER sig on something");
481 ok_status(SecKeyRawSign(pkey, kSecPaddingSigRaw,
482 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, &EC_signature_RAW_size), "sign RAW sig on something");
484 // Verify expecting that verification does the right thing.
485 ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1,
486 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_DER, EC_signature_DER_size), "verify DER sig on something");
488 ok_status(SecKeyRawVerify(pubkey, kSecPaddingSigRaw,
489 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, EC_signature_RAW_size), "verify RAW sig on something");
491 // Verify signature with one integer larger than it should be
492 ok_status(!SecKeyRawVerify(pubkey, kSecPaddingPKCS1,
493 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER_LargeInt, sizeof(EC_P256_SigDER_LargeInt)),
494 "verify DER sig with large integer");
496 CFReleaseNull(KeyArrayPub);
497 CFReleaseNull(KeyArrayPriv);
500 #if !TARGET_OS_IPHONE
501 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
503 if (left == NULL || right == NULL)
504 return left == right;
506 return CFEqual(left, right);
510 static void testkeyexchange(unsigned long keySizeInBits)
512 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
515 SecKeyRef pubKey1 = NULL, privKey1 = NULL;
516 NSDictionary *kgp1 = @{
517 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
518 (id)kSecAttrKeySizeInBits: @(keySizeInBits),
519 (id)kSecAttrIsPermanent: @NO,
520 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
521 (id)kSecAttrNoLegacy: @YES,
523 ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp1, &pubKey1, &privKey1),
524 "Generate %ld bit (%ld byte) EC keypair (status = %d)",
525 keySizeInBits, keySizeInBytes, (int)status);
527 SecKeyRef pubKey2 = NULL, privKey2 = NULL;
528 NSDictionary *kgp2 = @{
529 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
530 (id)kSecAttrKeySizeInBits: @(keySizeInBits),
531 (id)kSecAttrIsPermanent: @NO,
532 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
533 (id)kSecAttrNoLegacy: @NO,
535 ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp2, &pubKey2, &privKey2),
536 "Generate %ld bit (%ld byte) EC keypair (status = %d)",
537 keySizeInBits, keySizeInBytes, (int)status);
539 const SecKeyAlgorithm algos[] = {
540 kSecKeyAlgorithmECDHKeyExchangeStandard,
541 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1,
542 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224,
543 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256,
544 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384,
545 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512,
546 kSecKeyAlgorithmECDHKeyExchangeCofactor,
547 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1,
548 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224,
549 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256,
550 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384,
551 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512,
554 // Strange size to test borderline conditions.
555 const CFIndex requestedSize = 273;
556 NSDictionary *params = @{
557 (id)kSecKeyKeyExchangeParameterRequestedSize: @(requestedSize),
558 (id)kSecKeyKeyExchangeParameterSharedInfo: [NSData dataWithBytes:"shared" length:5],
561 for (size_t ix = 0; ix < array_size(algos); ++ix) {
562 CFErrorRef error = NULL;
564 NSData *secret1 = (NSData *)SecKeyCopyKeyExchangeResult(privKey1, algos[ix], pubKey2, (CFDictionaryRef)params, &error);
565 ok(secret1 != NULL && CFGetTypeID(secret1) == CFDataGetTypeID());
566 CFReleaseNull(error);
568 NSData *secret2 = (NSData *)SecKeyCopyKeyExchangeResult(privKey2, algos[ix], pubKey1, (CFDictionaryRef)params, &error);
569 ok(secret2 != NULL && CFGetTypeID(secret2) == CFDataGetTypeID());
570 CFReleaseNull(error);
572 eq_cf(secret1, secret2, "results of key exchange are equal");
573 if (algos[ix] != kSecKeyAlgorithmECDHKeyExchangeCofactor && algos[ix] != kSecKeyAlgorithmECDHKeyExchangeStandard) {
574 is(secret1.length, requestedSize, "generated response has expected length");
577 CFReleaseNull(secret1);
578 CFReleaseNull(secret2);
581 CFReleaseNull(privKey1);
582 CFReleaseNull(pubKey1);
583 CFReleaseNull(privKey2);
584 CFReleaseNull(pubKey2);
586 SecItemDelete((CFDictionaryRef)@{
587 (id)kSecClass: (id)kSecClassKey,
588 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
592 /* Test basic add delete update copy matching stuff. */
593 static void tests(void)
613 testkeyexchange(256);
614 testkeyexchange(384);
615 testkeyexchange(521);
618 int kc_41_sececkey(int argc, char *const *argv)