1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * This file contains RSA helper routines common to
31*0Sstevel@tonic-gate  * the PKCS11 soft token code and the kernel RSA code.
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <sys/types.h>
35*0Sstevel@tonic-gate #include "rsa_impl.h"
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #ifdef _KERNEL
38*0Sstevel@tonic-gate #include <sys/param.h>
39*0Sstevel@tonic-gate #else
40*0Sstevel@tonic-gate #include <strings.h>
41*0Sstevel@tonic-gate #include "softRandom.h"
42*0Sstevel@tonic-gate #endif
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate /*
45*0Sstevel@tonic-gate  * DER encoding T of the DigestInfo values for MD5 and SHA1
46*0Sstevel@tonic-gate  * from PKCS#1 v2.1: RSA Cryptography Standard Section 9.2 Note 1
47*0Sstevel@tonic-gate  *
48*0Sstevel@tonic-gate  * MD5:     (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H
49*0Sstevel@tonic-gate  * SHA-1:   (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H
50*0Sstevel@tonic-gate  *
51*0Sstevel@tonic-gate  * Where H is the digested output from MD5 or SHA1. We define the constant
52*0Sstevel@tonic-gate  * byte array (the prefix) here and use it rather than doing the DER
53*0Sstevel@tonic-gate  * encoding of the OID in a separate routine.
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate const CK_BYTE MD5_DER_PREFIX[MD5_DER_PREFIX_Len] = {0x30, 0x20, 0x30, 0x0c,
56*0Sstevel@tonic-gate     0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
57*0Sstevel@tonic-gate     0x04, 0x10};
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate const CK_BYTE SHA1_DER_PREFIX[SHA1_DER_PREFIX_Len] = {0x30, 0x21, 0x30,
60*0Sstevel@tonic-gate     0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate BIG_ERR_CODE
63*0Sstevel@tonic-gate RSA_key_init(RSAkey *key, int psize, int qsize)
64*0Sstevel@tonic-gate {
65*0Sstevel@tonic-gate 	BIG_ERR_CODE err = BIG_OK;
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate /* EXPORT DELETE START */
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	int plen, qlen, nlen;
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	plen = (psize + 31) / 32;
72*0Sstevel@tonic-gate 	qlen = (qsize + 31) / 32;
73*0Sstevel@tonic-gate 	nlen = plen + qlen;
74*0Sstevel@tonic-gate 	key->size = psize + qsize;
75*0Sstevel@tonic-gate 	if ((err = big_init(&(key->p), plen)) != BIG_OK)
76*0Sstevel@tonic-gate 		return (err);
77*0Sstevel@tonic-gate 	if ((err = big_init(&(key->q), qlen)) != BIG_OK)
78*0Sstevel@tonic-gate 		goto ret1;
79*0Sstevel@tonic-gate 	if ((err = big_init(&(key->n), nlen)) != BIG_OK)
80*0Sstevel@tonic-gate 		goto ret2;
81*0Sstevel@tonic-gate 	if ((err = big_init(&(key->d), nlen)) != BIG_OK)
82*0Sstevel@tonic-gate 		goto ret3;
83*0Sstevel@tonic-gate 	if ((err = big_init(&(key->e), nlen)) != BIG_OK)
84*0Sstevel@tonic-gate 		goto ret4;
85*0Sstevel@tonic-gate 	if ((err = big_init(&(key->dmodpminus1), plen)) != BIG_OK)
86*0Sstevel@tonic-gate 		goto ret5;
87*0Sstevel@tonic-gate 	if ((err = big_init(&(key->dmodqminus1), qlen)) != BIG_OK)
88*0Sstevel@tonic-gate 		goto ret6;
89*0Sstevel@tonic-gate 	if ((err = big_init(&(key->pinvmodq), qlen)) != BIG_OK)
90*0Sstevel@tonic-gate 		goto ret7;
91*0Sstevel@tonic-gate 	if ((err = big_init(&(key->p_rr), plen)) != BIG_OK)
92*0Sstevel@tonic-gate 		goto ret8;
93*0Sstevel@tonic-gate 	if ((err = big_init(&(key->q_rr), qlen)) != BIG_OK)
94*0Sstevel@tonic-gate 		goto ret9;
95*0Sstevel@tonic-gate 	if ((err = big_init(&(key->n_rr), nlen)) != BIG_OK)
96*0Sstevel@tonic-gate 		goto ret10;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	return (BIG_OK);
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate ret10:
101*0Sstevel@tonic-gate 	big_finish(&(key->q_rr));
102*0Sstevel@tonic-gate ret9:
103*0Sstevel@tonic-gate 	big_finish(&(key->p_rr));
104*0Sstevel@tonic-gate ret8:
105*0Sstevel@tonic-gate 	big_finish(&(key->pinvmodq));
106*0Sstevel@tonic-gate ret7:
107*0Sstevel@tonic-gate 	big_finish(&(key->dmodqminus1));
108*0Sstevel@tonic-gate ret6:
109*0Sstevel@tonic-gate 	big_finish(&(key->dmodpminus1));
110*0Sstevel@tonic-gate ret5:
111*0Sstevel@tonic-gate 	big_finish(&(key->e));
112*0Sstevel@tonic-gate ret4:
113*0Sstevel@tonic-gate 	big_finish(&(key->d));
114*0Sstevel@tonic-gate ret3:
115*0Sstevel@tonic-gate 	big_finish(&(key->n));
116*0Sstevel@tonic-gate ret2:
117*0Sstevel@tonic-gate 	big_finish(&(key->q));
118*0Sstevel@tonic-gate ret1:
119*0Sstevel@tonic-gate 	big_finish(&(key->p));
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate /* EXPORT DELETE END */
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 	return (err);
124*0Sstevel@tonic-gate }
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate void
128*0Sstevel@tonic-gate RSA_key_finish(RSAkey *key)
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate /* EXPORT DELETE START */
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	big_finish(&(key->n_rr));
134*0Sstevel@tonic-gate 	big_finish(&(key->q_rr));
135*0Sstevel@tonic-gate 	big_finish(&(key->p_rr));
136*0Sstevel@tonic-gate 	big_finish(&(key->pinvmodq));
137*0Sstevel@tonic-gate 	big_finish(&(key->dmodqminus1));
138*0Sstevel@tonic-gate 	big_finish(&(key->dmodpminus1));
139*0Sstevel@tonic-gate 	big_finish(&(key->e));
140*0Sstevel@tonic-gate 	big_finish(&(key->d));
141*0Sstevel@tonic-gate 	big_finish(&(key->n));
142*0Sstevel@tonic-gate 	big_finish(&(key->q));
143*0Sstevel@tonic-gate 	big_finish(&(key->p));
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate /* EXPORT DELETE END */
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate }
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate /*
151*0Sstevel@tonic-gate  * To create a block type "02" encryption block for RSA PKCS encryption
152*0Sstevel@tonic-gate  * process.
153*0Sstevel@tonic-gate  *
154*0Sstevel@tonic-gate  * The RSA PKCS Padding before encryption is in the following format:
155*0Sstevel@tonic-gate  * +------+--------------------+----+-----------------------------+
156*0Sstevel@tonic-gate  * |0x0002| 8 bytes or more RN |0x00|       DATA                  |
157*0Sstevel@tonic-gate  * +------+--------------------+----+-----------------------------+
158*0Sstevel@tonic-gate  *
159*0Sstevel@tonic-gate  */
160*0Sstevel@tonic-gate CK_RV
161*0Sstevel@tonic-gate soft_encrypt_rsa_pkcs_encode(uint8_t *databuf,
162*0Sstevel@tonic-gate     size_t datalen, uint8_t *padbuf, size_t padbuflen)
163*0Sstevel@tonic-gate {
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate /* EXPORT DELETE START */
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	size_t	padlen;
168*0Sstevel@tonic-gate 	CK_RV	rv;
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	padlen = padbuflen - datalen;
171*0Sstevel@tonic-gate 	if (padlen < MIN_PKCS1_PADLEN) {
172*0Sstevel@tonic-gate 		return (CKR_DATA_LEN_RANGE);
173*0Sstevel@tonic-gate 	}
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	/* Pad with 0x0002+non-zero pseudorandom numbers+0x00. */
176*0Sstevel@tonic-gate 	padbuf[0] = 0x00;
177*0Sstevel@tonic-gate 	padbuf[1] = 0x02;
178*0Sstevel@tonic-gate #ifdef _KERNEL
179*0Sstevel@tonic-gate 	rv = knzero_random_generator(padbuf + 2, padbuflen - 3);
180*0Sstevel@tonic-gate #else
181*0Sstevel@tonic-gate 	rv = soft_nzero_random_generator(padbuf + 2, padbuflen - 3);
182*0Sstevel@tonic-gate #endif
183*0Sstevel@tonic-gate 	if (rv != CKR_OK) {
184*0Sstevel@tonic-gate 		return (rv);
185*0Sstevel@tonic-gate 	}
186*0Sstevel@tonic-gate 	padbuf[padlen - 1] = 0x00;
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	bcopy(databuf, padbuf + padlen, datalen);
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate /* EXPORT DELETE END */
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	return (CKR_OK);
193*0Sstevel@tonic-gate }
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate /*
197*0Sstevel@tonic-gate  * The RSA PKCS Padding after decryption is in the following format:
198*0Sstevel@tonic-gate  * +------+--------------------+----+-----------------------------+
199*0Sstevel@tonic-gate  * |0x0002| 8 bytes or more RN |0x00|       DATA                  |
200*0Sstevel@tonic-gate  * +------+--------------------+----+-----------------------------+
201*0Sstevel@tonic-gate  *
202*0Sstevel@tonic-gate  * 'padbuf' points to the recovered message which is the modulus
203*0Sstevel@tonic-gate  * length. As a result, 'plen' is changed to hold the actual data length.
204*0Sstevel@tonic-gate  */
205*0Sstevel@tonic-gate CK_RV
206*0Sstevel@tonic-gate soft_decrypt_rsa_pkcs_decode(uint8_t *padbuf, int *plen)
207*0Sstevel@tonic-gate {
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate /* EXPORT DELETE START */
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	int	i;
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	/* Check to see if the recovered data is padded is 0x0002. */
214*0Sstevel@tonic-gate 	if (padbuf[0] != 0x00 || padbuf[1] != 0x02) {
215*0Sstevel@tonic-gate 		return (CKR_ENCRYPTED_DATA_INVALID);
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	/* Remove all the random bits up to 0x00 (= NULL char) */
219*0Sstevel@tonic-gate 	for (i = 2; (*plen - i) > 0; i++) {
220*0Sstevel@tonic-gate 		if (padbuf[i] == 0x00) {
221*0Sstevel@tonic-gate 			i++;
222*0Sstevel@tonic-gate 			if (i < MIN_PKCS1_PADLEN) {
223*0Sstevel@tonic-gate 				return (CKR_ENCRYPTED_DATA_INVALID);
224*0Sstevel@tonic-gate 			}
225*0Sstevel@tonic-gate 			*plen -= i;
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 			return (CKR_OK);
228*0Sstevel@tonic-gate 		}
229*0Sstevel@tonic-gate 	}
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate /* EXPORT DELETE END */
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 	return (CKR_ENCRYPTED_DATA_INVALID);
234*0Sstevel@tonic-gate }
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate /*
237*0Sstevel@tonic-gate  * To create a block type "01" block for RSA PKCS signature process.
238*0Sstevel@tonic-gate  *
239*0Sstevel@tonic-gate  * The RSA PKCS Padding before Signing is in the following format:
240*0Sstevel@tonic-gate  * +------+--------------+----+-----------------------------+
241*0Sstevel@tonic-gate  * |0x0001| 0xFFFF.......|0x00|          DATA               |
242*0Sstevel@tonic-gate  * +------+--------------+----+-----------------------------+
243*0Sstevel@tonic-gate  */
244*0Sstevel@tonic-gate CK_RV
245*0Sstevel@tonic-gate soft_sign_rsa_pkcs_encode(uint8_t *pData, size_t dataLen, uint8_t *data,
246*0Sstevel@tonic-gate     size_t mbit_l)
247*0Sstevel@tonic-gate {
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate /* EXPORT DELETE START */
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	size_t	padlen;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	padlen = mbit_l - dataLen;
254*0Sstevel@tonic-gate 	if (padlen < MIN_PKCS1_PADLEN) {
255*0Sstevel@tonic-gate 		return (CKR_DATA_LEN_RANGE);
256*0Sstevel@tonic-gate 	}
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	padlen -= 3;
259*0Sstevel@tonic-gate 	data[0] = 0x00;
260*0Sstevel@tonic-gate 	data[1] = 0x01;
261*0Sstevel@tonic-gate #ifdef _KERNEL
262*0Sstevel@tonic-gate 	kmemset(data + 2, 0xFF, padlen);
263*0Sstevel@tonic-gate #else
264*0Sstevel@tonic-gate 	(void) memset(data + 2, 0xFF, padlen);
265*0Sstevel@tonic-gate #endif
266*0Sstevel@tonic-gate 	data[padlen + 2] = 0x00;
267*0Sstevel@tonic-gate 	bcopy(pData, data + padlen + 3, dataLen);
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate /* EXPORT DELETE END */
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	return (CKR_OK);
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate CK_RV
276*0Sstevel@tonic-gate soft_verify_rsa_pkcs_decode(uint8_t *data, int *mbit_l)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate /* EXPORT DELETE START */
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	int i;
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate 	/* Check to see if the padding of recovered data starts with 0x0001. */
284*0Sstevel@tonic-gate 	if ((data[0] != 0x00) || (data[1] != 0x01)) {
285*0Sstevel@tonic-gate 		return (CKR_SIGNATURE_INVALID);
286*0Sstevel@tonic-gate 	}
287*0Sstevel@tonic-gate 	/* Check to see if the recovered data is padded with 0xFFF...00. */
288*0Sstevel@tonic-gate 	for (i = 2; i < *mbit_l; i++) {
289*0Sstevel@tonic-gate 		if (data[i] == 0x00) {
290*0Sstevel@tonic-gate 			i++;
291*0Sstevel@tonic-gate 			if (i < MIN_PKCS1_PADLEN) {
292*0Sstevel@tonic-gate 				return (CKR_SIGNATURE_INVALID);
293*0Sstevel@tonic-gate 			}
294*0Sstevel@tonic-gate 			*mbit_l -= i;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 			return (CKR_OK);
297*0Sstevel@tonic-gate 		} else if (data[i] != 0xFF) {
298*0Sstevel@tonic-gate 			return (CKR_SIGNATURE_INVALID);
299*0Sstevel@tonic-gate 		}
300*0Sstevel@tonic-gate 	}
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate /* EXPORT DELETE END */
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	return (CKR_SIGNATURE_INVALID);
305*0Sstevel@tonic-gate }
306