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