2 * Copyright (c) 2002-2012 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 #include "SecKeyPriv.h"
27 #include "SecItemPriv.h"
28 #include <libDER/asn1Types.h>
29 #include <libDER/DER_Encode.h>
30 #include <libDER/DER_Decode.h>
31 #include <libDER/DER_Keys.h>
32 #include <Security/SecAsn1Types.h>
33 #include <Security/SecAsn1Coder.h>
34 #include <security_keychain/KeyItem.h>
35 #include <CommonCrypto/CommonKeyDerivation.h>
37 #include "SecBridge.h"
39 #include <security_keychain/Access.h>
40 #include <security_keychain/Keychains.h>
41 #include <security_keychain/KeyItem.h>
45 #include <security_cdsa_utils/cuCdsaUtils.h>
46 #include <security_cdsa_client/wrapkey.h>
48 #include "SecImportExportCrypto.h"
55 return gTypes().KeyItem
.typeID
;
57 END_SECAPI1(_kCFRuntimeNotATypeID
)
62 SecKeychainRef keychainRef
,
63 CSSM_ALGORITHMS algorithm
,
65 CSSM_CC_HANDLE contextHandle
,
66 CSSM_KEYUSE publicKeyUsage
,
68 CSSM_KEYUSE privateKeyUsage
,
69 uint32 privateKeyAttr
,
70 SecAccessRef initialAccess
,
71 SecKeyRef
* publicKeyRef
,
72 SecKeyRef
* privateKeyRef
)
76 Keychain keychain
= Keychain::optional(keychainRef
);
77 SecPointer
<Access
> theAccess(initialAccess
? Access::required(initialAccess
) : new Access("<key>"));
78 SecPointer
<KeyItem
> pubItem
, privItem
;
80 KeyItem::createPair(keychain
,
92 // Return the generated keys.
94 *publicKeyRef
= pubItem
->handle();
96 *privateKeyRef
= privItem
->handle();
102 SecKeyGetCSSMKey(SecKeyRef key
, const CSSM_KEY
**cssmKey
)
106 Required(cssmKey
) = KeyItem::required(key
)->key();
117 SecKeyGetCSPHandle(SecKeyRef keyRef
, CSSM_CSP_HANDLE
*cspHandle
)
121 SecPointer
<KeyItem
> keyItem(KeyItem::required(keyRef
));
122 Required(cspHandle
) = keyItem
->csp()->handle();
127 /* deprecated as of 10.8 */
129 SecKeyGetAlgorithmID(SecKeyRef keyRef
, const CSSM_X509_ALGORITHM_IDENTIFIER
**algid
)
133 SecPointer
<KeyItem
> keyItem(KeyItem::required(keyRef
));
134 Required(algid
) = &keyItem
->algorithmIdentifier();
141 SecKeyGetAlgorithmId(SecKeyRef key
)
143 const CSSM_KEY
*cssmKey
;
145 if (SecKeyGetCSSMKey(key
, &cssmKey
) != noErr
)
146 return kSecNullAlgorithmID
;
148 switch (cssmKey
->KeyHeader
.AlgorithmId
) {
150 return kSecRSAAlgorithmID
;
152 return kSecDSAAlgorithmID
;
153 case CSSM_ALGID_ECDSA
:
154 return kSecECDSAAlgorithmID
;
156 assert(0); /* other algorithms TBA */
157 return kSecNullAlgorithmID
;
162 SecKeyGetStrengthInBits(SecKeyRef keyRef
, const CSSM_X509_ALGORITHM_IDENTIFIER
*algid
, unsigned int *strength
)
166 SecPointer
<KeyItem
> keyItem(KeyItem::required(keyRef
));
167 Required(strength
) = keyItem
->strengthInBits(algid
);
173 SecKeyGetCredentials(
175 CSSM_ACL_AUTHORIZATION_TAG operation
,
176 SecCredentialType credentialType
,
177 const CSSM_ACCESS_CREDENTIALS
**outCredentials
)
181 SecPointer
<KeyItem
> keyItem(KeyItem::required(keyRef
));
182 Required(outCredentials
) = keyItem
->getCredentials(operation
, credentialType
);
189 SecKeychainRef keychainRef
,
190 const CSSM_KEY
*publicCssmKey
,
191 const CSSM_KEY
*privateCssmKey
,
192 SecAccessRef initialAccess
,
193 SecKeyRef
* publicKey
,
194 SecKeyRef
* privateKey
)
198 Keychain keychain
= Keychain::optional(keychainRef
);
199 SecPointer
<Access
> theAccess(initialAccess
? Access::required(initialAccess
) : new Access("<key>"));
200 SecPointer
<KeyItem
> pubItem
, privItem
;
202 KeyItem::importPair(keychain
,
203 Required(publicCssmKey
),
204 Required(privateCssmKey
),
209 // Return the generated keys.
211 *publicKey
= pubItem
->handle();
213 *privateKey
= privItem
->handle();
219 SecKeyGenerateWithAttributes(
220 SecKeychainAttributeList
* attrList
,
221 SecKeychainRef keychainRef
,
222 CSSM_ALGORITHMS algorithm
,
223 uint32 keySizeInBits
,
224 CSSM_CC_HANDLE contextHandle
,
225 CSSM_KEYUSE keyUsage
,
227 SecAccessRef initialAccess
,
233 SecPointer
<Access
> theAccess
;
236 keychain
= KeychainImpl::required(keychainRef
);
238 theAccess
= Access::required(initialAccess
);
240 SecPointer
<KeyItem
> item
= KeyItem::generateWithAttributes(attrList
,
249 // Return the generated key.
251 *keyRef
= item
->handle();
258 SecKeychainRef keychainRef
,
259 CSSM_ALGORITHMS algorithm
,
260 uint32 keySizeInBits
,
261 CSSM_CC_HANDLE contextHandle
,
262 CSSM_KEYUSE keyUsage
,
264 SecAccessRef initialAccess
,
267 return SecKeyGenerateWithAttributes(NULL
,
268 keychainRef
, algorithm
, keySizeInBits
,
269 contextHandle
, keyUsage
, keyAttr
,
270 initialAccess
, keyRef
);
275 /* Create a key from supplied data and parameters */
277 SecKeyCreate(CFAllocatorRef allocator
,
278 const SecKeyDescriptor
*keyClass
,
279 const uint8_t *keyData
,
280 CFIndex keyDataLength
,
281 SecKeyEncoding encoding
)
283 SecKeyRef keyRef
= NULL
;
284 OSStatus __secapiresult
;
286 //FIXME: needs implementation
288 __secapiresult
=noErr
;
290 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
291 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
292 catch (const std::bad_alloc
&) { __secapiresult
=memFullErr
; }
293 catch (...) { __secapiresult
=internalComponentErr
; }
298 /* Generate a floating key reference from a CSSM_KEY */
300 SecKeyCreateWithCSSMKey(const CSSM_KEY
*cssmKey
,
306 CssmClient::CSP
csp(cssmKey
->KeyHeader
.CspId
);
307 CssmClient::Key
key(csp
, *cssmKey
);
308 KeyItem
*item
= new KeyItem(key
);
310 // Return the generated key.
312 *keyRef
= item
->handle();
319 static u_int32_t
ConvertCFStringToInteger(CFStringRef ref
)
326 // figure out the size of the string
327 int numChars
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref
), kCFStringEncodingUTF8
);
328 char buffer
[numChars
];
329 if (!CFStringGetCString(ref
, buffer
, numChars
, kCFStringEncodingUTF8
))
331 MacOSError::throwMe(paramErr
);
339 static OSStatus
CheckAlgorithmType(CFDictionaryRef parameters
, CSSM_ALGORITHMS
&algorithms
)
341 // figure out the algorithm to use
342 CFStringRef ktype
= (CFStringRef
) CFDictionaryGetValue(parameters
, kSecAttrKeyType
);
348 if (CFEqual(ktype
, kSecAttrKeyTypeRSA
)) {
349 algorithms
= CSSM_ALGID_RSA
;
351 } else if(CFEqual(ktype
, kSecAttrKeyTypeECDSA
)) {
352 algorithms
= CSSM_ALGID_ECDSA
;
354 } else if(CFEqual(ktype
, kSecAttrKeyTypeAES
)) {
355 algorithms
= CSSM_ALGID_AES
;
357 } else if(CFEqual(ktype
, kSecAttrKeyType3DES
)) {
358 algorithms
= CSSM_ALGID_3DES
;
361 return errSecUnsupportedAlgorithm
;
367 static OSStatus
GetKeySize(CFDictionaryRef parameters
, CSSM_ALGORITHMS algorithms
, uint32
&keySizeInBits
)
370 // get the key size and check it for validity
371 CFTypeRef ref
= CFDictionaryGetValue(parameters
, kSecAttrKeySizeInBits
);
373 keySizeInBits
= kSecDefaultKeySize
;
375 CFTypeID bitSizeType
= CFGetTypeID(ref
);
376 if (bitSizeType
== CFStringGetTypeID())
377 keySizeInBits
= ConvertCFStringToInteger((CFStringRef
) ref
);
378 else if (bitSizeType
== CFNumberGetTypeID())
379 CFNumberGetValue((CFNumberRef
) ref
, kCFNumberSInt32Type
, &keySizeInBits
);
380 else return errSecParam
;
383 switch (algorithms
) {
384 case CSSM_ALGID_ECDSA
:
385 if(keySizeInBits
== kSecDefaultKeySize
) keySizeInBits
= kSecp256r1
;
386 if(keySizeInBits
== kSecp192r1
|| keySizeInBits
== kSecp256r1
|| keySizeInBits
== kSecp384r1
|| keySizeInBits
== kSecp521r1
) return noErr
;
389 if(keySizeInBits
% 8) return errSecParam
;
390 if(keySizeInBits
== kSecDefaultKeySize
) keySizeInBits
= 2048;
391 if(keySizeInBits
>= kSecRSAMin
&& keySizeInBits
<= kSecRSAMax
) return noErr
;
394 if(keySizeInBits
== kSecDefaultKeySize
) keySizeInBits
= kSecAES128
;
395 if(keySizeInBits
== kSecAES128
|| keySizeInBits
== kSecAES192
|| keySizeInBits
== kSecAES256
) return noErr
;
397 case CSSM_ALGID_3DES
:
398 if(keySizeInBits
== kSecDefaultKeySize
) keySizeInBits
= kSec3DES192
;
399 if(keySizeInBits
== kSec3DES192
) return noErr
;
418 struct ParameterAttribute
420 const CFTypeRef
*name
;
426 static ParameterAttribute gAttributes
[] =
433 &kSecAttrIsPermanent
,
437 &kSecAttrApplicationTag
,
441 &kSecAttrEffectiveKeySize
,
470 const int kNumberOfAttributes
= sizeof(gAttributes
) / sizeof(ParameterAttribute
);
472 static OSStatus
ScanDictionaryForParameters(CFDictionaryRef parameters
, void* attributePointers
[])
475 for (i
= 0; i
< kNumberOfAttributes
; ++i
)
477 // see if the corresponding tag exists in the dictionary
478 CFTypeRef value
= CFDictionaryGetValue(parameters
, *(gAttributes
[i
].name
));
481 switch (gAttributes
[i
].type
)
484 // just return the value
485 *(CFTypeRef
*) attributePointers
[i
] = value
;
490 CFBooleanRef bRef
= (CFBooleanRef
) value
;
491 *(bool*) attributePointers
[i
] = CFBooleanGetValue(bRef
);
497 CFNumberRef nRef
= (CFNumberRef
) value
;
498 CFNumberGetValue(nRef
, kCFNumberSInt32Type
, attributePointers
[i
]);
510 static OSStatus
GetKeyParameters(CFDictionaryRef parameters
, int keySize
, bool isPublic
, CSSM_KEYUSE
&keyUse
, uint32
&attrs
, CFTypeRef
&labelRef
, CFDataRef
&applicationTagRef
)
512 // establish default values
514 bool isPermanent
= false;
515 applicationTagRef
= NULL
;
516 CFTypeRef effectiveKeySize
= NULL
;
517 bool canDecrypt
= isPublic
? false : true;
518 bool canEncrypt
= !canDecrypt
;
519 bool canDerive
= true;
520 bool canSign
= isPublic
? false : true;
521 bool canVerify
= !canSign
;
522 bool canUnwrap
= isPublic
? false : true;
523 attrs
= CSSM_KEYATTR_EXTRACTABLE
;
526 void* attributePointers
[] = {&labelRef
, &isPermanent
, &applicationTagRef
, &effectiveKeySize
, &canEncrypt
, &canDecrypt
,
527 &canDerive
, &canSign
, &canVerify
, &canUnwrap
};
529 // look for modifiers in the general dictionary
530 OSStatus result
= ScanDictionaryForParameters(parameters
, attributePointers
);
536 // see if we have anything which modifies the defaults
540 key
= kSecPublicKeyAttrs
;
544 key
= kSecPrivateKeyAttrs
;
547 CFTypeRef dType
= CFDictionaryGetValue(parameters
, key
);
550 // this had better be a dictionary
551 if (CFGetTypeID(dType
) != CFDictionaryGetTypeID())
556 // pull any additional parameters out of this dictionary
557 result
= ScanDictionaryForParameters(parameters
, attributePointers
);
564 // figure out the key usage
568 keyUse
|= CSSM_KEYUSE_DECRYPT
;
573 keyUse
|= CSSM_KEYUSE_ENCRYPT
;
578 keyUse
|= CSSM_KEYUSE_DERIVE
;
583 keyUse
|= CSSM_KEYUSE_SIGN
;
588 keyUse
|= CSSM_KEYUSE_VERIFY
;
593 keyUse
|= CSSM_KEYUSE_UNWRAP
;
596 // public key is always extractable;
597 // private key is extractable by default unless explicitly set to false
598 CFTypeRef value
= NULL
;
599 if (!isPublic
&& CFDictionaryGetValueIfPresent(parameters
, kSecAttrIsExtractable
, (const void **)&value
) && value
)
601 Boolean keyIsExtractable
= CFEqual(kCFBooleanTrue
, value
);
602 if (!keyIsExtractable
)
606 attrs
|= CSSM_KEYATTR_PERMANENT
;
613 static OSStatus
MakeKeyGenParametersFromDictionary(CFDictionaryRef parameters
,
614 CSSM_ALGORITHMS
&algorithms
,
615 uint32
&keySizeInBits
,
616 CSSM_KEYUSE
&publicKeyUse
,
617 uint32
&publicKeyAttr
,
618 CFTypeRef
&publicKeyLabelRef
,
619 CFDataRef
&publicKeyAttributeTagRef
,
620 CSSM_KEYUSE
&privateKeyUse
,
621 uint32
&privateKeyAttr
,
622 CFTypeRef
&privateKeyLabelRef
,
623 CFDataRef
&privateKeyAttributeTagRef
,
624 SecAccessRef
&initialAccess
)
628 result
= CheckAlgorithmType(parameters
, algorithms
);
634 result
= GetKeySize(parameters
, algorithms
, keySizeInBits
);
640 result
= GetKeyParameters(parameters
, keySizeInBits
, false, privateKeyUse
, privateKeyAttr
, publicKeyLabelRef
, publicKeyAttributeTagRef
);
646 result
= GetKeyParameters(parameters
, keySizeInBits
, true, publicKeyUse
, publicKeyAttr
, privateKeyLabelRef
, privateKeyAttributeTagRef
);
652 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrAccess
, (const void **)&initialAccess
))
654 initialAccess
= NULL
;
656 else if (SecAccessGetTypeID() != CFGetTypeID(initialAccess
))
666 static OSStatus
SetKeyLabelAndTag(SecKeyRef keyRef
, CFTypeRef label
, CFDataRef tag
)
679 if (numToModify
== 0)
684 SecKeychainAttributeList attrList
;
685 SecKeychainAttribute attributes
[numToModify
];
691 if (CFStringGetTypeID() == CFGetTypeID(label
)) {
692 CFStringRef label_string
= static_cast<CFStringRef
>(label
);
693 attributes
[i
].tag
= kSecKeyPrintName
;
694 attributes
[i
].data
= (void*) CFStringGetCStringPtr(label_string
, kCFStringEncodingUTF8
);
695 if (NULL
== attributes
[i
].data
) {
696 CFIndex buffer_length
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(label_string
), kCFStringEncodingUTF8
);
697 attributes
[i
].data
= alloca((size_t)buffer_length
);
698 if (NULL
== attributes
[i
].data
) {
699 UnixError::throwMe(ENOMEM
);
701 if (!CFStringGetCString(label_string
, static_cast<char *>(attributes
[i
].data
), buffer_length
, kCFStringEncodingUTF8
)) {
702 MacOSError::throwMe(paramErr
);
705 attributes
[i
].length
= strlen(static_cast<char *>(attributes
[i
].data
));
706 } else if (CFDataGetTypeID() == CFGetTypeID(label
)) {
707 // 10.6 bug compatibility
708 CFDataRef label_data
= static_cast<CFDataRef
>(label
);
709 attributes
[i
].tag
= kSecKeyLabel
;
710 attributes
[i
].data
= (void*) CFDataGetBytePtr(label_data
);
711 attributes
[i
].length
= CFDataGetLength(label_data
);
713 MacOSError::throwMe(paramErr
);
720 attributes
[i
].tag
= kSecKeyApplicationTag
;
721 attributes
[i
].data
= (void*) CFDataGetBytePtr(tag
);
722 attributes
[i
].length
= CFDataGetLength(tag
);
726 attrList
.count
= numToModify
;
727 attrList
.attr
= attributes
;
729 return SecKeychainItemModifyAttributesAndData((SecKeychainItemRef
) keyRef
, &attrList
, 0, NULL
);
735 /* Generate a private/public keypair. */
738 CFDictionaryRef parameters
,
739 SecKeyRef
*publicKey
,
740 SecKeyRef
*privateKey
)
744 Required(parameters
);
746 Required(privateKey
);
748 CSSM_ALGORITHMS algorithms
;
749 uint32 keySizeInBits
;
750 CSSM_KEYUSE publicKeyUse
;
751 uint32 publicKeyAttr
;
752 CFTypeRef publicKeyLabelRef
;
753 CFDataRef publicKeyAttributeTagRef
;
754 CSSM_KEYUSE privateKeyUse
;
755 uint32 privateKeyAttr
;
756 CFTypeRef privateKeyLabelRef
;
757 CFDataRef privateKeyAttributeTagRef
;
758 SecAccessRef initialAccess
;
759 SecKeychainRef keychain
;
761 OSStatus result
= MakeKeyGenParametersFromDictionary(parameters
, algorithms
, keySizeInBits
, publicKeyUse
, publicKeyAttr
, publicKeyLabelRef
,
762 publicKeyAttributeTagRef
, privateKeyUse
, privateKeyAttr
, privateKeyLabelRef
, privateKeyAttributeTagRef
,
770 // verify keychain parameter
772 if (!CFDictionaryGetValueIfPresent(parameters
, kSecUseKeychain
, (const void **)&keychain
))
774 else if (SecKeychainGetTypeID() != CFGetTypeID(keychain
))
777 // do the key generation
778 result
= SecKeyCreatePair(keychain
, algorithms
, keySizeInBits
, 0, publicKeyUse
, publicKeyAttr
, privateKeyUse
, privateKeyAttr
, initialAccess
, publicKey
, privateKey
);
784 // set the label and print attributes on the keys
785 SetKeyLabelAndTag(*publicKey
, publicKeyLabelRef
, publicKeyAttributeTagRef
);
786 SetKeyLabelAndTag(*privateKey
, privateKeyLabelRef
, privateKeyAttributeTagRef
);
797 const uint8_t *dataToSign
,
798 size_t dataToSignLen
,
805 SecPointer
<KeyItem
> keyItem(KeyItem::required(key
));
808 dataInput
.Data
= (uint8_t*) dataToSign
;
809 dataInput
.Length
= dataToSignLen
;
813 output
.Length
= *sigLen
;
815 const AccessCredentials
* credentials
= keyItem
->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN
, kSecCredentialTypeDefault
);
817 keyItem
->RawSign(padding
, dataInput
, credentials
, output
);
818 *sigLen
= output
.Length
;
828 const uint8_t *signedData
,
829 size_t signedDataLen
,
837 SecPointer
<KeyItem
> keyItem(KeyItem::required(key
));
840 dataInput
.Data
= (uint8_t*) signedData
;
841 dataInput
.Length
= signedDataLen
;
844 signature
.Data
= (uint8_t*) sig
;
845 signature
.Length
= sigLen
;
847 const AccessCredentials
* credentials
= keyItem
->getCredentials(CSSM_ACL_AUTHORIZATION_ANY
, kSecCredentialTypeDefault
);
849 keyItem
->RawVerify(padding
, dataInput
, credentials
, signature
);
859 const uint8_t *plainText
,
862 size_t *cipherTextLen
)
866 SecPointer
<KeyItem
> keyItem(KeyItem::required(key
));
867 CSSM_DATA inData
, outData
;
868 inData
.Data
= (uint8
*) plainText
;
869 inData
.Length
= plainTextLen
;
870 outData
.Data
= cipherText
;
871 outData
.Length
= *cipherTextLen
;
873 const AccessCredentials
* credentials
= keyItem
->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT
, kSecCredentialTypeDefault
);
875 keyItem
->Encrypt(padding
, inData
, credentials
, outData
);
876 *cipherTextLen
= outData
.Length
;
884 SecKeyRef key
, /* Private key */
885 SecPadding padding
, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */
886 const uint8_t *cipherText
,
887 size_t cipherTextLen
, /* length of cipherText */
889 size_t *plainTextLen
) /* IN/OUT */
893 SecPointer
<KeyItem
> keyItem(KeyItem::required(key
));
894 CSSM_DATA inData
, outData
;
895 inData
.Data
= (uint8
*) cipherText
;
896 inData
.Length
= cipherTextLen
;
897 outData
.Data
= plainText
;
898 outData
.Length
= *plainTextLen
;
900 const AccessCredentials
* credentials
= keyItem
->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT
, kSecCredentialTypeDefault
);
902 keyItem
->Decrypt(padding
, inData
, credentials
, outData
);
903 *plainTextLen
= outData
.Length
;
910 SecKeyGetBlockSize(SecKeyRef key
)
912 size_t blockSize
= 0;
913 OSStatus __secapiresult
;
915 CSSM_KEY cssmKey
= KeyItem::required(key
)->key();
916 switch(cssmKey
.KeyHeader
.AlgorithmId
)
920 blockSize
= cssmKey
.KeyHeader
.LogicalKeySizeInBits
/ 8;
922 case CSSM_ALGID_ECDSA
:
924 /* Block size is up to 9 bytes of DER encoding for sequence of 2 integers,
925 * plus both coordinates for the point used */
926 #define ECDSA_KEY_SIZE_IN_BYTES(bits) (((bits) + 7) / 8)
927 #define ECDSA_MAX_COORD_SIZE_IN_BYTES(n) (ECDSA_KEY_SIZE_IN_BYTES(n) + 1)
928 size_t coordSize
= ECDSA_MAX_COORD_SIZE_IN_BYTES(cssmKey
.KeyHeader
.LogicalKeySizeInBits
);
929 assert(coordSize
< 256); /* size must fit in a byte for DER */
930 size_t coordDERLen
= (coordSize
> 127) ? 2 : 1;
931 size_t coordLen
= 1 + coordDERLen
+ coordSize
;
933 size_t pointSize
= 2 * coordLen
;
934 assert(pointSize
< 256); /* size must fit in a byte for DER */
935 size_t pointDERLen
= (pointSize
> 127) ? 2 : 1;
936 size_t pointLen
= 1 + pointDERLen
+ pointSize
;
938 blockSize
= pointLen
;
942 blockSize
= 16; /* all AES keys use 128-bit blocks */
945 case CSSM_ALGID_3DES_3KEY
:
946 blockSize
= 8; /* all DES keys use 64-bit blocks */
949 assert(0); /* some other key algorithm */
950 blockSize
= 16; /* FIXME: revisit this */
953 __secapiresult
=noErr
;
955 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
956 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
957 catch (const std::bad_alloc
&) { __secapiresult
=memFullErr
; }
958 catch (...) { __secapiresult
=internalComponentErr
; }
968 utilGetStringFromCFDict(CFDictionaryRef parameters
, CFTypeRef key
, CFTypeRef defaultValue
)
970 CFTypeRef value
= CFDictionaryGetValue(parameters
, key
);
971 if (value
!= NULL
) return value
;
976 utilGetNumberFromCFDict(CFDictionaryRef parameters
, CFTypeRef key
, uint32_t defaultValue
)
978 uint32_t integerValue
;
979 CFTypeRef value
= CFDictionaryGetValue(parameters
, key
);
981 CFNumberRef nRef
= (CFNumberRef
) value
;
982 CFNumberGetValue(nRef
, kCFNumberSInt32Type
, &integerValue
);
989 utilGetMaskValFromCFDict(CFDictionaryRef parameters
, CFTypeRef key
, uint32_t maskValue
)
991 CFTypeRef value
= CFDictionaryGetValue(parameters
, key
);
993 CFBooleanRef bRef
= (CFBooleanRef
) value
;
994 if(CFBooleanGetValue(bRef
)) return maskValue
;
1000 utilGetKeyParametersFromCFDict(CFDictionaryRef parameters
, CSSM_ALGORITHMS
*algorithm
, uint32
*keySizeInBits
, CSSM_KEYUSE
*keyUsage
, CSSM_KEYCLASS
*keyClass
)
1002 CFTypeRef algorithmDictValue
= utilGetStringFromCFDict(parameters
, kSecAttrKeyType
, kSecAttrKeyTypeAES
);
1003 CFTypeRef keyClassDictValue
= utilGetStringFromCFDict(parameters
, kSecAttrKeyClass
, kSecAttrKeyClassSymmetric
);
1005 if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeAES
)) {
1006 *algorithm
= CSSM_ALGID_AES
;
1007 *keySizeInBits
= 128;
1008 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1009 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeDES
)) {
1010 *algorithm
= CSSM_ALGID_DES
;
1011 *keySizeInBits
= 128;
1012 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1013 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyType3DES
)) {
1014 *algorithm
= CSSM_ALGID_3DES_3KEY_EDE
;
1015 *keySizeInBits
= 128;
1016 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1017 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeRC4
)) {
1018 *algorithm
= CSSM_ALGID_RC4
;
1019 *keySizeInBits
= 128;
1020 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1021 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeRC2
)) {
1022 *algorithm
= CSSM_ALGID_RC2
;
1023 *keySizeInBits
= 128;
1024 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1025 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeCAST
)) {
1026 *algorithm
= CSSM_ALGID_CAST
;
1027 *keySizeInBits
= 128;
1028 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1029 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeRSA
)) {
1030 *algorithm
= CSSM_ALGID_RSA
;
1031 *keySizeInBits
= 128;
1032 *keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
1033 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeDSA
)) {
1034 *algorithm
= CSSM_ALGID_DSA
;
1035 *keySizeInBits
= 128;
1036 *keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
1037 } else if(CFEqual(algorithmDictValue
, kSecAttrKeyTypeECDSA
)) {
1038 *algorithm
= CSSM_ALGID_ECDSA
;
1039 *keySizeInBits
= 128;
1040 *keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
1042 *algorithm
= CSSM_ALGID_AES
;
1043 *keySizeInBits
= 128;
1044 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1047 if(CFEqual(keyClassDictValue
, kSecAttrKeyClassPublic
)) {
1048 *keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
1049 } else if(CFEqual(keyClassDictValue
, kSecAttrKeyClassPrivate
)) {
1050 *keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
1051 } else if(CFEqual(keyClassDictValue
, kSecAttrKeyClassSymmetric
)) {
1052 *keyClass
= CSSM_KEYCLASS_SESSION_KEY
;
1055 *keySizeInBits
= utilGetNumberFromCFDict(parameters
, kSecAttrKeySizeInBits
, *keySizeInBits
);
1056 *keyUsage
= utilGetMaskValFromCFDict(parameters
, kSecAttrCanEncrypt
, CSSM_KEYUSE_ENCRYPT
) |
1057 utilGetMaskValFromCFDict(parameters
, kSecAttrCanDecrypt
, CSSM_KEYUSE_DECRYPT
) |
1058 utilGetMaskValFromCFDict(parameters
, kSecAttrCanWrap
, CSSM_KEYUSE_WRAP
) |
1059 utilGetMaskValFromCFDict(parameters
, kSecAttrCanUnwrap
, CSSM_KEYUSE_UNWRAP
);
1062 if(*keyClass
== CSSM_KEYCLASS_PRIVATE_KEY
|| *keyClass
== CSSM_KEYCLASS_PUBLIC_KEY
) {
1063 *keyUsage
|= utilGetMaskValFromCFDict(parameters
, kSecAttrCanSign
, CSSM_KEYUSE_SIGN
) |
1064 utilGetMaskValFromCFDict(parameters
, kSecAttrCanVerify
, CSSM_KEYUSE_VERIFY
);
1067 if(*keyUsage
== 0) {
1068 switch (*keyClass
) {
1069 case CSSM_KEYCLASS_PRIVATE_KEY
:
1070 *keyUsage
= CSSM_KEYUSE_DECRYPT
| CSSM_KEYUSE_UNWRAP
| CSSM_KEYUSE_SIGN
;
1072 case CSSM_KEYCLASS_PUBLIC_KEY
:
1073 *keyUsage
= CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_VERIFY
| CSSM_KEYUSE_WRAP
;
1076 *keyUsage
= CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_DECRYPT
| CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP
| CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_VERIFY
;
1083 utilCopyDefaultKeyLabel(void)
1085 // generate a default label from the current date
1086 CFDateRef dateNow
= CFDateCreate(kCFAllocatorDefault
, CFAbsoluteTimeGetCurrent());
1087 CFStringRef defaultLabel
= CFCopyDescription(dateNow
);
1090 return defaultLabel
;
1094 SecKeyGenerateSymmetric(CFDictionaryRef parameters
, CFErrorRef
*error
)
1096 OSStatus result
= paramErr
; // default result for an early exit
1097 SecKeyRef key
= NULL
;
1098 SecKeychainRef keychain
= NULL
;
1099 SecAccessRef access
;
1101 CFStringRef appLabel
;
1103 CFStringRef dateLabel
= NULL
;
1105 CSSM_ALGORITHMS algorithm
;
1106 uint32 keySizeInBits
;
1107 CSSM_KEYUSE keyUsage
;
1108 uint32 keyAttr
= CSSM_KEYATTR_RETURN_DEFAULT
;
1109 CSSM_KEYCLASS keyClass
;
1111 Boolean isPermanent
;
1112 Boolean isExtractable
;
1114 // verify keychain parameter
1115 if (!CFDictionaryGetValueIfPresent(parameters
, kSecUseKeychain
, (const void **)&keychain
))
1117 else if (SecKeychainGetTypeID() != CFGetTypeID(keychain
)) {
1124 // verify permanent parameter
1125 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrIsPermanent
, (const void **)&value
))
1126 isPermanent
= false;
1127 else if (!value
|| (CFBooleanGetTypeID() != CFGetTypeID(value
)))
1130 isPermanent
= CFEqual(kCFBooleanTrue
, value
);
1132 if (keychain
== NULL
) {
1133 // no keychain was specified, so use the default keychain
1134 result
= SecKeychainCopyDefault(&keychain
);
1136 keyAttr
|= CSSM_KEYATTR_PERMANENT
;
1139 // verify extractable parameter
1140 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrIsExtractable
, (const void **)&value
))
1141 isExtractable
= true; // default to extractable if value not specified
1142 else if (!value
|| (CFBooleanGetTypeID() != CFGetTypeID(value
)))
1145 isExtractable
= CFEqual(kCFBooleanTrue
, value
);
1147 keyAttr
|= CSSM_KEYATTR_EXTRACTABLE
;
1149 // verify access parameter
1150 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrAccess
, (const void **)&access
))
1152 else if (SecAccessGetTypeID() != CFGetTypeID(access
))
1155 // verify label parameter
1156 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrLabel
, (const void **)&label
))
1157 label
= (dateLabel
= utilCopyDefaultKeyLabel()); // no label provided, so use default
1158 else if (CFStringGetTypeID() != CFGetTypeID(label
))
1161 // verify application label parameter
1162 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrApplicationLabel
, (const void **)&appLabel
))
1163 appLabel
= (dateLabel
) ? dateLabel
: (dateLabel
= utilCopyDefaultKeyLabel());
1164 else if (CFStringGetTypeID() != CFGetTypeID(appLabel
))
1167 // verify application tag parameter
1168 if (!CFDictionaryGetValueIfPresent(parameters
, kSecAttrApplicationTag
, (const void **)&appTag
))
1170 else if (CFStringGetTypeID() != CFGetTypeID(appTag
))
1173 utilGetKeyParametersFromCFDict(parameters
, &algorithm
, &keySizeInBits
, &keyUsage
, &keyClass
);
1176 // the generated key will not be stored in any keychain
1177 result
= SecKeyGenerate(keychain
, algorithm
, keySizeInBits
, 0, keyUsage
, keyAttr
, access
, &key
);
1180 // we can set the label attributes on the generated key if it's a keychain item
1181 size_t labelBufLen
= (label
) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label
), kCFStringEncodingUTF8
) + 1 : 0;
1182 char *labelBuf
= (char *)malloc(labelBufLen
);
1183 size_t appLabelBufLen
= (appLabel
) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel
), kCFStringEncodingUTF8
) + 1 : 0;
1184 char *appLabelBuf
= (char *)malloc(appLabelBufLen
);
1185 size_t appTagBufLen
= (appTag
) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag
), kCFStringEncodingUTF8
) + 1 : 0;
1186 char *appTagBuf
= (char *)malloc(appTagBufLen
);
1188 if (label
&& !CFStringGetCString(label
, labelBuf
, labelBufLen
-1, kCFStringEncodingUTF8
))
1190 if (appLabel
&& !CFStringGetCString(appLabel
, appLabelBuf
, appLabelBufLen
-1, kCFStringEncodingUTF8
))
1192 if (appTag
&& !CFStringGetCString(appTag
, appTagBuf
, appTagBufLen
-1, kCFStringEncodingUTF8
))
1195 SecKeychainAttribute attrs
[] = {
1196 { kSecKeyPrintName
, strlen(labelBuf
), (char *)labelBuf
},
1197 { kSecKeyLabel
, strlen(appLabelBuf
), (char *)appLabelBuf
},
1198 { kSecKeyApplicationTag
, strlen(appTagBuf
), (char *)appTagBuf
} };
1199 SecKeychainAttributeList attributes
= { sizeof(attrs
) / sizeof(attrs
[0]), attrs
};
1200 if (!appTag
) --attributes
.count
;
1202 result
= SecKeyGenerateWithAttributes(&attributes
,
1203 keychain
, algorithm
, keySizeInBits
, 0,
1204 keyUsage
, keyAttr
, access
, &key
);
1212 if (result
&& error
) {
1213 *error
= CFErrorCreate(kCFAllocatorDefault
, kCFErrorDomainOSStatus
, result
, NULL
);
1216 CFRelease(dateLabel
);
1218 CFRelease(keychain
);
1226 SecKeyCreateFromData(CFDictionaryRef parameters
, CFDataRef keyData
, CFErrorRef
*error
)
1228 CSSM_ALGORITHMS algorithm
;
1229 uint32 keySizeInBits
;
1230 CSSM_KEYUSE keyUsage
;
1231 CSSM_KEYCLASS keyClass
;
1234 utilGetKeyParametersFromCFDict(parameters
, &algorithm
, &keySizeInBits
, &keyUsage
, &keyClass
);
1236 CSSM_CSP_HANDLE cspHandle
= cuCspStartup(CSSM_FALSE
); // TRUE => CSP, FALSE => CSPDL
1238 SecKeyImportExportParameters iparam
;
1239 memset(&iparam
, 0, sizeof(iparam
));
1240 iparam
.keyUsage
= keyUsage
;
1242 SecExternalItemType itype
;
1244 case CSSM_KEYCLASS_PRIVATE_KEY
:
1245 itype
= kSecItemTypePrivateKey
;
1247 case CSSM_KEYCLASS_PUBLIC_KEY
:
1248 itype
= kSecItemTypePublicKey
;
1250 case CSSM_KEYCLASS_SESSION_KEY
:
1251 itype
= kSecItemTypeSessionKey
;
1254 itype
= kSecItemTypeUnknown
;
1258 CFMutableArrayRef ka
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1259 // NOTE: if we had a way to specify values other then kSecFormatUnknown we might be more useful.
1260 crtn
= impExpImportRawKey(keyData
, kSecFormatUnknown
, itype
, algorithm
, NULL
, cspHandle
, 0, NULL
, NULL
, ka
);
1261 if (crtn
== CSSM_OK
&& CFArrayGetCount((CFArrayRef
)ka
)) {
1262 SecKeyRef sk
= (SecKeyRef
)CFArrayGetValueAtIndex((CFArrayRef
)ka
, 0);
1268 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, crtn
? crtn
: CSSM_ERRCODE_INTERNAL_ERROR
, NULL
);
1276 SecKeyGeneratePairAsync(CFDictionaryRef parametersWhichMightBeMutiable
, dispatch_queue_t deliveryQueue
,
1277 SecKeyGeneratePairBlock result
)
1279 CFDictionaryRef parameters
= CFDictionaryCreateCopy(NULL
, parametersWhichMightBeMutiable
);
1280 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1281 SecKeyRef publicKey
= NULL
;
1282 SecKeyRef privateKey
= NULL
;
1283 OSStatus status
= SecKeyGeneratePair(parameters
, &publicKey
, &privateKey
);
1284 dispatch_async(deliveryQueue
, ^{
1285 CFErrorRef error
= NULL
;
1286 if (noErr
!= status
) {
1287 error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, status
, NULL
);
1289 result(publicKey
, privateKey
, error
);
1294 CFRelease(publicKey
);
1297 CFRelease(privateKey
);
1299 CFRelease(parameters
);
1305 SecKeyDeriveFromPassword(CFStringRef password
, CFDictionaryRef parameters
, CFErrorRef
*error
)
1307 char *thePassword
= NULL
;
1308 CFIndex passwordLen
;
1309 uint8_t *salt
= NULL
;
1311 CCPBKDFAlgorithm algorithm
;
1313 uint8_t *derivedKey
= NULL
;
1314 size_t derivedKeyLen
;
1315 CFDataRef saltDictValue
, algorithmDictValue
;
1317 /* Pick Values from parameters */
1319 if((saltDictValue
= (CFDataRef
) CFDictionaryGetValue(parameters
, kSecAttrSalt
)) == NULL
) {
1320 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecMissingAlgorithmParms
, NULL
);
1324 derivedKeyLen
= utilGetNumberFromCFDict(parameters
, kSecAttrKeySizeInBits
, 128);
1325 // This value come in bits but the rest of the code treats it as bytes
1328 algorithmDictValue
= (CFDataRef
) utilGetStringFromCFDict(parameters
, kSecAttrPRF
, kSecAttrPRFHmacAlgSHA256
);
1330 rounds
= utilGetNumberFromCFDict(parameters
, kSecAttrRounds
, 0);
1332 /* Convert any remaining parameters and get the password bytes */
1334 saltLen
= CFDataGetLength(saltDictValue
);
1335 if((salt
= (uint8_t *) malloc(saltLen
)) == NULL
) {
1336 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecAllocate
, NULL
);
1340 CFDataGetBytes(saltDictValue
, CFRangeMake(0, saltLen
), (UInt8
*) salt
);
1342 passwordLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(password
), kCFStringEncodingUTF8
) + 1;
1343 if((thePassword
= (char *) malloc(passwordLen
)) == NULL
) {
1345 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecAllocate
, NULL
);
1348 CFStringGetBytes(password
, CFRangeMake(0, CFStringGetLength(password
)), kCFStringEncodingUTF8
, '?', FALSE
, (UInt8
*)thePassword
, passwordLen
, &passwordLen
);
1350 if((derivedKey
= (uint8_t *) malloc(derivedKeyLen
)) == NULL
) {
1352 bzero(thePassword
, strlen(thePassword
));
1354 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecAllocate
, NULL
);
1359 if(algorithmDictValue
== NULL
) {
1360 algorithm
= kCCPRFHmacAlgSHA1
; /* default */
1361 } else if(CFEqual(algorithmDictValue
, kSecAttrPRFHmacAlgSHA1
)) {
1362 algorithm
= kCCPRFHmacAlgSHA1
;
1363 } else if(CFEqual(algorithmDictValue
, kSecAttrPRFHmacAlgSHA224
)) {
1364 algorithm
= kCCPRFHmacAlgSHA224
;
1365 } else if(CFEqual(algorithmDictValue
, kSecAttrPRFHmacAlgSHA256
)) {
1366 algorithm
= kCCPRFHmacAlgSHA256
;
1367 } else if(CFEqual(algorithmDictValue
, kSecAttrPRFHmacAlgSHA384
)) {
1368 algorithm
= kCCPRFHmacAlgSHA384
;
1369 } else if(CFEqual(algorithmDictValue
, kSecAttrPRFHmacAlgSHA512
)) {
1370 algorithm
= kCCPRFHmacAlgSHA512
;
1374 rounds
= 33333; // we need to pass back a consistent value since there's no way to record the round count.
1378 if(CCKeyDerivationPBKDF(kCCPBKDF2
, thePassword
, passwordLen
, salt
, saltLen
, algorithm
, rounds
, derivedKey
, derivedKeyLen
)) {
1379 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecInternalError
, NULL
);
1384 bzero(thePassword
, strlen(thePassword
));
1387 CFDataRef keyData
= CFDataCreate(NULL
, derivedKey
, derivedKeyLen
);
1388 bzero(derivedKey
, derivedKeyLen
);
1391 SecKeyRef retval
= SecKeyCreateFromData(parameters
, keyData
, error
);
1397 SecKeyWrapSymmetric(SecKeyRef keyToWrap
, SecKeyRef wrappingKey
, CFDictionaryRef parameters
, CFErrorRef
*error
)
1399 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecUnimplemented
, NULL
);
1404 SecKeyUnwrapSymmetric(CFDataRef
*keyToUnwrap
, SecKeyRef unwrappingKey
, CFDictionaryRef parameters
, CFErrorRef
*error
)
1406 *error
= CFErrorCreate(NULL
, kCFErrorDomainOSStatus
, errSecUnimplemented
, NULL
);
1411 /* iOS SecKey shim functions */
1413 #define MAX_DIGEST_LEN (CC_SHA512_DIGEST_LENGTH)
1415 /* Currently length of SHA512 oid + 1 */
1416 #define MAX_OID_LEN (10)
1418 #define DER_MAX_DIGEST_INFO_LEN (10 + MAX_DIGEST_LEN + MAX_OID_LEN)
1420 /* Encode the digestInfo header into digestInfo and return the offset from
1421 digestInfo at which to put the actual digest. Returns 0 if digestInfo
1422 won't fit within digestInfoLength bytes.
1426 0x06, oid.Len, oid.Data,
1431 static size_t DEREncodeDigestInfoPrefix(const SecAsn1Oid
*oid
,
1432 size_t digestLength
,
1433 uint8_t *digestInfo
,
1434 size_t digestInfoLength
)
1436 size_t algIdLen
= oid
->Length
+ 4;
1437 size_t topLen
= algIdLen
+ digestLength
+ 4;
1438 size_t totalLen
= topLen
+ 2;
1440 if (totalLen
> digestInfoLength
) {
1445 digestInfo
[ix
++] = (SEC_ASN1_SEQUENCE
| SEC_ASN1_CONSTRUCTED
);
1446 digestInfo
[ix
++] = topLen
;
1447 digestInfo
[ix
++] = (SEC_ASN1_SEQUENCE
| SEC_ASN1_CONSTRUCTED
);
1448 digestInfo
[ix
++] = algIdLen
;
1449 digestInfo
[ix
++] = SEC_ASN1_OBJECT_ID
;
1450 digestInfo
[ix
++] = oid
->Length
;
1451 memcpy(&digestInfo
[ix
], oid
->Data
, oid
->Length
);
1453 digestInfo
[ix
++] = SEC_ASN1_NULL
;
1454 digestInfo
[ix
++] = 0;
1455 digestInfo
[ix
++] = SEC_ASN1_OCTET_STRING
;
1456 digestInfo
[ix
++] = digestLength
;
1461 static OSStatus
SecKeyGetDigestInfo(SecKeyRef key
, const SecAsn1AlgId
*algId
,
1462 const uint8_t *data
, size_t dataLen
, bool digestData
,
1463 uint8_t *digestInfo
, size_t *digestInfoLen
/* IN/OUT */)
1465 unsigned char *(*digestFcn
)(const void *, CC_LONG
, unsigned char *);
1466 CFIndex keyAlgID
= kSecNullAlgorithmID
;
1467 const SecAsn1Oid
*digestOid
;
1471 /* Since these oids all have the same prefix, use switch. */
1472 if ((algId
->algorithm
.Length
== CSSMOID_RSA
.Length
) &&
1473 !memcmp(algId
->algorithm
.Data
, CSSMOID_RSA
.Data
,
1474 algId
->algorithm
.Length
- 1)) {
1475 keyAlgID
= kSecRSAAlgorithmID
;
1476 switch (algId
->algorithm
.Data
[algId
->algorithm
.Length
- 1]) {
1478 case 2: /* oidMD2WithRSA */
1480 digestLen
= CC_MD2_DIGEST_LENGTH
;
1481 digestOid
= &CSSMOID_MD2
;
1483 case 3: /* oidMD4WithRSA */
1485 digestLen
= CC_MD4_DIGEST_LENGTH
;
1486 digestOid
= &CSSMOID_MD4
;
1488 case 4: /* oidMD5WithRSA */
1490 digestLen
= CC_MD5_DIGEST_LENGTH
;
1491 digestOid
= &CSSMOID_MD5
;
1494 case 5: /* oidSHA1WithRSA */
1495 digestFcn
= CC_SHA1
;
1496 digestLen
= CC_SHA1_DIGEST_LENGTH
;
1497 digestOid
= &CSSMOID_SHA1
;
1499 case 11: /* oidSHA256WithRSA */
1500 digestFcn
= CC_SHA256
;
1501 digestLen
= CC_SHA256_DIGEST_LENGTH
;
1502 digestOid
= &CSSMOID_SHA256
;
1504 case 12: /* oidSHA384WithRSA */
1506 digestFcn
= CC_SHA384
;
1507 digestLen
= CC_SHA384_DIGEST_LENGTH
;
1508 digestOid
= &CSSMOID_SHA384
;
1510 case 13: /* oidSHA512WithRSA */
1511 digestFcn
= CC_SHA512
;
1512 digestLen
= CC_SHA512_DIGEST_LENGTH
;
1513 digestOid
= &CSSMOID_SHA512
;
1515 case 14: /* oidSHA224WithRSA */
1516 digestFcn
= CC_SHA224
;
1517 digestLen
= CC_SHA224_DIGEST_LENGTH
;
1518 digestOid
= &CSSMOID_SHA224
;
1521 secdebug("key", "unsupported rsa signature algorithm");
1522 return errSecUnsupportedAlgorithm
;
1524 } else if ((algId
->algorithm
.Length
== CSSMOID_ECDSA_WithSHA224
.Length
) &&
1525 !memcmp(algId
->algorithm
.Data
, CSSMOID_ECDSA_WithSHA224
.Data
,
1526 algId
->algorithm
.Length
- 1)) {
1527 keyAlgID
= kSecECDSAAlgorithmID
;
1528 switch (algId
->algorithm
.Data
[algId
->algorithm
.Length
- 1]) {
1529 case 1: /* oidSHA224WithECDSA */
1530 digestFcn
= CC_SHA224
;
1531 digestLen
= CC_SHA224_DIGEST_LENGTH
;
1533 case 2: /* oidSHA256WithECDSA */
1534 digestFcn
= CC_SHA256
;
1535 digestLen
= CC_SHA256_DIGEST_LENGTH
;
1537 case 3: /* oidSHA384WithECDSA */
1539 digestFcn
= CC_SHA384
;
1540 digestLen
= CC_SHA384_DIGEST_LENGTH
;
1542 case 4: /* oidSHA512WithECDSA */
1543 digestFcn
= CC_SHA512
;
1544 digestLen
= CC_SHA512_DIGEST_LENGTH
;
1547 secdebug("key", "unsupported ecdsa signature algorithm");
1548 return errSecUnsupportedAlgorithm
;
1550 } else if (SecAsn1OidCompare(&algId
->algorithm
, &CSSMOID_ECDSA_WithSHA1
)) {
1551 keyAlgID
= kSecECDSAAlgorithmID
;
1552 digestFcn
= CC_SHA1
;
1553 digestLen
= CC_SHA1_DIGEST_LENGTH
;
1554 } else if (SecAsn1OidCompare(&algId
->algorithm
, &CSSMOID_SHA1
)) {
1555 digestFcn
= CC_SHA1
;
1556 digestLen
= CC_SHA1_DIGEST_LENGTH
;
1557 digestOid
= &CSSMOID_SHA1
;
1558 } else if ((algId
->algorithm
.Length
== CSSMOID_SHA224
.Length
) &&
1559 !memcmp(algId
->algorithm
.Data
, CSSMOID_SHA224
.Data
, algId
->algorithm
.Length
- 1))
1561 switch (algId
->algorithm
.Data
[algId
->algorithm
.Length
- 1]) {
1562 case 4: /* OID_SHA224 */
1563 digestFcn
= CC_SHA224
;
1564 digestLen
= CC_SHA224_DIGEST_LENGTH
;
1565 digestOid
= &CSSMOID_SHA224
;
1567 case 1: /* OID_SHA256 */
1568 digestFcn
= CC_SHA256
;
1569 digestLen
= CC_SHA256_DIGEST_LENGTH
;
1570 digestOid
= &CSSMOID_SHA256
;
1572 case 2: /* OID_SHA384 */
1574 digestFcn
= CC_SHA384
;
1575 digestLen
= CC_SHA384_DIGEST_LENGTH
;
1576 digestOid
= &CSSMOID_SHA384
;
1578 case 3: /* OID_SHA512 */
1579 digestFcn
= CC_SHA512
;
1580 digestLen
= CC_SHA512_DIGEST_LENGTH
;
1581 digestOid
= &CSSMOID_SHA512
;
1584 secdebug("key", "unsupported sha-2 signature algorithm");
1585 return errSecUnsupportedAlgorithm
;
1587 } else if (SecAsn1OidCompare(&algId
->algorithm
, &CSSMOID_MD5
)) {
1589 digestLen
= CC_MD5_DIGEST_LENGTH
;
1590 digestOid
= &CSSMOID_MD5
;
1592 secdebug("key", "unsupported digesting algorithm");
1593 return errSecUnsupportedAlgorithm
;
1596 /* check key is appropriate for signature (superfluous for digest only oid) */
1598 CFIndex supportedKeyAlgID
= kSecNullAlgorithmID
;
1599 #if TARGET_OS_EMBEDDED
1600 supportedKeyAlgID
= SecKeyGetAlgorithmID(key
);
1602 const CSSM_KEY
* temporaryKey
;
1603 SecKeyGetCSSMKey(key
, &temporaryKey
);
1604 CSSM_ALGORITHMS tempAlgorithm
= temporaryKey
->KeyHeader
.AlgorithmId
;
1605 if (CSSM_ALGID_RSA
== tempAlgorithm
) {
1606 supportedKeyAlgID
= kSecRSAAlgorithmID
;
1607 } else if (CSSM_ALGID_ECDSA
== tempAlgorithm
) {
1608 supportedKeyAlgID
= kSecECDSAAlgorithmID
;
1612 if (keyAlgID
== kSecNullAlgorithmID
) {
1613 keyAlgID
= supportedKeyAlgID
;
1615 else if (keyAlgID
!= supportedKeyAlgID
) {
1616 return errSecUnsupportedAlgorithm
;
1621 case kSecRSAAlgorithmID
:
1622 offset
= DEREncodeDigestInfoPrefix(digestOid
, digestLen
,
1623 digestInfo
, *digestInfoLen
);
1625 return errSecBufferTooSmall
;
1627 case kSecDSAAlgorithmID
:
1628 if (digestOid
!= &CSSMOID_SHA1
)
1629 return errSecUnsupportedAlgorithm
;
1631 case kSecECDSAAlgorithmID
:
1634 secdebug("key", "unsupported signature algorithm");
1635 return errSecUnsupportedAlgorithm
;
1639 if(dataLen
>UINT32_MAX
) /* Check for overflow with CC_LONG cast */
1641 digestFcn(data
, (CC_LONG
)dataLen
, &digestInfo
[offset
]);
1642 *digestInfoLen
= offset
+ digestLen
;
1644 if (dataLen
!= digestLen
)
1646 memcpy(&digestInfo
[offset
], data
, dataLen
);
1647 *digestInfoLen
= offset
+ dataLen
;
1653 OSStatus
SecKeyVerifyDigest(
1654 SecKeyRef key
, /* Private key */
1655 const SecAsn1AlgId
*algId
, /* algorithm oid/params */
1656 const uint8_t *digestData
, /* signature over this digest */
1657 size_t digestDataLen
, /* length of dataToDigest */
1658 const uint8_t *sig
, /* signature to verify */
1659 size_t sigLen
) /* length of sig */
1661 size_t digestInfoLength
= DER_MAX_DIGEST_INFO_LEN
;
1662 uint8_t digestInfo
[digestInfoLength
];
1665 status
= SecKeyGetDigestInfo(key
, algId
, digestData
, digestDataLen
, false /* data is digest */,
1666 digestInfo
, &digestInfoLength
);
1669 return SecKeyRawVerify(key
, kSecPaddingPKCS1
,
1670 digestInfo
, digestInfoLength
, sig
, sigLen
);
1673 OSStatus
SecKeySignDigest(
1674 SecKeyRef key
, /* Private key */
1675 const SecAsn1AlgId
*algId
, /* algorithm oid/params */
1676 const uint8_t *digestData
, /* signature over this digest */
1677 size_t digestDataLen
, /* length of digestData */
1678 uint8_t *sig
, /* signature, RETURNED */
1679 size_t *sigLen
) /* IN/OUT */
1681 size_t digestInfoLength
= DER_MAX_DIGEST_INFO_LEN
;
1682 uint8_t digestInfo
[digestInfoLength
];
1685 status
= SecKeyGetDigestInfo(key
, algId
, digestData
, digestDataLen
, false,
1686 digestInfo
, &digestInfoLength
);
1689 return SecKeyRawSign(key
, kSecPaddingPKCS1
,
1690 digestInfo
, digestInfoLength
, sig
, sigLen
);
1693 /* It's debatable whether this belongs here or in the ssl code since the
1694 curve values come from a tls related rfc4492. */
1695 SecECNamedCurve
SecECKeyGetNamedCurve(SecKeyRef key
)
1698 SecPointer
<KeyItem
> keyItem(KeyItem::required(key
));
1699 switch (keyItem
->key().header().LogicalKeySizeInBits
) {
1702 return kSecECCurveSecp192r1
;
1704 return kSecECCurveSecp224r1
;
1707 return kSecECCurveSecp256r1
;
1709 return kSecECCurveSecp384r1
;
1711 return kSecECCurveSecp521r1
;
1715 return kSecECCurveNone
;
1718 static inline CFDataRef
_CFDataCreateReferenceFromRange(CFAllocatorRef allocator
, CFDataRef sourceData
, CFRange range
)
1720 return CFDataCreateWithBytesNoCopy(allocator
,
1721 CFDataGetBytePtr(sourceData
) + range
.location
, range
.length
,
1725 static inline CFDataRef
_CFDataCreateCopyFromRange(CFAllocatorRef allocator
, CFDataRef sourceData
, CFRange range
)
1727 return CFDataCreate(allocator
, CFDataGetBytePtr(sourceData
) + range
.location
, range
.length
);
1730 static inline bool _CFDataEquals(CFDataRef left
, CFDataRef right
)
1732 return (left
!= NULL
) &&
1734 (CFDataGetLength(left
) == CFDataGetLength(right
)) &&
1735 (0 == memcmp(CFDataGetBytePtr(left
), CFDataGetBytePtr(right
), (size_t)CFDataGetLength(left
)));
1739 void secdump(const unsigned char *data
, unsigned long len
)
1748 sprintf(t
, "%04lx :", i
);
1751 sprintf(t
, " %02x", data
[i
]);
1755 syslog(LOG_NOTICE
, s
);
1760 syslog(LOG_NOTICE
, s
);
1764 OSStatus
_SecKeyCopyPublicBytes(SecKeyRef key
, CFDataRef
* publicBytes
)
1767 #if TARGET_OS_EMBEDDED
1768 keyAlgId
= SecKeyGetAlgorithmID(key
);
1770 keyAlgId
= SecKeyGetAlgorithmId(key
);
1772 if (kSecRSAAlgorithmID
== keyAlgId
) {
1773 return SecItemExport(key
, kSecFormatBSAFE
, 0, NULL
, publicBytes
);
1775 if (kSecECDSAAlgorithmID
== keyAlgId
) {
1776 OSStatus ecStatus
= errSecParam
;
1777 *publicBytes
= NULL
;
1778 uint8 headerBytes
[] = { 0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86,
1779 0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a,
1780 0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,
1782 uint8 altHdrBytes
[] = { 0x30,0x81,0x9b,0x30,0x10,0x06,0x07,0x2a,
1783 0x86,0x48,0xce,0x3d,0x02,0x01,0x06,0x05,
1784 0x2b,0x81,0x04,0x00,0x23,0x03,0x81,0x86,
1787 const size_t headerLen
= sizeof(headerBytes
);
1788 const size_t altHdrLen
= sizeof(altHdrBytes
);
1789 CFDataRef requiredPublicHeader
= NULL
;
1790 CFDataRef tempPublicData
= NULL
;
1791 CFDataRef publicDataHeader
= NULL
;
1792 CFDataRef headerlessPublicData
= NULL
;
1793 ecStatus
= SecItemExport(key
, kSecFormatOpenSSL
, 0, NULL
, &tempPublicData
);
1794 if(ecStatus
!= errSecSuccess
) {
1795 secdebug("key", "SecKeyCopyPublicBytes: SecItemExport error (%d) for ECDSA public key %p",
1796 ecStatus
, (uintptr_t)key
);
1799 requiredPublicHeader
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, headerBytes
, headerLen
, kCFAllocatorNull
);
1800 if (!requiredPublicHeader
) {
1801 secdebug("key", "SecKeyCopyPublicBytes: requiredPublicHeader is nil (1)");
1804 publicDataHeader
= _CFDataCreateReferenceFromRange(kCFAllocatorDefault
,
1805 tempPublicData
, CFRangeMake(0, headerLen
));
1806 if (!publicDataHeader
) {
1807 secdebug("key", "SecKeyCopyPublicBytes: publicDataHeader is nil (1)");
1810 headerlessPublicData
= _CFDataCreateCopyFromRange(kCFAllocatorDefault
,
1811 tempPublicData
, CFRangeMake(headerLen
, CFDataGetLength(tempPublicData
) - headerLen
));
1812 if (!headerlessPublicData
) {
1813 secdebug("key", "SecKeyCopyPublicBytes: headerlessPublicData is nil (1)");
1816 if(!_CFDataEquals(publicDataHeader
, requiredPublicHeader
)) {
1817 CFRelease(publicDataHeader
);
1818 CFRelease(headerlessPublicData
);
1819 CFRelease(requiredPublicHeader
);
1820 requiredPublicHeader
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, altHdrBytes
, altHdrLen
, kCFAllocatorNull
);
1821 if (!requiredPublicHeader
) {
1822 secdebug("key", "SecKeyCopyPublicBytes: requiredPublicHeader is nil (2)");
1825 publicDataHeader
= _CFDataCreateReferenceFromRange(kCFAllocatorDefault
,
1826 tempPublicData
, CFRangeMake(0, altHdrLen
));
1827 if (!publicDataHeader
) {
1828 secdebug("key", "SecKeyCopyPublicBytes: publicDataHeader is nil (2)");
1831 headerlessPublicData
= _CFDataCreateCopyFromRange(kCFAllocatorDefault
,
1832 tempPublicData
, CFRangeMake(altHdrLen
, CFDataGetLength(tempPublicData
) - altHdrLen
));
1833 if (!headerlessPublicData
) {
1834 secdebug("key", "SecKeyCopyPublicBytes: headerlessPublicData is nil (2)");
1838 if(!_CFDataEquals(publicDataHeader
, requiredPublicHeader
)) {
1840 CFIndex dataLen
= CFDataGetLength(tempPublicData
);
1841 const UInt8
*dataPtr
= CFDataGetBytePtr(tempPublicData
);
1842 syslog(LOG_NOTICE
, "Public key data (with header):");
1843 secdump((const unsigned char *)dataPtr
,(unsigned long)dataLen
);
1844 dataLen
= CFDataGetLength(requiredPublicHeader
);
1845 dataPtr
= CFDataGetBytePtr(requiredPublicHeader
);
1846 syslog(LOG_NOTICE
, "Required header:");
1847 secdump((const unsigned char *)dataPtr
,(unsigned long)dataLen
);
1848 dataLen
= CFDataGetLength(publicDataHeader
);
1849 dataPtr
= CFDataGetBytePtr(publicDataHeader
);
1850 syslog(LOG_NOTICE
, "Actual header:");
1851 secdump((const unsigned char *)dataPtr
,(unsigned long)dataLen
);
1853 secdebug("key", "_SecKeyCopyPublicBytes: public data header mismatch");
1857 *publicBytes
= headerlessPublicData
;
1858 ecStatus
= errSecSuccess
;
1862 if(requiredPublicHeader
) CFRelease(requiredPublicHeader
);
1863 if(publicDataHeader
) CFRelease(publicDataHeader
);
1864 if(tempPublicData
) CFRelease(tempPublicData
);
1870 CFDataRef
SecECKeyCopyPublicBits(SecKeyRef key
)
1872 CFDataRef exportedKey
;
1873 if(_SecKeyCopyPublicBytes(key
, &exportedKey
) != noErr
) {
1879 SecKeyRef
_SecKeyCreateFromPublicData(CFAllocatorRef allocator
, CFIndex algorithmID
, CFDataRef publicBytes
)
1881 SecExternalFormat externalFormat
= kSecFormatOpenSSL
;
1882 SecExternalItemType externalItemType
= kSecItemTypePublicKey
;
1883 CFDataRef workingData
= NULL
;
1884 CFArrayRef outArray
= NULL
;
1885 SecKeyRef retVal
= NULL
;
1887 if (kSecRSAAlgorithmID
== algorithmID
) {
1889 * kSecFormatBSAFE uses the original PKCS#1 definition:
1890 * RSAPublicKey ::= SEQUENCE {
1891 * modulus INTEGER, -- n
1892 * publicExponent INTEGER -- e
1894 * kSecFormatOpenSSL uses different ASN.1 encoding.
1896 externalFormat
= kSecFormatBSAFE
;
1897 workingData
= _CFDataCreateReferenceFromRange(kCFAllocatorDefault
, publicBytes
, CFRangeMake(0, CFDataGetLength(publicBytes
)));
1898 } else if (kSecECDSAAlgorithmID
== algorithmID
) {
1899 CFMutableDataRef tempData
;
1900 uint8 headerBytes
[] = { 0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86,
1901 0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a,
1902 0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,
1905 /* FIXME: this code only handles one specific curve type; need to expand this */
1906 tempData
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
1907 CFDataAppendBytes(tempData
, headerBytes
, sizeof(headerBytes
));
1908 CFDataAppendBytes(tempData
, CFDataGetBytePtr(publicBytes
), CFDataGetLength(publicBytes
));
1909 workingData
= tempData
;
1911 if(SecItemImport(workingData
, NULL
, &externalFormat
, &externalItemType
, 0, NULL
, NULL
, &outArray
) != errSecSuccess
) {
1914 if(!outArray
|| CFArrayGetCount(outArray
) == 0) {
1917 retVal
= (SecKeyRef
)CFArrayGetValueAtIndex(outArray
, 0);
1921 if(workingData
) CFRelease(workingData
);
1922 if(outArray
) CFRelease(outArray
);
1926 SecKeyRef
SecKeyCreateRSAPublicKey(CFAllocatorRef allocator
,
1927 const uint8_t *keyData
, CFIndex keyDataLength
,
1928 SecKeyEncoding encoding
)
1930 CFDataRef pubKeyData
= NULL
;
1931 if(kSecKeyEncodingPkcs1
== encoding
) {
1932 /* DER-encoded according to PKCS1. */
1933 pubKeyData
= CFDataCreate(allocator
, keyData
, keyDataLength
);
1935 } else if(kSecKeyEncodingApplePkcs1
== encoding
) {
1936 /* DER-encoded according to PKCS1 with Apple Extensions. */
1937 /* FIXME: need to actually handle extensions */
1940 } else if(kSecKeyEncodingRSAPublicParams
== encoding
) {
1941 /* SecRSAPublicKeyParams format; we must encode as PKCS1. */
1942 #if !TARGET_OS_EMBEDDED
1943 typedef struct SecRSAPublicKeyParams
{
1944 uint8_t *modulus
; /* modulus */
1945 CFIndex modulusLength
;
1946 uint8_t *exponent
; /* public exponent */
1947 CFIndex exponentLength
;
1948 } SecRSAPublicKeyParams
;
1950 SecRSAPublicKeyParams
*params
= (SecRSAPublicKeyParams
*)keyData
;
1951 DERSize m_size
= params
->modulusLength
;
1952 DERSize e_size
= params
->exponentLength
;
1953 const DERSize seq_size
= DERLengthOfItem(ASN1_INTEGER
, m_size
) +
1954 DERLengthOfItem(ASN1_INTEGER
, e_size
);
1955 const DERSize result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
1956 DERSize r_size
, remaining_size
= result_size
;
1959 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
1960 if (pkcs1
== NULL
) {
1963 CFDataSetLength(pkcs1
, result_size
);
1964 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
1966 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
1969 drtn
= DEREncodeLength(seq_size
, bytes
, &r_size
);
1970 if (r_size
<= remaining_size
) {
1972 remaining_size
-= r_size
;
1974 r_size
= remaining_size
;
1975 drtn
= DEREncodeItem(ASN1_INTEGER
, m_size
, (const DERByte
*)params
->modulus
, (DERByte
*)bytes
, &r_size
);
1976 if (r_size
<= remaining_size
) {
1978 remaining_size
-= r_size
;
1980 r_size
= remaining_size
;
1981 drtn
= DEREncodeItem(ASN1_INTEGER
, e_size
, (const DERByte
*)params
->exponent
, (DERByte
*)bytes
, &r_size
);
1986 /* unsupported encoding */
1989 SecKeyRef publicKey
= _SecKeyCreateFromPublicData(allocator
, kSecRSAAlgorithmID
, pubKeyData
);
1990 CFRelease(pubKeyData
);
1994 #if !TARGET_OS_EMBEDDED
1996 // Given a CSSM public key, copy its modulus and/or exponent data.
1997 // Caller is responsible for releasing the returned CFDataRefs.
1999 OSStatus
_SecKeyCopyRSAPublicModulusAndExponent(SecKeyRef key
, CFDataRef
*modulus
, CFDataRef
*exponent
)
2001 const CSSM_KEY
*pubKey
;
2002 const CSSM_KEYHEADER
*hdr
;
2003 CSSM_DATA pubKeyBlob
;
2006 result
= SecKeyGetCSSMKey(key
, &pubKey
);
2007 if(result
!= noErr
) {
2010 hdr
= &pubKey
->KeyHeader
;
2011 if(hdr
->KeyClass
!= CSSM_KEYCLASS_PUBLIC_KEY
) {
2012 return errSSLInternal
;
2014 if(hdr
->AlgorithmId
!= CSSM_ALGID_RSA
) {
2015 return errSSLInternal
;
2017 switch(hdr
->BlobType
) {
2018 case CSSM_KEYBLOB_RAW
:
2019 pubKeyBlob
.Length
= pubKey
->KeyData
.Length
;
2020 pubKeyBlob
.Data
= pubKey
->KeyData
.Data
;
2022 case CSSM_KEYBLOB_REFERENCE
:
2023 // FIXME: currently SSL only uses raw public keys, obtained from the CL
2025 return errSSLInternal
;
2027 assert(hdr
->BlobType
== CSSM_KEYBLOB_RAW
);
2028 // at this point we should have a PKCS1-encoded blob
2030 DERItem keyItem
= {(DERByte
*)pubKeyBlob
.Data
, pubKeyBlob
.Length
};
2031 DERRSAPubKeyPKCS1 decodedKey
;
2032 if(DERParseSequence(&keyItem
, DERNumRSAPubKeyPKCS1ItemSpecs
,
2033 DERRSAPubKeyPKCS1ItemSpecs
,
2034 &decodedKey
, sizeof(decodedKey
)) != DR_Success
) {
2035 return errSecDecode
;
2038 *modulus
= CFDataCreate(kCFAllocatorDefault
, decodedKey
.modulus
.data
, decodedKey
.modulus
.length
);
2039 if(*modulus
== NULL
) {
2040 return errSecDecode
;
2044 *exponent
= CFDataCreate(kCFAllocatorDefault
, decodedKey
.pubExponent
.data
, decodedKey
.pubExponent
.length
);
2045 if(*exponent
== NULL
) {
2046 return errSecDecode
;
2050 return errSecSuccess
;
2052 #endif /* !TARGET_OS_EMBEDDED */
2054 CFDataRef
SecKeyCopyModulus(SecKeyRef key
)
2056 #if TARGET_OS_EMBEDDED
2057 ccrsa_pub_ctx_t pubkey
;
2058 pubkey
.pub
= key
->key
;
2060 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
2062 CFAllocatorRef allocator
= CFGetAllocator(key
);
2063 CFMutableDataRef modulusData
= CFDataCreateMutable(allocator
, m_size
);
2065 if (modulusData
== NULL
)
2068 CFDataSetLength(modulusData
, m_size
);
2070 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, CFDataGetMutableBytePtr(modulusData
));
2072 CFDataRef modulusData
;
2073 OSStatus status
= _SecKeyCopyRSAPublicModulusAndExponent(key
, &modulusData
, NULL
);
2074 if(status
!= errSecSuccess
) {
2082 CFDataRef
SecKeyCopyExponent(SecKeyRef key
)
2084 #if TARGET_OS_EMBEDDED
2085 ccrsa_pub_ctx_t pubkey
;
2086 pubkey
.pub
= key
->key
;
2088 size_t e_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
2090 CFAllocatorRef allocator
= CFGetAllocator(key
);
2091 CFMutableDataRef exponentData
= CFDataCreateMutable(allocator
, e_size
);
2093 if (exponentData
== NULL
)
2096 CFDataSetLength(exponentData
, e_size
);
2098 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), e_size
, CFDataGetMutableBytePtr(exponentData
));
2100 CFDataRef exponentData
;
2101 OSStatus status
= _SecKeyCopyRSAPublicModulusAndExponent(key
, NULL
, &exponentData
);
2102 if(status
!= errSecSuccess
) {
2103 exponentData
= NULL
;
2107 return exponentData
;