/ OSX / sec / Security / SecKey.m
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, &params, &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  }