]> git.saurik.com Git - apple/security.git/blob - sec/Security/SecECKey.c
Security-55471.14.8.tar.gz
[apple/security.git] / sec / Security / SecECKey.c
1 /*
2 * Copyright (c) 2010,2011 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 * SecECKey.c - CoreFoundation based rsa key object
26 */
27
28 #include "SecECKey.h"
29
30 #include <Security/SecKeyInternal.h>
31 #include <Security/SecItem.h>
32 #include <Security/SecBasePriv.h>
33 #include <AssertMacros.h>
34 #include <Security/SecureTransport.h> /* For error codes. */
35 #include <CoreFoundation/CFData.h> /* For error codes. */
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include <CoreFoundation/CFNumber.h>
40 #include <Security/SecFramework.h>
41 #include <Security/SecRandom.h>
42 #include <utilities/debugging.h>
43 #include "SecItemPriv.h"
44 #include <Security/SecInternal.h>
45 #include <corecrypto/ccec.h>
46 #include <corecrypto/ccsha1.h>
47 #include <corecrypto/ccsha2.h>
48 #include <corecrypto/ccrng.h>
49 #include <corecrypto/ccder_decode_eckey.h>
50
51 #define kMaximumECKeySize 521
52
53 static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) {
54 return kSecECDSAAlgorithmID;
55 }
56
57
58 /*
59 *
60 * Public Key
61 *
62 */
63
64 /* Public key static functions. */
65 static void SecECPublicKeyDestroy(SecKeyRef key) {
66 /* Zero out the public key */
67 ccec_pub_ctx_t pubkey;
68 pubkey.pub = key->key;
69 if (ccec_ctx_cp(pubkey).zp)
70 cc_zero(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey.pub);
71 }
72
73 static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length)
74 {
75 size_t keysize = ccec_x963_import_pub_size(encoded_length);
76 if(ccec_keysize_is_supported(keysize)) {
77 return ccec_get_cp(keysize);
78 }
79 ccec_const_cp_t nullCP = { .zp = NULL };
80 return nullCP;
81 }
82
83 static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length)
84 {
85 size_t keysize = ccec_x963_import_priv_size(encoded_length);
86 if(ccec_keysize_is_supported(keysize)) {
87 return ccec_get_cp(keysize);
88 }
89 ccec_const_cp_t nullCP = { .zp = NULL };
90 return nullCP;
91 }
92
93 static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1;
94 static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1;
95 static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1;
96 static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1;
97 static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1;
98
99 static ccec_const_cp_t ccec_cp_for_oid(ccoid_t oid)
100 {
101 if (oid.oid) {
102 if (ccoid_equal(oid, ccoid_secp192r1)) {
103 return ccec_cp_192();
104 } else if (ccoid_equal(oid, ccoid_secp256r1)) {
105 return ccec_cp_256();
106 } else if (ccoid_equal(oid, ccoid_secp224r1)) {
107 return ccec_cp_224();
108 } else if (ccoid_equal(oid, ccoid_secp384r1)) {
109 return ccec_cp_384();
110 } else if (ccoid_equal(oid, ccoid_secp521r1)) {
111 return ccec_cp_521();
112 }
113 }
114 return (ccec_const_cp_t){NULL};
115 }
116
117 static OSStatus SecECPublicKeyInit(SecKeyRef key,
118 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
119 ccec_pub_ctx_t pubkey;
120 pubkey.pub = key->key;
121 OSStatus err = errSecParam;
122
123 switch (encoding) {
124 case kSecDERKeyEncoding:
125 {
126 const SecDERKey *derKey = (const SecDERKey *)keyData;
127 if (keyDataLength != sizeof(SecDERKey)) {
128 err = errSecDecode;
129 break;
130 }
131
132 ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength);
133
134 /* TODO: Parse and use real params from passed in derKey->algId.params */
135 err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey)
136 ? errSecDecode : errSecSuccess);
137 break;
138 }
139 case kSecKeyEncodingBytes:
140 {
141 ccec_const_cp_t cp = getCPForPublicSize(keyDataLength);
142 err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey)
143 ? errSecDecode : errSecSuccess);
144 break;
145 }
146 case kSecExtractPublicFromPrivate:
147 {
148 ccec_full_ctx_t fullKey;
149 fullKey._full = (ccec_full_ctx *) keyData;
150
151 cc_size fullKeyN = ccec_ctx_n(fullKey);
152 require(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut);
153 memcpy(pubkey._pub, fullKey.pub, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN)));
154 err = errSecSuccess;
155 break;
156 }
157 case kSecKeyEncodingApplePkcs1:
158 default:
159 err = errSecParam;
160 break;
161 }
162
163 errOut:
164 return err;
165 }
166
167 static OSStatus SecECPublicKeyRawVerify(SecKeyRef key, SecPadding padding,
168 const uint8_t *signedData, size_t signedDataLen,
169 const uint8_t *sig, size_t sigLen) {
170 int err = errSSLCrypto; // TODO: Should be errSecNotSigner;
171 ccec_pub_ctx_t pubkey;
172 pubkey.pub = key->key;
173 bool valid = 0;
174
175 if (ccec_verify(pubkey, signedDataLen, signedData, sigLen, sig, &valid))
176 err = errSSLCrypto; // TODO: This seems weird. Shouldn't be SSL error
177 if (valid)
178 err = errSecSuccess;
179
180 return err;
181 }
182
183 static OSStatus SecECPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding,
184 const uint8_t *plainText, size_t plainTextLen,
185 uint8_t *cipherText, size_t *cipherTextLen) {
186 ccec_pub_ctx_t pubkey;
187 pubkey.pub = key->key;
188 int err = errSecUnimplemented;
189
190 #if 0
191 require_noerr(err = ccec_wrap_key(pubkey, &ccsha256_di,
192 plainTextLen, plainText, cipherText), errOut);
193
194 errOut:
195 #endif
196 return err;
197 }
198
199 static size_t SecECPublicKeyBlockSize(SecKeyRef key) {
200 /* Get key size in octets */
201 ccec_pub_ctx_t pubkey;
202 pubkey.pub = key->key;
203 return ccec_ctx_size(pubkey);
204 }
205
206 /* Encode the public key and return it in a newly allocated CFDataRef. */
207 static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator,
208 ccec_pub_ctx_t pubkey) {
209 size_t pub_size = ccec_export_pub_size(pubkey);
210 CFMutableDataRef blob = CFDataCreateMutable(allocator, pub_size);
211 if (blob) {
212 CFDataSetLength(blob, pub_size);
213 ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob));
214 }
215
216 return blob;
217 }
218
219 static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
220 {
221 ccec_pub_ctx_t pubkey;
222 pubkey.pub = key->key;
223
224 CFAllocatorRef allocator = CFGetAllocator(key);
225 *serailziation = SecECPublicKeyExport(allocator, pubkey);
226
227 if (NULL == *serailziation)
228 return errSecDecode;
229 else
230 return errSecSuccess;
231 }
232
233 static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) {
234 return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC);
235 }
236
237 static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key)
238 {
239 ccec_pub_ctx_t ecPubkey;
240 CFStringRef keyDescription = NULL;
241 size_t xlen, ylen, ix;
242 CFMutableStringRef xString = NULL;
243 CFMutableStringRef yString = NULL;
244
245 ecPubkey.pub = key->key;
246
247 //curve
248 long curveType = (long)SecECKeyGetNamedCurve(key);
249 char* curve= NULL;
250
251 switch (curveType)
252 {
253 case 23:
254 curve = "kSecECCurveSecp256r1";
255 break;
256 case 24:
257 curve = "kSecECCurveSecp384r1";
258 break;
259 case 25:
260 curve = "kSecECCurveSecp521r1";
261 break;
262 case -1:
263 curve = "kSecECCurveNone";
264 break;
265 default:
266 curve = "kSecECCurveNone";
267 break;
268 }
269
270 uint8_t *xunit = (uint8_t*)ccec_ctx_x(ecPubkey);
271 require_quiet( NULL != xunit, fail);
272 xlen = (size_t)strlen((char*)xunit);
273
274
275 xString = CFStringCreateMutable(kCFAllocatorDefault, xlen * 2);
276 require_quiet( NULL != xString, fail);
277
278 for (ix = 0; ix < xlen; ++ix)
279 {
280 CFStringAppendFormat(xString, NULL, CFSTR("%02X"), xunit[ix]);
281 }
282
283 uint8_t *yunit = (uint8_t*)ccec_ctx_y(ecPubkey);
284 require_quiet( NULL != yunit, fail);
285 ylen = (size_t)strlen((char*)yunit);
286
287 yString = CFStringCreateMutable(kCFAllocatorDefault, ylen*2);
288 require_quiet( NULL != yString, fail);
289
290 for(ix = 0; ix < ylen; ++ix)
291 {
292 CFStringAppendFormat(yString, NULL, CFSTR("%02X"), yunit[ix]);
293 }
294
295 keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, y: %@, x: %@, addr: %p>"), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), yString, xString, key);
296
297 fail:
298 CFReleaseSafe(xString);
299 CFReleaseSafe(yString);
300 if(!keyDescription)
301 keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve,(long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
302
303 return keyDescription;
304 }
305
306 SecKeyDescriptor kSecECPublicKeyDescriptor = {
307 kSecKeyDescriptorVersion,
308 "ECPublicKey",
309 ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */
310 SecECPublicKeyInit,
311 SecECPublicKeyDestroy,
312 NULL, /* SecKeyRawSignMethod */
313 SecECPublicKeyRawVerify,
314 SecECPublicKeyRawEncrypt,
315 NULL, /* SecKeyDecryptMethod */
316 NULL, /* SecKeyComputeMethod */
317 SecECPublicKeyBlockSize,
318 SecECPublicKeyCopyAttributeDictionary,
319 SecECPublicKeyCopyKeyDescription,
320 SecECKeyGetAlgorithmID,
321 SecECPublicKeyCopyPublicOctets,
322 };
323
324 /* Public Key API functions. */
325 SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator,
326 const uint8_t *keyData, CFIndex keyDataLength,
327 SecKeyEncoding encoding) {
328 return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData,
329 keyDataLength, encoding);
330 }
331
332
333
334 /*
335 *
336 * Private Key
337 *
338 */
339
340 /* Private key static functions. */
341 static void SecECPrivateKeyDestroy(SecKeyRef key) {
342 /* Zero out the public key */
343 ccec_full_ctx_t fullkey;
344 fullkey.hdr = key->key;
345 if (ccec_ctx_cp(fullkey).zp)
346 cc_zero(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey.hdr);
347 }
348
349
350 static OSStatus SecECPrivateKeyInit(SecKeyRef key,
351 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
352 ccec_full_ctx_t fullkey;
353 fullkey.hdr = key->key;
354 OSStatus err = errSecParam;
355
356 switch (encoding) {
357 case kSecKeyEncodingPkcs1:
358 {
359 /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */
360 //err = ecc_import(keyData, keyDataLength, fullkey);
361
362 /* DER != PKCS#1, but we'll go along with it */
363 ccoid_t oid;
364 size_t n;
365 ccec_const_cp_t cp;
366
367 require_noerr(ccec_der_import_priv_keytype(keyDataLength, keyData, &oid, &n), abort);
368 cp = ccec_cp_for_oid(oid);
369 if (cp.zp == NULL) {
370 cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */,
371 ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL);
372 }
373 require_action(cp.zp != NULL, abort, err = errSecDecode);
374 ccec_ctx_init(cp, fullkey);
375
376 require_noerr(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort);
377 err = errSecSuccess;
378 break;
379 }
380 case kSecKeyEncodingBytes:
381 {
382 ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength);
383 require(cp.zp != NULL, abort);
384
385 ccec_ctx_init(cp, fullkey);
386 size_t pubSize = ccec_export_pub_size(fullkey);
387
388 require(pubSize < (size_t) keyDataLength, abort);
389 require_noerr_action(ccec_import_pub(cp, pubSize, keyData, fullkey),
390 abort,
391 err = errSecDecode);
392
393
394 keyData += pubSize;
395 keyDataLength -= pubSize;
396
397 cc_unit *k = ccec_ctx_k(fullkey);
398 require_noerr_action(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData),
399 abort,
400 err = errSecDecode);
401
402 err = errSecSuccess;
403 break;
404
405 }
406 case kSecGenerateKey:
407 {
408 CFDictionaryRef parameters = (CFDictionaryRef) keyData;
409
410 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
411 CFIndex keyLengthInBits = getIntValue(ksize);
412
413 ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits);
414
415 if (!cp.zp) {
416 secwarning("Invalid or missing key size in: %@", parameters);
417 return errSecKeySizeNotAllowed;
418 }
419
420 if (!ccec_generate_key(cp, ccrng_seckey, fullkey))
421 err = errSecSuccess;
422 break;
423 }
424
425 default:
426 break;
427 }
428 abort:
429 return err;
430 }
431
432 static OSStatus SecECPrivateKeyRawSign(SecKeyRef key, SecPadding padding,
433 const uint8_t *dataToSign, size_t dataToSignLen,
434 uint8_t *sig, size_t *sigLen) {
435 ccec_full_ctx_t fullkey;
436 fullkey.hdr = key->key;
437 int err;;
438 check(sigLen);
439
440 require_noerr(err = ccec_sign(fullkey, dataToSignLen, dataToSign,
441 sigLen, sig, ccrng_seckey), errOut);
442 errOut:
443
444 return err;
445 }
446
447 #if 0
448 static const struct ccdigest_info *
449 ccdigest_lookup_by_oid(unsigned long oid_size, const void *oid) {
450 static const struct ccdigest_info *dis[] = {
451 &ccsha1_di,
452 &ccsha224_di,
453 &ccsha256_di,
454 &ccsha384_di,
455 &ccsha512_di
456 };
457 size_t i;
458 for (i = 0; i < array_size(dis); ++i) {
459 if (oid_size == dis[i]->oid_size && !memcmp(dis[i]->oid, oid, oid_size))
460 return dis[i];
461 }
462 return NULL;
463 }
464 #endif
465
466 static OSStatus SecECPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding,
467 const uint8_t *cipherText, size_t cipherTextLen,
468 uint8_t *plainText, size_t *plainTextLen) {
469 ccec_full_ctx_t fullkey;
470 fullkey.hdr = key->key;
471 int err = errSecUnimplemented;
472
473 #if 0
474 err = ccec_unwrap_key(fullkey, ccrng_seckey, ccdigest_lookup_by_oid,
475 cipherTextLen, cipherText, plainTextLen, plainText);
476 #endif
477
478 return err;
479 }
480
481 static size_t SecECPrivateKeyBlockSize(SecKeyRef key) {
482 ccec_full_ctx_t fullkey;
483 fullkey.hdr = key->key;
484 /* Get key size in octets */
485 return ccec_ctx_size(fullkey);
486 }
487
488 static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
489 {
490 ccec_full_ctx_t fullkey;
491 fullkey.hdr = key->key;
492
493 CFAllocatorRef allocator = CFGetAllocator(key);
494 *serailziation = SecECPublicKeyExport(allocator, fullkey);
495
496 if (NULL == *serailziation)
497 return errSecDecode;
498 else
499 return errSecSuccess;
500 }
501
502 static CFDataRef SecECPPrivateKeyExport(CFAllocatorRef allocator,
503 ccec_full_ctx_t fullkey) {
504 size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey));
505 size_t key_size = ccec_export_pub_size(fullkey) + prime_size;
506 CFMutableDataRef blob = CFDataCreateMutable(allocator, key_size);
507 if (blob) {
508 CFDataSetLength(blob, key_size);
509 ccec_export_pub(fullkey, CFDataGetMutableBytePtr(blob));
510 UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(fullkey);
511 const cc_unit *k = ccec_ctx_k(fullkey);
512 ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest);
513 }
514
515 return blob;
516 }
517
518
519 static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
520 CFDictionaryRef dict = NULL;
521 CFAllocatorRef allocator = CFGetAllocator(key);
522
523 ccec_full_ctx_t fullkey;
524 fullkey.hdr = key->key;
525
526 CFDataRef fullKeyBlob = NULL;
527
528 /* Export the full ec key pair. */
529 require(fullKeyBlob = SecECPPrivateKeyExport(allocator, fullkey), errOut);
530
531 dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob);
532
533 errOut:
534 CFReleaseSafe(fullKeyBlob);
535
536 return dict;
537 }
538 static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) {
539
540 //curve
541 long curveType = (long)SecECKeyGetNamedCurve(key);
542 char* curve= NULL;
543
544 switch (curveType)
545 {
546 case 23:
547 curve = "kSecECCurveSecp256r1";
548 break;
549 case 24:
550 curve = "kSecECCurveSecp384r1";
551 break;
552 case 25:
553 curve = "kSecECCurveSecp521r1";
554 break;
555 case -1:
556 curve = "kSecECCurveNone";
557 break;
558 default:
559 curve = "kSecECCurveNone";
560 break;
561 }
562
563 return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
564
565 }
566
567 SecKeyDescriptor kSecECPrivateKeyDescriptor = {
568 kSecKeyDescriptorVersion,
569 "ECPrivateKey",
570 ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */
571 SecECPrivateKeyInit,
572 SecECPrivateKeyDestroy,
573 SecECPrivateKeyRawSign,
574 NULL, /* SecKeyRawVerifyMethod */
575 NULL, /* SecKeyEncryptMethod */
576 SecECPrivateKeyRawDecrypt,
577 NULL, /* SecKeyComputeMethod */
578 SecECPrivateKeyBlockSize,
579 SecECPrivateKeyCopyAttributeDictionary,
580 SecECPrivateKeyCopyKeyDescription,
581 SecECKeyGetAlgorithmID,
582 SecECPrivateKeyCopyPublicOctets,
583 };
584
585 /* Private Key API functions. */
586 SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator,
587 const uint8_t *keyData, CFIndex keyDataLength,
588 SecKeyEncoding encoding) {
589 return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData,
590 keyDataLength, encoding);
591 }
592
593
594 OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters,
595 SecKeyRef *publicKey, SecKeyRef *privateKey) {
596 OSStatus status = errSecParam;
597
598 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
599 SecKeyRef pubKey = NULL;
600
601 SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor,
602 (const void*) parameters, 0, kSecGenerateKey);
603
604 require(privKey, errOut);
605
606 /* Create SecKeyRef's from the pkcs1 encoded keys. */
607 pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor,
608 privKey->key, 0, kSecExtractPublicFromPrivate);
609
610 require(pubKey, errOut);
611
612 if (publicKey) {
613 *publicKey = pubKey;
614 pubKey = NULL;
615 }
616 if (privateKey) {
617 *privateKey = privKey;
618 privKey = NULL;
619 }
620
621 status = errSecSuccess;
622
623 errOut:
624 CFReleaseSafe(pubKey);
625 CFReleaseSafe(privKey);
626
627 return status;
628 }
629
630
631 /* It's debatable whether this belongs here or in the ssl code since the
632 curve values come from a tls related rfc4492. */
633 SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) {
634 if (key->key_class != &kSecECPublicKeyDescriptor &&
635 key->key_class != &kSecECPrivateKeyDescriptor)
636 return kSecECCurveNone;
637
638 ccec_pub_ctx_t pubkey;
639 pubkey.pub = key->key;
640 switch (ccec_ctx_size(pubkey)) {
641 #if 0
642 case 24:
643 return kSecECCurveSecp192r1;
644 case 28:
645 return kSecECCurveSecp224r1;
646 #endif
647 case 32:
648 return kSecECCurveSecp256r1;
649 case 48:
650 return kSecECCurveSecp384r1;
651 case 66:
652 return kSecECCurveSecp521r1;
653 }
654 return kSecECCurveNone;
655 }
656
657 CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) {
658 if (key->key_class != &kSecECPublicKeyDescriptor &&
659 key->key_class != &kSecECPrivateKeyDescriptor)
660 return NULL;
661
662 ccec_pub_ctx_t pubkey;
663 pubkey.pub = key->key;
664 return SecECPublicKeyExport(CFGetAllocator(key), pubkey);
665 }