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
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};
613
614/* Public Key API functions. */
615SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator,
616                                   const uint8_t *keyData, CFIndex keyDataLength,
617                                   SecKeyEncoding encoding) {
618    return SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor, keyData,
619                        keyDataLength, encoding);
620}
621
622CFDataRef 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
641CFDataRef 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. */
668static 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
675static 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
707errOut:
708    return result;
709}
710
711
712static 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
748errOut:
749    return result;
750}
751
752static 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
792static 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
863errOut:
864    ccn_zero(ccrsa_ctx_n(fullkey), s);
865    return result;
866}
867
868static 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
946errOut:
947    bzero(recoveredData, sizeof(recoveredData));
948    ccn_zero(ccrsa_ctx_n(fullkey), s);
949
950    return result;
951}
952
953static 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
960static 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
1023static 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
1032static 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
1047static 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
1057errOut:
1058	CFReleaseSafe(fullKeyBlob);
1059
1060	return dict;
1061}
1062
1063static 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}
1068SecKeyDescriptor 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. */
1087SecKeyRef 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
1095OSStatus 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
1124errOut:
1125    CFReleaseSafe(pubKey);
1126    CFReleaseSafe(privKey);
1127
1128	return status;
1129}
1130