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 53static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) { 54 return kSecECDSAAlgorithmID; 55} 56 57 58/* 59 * 60 * Public Key 61 * 62 */ 63 64/* Public key static functions. */ 65static 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 73static 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 83static 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 93static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1; 94static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1; 95static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1; 96static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1; 97static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1; 98 99static 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 117static 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 163errOut: 164 return err; 165} 166 167static 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 183static 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 194errOut: 195#endif 196 return err; 197} 198 199static 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. */ 207static 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 219static 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 233static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) { 234 return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC); 235} 236 237static 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 297fail: 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 306SecKeyDescriptor 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. */ 325SecKeyRef 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. */ 341static 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 350static 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 } 428abort: 429 return err; 430} 431 432static 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); 442errOut: 443 444 return err; 445} 446 447#if 0 448static const struct ccdigest_info * 449ccdigest_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 466static 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 481static 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 488static 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 502static 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 519static 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 533errOut: 534 CFReleaseSafe(fullKeyBlob); 535 536 return dict; 537} 538static 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 567SecKeyDescriptor 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. */ 586SecKeyRef 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 594OSStatus 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 623errOut: 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. */ 633SecECNamedCurve 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 657CFDataRef 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} 666