]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecKey.m
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / sec / Security / 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
64 #include <asl.h>
65 #include <stdlib.h>
66 #include <os/lock.h>
67
68 #include <libDER/asn1Types.h>
69 #include <libDER/DER_Keys.h>
70 #include <libDER/DER_Encode.h>
71
72 CFDataRef SecKeyCopyPublicKeyHash(SecKeyRef key)
73 {
74 CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL;
75
76 /* encode the public key. */
77 require_noerr_quiet(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut);
78 require_quiet(pubKeyBlob, errOut);
79
80 /* Calculate the digest of the public key. */
81 require_quiet(pubKeyDigest = SecSHA1DigestCreate(CFGetAllocator(key),
82 CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)),
83 errOut);
84 errOut:
85 CFReleaseNull(pubKeyBlob);
86 return pubKeyDigest;
87 }
88
89
90 /*
91 */
92 static CFDictionaryRef SecKeyCopyAttributeDictionaryWithLocalKey(SecKeyRef key,
93 CFTypeRef keyType,
94 CFDataRef privateBlob)
95 {
96 CFAllocatorRef allocator = CFGetAllocator(key);
97 DICT_DECLARE(25);
98 CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL;
99 CFDictionaryRef dict = NULL;
100
101 size_t sizeValue = SecKeyGetSize(key, kSecKeyKeySizeInBits);
102 CFNumberRef sizeInBits = CFNumberCreate(allocator, kCFNumberLongType, &sizeValue);
103
104 /* encode the public key. */
105 require_noerr_quiet(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut);
106 require_quiet(pubKeyBlob, errOut);
107
108 /* Calculate the digest of the public key. */
109 require_quiet(pubKeyDigest = SecSHA1DigestCreate(allocator,
110 CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)),
111 errOut);
112
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);
126 DICT_ADDPAIR(kSecAttrCanEncrypt, privateBlob ? kCFBooleanFalse : kCFBooleanTrue);
127 DICT_ADDPAIR(kSecAttrCanDecrypt, privateBlob ? kCFBooleanTrue : kCFBooleanFalse);
128 DICT_ADDPAIR(kSecAttrCanDerive, kCFBooleanTrue);
129 DICT_ADDPAIR(kSecAttrCanSign, privateBlob ? kCFBooleanTrue : kCFBooleanFalse);
130 DICT_ADDPAIR(kSecAttrCanVerify, privateBlob ? kCFBooleanFalse : kCFBooleanTrue);
131 DICT_ADDPAIR(kSecAttrCanSignRecover, kCFBooleanFalse);
132 DICT_ADDPAIR(kSecAttrCanVerifyRecover, kCFBooleanFalse);
133 DICT_ADDPAIR(kSecAttrCanWrap, privateBlob ? kCFBooleanFalse : kCFBooleanTrue);
134 DICT_ADDPAIR(kSecAttrCanUnwrap, privateBlob ? kCFBooleanTrue : kCFBooleanFalse);
135 DICT_ADDPAIR(kSecValueData, privateBlob ? privateBlob : pubKeyBlob);
136 dict = CFDictionaryCreate(allocator, keys, values, numValues, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
137
138 errOut:
139 // @@@ Zero out key material.
140 CFReleaseSafe(pubKeyDigest);
141 CFReleaseSafe(pubKeyBlob);
142 CFReleaseSafe(sizeInBits);
143
144 return dict;
145 }
146
147 CFDictionaryRef SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key,
148 CFTypeRef keyType,
149 CFDataRef privateBlob)
150 {
151 return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, privateBlob);
152 }
153
154 CFDictionaryRef SecKeyGeneratePublicAttributeDictionary(SecKeyRef key, CFTypeRef keyType)
155 {
156 return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, NULL);
157 }
158
159 static CFStringRef SecKeyCopyDescription(CFTypeRef cf) {
160 SecKeyRef key = (SecKeyRef)cf;
161
162 if(key->key_class->describe)
163 return key->key_class->describe(key);
164 else
165 return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef: %p>"), key);
166 }
167
168 #if TARGET_OS_OSX
169 static CFMutableDictionaryRef auxilliaryCDSAKeyMap;
170 static struct os_unfair_lock_s auxilliaryCDSAKeyMapLock = OS_UNFAIR_LOCK_INIT;
171
172 static void SecKeyDestroyAuxilliaryCDSAKeyForKey(CFTypeRef cf) {
173 CFTypeRef keyToDestroy = NULL;
174 os_unfair_lock_lock(&auxilliaryCDSAKeyMapLock);
175 if (auxilliaryCDSAKeyMap != NULL) {
176 keyToDestroy = CFDictionaryGetValue(auxilliaryCDSAKeyMap, cf);
177 if (keyToDestroy != NULL) {
178 CFRetain(keyToDestroy);
179 CFDictionaryRemoveValue(auxilliaryCDSAKeyMap, cf);
180 }
181 }
182 os_unfair_lock_unlock(&auxilliaryCDSAKeyMapLock);
183
184 // Actual aux key destruction is performed outside unfair lock to avoid recursive lock.
185 if (keyToDestroy != NULL) {
186 CFRelease(keyToDestroy);
187 }
188 }
189
190 void 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
200 SecKeyRef 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
212 static void SecKeyDestroy(CFTypeRef cf) {
213 SecKeyRef key = (SecKeyRef)cf;
214 #if TARGET_OS_OSX
215 SecKeyDestroyAuxilliaryCDSAKeyForKey(cf);
216 #endif
217 if (key->key_class->destroy)
218 key->key_class->destroy(key);
219 }
220
221 static Boolean SecKeyEqual(CFTypeRef cf1, CFTypeRef cf2)
222 {
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;
229 if (key1->key_class->version >= 4 && key1->key_class->isEqual)
230 return key1->key_class->isEqual(key1, key2);
231 if (key1->key_class->extraBytes)
232 return !memcmp(key1->key, key2->key, key1->key_class->extraBytes);
233
234 /* TODO: Won't work when we get reference keys. */
235 CFDictionaryRef d1, d2;
236 d1 = SecKeyCopyAttributeDictionary(key1);
237 d2 = SecKeyCopyAttributeDictionary(key2);
238 // Returning NULL is an error; bail out of the equality check
239 if(!d1 || !d2) {
240 CFReleaseSafe(d1);
241 CFReleaseSafe(d2);
242 return false;
243 }
244 Boolean result = CFEqual(d1, d2);
245 CFReleaseSafe(d1);
246 CFReleaseSafe(d2);
247 return result;
248 }
249
250 struct ccrng_state *ccrng_seckey;
251
252 CFGiblisWithFunctions(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 })
257
258 static 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 }
267
268 return default_value;
269 }
270
271 static 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);
280 }
281
282 static 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. */
290 static CF_RETURNS_RETAINED CFMutableDictionaryRef merge_params(CFDictionaryRef dict,
291 CFStringRef key) {
292 CFDictionaryRef subdict = CFDictionaryGetValue(dict, key);
293 CFMutableDictionaryRef result;
294
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 }
302
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);
308
309 return result;
310 }
311
312 CFIndex SecKeyGetAlgorithmId(SecKeyRef key) {
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 }
322 /* All version 0 keys were RSA. */
323 return kSecRSAAlgorithmID;
324 }
325
326 /* Generate a private/public keypair. */
327 OSStatus SecKeyGeneratePair(CFDictionaryRef parameters,
328 SecKeyRef *publicKey, SecKeyRef *privateKey) {
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 }
347
348 require_noerr_quiet(result, errOut);
349
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 }
359
360 if (publicKey) {
361 *publicKey = pubKey;
362 pubKey = NULL;
363 }
364 if (privateKey) {
365 *privateKey = privKey;
366 privKey = NULL;
367 }
368
369 errOut:
370 CFReleaseSafe(pubParams);
371 CFReleaseSafe(privParams);
372 CFReleaseSafe(pubKey);
373 CFReleaseSafe(privKey);
374
375 return result;
376 }
377 }
378
379 SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey) {
380 return SecKeyCopyPublicKey(privateKey);
381 }
382
383 CFDictionaryRef CreatePrivateKeyMatchingQuery(SecKeyRef publicKey, bool returnPersistentRef)
384 {
385 const CFTypeRef refType = (returnPersistentRef) ? kSecReturnPersistentRef: kSecReturnRef;
386
387 CFDataRef public_key_hash = SecKeyCopyPublicKeyHash(publicKey);
388
389 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
390 kSecClass, kSecClassKey,
391 kSecAttrKeyClass, kSecAttrKeyClassPrivate,
392 kSecAttrSynchronizable, kSecAttrSynchronizableAny,
393 kSecAttrApplicationLabel, public_key_hash,
394 refType, kCFBooleanTrue,
395 NULL);
396 CFReleaseNull(public_key_hash);
397
398 return query;
399 }
400
401 CFDataRef 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);
407 fail:
408 CFReleaseNull(query);
409 return (CFDataRef)persistentRef;
410 }
411
412 SecKeyRef SecKeyCopyMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error) {
413 SecKeyRef privateKey = NULL;
414 CFTypeRef queryResult = NULL;
415 CFDictionaryRef query = NULL;
416
417 require_action_quiet(publicKey != NULL, errOut, SecError(errSecParam, error, CFSTR("Null Public Key")));
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);
423
424 if (CFGetTypeID(queryResult) == SecKeyGetTypeID()) {
425 privateKey = (SecKeyRef) queryResult;
426 queryResult = NULL;
427 }
428
429 errOut:
430 CFReleaseNull(query);
431 CFReleaseNull(queryResult);
432 return privateKey;
433 }
434
435 OSStatus SecKeyGetMatchingPrivateKeyStatus(SecKeyRef publicKey, CFErrorRef *error) {
436 OSStatus retval = errSecParam;
437 CFTypeRef private_key = NULL;
438 CFDictionaryRef query = NULL;
439
440 require_action_quiet(publicKey != NULL, errOut, SecError(errSecParam, error, NULL, CFSTR("Null Public Key")));
441
442 query = CreatePrivateKeyMatchingQuery(publicKey, false);
443
444 retval = SecItemCopyMatching(query, &private_key);
445
446 if (!retval && CFGetTypeID(private_key) != SecKeyGetTypeID()) {
447 retval = errSecInternalComponent;
448 }
449
450 errOut:
451 CFReleaseNull(query);
452 CFReleaseNull(private_key);
453 return retval;
454 }
455
456
457 SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator,
458 const SecAsn1Oid *oid, const SecAsn1Item *params,
459 const SecAsn1Item *keyData) {
460 SecKeyRef publicKey = NULL;
461 if (SecAsn1OidCompare(oid, &CSSMOID_RSA)) {
462 /* pkcs1 1 */
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,
468 keyData->Data, keyData->Length, kSecKeyEncodingPkcs1);
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 }
480 publicKey = SecKeyCreateECPublicKey(allocator,
481 (const uint8_t *)&derKey, sizeof(derKey), kSecDERKeyEncoding);
482 } else {
483 secwarning("Unsupported algorithm oid");
484 }
485
486 return publicKey;
487 }
488
489
490 SecKeyRef 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
524 out:
525
526 return NULL;
527 }
528
529 static const DERByte oidRSA[] = {
530 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
531 };
532 static const DERByte oidECsecp256[] = {
533 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
534 };
535 static const DERByte oidECsecp384[] = {
536 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
537 };
538 static const DERByte oidECsecp521[] = {
539 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
540 };
541
542
543 CFDataRef 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. */
555 require_noerr_quiet(SecKeyCopyPublicBytes(key, &publicKey), errOut);
556 require_quiet(publicKey, errOut);
557
558 require_quiet(CFDataGetLength(publicKey) != 0, errOut);
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.
578 CFIndex algorithm = SecKeyGetAlgorithmId(key);
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);
613 require_quiet(drtn == DR_Success, errOut);
614 CFDataSetLength(data, size);
615
616 dataret = CFRetain(data);
617 errOut:
618 CFReleaseNull(data);
619 CFReleaseNull(publicKey);
620
621 return dataret;
622 }
623
624
625
626 SecKeyRef SecKeyCreate(CFAllocatorRef allocator,
627 const SecKeyDescriptor *key_class, const uint8_t *keyData,
628 CFIndex keyDataLength, SecKeyEncoding encoding) {
629 if (!key_class) return NULL;
630 size_t size = sizeof(struct __SecKey) + key_class->extraBytes;
631 SecKeyRef result = (SecKeyRef)_CFRuntimeCreateInstance(allocator,
632 SecKeyGetTypeID(), size - sizeof(CFRuntimeBase), NULL);
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) {
644 secwarning("init %s key: %" PRIdOSStatus, key_class->name, status);
645 CFRelease(result);
646 result = NULL;
647 }
648 }
649 }
650 return result;
651 }
652
653 // Generic wrapper helper for invoking new-style CFDataRef-based operations with ptr/length arguments
654 // used by legacy RawSign-style functions.
655 static 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);
663 CFDataRef in2 = CFDataCreateWithBytesNoCopy(NULL, in2Ptr, in2Len, kCFAllocatorNull);
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);
675 }
676
677 out:
678 CFReleaseSafe(in1);
679 CFReleaseSafe(in2);
680 CFReleaseSafe(output);
681 if (error != NULL) {
682 status = SecErrorGetOSStatus(error);
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;
690 }
691
692 static 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
730 static 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
771 OSStatus SecKeyRawSign(
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 */
778 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding);
779 if (algorithm == NULL) {
780 return errSecParam;
781 }
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 });
786 }
787
788 #if TARGET_OS_OSX
789 OSStatus 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
808 OSStatus SecKeyRawVerify(
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 */
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) {
821 return SecKeyVerifySignature(key, algorithm, in1, in2, error)
822 ? kCFBooleanTrue : NULL;
823 });
824 return status;
825 }
826
827 #if TARGET_OS_OSX
828 OSStatus 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
848 static SecKeyAlgorithm SecKeyGetEncryptionAlgorithmForPadding(SecKeyRef key, SecPadding padding) {
849 switch (SecKeyGetAlgorithmId(key)) {
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;
863 }
864 }
865
866 OSStatus SecKeyEncrypt(
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 */
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 });
882 }
883
884 OSStatus SecKeyDecrypt(
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 */
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 });
912 }
913
914 size_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
922 CFDictionaryRef SecKeyCopyAttributeDictionary(SecKeyRef key) {
923 return SecKeyCopyAttributes(key);
924 }
925
926 SecKeyRef SecKeyCreateFromAttributeDictionary(CFDictionaryRef refAttributes) {
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);
934 }
935 return key;
936 }
937
938 static 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 } },
967 { &CSSMOID_MD5WithRSA, NULL, {
968 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5,
969 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5,
970 } },
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;
997 switch (SecKeyGetAlgorithmId(key)) {
998 case kSecRSAAlgorithmID:
999 table = translationTableRSA;
1000 break;
1001 case kSecECDSAAlgorithmID:
1002 table = translationTableECDSA;
1003 break;
1004 default:
1005 return NULL;
1006 }
1007
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 }
1013 }
1014 return NULL;
1015 }
1016
1017 OSStatus SecKeyDigestAndVerify(
1018 SecKeyRef key, /* Private key */
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 */
1024
1025 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, true);
1026 if (algorithm == NULL) {
1027 return errSecUnimplemented;
1028 }
1029
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 });
1035 }
1036
1037 OSStatus SecKeyDigestAndSign(
1038 SecKeyRef key, /* Private key */
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 */
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 });
1053 }
1054
1055 OSStatus SecKeyVerifyDigest(
1056 SecKeyRef key, /* Private key */
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 */
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 });
1072 }
1073
1074 OSStatus SecKeySignDigest(
1075 SecKeyRef key, /* Private key */
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 */
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 });
1090 }
1091
1092 #if TARGET_OS_OSX
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
1098 // Export original SecKeyGetAlgorithmID symbol for backward binary compatibility.
1099 #undef SecKeyGetAlgorithmID
1100 CFIndex SecKeyGetAlgorithmID(SecKeyRef key);
1101 CFIndex SecKeyGetAlgorithmID(SecKeyRef key) {
1102 return SecKeyGetAlgorithmId(key);
1103 }
1104 #endif
1105
1106 OSStatus 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
1112 SecKeyRef 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
1129 SecKeyRef 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.
1136 size_t SecKeyGetSize(SecKeyRef key, SecKeySize whichSize)
1137 {
1138 size_t result = SecKeyGetBlockSize(key);
1139
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)) {
1147 switch (whichSize) {
1148 case kSecKeyEncryptedDataSize:
1149 result = 0;
1150 break;
1151 case kSecKeySignatureSize:
1152 result = (result >= 66 ? 9 : 8) + 2 * result;
1153 break;
1154 case kSecKeyKeySizeInBits:
1155 if (result >= 66)
1156 return 521;
1157 }
1158 }
1159
1160 if (whichSize == kSecKeyKeySizeInBits)
1161 result *= 8;
1162
1163 return result;
1164
1165 }
1166
1167 OSStatus 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);
1176
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 }
1186
1187 CFReleaseSafe(foundRef);
1188 CFReleaseSafe(query);
1189
1190 return status;
1191 }
1192
1193 OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef)
1194 {
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;
1202 }
1203
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);
1211
1212 if (status == errSecSuccess) {
1213 if (CFGetTypeID(foundRef) == CFDataGetTypeID()) {
1214 *persistentRef = foundRef;
1215 foundRef = NULL;
1216 } else {
1217 secerror("SecKeyCopyPersistentRef: SecItemCopyMatching returned success, but we got type %lu instead of CFData for key %@.", CFGetTypeID(foundRef), key);
1218 status = errSecItemNotFound;
1219 }
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);
1225 }
1226
1227 CFReleaseSafe(foundRef);
1228 CFReleaseSafe(query);
1229
1230 return status;
1231 }
1232
1233 /*
1234 *
1235 */
1236
1237 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
1238
1239 SEC_CONST_DECL(_kSecKeyWrapPGPSymAlg, "kSecKeyWrapPGPSymAlg");
1240 SEC_CONST_DECL(_kSecKeyWrapPGPFingerprint, "kSecKeyWrapPGPFingerprint");
1241 SEC_CONST_DECL(_kSecKeyWrapPGPWrapAlg, "kSecKeyWrapPGPWrapAlg");
1242 SEC_CONST_DECL(_kSecKeyWrapRFC6637Flags, "kSecKeyWrapPGPECFlags");
1243 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA256KekAES128, "kSecKeyWrapPGPECWrapDigestSHA256KekAES128");
1244 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA512KekAES256, "kSecKeyWrapPGPECWrapDigestSHA512KekAES256");
1245
1246 #undef SEC_CONST_DECL
1247
1248 CFDataRef
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
1261 CFDataRef
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 }
1274
1275 static 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);
1290 }
1291 }
1292
1293 if (value != NULL && CFGetTypeID(value) == CFNumberGetTypeID()) {
1294 if (!CFNumberGetValue(value, kCFNumberCFIndexType, &result) || result < 0) {
1295 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value);
1296 }
1297 } else {
1298 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value);
1299 }
1300
1301 CFReleaseSafe(localValue);
1302 return result;
1303 }
1304
1305 SecKeyRef SecKeyCreateWithData(CFDataRef keyData, CFDictionaryRef parameters, CFErrorRef *error) {
1306
1307 SecKeyRef key = NULL;
1308 CFAllocatorRef allocator = NULL;
1309
1310 if (CFDictionaryGetValue(parameters, kSecAttrTokenID) != NULL) {
1311 return SecKeyCreateCTKKey(allocator, parameters, error);
1312 }
1313 else if (!keyData) {
1314 SecError(errSecParam, error, CFSTR("Failed to provide key data to SecKeyCreateWithData"));
1315 return NULL;
1316 }
1317 /* First figure out the key type (algorithm). */
1318 CFIndex algorithm, class;
1319 CFTypeRef ktype = CFDictionaryGetValue(parameters, kSecAttrKeyType);
1320 require_quiet((algorithm = SecKeyParamsGetCFIndex(ktype, CFSTR("key type"), error)) >= 0, out);
1321 CFTypeRef kclass = CFDictionaryGetValue(parameters, kSecAttrKeyClass);
1322 require_quiet((class = SecKeyParamsGetCFIndex(kclass, CFSTR("key class"), error)) >= 0, out);
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
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) {
1365 SecError(errSecParam, error, CFSTR("EC private key creation from data failed"));
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
1381 out:
1382 return key;
1383 }
1384
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.
1386 static 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
1399 CFDataRef SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
1400 if (!key->key_class->copyExternalRepresentation) {
1401 if (error != NULL) {
1402 *error = NULL;
1403 }
1404 SecError(errSecUnimplemented, error, CFSTR("export not implemented for key %@"), key);
1405 return NULL;
1406 }
1407
1408 CFErrorRef localError = NULL;
1409 CFDataRef result = key->key_class->copyExternalRepresentation(key, &localError);
1410 SecKeyErrorPropagate(result != NULL, localError, error);
1411 return result;
1412 }
1413
1414 CFDictionaryRef SecKeyCopyAttributes(SecKeyRef key) {
1415 if (key->key_class->copyDictionary) {
1416 return key->key_class->copyDictionary(key);
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
1427 switch (SecKeyGetAlgorithmId(key)) {
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 }
1444 }
1445
1446 SecKeyRef 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
1460 result = SecKeyCreateFromPublicData(kCFAllocatorDefault, SecKeyGetAlgorithmId(key), serializedPublic);
1461
1462 fail:
1463 CFReleaseSafe(serializedPublic);
1464 return result;
1465 }
1466
1467 SecKeyRef SecKeyCreateRandomKey(CFDictionaryRef parameters, CFErrorRef *error) {
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);
1476 }
1477 CFReleaseSafe(pubKey);
1478 return privKey;
1479 }
1480 }
1481
1482 SecKeyRef 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
1490 Boolean SecKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) {
1491 if (key == NULL) {
1492 SecCTKKeySetTestMode(name, value);
1493 return true;
1494 } else if (key->key_class->version >= 4 && key->key_class->setParameter) {
1495 CFErrorRef localError = NULL;
1496 Boolean result = key->key_class->setParameter(key, name, value, &localError);
1497 SecKeyErrorPropagate(result, localError, error);
1498 return result;
1499 } else {
1500 if (error != NULL) {
1501 *error = NULL;
1502 }
1503 return SecError(errSecUnimplemented, error, CFSTR("setParameter not implemented for %@"), key);
1504 }
1505 }
1506
1507 #pragma mark Generic algorithm adaptor lookup and invocation
1508
1509 static CFTypeRef SecKeyCopyBackendOperationResult(SecKeyOperationContext *context, SecKeyAlgorithm algorithm,
1510 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
1511 CFTypeRef result = kCFNull;
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;
1533 CFIndex keyAlg = SecKeyGetAlgorithmId(context->key);
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
1605 out:
1606 return result;
1607 }
1608
1609 CFTypeRef SecKeyRunAlgorithmAndCopyResult(SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
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 }
1618 }
1619
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 }
1626
1627 // To silence static analyzer.
1628 CFReleaseSafe(output);
1629
1630 // Get adaptor which is able to handle requested algorithm.
1631 SecKeyAlgorithmAdaptor adaptor = SecKeyGetAlgorithmAdaptor(context->operation, algorithm);
1632 require_quiet(adaptor != NULL, fail);
1633
1634 // Invoke the adaptor and return result.
1635 CFTypeRef result = adaptor(context, in1, in2, error);
1636 require_quiet(result != kCFNull, fail);
1637 return result;
1638
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 }
1647 }
1648 }
1649
1650 #pragma mark Algorithm-related SecKey API entry points
1651
1652 static CFMutableArrayRef SecKeyCreateAlgorithmArray(SecKeyAlgorithm algorithm) {
1653 CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
1654 CFArrayAppendValue(result, algorithm);
1655 return result;
1656 }
1657
1658 CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error) {
1659 CFErrorRef localError = NULL;
1660 SecKeyOperationContext context = { key, kSecKeyOperationTypeSign, SecKeyCreateAlgorithmArray(algorithm) };
1661 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, dataToSign, NULL, &localError);
1662 SecKeyOperationContextDestroy(&context);
1663 SecKeyErrorPropagate(result != NULL, localError, error);
1664 return result;
1665 }
1666
1667 Boolean SecKeyVerifySignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef signedData, CFDataRef signature,
1668 CFErrorRef *error) {
1669 CFErrorRef localError = NULL;
1670 SecKeyOperationContext context = { key, kSecKeyOperationTypeVerify, SecKeyCreateAlgorithmArray(algorithm) };
1671 CFTypeRef res = SecKeyRunAlgorithmAndCopyResult(&context, signedData, signature, &localError);
1672 Boolean result = CFEqualSafe(res, kCFBooleanTrue);
1673 CFReleaseSafe(res);
1674 SecKeyOperationContextDestroy(&context);
1675 SecKeyErrorPropagate(result, localError, error);
1676 return result;
1677 }
1678
1679 CFDataRef SecKeyCreateEncryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext,
1680 CFDictionaryRef parameters, CFErrorRef *error) {
1681 CFErrorRef localError = NULL;
1682 SecKeyOperationContext context = { key, kSecKeyOperationTypeEncrypt, SecKeyCreateAlgorithmArray(algorithm) };
1683 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, plaintext, parameters, &localError);
1684 SecKeyOperationContextDestroy(&context);
1685 SecKeyErrorPropagate(result, localError, error);
1686 return result;
1687 }
1688
1689 CFDataRef SecKeyCreateEncryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext, CFErrorRef *error) {
1690 return SecKeyCreateEncryptedDataWithParameters(key, algorithm, plaintext, NULL, error);
1691 }
1692
1693 CFDataRef SecKeyCreateDecryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext,
1694 CFDictionaryRef parameters, CFErrorRef *error) {
1695 SecKeyOperationContext context = { key, kSecKeyOperationTypeDecrypt, SecKeyCreateAlgorithmArray(algorithm) };
1696 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, ciphertext, parameters, error);
1697 SecKeyOperationContextDestroy(&context);
1698 return result;
1699 }
1700
1701 CFDataRef SecKeyCreateDecryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext, CFErrorRef *error) {
1702 return SecKeyCreateDecryptedDataWithParameters(key, algorithm, ciphertext, NULL, error);
1703 }
1704
1705 CFDataRef SecKeyCopyKeyExchangeResult(SecKeyRef key, SecKeyAlgorithm algorithm, SecKeyRef publicKey,
1706 CFDictionaryRef parameters, CFErrorRef *error) {
1707 CFErrorRef localError = NULL;
1708 CFDataRef publicKeyData = NULL, result = NULL;
1709 SecKeyOperationContext context = { key, kSecKeyOperationTypeKeyExchange, SecKeyCreateAlgorithmArray(algorithm) };
1710 require_quiet(publicKeyData = SecKeyCopyExternalRepresentation(publicKey, error), out);
1711 result = SecKeyRunAlgorithmAndCopyResult(&context, publicKeyData, parameters, &localError);
1712 SecKeyErrorPropagate(result != NULL, localError, error);
1713
1714 out:
1715 CFReleaseSafe(publicKeyData);
1716 SecKeyOperationContextDestroy(&context);
1717 return result;
1718 }
1719
1720 Boolean 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 }