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 2004 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  * RSA provider for the Kernel Cryptographic Framework (KCF)
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include <sys/types.h>
34*0Sstevel@tonic-gate #include <sys/systm.h>
35*0Sstevel@tonic-gate #include <sys/modctl.h>
36*0Sstevel@tonic-gate #include <sys/cmn_err.h>
37*0Sstevel@tonic-gate #include <sys/ddi.h>
38*0Sstevel@tonic-gate #include <sys/crypto/spi.h>
39*0Sstevel@tonic-gate #include <sys/sysmacros.h>
40*0Sstevel@tonic-gate #include <sys/strsun.h>
41*0Sstevel@tonic-gate #include <sys/md5.h>
42*0Sstevel@tonic-gate #include <sys/sha1.h>
43*0Sstevel@tonic-gate #include <sys/random.h>
44*0Sstevel@tonic-gate #include "rsa_impl.h"
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate extern struct mod_ops mod_cryptoops;
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate /*
49*0Sstevel@tonic-gate  * Module linkage information for the kernel.
50*0Sstevel@tonic-gate  */
51*0Sstevel@tonic-gate static struct modlcrypto modlcrypto = {
52*0Sstevel@tonic-gate 	&mod_cryptoops,
53*0Sstevel@tonic-gate 	"RSA Kernel SW Provider %I%"
54*0Sstevel@tonic-gate };
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate static struct modlinkage modlinkage = {
57*0Sstevel@tonic-gate 	MODREV_1,
58*0Sstevel@tonic-gate 	(void *)&modlcrypto,
59*0Sstevel@tonic-gate 	NULL
60*0Sstevel@tonic-gate };
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate /*
63*0Sstevel@tonic-gate  * CSPI information (entry points, provider info, etc.)
64*0Sstevel@tonic-gate  */
65*0Sstevel@tonic-gate typedef enum rsa_mech_type {
66*0Sstevel@tonic-gate 	RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_RSA_PKCS */
67*0Sstevel@tonic-gate 	RSA_X_509_MECH_INFO_TYPE,	/* SUN_CKM_RSA_X_509 */
68*0Sstevel@tonic-gate 	MD5_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_MD5_RSA_PKCS */
69*0Sstevel@tonic-gate 	SHA1_RSA_PKCS_MECH_INFO_TYPE	/* SUN_SHA1_RSA_PKCS */
70*0Sstevel@tonic-gate } rsa_mech_type_t;
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate /*
73*0Sstevel@tonic-gate  * Context for RSA_PKCS and RSA_X_509 mechanisms.
74*0Sstevel@tonic-gate  */
75*0Sstevel@tonic-gate typedef struct rsa_ctx {
76*0Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
77*0Sstevel@tonic-gate 	crypto_key_t *key;
78*0Sstevel@tonic-gate 	size_t keychunk_size;
79*0Sstevel@tonic-gate } rsa_ctx_t;
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate /*
82*0Sstevel@tonic-gate  * Context for MD5_RSA_PKCS and SHA1_RSA_PKCS mechanisms.
83*0Sstevel@tonic-gate  */
84*0Sstevel@tonic-gate typedef struct digest_rsa_ctx {
85*0Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
86*0Sstevel@tonic-gate 	crypto_key_t *key;
87*0Sstevel@tonic-gate 	size_t keychunk_size;
88*0Sstevel@tonic-gate 	union {
89*0Sstevel@tonic-gate 		MD5_CTX md5ctx;
90*0Sstevel@tonic-gate 		SHA1_CTX sha1ctx;
91*0Sstevel@tonic-gate 	} dctx_u;
92*0Sstevel@tonic-gate } digest_rsa_ctx_t;
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate #define	md5_ctx		dctx_u.md5ctx
95*0Sstevel@tonic-gate #define	sha1_ctx	dctx_u.sha1ctx
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate /*
98*0Sstevel@tonic-gate  * Mechanism info structure passed to KCF during registration.
99*0Sstevel@tonic-gate  */
100*0Sstevel@tonic-gate static crypto_mech_info_t rsa_mech_info_tab[] = {
101*0Sstevel@tonic-gate 	/* RSA_PKCS */
102*0Sstevel@tonic-gate 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
103*0Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
104*0Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
105*0Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
106*0Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
107*0Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
108*0Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
109*0Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	/* RSA_X_509 */
112*0Sstevel@tonic-gate 	{SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
113*0Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
114*0Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
115*0Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
116*0Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
117*0Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
118*0Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
119*0Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	/* MD5_RSA_PKCS */
122*0Sstevel@tonic-gate 	{SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE,
123*0Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
124*0Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
125*0Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	/* SHA1_RSA_PKCS */
128*0Sstevel@tonic-gate 	{SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE,
129*0Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
130*0Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
131*0Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}
132*0Sstevel@tonic-gate };
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate #define	RSA_VALID_MECH(mech)					\
135*0Sstevel@tonic-gate 	(((mech)->cm_type == RSA_PKCS_MECH_INFO_TYPE ||		\
136*0Sstevel@tonic-gate 	(mech)->cm_type == RSA_X_509_MECH_INFO_TYPE ||		\
137*0Sstevel@tonic-gate 	(mech)->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||	\
138*0Sstevel@tonic-gate 	(mech)->cm_type == SHA1_RSA_PKCS_MECH_INFO_TYPE) ? 1 : 0)
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */
141*0Sstevel@tonic-gate #define	RSA_ARG_INPLACE(input, output)				\
142*0Sstevel@tonic-gate 	if ((output) == NULL)					\
143*0Sstevel@tonic-gate 		(output) = (input);
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate static void rsa_provider_status(crypto_provider_handle_t, uint_t *);
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate static crypto_control_ops_t rsa_control_ops = {
148*0Sstevel@tonic-gate 	rsa_provider_status
149*0Sstevel@tonic-gate };
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate static int rsa_common_init(crypto_ctx_t *, crypto_mechanism_t *,
152*0Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
153*0Sstevel@tonic-gate static int rsa_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
154*0Sstevel@tonic-gate     crypto_req_handle_t);
155*0Sstevel@tonic-gate static int rsa_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
156*0Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
157*0Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
158*0Sstevel@tonic-gate static int rsa_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
159*0Sstevel@tonic-gate     crypto_req_handle_t);
160*0Sstevel@tonic-gate static int rsa_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
161*0Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
162*0Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate /*
165*0Sstevel@tonic-gate  * The RSA mechanisms do not have multiple-part cipher operations.
166*0Sstevel@tonic-gate  * So, the update and final routines are set to NULL.
167*0Sstevel@tonic-gate  */
168*0Sstevel@tonic-gate static crypto_cipher_ops_t rsa_cipher_ops = {
169*0Sstevel@tonic-gate 	rsa_common_init,
170*0Sstevel@tonic-gate 	rsa_encrypt,
171*0Sstevel@tonic-gate 	NULL,
172*0Sstevel@tonic-gate 	NULL,
173*0Sstevel@tonic-gate 	rsa_encrypt_atomic,
174*0Sstevel@tonic-gate 	rsa_common_init,
175*0Sstevel@tonic-gate 	rsa_decrypt,
176*0Sstevel@tonic-gate 	NULL,
177*0Sstevel@tonic-gate 	NULL,
178*0Sstevel@tonic-gate 	rsa_decrypt_atomic
179*0Sstevel@tonic-gate };
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate static int rsa_sign_verify_common_init(crypto_ctx_t *, crypto_mechanism_t *,
182*0Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
183*0Sstevel@tonic-gate static int rsa_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
184*0Sstevel@tonic-gate     crypto_req_handle_t);
185*0Sstevel@tonic-gate static int rsa_sign_update(crypto_ctx_t *, crypto_data_t *,
186*0Sstevel@tonic-gate     crypto_req_handle_t);
187*0Sstevel@tonic-gate static int rsa_sign_final(crypto_ctx_t *, crypto_data_t *,
188*0Sstevel@tonic-gate     crypto_req_handle_t);
189*0Sstevel@tonic-gate static int rsa_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
190*0Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
191*0Sstevel@tonic-gate     crypto_spi_ctx_template_t, crypto_req_handle_t);
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate /*
194*0Sstevel@tonic-gate  * We use the same routine for sign_init and sign_recover_init fields
195*0Sstevel@tonic-gate  * as they do the same thing. Same holds for sign and sign_recover fields,
196*0Sstevel@tonic-gate  * and sign_atomic and sign_recover_atomic fields.
197*0Sstevel@tonic-gate  */
198*0Sstevel@tonic-gate static crypto_sign_ops_t rsa_sign_ops = {
199*0Sstevel@tonic-gate 	rsa_sign_verify_common_init,
200*0Sstevel@tonic-gate 	rsa_sign,
201*0Sstevel@tonic-gate 	rsa_sign_update,
202*0Sstevel@tonic-gate 	rsa_sign_final,
203*0Sstevel@tonic-gate 	rsa_sign_atomic,
204*0Sstevel@tonic-gate 	rsa_sign_verify_common_init,
205*0Sstevel@tonic-gate 	rsa_sign,
206*0Sstevel@tonic-gate 	rsa_sign_atomic
207*0Sstevel@tonic-gate };
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate static int rsa_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
210*0Sstevel@tonic-gate     crypto_req_handle_t);
211*0Sstevel@tonic-gate static int rsa_verify_update(crypto_ctx_t *, crypto_data_t *,
212*0Sstevel@tonic-gate     crypto_req_handle_t);
213*0Sstevel@tonic-gate static int rsa_verify_final(crypto_ctx_t *, crypto_data_t *,
214*0Sstevel@tonic-gate     crypto_req_handle_t);
215*0Sstevel@tonic-gate static int rsa_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
216*0Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
217*0Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
218*0Sstevel@tonic-gate static int rsa_verify_recover(crypto_ctx_t *, crypto_data_t *,
219*0Sstevel@tonic-gate     crypto_data_t *, crypto_req_handle_t);
220*0Sstevel@tonic-gate static int rsa_verify_recover_atomic(crypto_provider_handle_t,
221*0Sstevel@tonic-gate     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
222*0Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
223*0Sstevel@tonic-gate     crypto_req_handle_t);
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate /*
226*0Sstevel@tonic-gate  * We use the same routine (rsa_sign_verify_common_init) for verify_init
227*0Sstevel@tonic-gate  * and verify_recover_init fields as they do the same thing.
228*0Sstevel@tonic-gate  */
229*0Sstevel@tonic-gate static crypto_verify_ops_t rsa_verify_ops = {
230*0Sstevel@tonic-gate 	rsa_sign_verify_common_init,
231*0Sstevel@tonic-gate 	rsa_verify,
232*0Sstevel@tonic-gate 	rsa_verify_update,
233*0Sstevel@tonic-gate 	rsa_verify_final,
234*0Sstevel@tonic-gate 	rsa_verify_atomic,
235*0Sstevel@tonic-gate 	rsa_sign_verify_common_init,
236*0Sstevel@tonic-gate 	rsa_verify_recover,
237*0Sstevel@tonic-gate 	rsa_verify_recover_atomic
238*0Sstevel@tonic-gate };
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate static int rsa_free_context(crypto_ctx_t *);
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate static crypto_ctx_ops_t rsa_ctx_ops = {
243*0Sstevel@tonic-gate 	NULL,
244*0Sstevel@tonic-gate 	rsa_free_context
245*0Sstevel@tonic-gate };
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate static crypto_ops_t rsa_crypto_ops = {
248*0Sstevel@tonic-gate 	&rsa_control_ops,
249*0Sstevel@tonic-gate 	NULL,
250*0Sstevel@tonic-gate 	&rsa_cipher_ops,
251*0Sstevel@tonic-gate 	NULL,
252*0Sstevel@tonic-gate 	&rsa_sign_ops,
253*0Sstevel@tonic-gate 	&rsa_verify_ops,
254*0Sstevel@tonic-gate 	NULL,
255*0Sstevel@tonic-gate 	NULL,
256*0Sstevel@tonic-gate 	NULL,
257*0Sstevel@tonic-gate 	NULL,
258*0Sstevel@tonic-gate 	NULL,
259*0Sstevel@tonic-gate 	NULL,
260*0Sstevel@tonic-gate 	NULL,
261*0Sstevel@tonic-gate 	&rsa_ctx_ops
262*0Sstevel@tonic-gate };
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate static crypto_provider_info_t rsa_prov_info = {
265*0Sstevel@tonic-gate 	CRYPTO_SPI_VERSION_1,
266*0Sstevel@tonic-gate 	"RSA Software Provider",
267*0Sstevel@tonic-gate 	CRYPTO_SW_PROVIDER,
268*0Sstevel@tonic-gate 	{&modlinkage},
269*0Sstevel@tonic-gate 	NULL,
270*0Sstevel@tonic-gate 	&rsa_crypto_ops,
271*0Sstevel@tonic-gate 	sizeof (rsa_mech_info_tab)/sizeof (crypto_mech_info_t),
272*0Sstevel@tonic-gate 	rsa_mech_info_tab
273*0Sstevel@tonic-gate };
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate static int rsa_encrypt_common(rsa_mech_type_t, crypto_key_t *,
276*0Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
277*0Sstevel@tonic-gate static int rsa_decrypt_common(rsa_mech_type_t, crypto_key_t *,
278*0Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
279*0Sstevel@tonic-gate static int rsa_sign_common(rsa_mech_type_t, crypto_key_t *,
280*0Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
281*0Sstevel@tonic-gate static int rsa_verify_common(rsa_mech_type_t, crypto_key_t *,
282*0Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
283*0Sstevel@tonic-gate static int compare_data(crypto_data_t *, uchar_t *);
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate /* EXPORT DELETE START */
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate static int core_rsa_encrypt(crypto_key_t *, uchar_t *,
288*0Sstevel@tonic-gate     int, uchar_t *, int, int);
289*0Sstevel@tonic-gate static int core_rsa_decrypt(crypto_key_t *, uchar_t *, int,
290*0Sstevel@tonic-gate     uchar_t *, int);
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate /* EXPORT DELETE END */
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate static crypto_kcf_provider_handle_t rsa_prov_handle = NULL;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate int
297*0Sstevel@tonic-gate _init(void)
298*0Sstevel@tonic-gate {
299*0Sstevel@tonic-gate 	int ret;
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate 	/*
302*0Sstevel@tonic-gate 	 * Register with KCF. If the registration fails, return error.
303*0Sstevel@tonic-gate 	 */
304*0Sstevel@tonic-gate 	if ((ret = crypto_register_provider(&rsa_prov_info,
305*0Sstevel@tonic-gate 	    &rsa_prov_handle)) != CRYPTO_SUCCESS) {
306*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "rsa _init: crypto_register_provider()"
307*0Sstevel@tonic-gate 		    "failed (0x%x)", ret);
308*0Sstevel@tonic-gate 		return (EACCES);
309*0Sstevel@tonic-gate 	}
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	if ((ret = mod_install(&modlinkage)) != 0) {
312*0Sstevel@tonic-gate 		int rv;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 		ASSERT(rsa_prov_handle != NULL);
315*0Sstevel@tonic-gate 		/* We should not return if the unregister returns busy. */
316*0Sstevel@tonic-gate 		while ((rv = crypto_unregister_provider(rsa_prov_handle))
317*0Sstevel@tonic-gate 		    == CRYPTO_BUSY) {
318*0Sstevel@tonic-gate 			cmn_err(CE_WARN, "rsa _init: "
319*0Sstevel@tonic-gate 			    "crypto_unregister_provider() "
320*0Sstevel@tonic-gate 			    "failed (0x%x). Retrying.", rv);
321*0Sstevel@tonic-gate 			/* wait 10 seconds and try again. */
322*0Sstevel@tonic-gate 			delay(10 * drv_usectohz(1000000));
323*0Sstevel@tonic-gate 		}
324*0Sstevel@tonic-gate 	}
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 	return (ret);
327*0Sstevel@tonic-gate }
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate int
330*0Sstevel@tonic-gate _fini(void)
331*0Sstevel@tonic-gate {
332*0Sstevel@tonic-gate 	int ret;
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	/*
335*0Sstevel@tonic-gate 	 * Unregister from KCF if previous registration succeeded.
336*0Sstevel@tonic-gate 	 */
337*0Sstevel@tonic-gate 	if (rsa_prov_handle != NULL) {
338*0Sstevel@tonic-gate 		if ((ret = crypto_unregister_provider(rsa_prov_handle)) !=
339*0Sstevel@tonic-gate 		    CRYPTO_SUCCESS) {
340*0Sstevel@tonic-gate 			cmn_err(CE_WARN, "rsa _fini: "
341*0Sstevel@tonic-gate 			    "crypto_unregister_provider() "
342*0Sstevel@tonic-gate 			    "failed (0x%x)", ret);
343*0Sstevel@tonic-gate 			return (EBUSY);
344*0Sstevel@tonic-gate 		}
345*0Sstevel@tonic-gate 		rsa_prov_handle = NULL;
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate int
352*0Sstevel@tonic-gate _info(struct modinfo *modinfop)
353*0Sstevel@tonic-gate {
354*0Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
355*0Sstevel@tonic-gate }
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate /* ARGSUSED */
358*0Sstevel@tonic-gate static void
359*0Sstevel@tonic-gate rsa_provider_status(crypto_provider_handle_t provider, uint_t *status)
360*0Sstevel@tonic-gate {
361*0Sstevel@tonic-gate 	*status = CRYPTO_PROVIDER_READY;
362*0Sstevel@tonic-gate }
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate /*
365*0Sstevel@tonic-gate  * Utility routine to look up a attribute of type, 'type',
366*0Sstevel@tonic-gate  * in the key.
367*0Sstevel@tonic-gate  */
368*0Sstevel@tonic-gate static int
369*0Sstevel@tonic-gate get_key_attr(crypto_key_t *key, crypto_attr_type_t type,
370*0Sstevel@tonic-gate     uchar_t **value, ssize_t *value_len)
371*0Sstevel@tonic-gate {
372*0Sstevel@tonic-gate 	int i;
373*0Sstevel@tonic-gate 
374*0Sstevel@tonic-gate 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
375*0Sstevel@tonic-gate 	for (i = 0; i < key->ck_count; i++) {
376*0Sstevel@tonic-gate 		if (key->ck_attrs[i].oa_type == type) {
377*0Sstevel@tonic-gate 			*value = (uchar_t *)key->ck_attrs[i].oa_value;
378*0Sstevel@tonic-gate 			*value_len = key->ck_attrs[i].oa_value_len;
379*0Sstevel@tonic-gate 			return (CRYPTO_SUCCESS);
380*0Sstevel@tonic-gate 		}
381*0Sstevel@tonic-gate 	}
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	return (CRYPTO_FAILED);
384*0Sstevel@tonic-gate }
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate static int
387*0Sstevel@tonic-gate check_mech_and_key(crypto_mechanism_t *mechanism, crypto_key_t *key)
388*0Sstevel@tonic-gate {
389*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate /* EXPORT DELETE START */
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 	uchar_t *modulus;
394*0Sstevel@tonic-gate 	ssize_t modulus_len; /* In bytes */
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 	if (!RSA_VALID_MECH(mechanism))
397*0Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 	/*
400*0Sstevel@tonic-gate 	 * We only support RSA keys that are passed as a list of
401*0Sstevel@tonic-gate 	 * object attributes.
402*0Sstevel@tonic-gate 	 */
403*0Sstevel@tonic-gate 	if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
404*0Sstevel@tonic-gate 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
408*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
409*0Sstevel@tonic-gate 		return (rv);
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 	if (modulus_len < MIN_RSA_KEYLENGTH_IN_BYTES ||
412*0Sstevel@tonic-gate 	    modulus_len > MAX_RSA_KEYLENGTH_IN_BYTES)
413*0Sstevel@tonic-gate 		return (CRYPTO_KEY_SIZE_RANGE);
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate /* EXPORT DELETE END */
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	return (rv);
418*0Sstevel@tonic-gate }
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate void
421*0Sstevel@tonic-gate kmemset(uint8_t *buf, char pattern, size_t len)
422*0Sstevel@tonic-gate {
423*0Sstevel@tonic-gate 	int i = 0;
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate 	while (i < len)
426*0Sstevel@tonic-gate 		buf[i++] = pattern;
427*0Sstevel@tonic-gate }
428*0Sstevel@tonic-gate 
429*0Sstevel@tonic-gate /*
430*0Sstevel@tonic-gate  * This function guarantees to return non-zero random numbers.
431*0Sstevel@tonic-gate  * This is needed as the /dev/urandom kernel interface,
432*0Sstevel@tonic-gate  * random_get_pseudo_bytes(), may return zeros.
433*0Sstevel@tonic-gate  */
434*0Sstevel@tonic-gate int
435*0Sstevel@tonic-gate knzero_random_generator(uint8_t *ran_out, size_t ran_len)
436*0Sstevel@tonic-gate {
437*0Sstevel@tonic-gate 	int rv;
438*0Sstevel@tonic-gate 	size_t ebc = 0; /* count of extra bytes in extrarand */
439*0Sstevel@tonic-gate 	size_t i = 0;
440*0Sstevel@tonic-gate 	uint8_t extrarand[32];
441*0Sstevel@tonic-gate 	size_t extrarand_len;
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate 	if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0)
444*0Sstevel@tonic-gate 		return (rv);
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 	/*
447*0Sstevel@tonic-gate 	 * Walk through the returned random numbers pointed by ran_out,
448*0Sstevel@tonic-gate 	 * and look for any random number which is zero.
449*0Sstevel@tonic-gate 	 * If we find zero, call random_get_pseudo_bytes() to generate
450*0Sstevel@tonic-gate 	 * another 32 random numbers pool. Replace any zeros in ran_out[]
451*0Sstevel@tonic-gate 	 * from the random number in pool.
452*0Sstevel@tonic-gate 	 */
453*0Sstevel@tonic-gate 	while (i < ran_len) {
454*0Sstevel@tonic-gate 		if (ran_out[i] != 0) {
455*0Sstevel@tonic-gate 			i++;
456*0Sstevel@tonic-gate 			continue;
457*0Sstevel@tonic-gate 		}
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 		/*
460*0Sstevel@tonic-gate 		 * Note that it is 'while' so we are guaranteed a
461*0Sstevel@tonic-gate 		 * non-zero value on exit.
462*0Sstevel@tonic-gate 		 */
463*0Sstevel@tonic-gate 		if (ebc == 0) {
464*0Sstevel@tonic-gate 			/* refresh extrarand */
465*0Sstevel@tonic-gate 			extrarand_len = sizeof (extrarand);
466*0Sstevel@tonic-gate 			if ((rv = random_get_pseudo_bytes(extrarand,
467*0Sstevel@tonic-gate 			    extrarand_len)) != 0) {
468*0Sstevel@tonic-gate 				return (rv);
469*0Sstevel@tonic-gate 			}
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 			ebc = extrarand_len;
472*0Sstevel@tonic-gate 		}
473*0Sstevel@tonic-gate 		/* Replace zero with byte from extrarand. */
474*0Sstevel@tonic-gate 		-- ebc;
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate 		/*
477*0Sstevel@tonic-gate 		 * The new random byte zero/non-zero will be checked in
478*0Sstevel@tonic-gate 		 * the next pass through the loop.
479*0Sstevel@tonic-gate 		 */
480*0Sstevel@tonic-gate 		ran_out[i] = extrarand[ebc];
481*0Sstevel@tonic-gate 	}
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
484*0Sstevel@tonic-gate }
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate typedef enum cmd_type {
487*0Sstevel@tonic-gate 	COPY_FROM_DATA,
488*0Sstevel@tonic-gate 	COPY_TO_DATA,
489*0Sstevel@tonic-gate 	COMPARE_TO_DATA,
490*0Sstevel@tonic-gate 	MD5_DIGEST_DATA,
491*0Sstevel@tonic-gate 	SHA1_DIGEST_DATA
492*0Sstevel@tonic-gate } cmd_type_t;
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate /*
495*0Sstevel@tonic-gate  * Utility routine to apply the command, 'cmd', to the
496*0Sstevel@tonic-gate  * data in the uio structure.
497*0Sstevel@tonic-gate  */
498*0Sstevel@tonic-gate static int
499*0Sstevel@tonic-gate process_uio_data(crypto_data_t *data, uchar_t *buf, int len,
500*0Sstevel@tonic-gate     cmd_type_t cmd, void *digest_ctx)
501*0Sstevel@tonic-gate {
502*0Sstevel@tonic-gate 	uio_t *uiop = data->cd_uio;
503*0Sstevel@tonic-gate 	off_t offset = data->cd_offset;
504*0Sstevel@tonic-gate 	size_t length = len;
505*0Sstevel@tonic-gate 	uint_t vec_idx;
506*0Sstevel@tonic-gate 	size_t cur_len;
507*0Sstevel@tonic-gate 	uchar_t *datap;
508*0Sstevel@tonic-gate 
509*0Sstevel@tonic-gate 	ASSERT(data->cd_format == CRYPTO_DATA_UIO);
510*0Sstevel@tonic-gate 	if (uiop->uio_segflg != UIO_SYSSPACE) {
511*0Sstevel@tonic-gate 		return (CRYPTO_ARGUMENTS_BAD);
512*0Sstevel@tonic-gate 	}
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate 	/*
515*0Sstevel@tonic-gate 	 * Jump to the first iovec containing data to be
516*0Sstevel@tonic-gate 	 * processed.
517*0Sstevel@tonic-gate 	 */
518*0Sstevel@tonic-gate 	for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
519*0Sstevel@tonic-gate 	    offset >= uiop->uio_iov[vec_idx].iov_len;
520*0Sstevel@tonic-gate 	    offset -= uiop->uio_iov[vec_idx++].iov_len);
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 	if (vec_idx == uiop->uio_iovcnt) {
523*0Sstevel@tonic-gate 		/*
524*0Sstevel@tonic-gate 		 * The caller specified an offset that is larger than
525*0Sstevel@tonic-gate 		 * the total size of the buffers it provided.
526*0Sstevel@tonic-gate 		 */
527*0Sstevel@tonic-gate 		return (CRYPTO_DATA_LEN_RANGE);
528*0Sstevel@tonic-gate 	}
529*0Sstevel@tonic-gate 
530*0Sstevel@tonic-gate 	while (vec_idx < uiop->uio_iovcnt && length > 0) {
531*0Sstevel@tonic-gate 		cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
532*0Sstevel@tonic-gate 		    offset, length);
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate 		datap = (uchar_t *)(uiop->uio_iov[vec_idx].iov_base +
535*0Sstevel@tonic-gate 		    offset);
536*0Sstevel@tonic-gate 		switch (cmd) {
537*0Sstevel@tonic-gate 		case COPY_FROM_DATA:
538*0Sstevel@tonic-gate 			bcopy(datap, buf, cur_len);
539*0Sstevel@tonic-gate 			buf += cur_len;
540*0Sstevel@tonic-gate 			break;
541*0Sstevel@tonic-gate 		case COPY_TO_DATA:
542*0Sstevel@tonic-gate 			bcopy(buf, datap, cur_len);
543*0Sstevel@tonic-gate 			buf += cur_len;
544*0Sstevel@tonic-gate 			break;
545*0Sstevel@tonic-gate 		case COMPARE_TO_DATA:
546*0Sstevel@tonic-gate 			if (bcmp(datap, buf, cur_len))
547*0Sstevel@tonic-gate 				return (CRYPTO_SIGNATURE_INVALID);
548*0Sstevel@tonic-gate 			buf += cur_len;
549*0Sstevel@tonic-gate 			break;
550*0Sstevel@tonic-gate 		case MD5_DIGEST_DATA:
551*0Sstevel@tonic-gate 			MD5Update(digest_ctx, datap, cur_len);
552*0Sstevel@tonic-gate 			break;
553*0Sstevel@tonic-gate 		case SHA1_DIGEST_DATA:
554*0Sstevel@tonic-gate 			SHA1Update(digest_ctx, datap, cur_len);
555*0Sstevel@tonic-gate 			break;
556*0Sstevel@tonic-gate 		}
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 		length -= cur_len;
559*0Sstevel@tonic-gate 		vec_idx++;
560*0Sstevel@tonic-gate 		offset = 0;
561*0Sstevel@tonic-gate 	}
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
564*0Sstevel@tonic-gate 		/*
565*0Sstevel@tonic-gate 		 * The end of the specified iovec's was reached but
566*0Sstevel@tonic-gate 		 * the length requested could not be processed.
567*0Sstevel@tonic-gate 		 */
568*0Sstevel@tonic-gate 		switch (cmd) {
569*0Sstevel@tonic-gate 		case COPY_TO_DATA:
570*0Sstevel@tonic-gate 			data->cd_length = len;
571*0Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
572*0Sstevel@tonic-gate 		default:
573*0Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
574*0Sstevel@tonic-gate 		}
575*0Sstevel@tonic-gate 	}
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
578*0Sstevel@tonic-gate }
579*0Sstevel@tonic-gate 
580*0Sstevel@tonic-gate /*
581*0Sstevel@tonic-gate  * Utility routine to apply the command, 'cmd', to the
582*0Sstevel@tonic-gate  * data in the mblk structure.
583*0Sstevel@tonic-gate  */
584*0Sstevel@tonic-gate static int
585*0Sstevel@tonic-gate process_mblk_data(crypto_data_t *data, uchar_t *buf, int len,
586*0Sstevel@tonic-gate     cmd_type_t cmd, void *digest_ctx)
587*0Sstevel@tonic-gate {
588*0Sstevel@tonic-gate 	off_t offset = data->cd_offset;
589*0Sstevel@tonic-gate 	size_t length = len;
590*0Sstevel@tonic-gate 	mblk_t *mp;
591*0Sstevel@tonic-gate 	size_t cur_len;
592*0Sstevel@tonic-gate 	uchar_t *datap;
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 	ASSERT(data->cd_format == CRYPTO_DATA_MBLK);
595*0Sstevel@tonic-gate 	/*
596*0Sstevel@tonic-gate 	 * Jump to the first mblk_t containing data to be processed.
597*0Sstevel@tonic-gate 	 */
598*0Sstevel@tonic-gate 	for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
599*0Sstevel@tonic-gate 	    offset -= MBLKL(mp), mp = mp->b_cont);
600*0Sstevel@tonic-gate 	if (mp == NULL) {
601*0Sstevel@tonic-gate 		/*
602*0Sstevel@tonic-gate 		 * The caller specified an offset that is larger
603*0Sstevel@tonic-gate 		 * than the total size of the buffers it provided.
604*0Sstevel@tonic-gate 		 */
605*0Sstevel@tonic-gate 		return (CRYPTO_DATA_LEN_RANGE);
606*0Sstevel@tonic-gate 	}
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate 	/*
609*0Sstevel@tonic-gate 	 * Now do the processing on the mblk chain.
610*0Sstevel@tonic-gate 	 */
611*0Sstevel@tonic-gate 	while (mp != NULL && length > 0) {
612*0Sstevel@tonic-gate 		cur_len = MIN(MBLKL(mp) - offset, length);
613*0Sstevel@tonic-gate 
614*0Sstevel@tonic-gate 		datap = (uchar_t *)(mp->b_rptr + offset);
615*0Sstevel@tonic-gate 		switch (cmd) {
616*0Sstevel@tonic-gate 		case COPY_FROM_DATA:
617*0Sstevel@tonic-gate 			bcopy(datap, buf, cur_len);
618*0Sstevel@tonic-gate 			buf += cur_len;
619*0Sstevel@tonic-gate 			break;
620*0Sstevel@tonic-gate 		case COPY_TO_DATA:
621*0Sstevel@tonic-gate 			bcopy(buf, datap, cur_len);
622*0Sstevel@tonic-gate 			buf += cur_len;
623*0Sstevel@tonic-gate 			break;
624*0Sstevel@tonic-gate 		case COMPARE_TO_DATA:
625*0Sstevel@tonic-gate 			if (bcmp(datap, buf, cur_len))
626*0Sstevel@tonic-gate 				return (CRYPTO_SIGNATURE_INVALID);
627*0Sstevel@tonic-gate 			buf += cur_len;
628*0Sstevel@tonic-gate 			break;
629*0Sstevel@tonic-gate 		case MD5_DIGEST_DATA:
630*0Sstevel@tonic-gate 			MD5Update(digest_ctx, datap, cur_len);
631*0Sstevel@tonic-gate 			break;
632*0Sstevel@tonic-gate 		case SHA1_DIGEST_DATA:
633*0Sstevel@tonic-gate 			SHA1Update(digest_ctx, datap, cur_len);
634*0Sstevel@tonic-gate 			break;
635*0Sstevel@tonic-gate 		}
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 		length -= cur_len;
638*0Sstevel@tonic-gate 		offset = 0;
639*0Sstevel@tonic-gate 		mp = mp->b_cont;
640*0Sstevel@tonic-gate 	}
641*0Sstevel@tonic-gate 
642*0Sstevel@tonic-gate 	if (mp == NULL && length > 0) {
643*0Sstevel@tonic-gate 		/*
644*0Sstevel@tonic-gate 		 * The end of the mblk was reached but the length
645*0Sstevel@tonic-gate 		 * requested could not be processed.
646*0Sstevel@tonic-gate 		 */
647*0Sstevel@tonic-gate 		switch (cmd) {
648*0Sstevel@tonic-gate 		case COPY_TO_DATA:
649*0Sstevel@tonic-gate 			data->cd_length = len;
650*0Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
651*0Sstevel@tonic-gate 		default:
652*0Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
653*0Sstevel@tonic-gate 		}
654*0Sstevel@tonic-gate 	}
655*0Sstevel@tonic-gate 
656*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
657*0Sstevel@tonic-gate }
658*0Sstevel@tonic-gate 
659*0Sstevel@tonic-gate static int
660*0Sstevel@tonic-gate compare_data(crypto_data_t *data, uchar_t *buf)
661*0Sstevel@tonic-gate {
662*0Sstevel@tonic-gate 	int len;
663*0Sstevel@tonic-gate 	uchar_t *dptr;
664*0Sstevel@tonic-gate 
665*0Sstevel@tonic-gate 	len = data->cd_length;
666*0Sstevel@tonic-gate 	switch (data->cd_format) {
667*0Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
668*0Sstevel@tonic-gate 		dptr = (uchar_t *)(data->cd_raw.iov_base +
669*0Sstevel@tonic-gate 		    data->cd_offset);
670*0Sstevel@tonic-gate 
671*0Sstevel@tonic-gate 		return (bcmp(dptr, buf, len));
672*0Sstevel@tonic-gate 
673*0Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
674*0Sstevel@tonic-gate 		return (process_uio_data(data, buf, len,
675*0Sstevel@tonic-gate 		    COMPARE_TO_DATA, NULL));
676*0Sstevel@tonic-gate 
677*0Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
678*0Sstevel@tonic-gate 		return (process_mblk_data(data, buf, len,
679*0Sstevel@tonic-gate 		    COMPARE_TO_DATA, NULL));
680*0Sstevel@tonic-gate 	}
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate 	return (CRYPTO_FAILED);
683*0Sstevel@tonic-gate }
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate /*
686*0Sstevel@tonic-gate  * Utility routine to copy a buffer to a crypto_data structure.
687*0Sstevel@tonic-gate  */
688*0Sstevel@tonic-gate static int
689*0Sstevel@tonic-gate put_output_data(uchar_t *buf, crypto_data_t *output, int len)
690*0Sstevel@tonic-gate {
691*0Sstevel@tonic-gate 	switch (output->cd_format) {
692*0Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
693*0Sstevel@tonic-gate 		if (output->cd_raw.iov_len < len) {
694*0Sstevel@tonic-gate 			output->cd_length = len;
695*0Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
696*0Sstevel@tonic-gate 		}
697*0Sstevel@tonic-gate 		bcopy(buf, (uchar_t *)(output->cd_raw.iov_base +
698*0Sstevel@tonic-gate 		    output->cd_offset), len);
699*0Sstevel@tonic-gate 		break;
700*0Sstevel@tonic-gate 
701*0Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
702*0Sstevel@tonic-gate 		return (process_uio_data(output, buf, len, COPY_TO_DATA, NULL));
703*0Sstevel@tonic-gate 
704*0Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
705*0Sstevel@tonic-gate 		return (process_mblk_data(output, buf, len,
706*0Sstevel@tonic-gate 		    COPY_TO_DATA, NULL));
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 	default:
709*0Sstevel@tonic-gate 		return (CRYPTO_ARGUMENTS_BAD);
710*0Sstevel@tonic-gate 	}
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
713*0Sstevel@tonic-gate }
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate /*
716*0Sstevel@tonic-gate  * Utility routine to get data from a crypto_data structure.
717*0Sstevel@tonic-gate  *
718*0Sstevel@tonic-gate  * '*dptr' contains a pointer to a buffer on return. 'buf'
719*0Sstevel@tonic-gate  * is allocated by the caller and is ignored for CRYPTO_DATA_RAW case.
720*0Sstevel@tonic-gate  */
721*0Sstevel@tonic-gate static int
722*0Sstevel@tonic-gate get_input_data(crypto_data_t *input, uchar_t **dptr, uchar_t *buf)
723*0Sstevel@tonic-gate {
724*0Sstevel@tonic-gate 	int rv;
725*0Sstevel@tonic-gate 
726*0Sstevel@tonic-gate 	switch (input->cd_format) {
727*0Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
728*0Sstevel@tonic-gate 		if (input->cd_raw.iov_len < input->cd_length)
729*0Sstevel@tonic-gate 			return (CRYPTO_ARGUMENTS_BAD);
730*0Sstevel@tonic-gate 		*dptr = (uchar_t *)(input->cd_raw.iov_base +
731*0Sstevel@tonic-gate 		    input->cd_offset);
732*0Sstevel@tonic-gate 		break;
733*0Sstevel@tonic-gate 
734*0Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
735*0Sstevel@tonic-gate 		if ((rv = process_uio_data(input, buf, input->cd_length,
736*0Sstevel@tonic-gate 		    COPY_FROM_DATA, NULL)) != CRYPTO_SUCCESS)
737*0Sstevel@tonic-gate 			return (rv);
738*0Sstevel@tonic-gate 		*dptr = buf;
739*0Sstevel@tonic-gate 		break;
740*0Sstevel@tonic-gate 
741*0Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
742*0Sstevel@tonic-gate 		if ((rv = process_mblk_data(input, buf, input->cd_length,
743*0Sstevel@tonic-gate 		    COPY_FROM_DATA, NULL)) != CRYPTO_SUCCESS)
744*0Sstevel@tonic-gate 			return (rv);
745*0Sstevel@tonic-gate 		*dptr = buf;
746*0Sstevel@tonic-gate 		break;
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 	default:
749*0Sstevel@tonic-gate 		return (CRYPTO_ARGUMENTS_BAD);
750*0Sstevel@tonic-gate 	}
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
753*0Sstevel@tonic-gate }
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate static int
756*0Sstevel@tonic-gate copy_key_to_ctx(crypto_key_t *in_key, rsa_ctx_t *ctx, int kmflag)
757*0Sstevel@tonic-gate {
758*0Sstevel@tonic-gate 	int i, count;
759*0Sstevel@tonic-gate 	size_t len;
760*0Sstevel@tonic-gate 	caddr_t attr_val;
761*0Sstevel@tonic-gate 	crypto_object_attribute_t *k_attrs = NULL;
762*0Sstevel@tonic-gate 
763*0Sstevel@tonic-gate 	ASSERT(in_key->ck_format == CRYPTO_KEY_ATTR_LIST);
764*0Sstevel@tonic-gate 
765*0Sstevel@tonic-gate 	count = in_key->ck_count;
766*0Sstevel@tonic-gate 	/* figure out how much memory to allocate for everything */
767*0Sstevel@tonic-gate 	len = sizeof (crypto_key_t) +
768*0Sstevel@tonic-gate 	    count * sizeof (crypto_object_attribute_t);
769*0Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
770*0Sstevel@tonic-gate 		len += roundup(in_key->ck_attrs[i].oa_value_len,
771*0Sstevel@tonic-gate 		    sizeof (caddr_t));
772*0Sstevel@tonic-gate 	}
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 	/* one big allocation for everything */
775*0Sstevel@tonic-gate 	ctx->key = kmem_alloc(len, kmflag);
776*0Sstevel@tonic-gate 	if (ctx->key == NULL)
777*0Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
778*0Sstevel@tonic-gate 	k_attrs = (crypto_object_attribute_t *)((caddr_t)(ctx->key) +
779*0Sstevel@tonic-gate 	    sizeof (crypto_key_t));
780*0Sstevel@tonic-gate 
781*0Sstevel@tonic-gate 	attr_val = (caddr_t)k_attrs +
782*0Sstevel@tonic-gate 	    count * sizeof (crypto_object_attribute_t);
783*0Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
784*0Sstevel@tonic-gate 		k_attrs[i].oa_type = in_key->ck_attrs[i].oa_type;
785*0Sstevel@tonic-gate 		bcopy(in_key->ck_attrs[i].oa_value, attr_val,
786*0Sstevel@tonic-gate 		    in_key->ck_attrs[i].oa_value_len);
787*0Sstevel@tonic-gate 		k_attrs[i].oa_value = attr_val;
788*0Sstevel@tonic-gate 		k_attrs[i].oa_value_len = in_key->ck_attrs[i].oa_value_len;
789*0Sstevel@tonic-gate 		attr_val += roundup(k_attrs[i].oa_value_len, sizeof (caddr_t));
790*0Sstevel@tonic-gate 	}
791*0Sstevel@tonic-gate 
792*0Sstevel@tonic-gate 	ctx->keychunk_size = len;	/* save the size to be freed */
793*0Sstevel@tonic-gate 	ctx->key->ck_format = CRYPTO_KEY_ATTR_LIST;
794*0Sstevel@tonic-gate 	ctx->key->ck_count = count;
795*0Sstevel@tonic-gate 	ctx->key->ck_attrs = k_attrs;
796*0Sstevel@tonic-gate 
797*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
798*0Sstevel@tonic-gate }
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate /* ARGSUSED */
801*0Sstevel@tonic-gate static int
802*0Sstevel@tonic-gate rsa_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
803*0Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t template,
804*0Sstevel@tonic-gate     crypto_req_handle_t req)
805*0Sstevel@tonic-gate {
806*0Sstevel@tonic-gate 	int rv;
807*0Sstevel@tonic-gate 	int kmflag;
808*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
809*0Sstevel@tonic-gate 
810*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
811*0Sstevel@tonic-gate 		return (rv);
812*0Sstevel@tonic-gate 
813*0Sstevel@tonic-gate 	/*
814*0Sstevel@tonic-gate 	 * Allocate a RSA context.
815*0Sstevel@tonic-gate 	 */
816*0Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
817*0Sstevel@tonic-gate 	if ((ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag)) == NULL)
818*0Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 	if ((rv = copy_key_to_ctx(key, ctxp, kmflag)) != CRYPTO_SUCCESS) {
821*0Sstevel@tonic-gate 		kmem_free(ctxp, sizeof (rsa_ctx_t));
822*0Sstevel@tonic-gate 		return (rv);
823*0Sstevel@tonic-gate 	}
824*0Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
827*0Sstevel@tonic-gate 
828*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
829*0Sstevel@tonic-gate }
830*0Sstevel@tonic-gate 
831*0Sstevel@tonic-gate /* ARGSUSED */
832*0Sstevel@tonic-gate static int
833*0Sstevel@tonic-gate rsa_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
834*0Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_req_handle_t req)
835*0Sstevel@tonic-gate {
836*0Sstevel@tonic-gate 	int rv;
837*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
838*0Sstevel@tonic-gate 
839*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
840*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
841*0Sstevel@tonic-gate 
842*0Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
843*0Sstevel@tonic-gate 
844*0Sstevel@tonic-gate 	/*
845*0Sstevel@tonic-gate 	 * Note on the KM_SLEEP flag passed to the routine below -
846*0Sstevel@tonic-gate 	 * rsa_encrypt() is a single-part encryption routine which is
847*0Sstevel@tonic-gate 	 * currently usable only by /dev/crypto. Since /dev/crypto calls are
848*0Sstevel@tonic-gate 	 * always synchronous, we can safely pass KM_SLEEP here.
849*0Sstevel@tonic-gate 	 */
850*0Sstevel@tonic-gate 	rv = rsa_encrypt_common(ctxp->mech_type, ctxp->key, plaintext,
851*0Sstevel@tonic-gate 	    ciphertext, KM_SLEEP);
852*0Sstevel@tonic-gate 
853*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
854*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate 	return (rv);
857*0Sstevel@tonic-gate }
858*0Sstevel@tonic-gate 
859*0Sstevel@tonic-gate /* ARGSUSED */
860*0Sstevel@tonic-gate static int
861*0Sstevel@tonic-gate rsa_encrypt_atomic(crypto_provider_handle_t provider,
862*0Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
863*0Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
864*0Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
865*0Sstevel@tonic-gate {
866*0Sstevel@tonic-gate 	int rv;
867*0Sstevel@tonic-gate 
868*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
869*0Sstevel@tonic-gate 		return (rv);
870*0Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
871*0Sstevel@tonic-gate 
872*0Sstevel@tonic-gate 	return (rsa_encrypt_common(mechanism->cm_type, key, plaintext,
873*0Sstevel@tonic-gate 	    ciphertext, crypto_kmflag(req)));
874*0Sstevel@tonic-gate }
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate static int
877*0Sstevel@tonic-gate rsa_free_context(crypto_ctx_t *ctx)
878*0Sstevel@tonic-gate {
879*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp = ctx->cc_provider_private;
880*0Sstevel@tonic-gate 
881*0Sstevel@tonic-gate 	if (ctxp != NULL) {
882*0Sstevel@tonic-gate 		bzero(ctxp->key, ctxp->keychunk_size);
883*0Sstevel@tonic-gate 		kmem_free(ctxp->key, ctxp->keychunk_size);
884*0Sstevel@tonic-gate 
885*0Sstevel@tonic-gate 		if (ctxp->mech_type == RSA_PKCS_MECH_INFO_TYPE ||
886*0Sstevel@tonic-gate 		    ctxp->mech_type == RSA_X_509_MECH_INFO_TYPE)
887*0Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
888*0Sstevel@tonic-gate 		else
889*0Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (digest_rsa_ctx_t));
890*0Sstevel@tonic-gate 
891*0Sstevel@tonic-gate 		ctx->cc_provider_private = NULL;
892*0Sstevel@tonic-gate 	}
893*0Sstevel@tonic-gate 
894*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
895*0Sstevel@tonic-gate }
896*0Sstevel@tonic-gate 
897*0Sstevel@tonic-gate static int
898*0Sstevel@tonic-gate rsa_encrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
899*0Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_data_t *ciphertext, int kmflag)
900*0Sstevel@tonic-gate {
901*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
902*0Sstevel@tonic-gate 
903*0Sstevel@tonic-gate /* EXPORT DELETE START */
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate 	int plen;
906*0Sstevel@tonic-gate 	uchar_t *ptptr;
907*0Sstevel@tonic-gate 	uchar_t *modulus;
908*0Sstevel@tonic-gate 	ssize_t modulus_len;
909*0Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
910*0Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
911*0Sstevel@tonic-gate 	uchar_t cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES];
912*0Sstevel@tonic-gate 
913*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
914*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
915*0Sstevel@tonic-gate 		return (rv);
916*0Sstevel@tonic-gate 	}
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 	plen = plaintext->cd_length;
919*0Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
920*0Sstevel@tonic-gate 		if (plen > (modulus_len - MIN_PKCS1_PADLEN))
921*0Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
922*0Sstevel@tonic-gate 	} else {
923*0Sstevel@tonic-gate 		if (plen > modulus_len)
924*0Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
925*0Sstevel@tonic-gate 	}
926*0Sstevel@tonic-gate 
927*0Sstevel@tonic-gate 	/*
928*0Sstevel@tonic-gate 	 * Output buf len must not be less than RSA modulus size.
929*0Sstevel@tonic-gate 	 */
930*0Sstevel@tonic-gate 	if (ciphertext->cd_length < modulus_len) {
931*0Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
932*0Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
933*0Sstevel@tonic-gate 	}
934*0Sstevel@tonic-gate 
935*0Sstevel@tonic-gate 	ASSERT(plaintext->cd_length <= sizeof (tmp_data));
936*0Sstevel@tonic-gate 	if ((rv = get_input_data(plaintext, &ptptr, tmp_data))
937*0Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
938*0Sstevel@tonic-gate 		return (rv);
939*0Sstevel@tonic-gate 
940*0Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
941*0Sstevel@tonic-gate 		rv = soft_encrypt_rsa_pkcs_encode(ptptr, plen,
942*0Sstevel@tonic-gate 		    plain_data, modulus_len);
943*0Sstevel@tonic-gate 
944*0Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
945*0Sstevel@tonic-gate 			return (rv);
946*0Sstevel@tonic-gate 	} else {
947*0Sstevel@tonic-gate 		bzero(plain_data, modulus_len - plen);
948*0Sstevel@tonic-gate 		bcopy(ptptr, &plain_data[modulus_len - plen], plen);
949*0Sstevel@tonic-gate 	}
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate 	rv = core_rsa_encrypt(key, plain_data, modulus_len,
952*0Sstevel@tonic-gate 	    cipher_data, kmflag, 1);
953*0Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
954*0Sstevel@tonic-gate 		/* copy out to ciphertext */
955*0Sstevel@tonic-gate 		if ((rv = put_output_data(cipher_data,
956*0Sstevel@tonic-gate 		    ciphertext, modulus_len)) != CRYPTO_SUCCESS)
957*0Sstevel@tonic-gate 			return (rv);
958*0Sstevel@tonic-gate 
959*0Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
960*0Sstevel@tonic-gate 	}
961*0Sstevel@tonic-gate 
962*0Sstevel@tonic-gate /* EXPORT DELETE END */
963*0Sstevel@tonic-gate 
964*0Sstevel@tonic-gate 	return (rv);
965*0Sstevel@tonic-gate }
966*0Sstevel@tonic-gate 
967*0Sstevel@tonic-gate /* EXPORT DELETE START */
968*0Sstevel@tonic-gate 
969*0Sstevel@tonic-gate static int
970*0Sstevel@tonic-gate core_rsa_encrypt(crypto_key_t *key, uchar_t *in,
971*0Sstevel@tonic-gate     int in_len, uchar_t *out, int kmflag, int is_public)
972*0Sstevel@tonic-gate {
973*0Sstevel@tonic-gate 	int rv;
974*0Sstevel@tonic-gate 	uchar_t *expo, *modulus;
975*0Sstevel@tonic-gate 	ssize_t	expo_len;
976*0Sstevel@tonic-gate 	ssize_t modulus_len;
977*0Sstevel@tonic-gate 	BIGNUM msg;
978*0Sstevel@tonic-gate 	RSAkey *rsakey;
979*0Sstevel@tonic-gate 
980*0Sstevel@tonic-gate 	if (is_public) {
981*0Sstevel@tonic-gate 		if ((rv = get_key_attr(key, SUN_CKA_PUBLIC_EXPONENT, &expo,
982*0Sstevel@tonic-gate 		    &expo_len)) != CRYPTO_SUCCESS)
983*0Sstevel@tonic-gate 			return (rv);
984*0Sstevel@tonic-gate 	} else {
985*0Sstevel@tonic-gate 		/*
986*0Sstevel@tonic-gate 		 * SUN_CKA_PRIVATE_EXPONENT is a required attribute for a
987*0Sstevel@tonic-gate 		 * RSA secret key. See the comments in core_rsa_decrypt
988*0Sstevel@tonic-gate 		 * routine which calls this routine with a private key.
989*0Sstevel@tonic-gate 		 */
990*0Sstevel@tonic-gate 		if ((rv = get_key_attr(key, SUN_CKA_PRIVATE_EXPONENT, &expo,
991*0Sstevel@tonic-gate 		    &expo_len)) != CRYPTO_SUCCESS)
992*0Sstevel@tonic-gate 			return (rv);
993*0Sstevel@tonic-gate 	}
994*0Sstevel@tonic-gate 
995*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
996*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
997*0Sstevel@tonic-gate 		return (rv);
998*0Sstevel@tonic-gate 	}
999*0Sstevel@tonic-gate 
1000*0Sstevel@tonic-gate 	rsakey = kmem_alloc(sizeof (RSAkey), kmflag);
1001*0Sstevel@tonic-gate 	if (rsakey == NULL)
1002*0Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
1003*0Sstevel@tonic-gate 
1004*0Sstevel@tonic-gate 	/* psize and qsize for RSA_key_init is in bits. */
1005*0Sstevel@tonic-gate 	if (RSA_key_init(rsakey, modulus_len * 4, modulus_len * 4) != BIG_OK) {
1006*0Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
1007*0Sstevel@tonic-gate 		goto clean1;
1008*0Sstevel@tonic-gate 	}
1009*0Sstevel@tonic-gate 
1010*0Sstevel@tonic-gate 	/* Size for big_init is in (32-bit) words. */
1011*0Sstevel@tonic-gate 	if (big_init(&msg, (in_len + (int)sizeof (uint32_t) - 1) /
1012*0Sstevel@tonic-gate 	    (int)sizeof (uint32_t)) != BIG_OK) {
1013*0Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
1014*0Sstevel@tonic-gate 		goto clean2;
1015*0Sstevel@tonic-gate 	}
1016*0Sstevel@tonic-gate 
1017*0Sstevel@tonic-gate 	/* Convert octet string exponent to big integer format. */
1018*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->e), expo, expo_len);
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate 	/* Convert octet string modulus to big integer format. */
1021*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->n), modulus, modulus_len);
1022*0Sstevel@tonic-gate 
1023*0Sstevel@tonic-gate 	/* Convert octet string input data to big integer format. */
1024*0Sstevel@tonic-gate 	bytestring2bignum(&msg, in, in_len);
1025*0Sstevel@tonic-gate 
1026*0Sstevel@tonic-gate 	if (big_cmp_abs(&msg, &(rsakey->n)) > 0) {
1027*0Sstevel@tonic-gate 		rv = CRYPTO_DATA_LEN_RANGE;
1028*0Sstevel@tonic-gate 		goto clean3;
1029*0Sstevel@tonic-gate 	}
1030*0Sstevel@tonic-gate 
1031*0Sstevel@tonic-gate 	/* Perform RSA computation on big integer input data. */
1032*0Sstevel@tonic-gate 	if (big_modexp(&msg, &msg, &(rsakey->e), &(rsakey->n), NULL)
1033*0Sstevel@tonic-gate 	    != BIG_OK) {
1034*0Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
1035*0Sstevel@tonic-gate 		goto clean3;
1036*0Sstevel@tonic-gate 	}
1037*0Sstevel@tonic-gate 
1038*0Sstevel@tonic-gate 	/* Convert the big integer output data to octet string. */
1039*0Sstevel@tonic-gate 	bignum2bytestring(out, &msg, modulus_len);
1040*0Sstevel@tonic-gate 
1041*0Sstevel@tonic-gate 	/*
1042*0Sstevel@tonic-gate 	 * Should not free modulus and expo as both are just pointers
1043*0Sstevel@tonic-gate 	 * to an attribute value buffer from the caller.
1044*0Sstevel@tonic-gate 	 */
1045*0Sstevel@tonic-gate clean3:
1046*0Sstevel@tonic-gate 	big_finish(&msg);
1047*0Sstevel@tonic-gate clean2:
1048*0Sstevel@tonic-gate 	RSA_key_finish(rsakey);
1049*0Sstevel@tonic-gate clean1:
1050*0Sstevel@tonic-gate 	kmem_free(rsakey, sizeof (RSAkey));
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate 	return (rv);
1053*0Sstevel@tonic-gate }
1054*0Sstevel@tonic-gate 
1055*0Sstevel@tonic-gate /* EXPORT DELETE END */
1056*0Sstevel@tonic-gate 
1057*0Sstevel@tonic-gate /* ARGSUSED */
1058*0Sstevel@tonic-gate static int
1059*0Sstevel@tonic-gate rsa_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
1060*0Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_req_handle_t req)
1061*0Sstevel@tonic-gate {
1062*0Sstevel@tonic-gate 	int rv;
1063*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
1064*0Sstevel@tonic-gate 
1065*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1066*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1067*0Sstevel@tonic-gate 
1068*0Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
1069*0Sstevel@tonic-gate 
1070*0Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
1071*0Sstevel@tonic-gate 	rv = rsa_decrypt_common(ctxp->mech_type, ctxp->key,
1072*0Sstevel@tonic-gate 	    ciphertext, plaintext, KM_SLEEP);
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1075*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
1076*0Sstevel@tonic-gate 
1077*0Sstevel@tonic-gate 	return (rv);
1078*0Sstevel@tonic-gate }
1079*0Sstevel@tonic-gate 
1080*0Sstevel@tonic-gate /* ARGSUSED */
1081*0Sstevel@tonic-gate static int
1082*0Sstevel@tonic-gate rsa_decrypt_atomic(crypto_provider_handle_t provider,
1083*0Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1084*0Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
1085*0Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
1086*0Sstevel@tonic-gate {
1087*0Sstevel@tonic-gate 	int rv;
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
1090*0Sstevel@tonic-gate 		return (rv);
1091*0Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
1092*0Sstevel@tonic-gate 
1093*0Sstevel@tonic-gate 	return (rsa_decrypt_common(mechanism->cm_type, key, ciphertext,
1094*0Sstevel@tonic-gate 	    plaintext, crypto_kmflag(req)));
1095*0Sstevel@tonic-gate }
1096*0Sstevel@tonic-gate 
1097*0Sstevel@tonic-gate static int
1098*0Sstevel@tonic-gate rsa_decrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1099*0Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_data_t *plaintext, int kmflag)
1100*0Sstevel@tonic-gate {
1101*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
1102*0Sstevel@tonic-gate 
1103*0Sstevel@tonic-gate /* EXPORT DELETE START */
1104*0Sstevel@tonic-gate 
1105*0Sstevel@tonic-gate 	int plain_len;
1106*0Sstevel@tonic-gate 	uchar_t *ctptr;
1107*0Sstevel@tonic-gate 	uchar_t *modulus;
1108*0Sstevel@tonic-gate 	ssize_t modulus_len;
1109*0Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1110*0Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1111*0Sstevel@tonic-gate 
1112*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
1113*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
1114*0Sstevel@tonic-gate 		return (rv);
1115*0Sstevel@tonic-gate 	}
1116*0Sstevel@tonic-gate 
1117*0Sstevel@tonic-gate 	/*
1118*0Sstevel@tonic-gate 	 * Ciphertext length must be equal to RSA modulus size.
1119*0Sstevel@tonic-gate 	 */
1120*0Sstevel@tonic-gate 	if (ciphertext->cd_length != modulus_len)
1121*0Sstevel@tonic-gate 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
1122*0Sstevel@tonic-gate 
1123*0Sstevel@tonic-gate 	ASSERT(ciphertext->cd_length <= sizeof (tmp_data));
1124*0Sstevel@tonic-gate 	if ((rv = get_input_data(ciphertext, &ctptr, tmp_data))
1125*0Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
1126*0Sstevel@tonic-gate 		return (rv);
1127*0Sstevel@tonic-gate 
1128*0Sstevel@tonic-gate 	rv = core_rsa_decrypt(key, ctptr, modulus_len, plain_data, kmflag);
1129*0Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
1130*0Sstevel@tonic-gate 		plain_len = modulus_len;
1131*0Sstevel@tonic-gate 
1132*0Sstevel@tonic-gate 		if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
1133*0Sstevel@tonic-gate 			/* Strip off the PKCS block formatting data. */
1134*0Sstevel@tonic-gate 			rv = soft_decrypt_rsa_pkcs_decode(plain_data,
1135*0Sstevel@tonic-gate 			    &plain_len);
1136*0Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
1137*0Sstevel@tonic-gate 				return (rv);
1138*0Sstevel@tonic-gate 		}
1139*0Sstevel@tonic-gate 
1140*0Sstevel@tonic-gate 		if (plain_len > plaintext->cd_length) {
1141*0Sstevel@tonic-gate 			plaintext->cd_length = plain_len;
1142*0Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
1143*0Sstevel@tonic-gate 		}
1144*0Sstevel@tonic-gate 
1145*0Sstevel@tonic-gate 		if ((rv = put_output_data(plain_data + modulus_len - plain_len,
1146*0Sstevel@tonic-gate 		    plaintext, plain_len)) != CRYPTO_SUCCESS)
1147*0Sstevel@tonic-gate 			return (rv);
1148*0Sstevel@tonic-gate 
1149*0Sstevel@tonic-gate 		plaintext->cd_length = plain_len;
1150*0Sstevel@tonic-gate 	}
1151*0Sstevel@tonic-gate 
1152*0Sstevel@tonic-gate /* EXPORT DELETE END */
1153*0Sstevel@tonic-gate 
1154*0Sstevel@tonic-gate 	return (rv);
1155*0Sstevel@tonic-gate }
1156*0Sstevel@tonic-gate 
1157*0Sstevel@tonic-gate /* EXPORT DELETE START */
1158*0Sstevel@tonic-gate 
1159*0Sstevel@tonic-gate static int
1160*0Sstevel@tonic-gate core_rsa_decrypt(crypto_key_t *key, uchar_t *in, int in_len,
1161*0Sstevel@tonic-gate     uchar_t *out, int kmflag)
1162*0Sstevel@tonic-gate {
1163*0Sstevel@tonic-gate 	int rv;
1164*0Sstevel@tonic-gate 	uchar_t *modulus, *prime1, *prime2, *expo1, *expo2, *coef;
1165*0Sstevel@tonic-gate 	ssize_t modulus_len;
1166*0Sstevel@tonic-gate 	ssize_t	prime1_len, prime2_len;
1167*0Sstevel@tonic-gate 	ssize_t	expo1_len, expo2_len, coef_len;
1168*0Sstevel@tonic-gate 	BIGNUM msg;
1169*0Sstevel@tonic-gate 	RSAkey *rsakey;
1170*0Sstevel@tonic-gate 
1171*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
1172*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
1173*0Sstevel@tonic-gate 		return (rv);
1174*0Sstevel@tonic-gate 	}
1175*0Sstevel@tonic-gate 
1176*0Sstevel@tonic-gate 	/*
1177*0Sstevel@tonic-gate 	 * The following attributes are not required to be
1178*0Sstevel@tonic-gate 	 * present in a RSA secret key. If any of them is not present
1179*0Sstevel@tonic-gate 	 * we call the encrypt routine with a flag indicating use of
1180*0Sstevel@tonic-gate 	 * private exponent (d). Note that SUN_CKA_PRIVATE_EXPONENT is
1181*0Sstevel@tonic-gate 	 * a required attribute for a RSA secret key.
1182*0Sstevel@tonic-gate 	 */
1183*0Sstevel@tonic-gate 	if ((get_key_attr(key, SUN_CKA_PRIME_1, &prime1, &prime1_len)
1184*0Sstevel@tonic-gate 		!= CRYPTO_SUCCESS) ||
1185*0Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_PRIME_2, &prime2, &prime2_len)
1186*0Sstevel@tonic-gate 		!= CRYPTO_SUCCESS) ||
1187*0Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_EXPONENT_1, &expo1, &expo1_len)
1188*0Sstevel@tonic-gate 		!= CRYPTO_SUCCESS) ||
1189*0Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_EXPONENT_2, &expo2, &expo2_len)
1190*0Sstevel@tonic-gate 		!= CRYPTO_SUCCESS) ||
1191*0Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_COEFFICIENT, &coef, &coef_len)
1192*0Sstevel@tonic-gate 		!= CRYPTO_SUCCESS)) {
1193*0Sstevel@tonic-gate 		return (core_rsa_encrypt(key, in, in_len, out, kmflag, 0));
1194*0Sstevel@tonic-gate 	}
1195*0Sstevel@tonic-gate 
1196*0Sstevel@tonic-gate 	rsakey = kmem_alloc(sizeof (RSAkey), kmflag);
1197*0Sstevel@tonic-gate 	if (rsakey == NULL)
1198*0Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
1199*0Sstevel@tonic-gate 
1200*0Sstevel@tonic-gate 	/* psize and qsize for RSA_key_init is in bits. */
1201*0Sstevel@tonic-gate 	if (RSA_key_init(rsakey, prime2_len * 8, prime1_len * 8) != BIG_OK) {
1202*0Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
1203*0Sstevel@tonic-gate 		goto clean1;
1204*0Sstevel@tonic-gate 	}
1205*0Sstevel@tonic-gate 
1206*0Sstevel@tonic-gate 	/* Size for big_init is in (32-bit) words. */
1207*0Sstevel@tonic-gate 	if (big_init(&msg, (in_len + (int)sizeof (uint32_t) - 1) /
1208*0Sstevel@tonic-gate 	    (int)sizeof (uint32_t)) != BIG_OK) {
1209*0Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
1210*0Sstevel@tonic-gate 		goto clean2;
1211*0Sstevel@tonic-gate 	}
1212*0Sstevel@tonic-gate 
1213*0Sstevel@tonic-gate 	/* Convert octet string input data to big integer format. */
1214*0Sstevel@tonic-gate 	bytestring2bignum(&msg, in, in_len);
1215*0Sstevel@tonic-gate 
1216*0Sstevel@tonic-gate 	/* Convert octet string modulus to big integer format. */
1217*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->n), modulus, modulus_len);
1218*0Sstevel@tonic-gate 
1219*0Sstevel@tonic-gate 	if (big_cmp_abs(&msg, &(rsakey->n)) > 0) {
1220*0Sstevel@tonic-gate 		rv = CRYPTO_DATA_LEN_RANGE;
1221*0Sstevel@tonic-gate 		goto clean3;
1222*0Sstevel@tonic-gate 	}
1223*0Sstevel@tonic-gate 
1224*0Sstevel@tonic-gate 	/* Convert the rest of private key attributes to big integer format. */
1225*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->dmodpminus1), expo2, expo2_len);
1226*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->dmodqminus1), expo1, expo1_len);
1227*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->p), prime2, prime2_len);
1228*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->q), prime1, prime1_len);
1229*0Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->pinvmodq), coef, coef_len);
1230*0Sstevel@tonic-gate 
1231*0Sstevel@tonic-gate 	if ((big_cmp_abs(&(rsakey->dmodpminus1), &(rsakey->p)) > 0) ||
1232*0Sstevel@tonic-gate 	    (big_cmp_abs(&(rsakey->dmodqminus1), &(rsakey->q)) > 0) ||
1233*0Sstevel@tonic-gate 	    (big_cmp_abs(&(rsakey->pinvmodq), &(rsakey->q)) > 0)) {
1234*0Sstevel@tonic-gate 		rv = CRYPTO_KEY_SIZE_RANGE;
1235*0Sstevel@tonic-gate 		goto clean3;
1236*0Sstevel@tonic-gate 	}
1237*0Sstevel@tonic-gate 
1238*0Sstevel@tonic-gate 	/* Perform RSA computation on big integer input data. */
1239*0Sstevel@tonic-gate 	if (big_modexp_crt(&msg, &msg, &(rsakey->dmodpminus1),
1240*0Sstevel@tonic-gate 	    &(rsakey->dmodqminus1), &(rsakey->p), &(rsakey->q),
1241*0Sstevel@tonic-gate 	    &(rsakey->pinvmodq), NULL, NULL) != BIG_OK) {
1242*0Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
1243*0Sstevel@tonic-gate 		goto clean3;
1244*0Sstevel@tonic-gate 	}
1245*0Sstevel@tonic-gate 
1246*0Sstevel@tonic-gate 	/* Convert the big integer output data to octet string. */
1247*0Sstevel@tonic-gate 	bignum2bytestring(out, &msg, modulus_len);
1248*0Sstevel@tonic-gate 
1249*0Sstevel@tonic-gate 	/*
1250*0Sstevel@tonic-gate 	 * Should not free modulus and friends as they are just pointers
1251*0Sstevel@tonic-gate 	 * to an attribute value buffer from the caller.
1252*0Sstevel@tonic-gate 	 */
1253*0Sstevel@tonic-gate clean3:
1254*0Sstevel@tonic-gate 	big_finish(&msg);
1255*0Sstevel@tonic-gate clean2:
1256*0Sstevel@tonic-gate 	RSA_key_finish(rsakey);
1257*0Sstevel@tonic-gate clean1:
1258*0Sstevel@tonic-gate 	kmem_free(rsakey, sizeof (RSAkey));
1259*0Sstevel@tonic-gate 
1260*0Sstevel@tonic-gate 	return (rv);
1261*0Sstevel@tonic-gate }
1262*0Sstevel@tonic-gate 
1263*0Sstevel@tonic-gate /* EXPORT DELETE END */
1264*0Sstevel@tonic-gate 
1265*0Sstevel@tonic-gate /* ARGSUSED */
1266*0Sstevel@tonic-gate static int
1267*0Sstevel@tonic-gate rsa_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
1268*0Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
1269*0Sstevel@tonic-gate     crypto_req_handle_t req)
1270*0Sstevel@tonic-gate {
1271*0Sstevel@tonic-gate 	int rv;
1272*0Sstevel@tonic-gate 	int kmflag;
1273*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
1274*0Sstevel@tonic-gate 	digest_rsa_ctx_t *dctxp;
1275*0Sstevel@tonic-gate 
1276*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
1277*0Sstevel@tonic-gate 		return (rv);
1278*0Sstevel@tonic-gate 
1279*0Sstevel@tonic-gate 	/*
1280*0Sstevel@tonic-gate 	 * Allocate a RSA context.
1281*0Sstevel@tonic-gate 	 */
1282*0Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
1283*0Sstevel@tonic-gate 	switch (mechanism->cm_type) {
1284*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1285*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1286*0Sstevel@tonic-gate 		dctxp = kmem_zalloc(sizeof (digest_rsa_ctx_t), kmflag);
1287*0Sstevel@tonic-gate 		ctxp = (rsa_ctx_t *)dctxp;
1288*0Sstevel@tonic-gate 		break;
1289*0Sstevel@tonic-gate 	default:
1290*0Sstevel@tonic-gate 		ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag);
1291*0Sstevel@tonic-gate 		break;
1292*0Sstevel@tonic-gate 	}
1293*0Sstevel@tonic-gate 
1294*0Sstevel@tonic-gate 	if (ctxp == NULL)
1295*0Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
1296*0Sstevel@tonic-gate 
1297*0Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
1298*0Sstevel@tonic-gate 	if ((rv = copy_key_to_ctx(key, ctxp, kmflag)) != CRYPTO_SUCCESS) {
1299*0Sstevel@tonic-gate 		switch (mechanism->cm_type) {
1300*0Sstevel@tonic-gate 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
1301*0Sstevel@tonic-gate 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1302*0Sstevel@tonic-gate 			kmem_free(dctxp, sizeof (digest_rsa_ctx_t));
1303*0Sstevel@tonic-gate 			break;
1304*0Sstevel@tonic-gate 		default:
1305*0Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
1306*0Sstevel@tonic-gate 			break;
1307*0Sstevel@tonic-gate 		}
1308*0Sstevel@tonic-gate 		return (rv);
1309*0Sstevel@tonic-gate 	}
1310*0Sstevel@tonic-gate 
1311*0Sstevel@tonic-gate 	switch (mechanism->cm_type) {
1312*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1313*0Sstevel@tonic-gate 		MD5Init(&(dctxp->md5_ctx));
1314*0Sstevel@tonic-gate 		break;
1315*0Sstevel@tonic-gate 
1316*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1317*0Sstevel@tonic-gate 		SHA1Init(&(dctxp->sha1_ctx));
1318*0Sstevel@tonic-gate 		break;
1319*0Sstevel@tonic-gate 	}
1320*0Sstevel@tonic-gate 
1321*0Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
1322*0Sstevel@tonic-gate 
1323*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
1324*0Sstevel@tonic-gate }
1325*0Sstevel@tonic-gate 
1326*0Sstevel@tonic-gate #define	SHA1_DIGEST_SIZE 20
1327*0Sstevel@tonic-gate #define	MD5_DIGEST_SIZE 16
1328*0Sstevel@tonic-gate 
1329*0Sstevel@tonic-gate #define	INIT_RAW_CRYPTO_DATA(data, base, len, cd_len)	\
1330*0Sstevel@tonic-gate 	(data).cd_format = CRYPTO_DATA_RAW;		\
1331*0Sstevel@tonic-gate 	(data).cd_offset = 0;				\
1332*0Sstevel@tonic-gate 	(data).cd_raw.iov_base = (char *)base;		\
1333*0Sstevel@tonic-gate 	(data).cd_raw.iov_len = len;			\
1334*0Sstevel@tonic-gate 	(data).cd_length = cd_len;
1335*0Sstevel@tonic-gate 
1336*0Sstevel@tonic-gate #define	DO_UPDATE	0x01
1337*0Sstevel@tonic-gate #define	DO_FINAL	0x02
1338*0Sstevel@tonic-gate #define	DO_MD5		0x04
1339*0Sstevel@tonic-gate #define	DO_SHA1		0x08
1340*0Sstevel@tonic-gate #define	DO_SIGN		0x10
1341*0Sstevel@tonic-gate #define	DO_VERIFY	0x20
1342*0Sstevel@tonic-gate 
1343*0Sstevel@tonic-gate static int
1344*0Sstevel@tonic-gate digest_data(crypto_data_t *data, void *dctx, uchar_t *digest,
1345*0Sstevel@tonic-gate     uchar_t flag)
1346*0Sstevel@tonic-gate {
1347*0Sstevel@tonic-gate 	int rv, dlen;
1348*0Sstevel@tonic-gate 	uchar_t *dptr;
1349*0Sstevel@tonic-gate 	cmd_type_t cmd;
1350*0Sstevel@tonic-gate 
1351*0Sstevel@tonic-gate 	ASSERT(flag & DO_MD5 || flag & DO_SHA1);
1352*0Sstevel@tonic-gate 	if (data == NULL) {
1353*0Sstevel@tonic-gate 		ASSERT((flag & DO_UPDATE) == 0);
1354*0Sstevel@tonic-gate 		goto dofinal;
1355*0Sstevel@tonic-gate 	}
1356*0Sstevel@tonic-gate 
1357*0Sstevel@tonic-gate 	dlen = data->cd_length;
1358*0Sstevel@tonic-gate 
1359*0Sstevel@tonic-gate 	switch (data->cd_format) {
1360*0Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
1361*0Sstevel@tonic-gate 		dptr = (uchar_t *)(data->cd_raw.iov_base +
1362*0Sstevel@tonic-gate 		    data->cd_offset);
1363*0Sstevel@tonic-gate 
1364*0Sstevel@tonic-gate 		if (flag & DO_MD5) {
1365*0Sstevel@tonic-gate 			if (flag & DO_UPDATE)
1366*0Sstevel@tonic-gate 				MD5Update(dctx, dptr, dlen);
1367*0Sstevel@tonic-gate 		} else {
1368*0Sstevel@tonic-gate 			if (flag & DO_UPDATE)
1369*0Sstevel@tonic-gate 				SHA1Update(dctx, dptr, dlen);
1370*0Sstevel@tonic-gate 		}
1371*0Sstevel@tonic-gate 		break;
1372*0Sstevel@tonic-gate 
1373*0Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
1374*0Sstevel@tonic-gate 		cmd = ((flag & DO_MD5) ? MD5_DIGEST_DATA : SHA1_DIGEST_DATA);
1375*0Sstevel@tonic-gate 		if (flag & DO_UPDATE) {
1376*0Sstevel@tonic-gate 			rv = process_uio_data(data, NULL, dlen, cmd, dctx);
1377*0Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
1378*0Sstevel@tonic-gate 				return (rv);
1379*0Sstevel@tonic-gate 		}
1380*0Sstevel@tonic-gate 		break;
1381*0Sstevel@tonic-gate 
1382*0Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
1383*0Sstevel@tonic-gate 		cmd = ((flag & DO_MD5) ? MD5_DIGEST_DATA : SHA1_DIGEST_DATA);
1384*0Sstevel@tonic-gate 		if (flag & DO_UPDATE) {
1385*0Sstevel@tonic-gate 			rv = process_mblk_data(data, NULL, dlen, cmd, dctx);
1386*0Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
1387*0Sstevel@tonic-gate 				return (rv);
1388*0Sstevel@tonic-gate 		}
1389*0Sstevel@tonic-gate 		break;
1390*0Sstevel@tonic-gate 	}
1391*0Sstevel@tonic-gate 
1392*0Sstevel@tonic-gate dofinal:
1393*0Sstevel@tonic-gate 	if (flag & DO_FINAL) {
1394*0Sstevel@tonic-gate 		if (flag & DO_MD5)
1395*0Sstevel@tonic-gate 			MD5Final(digest, dctx);
1396*0Sstevel@tonic-gate 		else
1397*0Sstevel@tonic-gate 			SHA1Final(digest, dctx);
1398*0Sstevel@tonic-gate 	}
1399*0Sstevel@tonic-gate 
1400*0Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
1401*0Sstevel@tonic-gate }
1402*0Sstevel@tonic-gate 
1403*0Sstevel@tonic-gate static int
1404*0Sstevel@tonic-gate rsa_digest_svrfy_common(digest_rsa_ctx_t *ctxp, crypto_data_t *data,
1405*0Sstevel@tonic-gate     crypto_data_t *signature, int kmflag, uchar_t flag)
1406*0Sstevel@tonic-gate {
1407*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
1408*0Sstevel@tonic-gate 
1409*0Sstevel@tonic-gate /* EXPORT DELETE START */
1410*0Sstevel@tonic-gate 
1411*0Sstevel@tonic-gate 	int dlen;
1412*0Sstevel@tonic-gate 	uchar_t digest[SHA1_DIGEST_SIZE];
1413*0Sstevel@tonic-gate 	/* The der_data size is enough for MD5 also */
1414*0Sstevel@tonic-gate 	uchar_t der_data[SHA1_DIGEST_SIZE + SHA1_DER_PREFIX_Len];
1415*0Sstevel@tonic-gate 	ulong_t der_data_len;
1416*0Sstevel@tonic-gate 	crypto_data_t der_cd;
1417*0Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
1418*0Sstevel@tonic-gate 
1419*0Sstevel@tonic-gate 	ASSERT(flag & DO_SIGN || flag & DO_VERIFY);
1420*0Sstevel@tonic-gate 	ASSERT(data != NULL || (flag & DO_FINAL));
1421*0Sstevel@tonic-gate 
1422*0Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
1423*0Sstevel@tonic-gate 	if (!(mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
1424*0Sstevel@tonic-gate 	    mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE))
1425*0Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
1426*0Sstevel@tonic-gate 
1427*0Sstevel@tonic-gate 	/*
1428*0Sstevel@tonic-gate 	 * We need to do the BUFFER_TOO_SMALL check before digesting
1429*0Sstevel@tonic-gate 	 * the data. No check is needed for verify as signature is not
1430*0Sstevel@tonic-gate 	 * an output argument for verify.
1431*0Sstevel@tonic-gate 	 */
1432*0Sstevel@tonic-gate 	if (flag & DO_SIGN) {
1433*0Sstevel@tonic-gate 		uchar_t *modulus;
1434*0Sstevel@tonic-gate 		ssize_t modulus_len;
1435*0Sstevel@tonic-gate 
1436*0Sstevel@tonic-gate 		if ((rv = get_key_attr(ctxp->key, SUN_CKA_MODULUS, &modulus,
1437*0Sstevel@tonic-gate 		    &modulus_len)) != CRYPTO_SUCCESS) {
1438*0Sstevel@tonic-gate 			return (rv);
1439*0Sstevel@tonic-gate 		}
1440*0Sstevel@tonic-gate 
1441*0Sstevel@tonic-gate 		if (signature->cd_length < modulus_len) {
1442*0Sstevel@tonic-gate 			signature->cd_length = modulus_len;
1443*0Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
1444*0Sstevel@tonic-gate 		}
1445*0Sstevel@tonic-gate 	}
1446*0Sstevel@tonic-gate 
1447*0Sstevel@tonic-gate 	dlen = ((mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE) ?
1448*0Sstevel@tonic-gate 	    MD5_DIGEST_SIZE : SHA1_DIGEST_SIZE);
1449*0Sstevel@tonic-gate 
1450*0Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
1451*0Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->md5_ctx),
1452*0Sstevel@tonic-gate 		    digest, flag | DO_MD5);
1453*0Sstevel@tonic-gate 	else
1454*0Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->sha1_ctx),
1455*0Sstevel@tonic-gate 		    digest, flag | DO_SHA1);
1456*0Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
1457*0Sstevel@tonic-gate 		return (rv);
1458*0Sstevel@tonic-gate 
1459*0Sstevel@tonic-gate 	/*
1460*0Sstevel@tonic-gate 	 * Prepare the DER encoding of the DigestInfo value as follows:
1461*0Sstevel@tonic-gate 	 * MD5:		MD5_DER_PREFIX || H
1462*0Sstevel@tonic-gate 	 * SHA-1:	SHA1_DER_PREFIX || H
1463*0Sstevel@tonic-gate 	 *
1464*0Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
1465*0Sstevel@tonic-gate 	 */
1466*0Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE) {
1467*0Sstevel@tonic-gate 		bcopy(MD5_DER_PREFIX, der_data, MD5_DER_PREFIX_Len);
1468*0Sstevel@tonic-gate 		bcopy(digest, der_data + MD5_DER_PREFIX_Len, dlen);
1469*0Sstevel@tonic-gate 		der_data_len = MD5_DER_PREFIX_Len + dlen;
1470*0Sstevel@tonic-gate 	} else {
1471*0Sstevel@tonic-gate 		bcopy(SHA1_DER_PREFIX, der_data, SHA1_DER_PREFIX_Len);
1472*0Sstevel@tonic-gate 		bcopy(digest, der_data + SHA1_DER_PREFIX_Len, dlen);
1473*0Sstevel@tonic-gate 		der_data_len = SHA1_DER_PREFIX_Len + dlen;
1474*0Sstevel@tonic-gate 	}
1475*0Sstevel@tonic-gate 
1476*0Sstevel@tonic-gate 	INIT_RAW_CRYPTO_DATA(der_cd, der_data, der_data_len, der_data_len);
1477*0Sstevel@tonic-gate 	/*
1478*0Sstevel@tonic-gate 	 * Now, we are ready to sign or verify the DER_ENCODED data.
1479*0Sstevel@tonic-gate 	 */
1480*0Sstevel@tonic-gate 	if (flag & DO_SIGN)
1481*0Sstevel@tonic-gate 		rv = rsa_sign_common(mech_type, ctxp->key, &der_cd,
1482*0Sstevel@tonic-gate 		    signature, kmflag);
1483*0Sstevel@tonic-gate 	else
1484*0Sstevel@tonic-gate 		rv = rsa_verify_common(mech_type, ctxp->key, &der_cd,
1485*0Sstevel@tonic-gate 		    signature, kmflag);
1486*0Sstevel@tonic-gate 
1487*0Sstevel@tonic-gate /* EXPORT DELETE END */
1488*0Sstevel@tonic-gate 
1489*0Sstevel@tonic-gate 	return (rv);
1490*0Sstevel@tonic-gate }
1491*0Sstevel@tonic-gate 
1492*0Sstevel@tonic-gate static int
1493*0Sstevel@tonic-gate rsa_sign_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1494*0Sstevel@tonic-gate     crypto_data_t *data, crypto_data_t *signature, int kmflag)
1495*0Sstevel@tonic-gate {
1496*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
1497*0Sstevel@tonic-gate 
1498*0Sstevel@tonic-gate /* EXPORT DELETE START */
1499*0Sstevel@tonic-gate 
1500*0Sstevel@tonic-gate 	int dlen;
1501*0Sstevel@tonic-gate 	uchar_t *dataptr, *modulus;
1502*0Sstevel@tonic-gate 	ssize_t modulus_len;
1503*0Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1504*0Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1505*0Sstevel@tonic-gate 	uchar_t signed_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1506*0Sstevel@tonic-gate 
1507*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
1508*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
1509*0Sstevel@tonic-gate 		return (rv);
1510*0Sstevel@tonic-gate 	}
1511*0Sstevel@tonic-gate 
1512*0Sstevel@tonic-gate 	dlen = data->cd_length;
1513*0Sstevel@tonic-gate 	switch (mech_type) {
1514*0Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
1515*0Sstevel@tonic-gate 		if (dlen > (modulus_len - MIN_PKCS1_PADLEN))
1516*0Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
1517*0Sstevel@tonic-gate 		break;
1518*0Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
1519*0Sstevel@tonic-gate 		if (dlen > modulus_len)
1520*0Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
1521*0Sstevel@tonic-gate 		break;
1522*0Sstevel@tonic-gate 	}
1523*0Sstevel@tonic-gate 
1524*0Sstevel@tonic-gate 	if (signature->cd_length < modulus_len) {
1525*0Sstevel@tonic-gate 		signature->cd_length = modulus_len;
1526*0Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
1527*0Sstevel@tonic-gate 	}
1528*0Sstevel@tonic-gate 
1529*0Sstevel@tonic-gate 	ASSERT(data->cd_length <= sizeof (tmp_data));
1530*0Sstevel@tonic-gate 	if ((rv = get_input_data(data, &dataptr, tmp_data))
1531*0Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
1532*0Sstevel@tonic-gate 		return (rv);
1533*0Sstevel@tonic-gate 
1534*0Sstevel@tonic-gate 	switch (mech_type) {
1535*0Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
1536*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1537*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1538*0Sstevel@tonic-gate 		/*
1539*0Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
1540*0Sstevel@tonic-gate 		 * type "01" encryption block.
1541*0Sstevel@tonic-gate 		 */
1542*0Sstevel@tonic-gate 		rv = soft_sign_rsa_pkcs_encode(dataptr, dlen, plain_data,
1543*0Sstevel@tonic-gate 		    modulus_len);
1544*0Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
1545*0Sstevel@tonic-gate 			return (rv);
1546*0Sstevel@tonic-gate 
1547*0Sstevel@tonic-gate 		break;
1548*0Sstevel@tonic-gate 
1549*0Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
1550*0Sstevel@tonic-gate 		bzero(plain_data, modulus_len - dlen);
1551*0Sstevel@tonic-gate 		bcopy(dataptr, &plain_data[modulus_len - dlen], dlen);
1552*0Sstevel@tonic-gate 		break;
1553*0Sstevel@tonic-gate 	}
1554*0Sstevel@tonic-gate 
1555*0Sstevel@tonic-gate 	rv = core_rsa_decrypt(key, plain_data, modulus_len, signed_data,
1556*0Sstevel@tonic-gate 	    kmflag);
1557*0Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
1558*0Sstevel@tonic-gate 		/* copy out to signature */
1559*0Sstevel@tonic-gate 		if ((rv = put_output_data(signed_data,
1560*0Sstevel@tonic-gate 		    signature, modulus_len)) != CRYPTO_SUCCESS)
1561*0Sstevel@tonic-gate 			return (rv);
1562*0Sstevel@tonic-gate 
1563*0Sstevel@tonic-gate 		signature->cd_length = modulus_len;
1564*0Sstevel@tonic-gate 	}
1565*0Sstevel@tonic-gate 
1566*0Sstevel@tonic-gate /* EXPORT DELETE END */
1567*0Sstevel@tonic-gate 
1568*0Sstevel@tonic-gate 	return (rv);
1569*0Sstevel@tonic-gate }
1570*0Sstevel@tonic-gate 
1571*0Sstevel@tonic-gate /* ARGSUSED */
1572*0Sstevel@tonic-gate static int
1573*0Sstevel@tonic-gate rsa_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
1574*0Sstevel@tonic-gate     crypto_req_handle_t req)
1575*0Sstevel@tonic-gate {
1576*0Sstevel@tonic-gate 	int rv;
1577*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
1578*0Sstevel@tonic-gate 
1579*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1580*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1581*0Sstevel@tonic-gate 
1582*0Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
1583*0Sstevel@tonic-gate 	switch (ctxp->mech_type) {
1584*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1585*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1586*0Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
1587*0Sstevel@tonic-gate 		    signature, KM_SLEEP, DO_SIGN | DO_UPDATE | DO_FINAL);
1588*0Sstevel@tonic-gate 		break;
1589*0Sstevel@tonic-gate 	default:
1590*0Sstevel@tonic-gate 		rv = rsa_sign_common(ctxp->mech_type, ctxp->key, data,
1591*0Sstevel@tonic-gate 		    signature, KM_SLEEP);
1592*0Sstevel@tonic-gate 		break;
1593*0Sstevel@tonic-gate 	}
1594*0Sstevel@tonic-gate 
1595*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1596*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
1597*0Sstevel@tonic-gate 
1598*0Sstevel@tonic-gate 	return (rv);
1599*0Sstevel@tonic-gate }
1600*0Sstevel@tonic-gate 
1601*0Sstevel@tonic-gate /* ARGSUSED */
1602*0Sstevel@tonic-gate static int
1603*0Sstevel@tonic-gate rsa_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
1604*0Sstevel@tonic-gate {
1605*0Sstevel@tonic-gate 	int rv;
1606*0Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
1607*0Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
1608*0Sstevel@tonic-gate 
1609*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1610*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1611*0Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
1612*0Sstevel@tonic-gate 
1613*0Sstevel@tonic-gate 	if (!(mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
1614*0Sstevel@tonic-gate 	    mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE))
1615*0Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
1616*0Sstevel@tonic-gate 
1617*0Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
1618*0Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->md5_ctx),
1619*0Sstevel@tonic-gate 		    NULL, DO_MD5 | DO_UPDATE);
1620*0Sstevel@tonic-gate 	else
1621*0Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->sha1_ctx),
1622*0Sstevel@tonic-gate 		    NULL, DO_SHA1 | DO_UPDATE);
1623*0Sstevel@tonic-gate 	return (rv);
1624*0Sstevel@tonic-gate }
1625*0Sstevel@tonic-gate 
1626*0Sstevel@tonic-gate static int
1627*0Sstevel@tonic-gate rsa_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
1628*0Sstevel@tonic-gate     crypto_req_handle_t req)
1629*0Sstevel@tonic-gate {
1630*0Sstevel@tonic-gate 	int rv;
1631*0Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
1632*0Sstevel@tonic-gate 
1633*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1634*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1635*0Sstevel@tonic-gate 
1636*0Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
1637*0Sstevel@tonic-gate 	    crypto_kmflag(req), DO_SIGN | DO_FINAL);
1638*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1639*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
1640*0Sstevel@tonic-gate 
1641*0Sstevel@tonic-gate 	return (rv);
1642*0Sstevel@tonic-gate }
1643*0Sstevel@tonic-gate 
1644*0Sstevel@tonic-gate /* ARGSUSED */
1645*0Sstevel@tonic-gate static int
1646*0Sstevel@tonic-gate rsa_sign_atomic(crypto_provider_handle_t provider,
1647*0Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1648*0Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
1649*0Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1650*0Sstevel@tonic-gate {
1651*0Sstevel@tonic-gate 	int rv;
1652*0Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
1653*0Sstevel@tonic-gate 
1654*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
1655*0Sstevel@tonic-gate 		return (rv);
1656*0Sstevel@tonic-gate 
1657*0Sstevel@tonic-gate 	switch (mechanism->cm_type) {
1658*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1659*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1660*0Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
1661*0Sstevel@tonic-gate 		dctx.key = key;
1662*0Sstevel@tonic-gate 		if (mechanism->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
1663*0Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1664*0Sstevel@tonic-gate 		else
1665*0Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1666*0Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common(&dctx, data,
1667*0Sstevel@tonic-gate 		    signature, crypto_kmflag(req),
1668*0Sstevel@tonic-gate 		    DO_SIGN | DO_UPDATE | DO_FINAL);
1669*0Sstevel@tonic-gate 		break;
1670*0Sstevel@tonic-gate 	default:
1671*0Sstevel@tonic-gate 		rv = rsa_sign_common(mechanism->cm_type, key, data,
1672*0Sstevel@tonic-gate 		    signature, crypto_kmflag(req));
1673*0Sstevel@tonic-gate 		break;
1674*0Sstevel@tonic-gate 	}
1675*0Sstevel@tonic-gate 
1676*0Sstevel@tonic-gate 	return (rv);
1677*0Sstevel@tonic-gate }
1678*0Sstevel@tonic-gate 
1679*0Sstevel@tonic-gate static int
1680*0Sstevel@tonic-gate rsa_verify_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1681*0Sstevel@tonic-gate     crypto_data_t *data, crypto_data_t *signature, int kmflag)
1682*0Sstevel@tonic-gate {
1683*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
1684*0Sstevel@tonic-gate 
1685*0Sstevel@tonic-gate /* EXPORT DELETE START */
1686*0Sstevel@tonic-gate 
1687*0Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
1688*0Sstevel@tonic-gate 	ssize_t modulus_len;
1689*0Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1690*0Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1691*0Sstevel@tonic-gate 
1692*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
1693*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
1694*0Sstevel@tonic-gate 		return (rv);
1695*0Sstevel@tonic-gate 	}
1696*0Sstevel@tonic-gate 
1697*0Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
1698*0Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
1699*0Sstevel@tonic-gate 
1700*0Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
1701*0Sstevel@tonic-gate 	if ((rv = get_input_data(signature, &sigptr, tmp_data))
1702*0Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
1703*0Sstevel@tonic-gate 		return (rv);
1704*0Sstevel@tonic-gate 
1705*0Sstevel@tonic-gate 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, kmflag, 1);
1706*0Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
1707*0Sstevel@tonic-gate 		return (rv);
1708*0Sstevel@tonic-gate 
1709*0Sstevel@tonic-gate 	switch (mech_type) {
1710*0Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
1711*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1712*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE: {
1713*0Sstevel@tonic-gate 		int data_len = modulus_len;
1714*0Sstevel@tonic-gate 
1715*0Sstevel@tonic-gate 		/*
1716*0Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
1717*0Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
1718*0Sstevel@tonic-gate 		 * the original data.
1719*0Sstevel@tonic-gate 		 */
1720*0Sstevel@tonic-gate 		rv = soft_verify_rsa_pkcs_decode(plain_data, &data_len);
1721*0Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
1722*0Sstevel@tonic-gate 			break;
1723*0Sstevel@tonic-gate 
1724*0Sstevel@tonic-gate 		if (data_len != data->cd_length) {
1725*0Sstevel@tonic-gate 			rv = CRYPTO_SIGNATURE_LEN_RANGE;
1726*0Sstevel@tonic-gate 			break;
1727*0Sstevel@tonic-gate 		}
1728*0Sstevel@tonic-gate 
1729*0Sstevel@tonic-gate 		if (compare_data(data, (plain_data + modulus_len
1730*0Sstevel@tonic-gate 		    - data_len)) != 0)
1731*0Sstevel@tonic-gate 			rv = CRYPTO_SIGNATURE_INVALID;
1732*0Sstevel@tonic-gate 		break;
1733*0Sstevel@tonic-gate 	}
1734*0Sstevel@tonic-gate 
1735*0Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
1736*0Sstevel@tonic-gate 		if (compare_data(data, (plain_data + modulus_len
1737*0Sstevel@tonic-gate 		    - data->cd_length)) != 0)
1738*0Sstevel@tonic-gate 			rv = CRYPTO_SIGNATURE_INVALID;
1739*0Sstevel@tonic-gate 		break;
1740*0Sstevel@tonic-gate 
1741*0Sstevel@tonic-gate 	default:
1742*0Sstevel@tonic-gate 		break;
1743*0Sstevel@tonic-gate 	}
1744*0Sstevel@tonic-gate 
1745*0Sstevel@tonic-gate /* EXPORT DELETE END */
1746*0Sstevel@tonic-gate 
1747*0Sstevel@tonic-gate 	return (rv);
1748*0Sstevel@tonic-gate }
1749*0Sstevel@tonic-gate 
1750*0Sstevel@tonic-gate /* ARGSUSED */
1751*0Sstevel@tonic-gate static int
1752*0Sstevel@tonic-gate rsa_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
1753*0Sstevel@tonic-gate     crypto_req_handle_t req)
1754*0Sstevel@tonic-gate {
1755*0Sstevel@tonic-gate 	int rv;
1756*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
1757*0Sstevel@tonic-gate 
1758*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1759*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1760*0Sstevel@tonic-gate 
1761*0Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
1762*0Sstevel@tonic-gate 	switch (ctxp->mech_type) {
1763*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1764*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1765*0Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
1766*0Sstevel@tonic-gate 		    signature, KM_SLEEP, DO_VERIFY | DO_UPDATE | DO_FINAL);
1767*0Sstevel@tonic-gate 		break;
1768*0Sstevel@tonic-gate 	default:
1769*0Sstevel@tonic-gate 		rv = rsa_verify_common(ctxp->mech_type, ctxp->key, data,
1770*0Sstevel@tonic-gate 		    signature, KM_SLEEP);
1771*0Sstevel@tonic-gate 		break;
1772*0Sstevel@tonic-gate 	}
1773*0Sstevel@tonic-gate 
1774*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1775*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
1776*0Sstevel@tonic-gate 
1777*0Sstevel@tonic-gate 	return (rv);
1778*0Sstevel@tonic-gate }
1779*0Sstevel@tonic-gate 
1780*0Sstevel@tonic-gate /* ARGSUSED */
1781*0Sstevel@tonic-gate static int
1782*0Sstevel@tonic-gate rsa_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
1783*0Sstevel@tonic-gate     crypto_req_handle_t req)
1784*0Sstevel@tonic-gate {
1785*0Sstevel@tonic-gate 	int rv;
1786*0Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
1787*0Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
1788*0Sstevel@tonic-gate 
1789*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1790*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1791*0Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
1792*0Sstevel@tonic-gate 
1793*0Sstevel@tonic-gate 	if (!(mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
1794*0Sstevel@tonic-gate 	    mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE))
1795*0Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
1796*0Sstevel@tonic-gate 
1797*0Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
1798*0Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->md5_ctx),
1799*0Sstevel@tonic-gate 		    NULL, DO_MD5 | DO_UPDATE);
1800*0Sstevel@tonic-gate 	else
1801*0Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->sha1_ctx),
1802*0Sstevel@tonic-gate 		    NULL, DO_SHA1 | DO_UPDATE);
1803*0Sstevel@tonic-gate 	return (rv);
1804*0Sstevel@tonic-gate }
1805*0Sstevel@tonic-gate 
1806*0Sstevel@tonic-gate static int
1807*0Sstevel@tonic-gate rsa_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
1808*0Sstevel@tonic-gate     crypto_req_handle_t req)
1809*0Sstevel@tonic-gate {
1810*0Sstevel@tonic-gate 	int rv;
1811*0Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
1812*0Sstevel@tonic-gate 
1813*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1814*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1815*0Sstevel@tonic-gate 
1816*0Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
1817*0Sstevel@tonic-gate 	    crypto_kmflag(req), DO_VERIFY | DO_FINAL);
1818*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1819*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
1820*0Sstevel@tonic-gate 
1821*0Sstevel@tonic-gate 	return (rv);
1822*0Sstevel@tonic-gate }
1823*0Sstevel@tonic-gate 
1824*0Sstevel@tonic-gate 
1825*0Sstevel@tonic-gate /* ARGSUSED */
1826*0Sstevel@tonic-gate static int
1827*0Sstevel@tonic-gate rsa_verify_atomic(crypto_provider_handle_t provider,
1828*0Sstevel@tonic-gate     crypto_session_id_t session_id,
1829*0Sstevel@tonic-gate     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
1830*0Sstevel@tonic-gate     crypto_data_t *signature, crypto_spi_ctx_template_t ctx_template,
1831*0Sstevel@tonic-gate     crypto_req_handle_t req)
1832*0Sstevel@tonic-gate {
1833*0Sstevel@tonic-gate 	int rv;
1834*0Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
1835*0Sstevel@tonic-gate 
1836*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
1837*0Sstevel@tonic-gate 		return (rv);
1838*0Sstevel@tonic-gate 
1839*0Sstevel@tonic-gate 	switch (mechanism->cm_type) {
1840*0Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
1841*0Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1842*0Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
1843*0Sstevel@tonic-gate 		dctx.key = key;
1844*0Sstevel@tonic-gate 		if (mechanism->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
1845*0Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1846*0Sstevel@tonic-gate 		else
1847*0Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1848*0Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common(&dctx, data,
1849*0Sstevel@tonic-gate 		    signature, crypto_kmflag(req),
1850*0Sstevel@tonic-gate 		    DO_VERIFY | DO_UPDATE | DO_FINAL);
1851*0Sstevel@tonic-gate 		break;
1852*0Sstevel@tonic-gate 	default:
1853*0Sstevel@tonic-gate 		rv = rsa_verify_common(mechanism->cm_type, key, data,
1854*0Sstevel@tonic-gate 		    signature, crypto_kmflag(req));
1855*0Sstevel@tonic-gate 		break;
1856*0Sstevel@tonic-gate 	}
1857*0Sstevel@tonic-gate 
1858*0Sstevel@tonic-gate 	return (rv);
1859*0Sstevel@tonic-gate }
1860*0Sstevel@tonic-gate 
1861*0Sstevel@tonic-gate static int
1862*0Sstevel@tonic-gate rsa_verify_recover_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1863*0Sstevel@tonic-gate     crypto_data_t *signature, crypto_data_t *data, int kmflag)
1864*0Sstevel@tonic-gate {
1865*0Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
1866*0Sstevel@tonic-gate 
1867*0Sstevel@tonic-gate /* EXPORT DELETE START */
1868*0Sstevel@tonic-gate 
1869*0Sstevel@tonic-gate 	int data_len;
1870*0Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
1871*0Sstevel@tonic-gate 	ssize_t modulus_len;
1872*0Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1873*0Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
1874*0Sstevel@tonic-gate 
1875*0Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
1876*0Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
1877*0Sstevel@tonic-gate 		return (rv);
1878*0Sstevel@tonic-gate 	}
1879*0Sstevel@tonic-gate 
1880*0Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
1881*0Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
1882*0Sstevel@tonic-gate 
1883*0Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
1884*0Sstevel@tonic-gate 	if ((rv = get_input_data(signature, &sigptr, tmp_data))
1885*0Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
1886*0Sstevel@tonic-gate 		return (rv);
1887*0Sstevel@tonic-gate 
1888*0Sstevel@tonic-gate 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, kmflag, 1);
1889*0Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
1890*0Sstevel@tonic-gate 		return (rv);
1891*0Sstevel@tonic-gate 
1892*0Sstevel@tonic-gate 	data_len = modulus_len;
1893*0Sstevel@tonic-gate 
1894*0Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
1895*0Sstevel@tonic-gate 		/*
1896*0Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
1897*0Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
1898*0Sstevel@tonic-gate 		 * the original data.
1899*0Sstevel@tonic-gate 		 */
1900*0Sstevel@tonic-gate 		rv = soft_verify_rsa_pkcs_decode(plain_data, &data_len);
1901*0Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
1902*0Sstevel@tonic-gate 			return (rv);
1903*0Sstevel@tonic-gate 	}
1904*0Sstevel@tonic-gate 
1905*0Sstevel@tonic-gate 	if (data->cd_length < data_len) {
1906*0Sstevel@tonic-gate 		data->cd_length = data_len;
1907*0Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
1908*0Sstevel@tonic-gate 	}
1909*0Sstevel@tonic-gate 
1910*0Sstevel@tonic-gate 	if ((rv = put_output_data(plain_data + modulus_len - data_len,
1911*0Sstevel@tonic-gate 	    data, data_len)) != CRYPTO_SUCCESS)
1912*0Sstevel@tonic-gate 		return (rv);
1913*0Sstevel@tonic-gate 	data->cd_length = data_len;
1914*0Sstevel@tonic-gate 
1915*0Sstevel@tonic-gate /* EXPORT DELETE END */
1916*0Sstevel@tonic-gate 
1917*0Sstevel@tonic-gate 	return (rv);
1918*0Sstevel@tonic-gate }
1919*0Sstevel@tonic-gate 
1920*0Sstevel@tonic-gate /* ARGSUSED */
1921*0Sstevel@tonic-gate static int
1922*0Sstevel@tonic-gate rsa_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
1923*0Sstevel@tonic-gate     crypto_data_t *data, crypto_req_handle_t req)
1924*0Sstevel@tonic-gate {
1925*0Sstevel@tonic-gate 	int rv;
1926*0Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
1927*0Sstevel@tonic-gate 
1928*0Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
1929*0Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
1930*0Sstevel@tonic-gate 
1931*0Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
1932*0Sstevel@tonic-gate 	rv = rsa_verify_recover_common(ctxp->mech_type, ctxp->key,
1933*0Sstevel@tonic-gate 	    signature, data, KM_SLEEP);
1934*0Sstevel@tonic-gate 
1935*0Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1936*0Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
1937*0Sstevel@tonic-gate 
1938*0Sstevel@tonic-gate 	return (rv);
1939*0Sstevel@tonic-gate }
1940*0Sstevel@tonic-gate 
1941*0Sstevel@tonic-gate /* ARGSUSED */
1942*0Sstevel@tonic-gate static int
1943*0Sstevel@tonic-gate rsa_verify_recover_atomic(crypto_provider_handle_t provider,
1944*0Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1945*0Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
1946*0Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1947*0Sstevel@tonic-gate {
1948*0Sstevel@tonic-gate 	int rv;
1949*0Sstevel@tonic-gate 
1950*0Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
1951*0Sstevel@tonic-gate 		return (rv);
1952*0Sstevel@tonic-gate 
1953*0Sstevel@tonic-gate 	return (rsa_verify_recover_common(mechanism->cm_type, key,
1954*0Sstevel@tonic-gate 	    signature, data, crypto_kmflag(req)));
1955*0Sstevel@tonic-gate }
1956