]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecKey.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / sec / Security / SecKey.c
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.c - CoreFoundation based key object
26 */
27 #include <Security/SecBase.h>
28
29 #include <Security/SecKeyInternal.h>
30 #include <Security/SecItem.h>
31 #include <Security/SecItemPriv.h>
32 #include <Security/SecItemShim.h>
33 #include <Security/SecFramework.h>
34
35 #include <utilities/SecIOFormat.h>
36
37 #include <utilities/SecCFWrappers.h>
38 #include <utilities/array_size.h>
39
40 #include "SecRSAKeyPriv.h"
41 #include "SecECKeyPriv.h"
42 #include "SecCTKKeyPriv.h"
43 #include "SecBasePriv.h"
44 #include <Security/SecKeyPriv.h>
45
46 #include <CoreFoundation/CFNumber.h>
47 #include <CoreFoundation/CFString.h>
48 #include <pthread.h>
49 #include <string.h>
50 #include <AssertMacros.h>
51 #include <utilities/debugging.h>
52 #include <utilities/SecCFError.h>
53 #include <CommonCrypto/CommonDigest.h>
54 #include <Security/SecAsn1Coder.h>
55 #include <Security/oidsalg.h>
56 #include <Security/SecInternal.h>
57 #include <Security/SecRandom.h>
58 #include <Security/SecureTransport.h> /* For error codes. */
59
60 #include <corecrypto/ccrng_system.h>
61
62 #include <asl.h>
63 #include <stdlib.h>
64 #include <syslog.h>
65
66 #include <libDER/asn1Types.h>
67 #include <libDER/DER_Keys.h>
68 #include <libDER/DER_Encode.h>
69
70 CFDataRef SecKeyCopyPublicKeyHash(SecKeyRef key)
71 {
72 CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL;
73
74 /* encode the public key. */
75 require_noerr_quiet(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut);
76 require_quiet(pubKeyBlob, errOut);
77
78 /* Calculate the digest of the public key. */
79 require_quiet(pubKeyDigest = SecSHA1DigestCreate(CFGetAllocator(key),
80 CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)),
81 errOut);
82 errOut:
83 CFReleaseNull(pubKeyBlob);
84 return pubKeyDigest;
85 }
86
87
88 /*
89 */
90 static CFDictionaryRef SecKeyCopyAttributeDictionaryWithLocalKey(SecKeyRef key,
91 CFTypeRef keyType,
92 CFDataRef privateBlob)
93 {
94 CFAllocatorRef allocator = CFGetAllocator(key);
95 DICT_DECLARE(25);
96 CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL;
97 CFDictionaryRef dict = NULL;
98
99 size_t sizeValue = SecKeyGetSize(key, kSecKeyKeySizeInBits);
100 CFNumberRef sizeInBits = CFNumberCreate(allocator, kCFNumberLongType, &sizeValue);
101
102 /* encode the public key. */
103 require_noerr_quiet(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut);
104 require_quiet(pubKeyBlob, errOut);
105
106 /* Calculate the digest of the public key. */
107 require_quiet(pubKeyDigest = SecSHA1DigestCreate(allocator,
108 CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)),
109 errOut);
110
111 DICT_ADDPAIR(kSecClass, kSecClassKey);
112 DICT_ADDPAIR(kSecAttrKeyClass, privateBlob ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic);
113 DICT_ADDPAIR(kSecAttrApplicationLabel, pubKeyDigest);
114 DICT_ADDPAIR(kSecAttrIsPermanent, kCFBooleanTrue);
115 DICT_ADDPAIR(kSecAttrIsPrivate, kCFBooleanTrue);
116 DICT_ADDPAIR(kSecAttrIsModifiable, kCFBooleanTrue);
117 DICT_ADDPAIR(kSecAttrKeyType, keyType);
118 DICT_ADDPAIR(kSecAttrKeySizeInBits, sizeInBits);
119 DICT_ADDPAIR(kSecAttrEffectiveKeySize, sizeInBits);
120 DICT_ADDPAIR(kSecAttrIsSensitive, kCFBooleanFalse);
121 DICT_ADDPAIR(kSecAttrWasAlwaysSensitive, kCFBooleanFalse);
122 DICT_ADDPAIR(kSecAttrIsExtractable, kCFBooleanTrue);
123 DICT_ADDPAIR(kSecAttrWasNeverExtractable, kCFBooleanFalse);
124 DICT_ADDPAIR(kSecAttrCanEncrypt, privateBlob ? kCFBooleanFalse : kCFBooleanTrue);
125 DICT_ADDPAIR(kSecAttrCanDecrypt, privateBlob ? kCFBooleanTrue : kCFBooleanFalse);
126 DICT_ADDPAIR(kSecAttrCanDerive, kCFBooleanTrue);
127 DICT_ADDPAIR(kSecAttrCanSign, privateBlob ? kCFBooleanTrue : kCFBooleanFalse);
128 DICT_ADDPAIR(kSecAttrCanVerify, privateBlob ? kCFBooleanFalse : kCFBooleanTrue);
129 DICT_ADDPAIR(kSecAttrCanSignRecover, kCFBooleanFalse);
130 DICT_ADDPAIR(kSecAttrCanVerifyRecover, kCFBooleanFalse);
131 DICT_ADDPAIR(kSecAttrCanWrap, privateBlob ? kCFBooleanFalse : kCFBooleanTrue);
132 DICT_ADDPAIR(kSecAttrCanUnwrap, privateBlob ? kCFBooleanTrue : kCFBooleanFalse);
133 DICT_ADDPAIR(kSecValueData, privateBlob ? privateBlob : pubKeyBlob);
134 dict = DICT_CREATE(allocator);
135
136 errOut:
137 // @@@ Zero out key material.
138 CFReleaseSafe(pubKeyDigest);
139 CFReleaseSafe(pubKeyBlob);
140 CFReleaseSafe(sizeInBits);
141
142 return dict;
143 }
144
145 CFDictionaryRef SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key,
146 CFTypeRef keyType,
147 CFDataRef privateBlob)
148 {
149 return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, privateBlob);
150 }
151
152 CFDictionaryRef SecKeyGeneratePublicAttributeDictionary(SecKeyRef key, CFTypeRef keyType)
153 {
154 return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, NULL);
155 }
156
157 static CFStringRef SecKeyCopyDescription(CFTypeRef cf) {
158 SecKeyRef key = (SecKeyRef)cf;
159
160 if(key->key_class->describe)
161 return key->key_class->describe(key);
162 else
163 return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef: %p>"), key);
164 }
165
166 static void SecKeyDestroy(CFTypeRef cf) {
167 SecKeyRef key = (SecKeyRef)cf;
168 #if !TARGET_OS_IPHONE
169 CFReleaseSafe(key->cdsaKey);
170 #endif
171 if (key->key_class->destroy)
172 key->key_class->destroy(key);
173 }
174
175 static Boolean SecKeyEqual(CFTypeRef cf1, CFTypeRef cf2)
176 {
177 SecKeyRef key1 = (SecKeyRef)cf1;
178 SecKeyRef key2 = (SecKeyRef)cf2;
179 if (key1 == key2)
180 return true;
181 if (!key2 || key1->key_class != key2->key_class)
182 return false;
183 if (key1->key_class->version >= 4 && key1->key_class->isEqual)
184 return key1->key_class->isEqual(key1, key2);
185 if (key1->key_class->extraBytes)
186 return !memcmp(key1->key, key2->key, key1->key_class->extraBytes);
187
188 /* TODO: Won't work when we get reference keys. */
189 CFDictionaryRef d1, d2;
190 d1 = SecKeyCopyAttributeDictionary(key1);
191 d2 = SecKeyCopyAttributeDictionary(key2);
192 // Returning NULL is an error; bail out of the equality check
193 if(!d1 || !d2) {
194 CFReleaseSafe(d1);
195 CFReleaseSafe(d2);
196 return false;
197 }
198 Boolean result = CFEqual(d1, d2);
199 CFReleaseSafe(d1);
200 CFReleaseSafe(d2);
201 return result;
202 }
203
204 struct ccrng_state *ccrng_seckey;
205
206 CFGiblisWithFunctions(SecKey, NULL, NULL, SecKeyDestroy, SecKeyEqual, NULL, NULL, SecKeyCopyDescription, NULL, NULL, ^{
207 static struct ccrng_system_state ccrng_system_state_seckey;
208 ccrng_seckey = (struct ccrng_state *)&ccrng_system_state_seckey;
209 ccrng_system_init(&ccrng_system_state_seckey);
210 })
211
212 static bool getBoolForKey(CFDictionaryRef dict, CFStringRef key, bool default_value) {
213 CFTypeRef value = CFDictionaryGetValue(dict, key);
214 if (value) {
215 if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
216 return CFBooleanGetValue(value);
217 } else {
218 secwarning("Value %@ for key %@ is not bool", value, key);
219 }
220 }
221
222 return default_value;
223 }
224
225 static OSStatus add_ref(CFTypeRef item, CFMutableDictionaryRef dict) {
226 CFDictionarySetValue(dict, kSecValueRef, item);
227 return SecItemAdd(dict, NULL);
228 }
229
230 static void merge_params_applier(const void *key, const void *value,
231 void *context) {
232 CFMutableDictionaryRef result = (CFMutableDictionaryRef)context;
233 CFDictionaryAddValue(result, key, value);
234 }
235
236 /* Create a mutable dictionary that is based on the subdictionary for key
237 with any attributes from the top level dict merged in. */
238 static CF_RETURNS_RETAINED CFMutableDictionaryRef merge_params(CFDictionaryRef dict,
239 CFStringRef key) {
240 CFDictionaryRef subdict = CFDictionaryGetValue(dict, key);
241 CFMutableDictionaryRef result;
242
243 if (subdict) {
244 result = CFDictionaryCreateMutableCopy(NULL, 0, subdict);
245 /* Add everything in dict not already in result to result. */
246 CFDictionaryApplyFunction(dict, merge_params_applier, result);
247 } else {
248 result = CFDictionaryCreateMutableCopy(NULL, 0, dict);
249 }
250
251 /* Remove values that only belong in the top level dict. */
252 CFDictionaryRemoveValue(result, kSecPublicKeyAttrs);
253 CFDictionaryRemoveValue(result, kSecPrivateKeyAttrs);
254 CFDictionaryRemoveValue(result, kSecAttrKeyType);
255 CFDictionaryRemoveValue(result, kSecAttrKeySizeInBits);
256
257 return result;
258 }
259
260 CFIndex SecKeyGetAlgorithmIdentifier(SecKeyRef key) {
261 if (!key || !key->key_class) {
262 // TBD: somehow, a key can be created with a NULL key_class in the
263 // SecCertificateCopyPublicKey -> SecKeyCreatePublicFromDER code path
264 return kSecNullAlgorithmID;
265 }
266 /* This method was added to version 1 keys. */
267 if (key->key_class->version > 0 && key->key_class->getAlgorithmID) {
268 return key->key_class->getAlgorithmID(key);
269 }
270 /* All version 0 keys were RSA. */
271 return kSecRSAAlgorithmID;
272 }
273
274 /* Generate a private/public keypair. */
275 OSStatus SecKeyGeneratePair(CFDictionaryRef parameters,
276 SecKeyRef *publicKey, SecKeyRef *privateKey) {
277 OSStatus result = errSecUnsupportedAlgorithm;
278 SecKeyRef privKey = NULL;
279 SecKeyRef pubKey = NULL;
280 CFMutableDictionaryRef pubParams = merge_params(parameters, kSecPublicKeyAttrs),
281 privParams = merge_params(parameters, kSecPrivateKeyAttrs);
282 CFStringRef ktype = CFDictionaryGetValue(parameters, kSecAttrKeyType);
283 CFStringRef tokenID = CFDictionaryGetValue(parameters, kSecAttrTokenID);
284
285 require_quiet(ktype, errOut);
286
287 if (tokenID != NULL) {
288 result = SecCTKKeyGeneratePair(parameters, &pubKey, &privKey);
289 } else if (CFEqual(ktype, kSecAttrKeyTypeECSECPrimeRandom)) {
290 result = SecECKeyGeneratePair(parameters, &pubKey, &privKey);
291 } else if (CFEqual(ktype, kSecAttrKeyTypeRSA)) {
292 result = SecRSAKeyGeneratePair(parameters, &pubKey, &privKey);
293 }
294
295 require_noerr_quiet(result, errOut);
296
297 /* Store the keys in the keychain if they are marked as permanent. */
298 if (getBoolForKey(pubParams, kSecAttrIsPermanent, false)) {
299 require_noerr_quiet(result = add_ref(pubKey, pubParams), errOut);
300 }
301 /* Token-based private keys are automatically stored on the token. */
302 if (tokenID == NULL && getBoolForKey(privParams, kSecAttrIsPermanent, false)) {
303 require_noerr_quiet(result = add_ref(privKey, privParams), errOut);
304 }
305
306 if (publicKey) {
307 *publicKey = pubKey;
308 pubKey = NULL;
309 }
310 if (privateKey) {
311 *privateKey = privKey;
312 privKey = NULL;
313 }
314
315 errOut:
316 CFReleaseSafe(pubParams);
317 CFReleaseSafe(privParams);
318 CFReleaseSafe(pubKey);
319 CFReleaseSafe(privKey);
320
321 return result;
322 }
323
324 SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey) {
325 return SecKeyCopyPublicKey(privateKey);
326 }
327
328 CFDictionaryRef CreatePrivateKeyMatchingQuery(SecKeyRef publicKey, bool returnPersistentRef)
329 {
330 const CFTypeRef refType = (returnPersistentRef) ? kSecReturnPersistentRef: kSecReturnRef;
331
332 CFDataRef public_key_hash = SecKeyCopyPublicKeyHash(publicKey);
333
334 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
335 kSecClass, kSecClassKey,
336 kSecAttrKeyClass, kSecAttrKeyClassPrivate,
337 kSecAttrSynchronizable, kSecAttrSynchronizableAny,
338 kSecAttrApplicationLabel, public_key_hash,
339 refType, kCFBooleanTrue,
340 NULL);
341 CFReleaseNull(public_key_hash);
342
343 return query;
344 }
345
346 CFDataRef SecKeyCreatePersistentRefToMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error) {
347 CFTypeRef persistentRef = NULL;
348 CFDictionaryRef query = CreatePrivateKeyMatchingQuery(publicKey, true);
349
350 require_quiet(SecError(SecItemCopyMatching(query, &persistentRef),error ,
351 CFSTR("Error finding persistent ref to key from public: %@"), publicKey), fail);
352 fail:
353 CFReleaseNull(query);
354 return (CFDataRef)persistentRef;
355 }
356
357 SecKeyRef SecKeyCopyMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error) {
358 SecKeyRef privateKey = NULL;
359 CFTypeRef queryResult = NULL;
360 CFDictionaryRef query = NULL;
361
362 require_action_quiet(publicKey != NULL, errOut, SecError(errSecParam, error, CFSTR("Null Public Key")));
363
364 query = CreatePrivateKeyMatchingQuery(publicKey, false);
365
366 require_quiet(SecError(SecItemCopyMatching(query, &queryResult), error,
367 CFSTR("Error finding private key from public: %@"), publicKey), errOut);
368
369 if (CFGetTypeID(queryResult) == SecKeyGetTypeID()) {
370 privateKey = (SecKeyRef) queryResult;
371 queryResult = NULL;
372 }
373
374 errOut:
375 CFReleaseNull(query);
376 CFReleaseNull(queryResult);
377 return privateKey;
378 }
379
380 OSStatus SecKeyGetMatchingPrivateKeyStatus(SecKeyRef publicKey, CFErrorRef *error) {
381 OSStatus retval = errSecParam;
382 CFTypeRef private_key = NULL;
383 CFDictionaryRef query = NULL;
384
385 require_action_quiet(publicKey != NULL, errOut, SecError(errSecParam, error, NULL, CFSTR("Null Public Key")));
386
387 query = CreatePrivateKeyMatchingQuery(publicKey, false);
388
389 retval = SecItemCopyMatching(query, &private_key);
390
391 if (!retval && CFGetTypeID(private_key) != SecKeyGetTypeID()) {
392 retval = errSecInternalComponent;
393 }
394
395 errOut:
396 CFReleaseNull(query);
397 CFReleaseNull(private_key);
398 return retval;
399 }
400
401
402 SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator,
403 const SecAsn1Oid *oid, const SecAsn1Item *params,
404 const SecAsn1Item *keyData) {
405 SecKeyRef publicKey = NULL;
406 if (SecAsn1OidCompare(oid, &CSSMOID_RSA)) {
407 /* pkcs1 1 */
408 /* Note that we call SecKeyCreateRSAPublicKey_ios directly instead of
409 SecKeyCreateRSAPublicKey, since on OS X the latter function will return
410 a CSSM SecKeyRef, and we always want an iOS format SecKeyRef here.
411 */
412 publicKey = SecKeyCreateRSAPublicKey_ios(allocator,
413 keyData->Data, keyData->Length, kSecKeyEncodingPkcs1);
414 } else if (SecAsn1OidCompare(oid, &CSSMOID_ecPublicKey)) {
415 SecDERKey derKey = {
416 .oid = oid->Data,
417 .oidLength = oid->Length,
418 .key = keyData->Data,
419 .keyLength = keyData->Length,
420 };
421 if (params) {
422 derKey.parameters = params->Data;
423 derKey.parametersLength = params->Length;
424 }
425 publicKey = SecKeyCreateECPublicKey(allocator,
426 (const uint8_t *)&derKey, sizeof(derKey), kSecDERKeyEncoding);
427 } else {
428 secwarning("Unsupported algorithm oid");
429 }
430
431 return publicKey;
432 }
433
434
435 SecKeyRef SecKeyCreateFromSubjectPublicKeyInfoData(CFAllocatorRef allocator, CFDataRef subjectPublicKeyInfoData)
436 {
437 DERReturn drtn;
438
439 DERItem subjectPublicKeyInfoDER = {
440 .data = (uint8_t *)CFDataGetBytePtr(subjectPublicKeyInfoData),
441 .length = (DERSize)CFDataGetLength(subjectPublicKeyInfoData),
442 };
443 DERSubjPubKeyInfo subjectPublicKeyInfo;
444 DERAlgorithmId algorithmId;
445 DERItem pubKeyBytes;
446
447 drtn = DERParseSequence(&subjectPublicKeyInfoDER,
448 DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs,
449 &subjectPublicKeyInfo, sizeof(subjectPublicKeyInfo));
450
451 require_noerr_quiet(drtn, out);
452
453 drtn = DERParseSequenceContent(&subjectPublicKeyInfo.algId,
454 DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs,
455 &algorithmId, sizeof(algorithmId));
456 require_noerr_quiet(drtn, out);
457
458 DERByte unusedBits;
459 drtn = DERParseBitString(&subjectPublicKeyInfo.pubKey, &pubKeyBytes, &unusedBits);
460 require_noerr_quiet(drtn, out);
461
462 /* Convert DERItem to SecAsn1Item : */
463 const SecAsn1Oid oid = { .Data = algorithmId.oid.data, .Length = algorithmId.oid.length };
464 const SecAsn1Item params = { .Data = algorithmId.params.data, .Length = algorithmId.params.length };
465 const SecAsn1Item pubKey = { .Data = pubKeyBytes.data, .Length = pubKeyBytes.length };
466
467 return SecKeyCreatePublicFromDER(allocator, &oid, &params, &pubKey);
468
469 out:
470
471 return NULL;
472
473 }
474
475
476
477 SecKeyRef SecKeyCreate(CFAllocatorRef allocator,
478 const SecKeyDescriptor *key_class, const uint8_t *keyData,
479 CFIndex keyDataLength, SecKeyEncoding encoding) {
480 if (!key_class) return NULL;
481 size_t size = sizeof(struct __SecKey) + key_class->extraBytes;
482 SecKeyRef result = (SecKeyRef)_CFRuntimeCreateInstance(allocator,
483 SecKeyGetTypeID(), size - sizeof(CFRuntimeBase), NULL);
484 if (result) {
485 memset((char*)result + sizeof(result->_base), 0, size - sizeof(result->_base));
486 result->key_class = key_class;
487 if (key_class->extraBytes) {
488 /* Make result->key point to the extraBytes we allocated. */
489 result->key = ((char*)result) + sizeof(*result);
490 }
491 if (key_class->init) {
492 OSStatus status;
493 status = key_class->init(result, keyData, keyDataLength, encoding);
494 if (status) {
495 secwarning("init %s key: %" PRIdOSStatus, key_class->name, status);
496 CFRelease(result);
497 result = NULL;
498 }
499 }
500 }
501 return result;
502 }
503
504 static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key, SecPadding padding) {
505 switch (SecKeyGetAlgorithmIdentifier(key)) {
506 case kSecRSAAlgorithmID:
507 switch (padding) {
508 case kSecPaddingNone:
509 return kSecKeyAlgorithmRSASignatureRaw;
510 case kSecPaddingPKCS1:
511 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw;
512 #if TARGET_OS_IPHONE
513 case kSecPaddingPKCS1SHA1:
514 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1;
515 case kSecPaddingPKCS1SHA224:
516 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224;
517 case kSecPaddingPKCS1SHA256:
518 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256;
519 case kSecPaddingPKCS1SHA384:
520 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384;
521 case kSecPaddingPKCS1SHA512:
522 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512;
523 #else
524 // On CSSM-based implementation, these functions actually did hash its input,
525 // so keep doing that for backward compatibility.
526 case kSecPaddingPKCS1SHA1:
527 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;
528 case kSecPaddingPKCS1SHA224:
529 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224;
530 case kSecPaddingPKCS1SHA256:
531 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256;
532 case kSecPaddingPKCS1SHA384:
533 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384;
534 case kSecPaddingPKCS1SHA512:
535 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512;
536 #endif
537 default:
538 return NULL;
539 }
540 case kSecECDSAAlgorithmID:
541 switch (padding) {
542 case kSecPaddingSigRaw:
543 return kSecKeyAlgorithmECDSASignatureRFC4754;
544 default:
545 // Although it is not very logical, previous SecECKey implementation really considered
546 // anything else than SigRaw (incl. None!) as PKCS1 (i.e. x962), so we keep the behaviour
547 // for backward compatibility.
548 return kSecKeyAlgorithmECDSASignatureDigestX962;
549 }
550 default:
551 return NULL;
552 }
553 }
554
555 // Generic wrapper helper for invoking new-style CFDataRef-based operations with ptr/length arguments
556 // used by legacy RawSign-style functions.
557 static OSStatus SecKeyPerformLegacyOperation(SecKeyRef key,
558 const uint8_t *in1Ptr, size_t in1Len,
559 const uint8_t *in2Ptr, size_t in2Len,
560 uint8_t *outPtr, size_t *outLen,
561 CFTypeRef (^operation)(CFDataRef in1, CFDataRef in2, CFRange *resultRange, CFErrorRef *error)) {
562 CFErrorRef error = NULL;
563 OSStatus status = errSecSuccess;
564 CFDataRef in1 = CFDataCreateWithBytesNoCopy(NULL, in1Ptr, in1Len, kCFAllocatorNull);
565 CFDataRef in2 = CFDataCreateWithBytesNoCopy(NULL, in2Ptr, in2Len, kCFAllocatorNull);
566 CFRange range = { 0, -1 };
567 CFTypeRef output = operation(in1, in2, &range, &error);
568 require_quiet(output, out);
569 if (CFGetTypeID(output) == CFDataGetTypeID() && outLen != NULL) {
570 if (range.length == -1) {
571 range.length = CFDataGetLength(output);
572 }
573 require_action_quiet((size_t)range.length <= *outLen, out,
574 SecError(errSecParam, &error, CFSTR("buffer too small")));
575 *outLen = range.length;
576 CFDataGetBytes(output, range, outPtr);
577 }
578
579 out:
580 CFReleaseSafe(in1);
581 CFReleaseSafe(in2);
582 CFReleaseSafe(output);
583 if (error != NULL) {
584 status = SecErrorGetOSStatus(error);
585 if (status == errSecVerifyFailed) {
586 // Legacy functions used errSSLCrypto, while new implementation uses errSecVerifyFailed.
587 status = errSSLCrypto;
588 }
589 CFRelease(error);
590 }
591 return status;
592 }
593
594 OSStatus SecKeyRawSign(
595 SecKeyRef key, /* Private key */
596 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */
597 const uint8_t *dataToSign, /* signature over this data */
598 size_t dataToSignLen, /* length of dataToSign */
599 uint8_t *sig, /* signature, RETURNED */
600 size_t *sigLen) { /* IN/OUT */
601 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding);
602 if (algorithm == NULL) {
603 return errSecParam;
604 }
605 return SecKeyPerformLegacyOperation(key, dataToSign, dataToSignLen, NULL, 0, sig, sigLen,
606 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
607 return SecKeyCreateSignature(key, algorithm, in1, error);
608 });
609 }
610
611 OSStatus SecKeyRawVerify(
612 SecKeyRef key, /* Public key */
613 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */
614 const uint8_t *signedData, /* signature over this data */
615 size_t signedDataLen, /* length of dataToSign */
616 const uint8_t *sig, /* signature */
617 size_t sigLen) { /* length of signature */
618 SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding);
619 if (algorithm == NULL) {
620 return errSecParam;
621 }
622 OSStatus status = SecKeyPerformLegacyOperation(key, signedData, signedDataLen, sig, sigLen, NULL, NULL,
623 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
624 return SecKeyVerifySignature(key, algorithm, in1, in2, error)
625 ? kCFBooleanTrue : NULL;
626 });
627 return status;
628 }
629
630 static SecKeyAlgorithm SecKeyGetEncryptionAlgorithmForPadding(SecKeyRef key, SecPadding padding) {
631 switch (SecKeyGetAlgorithmIdentifier(key)) {
632 case kSecRSAAlgorithmID:
633 switch (padding) {
634 case kSecPaddingNone:
635 return kSecKeyAlgorithmRSAEncryptionRaw;
636 case kSecPaddingPKCS1:
637 return kSecKeyAlgorithmRSAEncryptionPKCS1;
638 case kSecPaddingOAEP:
639 return kSecKeyAlgorithmRSAEncryptionOAEPSHA1;
640 default:
641 return NULL;
642 }
643 default:
644 return NULL;
645 }
646 }
647
648 OSStatus SecKeyEncrypt(
649 SecKeyRef key, /* Public key */
650 SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */
651 const uint8_t *plainText,
652 size_t plainTextLen, /* length of plainText */
653 uint8_t *cipherText,
654 size_t *cipherTextLen) { /* IN/OUT */
655 SecKeyAlgorithm algorithm = SecKeyGetEncryptionAlgorithmForPadding(key, padding);
656 if (algorithm == NULL) {
657 return errSecParam;
658 }
659
660 return SecKeyPerformLegacyOperation(key, plainText, plainTextLen, NULL, 0, cipherText, cipherTextLen,
661 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
662 return SecKeyCreateEncryptedData(key, algorithm, in1, error);
663 });
664 }
665
666 OSStatus SecKeyDecrypt(
667 SecKeyRef key, /* Private key */
668 SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */
669 const uint8_t *cipherText,
670 size_t cipherTextLen, /* length of cipherText */
671 uint8_t *plainText,
672 size_t *plainTextLen) { /* IN/OUT */
673 SecKeyAlgorithm algorithm = SecKeyGetEncryptionAlgorithmForPadding(key, padding);
674 if (algorithm == NULL) {
675 return errSecParam;
676 }
677 return SecKeyPerformLegacyOperation(key, cipherText, cipherTextLen, NULL, 0, plainText, plainTextLen,
678 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
679 CFDataRef decrypted = SecKeyCreateDecryptedData(key, algorithm, in1, error);
680 const UInt8 *data;
681 if (decrypted != NULL && algorithm == kSecKeyAlgorithmRSAEncryptionRaw &&
682 *(data = CFDataGetBytePtr(decrypted)) == 0x00) {
683 // Strip zero-padding from the beginning of the block, as the contract of this
684 // function says.
685 range->length = CFDataGetLength(decrypted);
686 while (*data == 0x00 && range->length > 0) {
687 range->location++;
688 range->length--;
689 data++;
690 }
691 }
692 return decrypted;
693 });
694 }
695
696 size_t SecKeyGetBlockSize(SecKeyRef key) {
697 if (key->key_class->blockSize)
698 return key->key_class->blockSize(key);
699 return 0;
700 }
701
702 /* Private API functions. */
703
704 CFDictionaryRef SecKeyCopyAttributeDictionary(SecKeyRef key) {
705 if (key->key_class->copyDictionary)
706 return key->key_class->copyDictionary(key);
707 return NULL;
708 }
709
710 SecKeyRef SecKeyCreateFromAttributeDictionary(CFDictionaryRef refAttributes) {
711 CFErrorRef error = NULL;
712 SecKeyRef key = SecKeyCreateWithData(CFDictionaryGetValue(refAttributes, kSecValueData), refAttributes, &error);
713 if (key == NULL) {
714 CFStringRef description = CFErrorCopyDescription(error);
715 secwarning("%@", description);
716 CFRelease(description);
717 CFRelease(error);
718 }
719 return key;
720 }
721
722 static SecKeyAlgorithm SecKeyGetAlgorithmForSecAsn1AlgId(SecKeyRef key, const SecAsn1AlgId *algId, bool digestData) {
723 static const struct TableItem {
724 const SecAsn1Oid *oid1, *oid2;
725 const SecKeyAlgorithm *algorithms[2];
726 } translationTableRSA[] = {
727 { &CSSMOID_SHA1WithRSA, &CSSMOID_SHA1, {
728 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1,
729 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1,
730 } },
731 { &CSSMOID_SHA224WithRSA, &CSSMOID_SHA224, {
732 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224,
733 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224,
734 } },
735 { &CSSMOID_SHA256WithRSA, &CSSMOID_SHA256, {
736 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
737 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256,
738 } },
739 { &CSSMOID_SHA384WithRSA, &CSSMOID_SHA384, {
740 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384,
741 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384,
742 } },
743 { &CSSMOID_SHA512WithRSA, &CSSMOID_SHA512, {
744 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512,
745 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512,
746 } },
747 { &CSSMOID_MD5, NULL, {
748 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5,
749 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5,
750 } },
751 { NULL },
752 }, translationTableECDSA[] = {
753 { &CSSMOID_ECDSA_WithSHA1, &CSSMOID_SHA1, {
754 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962,
755 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA1,
756 } },
757 { &CSSMOID_ECDSA_WithSHA224, &CSSMOID_SHA224, {
758 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962,
759 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA224,
760 } },
761 { &CSSMOID_ECDSA_WithSHA256, &CSSMOID_SHA256, {
762 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962,
763 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA256,
764 } },
765 { &CSSMOID_ECDSA_WithSHA384, &CSSMOID_SHA384, {
766 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962,
767 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA384,
768 } },
769 { &CSSMOID_ECDSA_WithSHA512, &CSSMOID_SHA512, {
770 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962,
771 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA512,
772 } },
773 { NULL },
774 };
775
776 const struct TableItem *table;
777 switch (SecKeyGetAlgorithmIdentifier(key)) {
778 case kSecRSAAlgorithmID:
779 table = translationTableRSA;
780 break;
781 case kSecECDSAAlgorithmID:
782 table = translationTableECDSA;
783 break;
784 default:
785 return NULL;
786 }
787
788 for (; table->oid1 != NULL; table++) {
789 if (SecAsn1OidCompare(table->oid1, &algId->algorithm) ||
790 (table->oid2 != NULL && SecAsn1OidCompare(table->oid2, &algId->algorithm))) {
791 return *table->algorithms[digestData];
792 }
793 }
794 return NULL;
795 }
796
797 OSStatus SecKeyDigestAndVerify(
798 SecKeyRef key, /* Private key */
799 const SecAsn1AlgId *algId, /* algorithm oid/params */
800 const uint8_t *dataToDigest, /* signature over this data */
801 size_t dataToDigestLen,/* length of dataToDigest */
802 const uint8_t *sig, /* signature to verify */
803 size_t sigLen) { /* length of sig */
804
805 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, true);
806 if (algorithm == NULL) {
807 return errSecUnimplemented;
808 }
809
810 return SecKeyPerformLegacyOperation(key, dataToDigest, dataToDigestLen, sig, sigLen, NULL, NULL,
811 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
812 return SecKeyVerifySignature(key, algorithm, in1, in2, error) ?
813 kCFBooleanTrue : NULL;
814 });
815 }
816
817 OSStatus SecKeyDigestAndSign(
818 SecKeyRef key, /* Private key */
819 const SecAsn1AlgId *algId, /* algorithm oid/params */
820 const uint8_t *dataToDigest, /* signature over this data */
821 size_t dataToDigestLen,/* length of dataToDigest */
822 uint8_t *sig, /* signature, RETURNED */
823 size_t *sigLen) { /* IN/OUT */
824 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, true);
825 if (algorithm == NULL) {
826 return errSecUnimplemented;
827 }
828
829 return SecKeyPerformLegacyOperation(key, dataToDigest, dataToDigestLen, NULL, 0, sig, sigLen,
830 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
831 return SecKeyCreateSignature(key, algorithm, in1, error);
832 });
833 }
834
835 OSStatus SecKeyVerifyDigest(
836 SecKeyRef key, /* Private key */
837 const SecAsn1AlgId *algId, /* algorithm oid/params */
838 const uint8_t *digestData, /* signature over this digest */
839 size_t digestDataLen,/* length of dataToDigest */
840 const uint8_t *sig, /* signature to verify */
841 size_t sigLen) { /* length of sig */
842 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, false);
843 if (algorithm == NULL) {
844 return errSecUnimplemented;
845 }
846
847 return SecKeyPerformLegacyOperation(key, digestData, digestDataLen, sig, sigLen, NULL, NULL,
848 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
849 return SecKeyVerifySignature(key, algorithm, in1, in2, error) ?
850 kCFBooleanTrue : NULL;
851 });
852 }
853
854 OSStatus SecKeySignDigest(
855 SecKeyRef key, /* Private key */
856 const SecAsn1AlgId *algId, /* algorithm oid/params */
857 const uint8_t *digestData, /* signature over this digest */
858 size_t digestDataLen,/* length of digestData */
859 uint8_t *sig, /* signature, RETURNED */
860 size_t *sigLen) { /* IN/OUT */
861 SecKeyAlgorithm algorithm = SecKeyGetAlgorithmForSecAsn1AlgId(key, algId, false);
862 if (algorithm == NULL) {
863 return errSecUnimplemented;
864 }
865
866 return SecKeyPerformLegacyOperation(key, digestData, digestDataLen, NULL, 0, sig, sigLen,
867 ^CFTypeRef(CFDataRef in1, CFDataRef in2, CFRange *range, CFErrorRef *error) {
868 return SecKeyCreateSignature(key, algorithm, in1, error);
869 });
870 }
871
872 CFIndex SecKeyGetAlgorithmId(SecKeyRef key) {
873 return SecKeyGetAlgorithmIdentifier(key);
874 }
875
876 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR))
877 /* On OS X, SecKeyGetAlgorithmID has a different function signature (two arguments,
878 with output in the second argument). Therefore, avoid implementing this function here
879 if compiling for OS X.
880 */
881 #else
882 CFIndex SecKeyGetAlgorithmID(SecKeyRef key) {
883 return SecKeyGetAlgorithmIdentifier(key);
884 }
885 #endif
886
887 OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* serializedPublic) {
888 if (key->key_class->version > 1 && key->key_class->copyPublic)
889 return key->key_class->copyPublic(key, serializedPublic);
890 return errSecUnimplemented;
891 }
892
893 SecKeyRef SecKeyCreateFromPublicBytes(CFAllocatorRef allocator, CFIndex algorithmID, const uint8_t *keyData, CFIndex keyDataLength)
894 {
895 switch (algorithmID)
896 {
897 case kSecRSAAlgorithmID:
898 return SecKeyCreateRSAPublicKey(allocator,
899 keyData, keyDataLength,
900 kSecKeyEncodingBytes);
901 case kSecECDSAAlgorithmID:
902 return SecKeyCreateECPublicKey(allocator,
903 keyData, keyDataLength,
904 kSecKeyEncodingBytes);
905 default:
906 return NULL;
907 }
908 }
909
910 SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef serialized)
911 {
912 return SecKeyCreateFromPublicBytes(allocator, algorithmID, CFDataGetBytePtr(serialized), CFDataGetLength(serialized));
913 }
914
915 // This is a bit icky hack to avoid changing the vtable for
916 // SecKey.
917 size_t SecKeyGetSize(SecKeyRef key, SecKeySize whichSize)
918 {
919 size_t result = SecKeyGetBlockSize(key);
920
921 if (kSecECDSAAlgorithmID == SecKeyGetAlgorithmIdentifier(key)) {
922 switch (whichSize) {
923 case kSecKeyEncryptedDataSize:
924 result = 0;
925 break;
926 case kSecKeySignatureSize:
927 result = (result >= 66 ? 9 : 8) + 2 * result;
928 break;
929 case kSecKeyKeySizeInBits:
930 if (result >= 66)
931 return 521;
932 }
933 }
934
935 if (whichSize == kSecKeyKeySizeInBits)
936 result *= 8;
937
938 return result;
939
940 }
941
942 OSStatus SecKeyFindWithPersistentRef(CFDataRef persistentRef, SecKeyRef* lookedUpData)
943 {
944 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
945 kSecReturnRef, kCFBooleanTrue,
946 kSecClass, kSecClassKey,
947 kSecValuePersistentRef, persistentRef,
948 NULL);
949 CFTypeRef foundRef = NULL;
950 OSStatus status = SecItemCopyMatching(query, &foundRef);
951
952 if (status == errSecSuccess) {
953 if (CFGetTypeID(foundRef) == SecKeyGetTypeID()) {
954 *lookedUpData = (SecKeyRef) foundRef;
955 foundRef = NULL;
956 status = errSecSuccess;
957 } else {
958 status = errSecItemNotFound;
959 }
960 }
961
962 CFReleaseSafe(foundRef);
963 CFReleaseSafe(query);
964
965 return status;
966 }
967
968 OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef)
969 {
970 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
971 kSecReturnPersistentRef, kCFBooleanTrue,
972 kSecValueRef, key,
973 kSecAttrSynchronizable, kSecAttrSynchronizableAny,
974 NULL);
975 CFTypeRef foundRef = NULL;
976 OSStatus status = SecItemCopyMatching(query, &foundRef);
977
978 if (status == errSecSuccess) {
979 if (CFGetTypeID(foundRef) == CFDataGetTypeID()) {
980 *persistentRef = foundRef;
981 foundRef = NULL;
982 } else {
983 status = errSecItemNotFound;
984 }
985 }
986
987 CFReleaseSafe(foundRef);
988 CFReleaseSafe(query);
989
990 return status;
991 }
992
993 /*
994 *
995 */
996
997 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
998
999 SEC_CONST_DECL(_kSecKeyWrapPGPSymAlg, "kSecKeyWrapPGPSymAlg");
1000 SEC_CONST_DECL(_kSecKeyWrapPGPFingerprint, "kSecKeyWrapPGPFingerprint");
1001 SEC_CONST_DECL(_kSecKeyWrapPGPWrapAlg, "kSecKeyWrapPGPWrapAlg");
1002 SEC_CONST_DECL(_kSecKeyWrapRFC6637Flags, "kSecKeyWrapPGPECFlags");
1003 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA256KekAES128, "kSecKeyWrapPGPECWrapDigestSHA256KekAES128");
1004 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA512KekAES256, "kSecKeyWrapPGPECWrapDigestSHA512KekAES256");
1005
1006 #undef SEC_CONST_DECL
1007
1008 CFDataRef
1009 _SecKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
1010 {
1011 if (error)
1012 *error = NULL;
1013 if (outParam)
1014 *outParam = NULL;
1015 if (key->key_class->version > 2 && key->key_class->copyWrapKey)
1016 return key->key_class->copyWrapKey(key, type, unwrappedKey, parameters, outParam, error);
1017 SecError(errSecUnsupportedOperation, error, CFSTR("No key wrap supported for key %@"), key);
1018 return NULL;
1019 }
1020
1021 CFDataRef
1022 _SecKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
1023 {
1024 if (error)
1025 *error = NULL;
1026 if (outParam)
1027 *outParam = NULL;
1028 if (key->key_class->version > 2 && key->key_class->copyUnwrapKey)
1029 return key->key_class->copyUnwrapKey(key, type, wrappedKey, parameters, outParam, error);
1030
1031 SecError(errSecUnsupportedOperation, error, CFSTR("No key unwrap for key %@"), key);
1032 return NULL;
1033 }
1034
1035 static SInt32 SecKeyParamsGetSInt32(CFTypeRef value, CFStringRef errName, CFErrorRef *error) {
1036 SInt32 result = -1;
1037 if (CFGetTypeID(value) == CFNumberGetTypeID()) {
1038 if (!CFNumberGetValue(value, kCFNumberSInt32Type, &result) || result < 0) {
1039 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value);
1040 }
1041 } else if (isString(value)) {
1042 result = CFStringGetIntValue(value);
1043 CFStringRef t = CFStringCreateWithFormat(0, 0, CFSTR("%ld"), (long) result);
1044 if (!CFEqual(t, value) || result < 0) {
1045 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value);
1046 result = -1;
1047 }
1048 CFReleaseSafe(t);
1049 } else {
1050 SecError(errSecParam, error, CFSTR("Unsupported %@: %@"), errName, value);
1051 }
1052 return result;
1053 }
1054
1055 SecKeyRef SecKeyCreateWithData(CFDataRef keyData, CFDictionaryRef parameters, CFErrorRef *error) {
1056
1057 SecKeyRef key = NULL;
1058 CFAllocatorRef allocator = NULL;
1059
1060 /* First figure out the key type (algorithm). */
1061 SInt32 algorithm;
1062 CFTypeRef ktype = CFDictionaryGetValue(parameters, kSecAttrKeyType);
1063 require_quiet((algorithm = SecKeyParamsGetSInt32(ktype, CFSTR("key type"), error)) >= 0, out);
1064 SInt32 class;
1065 CFTypeRef kclass = CFDictionaryGetValue(parameters, kSecAttrKeyClass);
1066 require_quiet((class = SecKeyParamsGetSInt32(kclass, CFSTR("key class"), error)) >= 0, out);
1067
1068 switch (class) {
1069 case 0: // kSecAttrKeyClassPublic
1070 switch (algorithm) {
1071 case 42: // kSecAlgorithmRSA
1072 key = SecKeyCreateRSAPublicKey(allocator,
1073 CFDataGetBytePtr(keyData), CFDataGetLength(keyData),
1074 kSecKeyEncodingBytes);
1075 if (key == NULL) {
1076 SecError(errSecParam, error, CFSTR("RSA public key creation from data failed"));
1077 }
1078 break;
1079 case 43: // kSecAlgorithmECDSA
1080 case 73: // kSecAlgorithmEC
1081 key = SecKeyCreateECPublicKey(allocator,
1082 CFDataGetBytePtr(keyData), CFDataGetLength(keyData),
1083 kSecKeyEncodingBytes);
1084 if (key == NULL) {
1085 SecError(errSecParam, error, CFSTR("EC public key creation from data failed"));
1086 }
1087 break;
1088 default:
1089 SecError(errSecParam, error, CFSTR("Unsupported public key type: %@"), ktype);
1090 break;
1091 };
1092 break;
1093 case 1: // kSecAttrKeyClassPrivate
1094 if (CFDictionaryGetValue(parameters, kSecAttrTokenID) != NULL) {
1095 key = SecKeyCreateCTKKey(allocator, parameters, error);
1096 break;
1097 }
1098 switch (algorithm) {
1099 case 42: // kSecAlgorithmRSA
1100 key = SecKeyCreateRSAPrivateKey(allocator,
1101 CFDataGetBytePtr(keyData), CFDataGetLength(keyData),
1102 kSecKeyEncodingBytes);
1103 if (key == NULL) {
1104 SecError(errSecParam, error, CFSTR("RSA private key creation from data failed"));
1105 }
1106 break;
1107 case 43: // kSecAlgorithmECDSA
1108 case 73: // kSecAlgorithmEC
1109 key = SecKeyCreateECPrivateKey(allocator,
1110 CFDataGetBytePtr(keyData), CFDataGetLength(keyData),
1111 kSecKeyEncodingBytes);
1112 if (key == NULL) {
1113 SecError(errSecParam, error, CFSTR("EC public key creation from data failed"));
1114 }
1115 break;
1116 default:
1117 SecError(errSecParam, error, CFSTR("Unsupported private key type: %@"), ktype);
1118 break;
1119 };
1120 break;
1121 case 2: // kSecAttrKeyClassSymmetric
1122 SecError(errSecUnimplemented, error, CFSTR("Unsupported symmetric key type: %@"), ktype);
1123 break;
1124 default:
1125 SecError(errSecParam, error, CFSTR("Unsupported key class: %@"), kclass);
1126 break;
1127 }
1128
1129 out:
1130 return key;
1131 }
1132
1133 CFDataRef SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
1134 if (!key->key_class->copyExternalRepresentation) {
1135 SecError(errSecUnimplemented, error, CFSTR("export not implemented for key %@"), key);
1136 return NULL;
1137 }
1138
1139 return key->key_class->copyExternalRepresentation(key, error);
1140 }
1141
1142 CFDictionaryRef SecKeyCopyAttributes(SecKeyRef key) {
1143 if (key->key_class->copyDictionary)
1144 return key->key_class->copyDictionary(key);
1145 return NULL;
1146 }
1147
1148 SecKeyRef SecKeyCopyPublicKey(SecKeyRef key) {
1149 SecKeyRef result = NULL;
1150 if (key->key_class->version >= 4 && key->key_class->copyPublicKey) {
1151 result = key->key_class->copyPublicKey(key);
1152 if (result != NULL) {
1153 return result;
1154 }
1155 }
1156
1157 CFDataRef serializedPublic = NULL;
1158
1159 require_noerr_quiet(SecKeyCopyPublicBytes(key, &serializedPublic), fail);
1160 require_quiet(serializedPublic, fail);
1161
1162 result = SecKeyCreateFromPublicData(kCFAllocatorDefault, SecKeyGetAlgorithmIdentifier(key), serializedPublic);
1163
1164 fail:
1165 CFReleaseSafe(serializedPublic);
1166 return result;
1167 }
1168
1169 SecKeyRef SecKeyCreateRandomKey(CFDictionaryRef parameters, CFErrorRef *error) {
1170 SecKeyRef privKey = NULL, pubKey = NULL;
1171 OSStatus status = SecKeyGeneratePair(parameters, &pubKey, &privKey);
1172 SecError(status, error, CFSTR("Key generation failed, error %d"), (int)status);
1173 CFReleaseSafe(pubKey);
1174 return privKey;
1175 }
1176
1177 SecKeyRef SecKeyCreateDuplicate(SecKeyRef key) {
1178 if (key->key_class->version >= 4 && key->key_class->createDuplicate) {
1179 return key->key_class->createDuplicate(key);
1180 } else {
1181 return (SecKeyRef)CFRetain(key);
1182 }
1183 }
1184
1185 Boolean SecKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) {
1186 if (key->key_class->version >= 4 && key->key_class->setParameter) {
1187 return key->key_class->setParameter(key, name, value, error);
1188 } else {
1189 return SecError(errSecUnimplemented, error, CFSTR("setParameter not implemented for %@"), key);
1190 }
1191 }
1192
1193 #pragma mark Generic algorithm adaptor lookup and invocation
1194
1195 static CFTypeRef SecKeyCopyBackendOperationResult(SecKeyOperationContext *context, SecKeyAlgorithm algorithm,
1196 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
1197 CFTypeRef result = kCFNull;
1198 assert(CFArrayGetCount(context->algorithm) > 0);
1199 if (context->key->key_class->version >= 4 && context->key->key_class->copyOperationResult != NULL) {
1200 return context->key->key_class->copyOperationResult(context->key, context->operation, algorithm,
1201 context->algorithm, context->mode, in1, in2, error);
1202 }
1203
1204 // Mapping from algorithms to legacy SecPadding values.
1205 static const struct {
1206 const SecKeyAlgorithm *algorithm;
1207 CFIndex keyAlg;
1208 SecPadding padding;
1209 } paddingMap[] = {
1210 { &kSecKeyAlgorithmRSASignatureRaw, kSecRSAAlgorithmID, kSecPaddingNone },
1211 { &kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw, kSecRSAAlgorithmID, kSecPaddingPKCS1 },
1212 { &kSecKeyAlgorithmECDSASignatureRFC4754, kSecECDSAAlgorithmID, kSecPaddingSigRaw },
1213 { &kSecKeyAlgorithmECDSASignatureDigestX962, kSecECDSAAlgorithmID, kSecPaddingPKCS1 },
1214 { &kSecKeyAlgorithmRSAEncryptionRaw, kSecRSAAlgorithmID, kSecPaddingNone },
1215 { &kSecKeyAlgorithmRSAEncryptionPKCS1, kSecRSAAlgorithmID, kSecPaddingPKCS1 },
1216 { &kSecKeyAlgorithmRSAEncryptionOAEPSHA1, kSecRSAAlgorithmID, kSecPaddingOAEP },
1217 };
1218 SecPadding padding = (SecPadding)-1;
1219 CFIndex keyAlg = SecKeyGetAlgorithmIdentifier(context->key);
1220 for (size_t i = 0; i < array_size(paddingMap); ++i) {
1221 if (keyAlg == paddingMap[i].keyAlg && CFEqual(algorithm, *paddingMap[i].algorithm)) {
1222 padding = paddingMap[i].padding;
1223 break;
1224 }
1225 }
1226 require_quiet(padding != (SecPadding)-1, out);
1227
1228 // Check legacy virtual table entries.
1229 size_t size = 0;
1230 OSStatus status = errSecSuccess;
1231 switch (context->operation) {
1232 case kSecKeyOperationTypeSign:
1233 if (context->key->key_class->rawSign != NULL) {
1234 result = kCFBooleanTrue;
1235 if (context->mode == kSecKeyOperationModePerform) {
1236 size = SecKeyGetSize(context->key, kSecKeySignatureSize);
1237 result = CFDataCreateMutableWithScratch(NULL, size);
1238 status = context->key->key_class->rawSign(context->key, padding,
1239 CFDataGetBytePtr(in1), CFDataGetLength(in1),
1240 CFDataGetMutableBytePtr((CFMutableDataRef)result), &size);
1241 }
1242 }
1243 break;
1244 case kSecKeyOperationTypeVerify:
1245 if (context->key->key_class->rawVerify != NULL) {
1246 result = kCFBooleanTrue;
1247 if (context->mode == kSecKeyOperationModePerform) {
1248 status = context->key->key_class->rawVerify(context->key, padding,
1249 CFDataGetBytePtr(in1), CFDataGetLength(in1),
1250 CFDataGetBytePtr(in2), CFDataGetLength(in2));
1251 }
1252 }
1253 break;
1254 case kSecKeyOperationTypeEncrypt:
1255 if (context->key->key_class->encrypt != NULL) {
1256 result = kCFBooleanTrue;
1257 if (context->mode == kSecKeyOperationModePerform) {
1258 size = SecKeyGetSize(context->key, kSecKeyEncryptedDataSize);
1259 result = CFDataCreateMutableWithScratch(NULL, size);
1260 status = context->key->key_class->encrypt(context->key, padding,
1261 CFDataGetBytePtr(in1), CFDataGetLength(in1),
1262 CFDataGetMutableBytePtr((CFMutableDataRef)result), &size);
1263 }
1264 }
1265 break;
1266 case kSecKeyOperationTypeDecrypt:
1267 if (context->key->key_class->decrypt != NULL) {
1268 result = kCFBooleanTrue;
1269 if (context->mode == kSecKeyOperationModePerform) {
1270 size = SecKeyGetSize(context->key, kSecKeyEncryptedDataSize);
1271 result = CFDataCreateMutableWithScratch(NULL, size);
1272 status = context->key->key_class->decrypt(context->key, padding,
1273 CFDataGetBytePtr(in1), CFDataGetLength(in1),
1274 CFDataGetMutableBytePtr((CFMutableDataRef)result), &size);
1275 }
1276 }
1277 break;
1278 default:
1279 goto out;
1280 }
1281
1282 if (status == errSecSuccess) {
1283 if (CFGetTypeID(result) == CFDataGetTypeID()) {
1284 CFDataSetLength((CFMutableDataRef)result, size);
1285 }
1286 } else {
1287 SecError(status, error, CFSTR("legacy SecKey backend operation:%d(%d) failed"), (int)context->operation, (int)padding);
1288 CFReleaseNull(result);
1289 }
1290
1291 out:
1292 return result;
1293 }
1294
1295 CFTypeRef SecKeyRunAlgorithmAndCopyResult(SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
1296
1297 // Check algorithm array for cycles; if any value of it is duplicated inside, report 'algorithm not found' error.
1298 CFIndex algorithmCount = CFArrayGetCount(context->algorithm);
1299 for (CFIndex index = 0; index < algorithmCount - 1; index++) {
1300 SecKeyAlgorithm indexAlgorithm = CFArrayGetValueAtIndex(context->algorithm, index);
1301 for (CFIndex tested = index + 1; tested < algorithmCount; tested++) {
1302 require_quiet(!CFEqual(indexAlgorithm, CFArrayGetValueAtIndex(context->algorithm, tested)), fail);
1303 }
1304 }
1305
1306 SecKeyAlgorithm algorithm = CFArrayGetValueAtIndex(context->algorithm, algorithmCount - 1);
1307 CFTypeRef output = SecKeyCopyBackendOperationResult(context, algorithm, in1, in2, error);
1308 if (output != kCFNull) {
1309 // Backend handled the operation, return result.
1310 return output;
1311 }
1312
1313 // To silence static analyzer.
1314 CFReleaseSafe(output);
1315
1316 // Get adaptor which is able to handle requested algorithm.
1317 SecKeyAlgorithmAdaptor adaptor = SecKeyGetAlgorithmAdaptor(context->operation, algorithm);
1318 require_quiet(adaptor != NULL, fail);
1319
1320 // Invoke the adaptor and return result.
1321 CFTypeRef result = adaptor(context, in1, in2, error);
1322 require_quiet(result != kCFNull, fail);
1323 return result;
1324
1325 fail:
1326 if (context->mode == kSecKeyOperationModePerform) {
1327 SecError(errSecParam, error, CFSTR("%@: algorithm not supported by the key %@"),
1328 CFArrayGetValueAtIndex(context->algorithm, 0), context->key);
1329 return NULL;
1330 } else {
1331 return kCFNull;
1332 }
1333 }
1334
1335 #pragma mark Algorithm-related SecKey API entry points
1336
1337 static CFMutableArrayRef SecKeyCreateAlgorithmArray(SecKeyAlgorithm algorithm) {
1338 CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
1339 CFArrayAppendValue(result, algorithm);
1340 return result;
1341 }
1342
1343 CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error) {
1344 SecKeyOperationContext context = { key, kSecKeyOperationTypeSign, SecKeyCreateAlgorithmArray(algorithm) };
1345 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, dataToSign, NULL, error);
1346 SecKeyOperationContextDestroy(&context);
1347 return result;
1348 }
1349
1350 Boolean SecKeyVerifySignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef signedData, CFDataRef signature,
1351 CFErrorRef *error) {
1352 SecKeyOperationContext context = { key, kSecKeyOperationTypeVerify, SecKeyCreateAlgorithmArray(algorithm) };
1353 CFTypeRef res = SecKeyRunAlgorithmAndCopyResult(&context, signedData, signature, error);
1354 Boolean result = CFEqualSafe(res, kCFBooleanTrue);
1355 CFReleaseSafe(res);
1356 SecKeyOperationContextDestroy(&context);
1357 return result;
1358 }
1359
1360 CFDataRef SecKeyCreateEncryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plainText, CFErrorRef *error) {
1361 SecKeyOperationContext context = { key, kSecKeyOperationTypeEncrypt, SecKeyCreateAlgorithmArray(algorithm) };
1362 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, plainText, NULL, error);
1363 SecKeyOperationContextDestroy(&context);
1364 return result;
1365 }
1366
1367 CFDataRef SecKeyCreateDecryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef cipherText, CFErrorRef *error) {
1368 SecKeyOperationContext context = { key, kSecKeyOperationTypeDecrypt, SecKeyCreateAlgorithmArray(algorithm) };
1369 CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, cipherText, NULL, error);
1370 SecKeyOperationContextDestroy(&context);
1371 return result;
1372 }
1373
1374 CFDataRef SecKeyCopyKeyExchangeResult(SecKeyRef key, SecKeyAlgorithm algorithm, SecKeyRef publicKey,
1375 CFDictionaryRef parameters, CFErrorRef *error) {
1376 CFDataRef publicKeyData = NULL, result = NULL;
1377 SecKeyOperationContext context = { key, kSecKeyOperationTypeKeyExchange, SecKeyCreateAlgorithmArray(algorithm) };
1378 require_quiet(publicKeyData = SecKeyCopyExternalRepresentation(publicKey, error), out);
1379 result = SecKeyRunAlgorithmAndCopyResult(&context, publicKeyData, parameters, error);
1380
1381 out:
1382 CFReleaseSafe(publicKeyData);
1383 SecKeyOperationContextDestroy(&context);
1384 return result;
1385 }
1386
1387 Boolean SecKeyIsAlgorithmSupported(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm) {
1388 SecKeyOperationContext context = { key, operation, SecKeyCreateAlgorithmArray(algorithm), kSecKeyOperationModeCheckIfSupported };
1389 CFErrorRef error = NULL;
1390 CFTypeRef res = SecKeyRunAlgorithmAndCopyResult(&context, NULL, NULL, &error);
1391 Boolean result = CFEqualSafe(res, kCFBooleanTrue);
1392 CFReleaseSafe(res);
1393 CFReleaseSafe(error);
1394 SecKeyOperationContextDestroy(&context);
1395 return result;
1396 }