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 <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 4096
64 #define kMaximumRSAKeyBytes ccn_sizeof(kMaximumRSAKeyBits)
66 #define RSA_PKCS1_PAD_SIGN 0x01
67 #define RSA_PKCS1_PAD_ENCRYPT 0x02
69 static void ccn_c_dump(cc_size count
, const cc_unit
*s
)
73 for (ix
= count
; ix
--;) {
74 printf("0x%.02x, 0x%.02x, 0x%.02x, 0x%.02x, ",
75 (int) ((s
[ix
] >> 24) & 0xFF),
76 (int) ((s
[ix
] >> 16) & 0xFF),
77 (int) ((s
[ix
] >> 8 ) & 0xFF),
78 (int) ((s
[ix
] >> 0 ) & 0xFF));
83 static void ccn_cprint(cc_size count
, char* prefix
, const cc_unit
*s
)
90 void ccrsa_dump_full_key(ccrsa_full_ctx_t key
); // Suppress warnings
91 void ccrsa_dump_full_key(ccrsa_full_ctx_t key
) {
92 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t m[] = ", ccrsa_ctx_m(key
));
93 ccn_cprint(ccrsa_ctx_n(key
) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key
)));
94 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t e[] = ", ccrsa_ctx_e(key
));
95 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t d[] = ", ccrsa_ctx_d(key
));
97 printf("cc_size np = %lu;\n", cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))));
98 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))), "uint8_t p[] = ",
99 cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))));
100 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))) + 1, "uint8_t rp[] = ",
101 cczp_recip(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))));
102 printf("cc_size nq = %lu;\n", cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))));
103 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))), "uint8_t q[] = ",
104 cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))));
105 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))) + 1, "uint8_t rq[] = ",
106 cczp_recip(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))));
107 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))), "uint8_t dp[] = ",
108 ccrsa_ctx_private_dp(ccrsa_ctx_private(key
)));
109 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key
))), "uint8_t dq[] = ",
110 ccrsa_ctx_private_dq(ccrsa_ctx_private(key
)));
111 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key
))), "uint8_t qinv[] = ",
112 ccrsa_ctx_private_qinv(ccrsa_ctx_private(key
)));
116 void ccrsa_dump_public_key(ccrsa_pub_ctx_t key
); // Suppress warning.
117 void ccrsa_dump_public_key(ccrsa_pub_ctx_t key
) {
118 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t m[] = ", ccrsa_ctx_m(key
));
119 ccn_cprint(ccrsa_ctx_n(key
) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key
)));
120 ccn_cprint(ccrsa_ctx_n(key
), "uint8_t e[] = ", ccrsa_ctx_e(key
));
131 /* Public key static functions. */
132 static void SecRSAPublicKeyDestroy(SecKeyRef key
) {
133 /* Zero out the public key */
134 ccrsa_pub_ctx_t pubkey
;
135 pubkey
.pub
= key
->key
;
136 cc_zero(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey
))), pubkey
.pub
);
139 #define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
142 // pubkey is initilaized with an n which is the maximum it can hold
143 // We set the n to its correct value given m.
145 static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey
,
146 size_t m_size
, const uint8_t* m
,
147 size_t e_size
, const uint8_t* e
)
149 cc_skip_zeros(m_size
, m
);
151 cc_size nm
= ccn_nof_size(m_size
);
152 if (nm
> ccrsa_ctx_n(pubkey
))
155 ccrsa_ctx_n(pubkey
) = nm
;
157 ccn_read_uint(nm
, ccrsa_ctx_m(pubkey
), m_size
, m
);
158 cczp_init(ccrsa_ctx_zm(pubkey
));
160 return ccn_read_uint(nm
, ccrsa_ctx_e(pubkey
), e_size
, e
);
164 static OSStatus
ccrsa_pub_decode(ccrsa_pub_ctx_t pubkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
166 OSStatus result
= errSecParam
;
168 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
169 DERRSAPubKeyPKCS1 decodedKey
;
171 require_noerr_action(DERParseSequence(&keyItem
,
172 DERNumRSAPubKeyPKCS1ItemSpecs
, DERRSAPubKeyPKCS1ItemSpecs
,
173 &decodedKey
, sizeof(decodedKey
)),
174 errOut
, result
= errSecDecode
);
176 require_noerr(ccrsa_pub_init(pubkey
,
177 decodedKey
.modulus
.length
, decodedKey
.modulus
.data
,
178 decodedKey
.pubExponent
.length
, decodedKey
.pubExponent
.data
),
181 result
= errSecSuccess
;
187 static OSStatus
ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
189 OSStatus result
= errSecParam
;
191 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
192 DERRSAPubKeyApple decodedKey
;
194 require_noerr_action(DERParseSequence(&keyItem
,
195 DERNumRSAPubKeyAppleItemSpecs
, DERRSAPubKeyAppleItemSpecs
,
196 &decodedKey
, sizeof(decodedKey
)),
197 errOut
, result
= errSecDecode
);
199 // We could honor the recipricol, but we don't think this is used enough to care.
200 // Don't bother exploding the below function to try to handle this case, it computes.
202 require_noerr(ccrsa_pub_init(pubkey
,
203 decodedKey
.modulus
.length
, decodedKey
.modulus
.data
,
204 decodedKey
.pubExponent
.length
, decodedKey
.pubExponent
.data
),
207 result
= errSecSuccess
;
214 static void ccasn_encode_int(cc_size n
, const cc_unit
*s
, size_t s_size
, uint8_t **buffer
)
216 **buffer
= ASN1_INTEGER
;
219 DERSize itemLength
= 4;
220 DEREncodeLength(s_size
, *buffer
, &itemLength
);
221 *buffer
+= itemLength
;
223 ccn_write_int(n
, s
, s_size
, *buffer
);
229 static OSStatus
SecRSAPublicKeyInit(SecKeyRef key
,
230 const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
232 OSStatus result
= errSecParam
;
234 ccrsa_pub_ctx_t pubkey
;
235 pubkey
.pub
= key
->key
;
237 // Set maximum size for parsers
238 ccrsa_ctx_n(pubkey
) = ccn_nof(kMaximumRSAKeyBits
);
241 case kSecKeyEncodingBytes
: // Octets is PKCS1
242 case kSecKeyEncodingPkcs1
:
243 result
= ccrsa_pub_decode(pubkey
, keyDataLength
, keyData
);
245 case kSecKeyEncodingApplePkcs1
:
246 result
= ccrsa_pub_decode_apple(pubkey
, keyDataLength
, keyData
);
248 case kSecKeyEncodingRSAPublicParams
:
250 SecRSAPublicKeyParams
*params
= (SecRSAPublicKeyParams
*)keyData
;
252 require_noerr(ccrsa_pub_init(pubkey
,
253 params
->modulusLength
, params
->modulus
,
254 params
->exponentLength
, params
->exponent
), errOut
);
256 result
= errSecSuccess
;
259 case kSecExtractPublicFromPrivate
:
261 ccrsa_full_ctx_t fullKey
;
262 fullKey
.full
= (ccrsa_full_ctx
*) keyData
;
264 cc_size fullKeyN
= ccrsa_ctx_n(fullKey
);
265 require(fullKeyN
<= ccrsa_ctx_n(pubkey
), errOut
);
266 memcpy(pubkey
.pub
, ccrsa_ctx_public(fullKey
).pub
, ccrsa_pub_ctx_size(ccn_sizeof_n(fullKeyN
)));
267 result
= errSecSuccess
;
278 static OSStatus
SecRSAPublicKeyRawVerify(SecKeyRef key
, SecPadding padding
,
279 const uint8_t *signedData
, size_t signedDataLen
,
280 const uint8_t *sig
, size_t sigLen
) {
281 OSStatus result
= errSSLCrypto
;
283 ccrsa_pub_ctx_t pubkey
;
284 pubkey
.pub
= key
->key
;
286 cc_unit s
[ccrsa_ctx_n(pubkey
)];
288 ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, sigLen
, sig
);
289 ccrsa_pub_crypt(pubkey
, s
, s
);
290 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
292 const uint8_t* sBytes
= (uint8_t*) s
;
293 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(pubkey
));
296 case kSecPaddingNone
:
297 // Skip leading zeros as long as s is bigger than signedData.
298 while (((ptrdiff_t)signedDataLen
< (sEnd
- sBytes
)) && (*sBytes
== 0))
302 case kSecPaddingPKCS1
:
304 // Verify and skip PKCS1 padding:
306 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
308 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
309 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
311 while (prefix_zeros
--)
312 require_quiet(*sBytes
++ == 0x00, errOut
);
314 require_quiet(*sBytes
++ == 0x00, errOut
);
315 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_SIGN
, errOut
);
317 while (*sBytes
== 0xFF) {
318 require_quiet(++sBytes
< sEnd
, errOut
);
320 // Required to have at least 8 0xFFs
321 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
323 require_quiet(*sBytes
== 0x00, errOut
);
324 require_quiet(++sBytes
< sEnd
, errOut
);
327 case kSecPaddingOAEP
:
328 result
= errSecParam
;
332 result
= errSecUnimplemented
;
337 require_quiet((sEnd
- sBytes
) == (ptrdiff_t)signedDataLen
, errOut
);
338 require_quiet(memcmp(sBytes
, signedData
, signedDataLen
) == 0, errOut
);
340 result
= errSecSuccess
;
343 cc_zero(ccrsa_ctx_n(pubkey
), s
);
348 static OSStatus
SecRSAPublicKeyRawEncrypt(SecKeyRef key
, SecPadding padding
,
349 const uint8_t *plainText
, size_t plainTextLen
,
350 uint8_t *cipherText
, size_t *cipherTextLen
) {
351 OSStatus result
= errSecParam
;
352 ccrsa_pub_ctx_t pubkey
;
353 pubkey
.pub
= key
->key
;
355 cc_unit s
[ccrsa_ctx_n(pubkey
)];
356 const size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
358 require(cipherTextLen
, errOut
);
359 require(*cipherTextLen
>= m_size
, errOut
);
361 uint8_t* sBytes
= (uint8_t*) s
;
364 case kSecPaddingNone
:
365 // We'll allow modulus size assuming input is smaller than modulus
366 require_quiet(plainTextLen
<= m_size
, errOut
);
367 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, plainTextLen
, plainText
), errOut
);
368 require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey
), s
, ccrsa_ctx_m(pubkey
)) < 0, errOut
);
371 case kSecPaddingPKCS1
:
373 // Create PKCS1 padding:
375 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
377 const int kMinimumPadding
= 1 + 1 + 8 + 1;
379 require_quiet(plainTextLen
<= m_size
- kMinimumPadding
, errOut
);
381 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
383 while (prefix_zeros
--)
386 size_t pad_size
= m_size
- plainTextLen
;
389 *sBytes
++ = RSA_PKCS1_PAD_ENCRYPT
;
391 ccrng_generate(ccrng_seckey
, pad_size
- 3, sBytes
);
392 // Remove zeroes from the random pad
394 const uint8_t* sEndOfPad
= sBytes
+ (pad_size
- 3);
395 while (sBytes
< sEndOfPad
)
398 *sBytes
= 0xFF; // Michael said 0xFF was good enough.
405 memcpy(sBytes
, plainText
, plainTextLen
);
407 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
410 case kSecPaddingOAEP
:
412 const struct ccdigest_info
* di
= ccsha1_di();
414 const size_t encodingOverhead
= 2 + 2 * di
->output_size
;
416 require_action(m_size
> encodingOverhead
, errOut
, result
= errSecParam
);
417 require_action_quiet(plainTextLen
<= m_size
- encodingOverhead
, errOut
, result
= errSecParam
);
419 require_noerr_action(ccrsa_oaep_encode(di
,
422 plainTextLen
, plainText
), errOut
, result
= errSecInternal
);
430 ccrsa_pub_crypt(pubkey
, s
, s
);
432 ccn_write_uint_padded(ccrsa_ctx_n(pubkey
), s
, m_size
, cipherText
);
433 *cipherTextLen
= m_size
;
435 result
= errSecSuccess
;
438 ccn_zero(ccrsa_ctx_n(pubkey
), s
);
442 static OSStatus
SecRSAPublicKeyRawDecrypt(SecKeyRef key
, SecPadding padding
,
443 const uint8_t *cipherText
, size_t cipherTextLen
, uint8_t *plainText
, size_t *plainTextLen
) {
444 OSStatus result
= errSSLCrypto
;
446 ccrsa_pub_ctx_t pubkey
;
447 pubkey
.pub
= key
->key
;
449 cc_unit s
[ccrsa_ctx_n(pubkey
)];
451 require_action_quiet(cipherText
!= NULL
, errOut
, result
= errSecParam
);
452 require_action_quiet(plainText
!= NULL
, errOut
, result
= errSecParam
);
453 require_action_quiet(plainTextLen
!= NULL
, errOut
, result
= errSecParam
);
455 ccn_read_uint(ccrsa_ctx_n(pubkey
), s
, cipherTextLen
, cipherText
);
456 ccrsa_pub_crypt(pubkey
, s
, s
);
457 ccn_swap(ccrsa_ctx_n(pubkey
), s
);
459 const uint8_t* sBytes
= (uint8_t*) s
;
460 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(pubkey
));
463 case kSecPaddingNone
:
464 // Skip leading zeros
465 // We return the bytes for a number and
466 // trim leading zeroes
467 while (sBytes
< sEnd
&& *sBytes
== 0x00)
471 case kSecPaddingPKCS1
:
473 // Verify and skip PKCS1 padding:
475 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
477 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
478 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(pubkey
)) - m_size
;
480 while (prefix_zeros
--)
481 require_quiet(*sBytes
++ == 0x00, errOut
);
483 require_quiet(*sBytes
++ == 0x00, errOut
);
484 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_ENCRYPT
, errOut
);
486 while (*sBytes
!= 0x00) {
487 require_quiet(++sBytes
< sEnd
, errOut
);
489 // Required to have at least 8 0xFFs
490 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
492 require_quiet(*sBytes
== 0x00, errOut
);
493 require_quiet(++sBytes
< sEnd
, errOut
);
497 case kSecPaddingOAEP
:
498 result
= errSecParam
;
504 require_action((sEnd
- sBytes
) <= (ptrdiff_t)*plainTextLen
, errOut
, result
= errSecParam
);
506 *plainTextLen
= sEnd
- sBytes
;
507 memcpy(plainText
, sBytes
, *plainTextLen
);
509 result
= errSecSuccess
;
512 ccn_zero(ccrsa_ctx_n(pubkey
), s
);
517 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key
) {
518 ccrsa_pub_ctx_t pubkey
;
519 pubkey
.pub
= key
->key
;
521 return ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
525 static CFDataRef
SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_pub_ctx_t pubkey
)
527 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
528 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
530 const size_t seq_size
= DERLengthOfItem(ASN1_INTEGER
, m_size
) +
531 DERLengthOfItem(ASN1_INTEGER
, e_size
);
533 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
535 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
540 CFDataSetLength(pkcs1
, result_size
);
542 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
544 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
546 DERSize itemLength
= 4;
547 DEREncodeLength(seq_size
, bytes
, &itemLength
);
550 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, &bytes
);
551 ccasn_encode_int(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
), e_size
, &bytes
);
556 static OSStatus
SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
558 ccrsa_pub_ctx_t pubkey
;
559 pubkey
.pub
= key
->key
;
561 CFAllocatorRef allocator
= CFGetAllocator(key
);
562 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, pubkey
);
564 if (NULL
== *serialized
)
567 return errSecSuccess
;
570 static CFDictionaryRef
SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key
) {
571 return SecKeyGeneratePublicAttributeDictionary(key
, kSecAttrKeyTypeRSA
);
574 static CFStringRef
SecRSAPublicKeyCopyDescription(SecKeyRef key
) {
576 CFStringRef keyDescription
= NULL
;
577 CFDataRef modRef
= SecKeyCopyModulus(key
);
579 ccrsa_pub_ctx_t pubkey
;
580 pubkey
.pub
= key
->key
;
582 CFStringRef modulusString
= CFDataCopyHexString(modRef
);
583 require( modulusString
, fail
);
585 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
);
588 CFReleaseSafe(modRef
);
589 CFReleaseSafe(modulusString
);
591 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
);
593 return keyDescription
;
596 SecKeyDescriptor kSecRSAPublicKeyDescriptor
= {
597 kSecKeyDescriptorVersion
,
599 ccrsa_pub_ctx_size(kMaximumRSAKeyBytes
), /* extraBytes */
601 SecRSAPublicKeyDestroy
,
602 NULL
, /* SecKeyRawSignMethod */
603 SecRSAPublicKeyRawVerify
,
604 SecRSAPublicKeyRawEncrypt
,
605 SecRSAPublicKeyRawDecrypt
,
606 NULL
, /* SecKeyComputeMethod */
607 SecRSAPublicKeyBlockSize
,
608 SecRSAPublicKeyCopyAttributeDictionary
,
609 SecRSAPublicKeyCopyDescription
,
611 SecRSAPublicKeyCopyPublicSerialization
,
614 /* Public Key API functions. */
615 SecKeyRef
SecKeyCreateRSAPublicKey(CFAllocatorRef allocator
,
616 const uint8_t *keyData
, CFIndex keyDataLength
,
617 SecKeyEncoding encoding
) {
618 return SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
, keyData
,
619 keyDataLength
, encoding
);
622 CFDataRef
SecKeyCopyModulus(SecKeyRef key
) {
623 ccrsa_pub_ctx_t pubkey
;
624 pubkey
.pub
= key
->key
;
626 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
));
628 CFAllocatorRef allocator
= CFGetAllocator(key
);
629 CFMutableDataRef modulusData
= CFDataCreateMutable(allocator
, m_size
);
631 if (modulusData
== NULL
)
634 CFDataSetLength(modulusData
, m_size
);
636 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), m_size
, CFDataGetMutableBytePtr(modulusData
));
641 CFDataRef
SecKeyCopyExponent(SecKeyRef key
) {
642 ccrsa_pub_ctx_t pubkey
;
643 pubkey
.pub
= key
->key
;
645 size_t e_size
= ccn_write_uint_size(ccrsa_ctx_n(pubkey
), ccrsa_ctx_e(pubkey
));
647 CFAllocatorRef allocator
= CFGetAllocator(key
);
648 CFMutableDataRef exponentData
= CFDataCreateMutable(allocator
, e_size
);
650 if (exponentData
== NULL
)
653 CFDataSetLength(exponentData
, e_size
);
655 ccn_write_uint(ccrsa_ctx_n(pubkey
), ccrsa_ctx_m(pubkey
), e_size
, CFDataGetMutableBytePtr(exponentData
));
667 /* Private key static functions. */
668 static void SecRSAPrivateKeyDestroy(SecKeyRef key
) {
669 /* Zero out the public key */
670 ccrsa_full_ctx_t fullkey
;
671 fullkey
.full
= key
->key
;
672 cc_zero(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey
))), fullkey
.full
);
675 static int ccrsa_priv_init(ccrsa_priv_ctx_t privkey
,
676 size_t p_size
, const uint8_t* p
,
677 size_t q_size
, const uint8_t* q
,
678 size_t dp_size
, const uint8_t* dp
,
679 size_t dq_size
, const uint8_t* dq
,
680 size_t qinv_size
, const uint8_t* qinv
)
684 const cc_size np
= cczp_n(ccrsa_ctx_private_zp(privkey
));
685 cc_size nq
= cczp_n(ccrsa_ctx_private_zq(privkey
));
687 if (ccn_read_uint(np
, CCZP_PRIME(ccrsa_ctx_private_zp(privkey
)), p_size
, p
))
689 cczp_init(ccrsa_ctx_private_zp(privkey
));
690 if (ccn_read_uint(np
, ccrsa_ctx_private_dp(privkey
), dp_size
, dp
))
692 if (ccn_read_uint(np
, ccrsa_ctx_private_qinv(privkey
), qinv_size
, qinv
))
695 if (ccn_read_uint(nq
, CCZP_PRIME(ccrsa_ctx_private_zq(privkey
)), q_size
, q
))
698 nq
= ccn_n(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)));
699 CCZP_N(ccrsa_ctx_private_zq(privkey
)) = nq
;
701 cczp_init(ccrsa_ctx_private_zq(privkey
));
702 if (ccn_read_uint(nq
, ccrsa_ctx_private_dq(privkey
), dq_size
, dq
))
712 static OSStatus
ccrsa_full_decode(ccrsa_full_ctx_t fullkey
, size_t pkcs1_size
, const uint8_t* pkcs1
)
714 OSStatus result
= errSecParam
;
716 DERItem keyItem
= {(DERByte
*)pkcs1
, pkcs1_size
};
717 DERRSAKeyPair decodedKey
;
719 require_noerr_action(DERParseSequence(&keyItem
,
720 DERNumRSAKeyPairItemSpecs
, DERRSAKeyPairItemSpecs
,
721 &decodedKey
, sizeof(decodedKey
)),
722 errOut
, result
= errSecDecode
);
724 require_noerr(ccrsa_pub_init(fullkey
,
725 decodedKey
.n
.length
, decodedKey
.n
.data
,
726 decodedKey
.e
.length
, decodedKey
.e
.data
),
728 ccn_read_uint(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
),
729 decodedKey
.d
.length
, decodedKey
.d
.data
);
731 ccrsa_priv_ctx_t privkey
= ccrsa_ctx_private(fullkey
);
732 CCZP_N(ccrsa_ctx_private_zp(privkey
)) = ccn_nof((ccn_bitsof_n(ccrsa_ctx_n(fullkey
)) / 2) + 1);
733 CCZP_N(ccrsa_ctx_private_zq(privkey
)) = cczp_n(ccrsa_ctx_private_zp(privkey
));
735 // TODO: Actually remember decodedKey.d.
737 require_noerr(ccrsa_priv_init(privkey
,
738 decodedKey
.p
.length
, decodedKey
.p
.data
,
739 decodedKey
.q
.length
, decodedKey
.q
.data
,
740 decodedKey
.dp
.length
, decodedKey
.dp
.data
,
741 decodedKey
.dq
.length
, decodedKey
.dq
.data
,
742 decodedKey
.qInv
.length
, decodedKey
.qInv
.data
),
746 result
= errSecSuccess
;
752 static OSStatus
SecRSAPrivateKeyInit(SecKeyRef key
,
753 const uint8_t *keyData
, CFIndex keyDataLength
, SecKeyEncoding encoding
) {
754 OSStatus result
= errSecParam
;
756 ccrsa_full_ctx_t fullkey
;
757 fullkey
.full
= key
->key
;
759 // Set maximum size for parsers
760 ccrsa_ctx_n(fullkey
) = ccn_nof(kMaximumRSAKeyBits
);
763 case kSecKeyEncodingBytes
: // Octets is PKCS1
764 case kSecKeyEncodingPkcs1
:
765 result
= ccrsa_full_decode(fullkey
, keyDataLength
, keyData
);
767 case kSecGenerateKey
:
769 CFDictionaryRef parameters
= (CFDictionaryRef
) keyData
;
771 CFTypeRef ksize
= CFDictionaryGetValue(parameters
, kSecAttrKeySizeInBits
);
772 CFIndex keyLengthInBits
= getIntValue(ksize
);
774 if (keyLengthInBits
< 256 || keyLengthInBits
> kMaximumRSAKeyBits
) {
775 secwarning("Invalid or missing key size in: %@", parameters
);
776 return errSecKeySizeNotAllowed
;
779 /* TODO: Add support for kSecPublicExponent parameter. */
780 static uint8_t e
[] = { 0x01, 0x00, 0x01 }; // Default is 65537
781 if (!ccrsa_generate_key(keyLengthInBits
, fullkey
.full
, sizeof(e
), e
, ccrng_seckey
))
782 result
= errSecSuccess
;
792 static OSStatus
SecRSAPrivateKeyRawSign(SecKeyRef key
, SecPadding padding
,
793 const uint8_t *dataToSign
, size_t dataToSignLen
,
794 uint8_t *sig
, size_t *sigLen
) {
796 OSStatus result
= errSecParam
;
798 ccrsa_full_ctx_t fullkey
;
799 fullkey
.full
= key
->key
;
801 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
802 cc_unit s
[ccrsa_ctx_n(fullkey
)];
804 uint8_t* sBytes
= (uint8_t*) s
;
806 require(sigLen
, errOut
);
807 require(*sigLen
>= m_size
, errOut
);
810 case kSecPaddingNone
:
811 // We'll allow modulus size assuming input is smaller than modulus
812 require_quiet(dataToSignLen
<= m_size
, errOut
);
813 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey
), s
, dataToSignLen
, dataToSign
), errOut
);
814 require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey
), s
, ccrsa_ctx_m(fullkey
)) < 0, errOut
);
817 case kSecPaddingPKCS1
:
819 // Create PKCS1 padding:
821 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
823 const int kMinimumPadding
= 1 + 1 + 8 + 1;
825 require_quiet(dataToSignLen
<= m_size
- kMinimumPadding
, errOut
);
827 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(fullkey
)) - m_size
;
829 while (prefix_zeros
--)
832 size_t pad_size
= m_size
- dataToSignLen
;
835 *sBytes
++ = RSA_PKCS1_PAD_SIGN
;
838 for(ff_size
= pad_size
- 3; ff_size
> 0; --ff_size
)
843 // Get the user data into s looking like a ccn.
844 memcpy(sBytes
, dataToSign
, dataToSignLen
);
845 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
849 case kSecPaddingOAEP
:
850 result
= errSecParam
;
855 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey
), s
, s
);
857 // Pad with leading zeros to fit in modulus size
858 ccn_write_uint_padded(ccrsa_ctx_n(fullkey
), s
, m_size
, sig
);
861 result
= errSecSuccess
;
864 ccn_zero(ccrsa_ctx_n(fullkey
), s
);
868 static OSStatus
SecRSAPrivateKeyRawDecrypt(SecKeyRef key
, SecPadding padding
,
869 const uint8_t *cipherText
, size_t cipherTextLen
,
870 uint8_t *plainText
, size_t *plainTextLen
) {
871 OSStatus result
= errSSLCrypto
;
873 ccrsa_full_ctx_t fullkey
;
874 fullkey
.full
= key
->key
;
876 size_t m_size
= ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
878 cc_unit s
[ccrsa_ctx_n(fullkey
)];
879 uint8_t recoveredData
[ccn_sizeof_n(ccrsa_ctx_n(fullkey
))];
881 ccn_read_uint(ccrsa_ctx_n(fullkey
), s
, cipherTextLen
, cipherText
);
882 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey
), s
, s
);
884 const uint8_t* sBytes
= (uint8_t*) s
;
885 const uint8_t* sEnd
= (uint8_t*) (s
+ ccrsa_ctx_n(fullkey
));
887 require(plainTextLen
, errOut
);
890 case kSecPaddingNone
:
891 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
892 // Skip Zeros since our contract is to do so.
893 while (sBytes
< sEnd
&& *sBytes
== 0x00)
897 case kSecPaddingPKCS1
:
899 ccn_swap(ccrsa_ctx_n(fullkey
), s
);
900 // Verify and skip PKCS1 padding:
902 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
905 size_t prefix_zeros
= ccn_sizeof_n(ccrsa_ctx_n(fullkey
)) - m_size
;
907 while (prefix_zeros
--)
908 require_quiet(*sBytes
++ == 0x00, errOut
);
910 require_quiet(*sBytes
++ == 0x00, errOut
);
911 require_quiet(*sBytes
++ == RSA_PKCS1_PAD_ENCRYPT
, errOut
);
913 while (*sBytes
!= 0x00) {
914 require_quiet(++sBytes
< sEnd
, errOut
);
916 // Required to have at least 8 non-zeros
917 require_quiet((sBytes
- (uint8_t*)s
) - 2 >= 8, errOut
);
919 require_quiet(*sBytes
== 0x00, errOut
);
920 require_quiet(++sBytes
< sEnd
, errOut
);
923 case kSecPaddingOAEP
:
925 size_t length
= sizeof(recoveredData
);
927 require_noerr_quiet(ccrsa_oaep_decode(ccsha1_di(),
928 &length
, recoveredData
,
929 ccn_write_uint_size(ccrsa_ctx_n(fullkey
),ccrsa_ctx_m(fullkey
)), s
932 sBytes
= recoveredData
;
933 sEnd
= recoveredData
+ length
;
940 require((sEnd
- sBytes
) <= (ptrdiff_t)*plainTextLen
, errOut
);
941 *plainTextLen
= sEnd
- sBytes
;
942 memcpy(plainText
, sBytes
, *plainTextLen
);
944 result
= errSecSuccess
;
947 bzero(recoveredData
, sizeof(recoveredData
));
948 ccn_zero(ccrsa_ctx_n(fullkey
), s
);
953 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key
) {
954 ccrsa_full_ctx_t fullkey
;
955 fullkey
.full
= key
->key
;
957 return ccn_write_uint_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
960 static CFDataRef
SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator
, ccrsa_full_ctx_t fullkey
)
962 ccrsa_priv_ctx_t privkey
= ccrsa_ctx_private(fullkey
);
964 const cc_size np
= cczp_n(ccrsa_ctx_private_zp(privkey
));
965 const cc_size nq
= cczp_n(ccrsa_ctx_private_zq(privkey
));
967 size_t m_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
));
968 size_t e_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_e(fullkey
));
969 size_t d_size
= ccn_write_int_size(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
));
971 size_t p_size
= ccn_write_int_size(np
, cczp_prime(ccrsa_ctx_private_zp(privkey
)));
972 size_t q_size
= ccn_write_int_size(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)));
974 size_t dp_size
= ccn_write_int_size(np
, ccrsa_ctx_private_dp(privkey
));
975 size_t dq_size
= ccn_write_int_size(nq
, ccrsa_ctx_private_dq(privkey
));
977 size_t qinv_size
= ccn_write_int_size(np
, ccrsa_ctx_private_qinv(privkey
));
979 const size_t seq_size
= 3 +
980 DERLengthOfItem(ASN1_INTEGER
, m_size
) +
981 DERLengthOfItem(ASN1_INTEGER
, e_size
) +
982 DERLengthOfItem(ASN1_INTEGER
, d_size
) +
983 DERLengthOfItem(ASN1_INTEGER
, p_size
) +
984 DERLengthOfItem(ASN1_INTEGER
, q_size
) +
985 DERLengthOfItem(ASN1_INTEGER
, dp_size
) +
986 DERLengthOfItem(ASN1_INTEGER
, dq_size
) +
987 DERLengthOfItem(ASN1_INTEGER
, qinv_size
);
989 const size_t result_size
= DERLengthOfItem(ASN1_SEQUENCE
, seq_size
);
991 CFMutableDataRef pkcs1
= CFDataCreateMutable(allocator
, result_size
);
996 CFDataSetLength(pkcs1
, result_size
);
998 uint8_t *bytes
= CFDataGetMutableBytePtr(pkcs1
);
1000 *bytes
++ = ASN1_CONSTR_SEQUENCE
;
1002 DERSize itemLength
= 4;
1003 DEREncodeLength(seq_size
, bytes
, &itemLength
);
1004 bytes
+= itemLength
;
1006 *bytes
++ = ASN1_INTEGER
;
1010 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_m(fullkey
), m_size
, &bytes
);
1011 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_e(fullkey
), e_size
, &bytes
);
1012 ccasn_encode_int(ccrsa_ctx_n(fullkey
), ccrsa_ctx_d(fullkey
), d_size
, &bytes
);
1014 ccasn_encode_int(np
, cczp_prime(ccrsa_ctx_private_zp(privkey
)), p_size
, &bytes
);
1015 ccasn_encode_int(nq
, cczp_prime(ccrsa_ctx_private_zq(privkey
)), q_size
, &bytes
);
1016 ccasn_encode_int(np
, ccrsa_ctx_private_dp(privkey
), dp_size
, &bytes
);
1017 ccasn_encode_int(nq
, ccrsa_ctx_private_dq(privkey
), dq_size
, &bytes
);
1018 ccasn_encode_int(np
, ccrsa_ctx_private_qinv(privkey
), qinv_size
, &bytes
);
1023 static CFDataRef
SecRSAPrivateKeyCopyPKCS1(SecKeyRef key
)
1025 ccrsa_full_ctx_t fullkey
;
1026 fullkey
.full
= key
->key
;
1028 CFAllocatorRef allocator
= CFGetAllocator(key
);
1029 return SecRSAPrivateKeyCreatePKCS1(allocator
, fullkey
);
1032 static OSStatus
SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key
, CFDataRef
* serialized
)
1034 ccrsa_full_ctx_t fullkey
;
1035 fullkey
.full
= key
->key
;
1037 CFAllocatorRef allocator
= CFGetAllocator(key
);
1038 *serialized
= SecRSAPublicKeyCreatePKCS1(allocator
, fullkey
);
1040 if (NULL
== *serialized
)
1041 return errSecDecode
;
1043 return errSecSuccess
;
1047 static CFDictionaryRef
SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key
) {
1048 CFDictionaryRef dict
= NULL
;
1049 CFDataRef fullKeyBlob
= NULL
;
1051 /* PKCS1 encode the key pair. */
1052 fullKeyBlob
= SecRSAPrivateKeyCopyPKCS1(key
);
1053 require(fullKeyBlob
, errOut
);
1055 dict
= SecKeyGeneratePrivateAttributeDictionary(key
, kSecAttrKeyTypeRSA
, fullKeyBlob
);
1058 CFReleaseSafe(fullKeyBlob
);
1063 static CFStringRef
SecRSAPrivateKeyCopyDescription(SecKeyRef key
){
1065 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
);
1068 SecKeyDescriptor kSecRSAPrivateKeyDescriptor
= {
1069 kSecKeyDescriptorVersion
,
1071 ccrsa_full_ctx_size(kMaximumRSAKeyBytes
), /* extraBytes */
1072 SecRSAPrivateKeyInit
,
1073 SecRSAPrivateKeyDestroy
,
1074 SecRSAPrivateKeyRawSign
,
1075 NULL
, /* SecKeyRawVerifyMethod */
1076 NULL
, /* SecKeyEncryptMethod */
1077 SecRSAPrivateKeyRawDecrypt
,
1078 NULL
, /* SecKeyComputeMethod */
1079 SecRSAPrivateKeyBlockSize
,
1080 SecRSAPrivateKeyCopyAttributeDictionary
,
1081 SecRSAPrivateKeyCopyDescription
,
1083 SecRSAPrivateKeyCopyPublicSerialization
,
1086 /* Private Key API functions. */
1087 SecKeyRef
SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator
,
1088 const uint8_t *keyData
, CFIndex keyDataLength
,
1089 SecKeyEncoding encoding
) {
1090 return SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
, keyData
,
1091 keyDataLength
, encoding
);
1095 OSStatus
SecRSAKeyGeneratePair(CFDictionaryRef parameters
,
1096 SecKeyRef
*rsaPublicKey
, SecKeyRef
*rsaPrivateKey
) {
1097 OSStatus status
= errSecParam
;
1099 CFAllocatorRef allocator
= NULL
; /* @@@ get from parameters. */
1101 SecKeyRef pubKey
= NULL
;
1102 SecKeyRef privKey
= SecKeyCreate(allocator
, &kSecRSAPrivateKeyDescriptor
,
1103 (const void*) parameters
, 0, kSecGenerateKey
);
1105 require(privKey
, errOut
);
1107 /* Create SecKeyRef's from the pkcs1 encoded keys. */
1108 pubKey
= SecKeyCreate(allocator
, &kSecRSAPublicKeyDescriptor
,
1109 privKey
->key
, 0, kSecExtractPublicFromPrivate
);
1111 require(pubKey
, errOut
);
1114 *rsaPublicKey
= pubKey
;
1117 if (rsaPrivateKey
) {
1118 *rsaPrivateKey
= privKey
;
1122 status
= errSecSuccess
;
1125 CFReleaseSafe(pubKey
);
1126 CFReleaseSafe(privKey
);