2 * Copyright (c) 2006-2015 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * SecKey.c - CoreFoundation based key object
27 #include <Security/SecBase.h>
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>
35 #include <utilities/SecIOFormat.h>
37 #include <utilities/SecCFWrappers.h>
38 #include <utilities/array_size.h>
40 #include "SecRSAKeyPriv.h"
41 #include "SecECKeyPriv.h"
42 #include "SecCTKKeyPriv.h"
43 #include "SecBasePriv.h"
44 #include <Security/SecKeyPriv.h>
46 #include <CoreFoundation/CFNumber.h>
47 #include <CoreFoundation/CFString.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. */
60 #include <corecrypto/ccrng_system.h>
66 #include <libDER/asn1Types.h>
67 #include <libDER/DER_Keys.h>
68 #include <libDER/DER_Encode.h>
70 CFDataRef
SecKeyCopyPublicKeyHash(SecKeyRef key
)
72 CFDataRef pubKeyDigest
= NULL
, pubKeyBlob
= NULL
;
74 /* encode the public key. */
75 require_noerr_quiet(SecKeyCopyPublicBytes(key
, &pubKeyBlob
), errOut
);
76 require_quiet(pubKeyBlob
, errOut
);
78 /* Calculate the digest of the public key. */
79 require_quiet(pubKeyDigest
= SecSHA1DigestCreate(CFGetAllocator(key
),
80 CFDataGetBytePtr(pubKeyBlob
), CFDataGetLength(pubKeyBlob
)),
83 CFReleaseNull(pubKeyBlob
);
90 static CFDictionaryRef
SecKeyCopyAttributeDictionaryWithLocalKey(SecKeyRef key
,
92 CFDataRef privateBlob
)
94 CFAllocatorRef allocator
= CFGetAllocator(key
);
96 CFDataRef pubKeyDigest
= NULL
, pubKeyBlob
= NULL
;
97 CFDictionaryRef dict
= NULL
;
99 size_t sizeValue
= SecKeyGetSize(key
, kSecKeyKeySizeInBits
);
100 CFNumberRef sizeInBits
= CFNumberCreate(allocator
, kCFNumberLongType
, &sizeValue
);
102 /* encode the public key. */
103 require_noerr_quiet(SecKeyCopyPublicBytes(key
, &pubKeyBlob
), errOut
);
104 require_quiet(pubKeyBlob
, errOut
);
106 /* Calculate the digest of the public key. */
107 require_quiet(pubKeyDigest
= SecSHA1DigestCreate(allocator
,
108 CFDataGetBytePtr(pubKeyBlob
), CFDataGetLength(pubKeyBlob
)),
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
= CFDictionaryCreate(allocator
, keys
, values
, numValues
, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
137 // @@@ Zero out key material.
138 CFReleaseSafe(pubKeyDigest
);
139 CFReleaseSafe(pubKeyBlob
);
140 CFReleaseSafe(sizeInBits
);
145 CFDictionaryRef
SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key
,
147 CFDataRef privateBlob
)
149 return SecKeyCopyAttributeDictionaryWithLocalKey(key
, keyType
, privateBlob
);
152 CFDictionaryRef
SecKeyGeneratePublicAttributeDictionary(SecKeyRef key
, CFTypeRef keyType
)
154 return SecKeyCopyAttributeDictionaryWithLocalKey(key
, keyType
, NULL
);
157 static CFStringRef
SecKeyCopyDescription(CFTypeRef cf
) {
158 SecKeyRef key
= (SecKeyRef
)cf
;
160 if(key
->key_class
->describe
)
161 return key
->key_class
->describe(key
);
163 return CFStringCreateWithFormat(kCFAllocatorDefault
,NULL
,CFSTR("<SecKeyRef: %p>"), key
);
166 static void SecKeyDestroy(CFTypeRef cf
) {
167 SecKeyRef key
= (SecKeyRef
)cf
;
168 #if !TARGET_OS_IPHONE
169 CFReleaseNull(key
->cdsaKey
);
171 if (key
->key_class
->destroy
)
172 key
->key_class
->destroy(key
);
175 static Boolean
SecKeyEqual(CFTypeRef cf1
, CFTypeRef cf2
)
177 SecKeyRef key1
= (SecKeyRef
)cf1
;
178 SecKeyRef key2
= (SecKeyRef
)cf2
;
181 if (!key2
|| key1
->key_class
!= key2
->key_class
)
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
);
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
198 Boolean result
= CFEqual(d1
, d2
);
204 struct ccrng_state
*ccrng_seckey
;
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
);
212 static bool getBoolForKey(CFDictionaryRef dict
, CFStringRef key
, bool default_value
) {
213 CFTypeRef value
= CFDictionaryGetValue(dict
, key
);
215 if (CFGetTypeID(value
) == CFBooleanGetTypeID()) {
216 return CFBooleanGetValue(value
);
218 secwarning("Value %@ for key %@ is not bool", value
, key
);
222 return default_value
;
225 static OSStatus
add_ref(CFTypeRef item
, CFMutableDictionaryRef dict
) {
226 CFDictionarySetValue(dict
, kSecValueRef
, item
);
227 return SecItemAdd(dict
, NULL
);
230 static void merge_params_applier(const void *key
, const void *value
,
232 CFMutableDictionaryRef result
= (CFMutableDictionaryRef
)context
;
233 CFDictionaryAddValue(result
, key
, value
);
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
,
240 CFDictionaryRef subdict
= CFDictionaryGetValue(dict
, key
);
241 CFMutableDictionaryRef result
;
244 result
= CFDictionaryCreateMutableCopy(NULL
, 0, subdict
);
245 /* Add everything in dict not already in result to result. */
246 CFDictionaryApplyFunction(dict
, merge_params_applier
, result
);
248 result
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
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
);
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
;
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
);
270 /* All version 0 keys were RSA. */
271 return kSecRSAAlgorithmID
;
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
);
285 require_quiet(ktype
, errOut
);
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
);
295 require_noerr_quiet(result
, errOut
);
297 // Store the keys in the keychain if they are marked as permanent. Governed by kSecAttrIsPermanent attribute, with default
298 // to 'false' (ephemeral keys), except private token-based keys, in which case the default is 'true' (permanent keys).
299 if (getBoolForKey(pubParams
, kSecAttrIsPermanent
, false)) {
300 CFDictionaryRemoveValue(pubParams
, kSecAttrTokenID
);
301 require_noerr_quiet(result
= add_ref(pubKey
, pubParams
), errOut
);
303 if (getBoolForKey(privParams
, kSecAttrIsPermanent
, CFDictionaryContainsKey(privParams
, kSecAttrTokenID
))) {
304 require_noerr_quiet(result
= add_ref(privKey
, privParams
), errOut
);
312 *privateKey
= privKey
;
317 CFReleaseSafe(pubParams
);
318 CFReleaseSafe(privParams
);
319 CFReleaseSafe(pubKey
);
320 CFReleaseSafe(privKey
);
325 SecKeyRef
SecKeyCreatePublicFromPrivate(SecKeyRef privateKey
) {
326 return SecKeyCopyPublicKey(privateKey
);
329 CFDictionaryRef
CreatePrivateKeyMatchingQuery(SecKeyRef publicKey
, bool returnPersistentRef
)
331 const CFTypeRef refType
= (returnPersistentRef
) ? kSecReturnPersistentRef
: kSecReturnRef
;
333 CFDataRef public_key_hash
= SecKeyCopyPublicKeyHash(publicKey
);
335 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
336 kSecClass
, kSecClassKey
,
337 kSecAttrKeyClass
, kSecAttrKeyClassPrivate
,
338 kSecAttrSynchronizable
, kSecAttrSynchronizableAny
,
339 kSecAttrApplicationLabel
, public_key_hash
,
340 refType
, kCFBooleanTrue
,
342 CFReleaseNull(public_key_hash
);
347 CFDataRef
SecKeyCreatePersistentRefToMatchingPrivateKey(SecKeyRef publicKey
, CFErrorRef
*error
) {
348 CFTypeRef persistentRef
= NULL
;
349 CFDictionaryRef query
= CreatePrivateKeyMatchingQuery(publicKey
, true);
351 require_quiet(SecError(SecItemCopyMatching(query
, &persistentRef
),error
,
352 CFSTR("Error finding persistent ref to key from public: %@"), publicKey
), fail
);
354 CFReleaseNull(query
);
355 return (CFDataRef
)persistentRef
;
358 SecKeyRef
SecKeyCopyMatchingPrivateKey(SecKeyRef publicKey
, CFErrorRef
*error
) {
359 SecKeyRef privateKey
= NULL
;
360 CFTypeRef queryResult
= NULL
;
361 CFDictionaryRef query
= NULL
;
363 require_action_quiet(publicKey
!= NULL
, errOut
, SecError(errSecParam
, error
, CFSTR("Null Public Key")));
365 query
= CreatePrivateKeyMatchingQuery(publicKey
, false);
367 require_quiet(SecError(SecItemCopyMatching(query
, &queryResult
), error
,
368 CFSTR("Error finding private key from public: %@"), publicKey
), errOut
);
370 if (CFGetTypeID(queryResult
) == SecKeyGetTypeID()) {
371 privateKey
= (SecKeyRef
) queryResult
;
376 CFReleaseNull(query
);
377 CFReleaseNull(queryResult
);
381 OSStatus
SecKeyGetMatchingPrivateKeyStatus(SecKeyRef publicKey
, CFErrorRef
*error
) {
382 OSStatus retval
= errSecParam
;
383 CFTypeRef private_key
= NULL
;
384 CFDictionaryRef query
= NULL
;
386 require_action_quiet(publicKey
!= NULL
, errOut
, SecError(errSecParam
, error
, NULL
, CFSTR("Null Public Key")));
388 query
= CreatePrivateKeyMatchingQuery(publicKey
, false);
390 retval
= SecItemCopyMatching(query
, &private_key
);
392 if (!retval
&& CFGetTypeID(private_key
) != SecKeyGetTypeID()) {
393 retval
= errSecInternalComponent
;
397 CFReleaseNull(query
);
398 CFReleaseNull(private_key
);
403 SecKeyRef
SecKeyCreatePublicFromDER(CFAllocatorRef allocator
,
404 const SecAsn1Oid
*oid
, const SecAsn1Item
*params
,
405 const SecAsn1Item
*keyData
) {
406 SecKeyRef publicKey
= NULL
;
407 if (SecAsn1OidCompare(oid
, &CSSMOID_RSA
)) {
409 /* Note that we call SecKeyCreateRSAPublicKey_ios directly instead of
410 SecKeyCreateRSAPublicKey, since on OS X the latter function will return
411 a CSSM SecKeyRef, and we always want an iOS format SecKeyRef here.
413 publicKey
= SecKeyCreateRSAPublicKey_ios(allocator
,
414 keyData
->Data
, keyData
->Length
, kSecKeyEncodingPkcs1
);
415 } else if (SecAsn1OidCompare(oid
, &CSSMOID_ecPublicKey
)) {
418 .oidLength
= oid
->Length
,
419 .key
= keyData
->Data
,
420 .keyLength
= keyData
->Length
,
423 derKey
.parameters
= params
->Data
;
424 derKey
.parametersLength
= params
->Length
;
426 publicKey
= SecKeyCreateECPublicKey(allocator
,
427 (const uint8_t *)&derKey
, sizeof(derKey
), kSecDERKeyEncoding
);
429 secwarning("Unsupported algorithm oid");
436 SecKeyRef
SecKeyCreateFromSubjectPublicKeyInfoData(CFAllocatorRef allocator
, CFDataRef subjectPublicKeyInfoData
)
440 DERItem subjectPublicKeyInfoDER
= {
441 .data
= (uint8_t *)CFDataGetBytePtr(subjectPublicKeyInfoData
),
442 .length
= (DERSize
)CFDataGetLength(subjectPublicKeyInfoData
),
444 DERSubjPubKeyInfo subjectPublicKeyInfo
;
445 DERAlgorithmId algorithmId
;
448 drtn
= DERParseSequence(&subjectPublicKeyInfoDER
,
449 DERNumSubjPubKeyInfoItemSpecs
, DERSubjPubKeyInfoItemSpecs
,
450 &subjectPublicKeyInfo
, sizeof(subjectPublicKeyInfo
));
452 require_noerr_quiet(drtn
, out
);
454 drtn
= DERParseSequenceContent(&subjectPublicKeyInfo
.algId
,
455 DERNumAlgorithmIdItemSpecs
, DERAlgorithmIdItemSpecs
,
456 &algorithmId
, sizeof(algorithmId
));
457 require_noerr_quiet(drtn
, out
);
460 drtn
= DERParseBitString(&subjectPublicKeyInfo
.pubKey
, &pubKeyBytes
, &unusedBits
);
461 require_noerr_quiet(drtn
, out
);
463 /* Convert DERItem to SecAsn1Item : */
464 const SecAsn1Oid oid
= { .Data
= algorithmId
.oid
.data
, .Length
= algorithmId
.oid
.length
};
465 const SecAsn1Item params
= { .Data
= algorithmId
.params
.data
, .Length
= algorithmId
.params
.length
};
466 const SecAsn1Item pubKey
= { .Data
= pubKeyBytes
.data
, .Length
= pubKeyBytes
.length
};
468 return SecKeyCreatePublicFromDER(allocator
, &oid
, ¶ms
, &pubKey
);
475 static const DERByte oidRSA
[] = {
476 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
478 static const DERByte oidECsecp256
[] = {
479 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
481 static const DERByte oidECsecp384
[] = {
482 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
484 static const DERByte oidECsecp521
[] = {
485 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
489 CFDataRef
SecKeyCopySubjectPublicKeyInfo(SecKeyRef key
)
491 CFMutableDataRef data
= NULL
;
492 CFDataRef publicKey
= NULL
;
493 CFDataRef dataret
= NULL
;
494 DERSubjPubKeyInfo spki
;
498 memset(&spki
, 0, sizeof(spki
));
500 /* encode the public key. */
501 require_noerr(SecKeyCopyPublicBytes(key
, &publicKey
), errOut
);
502 require_quiet(publicKey
, errOut
);
504 require(CFDataGetLength(publicKey
) != 0, errOut
);
506 // Add prefix 00 is needed to avoid creating negative bit strings
507 if (((uint8_t *)CFDataGetBytePtr(publicKey
))[0] & 0x80)
511 CFMutableDataRef paddedKey
= CFDataCreateMutable(NULL
, 0);
512 /* the bit strings bits used field first */
513 CFDataAppendBytes(paddedKey
, (const UInt8
*)"\x00", 1);
515 CFDataAppendBytes(paddedKey
, (const UInt8
*)"\x00", 1);
517 CFDataAppendBytes(paddedKey
, CFDataGetBytePtr(publicKey
), CFDataGetLength(publicKey
));
518 CFTransferRetained(publicKey
, paddedKey
);
520 spki
.pubKey
.data
= (DERByte
*)CFDataGetBytePtr(publicKey
);
521 spki
.pubKey
.length
= CFDataGetLength(publicKey
);
523 // Encode algId according to algorithm used.
524 CFIndex algorithm
= SecKeyGetAlgorithmIdentifier(key
);
525 if (algorithm
== kSecRSAAlgorithmID
) {
526 spki
.algId
.data
= (DERByte
*)oidRSA
;
527 spki
.algId
.length
= sizeof(oidRSA
);
528 } else if (algorithm
== kSecECDSAAlgorithmID
) {
529 SecECNamedCurve curve
= SecECKeyGetNamedCurve(key
);
531 case kSecECCurveSecp256r1
:
532 spki
.algId
.data
= (DERByte
*)oidECsecp256
;
533 spki
.algId
.length
= sizeof(oidECsecp256
);
535 case kSecECCurveSecp384r1
:
536 spki
.algId
.data
= (DERByte
*)oidECsecp384
;
537 spki
.algId
.length
= sizeof(oidECsecp384
);
539 case kSecECCurveSecp521r1
:
540 spki
.algId
.data
= (DERByte
*)oidECsecp521
;
541 spki
.algId
.length
= sizeof(oidECsecp521
);
550 DERSize size
= DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE
, &spki
,
551 DERNumSubjPubKeyInfoItemSpecs
, DERSubjPubKeyInfoItemSpecs
);
552 data
= CFDataCreateMutable(kCFAllocatorDefault
, size
);
553 CFDataSetLength(data
, size
);
555 drtn
= DEREncodeSequence(ASN1_CONSTR_SEQUENCE
, &spki
,
556 DERNumSubjPubKeyInfoItemSpecs
,
557 DERSubjPubKeyInfoItemSpecs
,
558 CFDataGetMutableBytePtr(data
), &size
);
559 require(drtn
== DR_Success
, errOut
);
560 CFDataSetLength(data
, size
);
562 dataret
= CFRetain(data
);
565 CFReleaseNull(publicKey
);
572 SecKeyRef
SecKeyCreate(CFAllocatorRef allocator
,
573 const SecKeyDescriptor
*key_class
, const uint8_t *keyData
,
574 CFIndex keyDataLength
, SecKeyEncoding encoding
) {
575 if (!key_class
) return NULL
;
576 size_t size
= sizeof(struct __SecKey
) + key_class
->extraBytes
;
577 SecKeyRef result
= (SecKeyRef
)_CFRuntimeCreateInstance(allocator
,
578 SecKeyGetTypeID(), size
- sizeof(CFRuntimeBase
), NULL
);
580 memset((char*)result
+ sizeof(result
->_base
), 0, size
- sizeof(result
->_base
));
581 result
->key_class
= key_class
;
582 if (key_class
->extraBytes
) {
583 /* Make result->key point to the extraBytes we allocated. */
584 result
->key
= ((char*)result
) + sizeof(*result
);
586 if (key_class
->init
) {
588 status
= key_class
->init(result
, keyData
, keyDataLength
, encoding
);
590 secwarning("init %s key: %" PRIdOSStatus
, key_class
->name
, status
);
599 static SecKeyAlgorithm
SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key
, SecPadding padding
) {
600 switch (SecKeyGetAlgorithmIdentifier(key
)) {
601 case kSecRSAAlgorithmID
:
603 case kSecPaddingNone
:
604 return kSecKeyAlgorithmRSASignatureRaw
;
605 case kSecPaddingPKCS1
:
606 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw
;
608 case kSecPaddingPKCS1SHA1
:
609 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
;
610 case kSecPaddingPKCS1SHA224
:
611 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224
;
612 case kSecPaddingPKCS1SHA256
:
613 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
;
614 case kSecPaddingPKCS1SHA384
:
615 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
;
616 case kSecPaddingPKCS1SHA512
:
617 return kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
;
619 // On CSSM-based implementation, these functions actually did hash its input,
620 // so keep doing that for backward compatibility.
621 case kSecPaddingPKCS1SHA1
:
622 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
;
623 case kSecPaddingPKCS1SHA224
:
624 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224
;
625 case kSecPaddingPKCS1SHA256
:
626 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256
;
627 case kSecPaddingPKCS1SHA384
:
628 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384
;
629 case kSecPaddingPKCS1SHA512
:
630 return kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512
;
635 case kSecECDSAAlgorithmID
:
637 case kSecPaddingSigRaw
:
638 return kSecKeyAlgorithmECDSASignatureRFC4754
;
640 // Although it is not very logical, previous SecECKey implementation really considered
641 // anything else than SigRaw (incl. None!) as PKCS1 (i.e. x962), so we keep the behaviour
642 // for backward compatibility.
643 return kSecKeyAlgorithmECDSASignatureDigestX962
;
650 // Generic wrapper helper for invoking new-style CFDataRef-based operations with ptr/length arguments
651 // used by legacy RawSign-style functions.
652 static OSStatus
SecKeyPerformLegacyOperation(SecKeyRef key
,
653 const uint8_t *in1Ptr
, size_t in1Len
,
654 const uint8_t *in2Ptr
, size_t in2Len
,
655 uint8_t *outPtr
, size_t *outLen
,
656 CFTypeRef (^operation
)(CFDataRef in1
, CFDataRef in2
, CFRange
*resultRange
, CFErrorRef
*error
)) {
657 CFErrorRef error
= NULL
;
658 OSStatus status
= errSecSuccess
;
659 CFDataRef in1
= CFDataCreateWithBytesNoCopy(NULL
, in1Ptr
, in1Len
, kCFAllocatorNull
);
660 CFDataRef in2
= CFDataCreateWithBytesNoCopy(NULL
, in2Ptr
, in2Len
, kCFAllocatorNull
);
661 CFRange range
= { 0, -1 };
662 CFTypeRef output
= operation(in1
, in2
, &range
, &error
);
663 require_quiet(output
, out
);
664 if (CFGetTypeID(output
) == CFDataGetTypeID() && outLen
!= NULL
) {
665 if (range
.length
== -1) {
666 range
.length
= CFDataGetLength(output
);
668 require_action_quiet((size_t)range
.length
<= *outLen
, out
,
669 SecError(errSecParam
, &error
, CFSTR("buffer too small")));
670 *outLen
= range
.length
;
671 CFDataGetBytes(output
, range
, outPtr
);
677 CFReleaseSafe(output
);
679 status
= SecErrorGetOSStatus(error
);
680 if (status
== errSecVerifyFailed
) {
681 // Legacy functions used errSSLCrypto, while new implementation uses errSecVerifyFailed.
682 status
= errSSLCrypto
;
689 OSStatus
SecKeyRawSign(
690 SecKeyRef key
, /* Private key */
691 SecPadding padding
, /* kSecPaddingNone or kSecPaddingPKCS1 */
692 const uint8_t *dataToSign
, /* signature over this data */
693 size_t dataToSignLen
, /* length of dataToSign */
694 uint8_t *sig
, /* signature, RETURNED */
695 size_t *sigLen
) { /* IN/OUT */
696 SecKeyAlgorithm algorithm
= SecKeyGetSignatureAlgorithmForPadding(key
, padding
);
697 if (algorithm
== NULL
) {
700 return SecKeyPerformLegacyOperation(key
, dataToSign
, dataToSignLen
, NULL
, 0, sig
, sigLen
,
701 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
702 return SecKeyCreateSignature(key
, algorithm
, in1
, error
);
706 OSStatus
SecKeyRawVerify(
707 SecKeyRef key
, /* Public key */
708 SecPadding padding
, /* kSecPaddingNone or kSecPaddingPKCS1 */
709 const uint8_t *signedData
, /* signature over this data */
710 size_t signedDataLen
, /* length of dataToSign */
711 const uint8_t *sig
, /* signature */
712 size_t sigLen
) { /* length of signature */
713 SecKeyAlgorithm algorithm
= SecKeyGetSignatureAlgorithmForPadding(key
, padding
);
714 if (algorithm
== NULL
) {
717 OSStatus status
= SecKeyPerformLegacyOperation(key
, signedData
, signedDataLen
, sig
, sigLen
, NULL
, NULL
,
718 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
719 return SecKeyVerifySignature(key
, algorithm
, in1
, in2
, error
)
720 ? kCFBooleanTrue
: NULL
;
725 static SecKeyAlgorithm
SecKeyGetEncryptionAlgorithmForPadding(SecKeyRef key
, SecPadding padding
) {
726 switch (SecKeyGetAlgorithmIdentifier(key
)) {
727 case kSecRSAAlgorithmID
:
729 case kSecPaddingNone
:
730 return kSecKeyAlgorithmRSAEncryptionRaw
;
731 case kSecPaddingPKCS1
:
732 return kSecKeyAlgorithmRSAEncryptionPKCS1
;
733 case kSecPaddingOAEP
:
734 return kSecKeyAlgorithmRSAEncryptionOAEPSHA1
;
743 OSStatus
SecKeyEncrypt(
744 SecKeyRef key
, /* Public key */
745 SecPadding padding
, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */
746 const uint8_t *plainText
,
747 size_t plainTextLen
, /* length of plainText */
749 size_t *cipherTextLen
) { /* IN/OUT */
750 SecKeyAlgorithm algorithm
= SecKeyGetEncryptionAlgorithmForPadding(key
, padding
);
751 if (algorithm
== NULL
) {
755 return SecKeyPerformLegacyOperation(key
, plainText
, plainTextLen
, NULL
, 0, cipherText
, cipherTextLen
,
756 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
757 return SecKeyCreateEncryptedData(key
, algorithm
, in1
, error
);
761 OSStatus
SecKeyDecrypt(
762 SecKeyRef key
, /* Private key */
763 SecPadding padding
, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */
764 const uint8_t *cipherText
,
765 size_t cipherTextLen
, /* length of cipherText */
767 size_t *plainTextLen
) { /* IN/OUT */
768 SecKeyAlgorithm algorithm
= SecKeyGetEncryptionAlgorithmForPadding(key
, padding
);
769 if (algorithm
== NULL
) {
772 return SecKeyPerformLegacyOperation(key
, cipherText
, cipherTextLen
, NULL
, 0, plainText
, plainTextLen
,
773 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
774 CFDataRef decrypted
= SecKeyCreateDecryptedData(key
, algorithm
, in1
, error
);
776 if (decrypted
!= NULL
&& algorithm
== kSecKeyAlgorithmRSAEncryptionRaw
&&
777 *(data
= CFDataGetBytePtr(decrypted
)) == 0x00) {
778 // Strip zero-padding from the beginning of the block, as the contract of this
780 range
->length
= CFDataGetLength(decrypted
);
781 while (*data
== 0x00 && range
->length
> 0) {
791 size_t SecKeyGetBlockSize(SecKeyRef key
) {
792 if (key
->key_class
->blockSize
)
793 return key
->key_class
->blockSize(key
);
797 /* Private API functions. */
799 CFDictionaryRef
SecKeyCopyAttributeDictionary(SecKeyRef key
) {
800 return SecKeyCopyAttributes(key
);
803 SecKeyRef
SecKeyCreateFromAttributeDictionary(CFDictionaryRef refAttributes
) {
804 CFErrorRef error
= NULL
;
805 SecKeyRef key
= SecKeyCreateWithData(CFDictionaryGetValue(refAttributes
, kSecValueData
), refAttributes
, &error
);
807 CFStringRef description
= CFErrorCopyDescription(error
);
808 secwarning("%@", description
);
809 CFRelease(description
);
815 static SecKeyAlgorithm
SecKeyGetAlgorithmForSecAsn1AlgId(SecKeyRef key
, const SecAsn1AlgId
*algId
, bool digestData
) {
816 static const struct TableItem
{
817 const SecAsn1Oid
*oid1
, *oid2
;
818 const SecKeyAlgorithm
*algorithms
[2];
819 } translationTableRSA
[] = {
820 { &CSSMOID_SHA1WithRSA
, &CSSMOID_SHA1
, {
821 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
,
822 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
,
824 { &CSSMOID_SHA224WithRSA
, &CSSMOID_SHA224
, {
825 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224
,
826 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224
,
828 { &CSSMOID_SHA256WithRSA
, &CSSMOID_SHA256
, {
829 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
,
830 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256
,
832 { &CSSMOID_SHA384WithRSA
, &CSSMOID_SHA384
, {
833 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
,
834 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384
,
836 { &CSSMOID_SHA512WithRSA
, &CSSMOID_SHA512
, {
837 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
,
838 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512
,
840 { &CSSMOID_MD5
, NULL
, {
841 [false] = &kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
,
842 [true] = &kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
,
845 }, translationTableECDSA
[] = {
846 { &CSSMOID_ECDSA_WithSHA1
, &CSSMOID_SHA1
, {
847 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962
,
848 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA1
,
850 { &CSSMOID_ECDSA_WithSHA224
, &CSSMOID_SHA224
, {
851 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962
,
852 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA224
,
854 { &CSSMOID_ECDSA_WithSHA256
, &CSSMOID_SHA256
, {
855 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962
,
856 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA256
,
858 { &CSSMOID_ECDSA_WithSHA384
, &CSSMOID_SHA384
, {
859 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962
,
860 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA384
,
862 { &CSSMOID_ECDSA_WithSHA512
, &CSSMOID_SHA512
, {
863 [false] = &kSecKeyAlgorithmECDSASignatureDigestX962
,
864 [true] = &kSecKeyAlgorithmECDSASignatureMessageX962SHA512
,
869 const struct TableItem
*table
;
870 switch (SecKeyGetAlgorithmIdentifier(key
)) {
871 case kSecRSAAlgorithmID
:
872 table
= translationTableRSA
;
874 case kSecECDSAAlgorithmID
:
875 table
= translationTableECDSA
;
881 for (; table
->oid1
!= NULL
; table
++) {
882 if (SecAsn1OidCompare(table
->oid1
, &algId
->algorithm
) ||
883 (table
->oid2
!= NULL
&& SecAsn1OidCompare(table
->oid2
, &algId
->algorithm
))) {
884 return *table
->algorithms
[digestData
];
890 OSStatus
SecKeyDigestAndVerify(
891 SecKeyRef key
, /* Private key */
892 const SecAsn1AlgId
*algId
, /* algorithm oid/params */
893 const uint8_t *dataToDigest
, /* signature over this data */
894 size_t dataToDigestLen
,/* length of dataToDigest */
895 const uint8_t *sig
, /* signature to verify */
896 size_t sigLen
) { /* length of sig */
898 SecKeyAlgorithm algorithm
= SecKeyGetAlgorithmForSecAsn1AlgId(key
, algId
, true);
899 if (algorithm
== NULL
) {
900 return errSecUnimplemented
;
903 return SecKeyPerformLegacyOperation(key
, dataToDigest
, dataToDigestLen
, sig
, sigLen
, NULL
, NULL
,
904 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
905 return SecKeyVerifySignature(key
, algorithm
, in1
, in2
, error
) ?
906 kCFBooleanTrue
: NULL
;
910 OSStatus
SecKeyDigestAndSign(
911 SecKeyRef key
, /* Private key */
912 const SecAsn1AlgId
*algId
, /* algorithm oid/params */
913 const uint8_t *dataToDigest
, /* signature over this data */
914 size_t dataToDigestLen
,/* length of dataToDigest */
915 uint8_t *sig
, /* signature, RETURNED */
916 size_t *sigLen
) { /* IN/OUT */
917 SecKeyAlgorithm algorithm
= SecKeyGetAlgorithmForSecAsn1AlgId(key
, algId
, true);
918 if (algorithm
== NULL
) {
919 return errSecUnimplemented
;
922 return SecKeyPerformLegacyOperation(key
, dataToDigest
, dataToDigestLen
, NULL
, 0, sig
, sigLen
,
923 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
924 return SecKeyCreateSignature(key
, algorithm
, in1
, error
);
928 OSStatus
SecKeyVerifyDigest(
929 SecKeyRef key
, /* Private key */
930 const SecAsn1AlgId
*algId
, /* algorithm oid/params */
931 const uint8_t *digestData
, /* signature over this digest */
932 size_t digestDataLen
,/* length of dataToDigest */
933 const uint8_t *sig
, /* signature to verify */
934 size_t sigLen
) { /* length of sig */
935 SecKeyAlgorithm algorithm
= SecKeyGetAlgorithmForSecAsn1AlgId(key
, algId
, false);
936 if (algorithm
== NULL
) {
937 return errSecUnimplemented
;
940 return SecKeyPerformLegacyOperation(key
, digestData
, digestDataLen
, sig
, sigLen
, NULL
, NULL
,
941 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
942 return SecKeyVerifySignature(key
, algorithm
, in1
, in2
, error
) ?
943 kCFBooleanTrue
: NULL
;
947 OSStatus
SecKeySignDigest(
948 SecKeyRef key
, /* Private key */
949 const SecAsn1AlgId
*algId
, /* algorithm oid/params */
950 const uint8_t *digestData
, /* signature over this digest */
951 size_t digestDataLen
,/* length of digestData */
952 uint8_t *sig
, /* signature, RETURNED */
953 size_t *sigLen
) { /* IN/OUT */
954 SecKeyAlgorithm algorithm
= SecKeyGetAlgorithmForSecAsn1AlgId(key
, algId
, false);
955 if (algorithm
== NULL
) {
956 return errSecUnimplemented
;
959 return SecKeyPerformLegacyOperation(key
, digestData
, digestDataLen
, NULL
, 0, sig
, sigLen
,
960 ^CFTypeRef(CFDataRef in1
, CFDataRef in2
, CFRange
*range
, CFErrorRef
*error
) {
961 return SecKeyCreateSignature(key
, algorithm
, in1
, error
);
965 CFIndex
SecKeyGetAlgorithmId(SecKeyRef key
) {
966 return SecKeyGetAlgorithmIdentifier(key
);
969 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR))
970 /* On OS X, SecKeyGetAlgorithmID has a different function signature (two arguments,
971 with output in the second argument). Therefore, avoid implementing this function here
972 if compiling for OS X.
975 CFIndex
SecKeyGetAlgorithmID(SecKeyRef key
) {
976 return SecKeyGetAlgorithmIdentifier(key
);
980 OSStatus
SecKeyCopyPublicBytes(SecKeyRef key
, CFDataRef
* serializedPublic
) {
981 if (key
->key_class
->version
> 1 && key
->key_class
->copyPublic
)
982 return key
->key_class
->copyPublic(key
, serializedPublic
);
983 return errSecUnimplemented
;
986 SecKeyRef
SecKeyCreateFromPublicBytes(CFAllocatorRef allocator
, CFIndex algorithmID
, const uint8_t *keyData
, CFIndex keyDataLength
)
990 case kSecRSAAlgorithmID
:
991 return SecKeyCreateRSAPublicKey(allocator
,
992 keyData
, keyDataLength
,
993 kSecKeyEncodingBytes
);
994 case kSecECDSAAlgorithmID
:
995 return SecKeyCreateECPublicKey(allocator
,
996 keyData
, keyDataLength
,
997 kSecKeyEncodingBytes
);
1003 SecKeyRef
SecKeyCreateFromPublicData(CFAllocatorRef allocator
, CFIndex algorithmID
, CFDataRef serialized
)
1005 return SecKeyCreateFromPublicBytes(allocator
, algorithmID
, CFDataGetBytePtr(serialized
), CFDataGetLength(serialized
));
1008 // This is a bit icky hack to avoid changing the vtable for
1010 size_t SecKeyGetSize(SecKeyRef key
, SecKeySize whichSize
)
1012 size_t result
= SecKeyGetBlockSize(key
);
1014 if (kSecECDSAAlgorithmID
== SecKeyGetAlgorithmIdentifier(key
)) {
1015 switch (whichSize
) {
1016 case kSecKeyEncryptedDataSize
:
1019 case kSecKeySignatureSize
:
1020 result
= (result
>= 66 ? 9 : 8) + 2 * result
;
1022 case kSecKeyKeySizeInBits
:
1028 if (whichSize
== kSecKeyKeySizeInBits
)
1035 OSStatus
SecKeyFindWithPersistentRef(CFDataRef persistentRef
, SecKeyRef
* lookedUpData
)
1037 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
1038 kSecReturnRef
, kCFBooleanTrue
,
1039 kSecClass
, kSecClassKey
,
1040 kSecValuePersistentRef
, persistentRef
,
1042 CFTypeRef foundRef
= NULL
;
1043 OSStatus status
= SecItemCopyMatching(query
, &foundRef
);
1045 if (status
== errSecSuccess
) {
1046 if (CFGetTypeID(foundRef
) == SecKeyGetTypeID()) {
1047 *lookedUpData
= (SecKeyRef
) foundRef
;
1049 status
= errSecSuccess
;
1051 status
= errSecItemNotFound
;
1055 CFReleaseSafe(foundRef
);
1056 CFReleaseSafe(query
);
1061 OSStatus
SecKeyCopyPersistentRef(SecKeyRef key
, CFDataRef
* persistentRef
)
1063 CFDictionaryRef query
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
1064 kSecReturnPersistentRef
, kCFBooleanTrue
,
1066 kSecAttrSynchronizable
, kSecAttrSynchronizableAny
,
1068 CFTypeRef foundRef
= NULL
;
1069 OSStatus status
= SecItemCopyMatching(query
, &foundRef
);
1071 if (status
== errSecSuccess
) {
1072 if (CFGetTypeID(foundRef
) == CFDataGetTypeID()) {
1073 *persistentRef
= foundRef
;
1076 status
= errSecItemNotFound
;
1080 CFReleaseSafe(foundRef
);
1081 CFReleaseSafe(query
);
1090 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
1092 SEC_CONST_DECL(_kSecKeyWrapPGPSymAlg
, "kSecKeyWrapPGPSymAlg");
1093 SEC_CONST_DECL(_kSecKeyWrapPGPFingerprint
, "kSecKeyWrapPGPFingerprint");
1094 SEC_CONST_DECL(_kSecKeyWrapPGPWrapAlg
, "kSecKeyWrapPGPWrapAlg");
1095 SEC_CONST_DECL(_kSecKeyWrapRFC6637Flags
, "kSecKeyWrapPGPECFlags");
1096 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA256KekAES128
, "kSecKeyWrapPGPECWrapDigestSHA256KekAES128");
1097 SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA512KekAES256
, "kSecKeyWrapPGPECWrapDigestSHA512KekAES256");
1099 #undef SEC_CONST_DECL
1102 _SecKeyCopyWrapKey(SecKeyRef key
, SecKeyWrapType type
, CFDataRef unwrappedKey
, CFDictionaryRef parameters
, CFDictionaryRef
*outParam
, CFErrorRef
*error
)
1108 if (key
->key_class
->version
> 2 && key
->key_class
->copyWrapKey
)
1109 return key
->key_class
->copyWrapKey(key
, type
, unwrappedKey
, parameters
, outParam
, error
);
1110 SecError(errSecUnsupportedOperation
, error
, CFSTR("No key wrap supported for key %@"), key
);
1115 _SecKeyCopyUnwrapKey(SecKeyRef key
, SecKeyWrapType type
, CFDataRef wrappedKey
, CFDictionaryRef parameters
, CFDictionaryRef
*outParam
, CFErrorRef
*error
)
1121 if (key
->key_class
->version
> 2 && key
->key_class
->copyUnwrapKey
)
1122 return key
->key_class
->copyUnwrapKey(key
, type
, wrappedKey
, parameters
, outParam
, error
);
1124 SecError(errSecUnsupportedOperation
, error
, CFSTR("No key unwrap for key %@"), key
);
1128 static CFIndex
SecKeyParamsGetCFIndex(CFTypeRef value
, CFStringRef errName
, CFErrorRef
*error
) {
1129 CFIndex result
= -1;
1130 CFNumberRef localValue
= NULL
;
1132 if (isString(value
)) {
1133 CFNumberFormatterRef formatter
= CFNumberFormatterCreate(kCFAllocatorDefault
, CFLocaleGetSystem(), kCFNumberFormatterDecimalStyle
);
1134 localValue
= CFNumberFormatterCreateNumberFromString(kCFAllocatorDefault
, formatter
, value
, NULL
, kCFNumberFormatterParseIntegersOnly
);
1135 CFReleaseSafe(formatter
);
1138 CFStringRef t
= CFStringCreateWithFormat(0, 0, CFSTR("%@"), localValue
);
1139 if (CFEqual(t
, value
)) {
1146 if (value
!= NULL
&& CFGetTypeID(value
) == CFNumberGetTypeID()) {
1147 if (!CFNumberGetValue(value
, kCFNumberCFIndexType
, &result
) || result
< 0) {
1148 SecError(errSecParam
, error
, CFSTR("Unsupported %@: %@"), errName
, value
);
1151 SecError(errSecParam
, error
, CFSTR("Unsupported %@: %@"), errName
, value
);
1154 CFReleaseSafe(localValue
);
1158 SecKeyRef
SecKeyCreateWithData(CFDataRef keyData
, CFDictionaryRef parameters
, CFErrorRef
*error
) {
1160 SecKeyRef key
= NULL
;
1161 CFAllocatorRef allocator
= NULL
;
1163 if (CFDictionaryGetValue(parameters
, kSecAttrTokenID
) != NULL
) {
1164 return SecKeyCreateCTKKey(allocator
, parameters
, error
);
1166 /* First figure out the key type (algorithm). */
1167 CFIndex algorithm
, class;
1168 CFTypeRef ktype
= CFDictionaryGetValue(parameters
, kSecAttrKeyType
);
1169 require_quiet((algorithm
= SecKeyParamsGetCFIndex(ktype
, CFSTR("key type"), error
)) >= 0, out
);
1170 CFTypeRef kclass
= CFDictionaryGetValue(parameters
, kSecAttrKeyClass
);
1171 require_quiet((class = SecKeyParamsGetCFIndex(kclass
, CFSTR("key class"), error
)) >= 0, out
);
1174 case 0: // kSecAttrKeyClassPublic
1175 switch (algorithm
) {
1176 case 42: // kSecAlgorithmRSA
1177 key
= SecKeyCreateRSAPublicKey(allocator
,
1178 CFDataGetBytePtr(keyData
), CFDataGetLength(keyData
),
1179 kSecKeyEncodingBytes
);
1181 SecError(errSecParam
, error
, CFSTR("RSA public key creation from data failed"));
1184 case 43: // kSecAlgorithmECDSA
1185 case 73: // kSecAlgorithmEC
1186 key
= SecKeyCreateECPublicKey(allocator
,
1187 CFDataGetBytePtr(keyData
), CFDataGetLength(keyData
),
1188 kSecKeyEncodingBytes
);
1190 SecError(errSecParam
, error
, CFSTR("EC public key creation from data failed"));
1194 SecError(errSecParam
, error
, CFSTR("Unsupported public key type: %@"), ktype
);
1198 case 1: // kSecAttrKeyClassPrivate
1199 switch (algorithm
) {
1200 case 42: // kSecAlgorithmRSA
1201 key
= SecKeyCreateRSAPrivateKey(allocator
,
1202 CFDataGetBytePtr(keyData
), CFDataGetLength(keyData
),
1203 kSecKeyEncodingBytes
);
1205 SecError(errSecParam
, error
, CFSTR("RSA private key creation from data failed"));
1208 case 43: // kSecAlgorithmECDSA
1209 case 73: // kSecAlgorithmEC
1210 key
= SecKeyCreateECPrivateKey(allocator
,
1211 CFDataGetBytePtr(keyData
), CFDataGetLength(keyData
),
1212 kSecKeyEncodingBytes
);
1214 SecError(errSecParam
, error
, CFSTR("EC public key creation from data failed"));
1218 SecError(errSecParam
, error
, CFSTR("Unsupported private key type: %@"), ktype
);
1222 case 2: // kSecAttrKeyClassSymmetric
1223 SecError(errSecUnimplemented
, error
, CFSTR("Unsupported symmetric key type: %@"), ktype
);
1226 SecError(errSecParam
, error
, CFSTR("Unsupported key class: %@"), kclass
);
1234 CFDataRef
SecKeyCopyExternalRepresentation(SecKeyRef key
, CFErrorRef
*error
) {
1235 if (!key
->key_class
->copyExternalRepresentation
) {
1236 SecError(errSecUnimplemented
, error
, CFSTR("export not implemented for key %@"), key
);
1240 return key
->key_class
->copyExternalRepresentation(key
, error
);
1243 CFDictionaryRef
SecKeyCopyAttributes(SecKeyRef key
) {
1244 if (key
->key_class
->copyDictionary
) {
1245 return key
->key_class
->copyDictionary(key
);
1247 // Create dictionary with basic values derived from other known information of the key.
1248 CFMutableDictionaryRef dict
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
1249 CFIndex blockSize
= SecKeyGetBlockSize(key
) * 8;
1250 if (blockSize
> 0) {
1251 CFNumberRef blockSizeRef
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberCFIndexType
, &blockSize
);
1252 CFDictionarySetValue(dict
, kSecAttrKeySizeInBits
, blockSizeRef
);
1253 CFRelease(blockSizeRef
);
1256 switch (SecKeyGetAlgorithmIdentifier(key
)) {
1257 case kSecRSAAlgorithmID
:
1258 CFDictionarySetValue(dict
, kSecAttrKeyType
, kSecAttrKeyTypeRSA
);
1260 case kSecECDSAAlgorithmID
:
1261 CFDictionarySetValue(dict
, kSecAttrKeyType
, kSecAttrKeyTypeECSECPrimeRandom
);
1265 if (key
->key_class
->rawSign
!= NULL
|| key
->key_class
->decrypt
!= NULL
) {
1266 CFDictionarySetValue(dict
, kSecAttrKeyClass
, kSecAttrKeyClassPrivate
);
1267 } else if (key
->key_class
->rawVerify
!= NULL
|| key
->key_class
->encrypt
!= NULL
) {
1268 CFDictionarySetValue(dict
, kSecAttrKeyClass
, kSecAttrKeyClassPublic
);
1275 SecKeyRef
SecKeyCopyPublicKey(SecKeyRef key
) {
1276 SecKeyRef result
= NULL
;
1277 if (key
->key_class
->version
>= 4 && key
->key_class
->copyPublicKey
) {
1278 result
= key
->key_class
->copyPublicKey(key
);
1279 if (result
!= NULL
) {
1284 CFDataRef serializedPublic
= NULL
;
1286 require_noerr_quiet(SecKeyCopyPublicBytes(key
, &serializedPublic
), fail
);
1287 require_quiet(serializedPublic
, fail
);
1289 result
= SecKeyCreateFromPublicData(kCFAllocatorDefault
, SecKeyGetAlgorithmIdentifier(key
), serializedPublic
);
1292 CFReleaseSafe(serializedPublic
);
1296 SecKeyRef
SecKeyCreateRandomKey(CFDictionaryRef parameters
, CFErrorRef
*error
) {
1297 SecKeyRef privKey
= NULL
, pubKey
= NULL
;
1298 OSStatus status
= SecKeyGeneratePair(parameters
, &pubKey
, &privKey
);
1299 SecError(status
, error
, CFSTR("Key generation failed, error %d"), (int)status
);
1300 CFReleaseSafe(pubKey
);
1304 SecKeyRef
SecKeyCreateDuplicate(SecKeyRef key
) {
1305 if (key
->key_class
->version
>= 4 && key
->key_class
->createDuplicate
) {
1306 return key
->key_class
->createDuplicate(key
);
1308 return (SecKeyRef
)CFRetain(key
);
1312 Boolean
SecKeySetParameter(SecKeyRef key
, CFStringRef name
, CFPropertyListRef value
, CFErrorRef
*error
) {
1313 if (key
->key_class
->version
>= 4 && key
->key_class
->setParameter
) {
1314 return key
->key_class
->setParameter(key
, name
, value
, error
);
1316 return SecError(errSecUnimplemented
, error
, CFSTR("setParameter not implemented for %@"), key
);
1320 #pragma mark Generic algorithm adaptor lookup and invocation
1322 static CFTypeRef
SecKeyCopyBackendOperationResult(SecKeyOperationContext
*context
, SecKeyAlgorithm algorithm
,
1323 CFTypeRef in1
, CFTypeRef in2
, CFErrorRef
*error
) {
1324 CFTypeRef result
= kCFNull
;
1325 assert(CFArrayGetCount(context
->algorithm
) > 0);
1326 if (context
->key
->key_class
->version
>= 4 && context
->key
->key_class
->copyOperationResult
!= NULL
) {
1327 return context
->key
->key_class
->copyOperationResult(context
->key
, context
->operation
, algorithm
,
1328 context
->algorithm
, context
->mode
, in1
, in2
, error
);
1331 // Mapping from algorithms to legacy SecPadding values.
1332 static const struct {
1333 const SecKeyAlgorithm
*algorithm
;
1337 { &kSecKeyAlgorithmRSASignatureRaw
, kSecRSAAlgorithmID
, kSecPaddingNone
},
1338 { &kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw
, kSecRSAAlgorithmID
, kSecPaddingPKCS1
},
1339 { &kSecKeyAlgorithmECDSASignatureRFC4754
, kSecECDSAAlgorithmID
, kSecPaddingSigRaw
},
1340 { &kSecKeyAlgorithmECDSASignatureDigestX962
, kSecECDSAAlgorithmID
, kSecPaddingPKCS1
},
1341 { &kSecKeyAlgorithmRSAEncryptionRaw
, kSecRSAAlgorithmID
, kSecPaddingNone
},
1342 { &kSecKeyAlgorithmRSAEncryptionPKCS1
, kSecRSAAlgorithmID
, kSecPaddingPKCS1
},
1343 { &kSecKeyAlgorithmRSAEncryptionOAEPSHA1
, kSecRSAAlgorithmID
, kSecPaddingOAEP
},
1345 SecPadding padding
= (SecPadding
)-1;
1346 CFIndex keyAlg
= SecKeyGetAlgorithmIdentifier(context
->key
);
1347 for (size_t i
= 0; i
< array_size(paddingMap
); ++i
) {
1348 if (keyAlg
== paddingMap
[i
].keyAlg
&& CFEqual(algorithm
, *paddingMap
[i
].algorithm
)) {
1349 padding
= paddingMap
[i
].padding
;
1353 require_quiet(padding
!= (SecPadding
)-1, out
);
1355 // Check legacy virtual table entries.
1357 OSStatus status
= errSecSuccess
;
1358 switch (context
->operation
) {
1359 case kSecKeyOperationTypeSign
:
1360 if (context
->key
->key_class
->rawSign
!= NULL
) {
1361 result
= kCFBooleanTrue
;
1362 if (context
->mode
== kSecKeyOperationModePerform
) {
1363 size
= SecKeyGetSize(context
->key
, kSecKeySignatureSize
);
1364 result
= CFDataCreateMutableWithScratch(NULL
, size
);
1365 status
= context
->key
->key_class
->rawSign(context
->key
, padding
,
1366 CFDataGetBytePtr(in1
), CFDataGetLength(in1
),
1367 CFDataGetMutableBytePtr((CFMutableDataRef
)result
), &size
);
1371 case kSecKeyOperationTypeVerify
:
1372 if (context
->key
->key_class
->rawVerify
!= NULL
) {
1373 result
= kCFBooleanTrue
;
1374 if (context
->mode
== kSecKeyOperationModePerform
) {
1375 status
= context
->key
->key_class
->rawVerify(context
->key
, padding
,
1376 CFDataGetBytePtr(in1
), CFDataGetLength(in1
),
1377 CFDataGetBytePtr(in2
), CFDataGetLength(in2
));
1381 case kSecKeyOperationTypeEncrypt
:
1382 if (context
->key
->key_class
->encrypt
!= NULL
) {
1383 result
= kCFBooleanTrue
;
1384 if (context
->mode
== kSecKeyOperationModePerform
) {
1385 size
= SecKeyGetSize(context
->key
, kSecKeyEncryptedDataSize
);
1386 result
= CFDataCreateMutableWithScratch(NULL
, size
);
1387 status
= context
->key
->key_class
->encrypt(context
->key
, padding
,
1388 CFDataGetBytePtr(in1
), CFDataGetLength(in1
),
1389 CFDataGetMutableBytePtr((CFMutableDataRef
)result
), &size
);
1393 case kSecKeyOperationTypeDecrypt
:
1394 if (context
->key
->key_class
->decrypt
!= NULL
) {
1395 result
= kCFBooleanTrue
;
1396 if (context
->mode
== kSecKeyOperationModePerform
) {
1397 size
= SecKeyGetSize(context
->key
, kSecKeyEncryptedDataSize
);
1398 result
= CFDataCreateMutableWithScratch(NULL
, size
);
1399 status
= context
->key
->key_class
->decrypt(context
->key
, padding
,
1400 CFDataGetBytePtr(in1
), CFDataGetLength(in1
),
1401 CFDataGetMutableBytePtr((CFMutableDataRef
)result
), &size
);
1409 if (status
== errSecSuccess
) {
1410 if (CFGetTypeID(result
) == CFDataGetTypeID()) {
1411 CFDataSetLength((CFMutableDataRef
)result
, size
);
1414 SecError(status
, error
, CFSTR("legacy SecKey backend operation:%d(%d) failed"), (int)context
->operation
, (int)padding
);
1415 CFReleaseNull(result
);
1422 CFTypeRef
SecKeyRunAlgorithmAndCopyResult(SecKeyOperationContext
*context
, CFTypeRef in1
, CFTypeRef in2
, CFErrorRef
*error
) {
1424 // Check algorithm array for cycles; if any value of it is duplicated inside, report 'algorithm not found' error.
1425 CFIndex algorithmCount
= CFArrayGetCount(context
->algorithm
);
1426 for (CFIndex index
= 0; index
< algorithmCount
- 1; index
++) {
1427 SecKeyAlgorithm indexAlgorithm
= CFArrayGetValueAtIndex(context
->algorithm
, index
);
1428 for (CFIndex tested
= index
+ 1; tested
< algorithmCount
; tested
++) {
1429 require_quiet(!CFEqual(indexAlgorithm
, CFArrayGetValueAtIndex(context
->algorithm
, tested
)), fail
);
1433 SecKeyAlgorithm algorithm
= CFArrayGetValueAtIndex(context
->algorithm
, algorithmCount
- 1);
1434 CFTypeRef output
= SecKeyCopyBackendOperationResult(context
, algorithm
, in1
, in2
, error
);
1435 if (output
!= kCFNull
) {
1436 // Backend handled the operation, return result.
1440 // To silence static analyzer.
1441 CFReleaseSafe(output
);
1443 // Get adaptor which is able to handle requested algorithm.
1444 SecKeyAlgorithmAdaptor adaptor
= SecKeyGetAlgorithmAdaptor(context
->operation
, algorithm
);
1445 require_quiet(adaptor
!= NULL
, fail
);
1447 // Invoke the adaptor and return result.
1448 CFTypeRef result
= adaptor(context
, in1
, in2
, error
);
1449 require_quiet(result
!= kCFNull
, fail
);
1453 if (context
->mode
== kSecKeyOperationModePerform
) {
1454 SecError(errSecParam
, error
, CFSTR("%@: algorithm not supported by the key %@"),
1455 CFArrayGetValueAtIndex(context
->algorithm
, 0), context
->key
);
1462 #pragma mark Algorithm-related SecKey API entry points
1464 static CFMutableArrayRef
SecKeyCreateAlgorithmArray(SecKeyAlgorithm algorithm
) {
1465 CFMutableArrayRef result
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
1466 CFArrayAppendValue(result
, algorithm
);
1470 CFDataRef
SecKeyCreateSignature(SecKeyRef key
, SecKeyAlgorithm algorithm
, CFDataRef dataToSign
, CFErrorRef
*error
) {
1471 SecKeyOperationContext context
= { key
, kSecKeyOperationTypeSign
, SecKeyCreateAlgorithmArray(algorithm
) };
1472 CFDataRef result
= SecKeyRunAlgorithmAndCopyResult(&context
, dataToSign
, NULL
, error
);
1473 SecKeyOperationContextDestroy(&context
);
1477 Boolean
SecKeyVerifySignature(SecKeyRef key
, SecKeyAlgorithm algorithm
, CFDataRef signedData
, CFDataRef signature
,
1478 CFErrorRef
*error
) {
1479 SecKeyOperationContext context
= { key
, kSecKeyOperationTypeVerify
, SecKeyCreateAlgorithmArray(algorithm
) };
1480 CFTypeRef res
= SecKeyRunAlgorithmAndCopyResult(&context
, signedData
, signature
, error
);
1481 Boolean result
= CFEqualSafe(res
, kCFBooleanTrue
);
1483 SecKeyOperationContextDestroy(&context
);
1487 CFDataRef
SecKeyCreateEncryptedData(SecKeyRef key
, SecKeyAlgorithm algorithm
, CFDataRef plainText
, CFErrorRef
*error
) {
1488 SecKeyOperationContext context
= { key
, kSecKeyOperationTypeEncrypt
, SecKeyCreateAlgorithmArray(algorithm
) };
1489 CFDataRef result
= SecKeyRunAlgorithmAndCopyResult(&context
, plainText
, NULL
, error
);
1490 SecKeyOperationContextDestroy(&context
);
1494 CFDataRef
SecKeyCreateDecryptedData(SecKeyRef key
, SecKeyAlgorithm algorithm
, CFDataRef cipherText
, CFErrorRef
*error
) {
1495 SecKeyOperationContext context
= { key
, kSecKeyOperationTypeDecrypt
, SecKeyCreateAlgorithmArray(algorithm
) };
1496 CFDataRef result
= SecKeyRunAlgorithmAndCopyResult(&context
, cipherText
, NULL
, error
);
1497 SecKeyOperationContextDestroy(&context
);
1501 CFDataRef
SecKeyCopyKeyExchangeResult(SecKeyRef key
, SecKeyAlgorithm algorithm
, SecKeyRef publicKey
,
1502 CFDictionaryRef parameters
, CFErrorRef
*error
) {
1503 CFDataRef publicKeyData
= NULL
, result
= NULL
;
1504 SecKeyOperationContext context
= { key
, kSecKeyOperationTypeKeyExchange
, SecKeyCreateAlgorithmArray(algorithm
) };
1505 require_quiet(publicKeyData
= SecKeyCopyExternalRepresentation(publicKey
, error
), out
);
1506 result
= SecKeyRunAlgorithmAndCopyResult(&context
, publicKeyData
, parameters
, error
);
1509 CFReleaseSafe(publicKeyData
);
1510 SecKeyOperationContextDestroy(&context
);
1514 Boolean
SecKeyIsAlgorithmSupported(SecKeyRef key
, SecKeyOperationType operation
, SecKeyAlgorithm algorithm
) {
1515 SecKeyOperationContext context
= { key
, operation
, SecKeyCreateAlgorithmArray(algorithm
), kSecKeyOperationModeCheckIfSupported
};
1516 CFErrorRef error
= NULL
;
1517 CFTypeRef res
= SecKeyRunAlgorithmAndCopyResult(&context
, NULL
, NULL
, &error
);
1518 Boolean result
= CFEqualSafe(res
, kCFBooleanTrue
);
1520 CFReleaseSafe(error
);
1521 SecKeyOperationContextDestroy(&context
);