]> git.saurik.com Git - apple/security.git/blob - sec/Security/SecRSAKey.c
Security-55471.14.8.tar.gz
[apple/security.git] / sec / Security / SecRSAKey.c
1 /*
2 * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * SecRSAKey.c - CoreFoundation based rsa key object
26 */
27
28
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. */
37 #include <fcntl.h>
38 #include <sys/types.h>
39 #include <unistd.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>
47
48 #include <corecrypto/ccn.h>
49 #include <corecrypto/ccrsa.h>
50 #include <corecrypto/ccsha1.h>
51
52 #include <libDER/asn1Types.h>
53 #include <libDER/DER_Keys.h>
54 #include <libDER/DER_Encode.h>
55
56 #include <CommonCrypto/CommonDigest.h>
57
58 #include <corecrypto/ccrsa_priv.h>
59
60 #include <stdint.h>
61 #include <string.h>
62
63 #define kMaximumRSAKeyBits 4096
64 #define kMaximumRSAKeyBytes ccn_sizeof(kMaximumRSAKeyBits)
65
66 #define RSA_PKCS1_PAD_SIGN 0x01
67 #define RSA_PKCS1_PAD_ENCRYPT 0x02
68
69 static void ccn_c_dump(cc_size count, const cc_unit *s)
70 {
71 printf("{ ");
72 cc_size ix;
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));
79 }
80 printf("};");
81 }
82
83 static void ccn_cprint(cc_size count, char* prefix, const cc_unit *s)
84 {
85 printf("%s", prefix);
86 ccn_c_dump(count, s);
87 printf("\n");
88 }
89
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));
96
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)));
113 printf("--\n");
114 }
115
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));
121
122 printf("--\n");
123 }
124
125 /*
126 *
127 * Public Key
128 *
129 */
130
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);
137 }
138
139 #define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
140
141 //
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.
144 //
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)
148 {
149 cc_skip_zeros(m_size, m);
150
151 cc_size nm = ccn_nof_size(m_size);
152 if (nm > ccrsa_ctx_n(pubkey))
153 return -1;
154
155 ccrsa_ctx_n(pubkey) = nm;
156
157 ccn_read_uint(nm, ccrsa_ctx_m(pubkey), m_size, m);
158 cczp_init(ccrsa_ctx_zm(pubkey));
159
160 return ccn_read_uint(nm, ccrsa_ctx_e(pubkey), e_size, e);
161 }
162
163
164 static OSStatus ccrsa_pub_decode(ccrsa_pub_ctx_t pubkey, size_t pkcs1_size, const uint8_t* pkcs1)
165 {
166 OSStatus result = errSecParam;
167
168 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
169 DERRSAPubKeyPKCS1 decodedKey;
170
171 require_noerr_action(DERParseSequence(&keyItem,
172 DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
173 &decodedKey, sizeof(decodedKey)),
174 errOut, result = errSecDecode);
175
176 require_noerr(ccrsa_pub_init(pubkey,
177 decodedKey.modulus.length, decodedKey.modulus.data,
178 decodedKey.pubExponent.length, decodedKey.pubExponent.data),
179 errOut);
180
181 result = errSecSuccess;
182
183 errOut:
184 return result;
185 }
186
187 static OSStatus ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey, size_t pkcs1_size, const uint8_t* pkcs1)
188 {
189 OSStatus result = errSecParam;
190
191 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
192 DERRSAPubKeyApple decodedKey;
193
194 require_noerr_action(DERParseSequence(&keyItem,
195 DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
196 &decodedKey, sizeof(decodedKey)),
197 errOut, result = errSecDecode);
198
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.
201
202 require_noerr(ccrsa_pub_init(pubkey,
203 decodedKey.modulus.length, decodedKey.modulus.data,
204 decodedKey.pubExponent.length, decodedKey.pubExponent.data),
205 errOut);
206
207 result = errSecSuccess;
208
209 errOut:
210 return result;
211 }
212
213
214 static void ccasn_encode_int(cc_size n, const cc_unit*s, size_t s_size, uint8_t **buffer)
215 {
216 **buffer = ASN1_INTEGER;
217 *buffer += 1;
218
219 DERSize itemLength = 4;
220 DEREncodeLength(s_size, *buffer, &itemLength);
221 *buffer += itemLength;
222
223 ccn_write_int(n, s, s_size, *buffer);
224
225 *buffer += s_size;
226 }
227
228
229 static OSStatus SecRSAPublicKeyInit(SecKeyRef key,
230 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
231
232 OSStatus result = errSecParam;
233
234 ccrsa_pub_ctx_t pubkey;
235 pubkey.pub = key->key;
236
237 // Set maximum size for parsers
238 ccrsa_ctx_n(pubkey) = ccn_nof(kMaximumRSAKeyBits);
239
240 switch (encoding) {
241 case kSecKeyEncodingBytes: // Octets is PKCS1
242 case kSecKeyEncodingPkcs1:
243 result = ccrsa_pub_decode(pubkey, keyDataLength, keyData);
244 break;
245 case kSecKeyEncodingApplePkcs1:
246 result = ccrsa_pub_decode_apple(pubkey, keyDataLength, keyData);
247 break;
248 case kSecKeyEncodingRSAPublicParams:
249 {
250 SecRSAPublicKeyParams *params = (SecRSAPublicKeyParams *)keyData;
251
252 require_noerr(ccrsa_pub_init(pubkey,
253 params->modulusLength, params->modulus,
254 params->exponentLength, params->exponent), errOut);
255
256 result = errSecSuccess;
257 break;
258 }
259 case kSecExtractPublicFromPrivate:
260 {
261 ccrsa_full_ctx_t fullKey;
262 fullKey.full = (ccrsa_full_ctx*) keyData;
263
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;
268 break;
269 }
270 default:
271 break;
272 }
273
274 errOut:
275 return result;
276 }
277
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;
282
283 ccrsa_pub_ctx_t pubkey;
284 pubkey.pub = key->key;
285
286 cc_unit s[ccrsa_ctx_n(pubkey)];
287
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);
291
292 const uint8_t* sBytes = (uint8_t*) s;
293 const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(pubkey));
294
295 switch (padding) {
296 case kSecPaddingNone:
297 // Skip leading zeros as long as s is bigger than signedData.
298 while (((ptrdiff_t)signedDataLen < (sEnd - sBytes)) && (*sBytes == 0))
299 ++sBytes;
300 break;
301
302 case kSecPaddingPKCS1:
303 {
304 // Verify and skip PKCS1 padding:
305 //
306 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
307 //
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;
310
311 while (prefix_zeros--)
312 require_quiet(*sBytes++ == 0x00, errOut);
313
314 require_quiet(*sBytes++ == 0x00, errOut);
315 require_quiet(*sBytes++ == RSA_PKCS1_PAD_SIGN, errOut);
316
317 while (*sBytes == 0xFF) {
318 require_quiet(++sBytes < sEnd, errOut);
319 }
320 // Required to have at least 8 0xFFs
321 require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
322
323 require_quiet(*sBytes == 0x00, errOut);
324 require_quiet(++sBytes < sEnd, errOut);
325 break;
326 }
327 case kSecPaddingOAEP:
328 result = errSecParam;
329 goto errOut;
330
331 default:
332 result = errSecUnimplemented;
333 goto errOut;
334 }
335
336 // Compare the rest.
337 require_quiet((sEnd - sBytes) == (ptrdiff_t)signedDataLen, errOut);
338 require_quiet(memcmp(sBytes, signedData, signedDataLen) == 0, errOut);
339
340 result = errSecSuccess;
341
342 errOut:
343 cc_zero(ccrsa_ctx_n(pubkey), s);
344
345 return result;
346 }
347
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;
354
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));
357
358 require(cipherTextLen, errOut);
359 require(*cipherTextLen >= m_size, errOut);
360
361 uint8_t* sBytes = (uint8_t*) s;
362
363 switch (padding) {
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);
369 break;
370
371 case kSecPaddingPKCS1:
372 {
373 // Create PKCS1 padding:
374 //
375 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
376 //
377 const int kMinimumPadding = 1 + 1 + 8 + 1;
378
379 require_quiet(plainTextLen <= m_size - kMinimumPadding, errOut);
380
381 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
382
383 while (prefix_zeros--)
384 *sBytes++ = 0x00;
385
386 size_t pad_size = m_size - plainTextLen;
387
388 *sBytes++ = 0x00;
389 *sBytes++ = RSA_PKCS1_PAD_ENCRYPT;
390
391 ccrng_generate(ccrng_seckey, pad_size - 3, sBytes);
392 // Remove zeroes from the random pad
393
394 const uint8_t* sEndOfPad = sBytes + (pad_size - 3);
395 while (sBytes < sEndOfPad)
396 {
397 if (*sBytes == 0x00)
398 *sBytes = 0xFF; // Michael said 0xFF was good enough.
399
400 ++sBytes;
401 }
402
403 *sBytes++ = 0x00;
404
405 memcpy(sBytes, plainText, plainTextLen);
406
407 ccn_swap(ccrsa_ctx_n(pubkey), s);
408 break;
409 }
410 case kSecPaddingOAEP:
411 {
412 const struct ccdigest_info* di = ccsha1_di();
413
414 const size_t encodingOverhead = 2 + 2 * di->output_size;
415
416 require_action(m_size > encodingOverhead, errOut, result = errSecParam);
417 require_action_quiet(plainTextLen <= m_size - encodingOverhead, errOut, result = errSecParam);
418
419 require_noerr_action(ccrsa_oaep_encode(di,
420 ccrng_seckey,
421 m_size, s,
422 plainTextLen, plainText), errOut, result = errSecInternal);
423 break;
424 }
425 default:
426 goto errOut;
427 }
428
429
430 ccrsa_pub_crypt(pubkey, s, s);
431
432 ccn_write_uint_padded(ccrsa_ctx_n(pubkey), s, m_size, cipherText);
433 *cipherTextLen = m_size;
434
435 result = errSecSuccess;
436
437 errOut:
438 ccn_zero(ccrsa_ctx_n(pubkey), s);
439 return result;
440 }
441
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;
445
446 ccrsa_pub_ctx_t pubkey;
447 pubkey.pub = key->key;
448
449 cc_unit s[ccrsa_ctx_n(pubkey)];
450
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);
454
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);
458
459 const uint8_t* sBytes = (uint8_t*) s;
460 const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(pubkey));
461
462 switch (padding) {
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)
468 ++sBytes;
469 break;
470
471 case kSecPaddingPKCS1:
472 {
473 // Verify and skip PKCS1 padding:
474 //
475 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
476 //
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;
479
480 while (prefix_zeros--)
481 require_quiet(*sBytes++ == 0x00, errOut);
482
483 require_quiet(*sBytes++ == 0x00, errOut);
484 require_quiet(*sBytes++ == RSA_PKCS1_PAD_ENCRYPT, errOut);
485
486 while (*sBytes != 0x00) {
487 require_quiet(++sBytes < sEnd, errOut);
488 }
489 // Required to have at least 8 0xFFs
490 require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
491
492 require_quiet(*sBytes == 0x00, errOut);
493 require_quiet(++sBytes < sEnd, errOut);
494
495 break;
496 }
497 case kSecPaddingOAEP:
498 result = errSecParam;
499 default:
500 goto errOut;
501 }
502
503 // Return the rest.
504 require_action((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut, result = errSecParam);
505
506 *plainTextLen = sEnd - sBytes;
507 memcpy(plainText, sBytes, *plainTextLen);
508
509 result = errSecSuccess;
510
511 errOut:
512 ccn_zero(ccrsa_ctx_n(pubkey), s);
513
514 return result;
515 }
516
517 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key) {
518 ccrsa_pub_ctx_t pubkey;
519 pubkey.pub = key->key;
520
521 return ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
522 }
523
524
525 static CFDataRef SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_pub_ctx_t pubkey)
526 {
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));
529
530 const size_t seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) +
531 DERLengthOfItem(ASN1_INTEGER, e_size);
532
533 const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);
534
535 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);
536
537 if (pkcs1 == NULL)
538 return NULL;
539
540 CFDataSetLength(pkcs1, result_size);
541
542 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
543
544 *bytes++ = ASN1_CONSTR_SEQUENCE;
545
546 DERSize itemLength = 4;
547 DEREncodeLength(seq_size, bytes, &itemLength);
548 bytes += itemLength;
549
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);
552
553 return pkcs1;
554 }
555
556 static OSStatus SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
557 {
558 ccrsa_pub_ctx_t pubkey;
559 pubkey.pub = key->key;
560
561 CFAllocatorRef allocator = CFGetAllocator(key);
562 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, pubkey);
563
564 if (NULL == *serialized)
565 return errSecDecode;
566 else
567 return errSecSuccess;
568 }
569
570 static CFDictionaryRef SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key) {
571 return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeRSA);
572 }
573
574 static CFStringRef SecRSAPublicKeyCopyDescription(SecKeyRef key) {
575
576 CFStringRef keyDescription = NULL;
577 CFDataRef modRef = SecKeyCopyModulus(key);
578
579 ccrsa_pub_ctx_t pubkey;
580 pubkey.pub = key->key;
581
582 CFStringRef modulusString = CFDataCopyHexString(modRef);
583 require( modulusString, fail);
584
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);
586
587 fail:
588 CFReleaseSafe(modRef);
589 CFReleaseSafe(modulusString);
590 if(!keyDescription)
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);
592
593 return keyDescription;
594 }
595
596 SecKeyDescriptor kSecRSAPublicKeyDescriptor = {
597 kSecKeyDescriptorVersion,
598 "RSAPublicKey",
599 ccrsa_pub_ctx_size(kMaximumRSAKeyBytes), /* extraBytes */
600 SecRSAPublicKeyInit,
601 SecRSAPublicKeyDestroy,
602 NULL, /* SecKeyRawSignMethod */
603 SecRSAPublicKeyRawVerify,
604 SecRSAPublicKeyRawEncrypt,
605 SecRSAPublicKeyRawDecrypt,
606 NULL, /* SecKeyComputeMethod */
607 SecRSAPublicKeyBlockSize,
608 SecRSAPublicKeyCopyAttributeDictionary,
609 SecRSAPublicKeyCopyDescription,
610 NULL,
611 SecRSAPublicKeyCopyPublicSerialization,
612 };
613
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);
620 }
621
622 CFDataRef SecKeyCopyModulus(SecKeyRef key) {
623 ccrsa_pub_ctx_t pubkey;
624 pubkey.pub = key->key;
625
626 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
627
628 CFAllocatorRef allocator = CFGetAllocator(key);
629 CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size);
630
631 if (modulusData == NULL)
632 return NULL;
633
634 CFDataSetLength(modulusData, m_size);
635
636 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData));
637
638 return modulusData;
639 }
640
641 CFDataRef SecKeyCopyExponent(SecKeyRef key) {
642 ccrsa_pub_ctx_t pubkey;
643 pubkey.pub = key->key;
644
645 size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));
646
647 CFAllocatorRef allocator = CFGetAllocator(key);
648 CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size);
649
650 if (exponentData == NULL)
651 return NULL;
652
653 CFDataSetLength(exponentData, e_size);
654
655 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), e_size, CFDataGetMutableBytePtr(exponentData));
656
657 return exponentData;
658 }
659
660
661 /*
662 *
663 * Private Key
664 *
665 */
666
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);
673 }
674
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)
681 {
682 int result = -1;
683
684 const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
685 cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));
686
687 if (ccn_read_uint(np, CCZP_PRIME(ccrsa_ctx_private_zp(privkey)), p_size, p))
688 goto errOut;
689 cczp_init(ccrsa_ctx_private_zp(privkey));
690 if (ccn_read_uint(np, ccrsa_ctx_private_dp(privkey), dp_size, dp))
691 goto errOut;
692 if (ccn_read_uint(np, ccrsa_ctx_private_qinv(privkey), qinv_size, qinv))
693 goto errOut;
694
695 if (ccn_read_uint(nq, CCZP_PRIME(ccrsa_ctx_private_zq(privkey)), q_size, q))
696 goto errOut;
697
698 nq = ccn_n(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)));
699 CCZP_N(ccrsa_ctx_private_zq(privkey)) = nq;
700
701 cczp_init(ccrsa_ctx_private_zq(privkey));
702 if (ccn_read_uint(nq, ccrsa_ctx_private_dq(privkey), dq_size, dq))
703 goto errOut;
704
705 result = 0;
706
707 errOut:
708 return result;
709 }
710
711
712 static OSStatus ccrsa_full_decode(ccrsa_full_ctx_t fullkey, size_t pkcs1_size, const uint8_t* pkcs1)
713 {
714 OSStatus result = errSecParam;
715
716 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
717 DERRSAKeyPair decodedKey;
718
719 require_noerr_action(DERParseSequence(&keyItem,
720 DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
721 &decodedKey, sizeof(decodedKey)),
722 errOut, result = errSecDecode);
723
724 require_noerr(ccrsa_pub_init(fullkey,
725 decodedKey.n.length, decodedKey.n.data,
726 decodedKey.e.length, decodedKey.e.data),
727 errOut);
728 ccn_read_uint(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey),
729 decodedKey.d.length, decodedKey.d.data);
730 {
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));
734
735 // TODO: Actually remember decodedKey.d.
736
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),
743 errOut);
744 }
745
746 result = errSecSuccess;
747
748 errOut:
749 return result;
750 }
751
752 static OSStatus SecRSAPrivateKeyInit(SecKeyRef key,
753 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
754 OSStatus result = errSecParam;
755
756 ccrsa_full_ctx_t fullkey;
757 fullkey.full = key->key;
758
759 // Set maximum size for parsers
760 ccrsa_ctx_n(fullkey) = ccn_nof(kMaximumRSAKeyBits);
761
762 switch (encoding) {
763 case kSecKeyEncodingBytes: // Octets is PKCS1
764 case kSecKeyEncodingPkcs1:
765 result = ccrsa_full_decode(fullkey, keyDataLength, keyData);
766 break;
767 case kSecGenerateKey:
768 {
769 CFDictionaryRef parameters = (CFDictionaryRef) keyData;
770
771 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
772 CFIndex keyLengthInBits = getIntValue(ksize);
773
774 if (keyLengthInBits < 256 || keyLengthInBits > kMaximumRSAKeyBits) {
775 secwarning("Invalid or missing key size in: %@", parameters);
776 return errSecKeySizeNotAllowed;
777 }
778
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;
783 break;
784 }
785 default:
786 break;
787 }
788
789 return result;
790 }
791
792 static OSStatus SecRSAPrivateKeyRawSign(SecKeyRef key, SecPadding padding,
793 const uint8_t *dataToSign, size_t dataToSignLen,
794 uint8_t *sig, size_t *sigLen) {
795
796 OSStatus result = errSecParam;
797
798 ccrsa_full_ctx_t fullkey;
799 fullkey.full = key->key;
800
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)];
803
804 uint8_t* sBytes = (uint8_t*) s;
805
806 require(sigLen, errOut);
807 require(*sigLen >= m_size, errOut);
808
809 switch (padding) {
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);
815 break;
816
817 case kSecPaddingPKCS1:
818 {
819 // Create PKCS1 padding:
820 //
821 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
822 //
823 const int kMinimumPadding = 1 + 1 + 8 + 1;
824
825 require_quiet(dataToSignLen <= m_size - kMinimumPadding, errOut);
826
827 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
828
829 while (prefix_zeros--)
830 *sBytes++ = 0x00;
831
832 size_t pad_size = m_size - dataToSignLen;
833
834 *sBytes++ = 0x00;
835 *sBytes++ = RSA_PKCS1_PAD_SIGN;
836
837 size_t ff_size;
838 for(ff_size = pad_size - 3; ff_size > 0; --ff_size)
839 *sBytes++ = 0xFF;
840
841 *sBytes++ = 0x00;
842
843 // Get the user data into s looking like a ccn.
844 memcpy(sBytes, dataToSign, dataToSignLen);
845 ccn_swap(ccrsa_ctx_n(fullkey), s);
846
847 break;
848 }
849 case kSecPaddingOAEP:
850 result = errSecParam;
851 default:
852 goto errOut;
853 }
854
855 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);
856
857 // Pad with leading zeros to fit in modulus size
858 ccn_write_uint_padded(ccrsa_ctx_n(fullkey), s, m_size, sig);
859 *sigLen = m_size;
860
861 result = errSecSuccess;
862
863 errOut:
864 ccn_zero(ccrsa_ctx_n(fullkey), s);
865 return result;
866 }
867
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;
872
873 ccrsa_full_ctx_t fullkey;
874 fullkey.full = key->key;
875
876 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
877
878 cc_unit s[ccrsa_ctx_n(fullkey)];
879 uint8_t recoveredData[ccn_sizeof_n(ccrsa_ctx_n(fullkey))];
880
881 ccn_read_uint(ccrsa_ctx_n(fullkey), s, cipherTextLen, cipherText);
882 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);
883
884 const uint8_t* sBytes = (uint8_t*) s;
885 const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(fullkey));
886
887 require(plainTextLen, errOut);
888
889 switch (padding) {
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)
894 ++sBytes;
895 break;
896
897 case kSecPaddingPKCS1:
898 {
899 ccn_swap(ccrsa_ctx_n(fullkey), s);
900 // Verify and skip PKCS1 padding:
901 //
902 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
903 //
904
905 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
906
907 while (prefix_zeros--)
908 require_quiet(*sBytes++ == 0x00, errOut);
909
910 require_quiet(*sBytes++ == 0x00, errOut);
911 require_quiet(*sBytes++ == RSA_PKCS1_PAD_ENCRYPT, errOut);
912
913 while (*sBytes != 0x00) {
914 require_quiet(++sBytes < sEnd, errOut);
915 }
916 // Required to have at least 8 non-zeros
917 require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
918
919 require_quiet(*sBytes == 0x00, errOut);
920 require_quiet(++sBytes < sEnd, errOut);
921 break;
922 }
923 case kSecPaddingOAEP:
924 {
925 size_t length = sizeof(recoveredData);
926
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
930 ), errOut);
931
932 sBytes = recoveredData;
933 sEnd = recoveredData + length;
934 break;
935 }
936 default:
937 goto errOut;
938 }
939
940 require((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut);
941 *plainTextLen = sEnd - sBytes;
942 memcpy(plainText, sBytes, *plainTextLen);
943
944 result = errSecSuccess;
945
946 errOut:
947 bzero(recoveredData, sizeof(recoveredData));
948 ccn_zero(ccrsa_ctx_n(fullkey), s);
949
950 return result;
951 }
952
953 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key) {
954 ccrsa_full_ctx_t fullkey;
955 fullkey.full = key->key;
956
957 return ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
958 }
959
960 static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey)
961 {
962 ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);
963
964 const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
965 const cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));
966
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));
970
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)));
973
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));
976
977 size_t qinv_size = ccn_write_int_size(np, ccrsa_ctx_private_qinv(privkey));
978
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);
988
989 const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);
990
991 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);
992
993 if (pkcs1 == NULL)
994 return NULL;
995
996 CFDataSetLength(pkcs1, result_size);
997
998 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
999
1000 *bytes++ = ASN1_CONSTR_SEQUENCE;
1001
1002 DERSize itemLength = 4;
1003 DEREncodeLength(seq_size, bytes, &itemLength);
1004 bytes += itemLength;
1005
1006 *bytes++ = ASN1_INTEGER;
1007 *bytes++ = 0x01;
1008 *bytes++ = 0x00;
1009
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);
1013
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);
1019
1020 return pkcs1;
1021 }
1022
1023 static CFDataRef SecRSAPrivateKeyCopyPKCS1(SecKeyRef key)
1024 {
1025 ccrsa_full_ctx_t fullkey;
1026 fullkey.full = key->key;
1027
1028 CFAllocatorRef allocator = CFGetAllocator(key);
1029 return SecRSAPrivateKeyCreatePKCS1(allocator, fullkey);
1030 }
1031
1032 static OSStatus SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
1033 {
1034 ccrsa_full_ctx_t fullkey;
1035 fullkey.full = key->key;
1036
1037 CFAllocatorRef allocator = CFGetAllocator(key);
1038 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, fullkey);
1039
1040 if (NULL == *serialized)
1041 return errSecDecode;
1042 else
1043 return errSecSuccess;
1044 }
1045
1046
1047 static CFDictionaryRef SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
1048 CFDictionaryRef dict = NULL;
1049 CFDataRef fullKeyBlob = NULL;
1050
1051 /* PKCS1 encode the key pair. */
1052 fullKeyBlob = SecRSAPrivateKeyCopyPKCS1(key);
1053 require(fullKeyBlob, errOut);
1054
1055 dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeRSA, fullKeyBlob);
1056
1057 errOut:
1058 CFReleaseSafe(fullKeyBlob);
1059
1060 return dict;
1061 }
1062
1063 static CFStringRef SecRSAPrivateKeyCopyDescription(SecKeyRef key){
1064
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);
1066
1067 }
1068 SecKeyDescriptor kSecRSAPrivateKeyDescriptor = {
1069 kSecKeyDescriptorVersion,
1070 "RSAPrivateKey",
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,
1082 NULL,
1083 SecRSAPrivateKeyCopyPublicSerialization,
1084 };
1085
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);
1092 }
1093
1094
1095 OSStatus SecRSAKeyGeneratePair(CFDictionaryRef parameters,
1096 SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey) {
1097 OSStatus status = errSecParam;
1098
1099 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
1100
1101 SecKeyRef pubKey = NULL;
1102 SecKeyRef privKey = SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor,
1103 (const void*) parameters, 0, kSecGenerateKey);
1104
1105 require(privKey, errOut);
1106
1107 /* Create SecKeyRef's from the pkcs1 encoded keys. */
1108 pubKey = SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor,
1109 privKey->key, 0, kSecExtractPublicFromPrivate);
1110
1111 require(pubKey, errOut);
1112
1113 if (rsaPublicKey) {
1114 *rsaPublicKey = pubKey;
1115 pubKey = NULL;
1116 }
1117 if (rsaPrivateKey) {
1118 *rsaPrivateKey = privKey;
1119 privKey = NULL;
1120 }
1121
1122 status = errSecSuccess;
1123
1124 errOut:
1125 CFReleaseSafe(pubKey);
1126 CFReleaseSafe(privKey);
1127
1128 return status;
1129 }