]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-41-sececkey.m
Security-58286.31.2.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-41-sececkey.m
1 /*
2 * Copyright (c) 2011,2013-2014 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 /*
26 * si-40-seckey.c
27 * Security
28 *
29 * Copyright (c) 2007-2009,2013-2014 Apple Inc. All Rights Reserved.
30 *
31 */
32
33 /*
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/
37 */
38 #define __KEYCHAINCORE__ 1
39 #import <Foundation/Foundation.h>
40
41 #include <TargetConditionals.h>
42 #include <CoreFoundation/CoreFoundation.h>
43 #include <Security/Security.h>
44 #include <Security/SecKeyPriv.h>
45 #include <Security/SecItemPriv.h>
46
47 #include <Security/SecItem.h>
48 #include <Security/SecKey.h>
49
50 #if 0
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>
62 #include <stdlib.h>
63 #include <unistd.h>
64 #endif
65
66
67 #include "keychain_regressions.h"
68 #include "utilities/SecCFRelease.h"
69 #include "utilities/array_size.h"
70
71
72 #if TARGET_OS_IPHONE
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);
77 uint8_t sig[sigLen];
78
79 DERItem oid;
80 oid.length = algId->algorithm.Length;
81 oid.data = algId->algorithm.Data;
82
83 /* Get the oid in decimal for display purposes. */
84 CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid);
85 char oidBuf[40];
86 CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8);
87 CFRelease(oidStr);
88
89 SKIP: {
90 OSStatus status;
91
92 /* Time to sign. */
93 ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen,
94 sig, &sigLen),
95 "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8);
96
97 skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess);
98
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. */
103 sig[0] ^= 0xff;
104 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
105 sig, sigLen), errSSLCrypto, "digest and verify bad sig");
106 sig[0] ^= 0xff;
107 dataToDigest[0] ^= 0xff;
108 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
109 sig, sigLen), errSSLCrypto, "digest and verify bad digest");
110 }
111 }
112
113 static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) {
114 static const SecAsn1Oid *oids[] = {
115 &CSSMOID_ECDSA_WithSHA1,
116 #if 0
117 &CSSMOID_ECDSA_WithSHA224,
118 &CSSMOID_ECDSA_WithSHA256,
119 &CSSMOID_ECDSA_WithSHA384,
120 &CSSMOID_ECDSA_WithSHA512,
121 #endif
122 };
123
124 uint32_t ix;
125 SecAsn1AlgId algId = {};
126 for (ix = 0; ix < sizeof(oids) / sizeof(*oids); ++ix) {
127 if (oids[ix]) {
128 algId.algorithm = *oids[ix];
129 } else {
130 algId.algorithm.Length = 0;
131 algId.algorithm.Data = NULL;
132 }
133
134 testdigestandsignalg(privKey, pubKey, &algId);
135 }
136 }
137 #endif
138
139
140 #if !TARGET_OS_IPHONE
141 /* This is part of Security.framework on iOS */
142
143 enum {
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.
149 };
150
151 static
152 size_t SecKeyGetSize(SecKeyRef key, int whichSize)
153 {
154 /* SecKeyGetBlockSize return the signature size on OS X -- smh */
155 size_t result = SecKeyGetBlockSize(key);
156
157 result = (result - 2)/2 - 3;
158
159 /* in this test, this is always an ECDSA key */
160 switch (whichSize) {
161 case kSecKeyEncryptedDataSize:
162 result = 0;
163 break;
164 case kSecKeySignatureSize:
165 result = (result >= 66 ? 9 : 8) + 2 * result;
166 break;
167 case kSecKeyKeySizeInBits:
168 if (result >= 66)
169 return 521;
170 }
171
172 if (whichSize == kSecKeyKeySizeInBits)
173 result *= 8;
174
175 return result;
176
177 }
178 #endif
179
180
181 static void testkeygen(size_t keySizeInBits) {
182 SecKeyRef pubKey = NULL, privKey = NULL;
183 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
184 CFNumberRef kzib;
185
186 kzib = CFNumberCreate(NULL, kCFNumberSInt64Type, &keySizeInBits);
187 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
188 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
189 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
190
191 OSStatus status;
192 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
193 "Generate %ld bit (%ld byte) EC keypair", keySizeInBits,
194 keySizeInBytes);
195 CFRelease(kzib);
196 CFRelease(kgp);
197
198 SecKeyRef pubKeybis = SecKeyCopyPublicKey(privKey);
199 ok(pubKeybis!=NULL);
200 is(CFGetRetainCount(pubKeybis),2); // pubKey + pubKeybis
201 CFDataRef PubKeyData = SecKeyCopyExternalRepresentation(pubKey, NULL);
202 CFDataRef PubKeybisData = SecKeyCopyExternalRepresentation(pubKeybis, NULL);
203 isnt(CFDataGetLength(PubKeyData),0);
204 ok(CFEqual(PubKeyData,PubKeybisData));
205 CFReleaseNull(PubKeyData);
206 CFReleaseNull(PubKeybisData);
207 CFReleaseNull(pubKeybis);
208
209
210 SKIP: {
211 skip("keygen failed", 8, status == errSecSuccess);
212 ok(pubKey, "pubKey returned");
213 ok(privKey, "privKey returned");
214 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
215 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
216
217 /* Sign something. */
218 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
219 uint8_t sig[8+2*keySizeInBytes];
220 size_t sigLen = sizeof(sig);
221 ok_status(SecKeyRawSign(privKey, kSecPaddingNone,
222 something, sizeof(something), sig, &sigLen), "sign something");
223 ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone,
224 something, sizeof(something), sig, sigLen), "verify sig on something");
225
226 #if TARGET_OS_IPHONE
227 testdigestandsign(privKey, pubKey);
228 #endif
229
230 const void *privkeys[] = {
231 kSecValueRef
232 };
233 const void *privvalues[] = {
234 privKey
235 };
236 CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
237 sizeof(privkeys) / sizeof(*privkeys), NULL, NULL);
238 #if TARGET_OS_IPHONE
239 ok_status(SecItemAdd(privitem, NULL), "add private key");
240 #endif
241 ok_status(SecItemDelete(privitem), "delete private key");
242 CFReleaseNull(privitem);
243
244 const void *pubKeys[] = {
245 kSecValueRef
246 };
247 const void *pubvalues[] = {
248 pubKey
249 };
250 CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubKeys, pubvalues,
251 sizeof(pubKeys) / sizeof(*pubKeys), NULL, NULL);
252 #if TARGET_OS_IPHONE
253 ok_status(SecItemAdd(pubitem, NULL), "add public key");
254 #endif
255 ok_status(SecItemDelete(pubitem), "delete public key");
256 CFReleaseNull(pubitem);
257
258 /* Cleanup. */
259 CFReleaseNull(pubKey);
260 CFReleaseNull(privKey);
261 }
262 }
263
264
265 static void testkeygen2(size_t keySizeInBits) {
266 SecKeyRef pubKey = NULL, privKey = NULL;
267 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
268 CFNumberRef kzib;
269
270 CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
271 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
272 CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
273 CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
274
275 CFReleaseNull(ourUUID);
276 CFReleaseNull(uuidString);
277
278 CFStringAppend(publicName, CFSTR("-Public-41"));
279 CFStringAppend(privateName, CFSTR("-Private-41"));
280
281 CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
282 CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
283 CFDictionaryAddValue(pubd, kSecAttrLabel, publicName);
284 CFDictionaryAddValue(privd, kSecAttrLabel, privateName);
285
286 kzib = CFNumberCreate(NULL, kCFNumberSInt64Type, &keySizeInBits);
287 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
288 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
289 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
290 CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue);
291 CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd);
292 CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd);
293
294 OSStatus status;
295 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
296 "Generate %ld bit (%ld byte) persistent RSA keypair",
297 keySizeInBits, keySizeInBytes);
298 CFRelease(kzib);
299 CFRelease(kgp);
300
301 SKIP: {
302 skip("keygen failed", 8, status == errSecSuccess);
303 ok(pubKey, "pubKey returned");
304 ok(privKey, "privKey returned");
305 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
306 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
307
308 SecKeyRef pubKey2, privKey2;
309 CFDictionaryAddValue(pubd, kSecClass, kSecClassKey);
310 CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue);
311 CFDictionaryAddValue(privd, kSecClass, kSecClassKey);
312 CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue);
313 CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue);
314 ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2),
315 "retrieve pub key by label");
316 ok(pubKey2, "got valid object");
317 ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2),
318 "retrieve priv key by label and kSecAttrCanSign");
319 ok(privKey2, "got valid object");
320
321 /* Sign something. */
322 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
323 size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize);
324 uint8_t sig[sigLen];
325 ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1,
326 something, sizeof(something), sig, &sigLen), "sign something");
327 ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1,
328 something, sizeof(something), sig, sigLen), "verify sig on something");
329
330 /* Cleanup. */
331 CFReleaseNull(pubKey2);
332 CFReleaseNull(privKey2);
333 }
334
335 /* delete from keychain - note: do it before releasing publicName and privateName
336 because pubd and privd have no retain/release callbacks */
337 ok_status(SecItemDelete(pubd), "delete generated pub key");
338 ok_status(SecItemDelete(privd), "delete generated priv key");
339
340 /* Cleanup. */
341 CFReleaseNull(pubKey);
342 CFReleaseNull(privKey);
343
344 CFReleaseNull(publicName);
345 CFReleaseNull(privateName);
346
347 CFRelease(pubd);
348 CFRelease(privd);
349 }
350
351 static void testkeygen3(size_t keySizeInBits) {
352 SecKeyRef pubKey = NULL, privKey = NULL;
353 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
354 CFNumberRef kzib;
355
356 kzib = CFNumberCreate(NULL, kCFNumberSInt64Type, &keySizeInBits);
357 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
358 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
359 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
360 CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanFalse);
361
362 ok(privKey = SecKeyCreateRandomKey(kgp, NULL));
363 CFRelease(kzib);
364 CFRelease(kgp);
365
366 ok(pubKey = SecKeyCopyPublicKey(privKey));
367 is(CFGetRetainCount(pubKey),1);
368
369 /* Sign something. */
370 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
371 uint8_t sig[8+2*keySizeInBytes];
372 size_t sigLen = sizeof(sig);
373 ok_status(SecKeyRawSign(privKey, kSecPaddingNone,
374 something, sizeof(something), sig, &sigLen), "sign something");
375 ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone,
376 something, sizeof(something), sig, sigLen), "verify sig on something");
377
378 /* Cleanup. */
379 CFReleaseNull(pubKey);
380 CFReleaseNull(privKey);
381 }
382
383
384 #if TARGET_OS_IPHONE
385 // Raw DER Key
386 const uint8_t EC_P256_KeyDER[]={
387 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1,
388 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23,
389 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8,
390 0xeb, 0xf3, 0x88, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7,
391 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d,
392 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f,
393 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97,
394 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07,
395 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04,
396 0xc7};
397 #else
398 // Open SSL Private Key
399 const uint8_t EC_P256_KeyDER_priv[]={
400 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1,
401 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23,
402 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8,
403 0xeb, 0xf3, 0x88, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
404 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7,
405 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d,
406 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f,
407 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97,
408 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07,
409 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04,
410 0xc7};
411
412 // Open SSL Public Key
413 const uint8_t EC_P256_KeyDER_pub[]={
414 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
415 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
416 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7, 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a,
417 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d, 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79,
418 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f, 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00,
419 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97, 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad,
420 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07, 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63,
421 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04, 0xc7};
422 #endif
423
424 const uint8_t EC_P256_SigDER[]={
425 0x30, 0x45, 0x02, 0x20, 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53,
426 0xb3, 0x62, 0x6f, 0x32, 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9,
427 0x17, 0x67, 0x03, 0x73, 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3,
428 0x02, 0x21, 0x00, 0xd6, 0x23, 0xaf, 0xd9, 0x7d, 0x72, 0xba, 0x3b, 0x90,
429 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d, 0xbb, 0xb4, 0x0f, 0x67, 0x26,
430 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, 0xe0, 0x45, 0xd5, 0x6b};
431
432 const uint8_t EC_P256_SigRaw[]= {
433 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53, 0xb3, 0x62, 0x6f, 0x32,
434 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, 0x17, 0x67, 0x03, 0x73,
435 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3, 0xd6, 0x23, 0xaf, 0xd9,
436 0x7d, 0x72, 0xba, 0x3b, 0x90, 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d,
437 0xbb, 0xb4, 0x0f, 0x67, 0x26, 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d,
438 0xe0, 0x45, 0xd5, 0x6b};
439
440 const uint8_t EC_SigDigest[24] = "012345678912345678901234";
441
442 /* r is 72 bytes longer than it should be */
443 const uint8_t EC_P256_SigDER_LargeInt[]={
444 0x30, 0x81, 0x8D, 0x02, 0x68,
445 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53,
450 0xb3, 0x62, 0x6f, 0x32, 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, 0x17, 0x67, 0x03, 0x73,
451 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3,
452 0x02, 0x21,
453 0x00, 0xd6, 0x23, 0xaf, 0xd9, 0x7d, 0x72, 0xba, 0x3b, 0x90, 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1,
454 0x0d, 0xbb, 0xb4, 0x0f, 0x67, 0x26, 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, 0xe0, 0x45, 0xd5,
455 0x6b};
456
457 static void testsignformat(void)
458 {
459 SecKeyRef privKey = NULL;
460 SecKeyRef pubKey = NULL;
461 CFArrayRef KeyArrayPub=NULL;
462 CFArrayRef KeyArrayPriv=NULL;
463 uint8_t EC_signature_DER[72];
464 uint8_t EC_signature_RAW[64];
465 size_t EC_signature_DER_size=sizeof(EC_signature_DER);
466 size_t EC_signature_RAW_size=sizeof(EC_signature_RAW);
467
468 #if TARGET_OS_IPHONE
469 // Key import for iOS
470 {
471 ok((privKey = SecKeyCreateECPrivateKey(kCFAllocatorDefault,
472 EC_P256_KeyDER, sizeof(EC_P256_KeyDER),
473 kSecKeyEncodingPkcs1)) != NULL, "import privkey");
474 CFDataRef pubdata = NULL;
475 ok_status(SecKeyCopyPublicBytes(privKey, &pubdata), "pub key from priv key");
476
477 ok((pubKey = SecKeyCreateECPublicKey(kCFAllocatorDefault,
478 CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata),
479 kSecKeyEncodingBytes))!=NULL,
480 "recreate seckey");
481 CFReleaseNull(pubdata);
482 }
483 #else
484 // Key import for MacOS
485 {
486 CFDataRef DER_key;
487 SecExternalFormat sef=kSecFormatOpenSSL;
488 SecExternalItemType seit;
489
490 // Public key
491 DER_key = CFDataCreate(kCFAllocatorDefault, EC_P256_KeyDER_pub, sizeof(EC_P256_KeyDER_pub));
492 seit=kSecItemTypePublicKey;
493 ok_status(SecItemImport(DER_key,NULL,&sef,&seit,0,NULL,NULL,&KeyArrayPub), "Import DER key");
494 ok((!(KeyArrayPub==NULL) && CFArrayGetCount(KeyArrayPub)==1), "One key imported");
495 pubKey=(SecKeyRef)CFArrayGetValueAtIndex(KeyArrayPub,0);
496 CFReleaseNull(DER_key);
497
498 // Private key
499 DER_key = CFDataCreate(kCFAllocatorDefault, EC_P256_KeyDER_priv, sizeof(EC_P256_KeyDER_priv));
500 seit=kSecItemTypePrivateKey;
501 ok_status(SecItemImport(DER_key,NULL,&sef,&seit,0,NULL,NULL,&KeyArrayPriv), "Import DER key");
502 ok((!(KeyArrayPriv==NULL) && CFArrayGetCount(KeyArrayPriv)==1), "One key imported");
503 privKey=(SecKeyRef)CFArrayGetValueAtIndex(KeyArrayPriv,0);
504 CFReleaseNull(DER_key);
505 }
506 #endif
507
508 // Verify fixed signature
509 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1,
510 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER, sizeof(EC_P256_SigDER)), "verify DER sig on something");
511
512 ok_status(SecKeyRawVerify(pubKey, kSecPaddingSigRaw,
513 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig on something");
514
515 // Verify signature with mismatching format
516 ok_status(!SecKeyRawVerify(pubKey, kSecPaddingSigRaw,
517 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER, sizeof(EC_P256_SigDER)), "verify DER sig with RAW option");
518
519 ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1,
520 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig with DER something");
521
522 // Sign something in each format
523 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1,
524 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_DER, &EC_signature_DER_size), "sign DER sig on something");
525
526 ok_status(SecKeyRawSign(privKey, kSecPaddingSigRaw,
527 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, &EC_signature_RAW_size), "sign RAW sig on something");
528
529 // Verify expecting that verification does the right thing.
530 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1,
531 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_DER, EC_signature_DER_size), "verify DER sig on something");
532
533 ok_status(SecKeyRawVerify(pubKey, kSecPaddingSigRaw,
534 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, EC_signature_RAW_size), "verify RAW sig on something");
535
536 // Verify signature with one integer larger than it should be
537 ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1,
538 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER_LargeInt, sizeof(EC_P256_SigDER_LargeInt)),
539 "verify DER sig with large integer");
540
541 CFReleaseNull(KeyArrayPub);
542 CFReleaseNull(KeyArrayPriv);
543 }
544
545 #if !TARGET_OS_IPHONE
546 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
547 {
548 if (left == NULL || right == NULL)
549 return left == right;
550 else
551 return CFEqual(left, right);
552 }
553 #endif
554
555 static void testkeyexchange(unsigned long keySizeInBits)
556 {
557 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
558 OSStatus status;
559
560 SecKeyRef pubKey1 = NULL, privKey1 = NULL;
561 NSDictionary *kgp1 = @{
562 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
563 (id)kSecAttrKeySizeInBits: @(keySizeInBits),
564 (id)kSecAttrIsPermanent: @NO,
565 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
566 (id)kSecAttrNoLegacy: @YES,
567 };
568 ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp1, &pubKey1, &privKey1),
569 "Generate %ld bit (%ld byte) EC keypair (status = %d)",
570 keySizeInBits, keySizeInBytes, (int)status);
571
572 SecKeyRef pubKey1bis = SecKeyCopyPublicKey(privKey1);
573 ok(pubKey1bis!=NULL);
574 is(CFGetRetainCount(pubKey1bis),1);
575 CFDataRef PubKey1Data = SecKeyCopyExternalRepresentation(pubKey1, NULL);
576 CFDataRef PubKey1bisData = SecKeyCopyExternalRepresentation(pubKey1bis, NULL);
577 isnt(CFDataGetLength(PubKey1Data),0);
578 ok(CFEqual(PubKey1Data,PubKey1bisData));
579 CFReleaseNull(PubKey1Data);
580 CFReleaseNull(PubKey1bisData);
581 CFReleaseNull(pubKey1bis);
582
583 SecKeyRef pubKey2 = NULL, privKey2 = NULL;
584 NSDictionary *kgp2 = @{
585 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
586 (id)kSecAttrKeySizeInBits: @(keySizeInBits),
587 (id)kSecAttrIsPermanent: @NO,
588 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
589 (id)kSecAttrNoLegacy: @NO,
590 };
591 ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp2, &pubKey2, &privKey2),
592 "Generate %ld bit (%ld byte) EC keypair (status = %d)",
593 keySizeInBits, keySizeInBytes, (int)status);
594
595 const SecKeyAlgorithm algos[] = {
596 kSecKeyAlgorithmECDHKeyExchangeStandard,
597 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1,
598 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224,
599 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256,
600 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384,
601 kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512,
602 kSecKeyAlgorithmECDHKeyExchangeCofactor,
603 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1,
604 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224,
605 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256,
606 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384,
607 kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512,
608 };
609
610 // Strange size to test borderline conditions.
611 const CFIndex requestedSize = 273;
612 NSDictionary *params = @{
613 (id)kSecKeyKeyExchangeParameterRequestedSize: @(requestedSize),
614 (id)kSecKeyKeyExchangeParameterSharedInfo: [NSData dataWithBytes:"shared" length:5],
615 };
616
617 for (size_t ix = 0; ix < array_size(algos); ++ix) {
618 CFErrorRef error = NULL;
619
620 NSData *secret1 = (__bridge_transfer NSData *)SecKeyCopyKeyExchangeResult(privKey1, algos[ix], pubKey2, (CFDictionaryRef)params, &error);
621 ok(secret1 != NULL && CFGetTypeID((__bridge CFTypeRef) secret1) == CFDataGetTypeID());
622 CFReleaseNull(error);
623
624 NSData *secret2 = (__bridge_transfer NSData *)SecKeyCopyKeyExchangeResult(privKey2, algos[ix], pubKey1, (CFDictionaryRef)params, &error);
625 ok(secret2 != NULL && CFGetTypeID((__bridge CFTypeRef) secret2) == CFDataGetTypeID());
626 CFReleaseNull(error);
627
628 eq_cf((__bridge CFTypeRef) secret1, (__bridge CFTypeRef) secret2, "results of key exchange are equal");
629 if (algos[ix] != kSecKeyAlgorithmECDHKeyExchangeCofactor && algos[ix] != kSecKeyAlgorithmECDHKeyExchangeStandard) {
630 is(secret1.length, requestedSize, "generated response has expected length");
631 }
632 }
633
634 CFReleaseNull(privKey1);
635 CFReleaseNull(pubKey1);
636 CFReleaseNull(privKey2);
637 CFReleaseNull(pubKey2);
638
639 SecItemDelete((CFDictionaryRef)@{
640 (id)kSecClass: (id)kSecClassKey,
641 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
642 });
643 }
644
645 /* Test basic add delete update copy matching stuff. */
646 static void tests(void)
647 {
648 testsignformat();
649
650 testkeygen(192);
651 #if TARGET_OS_IPHONE
652 testkeygen(224);
653 #endif
654 testkeygen(256);
655 testkeygen(384);
656 testkeygen(521);
657
658 testkeygen2(192);
659 #if TARGET_OS_IPHONE
660 testkeygen2(224);
661 #endif
662 testkeygen2(256);
663 testkeygen2(384);
664 testkeygen2(521);
665
666 testkeygen3(256);
667 testkeygen3(384);
668 testkeygen3(521);
669
670 testkeyexchange(256);
671 testkeyexchange(384);
672 testkeyexchange(521);
673 }
674
675 int kc_41_sececkey(int argc, char *const *argv)
676 {
677 plan_tests(288);
678
679 tests();
680
681 return 0;
682 }