SecECKey.m
1 /* 2 * Copyright (c) 2010-2015 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.m - CoreFoundation based ECDSA key object 26 */ 27 28 #include "SecECKey.h" 29 #include "SecECKeyPriv.h" 30 31 #import <Foundation/Foundation.h> 32 33 #include <Security/SecKeyInternal.h> 34 #include <Security/SecItem.h> 35 #include <Security/SecBasePriv.h> 36 #include <AssertMacros.h> 37 #include <Security/SecureTransport.h> /* For error codes. */ 38 #include <CoreFoundation/CFData.h> /* For error codes. */ 39 #include <CoreFoundation/CFNumber.h> 40 #include <Security/SecFramework.h> 41 #include <Security/SecRandom.h> 42 #include <utilities/debugging.h> 43 #include <Security/SecItemPriv.h> 44 #include <Security/SecInternal.h> 45 #include <utilities/SecCFError.h> 46 #include <utilities/SecCFWrappers.h> 47 #include <utilities/array_size.h> 48 #include <corecrypto/ccec.h> 49 #include <corecrypto/ccsha1.h> 50 #include <corecrypto/ccsha2.h> 51 #include <corecrypto/ccrng.h> 52 #include <corecrypto/ccder_decode_eckey.h> 53 54 #define kMaximumECKeySize 521 55 56 static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) { 57 return kSecECDSAAlgorithmID; 58 } 59 60 61 /* 62 * 63 * Public Key 64 * 65 */ 66 67 /* Public key static functions. */ 68 static void SecECPublicKeyDestroy(SecKeyRef key) { 69 /* Zero out the public key */ 70 ccec_pub_ctx_t pubkey = key->key; 71 if (ccec_ctx_cp(pubkey)) 72 cc_clear(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey); 73 } 74 75 static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length) 76 { 77 size_t keysize = ccec_x963_import_pub_size(encoded_length); 78 if(ccec_keysize_is_supported(keysize)) { 79 return ccec_get_cp(keysize); 80 } 81 return NULL; 82 } 83 84 static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length) 85 { 86 size_t keysize = ccec_x963_import_priv_size(encoded_length); 87 if(ccec_keysize_is_supported(keysize)) { 88 return ccec_get_cp(keysize); 89 } 90 return NULL; 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 // <rdar://problem/66864716> OID_CERTICOM is wrong 100 static ccoid_t ccoid_libder_secp384r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x22"); 101 static ccoid_t ccoid_libder_secp521r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x23"); 102 103 static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid) 104 { 105 if (oid!=NULL) { 106 if (ccoid_equal(oid, ccoid_secp192r1)) { 107 return ccec_cp_192(); 108 } else if (ccoid_equal(oid, ccoid_secp256r1)) { 109 return ccec_cp_256(); 110 } else if (ccoid_equal(oid, ccoid_secp224r1)) { 111 return ccec_cp_224(); 112 } else if (ccoid_equal(oid, ccoid_secp384r1) || ccoid_equal(oid, ccoid_libder_secp384r1)) { 113 return ccec_cp_384(); 114 } else if (ccoid_equal(oid, ccoid_secp521r1) || ccoid_equal(oid, ccoid_libder_secp521r1)) { 115 return ccec_cp_521(); 116 } 117 } 118 return (ccec_const_cp_t){NULL}; 119 } 120 121 static OSStatus SecECPublicKeyInit(SecKeyRef key, 122 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { 123 ccec_pub_ctx_t pubkey = key->key; 124 OSStatus err = errSecParam; 125 126 switch (encoding) { 127 case kSecDERKeyEncoding: 128 { 129 const SecDERKey *derKey = (const SecDERKey *)keyData; 130 if (keyDataLength != sizeof(SecDERKey)) { 131 err = errSecDecode; 132 break; 133 } 134 135 require_action_quiet(derKey->parameters && derKey->parametersLength > 2 && 136 derKey->parameters[1] <= derKey->parametersLength - 2, errOut, err = errSecDecode); 137 ccec_const_cp_t cp = ccec_cp_for_oid(derKey->parameters); 138 require_action_quiet(cp, errOut, err = errSecDecode); 139 140 err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey) 141 ? errSecDecode : errSecSuccess); 142 break; 143 } 144 case kSecKeyEncodingBytes: 145 { 146 ccec_const_cp_t cp = getCPForPublicSize(keyDataLength); 147 require_action_quiet(cp, errOut, err = errSecDecode); 148 err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey) 149 ? errSecDecode : errSecSuccess); 150 break; 151 } 152 case kSecExtractPublicFromPrivate: 153 { 154 ccec_full_ctx_t fullKey = (ccec_full_ctx_t)keyData; 155 156 cc_size fullKeyN = ccec_ctx_n(fullKey); 157 require_quiet(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut); 158 memcpy(pubkey, fullKey, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN))); 159 err = errSecSuccess; 160 break; 161 } 162 case kSecKeyEncodingApplePkcs1: 163 default: 164 err = errSecParam; 165 break; 166 } 167 168 errOut: 169 return err; 170 } 171 172 static CFTypeRef SecECPublicKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, 173 CFArrayRef algorithms, SecKeyOperationMode mode, 174 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { 175 if (operation != kSecKeyOperationTypeVerify || !CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) { 176 // EC public key supports only signature verification with X962 algorithm. 177 return kCFNull; 178 } 179 180 if (mode == kSecKeyOperationModePerform) { 181 bool valid = false; 182 int err = -1; 183 size_t sigLen = CFDataGetLength(in2); 184 uint8_t *sig = (uint8_t *)CFDataGetBytePtr(in2); 185 ccec_pub_ctx_t pubkey = key->key; 186 187 err = ccec_verify(pubkey, CFDataGetLength(in1), CFDataGetBytePtr(in1), sigLen, sig, &valid); 188 if (err != 0) { 189 SecError(errSecVerifyFailed, error, CFSTR("EC signature verification failed (ccerr %d)"), err); 190 return NULL; 191 } else if (!valid) { 192 SecError(errSecVerifyFailed, error, CFSTR("EC signature verification failed, no match")); 193 return NULL; 194 } else { 195 return kCFBooleanTrue; 196 } 197 } else { 198 // Algorithm is supported. 199 return kCFBooleanTrue; 200 } 201 } 202 203 static size_t SecECPublicKeyBlockSize(SecKeyRef key) { 204 /* Get key size in octets */ 205 return ccec_ctx_size(ccec_ctx_pub(key->key)); 206 } 207 208 /* Encode the public key and return it in a newly allocated CFDataRef. */ 209 static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator, 210 ccec_pub_ctx_t pubkey) { 211 size_t pub_size = ccec_export_pub_size(pubkey); 212 CFMutableDataRef blob = CFDataCreateMutableWithScratch(allocator, pub_size); 213 ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob)); 214 return blob; 215 } 216 217 static CFDataRef SecECPublicKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { 218 ccec_pub_ctx_t pubkey = key->key; 219 return SecECPublicKeyExport(NULL, pubkey); 220 } 221 222 static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation) 223 { 224 ccec_pub_ctx_t pubkey = key->key; 225 226 CFAllocatorRef allocator = CFGetAllocator(key); 227 *serailziation = SecECPublicKeyExport(allocator, pubkey); 228 229 if (NULL == *serailziation) 230 return errSecDecode; 231 else 232 return errSecSuccess; 233 } 234 235 static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) { 236 CFDictionaryRef dict = SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC); 237 CFMutableDictionaryRef mutableDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 238 CFDictionarySetValue(mutableDict, kSecAttrCanDerive, kCFBooleanFalse); 239 CFAssignRetained(dict, mutableDict); 240 return dict; 241 } 242 243 static const char * 244 getCurveName(SecKeyRef key) 245 { 246 SecECNamedCurve curveType = SecECKeyGetNamedCurve(key); 247 248 switch (curveType) 249 { 250 case kSecECCurveSecp256r1: 251 return "kSecECCurveSecp256r1"; 252 break; 253 case kSecECCurveSecp384r1: 254 return "kSecECCurveSecp384r1"; 255 break; 256 case kSecECCurveSecp521r1: 257 return "kSecECCurveSecp521r1"; 258 default: 259 return "kSecECCurveNone"; 260 } 261 } 262 263 static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key) 264 { 265 NSMutableString *strings[2]; 266 const char* curve = getCurveName(key); 267 268 ccec_pub_ctx_t ecPubkey = key->key; 269 size_t len = ccec_ctx_size(ecPubkey); 270 NSMutableData *buffer = [NSMutableData dataWithLength:len]; 271 for (int i = 0; i < 2; ++i) { 272 ccn_write_uint(ccec_ctx_n(ecPubkey), (i == 0) ? ccec_ctx_x(ecPubkey) : ccec_ctx_y(ecPubkey), len, buffer.mutableBytes); 273 strings[i] = [NSMutableString stringWithCapacity:len * 2]; 274 for (size_t byteIndex = 0; byteIndex < len; ++byteIndex) { 275 [strings[i] appendFormat:@"%02X", ((const uint8_t *)buffer.bytes)[byteIndex]]; 276 } 277 } 278 279 NSString *description = [NSString stringWithFormat:@"<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, y: %@, x: %@, addr: %p>", 280 curve, (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, 281 8 * SecKeyGetBlockSize(key), strings[1], strings[0], key]; 282 return CFBridgingRetain(description); 283 } 284 285 static const struct ccec_rfc6637_curve * get_rfc6637_curve(SecKeyRef key) 286 { 287 SecECNamedCurve curveType = SecECKeyGetNamedCurve(key); 288 289 if (curveType == kSecECCurveSecp256r1) { 290 return &ccec_rfc6637_dh_curve_p256; 291 } else if (curveType == kSecECCurveSecp521r1) { 292 return &ccec_rfc6637_dh_curve_p521; 293 } 294 return NULL; 295 } 296 297 static CFDataRef SecECKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) 298 { 299 ccec_pub_ctx_t pubkey = key->key; 300 int err = errSecUnimplemented; 301 const struct ccec_rfc6637_curve *curve; 302 const struct ccec_rfc6637_wrap *wrap = NULL; 303 uint8_t sym_alg = 0; 304 int32_t flags = 0; 305 306 if (type != kSecKeyWrapPublicKeyPGP) { 307 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported key wrapping algorithm")); 308 return NULL; 309 } 310 311 curve = get_rfc6637_curve(key); 312 if (curve == NULL) { 313 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve")); 314 return NULL; 315 } 316 317 CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPSymAlg); 318 if (!isNumber(num) || !CFNumberGetValue(num, kCFNumberSInt8Type, &sym_alg)) { 319 SecError(errSecUnsupportedOperation, error, CFSTR("unknown symalg given")); 320 return NULL; 321 } 322 323 CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint); 324 if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) { 325 SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint")); 326 return NULL; 327 } 328 329 CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg); 330 if (wrapAlg == NULL) { 331 SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg")); 332 return NULL; 333 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) { 334 wrap = &ccec_rfc6637_wrap_sha256_kek_aes128; 335 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) { 336 wrap = &ccec_rfc6637_wrap_sha512_kek_aes256; 337 } else { 338 SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg")); 339 return NULL; 340 } 341 342 num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags); 343 if (isNumber(num)) { 344 if (!CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) { 345 SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num); 346 return NULL; 347 } 348 } else if (num) { 349 SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags")); 350 return NULL; 351 } 352 353 CFIndex unwrappedKey_size = CFDataGetLength(unwrappedKey); 354 355 CFIndex output_size = ccec_rfc6637_wrap_key_size(pubkey, flags, unwrappedKey_size); 356 if (output_size == 0) { 357 SecError(errSecUnsupportedOperation, error, CFSTR("can't wrap that key, can't build size")); 358 return NULL; 359 } 360 361 CFMutableDataRef data = CFDataCreateMutableWithScratch(NULL, output_size); 362 require_quiet(data, errOut); 363 364 err = ccec_rfc6637_wrap_key(pubkey, CFDataGetMutableBytePtr(data), flags, 365 sym_alg, CFDataGetLength(unwrappedKey), CFDataGetBytePtr(unwrappedKey), 366 curve, wrap, CFDataGetBytePtr(fingerprint), 367 ccrng_seckey); 368 if (err) { 369 SecError(errSecUnsupportedOperation, error, CFSTR("Failed to wrap key")); 370 CFReleaseNull(data); 371 } 372 373 errOut: 374 return data; 375 } 376 377 SecKeyDescriptor kSecECPublicKeyDescriptor = { 378 .version = kSecKeyDescriptorVersion, 379 .name = "ECPublicKey", 380 .extraBytes = ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)), 381 .init = SecECPublicKeyInit, 382 .destroy = SecECPublicKeyDestroy, 383 .blockSize = SecECPublicKeyBlockSize, 384 .copyDictionary = SecECPublicKeyCopyAttributeDictionary, 385 .copyExternalRepresentation = SecECPublicKeyCopyExternalRepresentation, 386 .describe = SecECPublicKeyCopyKeyDescription, 387 .getAlgorithmID = SecECKeyGetAlgorithmID, 388 .copyPublic = SecECPublicKeyCopyPublicOctets, 389 .copyWrapKey = SecECKeyCopyWrapKey, 390 .copyOperationResult = SecECPublicKeyCopyOperationResult, 391 }; 392 393 /* Public Key API functions. */ 394 SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator, 395 const uint8_t *keyData, CFIndex keyDataLength, 396 SecKeyEncoding encoding) { 397 return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData, 398 keyDataLength, encoding); 399 } 400 401 402 403 /* 404 * 405 * Private Key 406 * 407 */ 408 409 /* Private key static functions. */ 410 static void SecECPrivateKeyDestroy(SecKeyRef key) { 411 /* Zero out the public key */ 412 ccec_full_ctx_t fullkey = key->key; 413 414 if (ccec_ctx_cp(fullkey)) 415 cc_clear(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey); 416 } 417 418 419 static OSStatus SecECPrivateKeyInit(SecKeyRef key, 420 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { 421 ccec_full_ctx_t fullkey = key->key; 422 OSStatus err = errSecParam; 423 424 switch (encoding) { 425 case kSecKeyEncodingPkcs1: 426 { 427 /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */ 428 //err = ecc_import(keyData, keyDataLength, fullkey); 429 430 /* DER != PKCS#1, but we'll go along with it */ 431 const unsigned char *oid; 432 size_t n; 433 ccec_const_cp_t cp; 434 435 require_noerr_quiet(ccec_der_import_priv_keytype(keyDataLength, keyData, (ccoid_t*)&oid, &n), abort); 436 cp = ccec_cp_for_oid(oid); 437 if (cp == NULL) { 438 cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */, 439 ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL); 440 } 441 require_action_quiet(cp != NULL, abort, err = errSecDecode); 442 ccec_ctx_init(cp, fullkey); 443 444 require_noerr_quiet(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort); 445 err = errSecSuccess; 446 break; 447 } 448 case kSecKeyEncodingBytes: 449 { 450 ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength); 451 require_quiet(cp != NULL, abort); 452 453 ccec_ctx_init(cp, fullkey); 454 size_t pubSize = ccec_export_pub_size(ccec_ctx_pub(fullkey)); 455 456 require_quiet(pubSize < (size_t) keyDataLength, abort); 457 require_noerr_action_quiet(ccec_import_pub(cp, pubSize, keyData, ccec_ctx_pub(fullkey)), 458 abort, 459 err = errSecDecode); 460 461 462 keyData += pubSize; 463 keyDataLength -= pubSize; 464 465 cc_unit *k = ccec_ctx_k(fullkey); 466 require_noerr_action_quiet(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData), 467 abort, 468 err = errSecDecode); 469 470 err = errSecSuccess; 471 break; 472 473 } 474 case kSecGenerateKey: 475 { 476 CFDictionaryRef parameters = (CFDictionaryRef) keyData; 477 478 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits); 479 CFIndex keyLengthInBits = getIntValue(ksize); 480 481 ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits); 482 483 if (!cp) { 484 secwarning("Invalid or missing key size in: %@", parameters); 485 return errSecKeySizeNotAllowed; 486 } 487 488 if (!ccec_generate_key_fips(cp, ccrng_seckey, fullkey)) 489 err = errSecSuccess; 490 break; 491 } 492 493 default: 494 break; 495 } 496 abort: 497 return err; 498 } 499 500 static CFTypeRef SecECPrivateKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, 501 CFArrayRef allAlgorithms, SecKeyOperationMode mode, 502 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { 503 // Default answer is 'unsupported', unless we find out that we can support it. 504 CFTypeRef result = kCFNull; 505 506 ccec_full_ctx_t fullkey = key->key; 507 switch (operation) { 508 case kSecKeyOperationTypeSign: { 509 if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) { 510 if (mode == kSecKeyOperationModePerform) { 511 // Perform x962 mode of signature. 512 size_t size = ccec_sign_max_size(ccec_ctx_cp(fullkey)); 513 result = CFDataCreateMutableWithScratch(NULL, size); 514 int err = ccec_sign(fullkey, CFDataGetLength(in1), CFDataGetBytePtr(in1), 515 &size, CFDataGetMutableBytePtr((CFMutableDataRef)result), ccrng_seckey); 516 require_action_quiet(err == 0, out, (CFReleaseNull(result), 517 SecError(errSecParam, error, CFSTR("%@: X962 signing failed (ccerr %d)"), 518 key, err))); 519 CFDataSetLength((CFMutableDataRef)result, size); 520 } else { 521 // Operation is supported. 522 result = kCFBooleanTrue; 523 } 524 } 525 break; 526 } 527 case kSecKeyOperationTypeKeyExchange: 528 if (CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeStandard) || 529 CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactor)) { 530 if (mode == kSecKeyOperationModePerform) { 531 int err; 532 ccec_const_cp_t cp = getCPForPublicSize(CFDataGetLength(in1)); 533 require_action_quiet(cp != NULL, out, 534 SecError(errSecParam, error, CFSTR("ECpriv sharedsecret: bad public key"))); 535 ccec_pub_ctx_decl_cp(cp, pubkey); 536 err = ccec_import_pub(cp, CFDataGetLength(in1), CFDataGetBytePtr(in1), pubkey); 537 require_noerr_action_quiet(err, out, SecError(errSecParam, error, 538 CFSTR("ECpriv sharedsecret: bad public key (err %d)"), err)); 539 size_t size = ccec_ccn_size(cp); 540 result = CFDataCreateMutableWithScratch(NULL, size); 541 err = ccecdh_compute_shared_secret(fullkey, pubkey, &size, 542 CFDataGetMutableBytePtr((CFMutableDataRef)result), ccrng_seckey); 543 require_noerr_action_quiet(err, out, (CFReleaseNull(result), 544 SecError(errSecDecode, error, 545 CFSTR("ECpriv failed to compute shared secret (err %d)"), err))); 546 CFDataSetLength((CFMutableDataRef)result, size); 547 } else { 548 // Operation is supported. 549 result = kCFBooleanTrue; 550 } 551 } 552 break; 553 default: 554 break; 555 } 556 557 out: 558 return result; 559 } 560 561 static size_t SecECPrivateKeyBlockSize(SecKeyRef key) { 562 ccec_full_ctx_t fullkey = key->key; 563 /* Get key size in octets */ 564 return ccec_ctx_size(fullkey); 565 } 566 567 static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation) 568 { 569 ccec_full_ctx_t fullkey = key->key; 570 571 CFAllocatorRef allocator = CFGetAllocator(key); 572 *serailziation = SecECPublicKeyExport(allocator, ccec_ctx_pub(fullkey)); 573 574 if (NULL == *serailziation) 575 return errSecDecode; 576 else 577 return errSecSuccess; 578 } 579 580 static CFDataRef SecECPrivateKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { 581 ccec_full_ctx_t fullkey = key->key; 582 size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey)); 583 size_t key_size = ccec_export_pub_size(ccec_ctx_pub(fullkey)) + prime_size; 584 CFMutableDataRef blob = CFDataCreateMutableWithScratch(NULL, key_size); 585 ccec_export_pub(ccec_ctx_pub(fullkey), CFDataGetMutableBytePtr(blob)); 586 UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(ccec_ctx_pub(fullkey)); 587 const cc_unit *k = ccec_ctx_k(fullkey); 588 ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest); 589 return blob; 590 } 591 592 static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) { 593 /* Export the full ec key pair. */ 594 CFDataRef fullKeyBlob = SecECPrivateKeyCopyExternalRepresentation(key, NULL); 595 596 CFDictionaryRef dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob); 597 CFReleaseSafe(fullKeyBlob); 598 return dict; 599 } 600 static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) { 601 602 const char* curve = getCurveName(key); 603 604 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); 605 606 } 607 608 static CFDataRef SecECKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) 609 { 610 const struct ccec_rfc6637_curve *curve; 611 const struct ccec_rfc6637_unwrap *unwrap; 612 ccec_full_ctx_t fullkey = key->key; 613 CFMutableDataRef data; 614 int res; 615 uint8_t sym_alg = 0; 616 int32_t flags = 0; 617 618 curve = get_rfc6637_curve(key); 619 if (curve == NULL) { 620 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve")); 621 return NULL; 622 } 623 624 CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg); 625 if (wrapAlg == NULL) { 626 SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg")); 627 return NULL; 628 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) { 629 unwrap = &ccec_rfc6637_unwrap_sha256_kek_aes128; 630 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) { 631 unwrap = &ccec_rfc6637_unwrap_sha512_kek_aes256; 632 } else { 633 SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg")); 634 return NULL; 635 } 636 637 CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint); 638 if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) { 639 SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint")); 640 return NULL; 641 } 642 643 CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags); 644 if (isNumber(num)) { 645 if (!CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) { 646 SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num); 647 return NULL; 648 } 649 } else if (num) { 650 SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags")); 651 return NULL; 652 } 653 654 size_t keysize = CFDataGetLength(wrappedKey); 655 data = CFDataCreateMutableWithScratch(NULL, keysize); 656 if (data == NULL) 657 return NULL; 658 659 res = ccec_rfc6637_unwrap_key(fullkey, &keysize, CFDataGetMutableBytePtr(data), 660 flags, &sym_alg, curve, unwrap, 661 CFDataGetBytePtr(fingerprint), 662 CFDataGetLength(wrappedKey), CFDataGetBytePtr(wrappedKey)); 663 if (res != 0) { 664 CFReleaseNull(data); 665 SecError(errSecUnsupportedOperation, error, CFSTR("failed to wrap key")); 666 return NULL; 667 } 668 assert(keysize <= (size_t)CFDataGetLength(data)); 669 CFDataSetLength(data, keysize); 670 671 if (outParam) { 672 CFMutableDictionaryRef out = CFDictionaryCreateMutableForCFTypes(NULL); 673 if (out) { 674 CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg); 675 if (num) { 676 CFDictionarySetValue(out, _kSecKeyWrapPGPSymAlg, num); 677 CFRelease(num); 678 } 679 *outParam = out; 680 } 681 } 682 683 return data; 684 } 685 686 SecKeyDescriptor kSecECPrivateKeyDescriptor = { 687 .version = kSecKeyDescriptorVersion, 688 .name = "ECPrivateKey", 689 .extraBytes = ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)), 690 691 .init = SecECPrivateKeyInit, 692 .destroy = SecECPrivateKeyDestroy, 693 .blockSize = SecECPrivateKeyBlockSize, 694 .copyDictionary = SecECPrivateKeyCopyAttributeDictionary, 695 .describe = SecECPrivateKeyCopyKeyDescription, 696 .getAlgorithmID = SecECKeyGetAlgorithmID, 697 .copyPublic = SecECPrivateKeyCopyPublicOctets, 698 .copyExternalRepresentation = SecECPrivateKeyCopyExternalRepresentation, 699 .copyWrapKey = SecECKeyCopyWrapKey, 700 .copyUnwrapKey = SecECKeyCopyUnwrapKey, 701 .copyOperationResult = SecECPrivateKeyCopyOperationResult, 702 }; 703 704 /* Private Key API functions. */ 705 SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator, 706 const uint8_t *keyData, CFIndex keyDataLength, 707 SecKeyEncoding encoding) { 708 return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData, 709 keyDataLength, encoding); 710 } 711 712 713 OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters, 714 SecKeyRef *publicKey, SecKeyRef *privateKey) { 715 OSStatus status = errSecParam; 716 717 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */ 718 SecKeyRef pubKey = NULL; 719 720 SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, 721 (const void*) parameters, 0, kSecGenerateKey); 722 723 require_quiet(privKey, errOut); 724 725 /* Create SecKeyRef's from the pkcs1 encoded keys. */ 726 pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, 727 privKey->key, 0, kSecExtractPublicFromPrivate); 728 729 require_quiet(pubKey, errOut); 730 731 if (publicKey) { 732 *publicKey = pubKey; 733 pubKey = NULL; 734 } 735 if (privateKey) { 736 *privateKey = privKey; 737 privKey = NULL; 738 } 739 740 status = errSecSuccess; 741 742 errOut: 743 CFReleaseSafe(pubKey); 744 CFReleaseSafe(privKey); 745 746 return status; 747 } 748 749 750 /* It's debatable whether this belongs here or in the ssl code since the 751 curve values come from a tls related rfc4492. */ 752 SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) { 753 SecECNamedCurve result = kSecECCurveNone; 754 CFDictionaryRef attributes = NULL; 755 require_quiet(SecKeyGetAlgorithmId(key) == kSecECDSAAlgorithmID, out); 756 require_quiet(attributes = SecKeyCopyAttributes(key), out); 757 CFTypeRef bitsRef = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits); 758 CFIndex bits = 0; 759 require_quiet(bitsRef != NULL && CFGetTypeID(bitsRef) == CFNumberGetTypeID() && 760 CFNumberGetValue(bitsRef, kCFNumberCFIndexType, &bits), out); 761 switch (bits) { 762 #if 0 763 case 192: 764 result = kSecECCurveSecp192r1; 765 break; 766 case 224: 767 result = kSecECCurveSecp224r1; 768 break; 769 #endif 770 case 256: 771 result = kSecECCurveSecp256r1; 772 break; 773 case 384: 774 result = kSecECCurveSecp384r1; 775 break; 776 case 521: 777 result = kSecECCurveSecp521r1; 778 break; 779 } 780 781 out: 782 CFReleaseSafe(attributes); 783 return result; 784 } 785 786 CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) { 787 CFDataRef bytes = NULL; 788 SecKeyCopyPublicBytes(key, &bytes); 789 return bytes; 790 } 791 792 /* Vile accessors that get us the pub or priv key to use temporarily */ 793 794 bool SecECDoWithFullKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_full_ctx_t private)) { 795 if (key->key_class == &kSecECPrivateKeyDescriptor) { 796 action(key->key); 797 } else { 798 return SecError(errSecParam, error, CFSTR("Not an EC Full Key object, sorry can't do.")); 799 } 800 801 return true; 802 } 803 804 bool SecECDoWithPubKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_pub_ctx_t public)) { 805 if (key->key_class == &kSecECPublicKeyDescriptor) { 806 action(key->key); 807 } else { 808 return SecError(errSecParam, error, CFSTR("Not an EC Public Key object, sorry can't do.")); 809 } 810 811 return true; 812 } 813