SecKey.m
1 /* 2 * Copyright (c) 2006-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 * SecKey.m - CoreFoundation based key object 26 */ 27 #include <AssertMacros.h> 28 #include <Security/SecBase.h> 29 30 #include <Security/SecKeyInternal.h> 31 #include <Security/SecItem.h> 32 #include <Security/SecItemPriv.h> 33 #include <Security/SecItemShim.h> 34 #include <Security/SecFramework.h> 35 #include <Security/SecCertificate.h> 36 37 #include <utilities/SecIOFormat.h> 38 39 #include <utilities/SecCFWrappers.h> 40 #include <utilities/array_size.h> 41 42 #include <Security/SecKeyPriv.h> 43 #include "SecRSAKeyPriv.h" 44 #include "SecECKeyPriv.h" 45 #include "SecCTKKeyPriv.h" 46 #include <Security/SecBasePriv.h> 47 48 #include <CoreFoundation/CFNumber.h> 49 #include <CoreFoundation/CFString.h> 50 #include <CoreFoundation/CFPriv.h> 51 #include <pthread.h> 52 #include <string.h> 53 #include <utilities/debugging.h> 54 #include <utilities/SecCFError.h> 55 #include <CommonCrypto/CommonDigest.h> 56 #include <Security/SecAsn1Coder.h> 57 #include <Security/oidsalg.h> 58 #include <Security/SecInternal.h> 59 #include <Security/SecRandom.h> 60 #include <Security/SecureTransport.h> /* For error codes. */ 61 62 #include <corecrypto/ccrng_system.h> 63 #include <corecrypto/ccsha1.h> 64 #include <corecrypto/ccsha2.h> 65 66 #include <asl.h> 67 #include <stdlib.h> 68 #include <os/lock.h> 69 70 #include <libDER/asn1Types.h> 71 #include <libDER/DER_Keys.h> 72 #include <libDER/DER_Encode.h> 73 74 CFDataRef SecKeyCopyPublicKeyHash(SecKeyRef key) 75 { 76 CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL; 77 78 /* encode the public key. */ 79 require_noerr_quiet(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut); 80 require_quiet(pubKeyBlob, errOut); 81 82 /* Calculate the digest of the public key. */ 83 require_quiet(pubKeyDigest = SecSHA1DigestCreate(CFGetAllocator(key), 84 CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)), 85 errOut); 86 errOut: 87 CFReleaseNull(pubKeyBlob); 88 return pubKeyDigest; 89 } 90 91 92 /* 93 */ 94 static CFDictionaryRef SecKeyCopyAttributeDictionaryWithLocalKey(SecKeyRef key, 95 CFTypeRef keyType, 96 CFDataRef privateBlob) 97 { 98 CFAllocatorRef allocator = CFGetAllocator(key); 99 DICT_DECLARE(25); 100 CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL; 101 CFDictionaryRef dict = NULL; 102 103 size_t sizeValue = SecKeyGetSize(key, kSecKeyKeySizeInBits); 104 CFNumberRef sizeInBits = CFNumberCreate(allocator, kCFNumberLongType, &sizeValue); 105 106 /* encode the public key. */ 107 require_noerr_quiet(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut); 108 require_quiet(pubKeyBlob, errOut); 109 110 /* Calculate the digest of the public key. */ 111 require_quiet(pubKeyDigest = SecSHA1DigestCreate(allocator, 112 CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)), 113 errOut); 114 115 DICT_ADDPAIR(kSecClass, kSecClassKey); 116 DICT_ADDPAIR(kSecAttrKeyClass, privateBlob ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic); 117 DICT_ADDPAIR(kSecAttrApplicationLabel, pubKeyDigest); 118 DICT_ADDPAIR(kSecAttrIsPermanent, kCFBooleanTrue); 119 DICT_ADDPAIR(kSecAttrIsPrivate, kCFBooleanTrue); 120 DICT_ADDPAIR(kSecAttrIsModifiable, kCFBooleanTrue); 121 DICT_ADDPAIR(kSecAttrKeyType, keyType); 122 DICT_ADDPAIR(kSecAttrKeySizeInBits, sizeInBits); 123 DICT_ADDPAIR(kSecAttrEffectiveKeySize, sizeInBits); 124 DICT_ADDPAIR(kSecAttrIsSensitive, kCFBooleanFalse); 125 DICT_ADDPAIR(kSecAttrWasAlwaysSensitive, kCFBooleanFalse); 126 DICT_ADDPAIR(kSecAttrIsExtractable, kCFBooleanTrue); 127 DICT_ADDPAIR(kSecAttrWasNeverExtractable, kCFBooleanFalse); 128 DICT_ADDPAIR(kSecAttrCanEncrypt, privateBlob ? kCFBooleanFalse : kCFBooleanTrue); 129 DICT_ADDPAIR(kSecAttrCanDecrypt, privateBlob ? kCFBooleanTrue : kCFBooleanFalse); 130 DICT_ADDPAIR(kSecAttrCanDerive, kCFBooleanTrue); 131 DICT_ADDPAIR(kSecAttrCanSign, privateBlob ? kCFBooleanTrue : kCFBooleanFalse); 132 DICT_ADDPAIR(kSecAttrCanVerify, privateBlob ? kCFBooleanFalse : kCFBooleanTrue); 133 DICT_ADDPAIR(kSecAttrCanSignRecover, kCFBooleanFalse); 134 DICT_ADDPAIR(kSecAttrCanVerifyRecover, kCFBooleanFalse); 135 DICT_ADDPAIR(kSecAttrCanWrap, privateBlob ? kCFBooleanFalse : kCFBooleanTrue); 136 DICT_ADDPAIR(kSecAttrCanUnwrap, privateBlob ? kCFBooleanTrue : kCFBooleanFalse); 137 DICT_ADDPAIR(kSecValueData, privateBlob ? privateBlob : pubKeyBlob); 138 dict = CFDictionaryCreate(allocator, keys, values, numValues, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 139 140 errOut: 141 // @@@ Zero out key material. 142 CFReleaseSafe(pubKeyDigest); 143 CFReleaseSafe(pubKeyBlob); 144 CFReleaseSafe(sizeInBits); 145 146 return dict; 147 } 148 149 CFDictionaryRef SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key, 150 CFTypeRef keyType, 151 CFDataRef privateBlob) 152 { 153 return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, privateBlob); 154 } 155 156 CFDictionaryRef SecKeyGeneratePublicAttributeDictionary(SecKeyRef key, CFTypeRef keyType) 157 { 158 return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, NULL); 159 } 160 161 static CFStringRef SecKeyCopyDescription(CFTypeRef cf) { 162 SecKeyRef key = (SecKeyRef)cf; 163 164 if(key->key_class->describe) 165 return key->key_class->describe(key); 166 else 167 return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef: %p>"), key); 168 } 169 170 #if TARGET_OS_OSX 171 static CFMutableDictionaryRef auxilliaryCDSAKeyMap; 172 static struct os_unfair_lock_s auxilliaryCDSAKeyMapLock = OS_UNFAIR_LOCK_INIT; 173 174 static void SecKeyDestroyAuxilliaryCDSAKeyForKey(CFTypeRef cf) { 175 CFTypeRef keyToDestroy = NULL; 176 os_unfair_lock_lock(&auxilliaryCDSAKeyMapLock); 177 if (auxilliaryCDSAKeyMap != NULL) { 178 keyToDestroy = CFDictionaryGetValue(auxilliaryCDSAKeyMap, cf); 179 if (keyToDestroy != NULL) { 180 CFRetain(keyToDestroy); 181 CFDictionaryRemoveValue(auxilliaryCDSAKeyMap, cf); 182 } 183 } 184 os_unfair_lock_unlock(&auxilliaryCDSAKeyMapLock); 185 186 // Actual aux key destruction is performed outside unfair lock to avoid recursive lock. 187 if (keyToDestroy != NULL) { 188 CFRelease(keyToDestroy); 189 } 190 } 191 192 void SecKeySetAuxilliaryCDSAKeyForKey(SecKeyRef cf, SecKeyRef auxKey) { 193 os_unfair_lock_lock(&auxilliaryCDSAKeyMapLock); 194 if (auxilliaryCDSAKeyMap == NULL) { 195 // Allocate map with weak (unretained) keys (which are source SecKeys) but strong values (which are held aux CDSA keys). 196 auxilliaryCDSAKeyMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); 197 } 198 CFDictionarySetValue(auxilliaryCDSAKeyMap, cf, auxKey); 199 os_unfair_lock_unlock(&auxilliaryCDSAKeyMapLock); 200 } 201 202 SecKeyRef SecKeyCopyAuxilliaryCDSAKeyForKey(SecKeyRef cf) { 203 os_unfair_lock_lock(&auxilliaryCDSAKeyMapLock); 204 if (auxilliaryCDSAKeyMap == NULL) { 205 os_unfair_lock_unlock(&auxilliaryCDSAKeyMapLock); 206 return NULL; 207 } 208 SecKeyRef result = (SecKeyRef)CFRetainSafe(CFDictionaryGetValue(auxilliaryCDSAKeyMap, cf)); 209 os_unfair_lock_unlock(&auxilliaryCDSAKeyMapLock); 210 return result; 211 } 212 #endif 213 214 static void SecKeyDestroy(CFTypeRef cf) { 215 SecKeyRef key = (SecKeyRef)cf; 216 #if TARGET_OS_OSX 217 SecKeyDestroyAuxilliaryCDSAKeyForKey(cf); 218 #endif 219 if (key->key_class->destroy) 220 key->key_class->destroy(key); 221 } 222 223 static Boolean SecKeyEqual(CFTypeRef cf1, CFTypeRef cf2) 224 { 225 SecKeyRef key1 = (SecKeyRef)cf1; 226 SecKeyRef key2 = (SecKeyRef)cf2; 227 if (key1 == key2) 228 return true; 229 if (!key2 || key1->key_class != key2->key_class) 230 return false; 231 if (key1->key_class->version >= 4 && key1->key_class->isEqual) 232 return key1->key_class->isEqual(key1, key2); 233 if (key1->key_class->extraBytes) 234 return !memcmp(key1->key, key2->key, key1->key_class->extraBytes); 235 236 /* TODO: Won't work when we get reference keys. */ 237 CFDictionaryRef d1, d2; 238 d1 = SecKeyCopyAttributeDictionary(key1); 239 d2 = SecKeyCopyAttributeDictionary(key2); 240 // Returning NULL is an error; bail out of the equality check 241 if(!d1 || !d2) { 242 CFReleaseSafe(d1); 243 CFReleaseSafe(d2); 244 return false; 245 } 246 Boolean result = CFEqual(d1, d2); 247 CFReleaseSafe(d1); 248 CFReleaseSafe(d2); 249 return result; 250 } 251 252 struct ccrng_state *ccrng_seckey; 253 254 CFGiblisWithFunctions(SecKey, NULL, NULL, SecKeyDestroy, SecKeyEqual, NULL, NULL, SecKeyCopyDescription, NULL, NULL, ^{ 255 static struct ccrng_system_state ccrng_system_state_seckey; 256 ccrng_seckey = (struct ccrng_state *)&ccrng_system_state_seckey; 257 ccrng_system_init(&ccrng_system_state_seckey); 258 }) 259 260 static bool getBoolForKey(CFDictionaryRef dict, CFStringRef key, bool default_value) { 261 CFTypeRef value = CFDictionaryGetValue(dict, key); 262 if (value) { 263 if (CFGetTypeID(value) == CFBooleanGetTypeID()) { 264 return CFBooleanGetValue(value); 265 } else { 266 secwarning("Value %@ for key %@ is not bool", value, key); 267 } 268 } 269 270 return default_value; 271 } 272 273 static OSStatus add_key(SecKeyRef key, CFMutableDictionaryRef dict) { 274 CFDictionarySetValue(dict, kSecValueRef, key); 275 CFDictionaryRef keyAttributes = SecKeyCopyAttributes(key); 276 if (keyAttributes != NULL && CFDictionaryContainsKey(keyAttributes, kSecAttrAccessControl)) { 277 // Avoid overriding ACL from the key with source ACL of the call; ACL of the key might be already processed during key generation and should be preferred to source unprocessed ACL. 278 CFDictionaryRemoveValue(dict, kSecAttrAccessControl); 279 } 280 CFReleaseNull(keyAttributes); 281 return SecItemAdd(dict, NULL); 282 } 283 284 static void merge_params_applier(const void *key, const void *value, 285 void *context) { 286 CFMutableDictionaryRef result = (CFMutableDictionaryRef)context; 287 CFDictionaryAddValue(result, key, value); 288 } 289 290 /* Create a mutable dictionary that is based on the subdictionary for key 291 with any attributes from the top level dict merged in. */ 292 static CF_RETURNS_RETAINED CFMutableDictionaryRef merge_params(CFDictionaryRef dict, 293 CFStringRef key) { 294 CFDictionaryRef subdict = CFDictionaryGetValue(dict, key); 295 CFMutableDictionaryRef result; 296 297 if (subdict) { 298 result = CFDictionaryCreateMutableCopy(NULL, 0, subdict); 299 /* Add everything in dict not already in result to result. */ 300 CFDictionaryApplyFunction(dict, merge_params_applier, result); 301 } else { 302 result = CFDictionaryCreateMutableCopy(NULL, 0, dict); 303 } 304 305 /* Remove values that only belong in the top level dict. */ 306 CFDictionaryRemoveValue(result, kSecPublicKeyAttrs); 307 CFDictionaryRemoveValue(result, kSecPrivateKeyAttrs); 308 CFDictionaryRemoveValue(result, kSecAttrKeyType); 309 CFDictionaryRemoveValue(result, kSecAttrKeySizeInBits); 310 311 return result; 312 } 313 314 CFIndex SecKeyGetAlgorithmId(SecKeyRef key) { 315 if (!key || !key->key_class) { 316 // TBD: somehow, a key can be created with a NULL key_class in the 317 // SecCertificateCopyPublicKey -> SecKeyCreatePublicFromDER code path 318 return kSecNullAlgorithmID; 319 } 320 /* This method was added to version 1 keys. */ 321 if (key->key_class->version > 0 && key->key_class->getAlgorithmID) { 322 return key->key_class->getAlgorithmID(key); 323 } 324 /* All version 0 keys were RSA. */ 325 return kSecRSAAlgorithmID; 326 } 327 328 /* Generate a private/public keypair. */ 329 OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, 330 SecKeyRef *publicKey, SecKeyRef *privateKey) { 331 @autoreleasepool { 332 OSStatus result = errSecUnsupportedAlgorithm; 333 SecKeyRef privKey = NULL; 334 SecKeyRef pubKey = NULL; 335 CFMutableDictionaryRef pubParams = merge_params(parameters, kSecPublicKeyAttrs), 336 privParams = merge_params(parameters, kSecPrivateKeyAttrs); 337 CFStringRef ktype = CFDictionaryGetValue(parameters, kSecAttrKeyType); 338 CFStringRef tokenID = CFDictionaryGetValue(parameters, kSecAttrTokenID); 339 340 require_quiet(ktype, errOut); 341 342 if (tokenID != NULL) { 343 result = SecCTKKeyGeneratePair(parameters, &pubKey, &privKey); 344 } else if (CFEqual(ktype, kSecAttrKeyTypeECSECPrimeRandom)) { 345 result = SecECKeyGeneratePair(parameters, &pubKey, &privKey); 346 } else if (CFEqual(ktype, kSecAttrKeyTypeRSA)) { 347 result = SecRSAKeyGeneratePair(parameters, &pubKey, &privKey); 348 } 349 350 require_noerr_quiet(result, errOut); 351 352 // Store the keys in the keychain if they are marked as permanent. Governed by kSecAttrIsPermanent attribute, with default 353 // to 'false' (ephemeral keys), except private token-based keys, in which case the default is 'true' (permanent keys). 354 if (getBoolForKey(pubParams, kSecAttrIsPermanent, false)) { 355 CFDictionaryRemoveValue(pubParams, kSecAttrTokenID); 356 require_noerr_quiet(result = add_key(pubKey, pubParams), errOut); 357 } 358 if (getBoolForKey(privParams, kSecAttrIsPermanent, CFDictionaryContainsKey(privParams, kSecAttrTokenID))) { 359 require_noerr_quiet(result = add_key(privKey, privParams), errOut); 360 } 361 362 if (publicKey) { 363 *publicKey = pubKey; 364 pubKey = NULL; 365 } 366 if (privateKey) { 367 *privateKey = privKey; 368 privKey = NULL; 369 } 370 371 errOut: 372 CFReleaseSafe(pubParams); 373 CFReleaseSafe(privParams); 374 CFReleaseSafe(pubKey); 375 CFReleaseSafe(privKey); 376 377 return result; 378 } 379 } 380 381 SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey) { 382 return SecKeyCopyPublicKey(privateKey); 383 } 384 385 CFDictionaryRef CreatePrivateKeyMatchingQuery(SecKeyRef publicKey, bool returnPersistentRef) 386 { 387 const CFTypeRef refType = (returnPersistentRef) ? kSecReturnPersistentRef: kSecReturnRef; 388 389 CFDataRef public_key_hash = SecKeyCopyPublicKeyHash(publicKey); 390 391 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, 392 kSecClass, kSecClassKey, 393 kSecAttrKeyClass, kSecAttrKeyClassPrivate, 394 kSecAttrSynchronizable, kSecAttrSynchronizableAny, 395 kSecAttrApplicationLabel, public_key_hash, 396 refType, kCFBooleanTrue, 397 NULL); 398 CFReleaseNull(public_key_hash); 399 400 return query; 401 } 402 403 CFDataRef SecKeyCreatePersistentRefToMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error) { 404 CFTypeRef persistentRef = NULL; 405 CFDictionaryRef query = CreatePrivateKeyMatchingQuery(publicKey, true); 406 407 require_quiet(SecError(SecItemCopyMatching(query, &persistentRef),error , 408 CFSTR("Error finding persistent ref to key from public: %@"), publicKey), fail); 409 fail: 410 CFReleaseNull(query); 411 return (CFDataRef)persistentRef; 412 } 413 414 SecKeyRef SecKeyCopyMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error) { 415 SecKeyRef privateKey = NULL; 416 CFTypeRef queryResult = NULL; 417 CFDictionaryRef query = NULL; 418 419 require_action_quiet(publicKey != NULL, errOut, SecError(errSecParam, error, CFSTR("Null Public Key"))); 420 421 query = CreatePrivateKeyMatchingQuery(publicKey, false); 422 423 require_quiet(SecError(SecItemCopyMatching(query, &queryResult), error, 424 CFSTR("Error finding private key from public: %@"), publicKey), errOut); 425 426 if (CFGetTypeID(queryResult) == SecKeyGetTypeID()) { 427 privateKey = (SecKeyRef) queryResult; 428 queryResult = NULL; 429 } 430 431 errOut: 432 CFReleaseNull(query); 433 CFReleaseNull(queryResult); 434 return privateKey; 435 } 436 437 OSStatus SecKeyGetMatchingPrivateKeyStatus(SecKeyRef publicKey, CFErrorRef *error) { 438 OSStatus retval = errSecParam; 439 CFTypeRef private_key = NULL; 440 CFDictionaryRef query = NULL; 441 442 require_action_quiet(publicKey != NULL, errOut, SecError(errSecParam, error, NULL, CFSTR("Null Public Key"))); 443 444 query = CreatePrivateKeyMatchingQuery(publicKey, false); 445 446 retval = SecItemCopyMatching(query, &private_key); 447 448 if (!retval && CFGetTypeID(private_key) != SecKeyGetTypeID()) { 449 retval = errSecInternalComponent; 450 } 451 452 errOut: 453 CFReleaseNull(query); 454 CFReleaseNull(private_key); 455 return retval; 456 } 457 458 459 SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator, 460 const SecAsn1Oid *oid, const SecAsn1Item *params, 461 const SecAsn1Item *keyData) { 462 SecKeyRef publicKey = NULL; 463 if (SecAsn1OidCompare(oid, &CSSMOID_RSA)) { 464 /* pkcs1 1 */ 465 /* Note that we call SecKeyCreateRSAPublicKey_ios directly instead of 466 SecKeyCreateRSAPublicKey, since on OS X the latter function will return 467 a CSSM SecKeyRef, and we always want an iOS format SecKeyRef here. 468 */ 469 publicKey = SecKeyCreateRSAPublicKey_ios(allocator, 470 keyData->Data, keyData->Length, kSecKeyEncodingPkcs1); 471 } else if (SecAsn1OidCompare(oid, &CSSMOID_ecPublicKey)) { 472 SecDERKey derKey = { 473 .oid = oid->Data, 474 .oidLength = oid->Length, 475 .key = keyData->Data, 476 .keyLength = keyData->Length, 477 }; 478 if (params) { 479 derKey.parameters = params->Data; 480 derKey.parametersLength = params->Length; 481 } 482 publicKey = SecKeyCreateECPublicKey(allocator, 483 (const uint8_t *)&derKey, sizeof(derKey), kSecDERKeyEncoding); 484 } else { 485 secwarning("Unsupported algorithm oid"); 486 } 487 488 return publicKey; 489 } 490 491 492 SecKeyRef SecKeyCreateFromSubjectPublicKeyInfoData(CFAllocatorRef allocator, CFDataRef subjectPublicKeyInfoData) 493 { 494 DERReturn drtn; 495 496 DERItem subjectPublicKeyInfoDER = { 497 .data = (uint8_t *)CFDataGetBytePtr(subjectPublicKeyInfoData), 498 .length = (DERSize)CFDataGetLength(subjectPublicKeyInfoData), 499 }; 500 DERSubjPubKeyInfo subjectPublicKeyInfo; 501 DERAlgorithmId algorithmId; 502 DERItem pubKeyBytes; 503 504 drtn = DERParseSequence(&subjectPublicKeyInfoDER, 505 DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, 506 &subjectPublicKeyInfo, sizeof(subjectPublicKeyInfo)); 507 508 require_noerr_quiet(drtn, out); 509 510 drtn = DERParseSequenceContent(&subjectPublicKeyInfo.algId, 511 DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, 512 &algorithmId, sizeof(algorithmId)); 513 require_noerr_quiet(drtn, out); 514 515 DERByte unusedBits; 516 drtn = DERParseBitString(&subjectPublicKeyInfo.pubKey, &pubKeyBytes, &unusedBits); 517 require_noerr_quiet(drtn, out); 518 519 /* Convert DERItem to SecAsn1Item : */ 520 const SecAsn1Oid oid = { .Data = algorithmId.oid.data, .Length = algorithmId.oid.length }; 521 const SecAsn1Item params = { .Data = algorithmId.params.data, .Length = algorithmId.params.length }; 522 const SecAsn1Item pubKey = { .Data = pubKeyBytes.data, .Length = pubKeyBytes.length }; 523 524 return SecKeyCreatePublicFromDER(allocator, &oid, ¶ms, &pubKey); 525 526 out: 527 528 return NULL; 529 } 530 531 static const DERByte oidRSA[] = { 532 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 533 }; 534 static const DERByte oidECsecp256[] = { 535 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 536 }; 537 static const DERByte oidECsecp384[] = { 538 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 539 }; 540 static const DERByte oidECsecp521[] = { 541 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 542 }; 543 544 545 CFDataRef SecKeyCopySubjectPublicKeyInfo(SecKeyRef key) 546 { 547 CFMutableDataRef data = NULL; 548 CFDataRef publicKey = NULL; 549 CFDataRef dataret = NULL; 550 DERSubjPubKeyInfo spki; 551 DERReturn drtn; 552 size_t zeroPad = 0; 553 554 memset(&spki, 0, sizeof(spki)); 555 556 /* encode the public key. */ 557 require_noerr_quiet(SecKeyCopyPublicBytes(key, &publicKey), errOut); 558 require_quiet(publicKey, errOut); 559 560 require_quiet(CFDataGetLength(publicKey) != 0, errOut); 561 562 // Add prefix 00 is needed to avoid creating negative bit strings 563 if (((uint8_t *)CFDataGetBytePtr(publicKey))[0] & 0x80) 564 zeroPad = 1; 565 566 567 CFMutableDataRef paddedKey = CFDataCreateMutable(NULL, 0); 568 /* the bit strings bits used field first */ 569 CFDataAppendBytes(paddedKey, (const UInt8 *)"\x00", 1); 570 if (zeroPad) 571 CFDataAppendBytes(paddedKey, (const UInt8 *)"\x00", 1); 572 573 CFDataAppendBytes(paddedKey, CFDataGetBytePtr(publicKey), CFDataGetLength(publicKey)); 574 CFTransferRetained(publicKey, paddedKey); 575 576 spki.pubKey.data = (DERByte *)CFDataGetBytePtr(publicKey); 577 spki.pubKey.length = CFDataGetLength(publicKey); 578 579 // Encode algId according to algorithm used. 580 CFIndex algorithm = SecKeyGetAlgorithmId(key); 581 if (algorithm == kSecRSAAlgorithmID) { 582 spki.algId.data = (DERByte *)oidRSA; 583 spki.algId.length = sizeof(oidRSA); 584 } else if (algorithm == kSecECDSAAlgorithmID) { 585 SecECNamedCurve curve = SecECKeyGetNamedCurve(key); 586 switch(curve) { 587 case kSecECCurveSecp256r1: 588 spki.algId.data = (DERByte *)oidECsecp256; 589 spki.algId.length = sizeof(oidECsecp256); 590 break; 591 case kSecECCurveSecp384r1: 592 spki.algId.data = (DERByte *)oidECsecp384; 593 spki.algId.length = sizeof(oidECsecp384); 594 break; 595 case kSecECCurveSecp521r1: 596 spki.algId.data = (DERByte *)oidECsecp521; 597 spki.algId.length = sizeof(oidECsecp521); 598 break; 599 default: 600 goto errOut; 601 } 602 } else { 603 goto errOut; 604 } 605 606 DERSize size = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, &spki, 607 DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs); 608 data = CFDataCreateMutable(kCFAllocatorDefault, size); 609 CFDataSetLength(data, size); 610 611 drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &spki, 612 DERNumSubjPubKeyInfoItemSpecs, 613 DERSubjPubKeyInfoItemSpecs, 614 CFDataGetMutableBytePtr(data), &size); 615 require_quiet(drtn == DR_Success, errOut); 616 CFDataSetLength(data, size); 617 618 dataret = CFRetain(data); 619 errOut: 620 CFReleaseNull(data); 621 CFReleaseNull(publicKey); 622 623 return dataret; 624 } 625 626 627 628 SecKeyRef SecKeyCreate(CFAllocatorRef allocator, 629 const SecKeyDescriptor *key_class, const uint8_t *keyData, 630 CFIndex keyDataLength, SecKeyEncoding encoding) { 631 if (!key_class) return NULL; 632 size_t size = sizeof(struct __SecKey) + key_class->extraBytes; 633 SecKeyRef result = (SecKeyRef)_CFRuntimeCreateInstance(allocator, 634 SecKeyGetTypeID(), size - sizeof(CFRuntimeBase), NULL); 635 if (result) { 636 memset((char*)result + sizeof(result->_base), 0, size - sizeof(result->_base)); 637 result->key_class = key_class; 638 if (key_class->extraBytes) { 639 /* Make result->key point to the extraBytes we allocated. */ 640 result->key = ((char*)result) + sizeof(*result); 641 } 642 if (key_class->init) { 643 OSStatus status; 644 status = key_class->init(result, keyData, keyDataLength, encoding); 645 if (status) { 646 secwarning("init %s key: %" PRIdOSStatus, key_class->name, status); 647 CFRelease(result); 648 result = NULL; 649 } 650 } 651 } 652 return result; 653 } 654 655 // Generic wrapper helper for invoking new-style CFDataRef-based operations with ptr/length arguments 656 // used by legacy RawSign-style functions. 657 static OSStatus SecKeyPerformLegacyOperation(SecKeyRef key, 658 const uint8_t *in1Ptr, size_t in1Len, 659 const uint8_t *in2Ptr, size_t in2Len, 660 uint8_t *outPtr, size_t *outLen, 661 CFTypeRef (^operation)(CFDataRef in1, CFDataRef in2, CFRange *resultRange, CFErrorRef *error)) { 662 CFErrorRef error = NULL; 663 OSStatus status = errSecSuccess; 664 CFDataRef in1 = CFDataCreateWithBytesNoCopy(NULL, in1Ptr, in1Len, kCFAllocatorNull); 665 CFDataRef in2 = CFDataCreateWithBytesNoCopy(NULL, in2Ptr, in2Len, kCFAllocatorNull); 666 CFRange range = { 0, -1 }; 667 CFTypeRef output = operation(in1, in2, &range, &error); 668 require_quiet(output, out); 669 if (CFGetTypeID(output) == CFDataGetTypeID() && outLen != NULL) { 670 if (range.length == -1) { 671 range.length = CFDataGetLength(output); 672 } 673 require_action_quiet((size_t)range.length <= *outLen, out, 674 SecError(errSecParam, &error, CFSTR("buffer too small"))); 675 *outLen = range.length; 676 CFDataGetBytes(output, range, outPtr); 677 } 678 679 out: 680 CFReleaseSafe(in1); 681 CFReleaseSafe(in2); 682 CFReleaseSafe(output); 683 if (error != NULL) { 684 status = SecErrorGetOSStatus(error); 685 if (status == errSecVerifyFailed) { 686 // Legacy functions used errSSLCrypto, while new implementation uses errSecVerifyFailed. 687 status = errSSLCrypto; 688 } 689 CFRelease(error); 690 } 691 return status; 692 } 693 694 static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key, SecPadding padding, size_t digestSize) { 695 switch (SecKeyGetAlgorithmId(key)) { 696 case kSecRSAAlgorithmID: { 697 switch (padding) { 698 case kSecPaddingNone: 699 return kSecKeyAlgorithmRSASignatureRaw; 700 case kSecPaddingPKCS1: 701 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw; 702 case kSecPaddingPKCS1SHA1: 703 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1; 704 case kSecPaddingPKCS1SHA224: 705 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224; 706 case kSecPaddingPKCS1SHA256: 707 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256; 708 case kSecPaddingPKCS1SHA384: 709 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384; 710 case kSecPaddingPKCS1SHA512: 711 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512; 712 default: 713 return NULL; 714 } 715 } 716 case kSecECDSAAlgorithmID: 717 switch (padding) { 718 case kSecPaddingSigRaw: 719 return kSecKeyAlgorithmECDSASignatureRFC4754; 720 case kSecPaddingPKCS1: { 721 // If digest has known size of some hash function, explicitly encode that hash type in the algorithm. 722 if (digestSize == ccsha1_di()->output_size) { 723 return kSecKeyAlgorithmECDSASignatureDigestX962SHA1; 724 } else if (digestSize == ccsha224_di()->output_size) { 725 return kSecKeyAlgorithmECDSASignatureDigestX962SHA224; 726 } else if (digestSize == ccsha256_di()->output_size) { 727 return kSecKeyAlgorithmECDSASignatureDigestX962SHA256; 728 } else if (digestSize == ccsha384_di()->output_size) { 729 return kSecKeyAlgorithmECDSASignatureDigestX962SHA384; 730 } else if (digestSize == ccsha512_di()->output_size) { 731 return kSecKeyAlgorithmECDSASignatureDigestX962SHA512; 732 } 733 734 // Fall through to common case, no break here. 735 } 736 default: 737 // Although it is not very logical, previous SecECKey implementation really considered 738 // anything else than SigRaw (incl. None!) as PKCS1 (i.e. x962), so we keep the behaviour 739 // for backward compatibility. 740 return kSecKeyAlgorithmECDSASignatureDigestX962; 741 } 742 default: 743 return NULL; 744 } 745 } 746 747 #if TARGET_OS_OSX 748 static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding_macOS(SecKeyRef key, SecPadding padding, size_t digestSize) { 749 switch (SecKeyGetAlgorithmId(key)) { 750 case kSecRSAAlgorithmID: { 751 // On CSSM-based implementation, these functions actually did hash its input, 752 // so keep doing that for backward compatibility. 753 switch (padding) { 754 case kSecPaddingNone: 755 return kSecKeyAlgorithmRSASignatureRaw; 756 case kSecPaddingPKCS1: 757 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw; 758 case kSecPaddingPKCS1SHA1: 759 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1; 760 case kSecPaddingPKCS1SHA224: 761 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224; 762 case kSecPaddingPKCS1SHA256: 763 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256; 764 case kSecPaddingPKCS1SHA384: 765 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384; 766 case kSecPaddingPKCS1SHA512: 767 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512; 768 default: 769 return NULL; 770 } 771 } 772 case kSecECDSAAlgorithmID: 773 switch (padding) { 774 case kSecPaddingSigRaw: 775 return kSecKeyAlgorithmECDSASignatureRFC4754; 776 case kSecPaddingPKCS1: { 777 // If digest has known size of some hash function, explicitly encode that hash type in the algorithm. 778 if (digestSize == ccsha1_di()->output_size) { 779 return kSecKeyAlgorithmECDSASignatureDigestX962SHA1; 780 } else if (digestSize == ccsha224_di()->output_size) { 781 return kSecKeyAlgorithmECDSASignatureDigestX962SHA224; 782 } else if (digestSize == ccsha256_di()->output_size) { 783 return kSecKeyAlgorithmECDSASignatureDigestX962SHA256; 784 } else if (digestSize == ccsha384_di()->output_size) { 785 return kSecKeyAlgorithmECDSASignatureDigestX962SHA384; 786 } else if (digestSize == ccsha512_di()->output_size) { 787 return kSecKeyAlgorithmECDSASignatureDigestX962SHA512; 788 } 789 790 // Fall through to common case, no break here. 791 } 792 default: 793 // Although it is not very logical, previous SecECKey implementation really considered 794 // anything else than SigRaw (incl. None!) as PKCS1 (i.e. x962), so we keep the behaviour 795 // for backward compatibility. 796 return kSecKeyAlgorithmECDSASignatureDigestX962; 797 } 798 default: 799 return NULL; 800 } 801 } 802 #endif // TARGET_OS_OSX 803 804 #undef SecKeyRawSign 805 OSStatus SecKeyRawSign( 806 SecKeyRef key, /* Private key */ 807 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */ 808 const uint8_t *dataToSign, /* signature over this data */ 809 size_t dataToSignLen, /* length of dataToSign */ 810 uint8_t *sig, /* signature, RETURNED */ 811 size_t *sigLen) { /* IN/OUT */ 812 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding, dataToSignLen); 813 if (algorithm == NULL) { 814 return errSecParam; 815 } 816 return SecKeyPerformLegacyOperation(key, dataToSign, dataToSignLen, NULL, 0, sig, sigLen, 817 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 818 return SecKeyCreateSignature(key, algorithm, in1, error); 819 }); 820 } 821 822 #if TARGET_OS_OSX 823 OSStatus SecKeyRawSign_macOS( 824 SecKeyRef key, /* Private key */ 825 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */ 826 const uint8_t *dataToSign, /* signature over this data */ 827 size_t dataToSignLen, /* length of dataToSign */ 828 uint8_t *sig, /* signature, RETURNED */ 829 size_t *sigLen) { /* IN/OUT */ 830 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding_macOS(key, padding, dataToSignLen); 831 if (algorithm == NULL) { 832 return errSecParam; 833 } 834 return SecKeyPerformLegacyOperation(key, dataToSign, dataToSignLen, NULL, 0, sig, sigLen, 835 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 836 return SecKeyCreateSignature(key, algorithm, in1, error); 837 }); 838 } 839 #endif 840 841 #undef SecKeyRawVerify 842 OSStatus SecKeyRawVerify( 843 SecKeyRef key, /* Public key */ 844 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */ 845 const uint8_t *signedData, /* signature over this data */ 846 size_t signedDataLen, /* length of dataToSign */ 847 const uint8_t *sig, /* signature */ 848 size_t sigLen) { /* length of signature */ 849 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding, signedDataLen); 850 if (algorithm == NULL) { 851 return errSecParam; 852 } 853 OSStatus status = SecKeyPerformLegacyOperation(key, signedData, signedDataLen, sig, sigLen, NULL, NULL, 854 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 855 return SecKeyVerifySignature(key, algorithm, in1, in2, error) 856 ? kCFBooleanTrue : NULL; 857 }); 858 return status; 859 } 860 861 #if TARGET_OS_OSX 862 OSStatus SecKeyRawVerify_macOS( 863 SecKeyRef key, /* Public key */ 864 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */ 865 const uint8_t *signedData, /* signature over this data */ 866 size_t signedDataLen, /* length of dataToSign */ 867 const uint8_t *sig, /* signature */ 868 size_t sigLen) { /* length of signature */ 869 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding_macOS(key, padding, signedDataLen); 870 if (algorithm == NULL) { 871 return errSecParam; 872 } 873 OSStatus status = SecKeyPerformLegacyOperation(key, signedData, signedDataLen, sig, sigLen, NULL, NULL, 874 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 875 return SecKeyVerifySignature(key, algorithm, in1, in2, error) 876 ? kCFBooleanTrue : NULL; 877 }); 878 return status; 879 } 880 #endif 881 882 static SecKeyAlgorithm SecKeyGetEncryptionAlgorithmForPadding(SecKeyRef key, SecPadding padding) { 883 switch (SecKeyGetAlgorithmId(key)) { 884 case kSecRSAAlgorithmID: 885 switch (padding) { 886 case kSecPaddingNone: 887 return kSecKeyAlgorithmRSAEncryptionRaw; 888 case kSecPaddingPKCS1: 889 return kSecKeyAlgorithmRSAEncryptionPKCS1; 890 case kSecPaddingOAEP: 891 return kSecKeyAlgorithmRSAEncryptionOAEPSHA1; 892 default: 893 return NULL; 894 } 895 default: 896 return NULL; 897 } 898 } 899 900 OSStatus SecKeyEncrypt( 901 SecKeyRef key, /* Public key */ 902 SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */ 903 const uint8_t *plainText, 904 size_t plainTextLen, /* length of plainText */ 905 uint8_t *cipherText, 906 size_t *cipherTextLen) { /* IN/OUT */ 907 SecKeyAlgorithm algorithm = SecKeyGetEncryptionAlgorithmForPadding(key, padding); 908 if (algorithm == NULL) { 909 return errSecParam; 910 } 911 912 return SecKeyPerformLegacyOperation(key, plainText, plainTextLen, NULL, 0, cipherText, cipherTextLen, 913 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 914 return SecKeyCreateEncryptedData(key, algorithm, in1, error); 915 }); 916 } 917 918 OSStatus SecKeyDecrypt( 919 SecKeyRef key, /* Private key */ 920 SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */ 921 const uint8_t *cipherText, 922 size_t cipherTextLen, /* length of cipherText */ 923 uint8_t *plainText, 924 size_t *plainTextLen) { /* IN/OUT */ 925 SecKeyAlgorithm algorithm = SecKeyGetEncryptionAlgorithmForPadding(key, padding); 926 if (algorithm == NULL) { 927 return errSecParam; 928 } 929 return SecKeyPerformLegacyOperation(key, cipherText, cipherTextLen, NULL, 0, plainText, plainTextLen, 930 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 931 CFDataRef decrypted = SecKeyCreateDecryptedData(key, algorithm, in1, error); 932 const UInt8 *data; 933 if (decrypted != NULL && algorithm == kSecKeyAlgorithmRSAEncryptionRaw && 934 *(data = CFDataGetBytePtr(decrypted)) == 0x00) { 935 // Strip zero-padding from the beginning of the block, as the contract of this 936 // function says. 937 range->length = CFDataGetLength(decrypted); 938 while (*data == 0x00 && range->length > 0) { 939 range->location++; 940 range->length--; 941 data++; 942 } 943 } 944 return decrypted; 945 }); 946 } 947 948 size_t SecKeyGetBlockSize(SecKeyRef key) { 949 if (key->key_class->blockSize) 950 return key->key_class->blockSize(key); 951 return 0; 952 } 953 954 /* Private API functions. */ 955 956 CFDictionaryRef SecKeyCopyAttributeDictionary(SecKeyRef key) { 957 return SecKeyCopyAttributes(key); 958 } 959 960 SecKeyRef SecKeyCreateFromAttributeDictionary(CFDictionaryRef refAttributes) { 961 CFErrorRef error = NULL; 962 SecKeyRef key = SecKeyCreateWithData(CFDictionaryGetValue(refAttributes, kSecValueData), refAttributes, &error); 963 if (key == NULL) { 964 CFStringRef description = CFErrorCopyDescription(error); 965 secwarning("%@", description); 966 CFRelease(description); 967 CFRelease(error); 968 } 969 return key; 970 } 971 972 static SecKeyAlgorithm SecKeyGetAlgorithmForSecAsn1AlgId(SecKeyRef key, const SecAsn1AlgId *algId, bool digestData) { 973 static const struct TableItem { 974 const SecAsn1Oid *oid1, *oid2; 975 const SecKeyAlgorithm *algorithms[2]; 976 } translationTableRSA[] = { 977 { &CSSMOID_SHA1WithRSA, &CSSMOID_SHA1, { 978 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, 979 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, 980 } }, 981 { &CSSMOID_SHA224WithRSA, &CSSMOID_SHA224, { 982 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224, 983 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224, 984 } }, 985 { &CSSMOID_SHA256WithRSA, &CSSMOID_SHA256, { 986 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256, 987 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, 988 } }, 989 { &CSSMOID_SHA384WithRSA, &CSSMOID_SHA384, { 990 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384, 991 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384, 992 } }, 993 { &CSSMOID_SHA512WithRSA, &CSSMOID_SHA512, { 994 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512, 995 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, 996 } }, 997 { &CSSMOID_MD5, NULL, { 998 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5, 999 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5, 1000 } }, 1001 { &CSSMOID_MD5WithRSA, NULL, { 1002 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5, 1003 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5, 1004 } }, 1005 { NULL }, 1006 }, translationTableECDSA[] = { 1007 { &CSSMOID_ECDSA_WithSHA1, &CSSMOID_SHA1, { 1008 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962, 1009 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA1, 1010 } }, 1011 { &CSSMOID_ECDSA_WithSHA224, &CSSMOID_SHA224, { 1012 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962, 1013 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA224, 1014 } }, 1015 { &CSSMOID_ECDSA_WithSHA256, &CSSMOID_SHA256, { 1016 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962, 1017 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA256, 1018 } }, 1019 { &CSSMOID_ECDSA_WithSHA384, &CSSMOID_SHA384, { 1020 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962, 1021 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA384, 1022 } }, 1023 { &CSSMOID_ECDSA_WithSHA512, &CSSMOID_SHA512, { 1024 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962, 1025 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA512, 1026 } }, 1027 { NULL }, 1028 }; 1029 1030 const struct TableItem *table; 1031 switch (SecKeyGetAlgorithmId(key)) { 1032 case kSecRSAAlgorithmID: 1033 table = translationTableRSA; 1034 break; 1035 case kSecECDSAAlgorithmID: 1036 table = translationTableECDSA; 1037 break; 1038 default: 1039 return NULL; 1040 } 1041 1042 for (; table->oid1 != NULL; table++) { 1043 if (SecAsn1OidCompare(table->oid1, &algId->algorithm) || 1044 (table->oid2 != NULL && SecAsn1OidCompare(table->oid2, &algId->algorithm))) { 1045 return *table->algorithms[digestData]; 1046 } 1047 } 1048 return NULL; 1049 } 1050 1051 OSStatus SecKeyDigestAndVerify( 1052 SecKeyRef key, /* Private key */ 1053 const SecAsn1AlgId *algId, /* algorithm oid/params */ 1054 const uint8_t *dataToDigest, /* signature over this data */ 1055 size_t dataToDigestLen,/* length of dataToDigest */ 1056 const uint8_t *sig, /* signature to verify */ 1057 size_t sigLen) { /* length of sig */ 1058 1059 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, true); 1060 if (algorithm == NULL) { 1061 return errSecUnimplemented; 1062 } 1063 1064 return SecKeyPerformLegacyOperation(key, dataToDigest, dataToDigestLen, sig, sigLen, NULL, NULL, 1065 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 1066 return SecKeyVerifySignature(key, algorithm, in1, in2, error) ? 1067 kCFBooleanTrue : NULL; 1068 }); 1069 } 1070 1071 OSStatus SecKeyDigestAndSign( 1072 SecKeyRef key, /* Private key */ 1073 const SecAsn1AlgId *algId, /* algorithm oid/params */ 1074 const uint8_t *dataToDigest, /* signature over this data */ 1075 size_t dataToDigestLen,/* length of dataToDigest */ 1076 uint8_t *sig, /* signature, RETURNED */ 1077 size_t *sigLen) { /* IN/OUT */ 1078 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, true); 1079 if (algorithm == NULL) { 1080 return errSecUnimplemented; 1081 } 1082 1083 return SecKeyPerformLegacyOperation(key, dataToDigest, dataToDigestLen, NULL, 0, sig, sigLen, 1084 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 1085 return SecKeyCreateSignature(key, algorithm, in1, error); 1086 }); 1087 } 1088 1089 OSStatus SecKeyVerifyDigest( 1090 SecKeyRef key, /* Private key */ 1091 const SecAsn1AlgId *algId, /* algorithm oid/params */ 1092 const uint8_t *digestData, /* signature over this digest */ 1093 size_t digestDataLen,/* length of dataToDigest */ 1094 const uint8_t *sig, /* signature to verify */ 1095 size_t sigLen) { /* length of sig */ 1096 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, false); 1097 if (algorithm == NULL) { 1098 return errSecUnimplemented; 1099 } 1100 1101 return SecKeyPerformLegacyOperation(key, digestData, digestDataLen, sig, sigLen, NULL, NULL, 1102 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 1103 return SecKeyVerifySignature(key, algorithm, in1, in2, error) ? 1104 kCFBooleanTrue : NULL; 1105 }); 1106 } 1107 1108 OSStatus SecKeySignDigest( 1109 SecKeyRef key, /* Private key */ 1110 const SecAsn1AlgId *algId, /* algorithm oid/params */ 1111 const uint8_t *digestData, /* signature over this digest */ 1112 size_t digestDataLen,/* length of digestData */ 1113 uint8_t *sig, /* signature, RETURNED */ 1114 size_t *sigLen) { /* IN/OUT */ 1115 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, false); 1116 if (algorithm == NULL) { 1117 return errSecUnimplemented; 1118 } 1119 1120 return SecKeyPerformLegacyOperation(key, digestData, digestDataLen, NULL, 0, sig, sigLen, 1121 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) { 1122 return SecKeyCreateSignature(key, algorithm, in1, error); 1123 }); 1124 } 1125 1126 #if TARGET_OS_OSX 1127 /* On OS X, SecKeyGetAlgorithmID has a different function signature (two arguments, 1128 with output in the second argument). Therefore, avoid implementing this function here 1129 if compiling for OS X. 1130 */ 1131 #else 1132 // Export original SecKeyGetAlgorithmID symbol for backward binary compatibility. 1133 #undef SecKeyGetAlgorithmID 1134 CFIndex SecKeyGetAlgorithmID(SecKeyRef key); 1135 CFIndex SecKeyGetAlgorithmID(SecKeyRef key) { 1136 return SecKeyGetAlgorithmId(key); 1137 } 1138 #endif 1139 1140 OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* serializedPublic) { 1141 if (key->key_class->version > 1 && key->key_class->copyPublic) 1142 return key->key_class->copyPublic(key, serializedPublic); 1143 return errSecUnimplemented; 1144 } 1145 1146 SecKeyRef SecKeyCreateFromPublicBytes(CFAllocatorRef allocator, CFIndex algorithmID, const uint8_t *keyData, CFIndex keyDataLength) 1147 { 1148 switch (algorithmID) 1149 { 1150 case kSecRSAAlgorithmID: 1151 return SecKeyCreateRSAPublicKey(allocator, 1152 keyData, keyDataLength, 1153 kSecKeyEncodingBytes); 1154 case kSecECDSAAlgorithmID: 1155 return SecKeyCreateECPublicKey(allocator, 1156 keyData, keyDataLength, 1157 kSecKeyEncodingBytes); 1158 default: 1159 return NULL; 1160 } 1161 } 1162 1163 SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef serialized) 1164 { 1165 return SecKeyCreateFromPublicBytes(allocator, algorithmID, CFDataGetBytePtr(serialized), CFDataGetLength(serialized)); 1166 } 1167 1168 // This is a bit icky hack to avoid changing the vtable for 1169 // SecKey. 1170 size_t SecKeyGetSize(SecKeyRef key, SecKeySize whichSize) 1171 { 1172 size_t result = SecKeyGetBlockSize(key); 1173 1174 if (whichSize == 0 || whichSize == 10) { 1175 // kSecKeyKeySizeInBits is declared as 0 on iOS (SPI) and 10 on macOS (API). Unified implementation 1176 // here deals with both values. 1177 whichSize = kSecKeyKeySizeInBits; 1178 } 1179 1180 if (kSecECDSAAlgorithmID == SecKeyGetAlgorithmId(key)) { 1181 switch (whichSize) { 1182 case kSecKeyEncryptedDataSize: 1183 result = 0; 1184 break; 1185 case kSecKeySignatureSize: 1186 result = (result >= 66 ? 9 : 8) + 2 * result; 1187 break; 1188 case kSecKeyKeySizeInBits: 1189 if (result >= 66) 1190 return 521; 1191 } 1192 } 1193 1194 if (whichSize == kSecKeyKeySizeInBits) 1195 result *= 8; 1196 1197 return result; 1198 1199 } 1200 1201 OSStatus SecKeyFindWithPersistentRef(CFDataRef persistentRef, SecKeyRef* lookedUpData) 1202 { 1203 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, 1204 kSecReturnRef, kCFBooleanTrue, 1205 kSecClass, kSecClassKey, 1206 kSecValuePersistentRef, persistentRef, 1207 NULL); 1208 CFTypeRef foundRef = NULL; 1209 OSStatus status = SecItemCopyMatching(query, &foundRef); 1210 1211 if (status == errSecSuccess) { 1212 if (CFGetTypeID(foundRef) == SecKeyGetTypeID()) { 1213 *lookedUpData = (SecKeyRef) foundRef; 1214 foundRef = NULL; 1215 status = errSecSuccess; 1216 } else { 1217 status = errSecItemNotFound; 1218 } 1219 } 1220 1221 CFReleaseSafe(foundRef); 1222 CFReleaseSafe(query); 1223 1224 return status; 1225 } 1226 1227 OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef) 1228 { 1229 if (!key) { 1230 secerror("SecKeyCopyPersistentRef: Need a key reference for this to work"); 1231 return errSecParam; 1232 } 1233 if (!persistentRef) { 1234 secerror("SecKeyCopyPersistentRef: Need a persistentRef pointer for this to work"); 1235 return errSecParam; 1236 } 1237 1238 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, 1239 kSecReturnPersistentRef, kCFBooleanTrue, 1240 kSecValueRef, key, 1241 kSecAttrSynchronizable, kSecAttrSynchronizableAny, 1242 NULL); 1243 CFTypeRef foundRef = NULL; 1244 OSStatus status = SecItemCopyMatching(query, &foundRef); 1245 1246 if (status == errSecSuccess) { 1247 if (CFGetTypeID(foundRef) == CFDataGetTypeID()) { 1248 *persistentRef = foundRef; 1249 foundRef = NULL; 1250 } else { 1251 secerror("SecKeyCopyPersistentRef: SecItemCopyMatching returned success, but we got type %lu instead of CFData for key %@.", CFGetTypeID(foundRef), key); 1252 status = errSecItemNotFound; 1253 } 1254 } else { 1255 secerror("SecKeyCopyPersistentRef: received status %i for key %@", (int)status, key); 1256 CFStringRef str = CFStringCreateWithFormat(NULL, NULL, CFSTR("Expected to find persistentref for key %@"), key); 1257 __security_stackshotreport(str, (int)status); 1258 CFReleaseNull(str); 1259 } 1260 1261 CFReleaseSafe(foundRef); 1262 CFReleaseSafe(query); 1263 1264 return status; 1265 } 1266 1267 /* 1268 * 1269 */ 1270 1271 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); 1272 1273 SEC_CONST_DECL(_kSecKeyWrapPGPSymAlg, "kSecKeyWrapPGPSymAlg"); 1274 SEC_CONST_DECL(_kSecKeyWrapPGPFingerprint, "kSecKeyWrapPGPFingerprint"); 1275 SEC_CONST_DECL(_kSecKeyWrapPGPWrapAlg, "kSecKeyWrapPGPWrapAlg"); 1276 SEC_CONST_DECL(_kSecKeyWrapRFC6637Flags, "kSecKeyWrapPGPECFlags"); 1277 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA256KekAES128, "kSecKeyWrapPGPECWrapDigestSHA256KekAES128"); 1278 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA512KekAES256, "kSecKeyWrapPGPECWrapDigestSHA512KekAES256"); 1279 1280 #undef SEC_CONST_DECL 1281 1282 CFDataRef 1283 _SecKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) 1284 { 1285 if (error) 1286 *error = NULL; 1287 if (outParam) 1288 *outParam = NULL; 1289 if (key->key_class->version > 2 && key->key_class->copyWrapKey) 1290 return key->key_class->copyWrapKey(key, type, unwrappedKey, parameters, outParam, error); 1291 SecError(errSecUnsupportedOperation, error, CFSTR("No key wrap supported for key %@"), key); 1292 return NULL; 1293 } 1294 1295 CFDataRef 1296 _SecKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) 1297 { 1298 if (error) 1299 *error = NULL; 1300 if (outParam) 1301 *outParam = NULL; 1302 if (key->key_class->version > 2 && key->key_class->copyUnwrapKey) 1303 return key->key_class->copyUnwrapKey(key, type, wrappedKey, parameters, outParam, error); 1304 1305 SecError(errSecUnsupportedOperation, error, CFSTR("No key unwrap for key %@"), key); 1306 return NULL; 1307 } 1308 1309 static CFIndex SecKeyParamsGetCFIndex(CFTypeRef value, CFStringRef errName, CFErrorRef *error) { 1310 CFIndex result = -1; 1311 CFNumberRef localValue = NULL; 1312 1313 if (isString(value)) { 1314 CFNumberFormatterRef formatter = CFNumberFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(), kCFNumberFormatterDecimalStyle); 1315 localValue = CFNumberFormatterCreateNumberFromString(kCFAllocatorDefault, formatter, value, NULL, kCFNumberFormatterParseIntegersOnly); 1316 CFReleaseSafe(formatter); 1317 1318 if (localValue) { 1319 CFStringRef t = CFStringCreateWithFormat(0, 0, CFSTR("%@"), localValue); 1320 if (CFEqual(t, value)) { 1321 value = localValue; 1322 } 1323 CFReleaseSafe(t); 1324 } 1325 } 1326 1327 if (value != NULL && CFGetTypeID(value) == CFNumberGetTypeID()) { 1328 if (!CFNumberGetValue(value, kCFNumberCFIndexType, &result) || result < 0) { 1329 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value); 1330 } 1331 } else { 1332 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value); 1333 } 1334 1335 CFReleaseSafe(localValue); 1336 return result; 1337 } 1338 1339 SecKeyRef SecKeyCreateWithData(CFDataRef keyData, CFDictionaryRef parameters, CFErrorRef *error) { 1340 1341 SecKeyRef key = NULL; 1342 CFAllocatorRef allocator = NULL; 1343 1344 if (CFDictionaryGetValue(parameters, kSecAttrTokenID) != NULL) { 1345 return SecKeyCreateCTKKey(allocator, parameters, error); 1346 } 1347 else if (!keyData) { 1348 SecError(errSecParam, error, CFSTR("Failed to provide key data to SecKeyCreateWithData")); 1349 return NULL; 1350 } 1351 /* First figure out the key type (algorithm). */ 1352 CFIndex algorithm, class; 1353 CFTypeRef ktype = CFDictionaryGetValue(parameters, kSecAttrKeyType); 1354 require_quiet((algorithm = SecKeyParamsGetCFIndex(ktype, CFSTR("key type"), error)) >= 0, out); 1355 CFTypeRef kclass = CFDictionaryGetValue(parameters, kSecAttrKeyClass); 1356 require_quiet((class = SecKeyParamsGetCFIndex(kclass, CFSTR("key class"), error)) >= 0, out); 1357 1358 switch (class) { 1359 case 0: // kSecAttrKeyClassPublic 1360 switch (algorithm) { 1361 case 42: // kSecAlgorithmRSA 1362 key = SecKeyCreateRSAPublicKey(allocator, 1363 CFDataGetBytePtr(keyData), CFDataGetLength(keyData), 1364 kSecKeyEncodingBytes); 1365 if (key == NULL) { 1366 SecError(errSecParam, error, CFSTR("RSA public key creation from data failed")); 1367 } 1368 break; 1369 case 43: // kSecAlgorithmECDSA 1370 case 73: // kSecAlgorithmEC 1371 key = SecKeyCreateECPublicKey(allocator, 1372 CFDataGetBytePtr(keyData), CFDataGetLength(keyData), 1373 kSecKeyEncodingBytes); 1374 if (key == NULL) { 1375 SecError(errSecParam, error, CFSTR("EC public key creation from data failed")); 1376 } 1377 break; 1378 default: 1379 SecError(errSecParam, error, CFSTR("Unsupported public key type: %@"), ktype); 1380 break; 1381 }; 1382 break; 1383 case 1: // kSecAttrKeyClassPrivate 1384 switch (algorithm) { 1385 case 42: // kSecAlgorithmRSA 1386 key = SecKeyCreateRSAPrivateKey(allocator, 1387 CFDataGetBytePtr(keyData), CFDataGetLength(keyData), 1388 kSecKeyEncodingBytes); 1389 if (key == NULL) { 1390 SecError(errSecParam, error, CFSTR("RSA private key creation from data failed")); 1391 } 1392 break; 1393 case 43: // kSecAlgorithmECDSA 1394 case 73: // kSecAlgorithmEC 1395 key = SecKeyCreateECPrivateKey(allocator, 1396 CFDataGetBytePtr(keyData), CFDataGetLength(keyData), 1397 kSecKeyEncodingBytes); 1398 if (key == NULL) { 1399 SecError(errSecParam, error, CFSTR("EC private key creation from data failed")); 1400 } 1401 break; 1402 default: 1403 SecError(errSecParam, error, CFSTR("Unsupported private key type: %@"), ktype); 1404 break; 1405 }; 1406 break; 1407 case 2: // kSecAttrKeyClassSymmetric 1408 SecError(errSecUnimplemented, error, CFSTR("Unsupported symmetric key type: %@"), ktype); 1409 break; 1410 default: 1411 SecError(errSecParam, error, CFSTR("Unsupported key class: %@"), kclass); 1412 break; 1413 } 1414 1415 out: 1416 return key; 1417 } 1418 1419 // Similar to CFErrorPropagate, but does not consult input value of *error, it can contain any garbage and if overwritten, previous value is never released. 1420 static inline bool SecKeyErrorPropagate(bool succeeded, CFErrorRef possibleError CF_CONSUMED, CFErrorRef *error) { 1421 if (succeeded) { 1422 return true; 1423 } else { 1424 if (error) { 1425 *error = possibleError; 1426 } else { 1427 CFRelease(possibleError); 1428 } 1429 return false; 1430 } 1431 } 1432 1433 CFDataRef SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { 1434 if (!key->key_class->copyExternalRepresentation) { 1435 if (error != NULL) { 1436 *error = NULL; 1437 } 1438 SecError(errSecUnimplemented, error, CFSTR("export not implemented for key %@"), key); 1439 return NULL; 1440 } 1441 1442 CFErrorRef localError = NULL; 1443 CFDataRef result = key->key_class->copyExternalRepresentation(key, &localError); 1444 SecKeyErrorPropagate(result != NULL, localError, error); 1445 return result; 1446 } 1447 1448 CFDictionaryRef SecKeyCopyAttributes(SecKeyRef key) { 1449 if (key->key_class->copyDictionary) { 1450 return key->key_class->copyDictionary(key); 1451 } else { 1452 // Create dictionary with basic values derived from other known information of the key. 1453 CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); 1454 CFIndex blockSize = SecKeyGetBlockSize(key) * 8; 1455 if (blockSize > 0) { 1456 CFNumberRef blockSizeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &blockSize); 1457 CFDictionarySetValue(dict, kSecAttrKeySizeInBits, blockSizeRef); 1458 CFRelease(blockSizeRef); 1459 } 1460 1461 switch (SecKeyGetAlgorithmId(key)) { 1462 case kSecRSAAlgorithmID: 1463 CFDictionarySetValue(dict, kSecAttrKeyType, kSecAttrKeyTypeRSA); 1464 break; 1465 case kSecECDSAAlgorithmID: 1466 CFDictionarySetValue(dict, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom); 1467 break; 1468 } 1469 1470 if (key->key_class->rawSign != NULL || key->key_class->decrypt != NULL) { 1471 CFDictionarySetValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPrivate); 1472 } else if (key->key_class->rawVerify != NULL || key->key_class->encrypt != NULL) { 1473 CFDictionarySetValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPublic); 1474 } 1475 1476 return dict; 1477 } 1478 } 1479 1480 SecKeyRef SecKeyCopyPublicKey(SecKeyRef key) { 1481 SecKeyRef result = NULL; 1482 if (key->key_class->version >= 4 && key->key_class->copyPublicKey) { 1483 result = key->key_class->copyPublicKey(key); 1484 if (result != NULL) { 1485 return result; 1486 } 1487 } 1488 1489 CFDataRef serializedPublic = NULL; 1490 1491 require_noerr_quiet(SecKeyCopyPublicBytes(key, &serializedPublic), fail); 1492 require_quiet(serializedPublic, fail); 1493 1494 result = SecKeyCreateFromPublicData(kCFAllocatorDefault, SecKeyGetAlgorithmId(key), serializedPublic); 1495 1496 fail: 1497 CFReleaseSafe(serializedPublic); 1498 return result; 1499 } 1500 1501 SecKeyRef SecKeyCreateRandomKey(CFDictionaryRef parameters, CFErrorRef *error) { 1502 @autoreleasepool { 1503 SecKeyRef privKey = NULL, pubKey = NULL; 1504 OSStatus status = SecKeyGeneratePair(parameters, &pubKey, &privKey); 1505 if (status != errSecSuccess) { 1506 if (error != NULL) { 1507 *error = NULL; 1508 } 1509 SecError(status, error, CFSTR("Key generation failed, error %d"), (int)status); 1510 } 1511 CFReleaseSafe(pubKey); 1512 return privKey; 1513 } 1514 } 1515 1516 SecKeyRef SecKeyCreateDuplicate(SecKeyRef key) { 1517 if (key->key_class->version >= 4 && key->key_class->createDuplicate) { 1518 return key->key_class->createDuplicate(key); 1519 } else { 1520 return (SecKeyRef)CFRetain(key); 1521 } 1522 } 1523 1524 Boolean SecKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) { 1525 if (key == NULL) { 1526 SecCTKKeySetTestMode(name, value); 1527 return true; 1528 } else if (key->key_class->version >= 4 && key->key_class->setParameter) { 1529 CFErrorRef localError = NULL; 1530 Boolean result = key->key_class->setParameter(key, name, value, &localError); 1531 SecKeyErrorPropagate(result, localError, error); 1532 return result; 1533 } else { 1534 if (error != NULL) { 1535 *error = NULL; 1536 } 1537 return SecError(errSecUnimplemented, error, CFSTR("setParameter not implemented for %@"), key); 1538 } 1539 } 1540 1541 #pragma mark Generic algorithm adaptor lookup and invocation 1542 1543 static CFTypeRef SecKeyCopyBackendOperationResult(SecKeyOperationContext *context, SecKeyAlgorithm algorithm, 1544 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { 1545 CFTypeRef result = kCFNull; 1546 assert(CFArrayGetCount(context->algorithm) > 0); 1547 if (context->key->key_class->version >= 4 && context->key->key_class->copyOperationResult != NULL) { 1548 return context->key->key_class->copyOperationResult(context->key, context->operation, algorithm, 1549 context->algorithm, context->mode, in1, in2, error); 1550 } 1551 1552 // Mapping from algorithms to legacy SecPadding values. 1553 static const struct { 1554 const SecKeyAlgorithm *algorithm; 1555 CFIndex keyAlg; 1556 SecPadding padding; 1557 } paddingMap[] = { 1558 { &kSecKeyAlgorithmRSASignatureRaw, kSecRSAAlgorithmID, kSecPaddingNone }, 1559 { &kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw, kSecRSAAlgorithmID, kSecPaddingPKCS1 }, 1560 { &kSecKeyAlgorithmECDSASignatureRFC4754, kSecECDSAAlgorithmID, kSecPaddingSigRaw }, 1561 { &kSecKeyAlgorithmECDSASignatureDigestX962, kSecECDSAAlgorithmID, kSecPaddingPKCS1 }, 1562 { &kSecKeyAlgorithmRSAEncryptionRaw, kSecRSAAlgorithmID, kSecPaddingNone }, 1563 { &kSecKeyAlgorithmRSAEncryptionPKCS1, kSecRSAAlgorithmID, kSecPaddingPKCS1 }, 1564 { &kSecKeyAlgorithmRSAEncryptionOAEPSHA1, kSecRSAAlgorithmID, kSecPaddingOAEP }, 1565 }; 1566 SecPadding padding = (SecPadding)-1; 1567 CFIndex keyAlg = SecKeyGetAlgorithmId(context->key); 1568 for (size_t i = 0; i < array_size(paddingMap); ++i) { 1569 if (keyAlg == paddingMap[i].keyAlg && CFEqual(algorithm, *paddingMap[i].algorithm)) { 1570 padding = paddingMap[i].padding; 1571 break; 1572 } 1573 } 1574 require_quiet(padding != (SecPadding)-1, out); 1575 1576 // Check legacy virtual table entries. 1577 size_t size = 0; 1578 OSStatus status = errSecSuccess; 1579 switch (context->operation) { 1580 case kSecKeyOperationTypeSign: 1581 if (context->key->key_class->rawSign != NULL) { 1582 result = kCFBooleanTrue; 1583 if (context->mode == kSecKeyOperationModePerform) { 1584 size = SecKeyGetSize(context->key, kSecKeySignatureSize); 1585 result = CFDataCreateMutableWithScratch(NULL, size); 1586 status = context->key->key_class->rawSign(context->key, padding, 1587 CFDataGetBytePtr(in1), CFDataGetLength(in1), 1588 CFDataGetMutableBytePtr((CFMutableDataRef)result), &size); 1589 } 1590 } 1591 break; 1592 case kSecKeyOperationTypeVerify: 1593 if (context->key->key_class->rawVerify != NULL) { 1594 result = kCFBooleanTrue; 1595 if (context->mode == kSecKeyOperationModePerform) { 1596 status = context->key->key_class->rawVerify(context->key, padding, 1597 CFDataGetBytePtr(in1), CFDataGetLength(in1), 1598 CFDataGetBytePtr(in2), CFDataGetLength(in2)); 1599 } 1600 } 1601 break; 1602 case kSecKeyOperationTypeEncrypt: 1603 if (context->key->key_class->encrypt != NULL) { 1604 result = kCFBooleanTrue; 1605 if (context->mode == kSecKeyOperationModePerform) { 1606 size = SecKeyGetSize(context->key, kSecKeyEncryptedDataSize); 1607 result = CFDataCreateMutableWithScratch(NULL, size); 1608 status = context->key->key_class->encrypt(context->key, padding, 1609 CFDataGetBytePtr(in1), CFDataGetLength(in1), 1610 CFDataGetMutableBytePtr((CFMutableDataRef)result), &size); 1611 } 1612 } 1613 break; 1614 case kSecKeyOperationTypeDecrypt: 1615 if (context->key->key_class->decrypt != NULL) { 1616 result = kCFBooleanTrue; 1617 if (context->mode == kSecKeyOperationModePerform) { 1618 size = SecKeyGetSize(context->key, kSecKeyEncryptedDataSize); 1619 result = CFDataCreateMutableWithScratch(NULL, size); 1620 status = context->key->key_class->decrypt(context->key, padding, 1621 CFDataGetBytePtr(in1), CFDataGetLength(in1), 1622 CFDataGetMutableBytePtr((CFMutableDataRef)result), &size); 1623 } 1624 } 1625 break; 1626 default: 1627 goto out; 1628 } 1629 1630 if (status == errSecSuccess) { 1631 if (CFGetTypeID(result) == CFDataGetTypeID()) { 1632 CFDataSetLength((CFMutableDataRef)result, size); 1633 } 1634 } else { 1635 SecError(status, error, CFSTR("legacy SecKey backend operation:%d(%d) failed"), (int)context->operation, (int)padding); 1636 CFReleaseNull(result); 1637 } 1638 1639 out: 1640 return result; 1641 } 1642 1643 CFTypeRef SecKeyRunAlgorithmAndCopyResult(SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { 1644 @autoreleasepool { 1645 // Check algorithm array for cycles; if any value of it is duplicated inside, report 'algorithm not found' error. 1646 CFIndex algorithmCount = CFArrayGetCount(context->algorithm); 1647 for (CFIndex index = 0; index < algorithmCount - 1; index++) { 1648 SecKeyAlgorithm indexAlgorithm = CFArrayGetValueAtIndex(context->algorithm, index); 1649 for (CFIndex tested = index + 1; tested < algorithmCount; tested++) { 1650 require_quiet(!CFEqual(indexAlgorithm, CFArrayGetValueAtIndex(context->algorithm, tested)), fail); 1651 } 1652 } 1653 1654 SecKeyAlgorithm algorithm = CFArrayGetValueAtIndex(context->algorithm, algorithmCount - 1); 1655 CFTypeRef output = SecKeyCopyBackendOperationResult(context, algorithm, in1, in2, error); 1656 if (output != kCFNull) { 1657 // Backend handled the operation, return result. 1658 return output; 1659 } 1660 1661 // To silence static analyzer. 1662 CFReleaseSafe(output); 1663 1664 // Get adaptor which is able to handle requested algorithm. 1665 SecKeyAlgorithmAdaptor adaptor = SecKeyGetAlgorithmAdaptor(context->operation, algorithm); 1666 require_quiet(adaptor != NULL, fail); 1667 1668 // Invoke the adaptor and return result. 1669 CFTypeRef result = adaptor(context, in1, in2, error); 1670 require_quiet(result != kCFNull, fail); 1671 return result; 1672 1673 fail: 1674 if (context->mode == kSecKeyOperationModePerform) { 1675 SecError(errSecParam, error, CFSTR("%@: algorithm not supported by the key %@"), 1676 CFArrayGetValueAtIndex(context->algorithm, 0), context->key); 1677 return NULL; 1678 } else { 1679 return kCFNull; 1680 } 1681 } 1682 } 1683 1684 #pragma mark Algorithm-related SecKey API entry points 1685 1686 static CFMutableArrayRef SecKeyCreateAlgorithmArray(SecKeyAlgorithm algorithm) { 1687 CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 1688 CFArrayAppendValue(result, algorithm); 1689 return result; 1690 } 1691 1692 CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error) { 1693 CFErrorRef localError = NULL; 1694 SecKeyOperationContext context = { key, kSecKeyOperationTypeSign, SecKeyCreateAlgorithmArray(algorithm) }; 1695 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, dataToSign, NULL, &localError); 1696 SecKeyOperationContextDestroy(&context); 1697 SecKeyErrorPropagate(result != NULL, localError, error); 1698 return result; 1699 } 1700 1701 Boolean SecKeyVerifySignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef signedData, CFDataRef signature, 1702 CFErrorRef *error) { 1703 CFErrorRef localError = NULL; 1704 SecKeyOperationContext context = { key, kSecKeyOperationTypeVerify, SecKeyCreateAlgorithmArray(algorithm) }; 1705 CFTypeRef res = SecKeyRunAlgorithmAndCopyResult(&context, signedData, signature, &localError); 1706 Boolean result = CFEqualSafe(res, kCFBooleanTrue); 1707 CFReleaseSafe(res); 1708 SecKeyOperationContextDestroy(&context); 1709 SecKeyErrorPropagate(result, localError, error); 1710 return result; 1711 } 1712 1713 CFDataRef SecKeyCreateEncryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext, 1714 CFDictionaryRef parameters, CFErrorRef *error) { 1715 CFErrorRef localError = NULL; 1716 SecKeyOperationContext context = { key, kSecKeyOperationTypeEncrypt, SecKeyCreateAlgorithmArray(algorithm) }; 1717 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, plaintext, parameters, &localError); 1718 SecKeyOperationContextDestroy(&context); 1719 SecKeyErrorPropagate(result, localError, error); 1720 return result; 1721 } 1722 1723 CFDataRef SecKeyCreateEncryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext, CFErrorRef *error) { 1724 return SecKeyCreateEncryptedDataWithParameters(key, algorithm, plaintext, NULL, error); 1725 } 1726 1727 CFDataRef SecKeyCreateDecryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext, 1728 CFDictionaryRef parameters, CFErrorRef *error) { 1729 SecKeyOperationContext context = { key, kSecKeyOperationTypeDecrypt, SecKeyCreateAlgorithmArray(algorithm) }; 1730 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, ciphertext, parameters, error); 1731 SecKeyOperationContextDestroy(&context); 1732 return result; 1733 } 1734 1735 CFDataRef SecKeyCreateDecryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext, CFErrorRef *error) { 1736 return SecKeyCreateDecryptedDataWithParameters(key, algorithm, ciphertext, NULL, error); 1737 } 1738 1739 CFDataRef SecKeyCopyKeyExchangeResult(SecKeyRef key, SecKeyAlgorithm algorithm, SecKeyRef publicKey, 1740 CFDictionaryRef parameters, CFErrorRef *error) { 1741 CFErrorRef localError = NULL; 1742 CFDataRef publicKeyData = NULL, result = NULL; 1743 SecKeyOperationContext context = { key, kSecKeyOperationTypeKeyExchange, SecKeyCreateAlgorithmArray(algorithm) }; 1744 require_quiet(publicKeyData = SecKeyCopyExternalRepresentation(publicKey, error), out); 1745 result = SecKeyRunAlgorithmAndCopyResult(&context, publicKeyData, parameters, &localError); 1746 SecKeyErrorPropagate(result != NULL, localError, error); 1747 1748 out: 1749 CFReleaseSafe(publicKeyData); 1750 SecKeyOperationContextDestroy(&context); 1751 return result; 1752 } 1753 1754 Boolean SecKeyIsAlgorithmSupported(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm) { 1755 SecKeyOperationContext context = { key, operation, SecKeyCreateAlgorithmArray(algorithm), kSecKeyOperationModeCheckIfSupported }; 1756 CFErrorRef error = NULL; 1757 CFTypeRef res = SecKeyRunAlgorithmAndCopyResult(&context, NULL, NULL, &error); 1758 Boolean result = CFEqualSafe(res, kCFBooleanTrue); 1759 CFReleaseSafe(res); 1760 CFReleaseSafe(error); 1761 SecKeyOperationContextDestroy(&context); 1762 return result; 1763 }