2 * Copyright (c) 2006-2010,2012-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 * SecRSAKey.c - CoreFoundation based rsa key object
29 #include "SecRSAKey.h"
30 #include "SecRSAKeyPriv.h"
31 #include <Security/SecKeyInternal.h>
32 #include <Security/SecItem.h>
33 #include <Security/SecBasePriv.h>
34 #include <AssertMacros.h>
35 #include <Security/SecureTransport.h> /* For error codes. */
36 #include <CoreFoundation/CFData.h> /* For error codes. */
38 #include <sys/types.h>
40 #include <CoreFoundation/CFNumber.h>
41 #include <Security/SecFramework.h>
42 #include <Security/SecRandom.h>
43 #include <utilities/debugging.h>
44 #include <utilities/SecCFWrappers.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/array_size.h>
47 #include <Security/SecItemPriv.h>
48 #include <Security/SecInternal.h>
50 #include <corecrypto/ccn.h>
51 #include <corecrypto/ccrsa.h>
52 #include <corecrypto/ccsha1.h>
53 #include <corecrypto/ccsha2.h>
55 #include <libDER/asn1Types.h>
56 #include <libDER/DER_Keys.h>
57 #include <libDER/DER_Encode.h>
59 #include <CommonCrypto/CommonDigest.h>
61 #include <corecrypto/ccrsa_priv.h>
66 #define kMaximumRSAKeyBits (1024 * 8)
68 #define RSA_PKCS1_PAD_SIGN 0x01
69 #define RSA_PKCS1_PAD_ENCRYPT 0x02
77 /* Public key static functions. */
78 static void SecRSAPublicKeyDestroy(SecKeyRef key
) {
79 /* Zero out the public key */
81 ccrsa_pub_ctx_t pubkey
= key
->key
;
82 cc_clear(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey
))), pubkey
);
88 #define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
91 // pubkey is initilaized with an n which is the maximum it can hold
92 // We set the n to its correct value given m.
94 static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey
,
95 size_t m_size
, const uint8_t* m
,
96 size_t e_size
, const uint8_t* e
)
98 cc_skip_zeros(m_size
, m
);
100 cc_size nm
= ccn_nof_size(m_size
);
101 if (nm
> ccrsa_ctx_n(pubkey
))
104 ccrsa_ctx_n(pubkey
) = nm
;
106 ccn_read_uint(nm
, ccrsa_ctx_m(pubkey
), m_size
, m
);
107 cczp_init(ccrsa_ctx_zm(pubkey
));
109 return ccn_read_uint(nm
, ccrsa_ctx_e(pubkey
), e_size
, e
);
113 static OSStatus
ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
115 OSStatus result
= errSecParam
;
117 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
118 DERRSAPubKeyApple decodedKey
;
120 require_noerr_action_quiet(DERParseSequence(&keyItem
,
121 DERNumRSAPubKeyAppleItemSpecs
, DERRSAPubKeyAppleItemSpecs
,
122 &decodedKey
, sizeof(decodedKey
)),
123 errOut
, result
= errSecDecode
);
125 // We could honor the reciprocal, but we don't think this is used enough to care.
126 // Don't bother exploding the below function to try to handle this case, it computes.
128 require_noerr_quiet(ccrsa_pub_init(pubkey
,
129 decodedKey
.modulus
.length
, decodedKey
.modulus
.data
,
130 decodedKey
.pubExponent
.length
, decodedKey
.pubExponent
.data
),
133 result
= errSecSuccess
;
140 static void ccasn_encode_int(cc_size n
, const cc_unit
*s
, size_t s_size
, uint8_t **buffer
)
142 **buffer
= ASN1_INTEGER
;
145 DERSize itemLength
= 4;
146 DEREncodeLength(s_size
, *buffer
, &itemLength
);
147 *buffer
+= itemLength
;
149 ccn_write_int(n
, s
, s_size
, *buffer
);
155 static OSStatus
SecRSAPublicKeyInit(SecKeyRef key
,
156 const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
158 OSStatus result
= errSecParam
;
159 ccrsa_pub_ctx_t pubkey
;
163 case kSecKeyEncodingBytes
: // Octets is PKCS1
164 case kSecKeyEncodingPkcs1
: {
165 size_n
= ccrsa_import_pub_n(keyDataLength
, keyData
);
166 require_quiet(size_n
!= 0, errOut
);
167 require_quiet(size_n
<= ccn_nof(kMaximumRSAKeyBits
), errOut
);
169 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
170 require_action_quiet(key
->key
, errOut
, result
= errSecAllocate
);
173 ccrsa_ctx_n(pubkey
) = size_n
;
175 require_noerr_quiet(ccrsa_import_pub(pubkey
, keyDataLength
, keyData
), errOut
);
177 result
= errSecSuccess
;
181 case kSecKeyEncodingApplePkcs1
:
182 /* for the few uses (I can't find any) that uses kSecKeyEncodingApplePkcs1, force largest keys */
183 size_n
= ccn_nof(kMaximumRSAKeyBits
);
185 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
186 require_action_quiet(key
->key
, errOut
, result
= errSecAllocate
);
189 ccrsa_ctx_n(pubkey
) = size_n
;
191 result
= ccrsa_pub_decode_apple(pubkey
, keyDataLength
, keyData
);
193 case kSecKeyEncodingRSAPublicParams
:
195 SecRSAPublicKeyParams
*params
= (SecRSAPublicKeyParams
*)keyData
;
197 size_n
= ccn_nof_size(params
->modulusLength
);
199 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
200 require_action_quiet(key
->key
, errOut
, result
= errSecAllocate
);
203 ccrsa_ctx_n(pubkey
) = size_n
;
205 require_noerr_quiet(ccrsa_pub_init(pubkey
,
206 params
->modulusLength
, params
->modulus
,
207 params
->exponentLength
, params
->exponent
), errOut
);
209 result
= errSecSuccess
;
212 case kSecExtractPublicFromPrivate
:
214 ccrsa_full_ctx_t fullKey
= (ccrsa_full_ctx_t
) keyData
;
216 size_n
= ccrsa_ctx_n(fullKey
);
218 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
219 require_action_quiet(key
->key
, errOut
, result
= errSecAllocate
);
222 ccrsa_ctx_n(pubkey
) = size_n
;
224 memcpy(pubkey
, ccrsa_ctx_public(fullKey
), ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
225 result
= errSecSuccess
;
236 static CFTypeRef
SecRSAPublicKeyCopyOperationResult(SecKeyRef key
, SecKeyOperationType operation
, SecKeyAlgorithm algorithm
,
237 CFArrayRef allAlgorithms
, SecKeyOperationMode mode
,
238 CFTypeRef in1
, CFTypeRef in2
, CFErrorRef
*error
) {
240 require_action_quiet(CFEqual(algorithm
, kSecKeyAlgorithmRSAEncryptionRawCCUnit
), out
, result
= kCFNull
);
242 ccrsa_pub_ctx_t pubkey
= key
->key
;
243 result
= kCFBooleanTrue
;
246 case kSecKeyOperationTypeEncrypt
:
247 if (mode
== kSecKeyOperationModePerform
) {
248 // Input buffer length must be cc_unit aligned, otherwise it is not a valid cc_unit buffer.
249 CFIndex bufferSize
= CFDataGetLength(in1
);
250 require_action_quiet(bufferSize
== ccn_sizeof_size(ccrsa_block_size(pubkey
)), out
,
252 SecError(errSecParam
, error
, CFSTR("%@: sign - input buffer bad size (%d bytes)"), key
,
255 // Verify that plaintext is smaller than modulus. Note that since we already verified that input algorithm
256 // is kSecKeyAlgorithmRSAEncryptionRawCCUnit, we can safely access in1 CFDataRef contents as cc_unit *.
257 require_action_quiet(ccn_cmpn(ccn_nof_size(CFDataGetLength(in1
)), (const cc_unit
*)CFDataGetBytePtr(in1
),
258 ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
)) < 0, out
,
260 SecError(errSecParam
, error
, CFSTR("RSApubkey wrong size of buffer to encrypt"))));
262 // Encrypt into output buffer.
263 result
= CFDataCreateMutableWithScratch(NULL
, bufferSize
);
264 ccerr
= ccrsa_pub_crypt(pubkey
, (cc_unit
*)CFDataGetMutableBytePtr((CFMutableDataRef
)result
),
265 (const cc_unit
*)CFDataGetBytePtr(in1
));
268 case kSecKeyOperationTypeDecrypt
:
269 if (mode
== kSecKeyOperationModePerform
) {
270 // Input buffer length must be cc_unit aligned, otherwise it is not a valid cc_unit buffer.
271 CFIndex bufferSize
= CFDataGetLength(in1
);
272 require_action_quiet(bufferSize
== ccn_sizeof_size(ccrsa_block_size(pubkey
)), out
,
274 SecError(errSecParam
, error
, CFSTR("%@: sign - input buffer bad size (%d bytes)"), key
,
277 // Decrypt into output buffer.
278 result
= CFDataCreateMutableWithScratch(NULL
, bufferSize
);
279 ccerr
= ccrsa_pub_crypt(pubkey
, (cc_unit
*)CFDataGetMutableBytePtr((CFMutableDataRef
)result
),
280 (const cc_unit
*)CFDataGetBytePtr(in1
));
288 require_noerr_action_quiet(ccerr
, out
, (CFReleaseNull(result
),
289 SecError(errSecParam
, error
, CFSTR("rsa_pub_crypt failed, ccerr=%d"), ccerr
)));
294 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key
) {
295 ccrsa_pub_ctx_t pubkey
= key
->key
;
296 return ccrsa_block_size(pubkey
);
300 static CFDataRef
SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_pub_ctx_t pubkey
)
302 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
303 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
305 const size_t seq_size
= DERLengthOfItem(ASN1_INTEGER
, m_size
) +
306 DERLengthOfItem(ASN1_INTEGER
, e_size
);
308 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
310 CFMutableDataRef pkcs1
= CFDataCreateMutableWithScratch(allocator
, result_size
);
311 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
313 *bytes
++ = ONE_BYTE_ASN1_CONSTR_SEQUENCE
;
315 DERSize itemLength
= 4;
316 DEREncodeLength(seq_size
, bytes
, &itemLength
);
319 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, &bytes
);
320 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
), e_size
, &bytes
);
325 static OSStatus
SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
327 ccrsa_pub_ctx_t pubkey
= key
->key
;
329 CFAllocatorRef allocator
= CFGetAllocator(key
);
330 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, pubkey
);
332 if (NULL
== *serialized
)
335 return errSecSuccess
;
338 static CFDictionaryRef
SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key
) {
339 CFDictionaryRef dict
= SecKeyGeneratePublicAttributeDictionary(key
, kSecAttrKeyTypeRSA
);
340 CFMutableDictionaryRef mutableDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
341 CFDictionarySetValue(mutableDict
, kSecAttrCanDecrypt
, kCFBooleanTrue
);
342 CFDictionarySetValue(mutableDict
, kSecAttrCanDerive
, kCFBooleanFalse
);
343 CFAssignRetained(dict
, mutableDict
);
347 static CFDataRef
SecRSAPublicKeyCopyExternalRepresentation(SecKeyRef key
, CFErrorRef
*error
) {
348 ccrsa_pub_ctx_t pubkey
= key
->key
;
349 return SecRSAPublicKeyCreatePKCS1(CFGetAllocator(key
), pubkey
);
352 static CFStringRef
SecRSAPublicKeyCopyDescription(SecKeyRef key
) {
354 CFStringRef keyDescription
= NULL
;
355 CFDataRef modRef
= SecKeyCopyModulus(key
);
357 ccrsa_pub_ctx_t pubkey
= key
->key
;
359 CFStringRef modulusString
= CFDataCopyHexString(modRef
);
360 require_quiet(modulusString
, fail
);
362 keyDescription
= CFStringCreateWithFormat(kCFAllocatorDefault
,NULL
,CFSTR( "<SecKeyRef algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, exponent: {hex: %llx, decimal: %lld}, modulus: %@, addr: %p>"), SecKeyGetAlgorithmId(key
), key
->key_class
->name
, key
->key_class
->version
, (8*SecKeyGetBlockSize(key
)), (long long)*ccrsa_ctx_e(pubkey
), (long long)*ccrsa_ctx_e(pubkey
), modulusString
, key
);
365 CFReleaseSafe(modRef
);
366 CFReleaseSafe(modulusString
);
368 keyDescription
= CFStringCreateWithFormat(kCFAllocatorDefault
,NULL
,CFSTR("<SecKeyRef algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), (long)SecKeyGetAlgorithmId(key
), key
->key_class
->name
, key
->key_class
->version
, (8*SecKeyGetBlockSize(key
)), key
);
370 return keyDescription
;
373 SecKeyDescriptor kSecRSAPublicKeyDescriptor
= {
374 .version
= kSecKeyDescriptorVersion
,
375 .name
= "RSAPublicKey",
377 .init
= SecRSAPublicKeyInit
,
378 .destroy
= SecRSAPublicKeyDestroy
,
379 .blockSize
= SecRSAPublicKeyBlockSize
,
380 .copyDictionary
= SecRSAPublicKeyCopyAttributeDictionary
,
381 .copyExternalRepresentation
= SecRSAPublicKeyCopyExternalRepresentation
,
382 .describe
= SecRSAPublicKeyCopyDescription
,
383 .copyPublic
= SecRSAPublicKeyCopyPublicSerialization
,
384 .copyOperationResult
= SecRSAPublicKeyCopyOperationResult
,
387 /* Public Key API functions. */
388 SecKeyRef
SecKeyCreateRSAPublicKey_ios(CFAllocatorRef allocator
,
389 const uint8_t *keyData
, CFIndex keyDataLength
,
390 SecKeyEncoding encoding
) {
391 return SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
, keyData
,
392 keyDataLength
, encoding
);
395 SecKeyRef
SecKeyCreateRSAPublicKey(CFAllocatorRef allocator
,
396 const uint8_t *keyData
, CFIndex keyDataLength
,
397 SecKeyEncoding encoding
) {
398 return SecKeyCreateRSAPublicKey_ios(allocator
, keyData
,
399 keyDataLength
, encoding
);
402 CFDataRef
SecKeyCopyModulus(SecKeyRef key
) {
403 CFDataRef modulus
= NULL
;
404 if (key
->key_class
== &kSecRSAPublicKeyDescriptor
) {
405 ccrsa_pub_ctx_t pubkey
= key
->key
;
407 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
409 CFAllocatorRef allocator
= CFGetAllocator(key
);
410 CFMutableDataRef modulusData
= CFDataCreateMutable(allocator
, m_size
);
412 if (modulusData
== NULL
)
415 CFDataSetLength(modulusData
, m_size
);
417 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, CFDataGetMutableBytePtr(modulusData
));
418 modulus
= modulusData
;
419 } else if (key
->key_class
->copyDictionary
!= NULL
) {
420 CFDictionaryRef dict
= key
->key_class
->copyDictionary(key
);
422 modulus
= CFRetainSafe(CFDictionaryGetValue(dict
, CFSTR("_rsam")));
430 CFDataRef
SecKeyCopyExponent(SecKeyRef key
) {
431 CFDataRef exponent
= NULL
;
432 if (key
->key_class
== &kSecRSAPublicKeyDescriptor
) {
433 ccrsa_pub_ctx_t pubkey
= key
->key
;
435 size_t e_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
437 CFAllocatorRef allocator
= CFGetAllocator(key
);
438 CFMutableDataRef exponentData
= CFDataCreateMutable(allocator
, e_size
);
440 if (exponentData
== NULL
)
443 CFDataSetLength(exponentData
, e_size
);
445 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
), e_size
, CFDataGetMutableBytePtr(exponentData
));
446 exponent
= exponentData
;
447 } else if (key
->key_class
->copyDictionary
!= NULL
) {
448 CFDictionaryRef dict
= key
->key_class
->copyDictionary(key
);
450 exponent
= CFRetainSafe(CFDictionaryGetValue(dict
, CFSTR("_rsae")));
465 /* Private key static functions. */
466 static void SecRSAPrivateKeyDestroy(SecKeyRef key
) {
467 /* Zero out the public key */
469 ccrsa_full_ctx_t fullkey
= key
->key
;
470 cc_clear(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey
))), fullkey
);
476 static OSStatus
SecRSAPrivateKeyInit(SecKeyRef key
, const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
477 OSStatus result
= errSecParam
;
478 ccrsa_full_ctx_t fullkey
;
482 case kSecKeyEncodingBytes
: // Octets is PKCS1
483 case kSecKeyEncodingPkcs1
:
485 size_n
= ccrsa_import_priv_n(keyDataLength
,keyData
);
486 require_quiet(size_n
!= 0, errOut
);
487 require_quiet(size_n
<= ccn_nof(kMaximumRSAKeyBits
), errOut
);
489 key
->key
= calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n
)));
490 require_action_quiet(key
->key
, errOut
, result
= errSecAllocate
);
493 ccrsa_ctx_n(fullkey
) = size_n
;
495 require_quiet(ccrsa_import_priv(fullkey
, keyDataLength
, keyData
)==0, errOut
);
497 result
= errSecSuccess
;
500 case kSecGenerateKey
:
502 CFDictionaryRef parameters
= (CFDictionaryRef
) keyData
;
504 CFTypeRef ksize
= CFDictionaryGetValue(parameters
, kSecAttrKeySizeInBits
);
505 CFIndex keyLengthInBits
= getIntValue(ksize
);
507 if (keyLengthInBits
< 512 || keyLengthInBits
> kMaximumRSAKeyBits
) {
508 secwarning("Invalid or missing key size in: %@", parameters
);
509 result
= errSecKeySizeNotAllowed
;
513 size_n
= ccn_nof(keyLengthInBits
);
515 key
->key
= calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n
)));
516 require_action_quiet(key
->key
, errOut
, result
= errSecAllocate
);
519 ccrsa_ctx_n(fullkey
) = size_n
;
521 /* TODO: Add support for kSecPublicExponent parameter. */
522 static uint8_t e
[] = { 0x01, 0x00, 0x01 }; // Default is 65537
523 if (!ccrsa_generate_fips186_key(keyLengthInBits
, fullkey
, sizeof(e
), e
, ccrng_seckey
,ccrng_seckey
))
524 result
= errSecSuccess
;
534 static CFTypeRef
SecRSAPrivateKeyCopyOperationResult(SecKeyRef key
, SecKeyOperationType operation
, SecKeyAlgorithm algorithm
,
535 CFArrayRef allAlgorithms
, SecKeyOperationMode mode
,
536 CFTypeRef in1
, CFTypeRef in2
, CFErrorRef
*error
) {
537 CFTypeRef result
= kCFNull
;
539 ccrsa_full_ctx_t fullkey
= key
->key
;
542 case kSecKeyOperationTypeSign
:
543 if (CFEqual(algorithm
, kSecKeyAlgorithmRSASignatureRawCCUnit
)) {
544 if (mode
== kSecKeyOperationModePerform
) {
545 // Input buffer length must be cc_unit aligned, otherwise it is not a valid cc_unit buffer.
546 CFIndex bufferSize
= CFDataGetLength(in1
);
547 require_action_quiet(bufferSize
== ccn_sizeof_size(ccrsa_block_size(ccrsa_ctx_public(fullkey
))), out
,
549 SecError(errSecParam
, error
, CFSTR("%@: sign - input buffer bad size (%d bytes)"), key
,
552 // Verify that data is smaller than modulus. Note that since we already verified that input algorithm
553 // is kSecKeyAlgorithmRSASignatureRawCCUnit, we can safely access in1 CFDataRef contents as cc_unit *.
554 require_action_quiet(ccn_cmpn(ccn_nof_size(CFDataGetLength(in1
)), (const cc_unit
*)CFDataGetBytePtr(in1
),
555 ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
)) < 0, out
,
557 SecError(errSecParam
, error
, CFSTR("%@: sign - digest too big (%d bytes)"), key
,
558 (int)CFDataGetLength(in1
))));
560 // Encrypt buffer and write it to output data.
561 result
= CFDataCreateMutableWithScratch(kCFAllocatorDefault
, bufferSize
);
562 ccerr
= ccrsa_priv_crypt(fullkey
, (cc_unit
*)CFDataGetMutableBytePtr((CFMutableDataRef
)result
),
563 (const cc_unit
*)CFDataGetBytePtr(in1
));
565 // Operation is supported.
566 result
= kCFBooleanTrue
;
570 case kSecKeyOperationTypeDecrypt
:
571 if (CFEqual(algorithm
, kSecKeyAlgorithmRSAEncryptionRawCCUnit
)) {
572 if (mode
== kSecKeyOperationModePerform
) {
573 // Input buffer length must be cc_unit aligned, otherwise it is not a valid cc_unit buffer.
574 CFIndex bufferSize
= CFDataGetLength(in1
);
575 require_action_quiet(bufferSize
== ccn_sizeof_size(ccrsa_block_size(ccrsa_ctx_public(fullkey
))), out
,
577 SecError(errSecParam
, error
, CFSTR("%@: sign - input buffer bad size (%d bytes)"), key
,
580 // Decrypt buffer and write it to output data.
581 result
= CFDataCreateMutableWithScratch(NULL
, bufferSize
);
582 ccerr
= ccrsa_priv_crypt(fullkey
, (cc_unit
*)CFDataGetMutableBytePtr((CFMutableDataRef
)result
),
583 (const cc_unit
*)CFDataGetBytePtr(in1
));
585 // Operation is supported.
586 result
= kCFBooleanTrue
;
594 require_noerr_action_quiet(ccerr
, out
, (CFReleaseNull(result
),
595 SecError(errSecParam
, error
, CFSTR("rsa_priv_crypt failed, ccerr=%d"), ccerr
)));
600 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key
) {
601 ccrsa_full_ctx_t fullkey
= key
->key
;
603 return ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
606 static CFDataRef
SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_full_ctx_t fullkey
)
608 const size_t result_size
= ccrsa_export_priv_size(fullkey
);
610 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
615 CFDataSetLength(pkcs1
, result_size
);
617 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
619 if (ccrsa_export_priv(fullkey
,result_size
,bytes
)!=0) {
620 /* Decoding failed */
621 CFReleaseNull(pkcs1
);
628 static CFDataRef
SecRSAPrivateKeyCopyPKCS1(SecKeyRef key
)
630 ccrsa_full_ctx_t fullkey
= key
->key
;
632 CFAllocatorRef allocator
= CFGetAllocator(key
);
633 return SecRSAPrivateKeyCreatePKCS1(allocator
, fullkey
);
636 static OSStatus
SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
638 ccrsa_full_ctx_t fullkey
= key
->key
;
640 CFAllocatorRef allocator
= CFGetAllocator(key
);
641 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, ccrsa_ctx_public(fullkey
));
643 if (NULL
== *serialized
)
646 return errSecSuccess
;
650 static CFDictionaryRef
SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key
) {
651 CFDictionaryRef dict
= NULL
;
652 CFDataRef fullKeyBlob
= NULL
;
654 /* PKCS1 encode the key pair. */
655 fullKeyBlob
= SecRSAPrivateKeyCopyPKCS1(key
);
656 require_quiet(fullKeyBlob
, errOut
);
658 dict
= SecKeyGeneratePrivateAttributeDictionary(key
, kSecAttrKeyTypeRSA
, fullKeyBlob
);
659 CFMutableDictionaryRef mutableDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
660 CFDictionarySetValue(mutableDict
, kSecAttrCanDerive
, kCFBooleanFalse
);
661 CFAssignRetained(dict
, mutableDict
);
664 CFReleaseSafe(fullKeyBlob
);
669 static CFDataRef
SecRSAPrivateKeyCopyExternalRepresentation(SecKeyRef key
, CFErrorRef
*error
) {
670 return SecRSAPrivateKeyCopyPKCS1(key
);
673 static CFStringRef
SecRSAPrivateKeyCopyDescription(SecKeyRef key
){
675 return CFStringCreateWithFormat(kCFAllocatorDefault
,NULL
,CFSTR( "<SecKeyRef algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), SecKeyGetAlgorithmId(key
), key
->key_class
->name
, key
->key_class
->version
, (8*SecKeyGetBlockSize(key
)), key
);
679 SecKeyDescriptor kSecRSAPrivateKeyDescriptor
= {
680 .version
= kSecKeyDescriptorVersion
,
681 .name
= "RSAPrivateKey",
683 .init
= SecRSAPrivateKeyInit
,
684 .destroy
= SecRSAPrivateKeyDestroy
,
685 .blockSize
= SecRSAPrivateKeyBlockSize
,
686 .copyExternalRepresentation
= SecRSAPrivateKeyCopyExternalRepresentation
,
687 .copyDictionary
= SecRSAPrivateKeyCopyAttributeDictionary
,
688 .describe
= SecRSAPrivateKeyCopyDescription
,
689 .copyPublic
= SecRSAPrivateKeyCopyPublicSerialization
,
690 .copyOperationResult
= SecRSAPrivateKeyCopyOperationResult
,
693 /* Private Key API functions. */
694 SecKeyRef
SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator
,
695 const uint8_t *keyData
, CFIndex keyDataLength
,
696 SecKeyEncoding encoding
) {
697 return SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
, keyData
,
698 keyDataLength
, encoding
);
702 OSStatus
SecRSAKeyGeneratePair(CFDictionaryRef parameters
,
703 SecKeyRef
*rsaPublicKey
, SecKeyRef
*rsaPrivateKey
) {
704 OSStatus status
= errSecParam
;
706 CFAllocatorRef allocator
= NULL
; /* @@@ get from parameters. */
708 SecKeyRef pubKey
= NULL
;
709 SecKeyRef privKey
= SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
,
710 (const void*) parameters
, 0, kSecGenerateKey
);
712 require_quiet(privKey
, errOut
);
714 /* Create SecKeyRef's from the pkcs1 encoded keys. */
715 pubKey
= SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
,
716 privKey
->key
, 0, kSecExtractPublicFromPrivate
);
718 require_quiet(pubKey
, errOut
);
721 *rsaPublicKey
= pubKey
;
725 *rsaPrivateKey
= privKey
;
729 status
= errSecSuccess
;
732 CFReleaseSafe(pubKey
);
733 CFReleaseSafe(privKey
);