1/*
2 * Copyright (c) 2012 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// #define COMMON_RSA_FUNCTIONS
25#include "CommonRSACryptor.h"
26#include "CommonDigest.h"
27#include "CommonDigestSPI.h"
28#include "CommonDigestPriv.h"
29
30#include "CommonRandomSPI.h"
31#include <corecrypto/ccrsa.h>
32#include <corecrypto/ccrsa_priv.h>
33#include <corecrypto/ccasn1.h>
34
35#if 0
36#include "asn1Types.h"
37#include "DER_Keys.h"
38#include "DER_Encode.h"
39#endif
40
41
42#include "ccErrors.h"
43#include "ccMemory.h"
44#include "ccdebug.h"
45#include <AssertMacros.h>
46
47#pragma mark internal
48
49#define kCCMaximumRSAKeyBits 4096
50#define kCCMaximumRSAKeyBytes ccn_sizeof(kCCMaximumRSAKeyBits)
51#define kCCRSAKeyContextSize ccrsa_full_ctx_size(kCCMaximumRSAKeyBytes)
52#define RSA_PKCS1_PAD_ENCRYPT	0x02
53
54
55typedef struct _CCRSACryptor {
56    ccrsa_full_ctx_decl(kCCMaximumRSAKeyBits, fk);
57    size_t keySize;
58    CCRSAKeyType keyType;
59} CCRSACryptor;
60
61static CCRSACryptor *
62ccMallocRSACryptor(size_t nbits, CCRSAKeyType keyType)
63{
64    CCRSACryptor *retval;
65    cc_size n = ccn_nof(nbits);
66    if((retval = CC_XMALLOC(sizeof(CCRSACryptor))) == NULL) return NULL;
67    retval->keySize = nbits;
68    ccrsa_ctx_n(retval->fk) = n;
69    return retval;
70}
71
72static void
73ccRSACryptorClear(CCRSACryptorRef theKey)
74{
75    CCRSACryptor *key = (CCRSACryptor *) theKey;
76    if(!key) return;
77    CC_XZEROMEM(key, sizeof(CCRSACryptor));
78    CC_XFREE(key, sizeof(CCRSACryptor));
79}
80
81static inline size_t
82ccRSAkeysize(CCRSACryptor *cryptor) {
83    return ccn_bitlen(ccrsa_ctx_n(cryptor->fk), ccrsa_ctx_m(cryptor->fk));
84}
85
86/*
87
88 This is done for FIPS.  Basically we make sure that the two keys will work to encrypt/decrypt
89 each other's data.  This will test up to 4K bit keys.
90
91*/
92
93#define MAXKEYTEST 512
94
95static bool
96ccRSApairwiseConsistencyCheck(CCRSACryptorRef privateKey, CCRSACryptorRef publicKey)
97{
98	CCCryptorStatus status = kCCSuccess;
99	size_t theDataLen = MAXKEYTEST, resultLen, recoveryLen;
100	uint8_t theData[MAXKEYTEST];
101	uint8_t theResult[MAXKEYTEST];
102	uint8_t theRecovered[MAXKEYTEST];
103
104    /*
105
106     the RSA keysize had better be equal - we convert keysizes to bytes since we need to
107     work with the appropriate size data buffers for tests.
108
109     */
110
111    theDataLen = CCRSAGetKeySize(privateKey) / 8;
112    if(theDataLen > MAXKEYTEST || theDataLen != (size_t) (CCRSAGetKeySize(publicKey) / 8)) {
113        return false;
114    }
115
116    /* Fill the input buffer for the test */
117
118    CC_XMEMSET(theData, 0x0a, theDataLen);
119
120    /* Encrypt the buffer with the private key then be sure the output isn't the same as the input */
121    resultLen = theDataLen;
122    status = CCRSACryptorCrypt(privateKey, theData, theDataLen, theResult, &resultLen);
123
124	if (kCCSuccess != status) {
125        return false;
126    }
127
128    if(CC_XMEMCMP(theData, theResult, theDataLen) == 0) {
129        return false;
130    }
131
132    /* Decrypt the buffer with the public key and be sure the output matches the original input */
133
134    recoveryLen = theDataLen;
135    status = CCRSACryptorCrypt(publicKey, theResult, resultLen, theRecovered, &recoveryLen);
136
137	if (kCCSuccess != status) {
138        return false;
139    }
140
141    if(recoveryLen != theDataLen) {
142        return false;
143    }
144
145    if(CC_XMEMCMP(theData, theRecovered, theDataLen) != 0) {
146        return false;
147    }
148
149    /* Cleanup and leave */
150
151    CC_XZEROMEM(theData, MAXKEYTEST);
152    CC_XZEROMEM(theResult, MAXKEYTEST);
153    CC_XZEROMEM(theRecovered, MAXKEYTEST);
154
155	return true;
156}
157
158
159#pragma mark APIDone
160
161CCCryptorStatus
162CCRSACryptorGeneratePair(size_t keysize, uint32_t e, CCRSACryptorRef *publicKey, CCRSACryptorRef *privateKey)
163{
164    CCCryptorStatus retval;
165    CCRSACryptor *privateCryptor = NULL;
166    CCRSACryptor *publicCryptor = NULL;
167    struct ccrng_state *theRng1 = ccDRBGGetRngState();
168    struct ccrng_state *theRng2 = ccDevRandomGetRngState();
169
170    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
171    // ccrsa_generate_key() requires the exponent as length / pointer to bytes
172    cc_unit cc_unit_e = (cc_unit) e;
173
174    size_t eSize = ccn_write_int_size(1, &cc_unit_e);
175    uint8_t eBytes[eSize];
176    ccn_write_int(1, &cc_unit_e, eSize, eBytes);
177
178    *publicKey = *privateKey = NULL;
179
180    __Require_Action((privateCryptor = ccMallocRSACryptor(keysize, ccRSAKeyPrivate)) != NULL, errOut, retval = kCCMemoryFailure);
181
182    // __Require_Action((ccrsa_generate_key(keysize, privateCryptor->rsaKey.full, sizeof(e), &e, theRng) == 0), errOut, retval = kCCDecodeError);
183    __Require_Action((ccrsa_generate_931_key(keysize, privateCryptor->fk, eSize, eBytes, theRng1, theRng2) == 0), errOut, retval = kCCDecodeError);
184
185    privateCryptor->keyType = ccRSAKeyPrivate;
186
187    __Require_Action((publicCryptor = CCRSACryptorGetPublicKeyFromPrivateKey(privateCryptor)) != NULL, errOut, retval = kCCMemoryFailure);
188
189    *publicKey = publicCryptor;
190    *privateKey = privateCryptor;
191
192    __Require_Action(ccRSApairwiseConsistencyCheck(*privateKey, *publicKey) == true, errOut, retval = kCCDecodeError);
193
194    return kCCSuccess;
195
196errOut:
197    if(privateCryptor) ccRSACryptorClear(privateCryptor);
198    if(publicCryptor) ccRSACryptorClear(publicCryptor);
199    *publicKey = *privateKey = NULL;
200    return retval;
201}
202
203CCRSACryptorRef CCRSACryptorGetPublicKeyFromPrivateKey(CCRSACryptorRef privateCryptorRef)
204{
205    CCRSACryptor *publicCryptor = NULL, *privateCryptor = privateCryptorRef;
206
207    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
208    if((publicCryptor = ccMallocRSACryptor(privateCryptor->keySize, ccRSAKeyPublic)) == NULL)  return NULL;
209    ccrsa_init_pub(ccrsa_ctx_public(publicCryptor->fk), ccrsa_ctx_m(privateCryptor->fk), ccrsa_ctx_e(privateCryptor->fk));
210    publicCryptor->keyType = ccRSAKeyPublic;
211    return publicCryptor;
212}
213
214CCRSAKeyType CCRSAGetKeyType(CCRSACryptorRef key)
215{
216    CCRSACryptor *cryptor = key;
217    CCRSAKeyType retval;
218
219    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
220    if(key == NULL) return ccRSABadKey;
221    retval = cryptor->keyType;
222    if(retval != ccRSAKeyPublic && retval != ccRSAKeyPrivate) return ccRSABadKey;
223    return retval;
224}
225
226int CCRSAGetKeySize(CCRSACryptorRef key)
227{
228    CCRSACryptor *cryptor = key;
229    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
230    if(key == NULL) return kCCParamError;
231
232    return (int) cryptor->keySize;
233}
234
235void
236CCRSACryptorRelease(CCRSACryptorRef key)
237{
238    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
239    ccRSACryptorClear(key);
240}
241
242
243CCCryptorStatus CCRSACryptorImport(const void *keyPackage, size_t keyPackageLen, CCRSACryptorRef *key)
244{
245    CCRSACryptor *cryptor = NULL;
246    CCCryptorStatus retval;
247    CCRSAKeyType keyToMake;
248    cc_size keyN;
249
250    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
251    if(!keyPackage || !key) return kCCParamError;
252    if((keyN = ccrsa_import_priv_n(keyPackageLen, keyPackage)) != 0) keyToMake = ccRSAKeyPrivate;
253    else if((keyN = ccrsa_import_pub_n(keyPackageLen, keyPackage)) != 0) keyToMake = ccRSAKeyPublic;
254    else return kCCDecodeError;
255
256    __Require_Action((cryptor = ccMallocRSACryptor(kCCMaximumRSAKeyBits, keyToMake)) != NULL, errOut, retval = kCCMemoryFailure);
257
258    switch(keyToMake) {
259        case ccRSAKeyPublic:
260            ccrsa_ctx_n(ccrsa_ctx_public(cryptor->fk)) = keyN;
261            if(ccrsa_import_pub(ccrsa_ctx_public(cryptor->fk), keyPackageLen, keyPackage)) {
262                ccRSACryptorClear(cryptor);
263                return kCCDecodeError;
264            }
265            break;
266        case ccRSAKeyPrivate:
267            ccrsa_ctx_n(cryptor->fk) = keyN;
268            if(ccrsa_import_priv(cryptor->fk, keyPackageLen, keyPackage)) {
269                ccRSACryptorClear(cryptor);
270                return kCCDecodeError;
271            }
272            break;
273    }
274    cryptor->keyType = keyToMake;
275    *key = cryptor;
276    cryptor->keySize = ccRSAkeysize(cryptor);
277
278    return kCCSuccess;
279
280errOut:
281    if(cryptor) ccRSACryptorClear(cryptor);
282    *key = NULL;
283    return retval;
284}
285
286
287CCCryptorStatus CCRSACryptorExport(CCRSACryptorRef cryptor, void *out, size_t *outLen)
288{
289    CCCryptorStatus retval = kCCSuccess;
290    size_t bufsiz;
291
292    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
293    if(!cryptor || !out) return kCCParamError;
294    switch(cryptor->keyType) {
295        case ccRSAKeyPublic:
296            bufsiz = ccrsa_export_pub_size(ccrsa_ctx_public(cryptor->fk));
297            if(*outLen <= bufsiz) {
298                *outLen = bufsiz;
299                return kCCBufferTooSmall;
300            }
301            *outLen = bufsiz;
302            if(ccrsa_export_pub(ccrsa_ctx_public(cryptor->fk), bufsiz, out))
303                return kCCDecodeError;
304            break;
305        case ccRSAKeyPrivate:
306            bufsiz = ccrsa_export_priv_size(cryptor->fk);
307            if(*outLen < bufsiz) {
308                *outLen = bufsiz;
309                return kCCBufferTooSmall;
310            }
311            *outLen = bufsiz;
312            if(ccrsa_export_priv(cryptor->fk, bufsiz, out))
313                return kCCDecodeError;
314            break;
315        default:
316            retval = kCCParamError;
317    }
318    return retval;
319}
320
321
322
323
324
325
326
327CCCryptorStatus
328CCRSACryptorEncrypt(CCRSACryptorRef publicKey, CCAsymmetricPadding padding, const void *plainText, size_t plainTextLen, void *cipherText, size_t *cipherTextLen,
329	const void *tagData, size_t tagDataLen, CCDigestAlgorithm digestType)
330{
331    CCCryptorStatus retval = kCCSuccess;
332
333    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
334    if(!publicKey || !cipherText || !plainText || !cipherTextLen) return kCCParamError;
335
336    switch(padding) {
337        case ccPKCS1Padding:
338            if(ccrsa_encrypt_eme_pkcs1v15(ccrsa_ctx_public(publicKey->fk), ccDRBGGetRngState(), cipherTextLen, cipherText, plainTextLen, (uint8_t *) plainText)  != 0)
339                retval =  kCCDecodeError;
340            break;
341        case ccOAEPPadding:
342            if(ccrsa_encrypt_oaep(ccrsa_ctx_public(publicKey->fk), CCDigestGetDigestInfo(digestType), ccDRBGGetRngState(), cipherTextLen, cipherText, plainTextLen, (uint8_t *) plainText, tagDataLen, tagData) != 0)
343                retval =  kCCDecodeError;
344            break;
345        default:
346            retval = kCCParamError;
347            goto errOut;
348
349    }
350
351errOut:
352    return retval;
353}
354
355
356
357CCCryptorStatus
358CCRSACryptorDecrypt(CCRSACryptorRef privateKey, CCAsymmetricPadding padding, const void *cipherText, size_t cipherTextLen,
359				 void *plainText, size_t *plainTextLen, const void *tagData, size_t tagDataLen, CCDigestAlgorithm digestType)
360{
361    CCCryptorStatus retval = kCCSuccess;
362
363    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
364    if(!privateKey || !cipherText || !plainText || !plainTextLen) return kCCParamError;
365
366    switch (padding) {
367        case ccPKCS1Padding:
368            if(ccrsa_decrypt_eme_pkcs1v15(privateKey->fk, plainTextLen, plainText, cipherTextLen, (uint8_t *) cipherText) != 0)
369                retval =  kCCDecodeError;
370            break;
371        case ccOAEPPadding:
372            if(ccrsa_decrypt_oaep(privateKey->fk, CCDigestGetDigestInfo(digestType), plainTextLen, plainText, cipherTextLen, (uint8_t *) cipherText,
373                                  tagDataLen, tagData) != 0)
374                retval =  kCCDecodeError;
375            break;
376        default:
377            goto errOut;
378    }
379
380errOut:
381
382    return retval;
383}
384
385CCCryptorStatus
386CCRSACryptorCrypt(CCRSACryptorRef rsaKey, const void *in, size_t inLen, void *out, size_t *outLen)
387{
388    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
389    if(!rsaKey || !in || !out || !outLen) return kCCParamError;
390
391    size_t keysizeBytes = (rsaKey->keySize+7)/8;
392
393    if(inLen != keysizeBytes || *outLen < keysizeBytes) return kCCMemoryFailure;
394
395    cc_size n = ccrsa_ctx_n(rsaKey->fk);
396    cc_unit buf[n];
397    ccn_read_uint(n, buf, inLen, in);
398
399    switch(rsaKey->keyType) {
400        case ccRSAKeyPublic:
401            ccrsa_pub_crypt(ccrsa_ctx_public(rsaKey->fk), buf, buf);
402            break;
403        case ccRSAKeyPrivate:
404            ccrsa_priv_crypt(ccrsa_ctx_private(rsaKey->fk), buf, buf);
405            break;
406        default:
407            return kCCParamError;
408    }
409
410    *outLen = keysizeBytes;
411    ccn_write_uint_padded(n, buf, *outLen, out);
412    return kCCSuccess;
413}
414
415
416#if 0
417static inline int cczp_read_uint(cczp_t r, size_t data_size, const uint8_t *data)
418{
419    if(ccn_read_uint(ccn_nof_size(data_size), CCZP_PRIME(r), data_size, data) != 0) return -1;
420    CCZP_N(r) = ccn_nof_size(data_size);
421    cczp_init(r);
422    return 0;
423}
424#endif
425
426static inline
427CCCryptorStatus ccn_write_arg(size_t n, const cc_unit *source, uint8_t *dest, size_t *destLen)
428{
429    size_t len;
430    if((len = ccn_write_uint_size(n, source)) > *destLen) {
431        return kCCMemoryFailure;
432    }
433    *destLen = len;
434    ccn_write_uint(n, source, *destLen, dest);
435    return kCCSuccess;
436}
437
438
439CCCryptorStatus
440CCRSACryptorCreatePairFromData(uint32_t e,
441    uint8_t *xp1, size_t xp1Length,
442    uint8_t *xp2, size_t xp2Length,
443    uint8_t *xp, size_t xpLength,
444    uint8_t *xq1, size_t xq1Length,
445    uint8_t *xq2, size_t xq2Length,
446    uint8_t *xq, size_t xqLength,
447    CCRSACryptorRef *publicKey, CCRSACryptorRef *privateKey,
448    uint8_t *retp, size_t *retpLength,
449    uint8_t *retq, size_t *retqLength,
450    uint8_t *retm, size_t *retmLength,
451    uint8_t *retd, size_t *retdLength)
452{
453    CCCryptorStatus retval;
454    CCRSACryptor *privateCryptor = NULL;
455    CCRSACryptor *publicCryptor = NULL;
456    cc_unit x_p1[ccn_nof_size(xp1Length)];
457    cc_unit x_p2[ccn_nof_size(xp2Length)];
458    cc_unit x_p[ccn_nof_size(xpLength)];
459    cc_unit x_q1[ccn_nof_size(xq1Length)];
460    cc_unit x_q2[ccn_nof_size(xq2Length)];
461    cc_unit x_q[ccn_nof_size(xqLength)];
462    cc_unit e_value[1];
463    size_t nbits = xpLength * 8 + xqLength * 8; // or we'll add this as a parameter.  This appears to be correct for FIPS
464    cc_size n = ccn_nof(nbits);
465    cc_unit p[n], q[n], m[n], d[n];
466    cc_size np, nq, nm, nd;
467
468    np = nq = nm = nd = n;
469
470    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
471    e_value[0] = (cc_unit) e;
472
473    __Require_Action((privateCryptor = ccMallocRSACryptor(nbits, ccRSAKeyPrivate)) != NULL, errOut, retval = kCCMemoryFailure);
474
475    __Require_Action(ccn_read_uint(ccn_nof_size(xp1Length), x_p1, xp1Length, xp1) == 0, errOut, retval = kCCParamError);
476    __Require_Action(ccn_read_uint(ccn_nof_size(xp2Length), x_p2, xp2Length, xp2)== 0, errOut, retval = kCCParamError);
477    __Require_Action(ccn_read_uint(ccn_nof_size(xpLength), x_p, xpLength, xp) == 0, errOut, retval = kCCParamError);
478    __Require_Action(ccn_read_uint(ccn_nof_size(xq1Length), x_q1, xq1Length, xq1) == 0, errOut, retval = kCCParamError);
479    __Require_Action(ccn_read_uint(ccn_nof_size(xq2Length), x_q2, xq2Length, xq2) == 0, errOut, retval = kCCParamError);
480    __Require_Action(ccn_read_uint(ccn_nof_size(xqLength), x_q, xqLength, xq) == 0, errOut, retval = kCCParamError);
481
482	__Require_Action(ccrsa_make_931_key(nbits, 1, e_value,
483                                        ccn_nof_size(xp1Length), x_p1, ccn_nof_size(xp2Length), x_p2, ccn_nof_size(xpLength), x_p,
484                                        ccn_nof_size(xq1Length), x_q1, ccn_nof_size(xq2Length), x_q2, ccn_nof_size(xqLength), x_q,
485                                        privateCryptor->fk,
486                                        &np, p,
487                                        &nq, q,
488                                        &nm, m,
489                                        &nd, d) == 0, errOut, retval = kCCDecodeError);
490
491    privateCryptor->keyType = ccRSAKeyPrivate;
492
493    __Require_Action((publicCryptor = CCRSACryptorGetPublicKeyFromPrivateKey(privateCryptor)) != NULL, errOut, retval = kCCMemoryFailure);
494
495    *publicKey = publicCryptor;
496    *privateKey = privateCryptor;
497    ccn_write_arg(np, p, retp, retpLength);
498    ccn_write_arg(nq, q, retq, retqLength);
499    ccn_write_arg(nm, m, retm, retmLength);
500    ccn_write_arg(nd, d, retd, retdLength);
501
502    return kCCSuccess;
503
504errOut:
505    if(privateCryptor) ccRSACryptorClear(privateCryptor);
506    if(publicCryptor) ccRSACryptorClear(publicCryptor);
507    // CLEAR the bits
508    *publicKey = *privateKey = NULL;
509    return retval;
510
511}
512
513
514
515CCCryptorStatus
516CCRSACryptorCreateFromData( CCRSAKeyType keyType, uint8_t *modulus, size_t modulusLength,
517                            uint8_t *exponent, size_t exponentLength,
518                            uint8_t *p, size_t pLength, uint8_t *q, size_t qLength,
519                            CCRSACryptorRef *ref)
520{
521    CCCryptorStatus retval = kCCSuccess;
522	CCRSACryptor *rsaKey = NULL;
523    size_t n = ccn_nof_size(modulusLength);
524    cc_unit m[n];
525
526    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
527    __Require_Action(ccn_read_uint(n, m, modulusLength, modulus) == 0, errOut, retval = kCCParamError);
528    size_t nbits = ccn_bitlen(n, m);
529
530    __Require_Action((rsaKey = ccMallocRSACryptor(nbits, keyType)) != NULL, errOut, retval = kCCMemoryFailure);
531
532    __Require_Action(ccn_read_uint(n, ccrsa_ctx_m(rsaKey->fk), modulusLength, modulus) == 0, errOut, retval = kCCParamError);
533    __Require_Action(ccn_read_uint(n, ccrsa_ctx_e(rsaKey->fk), exponentLength, exponent) == 0, errOut, retval = kCCParamError);
534    cczp_init(ccrsa_ctx_zm(rsaKey->fk));
535    rsaKey->keySize = ccn_bitlen(n, ccrsa_ctx_m(rsaKey->fk));
536
537	switch(keyType) {
538		case ccRSAKeyPublic:
539            rsaKey->keyType = ccRSAKeyPublic;
540            break;
541
542		case ccRSAKeyPrivate: {
543            ccrsa_priv_ctx_t privk = ccrsa_ctx_private(rsaKey->fk);
544            size_t psize = ccn_nof_size(pLength);
545            size_t qsize = ccn_nof_size(qLength);
546
547
548            CCZP_N(ccrsa_ctx_private_zp(privk)) = psize;
549            __Require_Action(ccn_read_uint(psize, CCZP_PRIME(ccrsa_ctx_private_zp(privk)), pLength, p) == 0, errOut, retval = kCCParamError);
550            CCZP_N(ccrsa_ctx_private_zq(privk)) = qsize;
551            __Require_Action(ccn_read_uint(qsize, CCZP_PRIME(ccrsa_ctx_private_zq(privk)), qLength, q) == 0, errOut, retval = kCCParamError);
552
553            ccrsa_crt_makekey(ccrsa_ctx_zm(rsaKey->fk), ccrsa_ctx_e(rsaKey->fk), ccrsa_ctx_d(rsaKey->fk),
554                              ccrsa_ctx_private_zp(privk),
555                              ccrsa_ctx_private_dp(privk), ccrsa_ctx_private_qinv(privk),
556                              ccrsa_ctx_private_zq(privk), ccrsa_ctx_private_dq(privk));
557
558            rsaKey->keyType = ccRSAKeyPrivate;
559
560       		break;
561        }
562
563		default:
564            retval = kCCParamError;
565			goto errOut;
566	}
567	*ref = rsaKey;
568	return kCCSuccess;
569
570errOut:
571	if(rsaKey) ccRSACryptorClear(rsaKey);
572	return retval;
573}
574
575
576
577
578CCCryptorStatus
579CCRSAGetKeyComponents(CCRSACryptorRef rsaKey, uint8_t *modulus, size_t *modulusLength, uint8_t *exponent, size_t *exponentLength,
580                      uint8_t *p, size_t *pLength, uint8_t *q, size_t *qLength)
581{
582    CCRSACryptor *rsa = rsaKey;
583
584    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
585	switch(rsa->keyType) {
586		case ccRSAKeyPublic: {
587            if(ccrsa_get_pubkey_components(ccrsa_ctx_public(rsaKey->fk), modulus, modulusLength, exponent, exponentLength)) return kCCParamError;
588            break;
589        }
590
591		case ccRSAKeyPrivate: {
592            if(ccrsa_get_fullkey_components(rsaKey->fk, modulus, modulusLength, exponent, exponentLength,
593                                             p, pLength, q, qLength)) return kCCParamError;
594            break;
595        }
596
597		default:
598			return kCCParamError;
599    }
600
601    return kCCSuccess;
602}
603
604
605CCCryptorStatus
606CCRSACryptorSign(CCRSACryptorRef privateKey, CCAsymmetricPadding padding,
607                 const void *hashToSign, size_t hashSignLen,
608                 CCDigestAlgorithm digestType, size_t saltLen,
609                 void *signedData, size_t *signedDataLen)
610{
611    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
612    if(!privateKey || !hashToSign || !signedData) return kCCParamError;
613
614    switch(padding) {
615        case ccPKCS1Padding:
616            if(ccrsa_sign_pkcs1v15(privateKey->fk, CCDigestGetDigestInfo(digestType)->oid,
617                                   hashSignLen, hashToSign, signedDataLen, signedData) != 0)
618                return kCCDecodeError;
619            break;
620
621        case ccOAEPPadding:
622            if(ccrsa_sign_oaep(privateKey->fk, CCDigestGetDigestInfo(digestType),
623                               ccDRBGGetRngState(), hashSignLen, hashToSign,
624                               signedDataLen, signedData) != 0)
625                return kCCDecodeError;
626            break;
627        case ccX931Padding:
628        case ccPKCS1PaddingRaw:
629        case ccPaddingNone:
630        default:
631            return kCCParamError;
632            break;
633    }
634    return kCCSuccess;
635}
636
637
638
639CCCryptorStatus
640CCRSACryptorVerify(CCRSACryptorRef publicKey, CCAsymmetricPadding padding,
641                   const void *hash, size_t hashLen,
642                   CCDigestAlgorithm digestType, size_t saltLen,
643                   const void *signedData, size_t signedDataLen)
644{
645    bool valid;
646
647    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
648    if(!publicKey || !hash || !signedData) return kCCParamError;
649
650    switch(padding) {
651        case ccPKCS1Padding:
652            if(ccrsa_verify_pkcs1v15(ccrsa_ctx_public(publicKey->fk), CCDigestGetDigestInfo(digestType)->oid,
653                                     hashLen, hash, signedDataLen, signedData, &valid) != 0)
654                return kCCDecodeError;
655            if(!valid) return kCCDecodeError;
656            break;
657
658        case ccOAEPPadding:
659            if(ccrsa_verify_oaep(ccrsa_ctx_public(publicKey->fk),  CCDigestGetDigestInfo(digestType),
660                                 hashLen, hash, signedDataLen, signedData, &valid) != 0)
661                return kCCDecodeError;
662            if(!valid) return kCCDecodeError;
663            break;
664        case ccX931Padding:
665        case ccPKCS1PaddingRaw:
666        case ccPaddingNone:
667        default:
668            return kCCParamError;
669            break;
670    }
671    return kCCSuccess;
672}
673
674#pragma mark APINotDone
675#ifdef NEVER
676
677// This was only here for FIPS.  If we move FIPS to the corecrypto layer it will need to be there.
678
679CCCryptorStatus
680CCRSACryptorDecodePayloadPKCS1(
681                               CCRSACryptorRef publicKey,
682                               const void *cipherText,
683                               size_t cipherTextLen,
684                               void *plainText,
685                               size_t *plainTextLen)
686{
687    int tcReturn;
688	int stat = 0;
689    CCRSACryptor *publicCryptor = publicKey;
690    uint8_t *message;
691    unsigned long messageLen, modulusLen;
692    CCCryptorStatus retval = kCCSuccess;
693
694    modulusLen = CCRSAGetKeySize(publicKey);
695    messageLen = modulusLen / 8;
696
697    if((message = CC_XMALLOC(messageLen)) == NULL) return kCCMemoryFailure;
698
699	tcReturn = rsa_exptmod(cipherText, cipherTextLen, message, messageLen, publicCryptor->keyType, &publicCryptor->key);
700    if(tcReturn) {
701        retval = kCCDecodeError;
702        goto out;
703    }
704    tcReturn = pkcs_1_v1_5_decode(message, messageLen, LTC_PKCS_1_EME, modulusLen, plainText, plainTextLen, &stat);
705    if(tcReturn) {
706        retval = kCCDecodeError;
707        goto out;
708    }
709    if(!stat) {
710        retval = kCCDecodeError;
711        goto out;
712    }
713
714out:
715    CC_XZEROMEM(message, messageLen);
716    CC_XFREE(message, messageLen);
717    return retval;
718}
719
720#endif
721
722
723
724