2 * Copyright (c) 2006-2010 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 <security_utilities/debugging.h>
44 #include "SecItemPriv.h"
45 #include <Security/SecInternal.h>
47 #include <corecrypto/ccn.h>
48 #include <corecrypto/ccrsa.h>
49 #include <corecrypto/ccsha1.h>
51 #include <libDER/asn1Types.h>
52 #include <libDER/DER_Keys.h>
53 #include <libDER/DER_Encode.h>
55 #include <CommonCrypto/CommonDigest.h>
57 #include <corecrypto/ccrsa_priv.h>
62 #define kMaximumRSAKeyBits 4096
63 #define kMaximumRSAKeyBytes ccn_sizeof(kMaximumRSAKeyBits)
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, ",
77 (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 */
133 ccrsa_pub_ctx_t pubkey
;
134 pubkey
.pub
= key
->key
;
135 cc_zero(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey
))), pubkey
.pub
);
138 #define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
141 // pubkey is initilaized with an n which is the maximum it can hold
142 // We set the n to its correct value given m.
144 static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey
,
145 size_t m_size
, const uint8_t* m
,
146 size_t e_size
, const uint8_t* e
)
148 cc_skip_zeros(m_size
, m
);
150 cc_size nm
= ccn_nof_size(m_size
);
151 if (nm
> ccrsa_ctx_n(pubkey
))
154 ccrsa_ctx_n(pubkey
) = nm
;
156 ccn_read_uint(nm
, ccrsa_ctx_m(pubkey
), m_size
, m
);
157 cczp_init(ccrsa_ctx_zm(pubkey
));
159 return ccn_read_uint(nm
, ccrsa_ctx_e(pubkey
), e_size
, e
);
163 static OSStatus
ccrsa_pub_decode(ccrsa_pub_ctx_t pubkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
165 OSStatus result
= errSecParam
;
167 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
168 DERRSAPubKeyPKCS1 decodedKey
;
170 require_noerr_action(DERParseSequence(&keyItem
,
171 DERNumRSAPubKeyPKCS1ItemSpecs
, DERRSAPubKeyPKCS1ItemSpecs
,
172 &decodedKey
, sizeof(decodedKey
)),
173 errOut
, result
= errSecDecode
);
175 require_noerr(ccrsa_pub_init(pubkey
,
176 decodedKey
.modulus
.length
, decodedKey
.modulus
.data
,
177 decodedKey
.pubExponent
.length
, decodedKey
.pubExponent
.data
),
180 result
= errSecSuccess
;
186 static OSStatus
ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
188 OSStatus result
= errSecParam
;
190 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
191 DERRSAPubKeyApple decodedKey
;
193 require_noerr_action(DERParseSequence(&keyItem
,
194 DERNumRSAPubKeyAppleItemSpecs
, DERRSAPubKeyAppleItemSpecs
,
195 &decodedKey
, sizeof(decodedKey
)),
196 errOut
, result
= errSecDecode
);
198 // We could honor the recipricol, but we don't think this is used enough to care.
199 // Don't bother exploding the below function to try to handle this case, it computes.
201 require_noerr(ccrsa_pub_init(pubkey
,
202 decodedKey
.modulus
.length
, decodedKey
.modulus
.data
,
203 decodedKey
.pubExponent
.length
, decodedKey
.pubExponent
.data
),
206 result
= errSecSuccess
;
213 static void ccasn_encode_int(cc_size n
, const cc_unit
*s
, size_t s_size
, uint8_t **buffer
)
215 **buffer
= ASN1_INTEGER
;
218 DERSize itemLength
= 4;
219 DEREncodeLength(s_size
, *buffer
, &itemLength
);
220 *buffer
+= itemLength
;
222 ccn_write_int(n
, s
, s_size
, *buffer
);
228 static OSStatus
SecRSAPublicKeyInit(SecKeyRef key
,
229 const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
231 OSStatus result
= errSecParam
;
233 ccrsa_pub_ctx_t pubkey
;
234 pubkey
.pub
= key
->key
;
236 // Set maximum size for parsers
237 ccrsa_ctx_n(pubkey
) = ccn_nof(kMaximumRSAKeyBits
);
240 case kSecKeyEncodingBytes
: // Octets is PKCS1
241 case kSecKeyEncodingPkcs1
:
242 result
= ccrsa_pub_decode(pubkey
, keyDataLength
, keyData
);
244 case kSecKeyEncodingApplePkcs1
:
245 result
= ccrsa_pub_decode_apple(pubkey
, keyDataLength
, keyData
);
247 case kSecKeyEncodingRSAPublicParams
:
249 SecRSAPublicKeyParams
*params
= (SecRSAPublicKeyParams
*)keyData
;
251 require_noerr(ccrsa_pub_init(pubkey
,
252 params
->modulusLength
, params
->modulus
,
253 params
->exponentLength
, params
->exponent
), errOut
);
255 result
= errSecSuccess
;
258 case kSecExtractPublicFromPrivate
:
260 ccrsa_full_ctx_t fullKey
;
261 fullKey
.full
= (ccrsa_full_ctx
*) keyData
;
263 cc_size fullKeyN
= ccrsa_ctx_n(fullKey
);
264 require(fullKeyN
<= ccrsa_ctx_n(pubkey
), errOut
);
265 memcpy(pubkey
.pub
, ccrsa_ctx_public(fullKey
).pub
, ccrsa_pub_ctx_size(ccn_sizeof_n(fullKeyN
)));
266 result
= errSecSuccess
;
277 static OSStatus
SecRSAPublicKeyRawVerify(SecKeyRef key
, SecPadding padding
,
278 const uint8_t *signedData
, size_t signedDataLen
,
279 const uint8_t *sig
, size_t sigLen
) {
280 OSStatus result
= errSSLCrypto
;
282 ccrsa_pub_ctx_t pubkey
;
283 pubkey
.pub
= key
->key
;
285 cc_unit s
[ccrsa_ctx_n(pubkey
)];
287 ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, sigLen
, sig
);
288 ccrsa_pub_crypt(pubkey
, s
, s
);
289 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
291 const uint8_t* sBytes
= (uint8_t*) s
;
292 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(pubkey
));
295 case kSecPaddingNone
:
296 // Skip leading zeros as long as s is bigger than signedData.
297 while (((ptrdiff_t)signedDataLen
< (sEnd
- sBytes
)) && (*sBytes
== 0))
301 case kSecPaddingPKCS1
:
303 // Verify and skip PKCS1 padding:
305 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
307 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
308 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
310 while (prefix_zeros
--)
311 require_quiet(*sBytes
++ == 0x00, errOut
);
313 require_quiet(*sBytes
++ == 0x00, errOut
);
314 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_SIGN
, errOut
);
316 while (*sBytes
== 0xFF) {
317 require_quiet(++sBytes
< sEnd
, errOut
);
319 // Required to have at least 8 0xFFs
320 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
322 require_quiet(*sBytes
== 0x00, errOut
);
323 require_quiet(++sBytes
< sEnd
, errOut
);
326 case kSecPaddingOAEP
:
327 result
= errSecParam
;
331 result
= errSecUnimplemented
;
336 require_quiet((sEnd
- sBytes
) == (ptrdiff_t)signedDataLen
, errOut
);
337 require_quiet(memcmp(sBytes
, signedData
, signedDataLen
) == 0, errOut
);
339 result
= errSecSuccess
;
342 cc_zero(ccrsa_ctx_n(pubkey
), s
);
347 static OSStatus
SecRSAPublicKeyRawEncrypt(SecKeyRef key
, SecPadding padding
,
348 const uint8_t *plainText
, size_t plainTextLen
,
349 uint8_t *cipherText
, size_t *cipherTextLen
) {
350 OSStatus result
= errSecParam
;
351 ccrsa_pub_ctx_t pubkey
;
352 pubkey
.pub
= key
->key
;
354 cc_unit s
[ccrsa_ctx_n(pubkey
)];
355 const size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
357 require(cipherTextLen
, errOut
);
358 require(*cipherTextLen
>= m_size
, errOut
);
360 uint8_t* sBytes
= (uint8_t*) s
;
363 case kSecPaddingNone
:
364 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, plainTextLen
, plainText
), errOut
);
365 require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey
), s
, ccrsa_ctx_m(pubkey
)) < 0, errOut
);
368 case kSecPaddingPKCS1
:
370 // Create PKCS1 padding:
372 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
374 const int kMinimumPadding
= 1 + 1 + 8 + 1;
376 require_quiet(plainTextLen
< m_size
- kMinimumPadding
, errOut
);
378 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
380 while (prefix_zeros
--)
383 size_t pad_size
= m_size
- plainTextLen
;
386 *sBytes
++ = RSA_PKCS1_PAD_ENCRYPT
;
388 ccrng_generate(ccrng_seckey
, pad_size
- 3, sBytes
);
389 // Remove zeroes from the random pad
391 const uint8_t* sEndOfPad
= sBytes
+ (pad_size
- 3);
392 while (sBytes
< sEndOfPad
)
395 *sBytes
= 0xFF; // Michael said 0xFF was good enough.
402 memcpy(sBytes
, plainText
, plainTextLen
);
404 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
407 case kSecPaddingOAEP
:
409 const struct ccdigest_info
* di
= ccsha1_di();
411 const size_t encodingOverhead
= 2 + 2 * di
->output_size
;
413 require_action(m_size
> encodingOverhead
, errOut
, result
= errSecParam
);
414 require_action_quiet(plainTextLen
< m_size
- encodingOverhead
, errOut
, result
= errSSLCrypto
);
416 require_noerr_action(ccrsa_oaep_encode(di
,
419 plainTextLen
, plainText
), errOut
, result
= errSecInternal
);
427 ccrsa_pub_crypt(pubkey
, s
, s
);
429 ccn_write_uint_padded(ccrsa_ctx_n(pubkey
), s
, m_size
, cipherText
);
430 *cipherTextLen
= m_size
;
432 result
= errSecSuccess
;
435 ccn_zero(ccrsa_ctx_n(pubkey
), s
);
439 static OSStatus
SecRSAPublicKeyRawDecrypt(SecKeyRef key
, SecPadding padding
,
440 const uint8_t *cipherText
, size_t cipherTextLen
, uint8_t *plainText
, size_t *plainTextLen
) {
441 OSStatus result
= errSSLCrypto
;
443 ccrsa_pub_ctx_t pubkey
;
444 pubkey
.pub
= key
->key
;
446 cc_unit s
[ccrsa_ctx_n(pubkey
)];
448 require_action_quiet(cipherText
!= NULL
, errOut
, result
= errSecParam
);
449 require_action_quiet(plainText
!= NULL
, errOut
, result
= errSecParam
);
450 require_action_quiet(plainTextLen
!= NULL
, errOut
, result
= errSecParam
);
452 ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, cipherTextLen
, cipherText
);
453 ccrsa_pub_crypt(pubkey
, s
, s
);
454 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
456 const uint8_t* sBytes
= (uint8_t*) s
;
457 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(pubkey
));
460 case kSecPaddingNone
:
461 // Skip leading zeros
462 // We return the bytes for a number and
463 // trim leading zeroes
464 while (sBytes
< sEnd
&& *sBytes
== 0x00)
468 case kSecPaddingPKCS1
:
470 // Verify and skip PKCS1 padding:
472 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
474 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
475 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
477 while (prefix_zeros
--)
478 require_quiet(*sBytes
++ == 0x00, errOut
);
480 require_quiet(*sBytes
++ == 0x00, errOut
);
481 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_ENCRYPT
, errOut
);
483 while (*sBytes
!= 0x00) {
484 require_quiet(++sBytes
< sEnd
, errOut
);
486 // Required to have at least 8 0xFFs
487 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
489 require_quiet(*sBytes
== 0x00, errOut
);
490 require_quiet(++sBytes
< sEnd
, errOut
);
494 case kSecPaddingOAEP
:
495 result
= errSecParam
;
501 require_action((sEnd
- sBytes
) <= (ptrdiff_t)*plainTextLen
, errOut
, result
= errSecParam
);
503 *plainTextLen
= sEnd
- sBytes
;
504 memcpy(plainText
, sBytes
, *plainTextLen
);
506 result
= errSecSuccess
;
509 ccn_zero(ccrsa_ctx_n(pubkey
), s
);
514 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key
) {
515 ccrsa_pub_ctx_t pubkey
;
516 pubkey
.pub
= key
->key
;
518 return ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
522 static CFDataRef
SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_pub_ctx_t pubkey
)
524 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
525 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
527 const size_t seq_size
= DERLengthOfItem(ASN1_INTEGER
, m_size
) +
528 DERLengthOfItem(ASN1_INTEGER
, e_size
);
530 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
532 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
537 CFDataSetLength(pkcs1
, result_size
);
539 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
541 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
543 DERSize itemLength
= 4;
544 DEREncodeLength(seq_size
, bytes
, &itemLength
);
547 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, &bytes
);
548 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
), e_size
, &bytes
);
553 static OSStatus
SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
555 ccrsa_pub_ctx_t pubkey
;
556 pubkey
.pub
= key
->key
;
558 CFAllocatorRef allocator
= CFGetAllocator(key
);
559 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, pubkey
);
561 if (NULL
== *serialized
)
564 return errSecSuccess
;
567 static CFDictionaryRef
SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key
) {
568 return SecKeyGeneratePublicAttributeDictionary(key
, kSecAttrKeyTypeRSA
);
571 SecKeyDescriptor kSecRSAPublicKeyDescriptor
= {
572 kSecKeyDescriptorVersion
,
574 ccrsa_pub_ctx_size(kMaximumRSAKeyBytes
), /* extraBytes */
576 SecRSAPublicKeyDestroy
,
577 NULL
, /* SecKeyRawSignMethod */
578 SecRSAPublicKeyRawVerify
,
579 SecRSAPublicKeyRawEncrypt
,
580 SecRSAPublicKeyRawDecrypt
,
581 NULL
, /* SecKeyComputeMethod */
582 SecRSAPublicKeyBlockSize
,
583 SecRSAPublicKeyCopyAttributeDictionary
,
585 SecRSAPublicKeyCopyPublicSerialization
,
588 /* Public Key API functions. */
589 SecKeyRef
SecKeyCreateRSAPublicKey(CFAllocatorRef allocator
,
590 const uint8_t *keyData
, CFIndex keyDataLength
,
591 SecKeyEncoding encoding
) {
592 return SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
, keyData
,
593 keyDataLength
, encoding
);
596 CFDataRef
SecKeyCopyModulus(SecKeyRef key
) {
597 ccrsa_pub_ctx_t pubkey
;
598 pubkey
.pub
= key
->key
;
600 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
602 CFAllocatorRef allocator
= CFGetAllocator(key
);
603 CFMutableDataRef modulusData
= CFDataCreateMutable(allocator
, m_size
);
605 if (modulusData
== NULL
)
608 CFDataSetLength(modulusData
, m_size
);
610 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, CFDataGetMutableBytePtr(modulusData
));
615 CFDataRef
SecKeyCopyExponent(SecKeyRef key
) {
616 ccrsa_pub_ctx_t pubkey
;
617 pubkey
.pub
= key
->key
;
619 size_t e_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
621 CFAllocatorRef allocator
= CFGetAllocator(key
);
622 CFMutableDataRef exponentData
= CFDataCreateMutable(allocator
, e_size
);
624 if (exponentData
== NULL
)
627 CFDataSetLength(exponentData
, e_size
);
629 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), e_size
, CFDataGetMutableBytePtr(exponentData
));
641 /* Private key static functions. */
642 static void SecRSAPrivateKeyDestroy(SecKeyRef key
) {
643 /* Zero out the public key */
644 ccrsa_full_ctx_t fullkey
;
645 fullkey
.full
= key
->key
;
646 cc_zero(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey
))), fullkey
.full
);
649 static int ccrsa_priv_init(ccrsa_priv_ctx_t privkey
,
650 size_t p_size
, const uint8_t* p
,
651 size_t q_size
, const uint8_t* q
,
652 size_t dp_size
, const uint8_t* dp
,
653 size_t dq_size
, const uint8_t* dq
,
654 size_t qinv_size
, const uint8_t* qinv
)
658 const cc_size np
= cczp_n(ccrsa_ctx_private_zp(privkey
));
659 cc_size nq
= cczp_n(ccrsa_ctx_private_zq(privkey
));
661 if (ccn_read_uint(np
, CCZP_PRIME(ccrsa_ctx_private_zp(privkey
)), p_size
, p
))
663 cczp_init(ccrsa_ctx_private_zp(privkey
));
664 if (ccn_read_uint(np
, ccrsa_ctx_private_dp(privkey
), dp_size
, dp
))
666 if (ccn_read_uint(np
, ccrsa_ctx_private_qinv(privkey
), qinv_size
, qinv
))
669 if (ccn_read_uint(nq
, CCZP_PRIME(ccrsa_ctx_private_zq(privkey
)), q_size
, q
))
672 nq
= ccn_n(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)));
673 CCZP_N(ccrsa_ctx_private_zq(privkey
)) = nq
;
675 cczp_init(ccrsa_ctx_private_zq(privkey
));
676 if (ccn_read_uint(nq
, ccrsa_ctx_private_dq(privkey
), dq_size
, dq
))
686 static OSStatus
ccrsa_full_decode(ccrsa_full_ctx_t fullkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
688 OSStatus result
= errSecParam
;
690 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
691 DERRSAKeyPair decodedKey
;
693 require_noerr_action(DERParseSequence(&keyItem
,
694 DERNumRSAKeyPairItemSpecs
, DERRSAKeyPairItemSpecs
,
695 &decodedKey
, sizeof(decodedKey
)),
696 errOut
, result
= errSecDecode
);
698 require_noerr(ccrsa_pub_init(fullkey
,
699 decodedKey
.n
.length
, decodedKey
.n
.data
,
700 decodedKey
.e
.length
, decodedKey
.e
.data
),
702 ccn_read_uint(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
),
703 decodedKey
.d
.length
, decodedKey
.d
.data
);
705 ccrsa_priv_ctx_t privkey
= ccrsa_ctx_private(fullkey
);
706 CCZP_N(ccrsa_ctx_private_zp(privkey
)) = ccn_nof((ccn_bitsof_n(ccrsa_ctx_n(fullkey
)) / 2) + 1);
707 CCZP_N(ccrsa_ctx_private_zq(privkey
)) = cczp_n(ccrsa_ctx_private_zp(privkey
));
709 // TODO: Actually remember decodedKey.d.
711 require_noerr(ccrsa_priv_init(privkey
,
712 decodedKey
.p
.length
, decodedKey
.p
.data
,
713 decodedKey
.q
.length
, decodedKey
.q
.data
,
714 decodedKey
.dp
.length
, decodedKey
.dp
.data
,
715 decodedKey
.dq
.length
, decodedKey
.dq
.data
,
716 decodedKey
.qInv
.length
, decodedKey
.qInv
.data
),
720 result
= errSecSuccess
;
726 static OSStatus
SecRSAPrivateKeyInit(SecKeyRef key
,
727 const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
728 OSStatus result
= errSecParam
;
730 ccrsa_full_ctx_t fullkey
;
731 fullkey
.full
= key
->key
;
733 // Set maximum size for parsers
734 ccrsa_ctx_n(fullkey
) = ccn_nof(kMaximumRSAKeyBits
);
737 case kSecKeyEncodingBytes
: // Octets is PKCS1
738 case kSecKeyEncodingPkcs1
:
739 result
= ccrsa_full_decode(fullkey
, keyDataLength
, keyData
);
741 case kSecGenerateKey
:
743 CFDictionaryRef parameters
= (CFDictionaryRef
) keyData
;
745 CFTypeRef ksize
= CFDictionaryGetValue(parameters
, kSecAttrKeySizeInBits
);
746 CFIndex keyLengthInBits
= getIntValue(ksize
);
748 if (keyLengthInBits
< 256 || keyLengthInBits
> kMaximumRSAKeyBits
) {
749 secwarning("Invalid or missing key size in: %@", parameters
);
750 return errSecKeySizeNotAllowed
;
753 /* TODO: Add support for kSecPublicExponent parameter. */
754 static uint8_t e
[] = { 0x01, 0x00, 0x01 }; // Default is 65537
755 if (!ccrsa_generate_key(keyLengthInBits
, fullkey
.full
, sizeof(e
), e
, ccrng_seckey
))
756 result
= errSecSuccess
;
766 static OSStatus
SecRSAPrivateKeyRawSign(SecKeyRef key
, SecPadding padding
,
767 const uint8_t *dataToSign
, size_t dataToSignLen
,
768 uint8_t *sig
, size_t *sigLen
) {
770 OSStatus result
= errSecParam
;
772 ccrsa_full_ctx_t fullkey
;
773 fullkey
.full
= key
->key
;
775 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
776 cc_unit s
[ccrsa_ctx_n(fullkey
)];
778 uint8_t* sBytes
= (uint8_t*) s
;
780 require(sigLen
, errOut
);
781 require(*sigLen
>= m_size
, errOut
);
784 case kSecPaddingNone
:
785 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey
), s
, dataToSignLen
, dataToSign
), errOut
);
786 require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey
), s
, ccrsa_ctx_m(fullkey
)) < 0, errOut
);
789 case kSecPaddingPKCS1
:
791 // Create PKCS1 padding:
793 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
795 const int kMinimumPadding
= 1 + 1 + 8 + 1;
797 require(dataToSignLen
< m_size
- kMinimumPadding
, errOut
);
799 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(fullkey
)) - m_size
;
801 while (prefix_zeros
--)
804 size_t pad_size
= m_size
- dataToSignLen
;
807 *sBytes
++ = RSA_PKCS1_PAD_SIGN
;
810 for(ff_size
= pad_size
- 3; ff_size
> 0; --ff_size
)
815 // Get the user data into s looking like a ccn.
816 memcpy(sBytes
, dataToSign
, dataToSignLen
);
817 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
821 case kSecPaddingOAEP
:
822 result
= errSecParam
;
827 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey
), s
, s
);
829 // Pad with leading zeros to fit in modulus size
830 ccn_write_uint_padded(ccrsa_ctx_n(fullkey
), s
, m_size
, sig
);
833 result
= errSecSuccess
;
836 ccn_zero(ccrsa_ctx_n(fullkey
), s
);
840 static OSStatus
SecRSAPrivateKeyRawDecrypt(SecKeyRef key
, SecPadding padding
,
841 const uint8_t *cipherText
, size_t cipherTextLen
,
842 uint8_t *plainText
, size_t *plainTextLen
) {
843 OSStatus result
= errSSLCrypto
;
845 ccrsa_full_ctx_t fullkey
;
846 fullkey
.full
= key
->key
;
848 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
850 cc_unit s
[ccrsa_ctx_n(fullkey
)];
851 uint8_t recoveredData
[ccn_sizeof_n(ccrsa_ctx_n(fullkey
))];
853 ccn_read_uint(ccrsa_ctx_n(fullkey
), s
, cipherTextLen
, cipherText
);
854 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey
), s
, s
);
856 const uint8_t* sBytes
= (uint8_t*) s
;
857 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(fullkey
));
859 require(plainTextLen
, errOut
);
862 case kSecPaddingNone
:
863 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
864 // Skip Zeros since our contract is to do so.
865 while (sBytes
< sEnd
&& *sBytes
== 0x00)
869 case kSecPaddingPKCS1
:
871 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
872 // Verify and skip PKCS1 padding:
874 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
877 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(fullkey
)) - m_size
;
879 while (prefix_zeros
--)
880 require_quiet(*sBytes
++ == 0x00, errOut
);
882 require_quiet(*sBytes
++ == 0x00, errOut
);
883 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_ENCRYPT
, errOut
);
885 while (*sBytes
!= 0x00) {
886 require_quiet(++sBytes
< sEnd
, errOut
);
888 // Required to have at least 8 non-zeros
889 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
891 require_quiet(*sBytes
== 0x00, errOut
);
892 require_quiet(++sBytes
< sEnd
, errOut
);
895 case kSecPaddingOAEP
:
897 size_t length
= sizeof(recoveredData
);
899 require_noerr_quiet(ccrsa_oaep_decode(ccsha1_di(),
900 ccn_write_uint_size(ccrsa_ctx_n(fullkey
),ccrsa_ctx_m(fullkey
)), s
,
901 &length
, recoveredData
), errOut
);
903 sBytes
= recoveredData
;
904 sEnd
= recoveredData
+ length
;
911 require((sEnd
- sBytes
) <= (ptrdiff_t)*plainTextLen
, errOut
);
912 *plainTextLen
= sEnd
- sBytes
;
913 memcpy(plainText
, sBytes
, *plainTextLen
);
915 result
= errSecSuccess
;
918 bzero(recoveredData
, sizeof(recoveredData
));
919 ccn_zero(ccrsa_ctx_n(fullkey
), s
);
924 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key
) {
925 ccrsa_full_ctx_t fullkey
;
926 fullkey
.full
= key
->key
;
928 return ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
931 static CFDataRef
SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_full_ctx_t fullkey
)
933 ccrsa_priv_ctx_t privkey
= ccrsa_ctx_private(fullkey
);
935 const cc_size np
= cczp_n(ccrsa_ctx_private_zp(privkey
));
936 const cc_size nq
= cczp_n(ccrsa_ctx_private_zq(privkey
));
938 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
939 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_e(fullkey
));
940 size_t d_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
));
942 size_t p_size
= ccn_write_int_size(np
, cczp_prime(ccrsa_ctx_private_zp(privkey
)));
943 size_t q_size
= ccn_write_int_size(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)));
945 size_t dp_size
= ccn_write_int_size(np
, ccrsa_ctx_private_dp(privkey
));
946 size_t dq_size
= ccn_write_int_size(nq
, ccrsa_ctx_private_dq(privkey
));
948 size_t qinv_size
= ccn_write_int_size(np
, ccrsa_ctx_private_qinv(privkey
));
950 const size_t seq_size
= 3 +
951 DERLengthOfItem(ASN1_INTEGER
, m_size
) +
952 DERLengthOfItem(ASN1_INTEGER
, e_size
) +
953 DERLengthOfItem(ASN1_INTEGER
, d_size
) +
954 DERLengthOfItem(ASN1_INTEGER
, p_size
) +
955 DERLengthOfItem(ASN1_INTEGER
, q_size
) +
956 DERLengthOfItem(ASN1_INTEGER
, dp_size
) +
957 DERLengthOfItem(ASN1_INTEGER
, dq_size
) +
958 DERLengthOfItem(ASN1_INTEGER
, qinv_size
);
960 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
962 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
967 CFDataSetLength(pkcs1
, result_size
);
969 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
971 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
973 DERSize itemLength
= 4;
974 DEREncodeLength(seq_size
, bytes
, &itemLength
);
977 *bytes
++ = ASN1_INTEGER
;
981 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
), m_size
, &bytes
);
982 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_e(fullkey
), e_size
, &bytes
);
983 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
), d_size
, &bytes
);
985 ccasn_encode_int(np
, cczp_prime(ccrsa_ctx_private_zp(privkey
)), p_size
, &bytes
);
986 ccasn_encode_int(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)), q_size
, &bytes
);
987 ccasn_encode_int(np
, ccrsa_ctx_private_dp(privkey
), dp_size
, &bytes
);
988 ccasn_encode_int(nq
, ccrsa_ctx_private_dq(privkey
), dq_size
, &bytes
);
989 ccasn_encode_int(np
, ccrsa_ctx_private_qinv(privkey
), qinv_size
, &bytes
);
994 static CFDataRef
SecRSAPrivateKeyCopyPKCS1(SecKeyRef key
)
996 ccrsa_full_ctx_t fullkey
;
997 fullkey
.full
= key
->key
;
999 CFAllocatorRef allocator
= CFGetAllocator(key
);
1000 return SecRSAPrivateKeyCreatePKCS1(allocator
, fullkey
);
1003 static OSStatus
SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
1005 ccrsa_full_ctx_t fullkey
;
1006 fullkey
.full
= key
->key
;
1008 CFAllocatorRef allocator
= CFGetAllocator(key
);
1009 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, fullkey
);
1011 if (NULL
== *serialized
)
1012 return errSecDecode
;
1014 return errSecSuccess
;
1018 static CFDictionaryRef
SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key
) {
1019 CFDictionaryRef dict
= NULL
;
1020 CFDataRef fullKeyBlob
= NULL
;
1022 /* PKCS1 encode the key pair. */
1023 fullKeyBlob
= SecRSAPrivateKeyCopyPKCS1(key
);
1024 require(fullKeyBlob
, errOut
);
1026 dict
= SecKeyGeneratePrivateAttributeDictionary(key
, kSecAttrKeyTypeRSA
, fullKeyBlob
);
1029 CFReleaseSafe(fullKeyBlob
);
1034 SecKeyDescriptor kSecRSAPrivateKeyDescriptor
= {
1035 kSecKeyDescriptorVersion
,
1037 ccrsa_full_ctx_size(kMaximumRSAKeyBytes
), /* extraBytes */
1038 SecRSAPrivateKeyInit
,
1039 SecRSAPrivateKeyDestroy
,
1040 SecRSAPrivateKeyRawSign
,
1041 NULL
, /* SecKeyRawVerifyMethod */
1042 NULL
, /* SecKeyEncryptMethod */
1043 SecRSAPrivateKeyRawDecrypt
,
1044 NULL
, /* SecKeyComputeMethod */
1045 SecRSAPrivateKeyBlockSize
,
1046 SecRSAPrivateKeyCopyAttributeDictionary
,
1048 SecRSAPrivateKeyCopyPublicSerialization
,
1051 /* Private Key API functions. */
1052 SecKeyRef
SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator
,
1053 const uint8_t *keyData
, CFIndex keyDataLength
,
1054 SecKeyEncoding encoding
) {
1055 return SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
, keyData
,
1056 keyDataLength
, encoding
);
1060 OSStatus
SecRSAKeyGeneratePair(CFDictionaryRef parameters
,
1061 SecKeyRef
*rsaPublicKey
, SecKeyRef
*rsaPrivateKey
) {
1062 OSStatus status
= errSecParam
;
1064 CFAllocatorRef allocator
= NULL
; /* @@@ get from parameters. */
1066 SecKeyRef pubKey
= NULL
;
1067 SecKeyRef privKey
= SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
,
1068 (const void*) parameters
, 0, kSecGenerateKey
);
1070 require(privKey
, errOut
);
1072 /* Create SecKeyRef's from the pkcs1 encoded keys. */
1073 pubKey
= SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
,
1074 privKey
->key
, 0, kSecExtractPublicFromPrivate
);
1076 require(pubKey
, errOut
);
1079 *rsaPublicKey
= pubKey
;
1082 if (rsaPrivateKey
) {
1083 *rsaPrivateKey
= privKey
;
1087 status
= errSecSuccess
;
1090 CFReleaseSafe(pubKey
);
1091 CFReleaseSafe(privKey
);