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 "SecItemPriv.h"
46 #include <Security/SecInternal.h>
48 #include <corecrypto/ccn.h>
49 #include <corecrypto/ccrsa.h>
50 #include <corecrypto/ccsha1.h>
52 #include <libDER/asn1Types.h>
53 #include <libDER/DER_Keys.h>
54 #include <libDER/DER_Encode.h>
56 #include <CommonCrypto/CommonDigest.h>
58 #include <corecrypto/ccrsa_priv.h>
63 #define kMaximumRSAKeyBits (1024 * 8)
65 #define RSA_PKCS1_PAD_SIGN 0x01
66 #define RSA_PKCS1_PAD_ENCRYPT 0x02
68 static void ccn_c_dump(cc_size count
, const cc_unit
*s
)
72 for (ix
= count
; ix
--;) {
73 printf("0x%.02x, 0x%.02x, 0x%.02x, 0x%.02x, ",
74 (int) ((s
[ix
] >> 24) & 0xFF),
75 (int) ((s
[ix
] >> 16) & 0xFF),
76 (int) ((s
[ix
] >> 8 ) & 0xFF),
77 (int) ((s
[ix
] >> 0 ) & 0xFF));
82 static void ccn_cprint(cc_size count
, char* prefix
, const cc_unit
*s
)
89 void ccrsa_dump_full_key(ccrsa_full_ctx_t key
); // Suppress warnings
90 void ccrsa_dump_full_key(ccrsa_full_ctx_t key
) {
91 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t m[] = ", ccrsa_ctx_m(key
));
92 ccn_cprint(ccrsa_ctx_n(key
) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key
)));
93 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t e[] = ", ccrsa_ctx_e(key
));
94 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t d[] = ", ccrsa_ctx_d(key
));
96 printf("cc_size np = %lu;\n", cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))));
97 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))), "uint8_t p[] = ",
98 cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))));
99 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))) + 1, "uint8_t rp[] = ",
100 cczp_recip(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))));
101 printf("cc_size nq = %lu;\n", cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))));
102 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))), "uint8_t q[] = ",
103 cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))));
104 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))) + 1, "uint8_t rq[] = ",
105 cczp_recip(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))));
106 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))), "uint8_t dp[] = ",
107 ccrsa_ctx_private_dp(ccrsa_ctx_private(key
)));
108 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))), "uint8_t dq[] = ",
109 ccrsa_ctx_private_dq(ccrsa_ctx_private(key
)));
110 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))), "uint8_t qinv[] = ",
111 ccrsa_ctx_private_qinv(ccrsa_ctx_private(key
)));
115 void ccrsa_dump_public_key(ccrsa_pub_ctx_t key
); // Suppress warning.
116 void ccrsa_dump_public_key(ccrsa_pub_ctx_t key
) {
117 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t m[] = ", ccrsa_ctx_m(key
));
118 ccn_cprint(ccrsa_ctx_n(key
) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key
)));
119 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t e[] = ", ccrsa_ctx_e(key
));
130 /* Public key static functions. */
131 static void SecRSAPublicKeyDestroy(SecKeyRef key
) {
132 /* Zero out the public key */
134 ccrsa_pub_ctx_t pubkey
;
135 pubkey
.pub
= key
->key
;
136 cc_clear(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey
))), pubkey
.pub
);
142 #define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
145 // pubkey is initilaized with an n which is the maximum it can hold
146 // We set the n to its correct value given m.
148 static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey
,
149 size_t m_size
, const uint8_t* m
,
150 size_t e_size
, const uint8_t* e
)
152 cc_skip_zeros(m_size
, m
);
154 cc_size nm
= ccn_nof_size(m_size
);
155 if (nm
> ccrsa_ctx_n(pubkey
))
158 ccrsa_ctx_n(pubkey
) = nm
;
160 ccn_read_uint(nm
, ccrsa_ctx_m(pubkey
), m_size
, m
);
161 cczp_init(ccrsa_ctx_zm(pubkey
));
163 return ccn_read_uint(nm
, ccrsa_ctx_e(pubkey
), e_size
, e
);
167 static OSStatus
ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
169 OSStatus result
= errSecParam
;
171 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
172 DERRSAPubKeyApple decodedKey
;
174 require_noerr_action(DERParseSequence(&keyItem
,
175 DERNumRSAPubKeyAppleItemSpecs
, DERRSAPubKeyAppleItemSpecs
,
176 &decodedKey
, sizeof(decodedKey
)),
177 errOut
, result
= errSecDecode
);
179 // We could honor the recipricol, but we don't think this is used enough to care.
180 // Don't bother exploding the below function to try to handle this case, it computes.
182 require_noerr(ccrsa_pub_init(pubkey
,
183 decodedKey
.modulus
.length
, decodedKey
.modulus
.data
,
184 decodedKey
.pubExponent
.length
, decodedKey
.pubExponent
.data
),
187 result
= errSecSuccess
;
194 static void ccasn_encode_int(cc_size n
, const cc_unit
*s
, size_t s_size
, uint8_t **buffer
)
196 **buffer
= ASN1_INTEGER
;
199 DERSize itemLength
= 4;
200 DEREncodeLength(s_size
, *buffer
, &itemLength
);
201 *buffer
+= itemLength
;
203 ccn_write_int(n
, s
, s_size
, *buffer
);
209 static OSStatus
SecRSAPublicKeyInit(SecKeyRef key
,
210 const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
212 OSStatus result
= errSecParam
;
213 ccrsa_pub_ctx_t pubkey
;
217 case kSecKeyEncodingBytes
: // Octets is PKCS1
218 case kSecKeyEncodingPkcs1
: {
219 const uint8_t *der_end
= keyData
+ keyDataLength
;
220 size_n
= ccder_decode_rsa_pub_n(keyData
, der_end
);
221 require(size_n
!= 0, errOut
);
222 require(size_n
<= ccn_nof(kMaximumRSAKeyBits
), errOut
);
224 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
225 require_action(key
->key
, errOut
, result
= errSecAllocate
);
227 pubkey
.pub
= key
->key
;
228 ccrsa_ctx_n(pubkey
) = size_n
;
230 require_noerr(ccrsa_import_pub(pubkey
, keyDataLength
, keyData
), errOut
);
232 result
= errSecSuccess
;
236 case kSecKeyEncodingApplePkcs1
:
237 /* for the few uses (I can't find any) that uses kSecKeyEncodingApplePkcs1, force largest keys */
238 size_n
= ccn_nof(kMaximumRSAKeyBits
);
240 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
241 require_action(key
->key
, errOut
, result
= errSecAllocate
);
243 pubkey
.pub
= key
->key
;
244 ccrsa_ctx_n(pubkey
) = size_n
;
246 result
= ccrsa_pub_decode_apple(pubkey
, keyDataLength
, keyData
);
248 case kSecKeyEncodingRSAPublicParams
:
250 SecRSAPublicKeyParams
*params
= (SecRSAPublicKeyParams
*)keyData
;
252 size_n
= ccn_nof_size(params
->modulusLength
);
254 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
255 require_action(key
->key
, errOut
, result
= errSecAllocate
);
257 pubkey
.pub
= key
->key
;
258 ccrsa_ctx_n(pubkey
) = size_n
;
260 require_noerr(ccrsa_pub_init(pubkey
,
261 params
->modulusLength
, params
->modulus
,
262 params
->exponentLength
, params
->exponent
), errOut
);
264 result
= errSecSuccess
;
267 case kSecExtractPublicFromPrivate
:
269 ccrsa_full_ctx_t fullKey
;
270 fullKey
.full
= (ccrsa_full_ctx
*) keyData
;
272 size_n
= ccrsa_ctx_n(fullKey
);
274 key
->key
= calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
275 require_action(key
->key
, errOut
, result
= errSecAllocate
);
277 pubkey
.pub
= key
->key
;
278 ccrsa_ctx_n(pubkey
) = size_n
;
280 memcpy(pubkey
.pub
, ccrsa_ctx_public(fullKey
).pub
, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n
)));
281 result
= errSecSuccess
;
292 static OSStatus
SecRSAPublicKeyRawVerify(SecKeyRef key
, SecPadding padding
,
293 const uint8_t *signedData
, size_t signedDataLen
,
294 const uint8_t *sig
, size_t sigLen
) {
295 OSStatus result
= errSSLCrypto
;
297 ccrsa_pub_ctx_t pubkey
;
298 pubkey
.pub
= key
->key
;
300 cc_unit s
[ccrsa_ctx_n(pubkey
)];
302 ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, sigLen
, sig
);
303 ccrsa_pub_crypt(pubkey
, s
, s
);
304 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
306 const uint8_t* sBytes
= (uint8_t*) s
;
307 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(pubkey
));
310 case kSecPaddingNone
:
311 // Skip leading zeros as long as s is bigger than signedData.
312 while (((ptrdiff_t)signedDataLen
< (sEnd
- sBytes
)) && (*sBytes
== 0))
316 case kSecPaddingPKCS1
:
318 // Verify and skip PKCS1 padding:
320 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
322 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
323 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
325 while (prefix_zeros
--)
326 require_quiet(*sBytes
++ == 0x00, errOut
);
328 require_quiet(*sBytes
++ == 0x00, errOut
);
329 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_SIGN
, errOut
);
331 while (*sBytes
== 0xFF) {
332 require_quiet(++sBytes
< sEnd
, errOut
);
334 // Required to have at least 8 0xFFs
335 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
337 require_quiet(*sBytes
== 0x00, errOut
);
338 require_quiet(++sBytes
< sEnd
, errOut
);
341 case kSecPaddingOAEP
:
342 result
= errSecParam
;
346 result
= errSecUnimplemented
;
351 require_quiet((sEnd
- sBytes
) == (ptrdiff_t)signedDataLen
, errOut
);
352 require_quiet(memcmp(sBytes
, signedData
, signedDataLen
) == 0, errOut
);
354 result
= errSecSuccess
;
357 cc_clear(ccrsa_ctx_n(pubkey
), s
);
362 static OSStatus
SecRSAPublicKeyRawEncrypt(SecKeyRef key
, SecPadding padding
,
363 const uint8_t *plainText
, size_t plainTextLen
,
364 uint8_t *cipherText
, size_t *cipherTextLen
) {
365 OSStatus result
= errSecParam
;
366 ccrsa_pub_ctx_t pubkey
;
367 pubkey
.pub
= key
->key
;
369 cc_unit s
[ccrsa_ctx_n(pubkey
)];
370 const size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
372 require(cipherTextLen
, errOut
);
373 require(*cipherTextLen
>= m_size
, errOut
);
375 uint8_t* sBytes
= (uint8_t*) s
;
378 case kSecPaddingNone
:
379 // We'll allow modulus size assuming input is smaller than modulus
380 require_quiet(plainTextLen
<= m_size
, errOut
);
381 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, plainTextLen
, plainText
), errOut
);
382 require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey
), s
, ccrsa_ctx_m(pubkey
)) < 0, errOut
);
385 case kSecPaddingPKCS1
:
387 // Create PKCS1 padding:
389 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
391 const int kMinimumPadding
= 1 + 1 + 8 + 1;
393 require_quiet(plainTextLen
<= m_size
- kMinimumPadding
, errOut
);
395 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
397 while (prefix_zeros
--)
400 size_t pad_size
= m_size
- plainTextLen
;
403 *sBytes
++ = RSA_PKCS1_PAD_ENCRYPT
;
405 ccrng_generate(ccrng_seckey
, pad_size
- 3, sBytes
);
406 // Remove zeroes from the random pad
408 const uint8_t* sEndOfPad
= sBytes
+ (pad_size
- 3);
409 while (sBytes
< sEndOfPad
)
412 *sBytes
= 0xFF; // Michael said 0xFF was good enough.
419 memcpy(sBytes
, plainText
, plainTextLen
);
421 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
424 case kSecPaddingOAEP
:
426 const struct ccdigest_info
* di
= ccsha1_di();
428 const size_t encodingOverhead
= 2 + 2 * di
->output_size
;
430 require_action(m_size
> encodingOverhead
, errOut
, result
= errSecParam
);
431 require_action_quiet(plainTextLen
<= m_size
- encodingOverhead
, errOut
, result
= errSecParam
);
433 require_noerr_action(ccrsa_oaep_encode(di
,
436 plainTextLen
, plainText
), errOut
, result
= errSecInternal
);
444 ccrsa_pub_crypt(pubkey
, s
, s
);
446 ccn_write_uint_padded(ccrsa_ctx_n(pubkey
), s
, m_size
, cipherText
);
447 *cipherTextLen
= m_size
;
449 result
= errSecSuccess
;
452 ccn_zero(ccrsa_ctx_n(pubkey
), s
);
456 static OSStatus
SecRSAPublicKeyRawDecrypt(SecKeyRef key
, SecPadding padding
,
457 const uint8_t *cipherText
, size_t cipherTextLen
, uint8_t *plainText
, size_t *plainTextLen
) {
458 OSStatus result
= errSSLCrypto
;
460 ccrsa_pub_ctx_t pubkey
;
461 pubkey
.pub
= key
->key
;
463 cc_unit s
[ccrsa_ctx_n(pubkey
)];
465 require_action_quiet(cipherText
!= NULL
, errOut
, result
= errSecParam
);
466 require_action_quiet(plainText
!= NULL
, errOut
, result
= errSecParam
);
467 require_action_quiet(plainTextLen
!= NULL
, errOut
, result
= errSecParam
);
469 ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, cipherTextLen
, cipherText
);
470 ccrsa_pub_crypt(pubkey
, s
, s
);
471 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
473 const uint8_t* sBytes
= (uint8_t*) s
;
474 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(pubkey
));
477 case kSecPaddingNone
:
478 // Skip leading zeros
479 // We return the bytes for a number and
480 // trim leading zeroes
481 while (sBytes
< sEnd
&& *sBytes
== 0x00)
485 case kSecPaddingPKCS1
:
487 // Verify and skip PKCS1 padding:
489 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
491 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
492 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
494 while (prefix_zeros
--)
495 require_quiet(*sBytes
++ == 0x00, errOut
);
497 require_quiet(*sBytes
++ == 0x00, errOut
);
498 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_ENCRYPT
, errOut
);
500 while (*sBytes
!= 0x00) {
501 require_quiet(++sBytes
< sEnd
, errOut
);
503 // Required to have at least 8 0xFFs
504 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
506 require_quiet(*sBytes
== 0x00, errOut
);
507 require_quiet(++sBytes
< sEnd
, errOut
);
511 case kSecPaddingOAEP
:
512 result
= errSecParam
;
518 require_action((sEnd
- sBytes
) <= (ptrdiff_t)*plainTextLen
, errOut
, result
= errSecParam
);
520 *plainTextLen
= sEnd
- sBytes
;
521 memcpy(plainText
, sBytes
, *plainTextLen
);
523 result
= errSecSuccess
;
526 ccn_zero(ccrsa_ctx_n(pubkey
), s
);
531 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key
) {
532 ccrsa_pub_ctx_t pubkey
;
533 pubkey
.pub
= key
->key
;
535 return ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
539 static CFDataRef
SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_pub_ctx_t pubkey
)
541 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
542 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
544 const size_t seq_size
= DERLengthOfItem(ASN1_INTEGER
, m_size
) +
545 DERLengthOfItem(ASN1_INTEGER
, e_size
);
547 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
549 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
554 CFDataSetLength(pkcs1
, result_size
);
556 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
558 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
560 DERSize itemLength
= 4;
561 DEREncodeLength(seq_size
, bytes
, &itemLength
);
564 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, &bytes
);
565 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
), e_size
, &bytes
);
570 static OSStatus
SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
572 ccrsa_pub_ctx_t pubkey
;
573 pubkey
.pub
= key
->key
;
575 CFAllocatorRef allocator
= CFGetAllocator(key
);
576 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, pubkey
);
578 if (NULL
== *serialized
)
581 return errSecSuccess
;
584 static CFDictionaryRef
SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key
) {
585 return SecKeyGeneratePublicAttributeDictionary(key
, kSecAttrKeyTypeRSA
);
588 static CFStringRef
SecRSAPublicKeyCopyDescription(SecKeyRef key
) {
590 CFStringRef keyDescription
= NULL
;
591 CFDataRef modRef
= SecKeyCopyModulus(key
);
593 ccrsa_pub_ctx_t pubkey
;
594 pubkey
.pub
= key
->key
;
596 CFStringRef modulusString
= CFDataCopyHexString(modRef
);
597 require( modulusString
, fail
);
599 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
);
602 CFReleaseSafe(modRef
);
603 CFReleaseSafe(modulusString
);
605 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
);
607 return keyDescription
;
610 SecKeyDescriptor kSecRSAPublicKeyDescriptor
= {
611 kSecKeyDescriptorVersion
,
615 SecRSAPublicKeyDestroy
,
616 NULL
, /* SecKeyRawSignMethod */
617 SecRSAPublicKeyRawVerify
,
618 SecRSAPublicKeyRawEncrypt
,
619 SecRSAPublicKeyRawDecrypt
,
620 NULL
, /* SecKeyComputeMethod */
621 SecRSAPublicKeyBlockSize
,
622 SecRSAPublicKeyCopyAttributeDictionary
,
623 SecRSAPublicKeyCopyDescription
,
625 SecRSAPublicKeyCopyPublicSerialization
,
630 /* Public Key API functions. */
631 SecKeyRef
SecKeyCreateRSAPublicKey(CFAllocatorRef allocator
,
632 const uint8_t *keyData
, CFIndex keyDataLength
,
633 SecKeyEncoding encoding
) {
634 return SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
, keyData
,
635 keyDataLength
, encoding
);
638 CFDataRef
SecKeyCopyModulus(SecKeyRef key
) {
639 ccrsa_pub_ctx_t pubkey
;
640 pubkey
.pub
= key
->key
;
642 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
644 CFAllocatorRef allocator
= CFGetAllocator(key
);
645 CFMutableDataRef modulusData
= CFDataCreateMutable(allocator
, m_size
);
647 if (modulusData
== NULL
)
650 CFDataSetLength(modulusData
, m_size
);
652 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, CFDataGetMutableBytePtr(modulusData
));
657 CFDataRef
SecKeyCopyExponent(SecKeyRef key
) {
658 ccrsa_pub_ctx_t pubkey
;
659 pubkey
.pub
= key
->key
;
661 size_t e_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
663 CFAllocatorRef allocator
= CFGetAllocator(key
);
664 CFMutableDataRef exponentData
= CFDataCreateMutable(allocator
, e_size
);
666 if (exponentData
== NULL
)
669 CFDataSetLength(exponentData
, e_size
);
671 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
), e_size
, CFDataGetMutableBytePtr(exponentData
));
683 /* Private key static functions. */
684 static void SecRSAPrivateKeyDestroy(SecKeyRef key
) {
685 /* Zero out the public key */
687 ccrsa_full_ctx_t fullkey
;
688 fullkey
.full
= key
->key
;
689 cc_clear(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey
))), fullkey
.full
);
695 static OSStatus
SecRSAPrivateKeyInit(SecKeyRef key
, const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
696 OSStatus result
= errSecParam
;
697 ccrsa_full_ctx_t fullkey
;
701 case kSecKeyEncodingBytes
: // Octets is PKCS1
702 case kSecKeyEncodingPkcs1
:
704 const uint8_t *der_end
= keyData
+ keyDataLength
;
705 size_n
= ccder_decode_rsa_priv_n(keyData
, der_end
);
706 require(size_n
!= 0, errOut
);
707 require(size_n
<= ccn_nof(kMaximumRSAKeyBits
), errOut
);
709 key
->key
= calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n
)));
710 require_action(key
->key
, errOut
, result
= errSecAllocate
);
712 fullkey
.full
= key
->key
;
713 ccrsa_ctx_n(fullkey
) = size_n
;
715 require(ccder_decode_rsa_priv(fullkey
, keyData
, der_end
), errOut
);
717 result
= errSecSuccess
;
720 case kSecGenerateKey
:
722 CFDictionaryRef parameters
= (CFDictionaryRef
) keyData
;
724 CFTypeRef ksize
= CFDictionaryGetValue(parameters
, kSecAttrKeySizeInBits
);
725 CFIndex keyLengthInBits
= getIntValue(ksize
);
727 if (keyLengthInBits
< 512 || keyLengthInBits
> kMaximumRSAKeyBits
) {
728 secwarning("Invalid or missing key size in: %@", parameters
);
729 result
= errSecKeySizeNotAllowed
;
733 size_n
= ccn_nof(keyLengthInBits
);
735 key
->key
= calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n
)));
736 require_action(key
->key
, errOut
, result
= errSecAllocate
);
738 fullkey
.full
= key
->key
;
739 ccrsa_ctx_n(fullkey
) = size_n
;
741 /* TODO: Add support for kSecPublicExponent parameter. */
742 static uint8_t e
[] = { 0x01, 0x00, 0x01 }; // Default is 65537
743 if (!ccrsa_generate_key(keyLengthInBits
, fullkey
.full
, sizeof(e
), e
, ccrng_seckey
))
744 result
= errSecSuccess
;
754 static OSStatus
SecRSAPrivateKeyRawSign(SecKeyRef key
, SecPadding padding
,
755 const uint8_t *dataToSign
, size_t dataToSignLen
,
756 uint8_t *sig
, size_t *sigLen
) {
758 OSStatus result
= errSecParam
;
760 ccrsa_full_ctx_t fullkey
;
761 fullkey
.full
= key
->key
;
763 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
764 cc_unit s
[ccrsa_ctx_n(fullkey
)];
766 uint8_t* sBytes
= (uint8_t*) s
;
768 require(sigLen
, errOut
);
769 require(*sigLen
>= m_size
, errOut
);
772 case kSecPaddingNone
:
773 // We'll allow modulus size assuming input is smaller than modulus
774 require_quiet(dataToSignLen
<= m_size
, errOut
);
775 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey
), s
, dataToSignLen
, dataToSign
), errOut
);
776 require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey
), s
, ccrsa_ctx_m(fullkey
)) < 0, errOut
);
779 case kSecPaddingPKCS1
:
781 // Create PKCS1 padding:
783 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
785 const int kMinimumPadding
= 1 + 1 + 8 + 1;
787 require_quiet(dataToSignLen
<= m_size
- kMinimumPadding
, errOut
);
789 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(fullkey
)) - m_size
;
791 while (prefix_zeros
--)
794 size_t pad_size
= m_size
- dataToSignLen
;
797 *sBytes
++ = RSA_PKCS1_PAD_SIGN
;
800 for(ff_size
= pad_size
- 3; ff_size
> 0; --ff_size
)
805 // Get the user data into s looking like a ccn.
806 memcpy(sBytes
, dataToSign
, dataToSignLen
);
807 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
811 case kSecPaddingOAEP
:
812 result
= errSecParam
;
817 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey
), s
, s
);
819 // Pad with leading zeros to fit in modulus size
820 ccn_write_uint_padded(ccrsa_ctx_n(fullkey
), s
, m_size
, sig
);
823 result
= errSecSuccess
;
826 ccn_zero(ccrsa_ctx_n(fullkey
), s
);
830 static OSStatus
SecRSAPrivateKeyRawDecrypt(SecKeyRef key
, SecPadding padding
,
831 const uint8_t *cipherText
, size_t cipherTextLen
,
832 uint8_t *plainText
, size_t *plainTextLen
) {
833 OSStatus result
= errSSLCrypto
;
835 ccrsa_full_ctx_t fullkey
;
836 fullkey
.full
= key
->key
;
838 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
840 cc_unit s
[ccrsa_ctx_n(fullkey
)];
841 uint8_t recoveredData
[ccn_sizeof_n(ccrsa_ctx_n(fullkey
))];
843 ccn_read_uint(ccrsa_ctx_n(fullkey
), s
, cipherTextLen
, cipherText
);
844 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey
), s
, s
);
846 const uint8_t* sBytes
= (uint8_t*) s
;
847 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(fullkey
));
849 require(plainTextLen
, errOut
);
852 case kSecPaddingNone
:
853 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
854 // Skip Zeros since our contract is to do so.
855 while (sBytes
< sEnd
&& *sBytes
== 0x00)
859 case kSecPaddingPKCS1
:
861 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
862 // Verify and skip PKCS1 padding:
864 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
867 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(fullkey
)) - m_size
;
869 while (prefix_zeros
--)
870 require_quiet(*sBytes
++ == 0x00, errOut
);
872 require_quiet(*sBytes
++ == 0x00, errOut
);
873 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_ENCRYPT
, errOut
);
875 while (*sBytes
!= 0x00) {
876 require_quiet(++sBytes
< sEnd
, errOut
);
878 // Required to have at least 8 non-zeros
879 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
881 require_quiet(*sBytes
== 0x00, errOut
);
882 require_quiet(++sBytes
< sEnd
, errOut
);
885 case kSecPaddingOAEP
:
887 size_t length
= sizeof(recoveredData
);
889 require_noerr_quiet(ccrsa_oaep_decode(ccsha1_di(),
890 &length
, recoveredData
,
891 ccn_write_uint_size(ccrsa_ctx_n(fullkey
),ccrsa_ctx_m(fullkey
)), s
894 sBytes
= recoveredData
;
895 sEnd
= recoveredData
+ length
;
902 require((sEnd
- sBytes
) <= (ptrdiff_t)*plainTextLen
, errOut
);
903 *plainTextLen
= sEnd
- sBytes
;
904 memcpy(plainText
, sBytes
, *plainTextLen
);
906 result
= errSecSuccess
;
909 bzero(recoveredData
, sizeof(recoveredData
));
910 ccn_zero(ccrsa_ctx_n(fullkey
), s
);
915 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key
) {
916 ccrsa_full_ctx_t fullkey
;
917 fullkey
.full
= key
->key
;
919 return ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
922 static CFDataRef
SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_full_ctx_t fullkey
)
924 ccrsa_priv_ctx_t privkey
= ccrsa_ctx_private(fullkey
);
926 const cc_size np
= cczp_n(ccrsa_ctx_private_zp(privkey
));
927 const cc_size nq
= cczp_n(ccrsa_ctx_private_zq(privkey
));
929 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
930 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_e(fullkey
));
931 size_t d_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
));
933 size_t p_size
= ccn_write_int_size(np
, cczp_prime(ccrsa_ctx_private_zp(privkey
)));
934 size_t q_size
= ccn_write_int_size(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)));
936 size_t dp_size
= ccn_write_int_size(np
, ccrsa_ctx_private_dp(privkey
));
937 size_t dq_size
= ccn_write_int_size(nq
, ccrsa_ctx_private_dq(privkey
));
939 size_t qinv_size
= ccn_write_int_size(np
, ccrsa_ctx_private_qinv(privkey
));
941 const size_t seq_size
= 3 +
942 DERLengthOfItem(ASN1_INTEGER
, m_size
) +
943 DERLengthOfItem(ASN1_INTEGER
, e_size
) +
944 DERLengthOfItem(ASN1_INTEGER
, d_size
) +
945 DERLengthOfItem(ASN1_INTEGER
, p_size
) +
946 DERLengthOfItem(ASN1_INTEGER
, q_size
) +
947 DERLengthOfItem(ASN1_INTEGER
, dp_size
) +
948 DERLengthOfItem(ASN1_INTEGER
, dq_size
) +
949 DERLengthOfItem(ASN1_INTEGER
, qinv_size
);
951 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
953 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
958 CFDataSetLength(pkcs1
, result_size
);
960 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
962 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
964 DERSize itemLength
= 4;
965 DEREncodeLength(seq_size
, bytes
, &itemLength
);
968 *bytes
++ = ASN1_INTEGER
;
972 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
), m_size
, &bytes
);
973 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_e(fullkey
), e_size
, &bytes
);
974 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
), d_size
, &bytes
);
976 ccasn_encode_int(np
, cczp_prime(ccrsa_ctx_private_zp(privkey
)), p_size
, &bytes
);
977 ccasn_encode_int(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)), q_size
, &bytes
);
978 ccasn_encode_int(np
, ccrsa_ctx_private_dp(privkey
), dp_size
, &bytes
);
979 ccasn_encode_int(nq
, ccrsa_ctx_private_dq(privkey
), dq_size
, &bytes
);
980 ccasn_encode_int(np
, ccrsa_ctx_private_qinv(privkey
), qinv_size
, &bytes
);
985 static CFDataRef
SecRSAPrivateKeyCopyPKCS1(SecKeyRef key
)
987 ccrsa_full_ctx_t fullkey
;
988 fullkey
.full
= key
->key
;
990 CFAllocatorRef allocator
= CFGetAllocator(key
);
991 return SecRSAPrivateKeyCreatePKCS1(allocator
, fullkey
);
994 static OSStatus
SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
996 ccrsa_full_ctx_t fullkey
;
997 fullkey
.full
= key
->key
;
999 CFAllocatorRef allocator
= CFGetAllocator(key
);
1000 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, fullkey
);
1002 if (NULL
== *serialized
)
1003 return errSecDecode
;
1005 return errSecSuccess
;
1009 static CFDictionaryRef
SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key
) {
1010 CFDictionaryRef dict
= NULL
;
1011 CFDataRef fullKeyBlob
= NULL
;
1013 /* PKCS1 encode the key pair. */
1014 fullKeyBlob
= SecRSAPrivateKeyCopyPKCS1(key
);
1015 require(fullKeyBlob
, errOut
);
1017 dict
= SecKeyGeneratePrivateAttributeDictionary(key
, kSecAttrKeyTypeRSA
, fullKeyBlob
);
1020 CFReleaseSafe(fullKeyBlob
);
1025 static CFStringRef
SecRSAPrivateKeyCopyDescription(SecKeyRef key
){
1027 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
);
1030 SecKeyDescriptor kSecRSAPrivateKeyDescriptor
= {
1031 kSecKeyDescriptorVersion
,
1034 SecRSAPrivateKeyInit
,
1035 SecRSAPrivateKeyDestroy
,
1036 SecRSAPrivateKeyRawSign
,
1037 NULL
, /* SecKeyRawVerifyMethod */
1038 NULL
, /* SecKeyEncryptMethod */
1039 SecRSAPrivateKeyRawDecrypt
,
1040 NULL
, /* SecKeyComputeMethod */
1041 SecRSAPrivateKeyBlockSize
,
1042 SecRSAPrivateKeyCopyAttributeDictionary
,
1043 SecRSAPrivateKeyCopyDescription
,
1045 SecRSAPrivateKeyCopyPublicSerialization
,
1050 /* Private Key API functions. */
1051 SecKeyRef
SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator
,
1052 const uint8_t *keyData
, CFIndex keyDataLength
,
1053 SecKeyEncoding encoding
) {
1054 return SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
, keyData
,
1055 keyDataLength
, encoding
);
1059 OSStatus
SecRSAKeyGeneratePair(CFDictionaryRef parameters
,
1060 SecKeyRef
*rsaPublicKey
, SecKeyRef
*rsaPrivateKey
) {
1061 OSStatus status
= errSecParam
;
1063 CFAllocatorRef allocator
= NULL
; /* @@@ get from parameters. */
1065 SecKeyRef pubKey
= NULL
;
1066 SecKeyRef privKey
= SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
,
1067 (const void*) parameters
, 0, kSecGenerateKey
);
1069 require(privKey
, errOut
);
1071 /* Create SecKeyRef's from the pkcs1 encoded keys. */
1072 pubKey
= SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
,
1073 privKey
->key
, 0, kSecExtractPublicFromPrivate
);
1075 require(pubKey
, errOut
);
1078 *rsaPublicKey
= pubKey
;
1081 if (rsaPrivateKey
) {
1082 *rsaPrivateKey
= privKey
;
1086 status
= errSecSuccess
;
1089 CFReleaseSafe(pubKey
);
1090 CFReleaseSafe(privKey
);