xref: /onnv-gate/usr/src/common/crypto/rsa/rsa_impl.c (revision 12573:fb4ef506980f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56557Sfr41279  * Common Development and Distribution License (the "License").
66557Sfr41279  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*12573SDina.Nimeh@Sun.COM 
220Sstevel@tonic-gate /*
23*12573SDina.Nimeh@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This file contains RSA helper routines common to
280Sstevel@tonic-gate  * the PKCS11 soft token code and the kernel RSA code.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <sys/types.h>
32*12573SDina.Nimeh@Sun.COM #include <bignum.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #ifdef _KERNEL
350Sstevel@tonic-gate #include <sys/param.h>
360Sstevel@tonic-gate #else
370Sstevel@tonic-gate #include <strings.h>
389127SDina.Nimeh@Sun.COM #include <cryptoutil.h>
390Sstevel@tonic-gate #endif
400Sstevel@tonic-gate 
41*12573SDina.Nimeh@Sun.COM #include <sys/crypto/common.h>
42*12573SDina.Nimeh@Sun.COM #include "rsa_impl.h"
43*12573SDina.Nimeh@Sun.COM 
440Sstevel@tonic-gate /*
45676Sizick  * DER encoding T of the DigestInfo values for MD5, SHA1, and SHA2
460Sstevel@tonic-gate  * from PKCS#1 v2.1: RSA Cryptography Standard Section 9.2 Note 1
470Sstevel@tonic-gate  *
480Sstevel@tonic-gate  * MD5:     (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H
490Sstevel@tonic-gate  * SHA-1:   (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H
50676Sizick  * SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
51676Sizick  * SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H.
52676Sizick  * SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H.
530Sstevel@tonic-gate  *
540Sstevel@tonic-gate  * Where H is the digested output from MD5 or SHA1. We define the constant
550Sstevel@tonic-gate  * byte array (the prefix) here and use it rather than doing the DER
560Sstevel@tonic-gate  * encoding of the OID in a separate routine.
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate const CK_BYTE MD5_DER_PREFIX[MD5_DER_PREFIX_Len] = {0x30, 0x20, 0x30, 0x0c,
590Sstevel@tonic-gate     0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
600Sstevel@tonic-gate     0x04, 0x10};
610Sstevel@tonic-gate 
620Sstevel@tonic-gate const CK_BYTE SHA1_DER_PREFIX[SHA1_DER_PREFIX_Len] = {0x30, 0x21, 0x30,
630Sstevel@tonic-gate     0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
640Sstevel@tonic-gate 
65872Sizick const CK_BYTE SHA1_DER_PREFIX_OID[SHA1_DER_PREFIX_OID_Len] = {0x30, 0x1f, 0x30,
66872Sizick     0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14};
67872Sizick 
68676Sizick const CK_BYTE SHA256_DER_PREFIX[SHA2_DER_PREFIX_Len] = {0x30, 0x31, 0x30, 0x0d,
69676Sizick     0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
70676Sizick     0x00, 0x04, 0x20};
71676Sizick 
72676Sizick const CK_BYTE SHA384_DER_PREFIX[SHA2_DER_PREFIX_Len] = {0x30, 0x41, 0x30, 0x0d,
73676Sizick     0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
74676Sizick     0x00, 0x04, 0x30};
75676Sizick 
76676Sizick const CK_BYTE SHA512_DER_PREFIX[SHA2_DER_PREFIX_Len] = {0x30, 0x51, 0x30, 0x0d,
77676Sizick     0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
78676Sizick     0x00, 0x04, 0x40};
79676Sizick 
809536SDina.Nimeh@Sun.COM const CK_BYTE DEFAULT_PUB_EXPO[DEFAULT_PUB_EXPO_Len] = { 0x01, 0x00, 0x01 };
816557Sfr41279 
82*12573SDina.Nimeh@Sun.COM 
83*12573SDina.Nimeh@Sun.COM static CK_RV
convert_rv(BIG_ERR_CODE err)84*12573SDina.Nimeh@Sun.COM convert_rv(BIG_ERR_CODE err)
85*12573SDina.Nimeh@Sun.COM {
86*12573SDina.Nimeh@Sun.COM 	switch (err) {
87*12573SDina.Nimeh@Sun.COM 
88*12573SDina.Nimeh@Sun.COM 	case BIG_OK:
89*12573SDina.Nimeh@Sun.COM 		return (CKR_OK);
90*12573SDina.Nimeh@Sun.COM 
91*12573SDina.Nimeh@Sun.COM 	case BIG_NO_MEM:
92*12573SDina.Nimeh@Sun.COM 		return (CKR_HOST_MEMORY);
93*12573SDina.Nimeh@Sun.COM 
94*12573SDina.Nimeh@Sun.COM 	case BIG_NO_RANDOM:
95*12573SDina.Nimeh@Sun.COM 		return (CKR_DEVICE_ERROR);
96*12573SDina.Nimeh@Sun.COM 
97*12573SDina.Nimeh@Sun.COM 	case BIG_INVALID_ARGS:
98*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
99*12573SDina.Nimeh@Sun.COM 
100*12573SDina.Nimeh@Sun.COM 	case BIG_DIV_BY_0:
101*12573SDina.Nimeh@Sun.COM 	default:
102*12573SDina.Nimeh@Sun.COM 		return (CKR_GENERAL_ERROR);
103*12573SDina.Nimeh@Sun.COM 	}
104*12573SDina.Nimeh@Sun.COM }
105*12573SDina.Nimeh@Sun.COM 
1066557Sfr41279 /* psize and qsize are in bits */
107*12573SDina.Nimeh@Sun.COM static BIG_ERR_CODE
RSA_key_init(RSAkey * key,int psize,int qsize)1080Sstevel@tonic-gate RSA_key_init(RSAkey *key, int psize, int qsize)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	BIG_ERR_CODE err = BIG_OK;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate /* EXPORT DELETE START */
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	int plen, qlen, nlen;
1150Sstevel@tonic-gate 
1166557Sfr41279 	plen = BITLEN2BIGNUMLEN(psize);
1176557Sfr41279 	qlen = BITLEN2BIGNUMLEN(qsize);
1180Sstevel@tonic-gate 	nlen = plen + qlen;
1190Sstevel@tonic-gate 	key->size = psize + qsize;
1200Sstevel@tonic-gate 	if ((err = big_init(&(key->p), plen)) != BIG_OK)
1210Sstevel@tonic-gate 		return (err);
1220Sstevel@tonic-gate 	if ((err = big_init(&(key->q), qlen)) != BIG_OK)
1230Sstevel@tonic-gate 		goto ret1;
1240Sstevel@tonic-gate 	if ((err = big_init(&(key->n), nlen)) != BIG_OK)
1250Sstevel@tonic-gate 		goto ret2;
1260Sstevel@tonic-gate 	if ((err = big_init(&(key->d), nlen)) != BIG_OK)
1270Sstevel@tonic-gate 		goto ret3;
1280Sstevel@tonic-gate 	if ((err = big_init(&(key->e), nlen)) != BIG_OK)
1290Sstevel@tonic-gate 		goto ret4;
1300Sstevel@tonic-gate 	if ((err = big_init(&(key->dmodpminus1), plen)) != BIG_OK)
1310Sstevel@tonic-gate 		goto ret5;
1320Sstevel@tonic-gate 	if ((err = big_init(&(key->dmodqminus1), qlen)) != BIG_OK)
1330Sstevel@tonic-gate 		goto ret6;
1340Sstevel@tonic-gate 	if ((err = big_init(&(key->pinvmodq), qlen)) != BIG_OK)
1350Sstevel@tonic-gate 		goto ret7;
1360Sstevel@tonic-gate 	if ((err = big_init(&(key->p_rr), plen)) != BIG_OK)
1370Sstevel@tonic-gate 		goto ret8;
1380Sstevel@tonic-gate 	if ((err = big_init(&(key->q_rr), qlen)) != BIG_OK)
1390Sstevel@tonic-gate 		goto ret9;
1400Sstevel@tonic-gate 	if ((err = big_init(&(key->n_rr), nlen)) != BIG_OK)
1410Sstevel@tonic-gate 		goto ret10;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	return (BIG_OK);
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate ret10:
1460Sstevel@tonic-gate 	big_finish(&(key->q_rr));
1470Sstevel@tonic-gate ret9:
1480Sstevel@tonic-gate 	big_finish(&(key->p_rr));
1490Sstevel@tonic-gate ret8:
1500Sstevel@tonic-gate 	big_finish(&(key->pinvmodq));
1510Sstevel@tonic-gate ret7:
1520Sstevel@tonic-gate 	big_finish(&(key->dmodqminus1));
1530Sstevel@tonic-gate ret6:
1540Sstevel@tonic-gate 	big_finish(&(key->dmodpminus1));
1550Sstevel@tonic-gate ret5:
1560Sstevel@tonic-gate 	big_finish(&(key->e));
1570Sstevel@tonic-gate ret4:
1580Sstevel@tonic-gate 	big_finish(&(key->d));
1590Sstevel@tonic-gate ret3:
1600Sstevel@tonic-gate 	big_finish(&(key->n));
1610Sstevel@tonic-gate ret2:
1620Sstevel@tonic-gate 	big_finish(&(key->q));
1630Sstevel@tonic-gate ret1:
1640Sstevel@tonic-gate 	big_finish(&(key->p));
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate /* EXPORT DELETE END */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	return (err);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate 
171*12573SDina.Nimeh@Sun.COM static void
RSA_key_finish(RSAkey * key)1720Sstevel@tonic-gate RSA_key_finish(RSAkey *key)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate /* EXPORT DELETE START */
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	big_finish(&(key->n_rr));
1780Sstevel@tonic-gate 	big_finish(&(key->q_rr));
1790Sstevel@tonic-gate 	big_finish(&(key->p_rr));
1800Sstevel@tonic-gate 	big_finish(&(key->pinvmodq));
1810Sstevel@tonic-gate 	big_finish(&(key->dmodqminus1));
1820Sstevel@tonic-gate 	big_finish(&(key->dmodpminus1));
1830Sstevel@tonic-gate 	big_finish(&(key->e));
1840Sstevel@tonic-gate 	big_finish(&(key->d));
1850Sstevel@tonic-gate 	big_finish(&(key->n));
1860Sstevel@tonic-gate 	big_finish(&(key->q));
1870Sstevel@tonic-gate 	big_finish(&(key->p));
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate /* EXPORT DELETE END */
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate /*
194*12573SDina.Nimeh@Sun.COM  * Generate RSA key
1950Sstevel@tonic-gate  */
196*12573SDina.Nimeh@Sun.COM static CK_RV
generate_rsa_key(RSAkey * key,int psize,int qsize,BIGNUM * pubexp,int (* rfunc)(void *,size_t))197*12573SDina.Nimeh@Sun.COM generate_rsa_key(RSAkey *key, int psize, int qsize, BIGNUM *pubexp,
198*12573SDina.Nimeh@Sun.COM     int (*rfunc)(void *, size_t))
1990Sstevel@tonic-gate {
200*12573SDina.Nimeh@Sun.COM 	CK_RV		rv = CKR_OK;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate /* EXPORT DELETE START */
2030Sstevel@tonic-gate 
204*12573SDina.Nimeh@Sun.COM 	int		(*rf)(void *, size_t);
205*12573SDina.Nimeh@Sun.COM 	BIGNUM		a, b, c, d, e, f, g, h;
206*12573SDina.Nimeh@Sun.COM 	int		len, keylen, size;
207*12573SDina.Nimeh@Sun.COM 	BIG_ERR_CODE	brv = BIG_OK;
208*12573SDina.Nimeh@Sun.COM 
209*12573SDina.Nimeh@Sun.COM 	size = psize + qsize;
210*12573SDina.Nimeh@Sun.COM 	keylen = BITLEN2BIGNUMLEN(size);
211*12573SDina.Nimeh@Sun.COM 	len = keylen * 2 + 1;
212*12573SDina.Nimeh@Sun.COM 	key->size = size;
213*12573SDina.Nimeh@Sun.COM 
214*12573SDina.Nimeh@Sun.COM 	/*
215*12573SDina.Nimeh@Sun.COM 	 * Note: It is not really necessary to compute e, it is in pubexp:
216*12573SDina.Nimeh@Sun.COM 	 * 	(void) big_copy(&(key->e), pubexp);
217*12573SDina.Nimeh@Sun.COM 	 */
218*12573SDina.Nimeh@Sun.COM 
219*12573SDina.Nimeh@Sun.COM 	a.malloced = 0;
220*12573SDina.Nimeh@Sun.COM 	b.malloced = 0;
221*12573SDina.Nimeh@Sun.COM 	c.malloced = 0;
222*12573SDina.Nimeh@Sun.COM 	d.malloced = 0;
223*12573SDina.Nimeh@Sun.COM 	e.malloced = 0;
224*12573SDina.Nimeh@Sun.COM 	f.malloced = 0;
225*12573SDina.Nimeh@Sun.COM 	g.malloced = 0;
226*12573SDina.Nimeh@Sun.COM 	h.malloced = 0;
2270Sstevel@tonic-gate 
228*12573SDina.Nimeh@Sun.COM 	if ((big_init(&a, len) != BIG_OK) ||
229*12573SDina.Nimeh@Sun.COM 	    (big_init(&b, len) != BIG_OK) ||
230*12573SDina.Nimeh@Sun.COM 	    (big_init(&c, len) != BIG_OK) ||
231*12573SDina.Nimeh@Sun.COM 	    (big_init(&d, len) != BIG_OK) ||
232*12573SDina.Nimeh@Sun.COM 	    (big_init(&e, len) != BIG_OK) ||
233*12573SDina.Nimeh@Sun.COM 	    (big_init(&f, len) != BIG_OK) ||
234*12573SDina.Nimeh@Sun.COM 	    (big_init(&g, len) != BIG_OK) ||
235*12573SDina.Nimeh@Sun.COM 	    (big_init(&h, len) != BIG_OK)) {
236*12573SDina.Nimeh@Sun.COM 		big_finish(&h);
237*12573SDina.Nimeh@Sun.COM 		big_finish(&g);
238*12573SDina.Nimeh@Sun.COM 		big_finish(&f);
239*12573SDina.Nimeh@Sun.COM 		big_finish(&e);
240*12573SDina.Nimeh@Sun.COM 		big_finish(&d);
241*12573SDina.Nimeh@Sun.COM 		big_finish(&c);
242*12573SDina.Nimeh@Sun.COM 		big_finish(&b);
243*12573SDina.Nimeh@Sun.COM 		big_finish(&a);
244*12573SDina.Nimeh@Sun.COM 
245*12573SDina.Nimeh@Sun.COM 		return (CKR_HOST_MEMORY);
246*12573SDina.Nimeh@Sun.COM 	}
247*12573SDina.Nimeh@Sun.COM 
248*12573SDina.Nimeh@Sun.COM 	rf = rfunc;
249*12573SDina.Nimeh@Sun.COM 	if (rf == NULL) {
250*12573SDina.Nimeh@Sun.COM #ifdef _KERNEL
251*12573SDina.Nimeh@Sun.COM 		rf = (int (*)(void *, size_t))random_get_pseudo_bytes;
252*12573SDina.Nimeh@Sun.COM #else
253*12573SDina.Nimeh@Sun.COM 		rf = pkcs11_get_urandom;
254*12573SDina.Nimeh@Sun.COM #endif
255*12573SDina.Nimeh@Sun.COM 	}
256*12573SDina.Nimeh@Sun.COM 
257*12573SDina.Nimeh@Sun.COM nextp:
258*12573SDina.Nimeh@Sun.COM 	if ((brv = big_random(&a, psize, rf)) != BIG_OK) {
259*12573SDina.Nimeh@Sun.COM 		goto ret;
260*12573SDina.Nimeh@Sun.COM 	}
261*12573SDina.Nimeh@Sun.COM 
262*12573SDina.Nimeh@Sun.COM 	if ((brv = big_nextprime_pos(&b, &a)) != BIG_OK) {
263*12573SDina.Nimeh@Sun.COM 		goto ret;
264*12573SDina.Nimeh@Sun.COM 	}
265*12573SDina.Nimeh@Sun.COM 	/* b now contains the potential prime p */
266*12573SDina.Nimeh@Sun.COM 
267*12573SDina.Nimeh@Sun.COM 	(void) big_sub_pos(&a, &b, &big_One);
268*12573SDina.Nimeh@Sun.COM 	if ((brv = big_ext_gcd_pos(&f, &d, &g, pubexp, &a)) != BIG_OK) {
269*12573SDina.Nimeh@Sun.COM 		goto ret;
270*12573SDina.Nimeh@Sun.COM 	}
271*12573SDina.Nimeh@Sun.COM 	if (big_cmp_abs(&f, &big_One) != 0) {
272*12573SDina.Nimeh@Sun.COM 		goto nextp;
273*12573SDina.Nimeh@Sun.COM 	}
274*12573SDina.Nimeh@Sun.COM 
275*12573SDina.Nimeh@Sun.COM 	if ((brv = big_random(&c, qsize, rf)) != BIG_OK) {
276*12573SDina.Nimeh@Sun.COM 		goto ret;
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 
279*12573SDina.Nimeh@Sun.COM nextq:
280*12573SDina.Nimeh@Sun.COM 	(void) big_add(&a, &c, &big_Two);
281*12573SDina.Nimeh@Sun.COM 
282*12573SDina.Nimeh@Sun.COM 	if (big_bitlength(&a) != qsize) {
283*12573SDina.Nimeh@Sun.COM 		goto nextp;
284*12573SDina.Nimeh@Sun.COM 	}
285*12573SDina.Nimeh@Sun.COM 	if (big_cmp_abs(&a, &b) == 0) {
286*12573SDina.Nimeh@Sun.COM 		goto nextp;
287*12573SDina.Nimeh@Sun.COM 	}
288*12573SDina.Nimeh@Sun.COM 	if ((brv = big_nextprime_pos(&c, &a)) != BIG_OK) {
289*12573SDina.Nimeh@Sun.COM 		goto ret;
290*12573SDina.Nimeh@Sun.COM 	}
291*12573SDina.Nimeh@Sun.COM 	/* c now contains the potential prime q */
292*12573SDina.Nimeh@Sun.COM 
293*12573SDina.Nimeh@Sun.COM 	if ((brv = big_mul(&g, &b, &c)) != BIG_OK) {
294*12573SDina.Nimeh@Sun.COM 		goto ret;
295*12573SDina.Nimeh@Sun.COM 	}
296*12573SDina.Nimeh@Sun.COM 	if (big_bitlength(&g) != size) {
297*12573SDina.Nimeh@Sun.COM 		goto nextp;
298*12573SDina.Nimeh@Sun.COM 	}
299*12573SDina.Nimeh@Sun.COM 	/* g now contains the potential modulus n */
300*12573SDina.Nimeh@Sun.COM 
301*12573SDina.Nimeh@Sun.COM 	(void) big_sub_pos(&a, &b, &big_One);
302*12573SDina.Nimeh@Sun.COM 	(void) big_sub_pos(&d, &c, &big_One);
303*12573SDina.Nimeh@Sun.COM 
304*12573SDina.Nimeh@Sun.COM 	if ((brv = big_mul(&a, &a, &d)) != BIG_OK) {
305*12573SDina.Nimeh@Sun.COM 		goto ret;
306*12573SDina.Nimeh@Sun.COM 	}
307*12573SDina.Nimeh@Sun.COM 	if ((brv = big_ext_gcd_pos(&f, &d, &h, pubexp, &a)) != BIG_OK) {
308*12573SDina.Nimeh@Sun.COM 		goto ret;
309*12573SDina.Nimeh@Sun.COM 	}
310*12573SDina.Nimeh@Sun.COM 	if (big_cmp_abs(&f, &big_One) != 0) {
311*12573SDina.Nimeh@Sun.COM 		goto nextq;
312*12573SDina.Nimeh@Sun.COM 	} else {
313*12573SDina.Nimeh@Sun.COM 		(void) big_copy(&e, pubexp);
314*12573SDina.Nimeh@Sun.COM 	}
315*12573SDina.Nimeh@Sun.COM 	if (d.sign == -1) {
316*12573SDina.Nimeh@Sun.COM 		if ((brv = big_add(&d, &d, &a)) != BIG_OK) {
317*12573SDina.Nimeh@Sun.COM 			goto ret;
318*12573SDina.Nimeh@Sun.COM 		}
319*12573SDina.Nimeh@Sun.COM 	}
320*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->p), &b);
321*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->q), &c);
322*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->n), &g);
323*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->d), &d);
324*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->e), &e);
325*12573SDina.Nimeh@Sun.COM 
326*12573SDina.Nimeh@Sun.COM 	if ((brv = big_ext_gcd_pos(&a, &f, &h, &b, &c)) != BIG_OK) {
327*12573SDina.Nimeh@Sun.COM 		goto ret;
3280Sstevel@tonic-gate 	}
329*12573SDina.Nimeh@Sun.COM 	if (f.sign == -1) {
330*12573SDina.Nimeh@Sun.COM 		if ((brv = big_add(&f, &f, &c)) != BIG_OK) {
331*12573SDina.Nimeh@Sun.COM 			goto ret;
332*12573SDina.Nimeh@Sun.COM 		}
333*12573SDina.Nimeh@Sun.COM 	}
334*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->pinvmodq), &f);
335*12573SDina.Nimeh@Sun.COM 
336*12573SDina.Nimeh@Sun.COM 	(void) big_sub(&a, &b, &big_One);
337*12573SDina.Nimeh@Sun.COM 	if ((brv = big_div_pos(&a, &f, &d, &a)) != BIG_OK) {
338*12573SDina.Nimeh@Sun.COM 		goto ret;
339*12573SDina.Nimeh@Sun.COM 	}
340*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->dmodpminus1), &f);
341*12573SDina.Nimeh@Sun.COM 	(void) big_sub(&a, &c, &big_One);
342*12573SDina.Nimeh@Sun.COM 	if ((brv = big_div_pos(&a, &f, &d, &a)) != BIG_OK) {
343*12573SDina.Nimeh@Sun.COM 		goto ret;
344*12573SDina.Nimeh@Sun.COM 	}
345*12573SDina.Nimeh@Sun.COM 	(void) big_copy(&(key->dmodqminus1), &f);
3460Sstevel@tonic-gate 
347*12573SDina.Nimeh@Sun.COM 	/* pairwise consistency check:  decrypt and encrypt restores value */
348*12573SDina.Nimeh@Sun.COM 	if ((brv = big_random(&h, size, rf)) != BIG_OK) {
349*12573SDina.Nimeh@Sun.COM 		goto ret;
350*12573SDina.Nimeh@Sun.COM 	}
351*12573SDina.Nimeh@Sun.COM 	if ((brv = big_div_pos(&a, &h, &h, &g)) != BIG_OK) {
352*12573SDina.Nimeh@Sun.COM 		goto ret;
353*12573SDina.Nimeh@Sun.COM 	}
354*12573SDina.Nimeh@Sun.COM 	if ((brv = big_modexp(&a, &h, &d, &g, NULL)) != BIG_OK) {
355*12573SDina.Nimeh@Sun.COM 		goto ret;
356*12573SDina.Nimeh@Sun.COM 	}
357*12573SDina.Nimeh@Sun.COM 
358*12573SDina.Nimeh@Sun.COM 	if ((brv = big_modexp(&b, &a, &e, &g, NULL)) != BIG_OK) {
359*12573SDina.Nimeh@Sun.COM 		goto ret;
360*12573SDina.Nimeh@Sun.COM 	}
361*12573SDina.Nimeh@Sun.COM 
362*12573SDina.Nimeh@Sun.COM 	if (big_cmp_abs(&b, &h) != 0) {
363*12573SDina.Nimeh@Sun.COM 		/* this should not happen */
364*12573SDina.Nimeh@Sun.COM 		rv = generate_rsa_key(key, psize, qsize, pubexp, rf);
365*12573SDina.Nimeh@Sun.COM 		goto ret1;
366*12573SDina.Nimeh@Sun.COM 	} else {
367*12573SDina.Nimeh@Sun.COM 		brv = BIG_OK;
368*12573SDina.Nimeh@Sun.COM 	}
369*12573SDina.Nimeh@Sun.COM 
370*12573SDina.Nimeh@Sun.COM ret:
371*12573SDina.Nimeh@Sun.COM 	rv = convert_rv(brv);
372*12573SDina.Nimeh@Sun.COM ret1:
373*12573SDina.Nimeh@Sun.COM 	big_finish(&h);
374*12573SDina.Nimeh@Sun.COM 	big_finish(&g);
375*12573SDina.Nimeh@Sun.COM 	big_finish(&f);
376*12573SDina.Nimeh@Sun.COM 	big_finish(&e);
377*12573SDina.Nimeh@Sun.COM 	big_finish(&d);
378*12573SDina.Nimeh@Sun.COM 	big_finish(&c);
379*12573SDina.Nimeh@Sun.COM 	big_finish(&b);
380*12573SDina.Nimeh@Sun.COM 	big_finish(&a);
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate /* EXPORT DELETE END */
3830Sstevel@tonic-gate 
384*12573SDina.Nimeh@Sun.COM 	return (rv);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate CK_RV
rsa_genkey_pair(RSAbytekey * bkey)388*12573SDina.Nimeh@Sun.COM rsa_genkey_pair(RSAbytekey *bkey)
3890Sstevel@tonic-gate {
390*12573SDina.Nimeh@Sun.COM 	/*
391*12573SDina.Nimeh@Sun.COM 	 * NOTE:  Whomever originally wrote this function swapped p and q.
392*12573SDina.Nimeh@Sun.COM 	 * This table shows the mapping between name convention used here
393*12573SDina.Nimeh@Sun.COM 	 * versus what is used in most texts that describe RSA key generation.
394*12573SDina.Nimeh@Sun.COM 	 *	This function:			Standard convention:
395*12573SDina.Nimeh@Sun.COM 	 *	--------------			--------------------
396*12573SDina.Nimeh@Sun.COM 	 *	modulus, n			-same-
397*12573SDina.Nimeh@Sun.COM 	 *	prime 1, q			prime 1, p
398*12573SDina.Nimeh@Sun.COM 	 *	prime 2, p			prime 2, q
399*12573SDina.Nimeh@Sun.COM 	 *	private exponent, d		-same-
400*12573SDina.Nimeh@Sun.COM 	 *	public exponent, e		-same-
401*12573SDina.Nimeh@Sun.COM 	 *	exponent 1, d mod (q-1)		d mod (p-1)
402*12573SDina.Nimeh@Sun.COM 	 *	exponent 2, d mod (p-1)		d mod (q-1)
403*12573SDina.Nimeh@Sun.COM 	 *	coefficient, p^-1 mod q		q^-1 mod p
404*12573SDina.Nimeh@Sun.COM 	 *
405*12573SDina.Nimeh@Sun.COM 	 * Also notice the struct member for coefficient is named .pinvmodq
406*12573SDina.Nimeh@Sun.COM 	 * rather than .qinvmodp, reflecting the switch.
407*12573SDina.Nimeh@Sun.COM 	 *
408*12573SDina.Nimeh@Sun.COM 	 * The code here wasn't unswapped, because "it works".  Further,
409*12573SDina.Nimeh@Sun.COM 	 * p and q are interchangeable as long as exponent 1 and 2 and
410*12573SDina.Nimeh@Sun.COM 	 * the coefficient are kept straight too.  This note is here to
411*12573SDina.Nimeh@Sun.COM 	 * make the reader aware of the switcheroo.
412*12573SDina.Nimeh@Sun.COM 	 */
413*12573SDina.Nimeh@Sun.COM 	CK_RV	rv = CKR_OK;
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate /* EXPORT DELETE START */
4160Sstevel@tonic-gate 
417*12573SDina.Nimeh@Sun.COM 	BIGNUM	public_exponent = {0};
418*12573SDina.Nimeh@Sun.COM 	RSAkey	rsakey;
419*12573SDina.Nimeh@Sun.COM 	uint32_t modulus_bytes;
420*12573SDina.Nimeh@Sun.COM 
421*12573SDina.Nimeh@Sun.COM 	if (bkey == NULL)
422*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
423*12573SDina.Nimeh@Sun.COM 
424*12573SDina.Nimeh@Sun.COM 	/* Must have modulus bits set */
425*12573SDina.Nimeh@Sun.COM 	if (bkey->modulus_bits == 0)
426*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
427*12573SDina.Nimeh@Sun.COM 
428*12573SDina.Nimeh@Sun.COM 	/* Must have public exponent set */
429*12573SDina.Nimeh@Sun.COM 	if (bkey->pubexpo_bytes == 0 || bkey->pubexpo == NULL)
430*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
4310Sstevel@tonic-gate 
432*12573SDina.Nimeh@Sun.COM 	/* Note: modulus_bits may not be same as (8 * sizeof (modulus)) */
433*12573SDina.Nimeh@Sun.COM 	modulus_bytes = CRYPTO_BITS2BYTES(bkey->modulus_bits);
434*12573SDina.Nimeh@Sun.COM 
435*12573SDina.Nimeh@Sun.COM 	/* Modulus length needs to be between min key size and max key size. */
436*12573SDina.Nimeh@Sun.COM 	if ((modulus_bytes < MIN_RSA_KEYLENGTH_IN_BYTES) ||
437*12573SDina.Nimeh@Sun.COM 	    (modulus_bytes > MAX_RSA_KEYLENGTH_IN_BYTES)) {
438*12573SDina.Nimeh@Sun.COM 		return (CKR_KEY_SIZE_RANGE);
439*12573SDina.Nimeh@Sun.COM 	}
440*12573SDina.Nimeh@Sun.COM 
441*12573SDina.Nimeh@Sun.COM 	/*
442*12573SDina.Nimeh@Sun.COM 	 * Initialize the RSA key.
443*12573SDina.Nimeh@Sun.COM 	 */
444*12573SDina.Nimeh@Sun.COM 	if (RSA_key_init(&rsakey, modulus_bytes * 4, modulus_bytes * 4) !=
445*12573SDina.Nimeh@Sun.COM 	    BIG_OK) {
446*12573SDina.Nimeh@Sun.COM 		return (CKR_HOST_MEMORY);
4470Sstevel@tonic-gate 	}
4480Sstevel@tonic-gate 
449*12573SDina.Nimeh@Sun.COM 	/* Create a public exponent in bignum format. */
450*12573SDina.Nimeh@Sun.COM 	if (big_init(&public_exponent,
451*12573SDina.Nimeh@Sun.COM 	    CHARLEN2BIGNUMLEN(bkey->pubexpo_bytes)) != BIG_OK) {
452*12573SDina.Nimeh@Sun.COM 		rv = CKR_HOST_MEMORY;
453*12573SDina.Nimeh@Sun.COM 		goto clean1;
454*12573SDina.Nimeh@Sun.COM 	}
455*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&public_exponent, bkey->pubexpo, bkey->pubexpo_bytes);
456*12573SDina.Nimeh@Sun.COM 
457*12573SDina.Nimeh@Sun.COM 	/* Generate RSA key pair. */
458*12573SDina.Nimeh@Sun.COM 	if ((rv = generate_rsa_key(&rsakey,
459*12573SDina.Nimeh@Sun.COM 	    modulus_bytes * 4, modulus_bytes * 4, &public_exponent,
460*12573SDina.Nimeh@Sun.COM 	    bkey->rfunc)) != CKR_OK) {
461*12573SDina.Nimeh@Sun.COM 		big_finish(&public_exponent);
462*12573SDina.Nimeh@Sun.COM 		goto clean1;
463*12573SDina.Nimeh@Sun.COM 	}
464*12573SDina.Nimeh@Sun.COM 	big_finish(&public_exponent);
465*12573SDina.Nimeh@Sun.COM 
466*12573SDina.Nimeh@Sun.COM 	/* modulus_bytes = rsakey.n.len * (int)sizeof (BIG_CHUNK_TYPE); */
467*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->modulus, &(rsakey.n), modulus_bytes);
468*12573SDina.Nimeh@Sun.COM 
469*12573SDina.Nimeh@Sun.COM 	bkey->privexpo_bytes = rsakey.d.len * (int)sizeof (BIG_CHUNK_TYPE);
470*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->privexpo, &(rsakey.d), bkey->privexpo_bytes);
4710Sstevel@tonic-gate 
472*12573SDina.Nimeh@Sun.COM 	bkey->pubexpo_bytes = rsakey.e.len * (int)sizeof (BIG_CHUNK_TYPE);
473*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->pubexpo, &(rsakey.e), bkey->pubexpo_bytes);
474*12573SDina.Nimeh@Sun.COM 
475*12573SDina.Nimeh@Sun.COM 	bkey->prime1_bytes = rsakey.q.len * (int)sizeof (BIG_CHUNK_TYPE);
476*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->prime1, &(rsakey.q), bkey->prime1_bytes);
477*12573SDina.Nimeh@Sun.COM 
478*12573SDina.Nimeh@Sun.COM 	bkey->prime2_bytes = rsakey.p.len * (int)sizeof (BIG_CHUNK_TYPE);
479*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->prime2, &(rsakey.p), bkey->prime2_bytes);
480*12573SDina.Nimeh@Sun.COM 
481*12573SDina.Nimeh@Sun.COM 	bkey->expo1_bytes =
482*12573SDina.Nimeh@Sun.COM 	    rsakey.dmodqminus1.len * (int)sizeof (BIG_CHUNK_TYPE);
483*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->expo1, &(rsakey.dmodqminus1),
484*12573SDina.Nimeh@Sun.COM 	    bkey->expo1_bytes);
485*12573SDina.Nimeh@Sun.COM 
486*12573SDina.Nimeh@Sun.COM 	bkey->expo2_bytes =
487*12573SDina.Nimeh@Sun.COM 	    rsakey.dmodpminus1.len * (int)sizeof (BIG_CHUNK_TYPE);
488*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->expo2,
489*12573SDina.Nimeh@Sun.COM 	    &(rsakey.dmodpminus1), bkey->expo2_bytes);
490*12573SDina.Nimeh@Sun.COM 
491*12573SDina.Nimeh@Sun.COM 	bkey->coeff_bytes =
492*12573SDina.Nimeh@Sun.COM 	    rsakey.pinvmodq.len * (int)sizeof (BIG_CHUNK_TYPE);
493*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(bkey->coeff, &(rsakey.pinvmodq), bkey->coeff_bytes);
494*12573SDina.Nimeh@Sun.COM 
495*12573SDina.Nimeh@Sun.COM clean1:
496*12573SDina.Nimeh@Sun.COM 	RSA_key_finish(&rsakey);
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate /* EXPORT DELETE END */
4990Sstevel@tonic-gate 
500*12573SDina.Nimeh@Sun.COM 	return (rv);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate /*
504*12573SDina.Nimeh@Sun.COM  * RSA encrypt operation
5050Sstevel@tonic-gate  */
5060Sstevel@tonic-gate CK_RV
rsa_encrypt(RSAbytekey * bkey,uchar_t * in,uint32_t in_len,uchar_t * out)507*12573SDina.Nimeh@Sun.COM rsa_encrypt(RSAbytekey *bkey, uchar_t *in, uint32_t in_len, uchar_t *out)
5080Sstevel@tonic-gate {
509*12573SDina.Nimeh@Sun.COM 	CK_RV rv = CKR_OK;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate /* EXPORT DELETE START */
5120Sstevel@tonic-gate 
513*12573SDina.Nimeh@Sun.COM 	BIGNUM msg;
514*12573SDina.Nimeh@Sun.COM 	RSAkey rsakey;
515*12573SDina.Nimeh@Sun.COM 	uint32_t modulus_bytes;
516*12573SDina.Nimeh@Sun.COM 
517*12573SDina.Nimeh@Sun.COM 	if (bkey == NULL)
518*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
519*12573SDina.Nimeh@Sun.COM 
520*12573SDina.Nimeh@Sun.COM 	/* Must have modulus and public exponent set */
521*12573SDina.Nimeh@Sun.COM 	if (bkey->modulus_bits == 0 || bkey->modulus == NULL ||
522*12573SDina.Nimeh@Sun.COM 	    bkey->pubexpo_bytes == 0 || bkey->pubexpo == NULL)
523*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
5240Sstevel@tonic-gate 
525*12573SDina.Nimeh@Sun.COM 	/* Note: modulus_bits may not be same as (8 * sizeof (modulus)) */
526*12573SDina.Nimeh@Sun.COM 	modulus_bytes = CRYPTO_BITS2BYTES(bkey->modulus_bits);
527*12573SDina.Nimeh@Sun.COM 
528*12573SDina.Nimeh@Sun.COM 	if (bkey->pubexpo_bytes > modulus_bytes) {
529*12573SDina.Nimeh@Sun.COM 		return (CKR_KEY_SIZE_RANGE);
530*12573SDina.Nimeh@Sun.COM 	}
531*12573SDina.Nimeh@Sun.COM 
532*12573SDina.Nimeh@Sun.COM 	/* psize and qsize for RSA_key_init is in bits. */
533*12573SDina.Nimeh@Sun.COM 	if (RSA_key_init(&rsakey, modulus_bytes * 4, modulus_bytes * 4) !=
534*12573SDina.Nimeh@Sun.COM 	    BIG_OK) {
535*12573SDina.Nimeh@Sun.COM 		return (CKR_HOST_MEMORY);
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate 
538*12573SDina.Nimeh@Sun.COM 	/* Size for big_init is in BIG_CHUNK_TYPE words. */
539*12573SDina.Nimeh@Sun.COM 	if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
540*12573SDina.Nimeh@Sun.COM 		rv = CKR_HOST_MEMORY;
541*12573SDina.Nimeh@Sun.COM 		goto clean2;
542*12573SDina.Nimeh@Sun.COM 	}
543*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&msg, in, in_len);
544*12573SDina.Nimeh@Sun.COM 
545*12573SDina.Nimeh@Sun.COM 	/* Convert public exponent and modulus to big integer format. */
546*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.e), bkey->pubexpo, bkey->pubexpo_bytes);
547*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.n), bkey->modulus, modulus_bytes);
548*12573SDina.Nimeh@Sun.COM 
549*12573SDina.Nimeh@Sun.COM 	if (big_cmp_abs(&msg, &(rsakey.n)) > 0) {
550*12573SDina.Nimeh@Sun.COM 		rv = CKR_DATA_LEN_RANGE;
551*12573SDina.Nimeh@Sun.COM 		goto clean3;
552*12573SDina.Nimeh@Sun.COM 	}
553*12573SDina.Nimeh@Sun.COM 
554*12573SDina.Nimeh@Sun.COM 	/* Perform RSA computation on big integer input data. */
555*12573SDina.Nimeh@Sun.COM 	if (big_modexp(&msg, &msg, &(rsakey.e), &(rsakey.n), NULL) !=
556*12573SDina.Nimeh@Sun.COM 	    BIG_OK) {
557*12573SDina.Nimeh@Sun.COM 		rv = CKR_HOST_MEMORY;
558*12573SDina.Nimeh@Sun.COM 		goto clean3;
559*12573SDina.Nimeh@Sun.COM 	}
560*12573SDina.Nimeh@Sun.COM 
561*12573SDina.Nimeh@Sun.COM 	/* Convert the big integer output data to octet string. */
562*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(out, &msg, modulus_bytes);
563*12573SDina.Nimeh@Sun.COM 
564*12573SDina.Nimeh@Sun.COM clean3:
565*12573SDina.Nimeh@Sun.COM 	big_finish(&msg);
566*12573SDina.Nimeh@Sun.COM clean2:
567*12573SDina.Nimeh@Sun.COM 	RSA_key_finish(&rsakey);
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate /* EXPORT DELETE END */
5700Sstevel@tonic-gate 
571*12573SDina.Nimeh@Sun.COM 	return (rv);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate 
574*12573SDina.Nimeh@Sun.COM /*
575*12573SDina.Nimeh@Sun.COM  * RSA decrypt operation
576*12573SDina.Nimeh@Sun.COM  */
5770Sstevel@tonic-gate CK_RV
rsa_decrypt(RSAbytekey * bkey,uchar_t * in,uint32_t in_len,uchar_t * out)578*12573SDina.Nimeh@Sun.COM rsa_decrypt(RSAbytekey *bkey, uchar_t *in, uint32_t in_len, uchar_t *out)
5790Sstevel@tonic-gate {
580*12573SDina.Nimeh@Sun.COM 	CK_RV rv = CKR_OK;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate /* EXPORT DELETE START */
5830Sstevel@tonic-gate 
584*12573SDina.Nimeh@Sun.COM 	BIGNUM msg;
585*12573SDina.Nimeh@Sun.COM 	RSAkey rsakey;
586*12573SDina.Nimeh@Sun.COM 	uint32_t modulus_bytes;
587*12573SDina.Nimeh@Sun.COM 
588*12573SDina.Nimeh@Sun.COM 	if (bkey == NULL)
589*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
5900Sstevel@tonic-gate 
591*12573SDina.Nimeh@Sun.COM 	/* Must have modulus, prime1, prime2, expo1, expo2, and coeff set */
592*12573SDina.Nimeh@Sun.COM 	if (bkey->modulus_bits == 0 || bkey->modulus == NULL ||
593*12573SDina.Nimeh@Sun.COM 	    bkey->prime1_bytes == 0 || bkey->prime1 == NULL ||
594*12573SDina.Nimeh@Sun.COM 	    bkey->prime2_bytes == 0 || bkey->prime2 == NULL ||
595*12573SDina.Nimeh@Sun.COM 	    bkey->expo1_bytes == 0 || bkey->expo1 == NULL ||
596*12573SDina.Nimeh@Sun.COM 	    bkey->expo2_bytes == 0 || bkey->expo2 == NULL ||
597*12573SDina.Nimeh@Sun.COM 	    bkey->coeff_bytes == 0 || bkey->coeff == NULL)
598*12573SDina.Nimeh@Sun.COM 		return (CKR_ARGUMENTS_BAD);
599*12573SDina.Nimeh@Sun.COM 
600*12573SDina.Nimeh@Sun.COM 	/* Note: modulus_bits may not be same as (8 * sizeof (modulus)) */
601*12573SDina.Nimeh@Sun.COM 	modulus_bytes = CRYPTO_BITS2BYTES(bkey->modulus_bits);
602*12573SDina.Nimeh@Sun.COM 
603*12573SDina.Nimeh@Sun.COM 	/* psize and qsize for RSA_key_init is in bits. */
604*12573SDina.Nimeh@Sun.COM 	if (RSA_key_init(&rsakey, CRYPTO_BYTES2BITS(bkey->prime2_bytes),
605*12573SDina.Nimeh@Sun.COM 	    CRYPTO_BYTES2BITS(bkey->prime1_bytes)) != BIG_OK) {
606*12573SDina.Nimeh@Sun.COM 		return (CKR_HOST_MEMORY);
607*12573SDina.Nimeh@Sun.COM 	}
608*12573SDina.Nimeh@Sun.COM 
609*12573SDina.Nimeh@Sun.COM 	/* Size for big_init is in BIG_CHUNK_TYPE words. */
610*12573SDina.Nimeh@Sun.COM 	if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
611*12573SDina.Nimeh@Sun.COM 		rv = CKR_HOST_MEMORY;
612*12573SDina.Nimeh@Sun.COM 		goto clean3;
6130Sstevel@tonic-gate 	}
614*12573SDina.Nimeh@Sun.COM 	/* Convert octet string input data to big integer format. */
615*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&msg, in, in_len);
616*12573SDina.Nimeh@Sun.COM 
617*12573SDina.Nimeh@Sun.COM 	/* Convert octet string modulus to big integer format. */
618*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.n), bkey->modulus, modulus_bytes);
619*12573SDina.Nimeh@Sun.COM 
620*12573SDina.Nimeh@Sun.COM 	if (big_cmp_abs(&msg, &(rsakey.n)) > 0) {
621*12573SDina.Nimeh@Sun.COM 		rv = CKR_DATA_LEN_RANGE;
622*12573SDina.Nimeh@Sun.COM 		goto clean4;
623*12573SDina.Nimeh@Sun.COM 	}
624*12573SDina.Nimeh@Sun.COM 
625*12573SDina.Nimeh@Sun.COM 	/* Convert the rest of private key attributes to big integer format. */
626*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.q), bkey->prime1, bkey->prime1_bytes);
627*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.p), bkey->prime2, bkey->prime2_bytes);
628*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.dmodqminus1),
629*12573SDina.Nimeh@Sun.COM 	    bkey->expo1, bkey->expo1_bytes);
630*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.dmodpminus1),
631*12573SDina.Nimeh@Sun.COM 	    bkey->expo2, bkey->expo2_bytes);
632*12573SDina.Nimeh@Sun.COM 	bytestring2bignum(&(rsakey.pinvmodq),
633*12573SDina.Nimeh@Sun.COM 	    bkey->coeff, bkey->coeff_bytes);
6340Sstevel@tonic-gate 
635*12573SDina.Nimeh@Sun.COM 	if ((big_cmp_abs(&(rsakey.dmodpminus1), &(rsakey.p)) > 0) ||
636*12573SDina.Nimeh@Sun.COM 	    (big_cmp_abs(&(rsakey.dmodqminus1), &(rsakey.q)) > 0) ||
637*12573SDina.Nimeh@Sun.COM 	    (big_cmp_abs(&(rsakey.pinvmodq), &(rsakey.q)) > 0)) {
638*12573SDina.Nimeh@Sun.COM 		rv = CKR_KEY_SIZE_RANGE;
639*12573SDina.Nimeh@Sun.COM 		goto clean4;
6400Sstevel@tonic-gate 	}
6410Sstevel@tonic-gate 
642*12573SDina.Nimeh@Sun.COM 	/* Perform RSA computation on big integer input data. */
643*12573SDina.Nimeh@Sun.COM 	if (big_modexp_crt(&msg, &msg, &(rsakey.dmodpminus1),
644*12573SDina.Nimeh@Sun.COM 	    &(rsakey.dmodqminus1), &(rsakey.p), &(rsakey.q),
645*12573SDina.Nimeh@Sun.COM 	    &(rsakey.pinvmodq), NULL, NULL) != BIG_OK) {
646*12573SDina.Nimeh@Sun.COM 		rv = CKR_HOST_MEMORY;
647*12573SDina.Nimeh@Sun.COM 		goto clean4;
648*12573SDina.Nimeh@Sun.COM 	}
649*12573SDina.Nimeh@Sun.COM 
650*12573SDina.Nimeh@Sun.COM 	/* Convert the big integer output data to octet string. */
651*12573SDina.Nimeh@Sun.COM 	bignum2bytestring(out, &msg, modulus_bytes);
652*12573SDina.Nimeh@Sun.COM 
653*12573SDina.Nimeh@Sun.COM clean4:
654*12573SDina.Nimeh@Sun.COM 	big_finish(&msg);
655*12573SDina.Nimeh@Sun.COM clean3:
656*12573SDina.Nimeh@Sun.COM 	RSA_key_finish(&rsakey);
657*12573SDina.Nimeh@Sun.COM 
6580Sstevel@tonic-gate /* EXPORT DELETE END */
6590Sstevel@tonic-gate 
660*12573SDina.Nimeh@Sun.COM 	return (rv);
6610Sstevel@tonic-gate }
662