1/*
2 * Copyright (c) 2006-2010,2012-2014 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
69static 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
83static 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
90void ccrsa_dump_full_key(ccrsa_full_ctx_t key); // Suppress warnings
91void 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
116void ccrsa_dump_public_key(ccrsa_pub_ctx_t key); // Suppress warning.
117void 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. */
132static 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//
145static 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
164static 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
183errOut:
184    return result;
185}
186
187static 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
209errOut:
210    return result;
211}
212
213
214static 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
229static 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
274errOut:
275    return result;
276}
277
278static 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
342errOut:
343    cc_zero(ccrsa_ctx_n(pubkey), s);
344
345    return result;
346}
347
348static 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
437errOut:
438    ccn_zero(ccrsa_ctx_n(pubkey), s);
439    return result;
440}
441
442static 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
511errOut:
512    ccn_zero(ccrsa_ctx_n(pubkey), s);
513
514    return result;
515}
516
517static 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
525static 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
556static 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
570static CFDictionaryRef SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key) {
571    return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeRSA);
572}
573
574static 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
587fail:
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
596SecKeyDescriptor 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    NULL,
613    NULL
614};
615
616/* Public Key API functions. */
617SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator,
618                                   const uint8_t *keyData, CFIndex keyDataLength,
619                                   SecKeyEncoding encoding) {
620    return SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor, keyData,
621                        keyDataLength, encoding);
622}
623
624CFDataRef SecKeyCopyModulus(SecKeyRef key) {
625    ccrsa_pub_ctx_t pubkey;
626    pubkey.pub = key->key;
627
628    size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
629
630	CFAllocatorRef allocator = CFGetAllocator(key);
631	CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size);
632
633    if (modulusData == NULL)
634        return NULL;
635
636	CFDataSetLength(modulusData, m_size);
637
638    ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData));
639
640    return modulusData;
641}
642
643CFDataRef SecKeyCopyExponent(SecKeyRef key) {
644    ccrsa_pub_ctx_t pubkey;
645    pubkey.pub = key->key;
646
647    size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));
648
649	CFAllocatorRef allocator = CFGetAllocator(key);
650	CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size);
651
652    if (exponentData == NULL)
653        return NULL;
654
655	CFDataSetLength(exponentData, e_size);
656
657    ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, CFDataGetMutableBytePtr(exponentData));
658
659    return exponentData;
660}
661
662
663/*
664 *
665 * Private Key
666 *
667 */
668
669/* Private key static functions. */
670static void SecRSAPrivateKeyDestroy(SecKeyRef key) {
671    /* Zero out the public key */
672    ccrsa_full_ctx_t fullkey;
673    fullkey.full = key->key;
674    cc_zero(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey))), fullkey.full);
675}
676
677static int ccrsa_priv_init(ccrsa_priv_ctx_t privkey,
678                           size_t p_size, const uint8_t* p,
679                           size_t q_size, const uint8_t* q,
680                           size_t dp_size, const uint8_t* dp,
681                           size_t dq_size, const uint8_t* dq,
682                           size_t qinv_size, const uint8_t* qinv)
683{
684    int result = -1;
685
686    const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
687    cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));
688
689    if (ccn_read_uint(np, CCZP_PRIME(ccrsa_ctx_private_zp(privkey)), p_size, p))
690        goto errOut;
691    cczp_init(ccrsa_ctx_private_zp(privkey));
692    if (ccn_read_uint(np, ccrsa_ctx_private_dp(privkey), dp_size, dp))
693        goto errOut;
694    if (ccn_read_uint(np, ccrsa_ctx_private_qinv(privkey), qinv_size, qinv))
695        goto errOut;
696
697    if (ccn_read_uint(nq, CCZP_PRIME(ccrsa_ctx_private_zq(privkey)), q_size, q))
698        goto errOut;
699
700    nq = ccn_n(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)));
701    CCZP_N(ccrsa_ctx_private_zq(privkey)) = nq;
702
703    cczp_init(ccrsa_ctx_private_zq(privkey));
704    if (ccn_read_uint(nq, ccrsa_ctx_private_dq(privkey), dq_size, dq))
705        goto errOut;
706
707    result = 0;
708
709errOut:
710    return result;
711}
712
713
714static OSStatus ccrsa_full_decode(ccrsa_full_ctx_t fullkey, size_t pkcs1_size, const uint8_t* pkcs1)
715{
716    OSStatus result = errSecParam;
717
718	DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
719    DERRSAKeyPair decodedKey;
720
721	require_noerr_action(DERParseSequence(&keyItem,
722                                          DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
723                                          &decodedKey, sizeof(decodedKey)),
724                         errOut, result = errSecDecode);
725
726    require_noerr(ccrsa_pub_init(fullkey,
727                                 decodedKey.n.length, decodedKey.n.data,
728                                 decodedKey.e.length, decodedKey.e.data),
729                  errOut);
730    ccn_read_uint(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey),
731                  decodedKey.d.length, decodedKey.d.data);
732    {
733        ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);
734        CCZP_N(ccrsa_ctx_private_zp(privkey)) = ccn_nof((ccn_bitsof_n(ccrsa_ctx_n(fullkey)) / 2) + 1);
735        CCZP_N(ccrsa_ctx_private_zq(privkey)) = cczp_n(ccrsa_ctx_private_zp(privkey));
736
737        // TODO: Actually remember decodedKey.d.
738
739        require_noerr(ccrsa_priv_init(privkey,
740                                      decodedKey.p.length, decodedKey.p.data,
741                                      decodedKey.q.length, decodedKey.q.data,
742                                      decodedKey.dp.length, decodedKey.dp.data,
743                                      decodedKey.dq.length, decodedKey.dq.data,
744                                      decodedKey.qInv.length, decodedKey.qInv.data),
745                      errOut);
746    }
747
748    result = errSecSuccess;
749
750errOut:
751    return result;
752}
753
754static OSStatus SecRSAPrivateKeyInit(SecKeyRef key,
755                                     const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
756    OSStatus result = errSecParam;
757
758    ccrsa_full_ctx_t fullkey;
759    fullkey.full = key->key;
760
761    // Set maximum size for parsers
762    ccrsa_ctx_n(fullkey) = ccn_nof(kMaximumRSAKeyBits);
763
764    switch (encoding) {
765        case kSecKeyEncodingBytes: // Octets is PKCS1
766        case kSecKeyEncodingPkcs1:
767            result = ccrsa_full_decode(fullkey, keyDataLength, keyData);
768            break;
769        case kSecGenerateKey:
770        {
771            CFDictionaryRef parameters = (CFDictionaryRef) keyData;
772
773            CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
774            CFIndex keyLengthInBits = getIntValue(ksize);
775
776            if (keyLengthInBits < 256 || keyLengthInBits > kMaximumRSAKeyBits) {
777                secwarning("Invalid or missing key size in: %@", parameters);
778                return errSecKeySizeNotAllowed;
779            }
780
781            /* TODO: Add support for kSecPublicExponent parameter. */
782            static uint8_t e[] = { 0x01, 0x00, 0x01 }; // Default is 65537
783            if (!ccrsa_generate_key(keyLengthInBits, fullkey.full, sizeof(e), e, ccrng_seckey))
784                result = errSecSuccess;
785            break;
786        }
787        default:
788            break;
789    }
790
791    return result;
792}
793
794static OSStatus SecRSAPrivateKeyRawSign(SecKeyRef key, SecPadding padding,
795                                        const uint8_t *dataToSign, size_t dataToSignLen,
796                                        uint8_t *sig, size_t *sigLen) {
797
798    OSStatus result = errSecParam;
799
800    ccrsa_full_ctx_t fullkey;
801    fullkey.full = key->key;
802
803    size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
804    cc_unit s[ccrsa_ctx_n(fullkey)];
805
806    uint8_t* sBytes = (uint8_t*) s;
807
808    require(sigLen, errOut);
809    require(*sigLen >= m_size, errOut);
810
811    switch (padding) {
812        case kSecPaddingNone:
813            // We'll allow modulus size assuming input is smaller than modulus
814            require_quiet(dataToSignLen <= m_size, errOut);
815            require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey), s, dataToSignLen, dataToSign), errOut);
816            require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey), s, ccrsa_ctx_m(fullkey)) < 0, errOut);
817            break;
818
819        case kSecPaddingPKCS1:
820        {
821            // Create PKCS1 padding:
822            //
823            // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
824            //
825            const int kMinimumPadding = 1 + 1 + 8 + 1;
826
827            require_quiet(dataToSignLen <= m_size - kMinimumPadding, errOut);
828
829            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
830
831            while (prefix_zeros--)
832                *sBytes++ = 0x00;
833
834            size_t pad_size = m_size - dataToSignLen;
835
836            *sBytes++ = 0x00;
837            *sBytes++ = RSA_PKCS1_PAD_SIGN;
838
839            size_t ff_size;
840            for(ff_size = pad_size - 3; ff_size > 0; --ff_size)
841                *sBytes++ = 0xFF;
842
843            *sBytes++ = 0x00;
844
845            // Get the user data into s looking like a ccn.
846            memcpy(sBytes, dataToSign, dataToSignLen);
847            ccn_swap(ccrsa_ctx_n(fullkey), s);
848
849            break;
850        }
851        case kSecPaddingOAEP:
852            result = errSecParam;
853        default:
854            goto errOut;
855    }
856
857    ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);
858
859    // Pad with leading zeros to fit in modulus size
860    ccn_write_uint_padded(ccrsa_ctx_n(fullkey), s, m_size, sig);
861    *sigLen = m_size;
862
863    result = errSecSuccess;
864
865errOut:
866    ccn_zero(ccrsa_ctx_n(fullkey), s);
867    return result;
868}
869
870static OSStatus SecRSAPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding,
871                                           const uint8_t *cipherText, size_t cipherTextLen,
872                                           uint8_t *plainText, size_t *plainTextLen) {
873    OSStatus result = errSSLCrypto;
874
875    ccrsa_full_ctx_t fullkey;
876    fullkey.full = key->key;
877
878    size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
879
880    cc_unit s[ccrsa_ctx_n(fullkey)];
881    uint8_t recoveredData[ccn_sizeof_n(ccrsa_ctx_n(fullkey))];
882
883    ccn_read_uint(ccrsa_ctx_n(fullkey), s, cipherTextLen, cipherText);
884    ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);
885
886    const uint8_t* sBytes = (uint8_t*) s;
887    const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(fullkey));
888
889    require(plainTextLen, errOut);
890
891    switch (padding) {
892        case kSecPaddingNone:
893            ccn_swap(ccrsa_ctx_n(fullkey), s);
894            // Skip Zeros since our contract is to do so.
895            while (sBytes < sEnd && *sBytes == 0x00)
896                ++sBytes;
897            break;
898
899        case kSecPaddingPKCS1:
900        {
901            ccn_swap(ccrsa_ctx_n(fullkey), s);
902            // Verify and skip PKCS1 padding:
903            //
904            // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
905            //
906
907            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
908
909            while (prefix_zeros--)
910                require_quiet(*sBytes++ == 0x00, errOut);
911
912            require_quiet(*sBytes++ == 0x00, errOut);
913            require_quiet(*sBytes++ == RSA_PKCS1_PAD_ENCRYPT, errOut);
914
915            while (*sBytes != 0x00) {
916                require_quiet(++sBytes < sEnd, errOut);
917            }
918            // Required to have at least 8 non-zeros
919            require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
920
921            require_quiet(*sBytes == 0x00, errOut);
922            require_quiet(++sBytes < sEnd, errOut);
923            break;
924        }
925        case kSecPaddingOAEP:
926        {
927            size_t length = sizeof(recoveredData);
928
929            require_noerr_quiet(ccrsa_oaep_decode(ccsha1_di(),
930 												  &length, recoveredData,
931                                                  ccn_write_uint_size(ccrsa_ctx_n(fullkey),ccrsa_ctx_m(fullkey)), s
932                                                  ), errOut);
933
934            sBytes = recoveredData;
935            sEnd = recoveredData + length;
936            break;
937        }
938        default:
939            goto errOut;
940    }
941
942    require((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut);
943    *plainTextLen = sEnd - sBytes;
944    memcpy(plainText, sBytes, *plainTextLen);
945
946    result = errSecSuccess;
947
948errOut:
949    bzero(recoveredData, sizeof(recoveredData));
950    ccn_zero(ccrsa_ctx_n(fullkey), s);
951
952    return result;
953}
954
955static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key) {
956    ccrsa_full_ctx_t fullkey;
957    fullkey.full = key->key;
958
959    return ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
960}
961
962static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey)
963{
964    ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);
965
966    const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
967    const cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));
968
969    size_t m_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
970    size_t e_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey));
971    size_t d_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey));
972
973    size_t p_size = ccn_write_int_size(np, cczp_prime(ccrsa_ctx_private_zp(privkey)));
974    size_t q_size = ccn_write_int_size(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)));
975
976    size_t dp_size = ccn_write_int_size(np, ccrsa_ctx_private_dp(privkey));
977    size_t dq_size = ccn_write_int_size(nq, ccrsa_ctx_private_dq(privkey));
978
979    size_t qinv_size = ccn_write_int_size(np, ccrsa_ctx_private_qinv(privkey));
980
981    const size_t seq_size = 3 +
982    DERLengthOfItem(ASN1_INTEGER, m_size) +
983    DERLengthOfItem(ASN1_INTEGER, e_size) +
984    DERLengthOfItem(ASN1_INTEGER, d_size) +
985    DERLengthOfItem(ASN1_INTEGER, p_size) +
986    DERLengthOfItem(ASN1_INTEGER, q_size) +
987    DERLengthOfItem(ASN1_INTEGER, dp_size) +
988    DERLengthOfItem(ASN1_INTEGER, dq_size) +
989    DERLengthOfItem(ASN1_INTEGER, qinv_size);
990
991    const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);
992
993	CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);
994
995    if (pkcs1 == NULL)
996        return NULL;
997
998	CFDataSetLength(pkcs1, result_size);
999
1000    uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
1001
1002    *bytes++ = ASN1_CONSTR_SEQUENCE;
1003
1004    DERSize itemLength = 4;
1005    DEREncodeLength(seq_size, bytes, &itemLength);
1006    bytes += itemLength;
1007
1008    *bytes++ = ASN1_INTEGER;
1009    *bytes++ = 0x01;
1010    *bytes++ = 0x00;
1011
1012    ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey), m_size, &bytes);
1013    ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey), e_size, &bytes);
1014    ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey), d_size, &bytes);
1015
1016    ccasn_encode_int(np, cczp_prime(ccrsa_ctx_private_zp(privkey)), p_size, &bytes);
1017    ccasn_encode_int(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)), q_size, &bytes);
1018    ccasn_encode_int(np, ccrsa_ctx_private_dp(privkey), dp_size, &bytes);
1019    ccasn_encode_int(nq, ccrsa_ctx_private_dq(privkey), dq_size, &bytes);
1020    ccasn_encode_int(np, ccrsa_ctx_private_qinv(privkey), qinv_size, &bytes);
1021
1022    return pkcs1;
1023}
1024
1025static CFDataRef SecRSAPrivateKeyCopyPKCS1(SecKeyRef key)
1026{
1027    ccrsa_full_ctx_t fullkey;
1028    fullkey.full = key->key;
1029
1030	CFAllocatorRef allocator = CFGetAllocator(key);
1031    return SecRSAPrivateKeyCreatePKCS1(allocator, fullkey);
1032}
1033
1034static OSStatus SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
1035{
1036    ccrsa_full_ctx_t fullkey;
1037    fullkey.full = key->key;
1038
1039	CFAllocatorRef allocator = CFGetAllocator(key);
1040    *serialized = SecRSAPublicKeyCreatePKCS1(allocator, fullkey);
1041
1042    if (NULL == *serialized)
1043        return errSecDecode;
1044    else
1045        return errSecSuccess;
1046}
1047
1048
1049static CFDictionaryRef SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
1050	CFDictionaryRef dict = NULL;
1051	CFDataRef fullKeyBlob = NULL;
1052
1053	/* PKCS1 encode the key pair. */
1054	fullKeyBlob = SecRSAPrivateKeyCopyPKCS1(key);
1055    require(fullKeyBlob, errOut);
1056
1057	dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeRSA, fullKeyBlob);
1058
1059errOut:
1060	CFReleaseSafe(fullKeyBlob);
1061
1062	return dict;
1063}
1064
1065static CFStringRef SecRSAPrivateKeyCopyDescription(SecKeyRef key){
1066
1067	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
1069}
1070SecKeyDescriptor kSecRSAPrivateKeyDescriptor = {
1071    kSecKeyDescriptorVersion,
1072    "RSAPrivateKey",
1073    ccrsa_full_ctx_size(kMaximumRSAKeyBytes), /* extraBytes */
1074    SecRSAPrivateKeyInit,
1075    SecRSAPrivateKeyDestroy,
1076    SecRSAPrivateKeyRawSign,
1077    NULL, /* SecKeyRawVerifyMethod */
1078    NULL, /* SecKeyEncryptMethod */
1079    SecRSAPrivateKeyRawDecrypt,
1080    NULL, /* SecKeyComputeMethod */
1081    SecRSAPrivateKeyBlockSize,
1082	SecRSAPrivateKeyCopyAttributeDictionary,
1083    SecRSAPrivateKeyCopyDescription,
1084    NULL,
1085    SecRSAPrivateKeyCopyPublicSerialization,
1086    NULL,
1087    NULL
1088};
1089
1090/* Private Key API functions. */
1091SecKeyRef SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator,
1092                                    const uint8_t *keyData, CFIndex keyDataLength,
1093                                    SecKeyEncoding encoding) {
1094    return SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor, keyData,
1095                        keyDataLength, encoding);
1096}
1097
1098
1099OSStatus SecRSAKeyGeneratePair(CFDictionaryRef parameters,
1100                               SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey) {
1101    OSStatus status = errSecParam;
1102
1103    CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
1104
1105    SecKeyRef pubKey = NULL;
1106    SecKeyRef privKey = SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor,
1107                                     (const void*) parameters, 0, kSecGenerateKey);
1108
1109    require(privKey, errOut);
1110
1111	/* Create SecKeyRef's from the pkcs1 encoded keys. */
1112    pubKey = SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor,
1113                          privKey->key, 0, kSecExtractPublicFromPrivate);
1114
1115    require(pubKey, errOut);
1116
1117    if (rsaPublicKey) {
1118        *rsaPublicKey = pubKey;
1119        pubKey = NULL;
1120    }
1121    if (rsaPrivateKey) {
1122        *rsaPrivateKey = privKey;
1123        privKey = NULL;
1124    }
1125
1126    status = errSecSuccess;
1127
1128errOut:
1129    CFReleaseSafe(pubKey);
1130    CFReleaseSafe(privKey);
1131
1132	return status;
1133}
1134