]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-41-sececkey.m
Security-57740.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, kCFNumberSInt32Type, &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 SKIP: {
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");
204
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");
213
214 #if TARGET_OS_IPHONE
215 testdigestandsign(privKey, pubKey);
216 #endif
217
218 const void *privkeys[] = {
219 kSecValueRef
220 };
221 const void *privvalues[] = {
222 privKey
223 };
224 CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
225 sizeof(privkeys) / sizeof(*privkeys), NULL, NULL);
226 #if TARGET_OS_IPHONE
227 ok_status(SecItemAdd(privitem, NULL), "add private key");
228 #endif
229 ok_status(SecItemDelete(privitem), "delete private key");
230 CFReleaseNull(privitem);
231
232 const void *pubkeys[] = {
233 kSecValueRef
234 };
235 const void *pubvalues[] = {
236 pubKey
237 };
238 CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues,
239 sizeof(pubkeys) / sizeof(*pubkeys), NULL, NULL);
240 #if TARGET_OS_IPHONE
241 ok_status(SecItemAdd(pubitem, NULL), "add public key");
242 #endif
243 ok_status(SecItemDelete(pubitem), "delete public key");
244 CFReleaseNull(pubitem);
245
246 /* Cleanup. */
247 CFReleaseNull(pubKey);
248 CFReleaseNull(privKey);
249 }
250 }
251
252
253 static void testkeygen2(size_t keySizeInBits) {
254 SecKeyRef pubKey = NULL, privKey = NULL;
255 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
256 CFNumberRef kzib;
257
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);
262
263 CFReleaseNull(ourUUID);
264 CFReleaseNull(uuidString);
265
266 CFStringAppend(publicName, CFSTR("-Public-41"));
267 CFStringAppend(privateName, CFSTR("-Private-41"));
268
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);
273
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);
281
282 OSStatus status;
283 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
284 "Generate %ld bit (%ld byte) persistent RSA keypair",
285 keySizeInBits, keySizeInBytes);
286 CFRelease(kzib);
287 CFRelease(kgp);
288
289 SKIP: {
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");
295
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");
308
309 /* Sign something. */
310 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
311 size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize);
312 uint8_t sig[sigLen];
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");
317
318 /* Cleanup. */
319 CFReleaseNull(pubKey2);
320 CFReleaseNull(privKey2);
321 }
322
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");
327
328 /* Cleanup. */
329 CFReleaseNull(pubKey);
330 CFReleaseNull(privKey);
331
332 CFReleaseNull(publicName);
333 CFReleaseNull(privateName);
334
335 CFRelease(pubd);
336 CFRelease(privd);
337 }
338
339 #if TARGET_OS_IPHONE
340 // Raw DER Key
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,
351 0xc7};
352 #else
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,
365 0xc7};
366
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};
377 #endif
378
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};
386
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};
394
395 const uint8_t EC_SigDigest[24] = "012345678912345678901234";
396
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,
407 0x02, 0x21,
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,
410 0x6b};
411
412 static void testsignformat(void)
413 {
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);
422
423 #if TARGET_OS_IPHONE
424 // Key import for iOS
425 {
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");
431
432 ok((pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault,
433 CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata),
434 kSecKeyEncodingBytes))!=NULL,
435 "recreate seckey");
436 CFReleaseNull(pubdata);
437 }
438 #else
439 // Key import for MacOS
440 {
441 CFDataRef DER_key;
442 SecExternalFormat sef=kSecFormatOpenSSL;
443 SecExternalItemType seit;
444
445 // Public key
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);
452
453 // Private 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);
460 }
461 #endif
462
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");
466
467 ok_status(SecKeyRawVerify(pubkey, kSecPaddingSigRaw,
468 EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig on something");
469
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");
473
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");
476
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");
480
481 ok_status(SecKeyRawSign(pkey, kSecPaddingSigRaw,
482 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, &EC_signature_RAW_size), "sign RAW sig on something");
483
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");
487
488 ok_status(SecKeyRawVerify(pubkey, kSecPaddingSigRaw,
489 EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, EC_signature_RAW_size), "verify RAW sig on something");
490
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");
495
496 CFReleaseNull(KeyArrayPub);
497 CFReleaseNull(KeyArrayPriv);
498 }
499
500 #if !TARGET_OS_IPHONE
501 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
502 {
503 if (left == NULL || right == NULL)
504 return left == right;
505 else
506 return CFEqual(left, right);
507 }
508 #endif
509
510 static void testkeyexchange(unsigned long keySizeInBits)
511 {
512 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
513 OSStatus status;
514
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,
522 };
523 ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp1, &pubKey1, &privKey1),
524 "Generate %ld bit (%ld byte) EC keypair (status = %d)",
525 keySizeInBits, keySizeInBytes, (int)status);
526
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,
534 };
535 ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp2, &pubKey2, &privKey2),
536 "Generate %ld bit (%ld byte) EC keypair (status = %d)",
537 keySizeInBits, keySizeInBytes, (int)status);
538
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,
552 };
553
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],
559 };
560
561 for (size_t ix = 0; ix < array_size(algos); ++ix) {
562 CFErrorRef error = NULL;
563
564 NSData *secret1 = (NSData *)SecKeyCopyKeyExchangeResult(privKey1, algos[ix], pubKey2, (CFDictionaryRef)params, &error);
565 ok(secret1 != NULL && CFGetTypeID(secret1) == CFDataGetTypeID());
566 CFReleaseNull(error);
567
568 NSData *secret2 = (NSData *)SecKeyCopyKeyExchangeResult(privKey2, algos[ix], pubKey1, (CFDictionaryRef)params, &error);
569 ok(secret2 != NULL && CFGetTypeID(secret2) == CFDataGetTypeID());
570 CFReleaseNull(error);
571
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");
575 }
576
577 CFReleaseNull(secret1);
578 CFReleaseNull(secret2);
579 }
580
581 CFReleaseNull(privKey1);
582 CFReleaseNull(pubKey1);
583 CFReleaseNull(privKey2);
584 CFReleaseNull(pubKey2);
585
586 SecItemDelete((CFDictionaryRef)@{
587 (id)kSecClass: (id)kSecClassKey,
588 (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange",
589 });
590 }
591
592 /* Test basic add delete update copy matching stuff. */
593 static void tests(void)
594 {
595 testsignformat();
596
597 testkeygen(192);
598 #if TARGET_OS_IPHONE
599 testkeygen(224);
600 #endif
601 testkeygen(256);
602 testkeygen(384);
603 testkeygen(521);
604
605 testkeygen2(192);
606 #if TARGET_OS_IPHONE
607 testkeygen2(224);
608 #endif
609 testkeygen2(256);
610 testkeygen2(384);
611 testkeygen2(521);
612
613 testkeyexchange(256);
614 testkeyexchange(384);
615 testkeyexchange(521);
616 }
617
618 int kc_41_sececkey(int argc, char *const *argv)
619 {
620 plan_tests(245);
621
622 tests();
623
624 return 0;
625 }