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