xref: /onnv-gate/usr/src/uts/common/crypto/io/rsa.c (revision 12573:fb4ef506980f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55072Smcpowers  * Common Development and Distribution License (the "License").
65072Smcpowers  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*12573SDina.Nimeh@Sun.COM 
220Sstevel@tonic-gate /*
23*12573SDina.Nimeh@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * RSA provider for the Kernel Cryptographic Framework (KCF)
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/systm.h>
320Sstevel@tonic-gate #include <sys/modctl.h>
330Sstevel@tonic-gate #include <sys/cmn_err.h>
340Sstevel@tonic-gate #include <sys/ddi.h>
350Sstevel@tonic-gate #include <sys/crypto/spi.h>
360Sstevel@tonic-gate #include <sys/sysmacros.h>
370Sstevel@tonic-gate #include <sys/strsun.h>
380Sstevel@tonic-gate #include <sys/md5.h>
390Sstevel@tonic-gate #include <sys/sha1.h>
4010500SHai-May.Chao@Sun.COM #define	_SHA2_IMPL
41676Sizick #include <sys/sha2.h>
420Sstevel@tonic-gate #include <sys/random.h>
437188Smcpowers #include <sys/crypto/impl.h>
4410500SHai-May.Chao@Sun.COM #include <sha1/sha1_impl.h>
4510500SHai-May.Chao@Sun.COM #include <sha2/sha2_impl.h>
46*12573SDina.Nimeh@Sun.COM #include <padding/padding.h>
4710500SHai-May.Chao@Sun.COM #define	_RSA_FIPS_POST
4810500SHai-May.Chao@Sun.COM #include <rsa/rsa_impl.h>
490Sstevel@tonic-gate 
500Sstevel@tonic-gate extern struct mod_ops mod_cryptoops;
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate  * Module linkage information for the kernel.
540Sstevel@tonic-gate  */
550Sstevel@tonic-gate static struct modlcrypto modlcrypto = {
560Sstevel@tonic-gate 	&mod_cryptoops,
575072Smcpowers 	"RSA Kernel SW Provider"
580Sstevel@tonic-gate };
590Sstevel@tonic-gate 
600Sstevel@tonic-gate static struct modlinkage modlinkage = {
610Sstevel@tonic-gate 	MODREV_1,
620Sstevel@tonic-gate 	(void *)&modlcrypto,
630Sstevel@tonic-gate 	NULL
640Sstevel@tonic-gate };
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate  * CSPI information (entry points, provider info, etc.)
680Sstevel@tonic-gate  */
690Sstevel@tonic-gate typedef enum rsa_mech_type {
700Sstevel@tonic-gate 	RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_RSA_PKCS */
710Sstevel@tonic-gate 	RSA_X_509_MECH_INFO_TYPE,	/* SUN_CKM_RSA_X_509 */
720Sstevel@tonic-gate 	MD5_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_MD5_RSA_PKCS */
73676Sizick 	SHA1_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA1_RSA_PKCS */
74676Sizick 	SHA256_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA256_RSA_PKCS */
75676Sizick 	SHA384_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA384_RSA_PKCS */
76676Sizick 	SHA512_RSA_PKCS_MECH_INFO_TYPE	/* SUN_SHA512_RSA_PKCS */
770Sstevel@tonic-gate } rsa_mech_type_t;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate  * Context for RSA_PKCS and RSA_X_509 mechanisms.
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate typedef struct rsa_ctx {
830Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
840Sstevel@tonic-gate 	crypto_key_t *key;
850Sstevel@tonic-gate 	size_t keychunk_size;
860Sstevel@tonic-gate } rsa_ctx_t;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate /*
89676Sizick  * Context for MD5_RSA_PKCS and SHA*_RSA_PKCS mechanisms.
900Sstevel@tonic-gate  */
910Sstevel@tonic-gate typedef struct digest_rsa_ctx {
920Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
930Sstevel@tonic-gate 	crypto_key_t *key;
940Sstevel@tonic-gate 	size_t keychunk_size;
950Sstevel@tonic-gate 	union {
960Sstevel@tonic-gate 		MD5_CTX md5ctx;
970Sstevel@tonic-gate 		SHA1_CTX sha1ctx;
98676Sizick 		SHA2_CTX sha2ctx;
990Sstevel@tonic-gate 	} dctx_u;
1000Sstevel@tonic-gate } digest_rsa_ctx_t;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate #define	md5_ctx		dctx_u.md5ctx
1030Sstevel@tonic-gate #define	sha1_ctx	dctx_u.sha1ctx
104676Sizick #define	sha2_ctx	dctx_u.sha2ctx
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate /*
1070Sstevel@tonic-gate  * Mechanism info structure passed to KCF during registration.
1080Sstevel@tonic-gate  */
1090Sstevel@tonic-gate static crypto_mech_info_t rsa_mech_info_tab[] = {
1100Sstevel@tonic-gate 	/* RSA_PKCS */
1110Sstevel@tonic-gate 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
1120Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1130Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1140Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1150Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
1160Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1170Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
1180Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	/* RSA_X_509 */
1210Sstevel@tonic-gate 	{SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
1220Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1230Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1240Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1250Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
1260Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1270Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
1280Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	/* MD5_RSA_PKCS */
1310Sstevel@tonic-gate 	{SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE,
1320Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1330Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1340Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	/* SHA1_RSA_PKCS */
1370Sstevel@tonic-gate 	{SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE,
1380Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1390Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
140676Sizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
141676Sizick 
142676Sizick 	/* SHA256_RSA_PKCS */
143676Sizick 	{SUN_CKM_SHA256_RSA_PKCS, SHA256_RSA_PKCS_MECH_INFO_TYPE,
144676Sizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
145676Sizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
146676Sizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
147676Sizick 
148676Sizick 	/* SHA384_RSA_PKCS */
149676Sizick 	{SUN_CKM_SHA384_RSA_PKCS, SHA384_RSA_PKCS_MECH_INFO_TYPE,
150676Sizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
151676Sizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
152676Sizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
153676Sizick 
154676Sizick 	/* SHA512_RSA_PKCS */
155676Sizick 	{SUN_CKM_SHA512_RSA_PKCS, SHA512_RSA_PKCS_MECH_INFO_TYPE,
156676Sizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
157676Sizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1580Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}
159676Sizick 
1600Sstevel@tonic-gate };
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate #define	RSA_VALID_MECH(mech)					\
1630Sstevel@tonic-gate 	(((mech)->cm_type == RSA_PKCS_MECH_INFO_TYPE ||		\
1640Sstevel@tonic-gate 	(mech)->cm_type == RSA_X_509_MECH_INFO_TYPE ||		\
1650Sstevel@tonic-gate 	(mech)->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||	\
166676Sizick 	(mech)->cm_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||	\
167676Sizick 	(mech)->cm_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||	\
168676Sizick 	(mech)->cm_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||	\
169676Sizick 	(mech)->cm_type == SHA512_RSA_PKCS_MECH_INFO_TYPE) ? 1 : 0)
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */
1720Sstevel@tonic-gate #define	RSA_ARG_INPLACE(input, output)				\
1730Sstevel@tonic-gate 	if ((output) == NULL)					\
1740Sstevel@tonic-gate 		(output) = (input);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate static void rsa_provider_status(crypto_provider_handle_t, uint_t *);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate static crypto_control_ops_t rsa_control_ops = {
1790Sstevel@tonic-gate 	rsa_provider_status
1800Sstevel@tonic-gate };
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate static int rsa_common_init(crypto_ctx_t *, crypto_mechanism_t *,
1830Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
184*12573SDina.Nimeh@Sun.COM static int rsaprov_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1850Sstevel@tonic-gate     crypto_req_handle_t);
1860Sstevel@tonic-gate static int rsa_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1870Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1880Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
189*12573SDina.Nimeh@Sun.COM static int rsaprov_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1900Sstevel@tonic-gate     crypto_req_handle_t);
1910Sstevel@tonic-gate static int rsa_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1920Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1930Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate /*
1960Sstevel@tonic-gate  * The RSA mechanisms do not have multiple-part cipher operations.
1970Sstevel@tonic-gate  * So, the update and final routines are set to NULL.
1980Sstevel@tonic-gate  */
1990Sstevel@tonic-gate static crypto_cipher_ops_t rsa_cipher_ops = {
2000Sstevel@tonic-gate 	rsa_common_init,
201*12573SDina.Nimeh@Sun.COM 	rsaprov_encrypt,
2020Sstevel@tonic-gate 	NULL,
2030Sstevel@tonic-gate 	NULL,
2040Sstevel@tonic-gate 	rsa_encrypt_atomic,
2050Sstevel@tonic-gate 	rsa_common_init,
206*12573SDina.Nimeh@Sun.COM 	rsaprov_decrypt,
2070Sstevel@tonic-gate 	NULL,
2080Sstevel@tonic-gate 	NULL,
2090Sstevel@tonic-gate 	rsa_decrypt_atomic
2100Sstevel@tonic-gate };
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate static int rsa_sign_verify_common_init(crypto_ctx_t *, crypto_mechanism_t *,
2130Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
214*12573SDina.Nimeh@Sun.COM static int rsaprov_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
2150Sstevel@tonic-gate     crypto_req_handle_t);
2160Sstevel@tonic-gate static int rsa_sign_update(crypto_ctx_t *, crypto_data_t *,
2170Sstevel@tonic-gate     crypto_req_handle_t);
2180Sstevel@tonic-gate static int rsa_sign_final(crypto_ctx_t *, crypto_data_t *,
2190Sstevel@tonic-gate     crypto_req_handle_t);
2200Sstevel@tonic-gate static int rsa_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
2210Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
2220Sstevel@tonic-gate     crypto_spi_ctx_template_t, crypto_req_handle_t);
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate  * We use the same routine for sign_init and sign_recover_init fields
2260Sstevel@tonic-gate  * as they do the same thing. Same holds for sign and sign_recover fields,
2270Sstevel@tonic-gate  * and sign_atomic and sign_recover_atomic fields.
2280Sstevel@tonic-gate  */
2290Sstevel@tonic-gate static crypto_sign_ops_t rsa_sign_ops = {
2300Sstevel@tonic-gate 	rsa_sign_verify_common_init,
231*12573SDina.Nimeh@Sun.COM 	rsaprov_sign,
2320Sstevel@tonic-gate 	rsa_sign_update,
2330Sstevel@tonic-gate 	rsa_sign_final,
2340Sstevel@tonic-gate 	rsa_sign_atomic,
2350Sstevel@tonic-gate 	rsa_sign_verify_common_init,
236*12573SDina.Nimeh@Sun.COM 	rsaprov_sign,
2370Sstevel@tonic-gate 	rsa_sign_atomic
2380Sstevel@tonic-gate };
2390Sstevel@tonic-gate 
240*12573SDina.Nimeh@Sun.COM static int rsaprov_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
2410Sstevel@tonic-gate     crypto_req_handle_t);
2420Sstevel@tonic-gate static int rsa_verify_update(crypto_ctx_t *, crypto_data_t *,
2430Sstevel@tonic-gate     crypto_req_handle_t);
2440Sstevel@tonic-gate static int rsa_verify_final(crypto_ctx_t *, crypto_data_t *,
2450Sstevel@tonic-gate     crypto_req_handle_t);
2460Sstevel@tonic-gate static int rsa_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
2470Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
2480Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
2490Sstevel@tonic-gate static int rsa_verify_recover(crypto_ctx_t *, crypto_data_t *,
2500Sstevel@tonic-gate     crypto_data_t *, crypto_req_handle_t);
2510Sstevel@tonic-gate static int rsa_verify_recover_atomic(crypto_provider_handle_t,
2520Sstevel@tonic-gate     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2530Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
2540Sstevel@tonic-gate     crypto_req_handle_t);
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate /*
2570Sstevel@tonic-gate  * We use the same routine (rsa_sign_verify_common_init) for verify_init
2580Sstevel@tonic-gate  * and verify_recover_init fields as they do the same thing.
2590Sstevel@tonic-gate  */
2600Sstevel@tonic-gate static crypto_verify_ops_t rsa_verify_ops = {
2610Sstevel@tonic-gate 	rsa_sign_verify_common_init,
262*12573SDina.Nimeh@Sun.COM 	rsaprov_verify,
2630Sstevel@tonic-gate 	rsa_verify_update,
2640Sstevel@tonic-gate 	rsa_verify_final,
2650Sstevel@tonic-gate 	rsa_verify_atomic,
2660Sstevel@tonic-gate 	rsa_sign_verify_common_init,
2670Sstevel@tonic-gate 	rsa_verify_recover,
2680Sstevel@tonic-gate 	rsa_verify_recover_atomic
2690Sstevel@tonic-gate };
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate static int rsa_free_context(crypto_ctx_t *);
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate static crypto_ctx_ops_t rsa_ctx_ops = {
2740Sstevel@tonic-gate 	NULL,
2750Sstevel@tonic-gate 	rsa_free_context
2760Sstevel@tonic-gate };
2770Sstevel@tonic-gate 
27810732SAnthony.Scarpino@Sun.COM static void rsa_POST(int *);
27910732SAnthony.Scarpino@Sun.COM 
28010732SAnthony.Scarpino@Sun.COM static crypto_fips140_ops_t rsa_fips140_ops = {
28110732SAnthony.Scarpino@Sun.COM 	rsa_POST
28210732SAnthony.Scarpino@Sun.COM };
28310732SAnthony.Scarpino@Sun.COM 
2840Sstevel@tonic-gate static crypto_ops_t rsa_crypto_ops = {
2850Sstevel@tonic-gate 	&rsa_control_ops,
2860Sstevel@tonic-gate 	NULL,
2870Sstevel@tonic-gate 	&rsa_cipher_ops,
2880Sstevel@tonic-gate 	NULL,
2890Sstevel@tonic-gate 	&rsa_sign_ops,
2900Sstevel@tonic-gate 	&rsa_verify_ops,
2910Sstevel@tonic-gate 	NULL,
2920Sstevel@tonic-gate 	NULL,
2930Sstevel@tonic-gate 	NULL,
2940Sstevel@tonic-gate 	NULL,
2950Sstevel@tonic-gate 	NULL,
2960Sstevel@tonic-gate 	NULL,
2970Sstevel@tonic-gate 	NULL,
29810732SAnthony.Scarpino@Sun.COM 	&rsa_ctx_ops,
29910732SAnthony.Scarpino@Sun.COM 	NULL,
30010732SAnthony.Scarpino@Sun.COM 	NULL,
30110732SAnthony.Scarpino@Sun.COM 	&rsa_fips140_ops
3020Sstevel@tonic-gate };
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate static crypto_provider_info_t rsa_prov_info = {
30510732SAnthony.Scarpino@Sun.COM 	CRYPTO_SPI_VERSION_4,
3060Sstevel@tonic-gate 	"RSA Software Provider",
3070Sstevel@tonic-gate 	CRYPTO_SW_PROVIDER,
3080Sstevel@tonic-gate 	{&modlinkage},
3090Sstevel@tonic-gate 	NULL,
3100Sstevel@tonic-gate 	&rsa_crypto_ops,
3110Sstevel@tonic-gate 	sizeof (rsa_mech_info_tab)/sizeof (crypto_mech_info_t),
3120Sstevel@tonic-gate 	rsa_mech_info_tab
3130Sstevel@tonic-gate };
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate static int rsa_encrypt_common(rsa_mech_type_t, crypto_key_t *,
316*12573SDina.Nimeh@Sun.COM     crypto_data_t *, crypto_data_t *);
3170Sstevel@tonic-gate static int rsa_decrypt_common(rsa_mech_type_t, crypto_key_t *,
318*12573SDina.Nimeh@Sun.COM     crypto_data_t *, crypto_data_t *);
3190Sstevel@tonic-gate static int rsa_sign_common(rsa_mech_type_t, crypto_key_t *,
320*12573SDina.Nimeh@Sun.COM     crypto_data_t *, crypto_data_t *);
3210Sstevel@tonic-gate static int rsa_verify_common(rsa_mech_type_t, crypto_key_t *,
322*12573SDina.Nimeh@Sun.COM     crypto_data_t *, crypto_data_t *);
3230Sstevel@tonic-gate static int compare_data(crypto_data_t *, uchar_t *);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate /* EXPORT DELETE START */
3260Sstevel@tonic-gate 
327*12573SDina.Nimeh@Sun.COM static int core_rsa_encrypt(crypto_key_t *, uchar_t *, int, uchar_t *, int);
328*12573SDina.Nimeh@Sun.COM static int core_rsa_decrypt(crypto_key_t *, uchar_t *, int, uchar_t *);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate /* EXPORT DELETE END */
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate static crypto_kcf_provider_handle_t rsa_prov_handle = NULL;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate int
_init(void)3350Sstevel@tonic-gate _init(void)
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate 	int ret;
3380Sstevel@tonic-gate 
33911751SAnthony.Scarpino@Sun.COM 	if ((ret = mod_install(&modlinkage)) != 0)
34011751SAnthony.Scarpino@Sun.COM 		return (ret);
34111751SAnthony.Scarpino@Sun.COM 
34211751SAnthony.Scarpino@Sun.COM 	/* Register with KCF.  If the registration fails, remove the module. */
34311751SAnthony.Scarpino@Sun.COM 	if (crypto_register_provider(&rsa_prov_info, &rsa_prov_handle)) {
34411751SAnthony.Scarpino@Sun.COM 		(void) mod_remove(&modlinkage);
3450Sstevel@tonic-gate 		return (EACCES);
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 
34811751SAnthony.Scarpino@Sun.COM 	return (0);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate int
_fini(void)3520Sstevel@tonic-gate _fini(void)
3530Sstevel@tonic-gate {
35411751SAnthony.Scarpino@Sun.COM 	/* Unregister from KCF if module is registered */
3550Sstevel@tonic-gate 	if (rsa_prov_handle != NULL) {
35611751SAnthony.Scarpino@Sun.COM 		if (crypto_unregister_provider(rsa_prov_handle))
3570Sstevel@tonic-gate 			return (EBUSY);
35811751SAnthony.Scarpino@Sun.COM 
3590Sstevel@tonic-gate 		rsa_prov_handle = NULL;
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate int
_info(struct modinfo * modinfop)3660Sstevel@tonic-gate _info(struct modinfo *modinfop)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate /* ARGSUSED */
3720Sstevel@tonic-gate static void
rsa_provider_status(crypto_provider_handle_t provider,uint_t * status)3730Sstevel@tonic-gate rsa_provider_status(crypto_provider_handle_t provider, uint_t *status)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate 	*status = CRYPTO_PROVIDER_READY;
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate static int
check_mech_and_key(crypto_mechanism_t * mechanism,crypto_key_t * key)3790Sstevel@tonic-gate check_mech_and_key(crypto_mechanism_t *mechanism, crypto_key_t *key)
3800Sstevel@tonic-gate {
3810Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate /* EXPORT DELETE START */
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	uchar_t *modulus;
3860Sstevel@tonic-gate 	ssize_t modulus_len; /* In bytes */
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	if (!RSA_VALID_MECH(mechanism))
3890Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	/*
3920Sstevel@tonic-gate 	 * We only support RSA keys that are passed as a list of
3930Sstevel@tonic-gate 	 * object attributes.
3940Sstevel@tonic-gate 	 */
3950Sstevel@tonic-gate 	if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
3960Sstevel@tonic-gate 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 
3997188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
4000Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
4010Sstevel@tonic-gate 		return (rv);
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 	if (modulus_len < MIN_RSA_KEYLENGTH_IN_BYTES ||
4040Sstevel@tonic-gate 	    modulus_len > MAX_RSA_KEYLENGTH_IN_BYTES)
4050Sstevel@tonic-gate 		return (CRYPTO_KEY_SIZE_RANGE);
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /* EXPORT DELETE END */
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	return (rv);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate void
kmemset(uint8_t * buf,char pattern,size_t len)4130Sstevel@tonic-gate kmemset(uint8_t *buf, char pattern, size_t len)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate 	int i = 0;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	while (i < len)
4180Sstevel@tonic-gate 		buf[i++] = pattern;
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate /*
4220Sstevel@tonic-gate  * This function guarantees to return non-zero random numbers.
4230Sstevel@tonic-gate  * This is needed as the /dev/urandom kernel interface,
4240Sstevel@tonic-gate  * random_get_pseudo_bytes(), may return zeros.
4250Sstevel@tonic-gate  */
4260Sstevel@tonic-gate int
knzero_random_generator(uint8_t * ran_out,size_t ran_len)4270Sstevel@tonic-gate knzero_random_generator(uint8_t *ran_out, size_t ran_len)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate 	int rv;
4300Sstevel@tonic-gate 	size_t ebc = 0; /* count of extra bytes in extrarand */
4310Sstevel@tonic-gate 	size_t i = 0;
4320Sstevel@tonic-gate 	uint8_t extrarand[32];
4330Sstevel@tonic-gate 	size_t extrarand_len;
4340Sstevel@tonic-gate 
43510732SAnthony.Scarpino@Sun.COM 	if ((rv = random_get_pseudo_bytes_fips140(ran_out, ran_len)) != 0)
4360Sstevel@tonic-gate 		return (rv);
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	/*
4390Sstevel@tonic-gate 	 * Walk through the returned random numbers pointed by ran_out,
4400Sstevel@tonic-gate 	 * and look for any random number which is zero.
4410Sstevel@tonic-gate 	 * If we find zero, call random_get_pseudo_bytes() to generate
4420Sstevel@tonic-gate 	 * another 32 random numbers pool. Replace any zeros in ran_out[]
4430Sstevel@tonic-gate 	 * from the random number in pool.
4440Sstevel@tonic-gate 	 */
4450Sstevel@tonic-gate 	while (i < ran_len) {
4460Sstevel@tonic-gate 		if (ran_out[i] != 0) {
4470Sstevel@tonic-gate 			i++;
4480Sstevel@tonic-gate 			continue;
4490Sstevel@tonic-gate 		}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 		/*
4520Sstevel@tonic-gate 		 * Note that it is 'while' so we are guaranteed a
4530Sstevel@tonic-gate 		 * non-zero value on exit.
4540Sstevel@tonic-gate 		 */
4550Sstevel@tonic-gate 		if (ebc == 0) {
4560Sstevel@tonic-gate 			/* refresh extrarand */
4570Sstevel@tonic-gate 			extrarand_len = sizeof (extrarand);
45810732SAnthony.Scarpino@Sun.COM 			if ((rv = random_get_pseudo_bytes_fips140(extrarand,
4590Sstevel@tonic-gate 			    extrarand_len)) != 0) {
4600Sstevel@tonic-gate 				return (rv);
4610Sstevel@tonic-gate 			}
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 			ebc = extrarand_len;
4640Sstevel@tonic-gate 		}
4650Sstevel@tonic-gate 		/* Replace zero with byte from extrarand. */
4660Sstevel@tonic-gate 		-- ebc;
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 		/*
4690Sstevel@tonic-gate 		 * The new random byte zero/non-zero will be checked in
4700Sstevel@tonic-gate 		 * the next pass through the loop.
4710Sstevel@tonic-gate 		 */
4720Sstevel@tonic-gate 		ran_out[i] = extrarand[ebc];
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate static int
compare_data(crypto_data_t * data,uchar_t * buf)4790Sstevel@tonic-gate compare_data(crypto_data_t *data, uchar_t *buf)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate 	int len;
4820Sstevel@tonic-gate 	uchar_t *dptr;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	len = data->cd_length;
4850Sstevel@tonic-gate 	switch (data->cd_format) {
4860Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
4870Sstevel@tonic-gate 		dptr = (uchar_t *)(data->cd_raw.iov_base +
4880Sstevel@tonic-gate 		    data->cd_offset);
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 		return (bcmp(dptr, buf, len));
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
4937188Smcpowers 		return (crypto_uio_data(data, buf, len,
4947188Smcpowers 		    COMPARE_TO_DATA, NULL, NULL));
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
4977188Smcpowers 		return (crypto_mblk_data(data, buf, len,
4987188Smcpowers 		    COMPARE_TO_DATA, NULL, NULL));
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	return (CRYPTO_FAILED);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate /* ARGSUSED */
5050Sstevel@tonic-gate static int
rsa_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t template,crypto_req_handle_t req)5060Sstevel@tonic-gate rsa_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
5070Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t template,
5080Sstevel@tonic-gate     crypto_req_handle_t req)
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate 	int rv;
5110Sstevel@tonic-gate 	int kmflag;
5120Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
5150Sstevel@tonic-gate 		return (rv);
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	/*
5180Sstevel@tonic-gate 	 * Allocate a RSA context.
5190Sstevel@tonic-gate 	 */
5200Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
5210Sstevel@tonic-gate 	if ((ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag)) == NULL)
5220Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
5230Sstevel@tonic-gate 
5247188Smcpowers 	if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size,
5257188Smcpowers 	    kmflag)) != CRYPTO_SUCCESS) {
5260Sstevel@tonic-gate 		kmem_free(ctxp, sizeof (rsa_ctx_t));
5270Sstevel@tonic-gate 		return (rv);
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate /* ARGSUSED */
5370Sstevel@tonic-gate static int
rsaprov_encrypt(crypto_ctx_t * ctx,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_req_handle_t req)538*12573SDina.Nimeh@Sun.COM rsaprov_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
5390Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_req_handle_t req)
5400Sstevel@tonic-gate {
5410Sstevel@tonic-gate 	int rv;
5420Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
5450Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	/*
5500Sstevel@tonic-gate 	 * Note on the KM_SLEEP flag passed to the routine below -
551*12573SDina.Nimeh@Sun.COM 	 * rsaprov_encrypt() is a single-part encryption routine which is
5520Sstevel@tonic-gate 	 * currently usable only by /dev/crypto. Since /dev/crypto calls are
5530Sstevel@tonic-gate 	 * always synchronous, we can safely pass KM_SLEEP here.
5540Sstevel@tonic-gate 	 */
5550Sstevel@tonic-gate 	rv = rsa_encrypt_common(ctxp->mech_type, ctxp->key, plaintext,
556*12573SDina.Nimeh@Sun.COM 	    ciphertext);
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
5590Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	return (rv);
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate /* ARGSUSED */
5650Sstevel@tonic-gate static int
rsa_encrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)5660Sstevel@tonic-gate rsa_encrypt_atomic(crypto_provider_handle_t provider,
5670Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
5680Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
5690Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate 	int rv;
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
5740Sstevel@tonic-gate 		return (rv);
5750Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	return (rsa_encrypt_common(mechanism->cm_type, key, plaintext,
578*12573SDina.Nimeh@Sun.COM 	    ciphertext));
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate static int
rsa_free_context(crypto_ctx_t * ctx)5820Sstevel@tonic-gate rsa_free_context(crypto_ctx_t *ctx)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate 	rsa_ctx_t *ctxp = ctx->cc_provider_private;
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	if (ctxp != NULL) {
5870Sstevel@tonic-gate 		bzero(ctxp->key, ctxp->keychunk_size);
5880Sstevel@tonic-gate 		kmem_free(ctxp->key, ctxp->keychunk_size);
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 		if (ctxp->mech_type == RSA_PKCS_MECH_INFO_TYPE ||
5910Sstevel@tonic-gate 		    ctxp->mech_type == RSA_X_509_MECH_INFO_TYPE)
5920Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
5930Sstevel@tonic-gate 		else
5940Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (digest_rsa_ctx_t));
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 		ctx->cc_provider_private = NULL;
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate static int
rsa_encrypt_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext)6030Sstevel@tonic-gate rsa_encrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
604*12573SDina.Nimeh@Sun.COM     crypto_data_t *plaintext, crypto_data_t *ciphertext)
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate /* EXPORT DELETE START */
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	int plen;
6110Sstevel@tonic-gate 	uchar_t *ptptr;
6120Sstevel@tonic-gate 	uchar_t *modulus;
6130Sstevel@tonic-gate 	ssize_t modulus_len;
6140Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
6150Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
6160Sstevel@tonic-gate 	uchar_t cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES];
6170Sstevel@tonic-gate 
6187188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
6190Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
6200Sstevel@tonic-gate 		return (rv);
6210Sstevel@tonic-gate 	}
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	plen = plaintext->cd_length;
6240Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
6250Sstevel@tonic-gate 		if (plen > (modulus_len - MIN_PKCS1_PADLEN))
6260Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
6270Sstevel@tonic-gate 	} else {
6280Sstevel@tonic-gate 		if (plen > modulus_len)
6290Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
6300Sstevel@tonic-gate 	}
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	/*
6330Sstevel@tonic-gate 	 * Output buf len must not be less than RSA modulus size.
6340Sstevel@tonic-gate 	 */
6350Sstevel@tonic-gate 	if (ciphertext->cd_length < modulus_len) {
6360Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
6370Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	ASSERT(plaintext->cd_length <= sizeof (tmp_data));
6417188Smcpowers 	if ((rv = crypto_get_input_data(plaintext, &ptptr, tmp_data))
6420Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
6430Sstevel@tonic-gate 		return (rv);
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
646*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_encode(PKCS1_ENCRYPT, ptptr, plen,
6470Sstevel@tonic-gate 		    plain_data, modulus_len);
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
6500Sstevel@tonic-gate 			return (rv);
6510Sstevel@tonic-gate 	} else {
6520Sstevel@tonic-gate 		bzero(plain_data, modulus_len - plen);
6530Sstevel@tonic-gate 		bcopy(ptptr, &plain_data[modulus_len - plen], plen);
6540Sstevel@tonic-gate 	}
6550Sstevel@tonic-gate 
656*12573SDina.Nimeh@Sun.COM 	rv = core_rsa_encrypt(key, plain_data, modulus_len, cipher_data, 1);
6570Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
6580Sstevel@tonic-gate 		/* copy out to ciphertext */
6597188Smcpowers 		if ((rv = crypto_put_output_data(cipher_data,
6600Sstevel@tonic-gate 		    ciphertext, modulus_len)) != CRYPTO_SUCCESS)
6610Sstevel@tonic-gate 			return (rv);
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
6640Sstevel@tonic-gate 	}
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate /* EXPORT DELETE END */
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	return (rv);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate /* EXPORT DELETE START */
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate static int
core_rsa_encrypt(crypto_key_t * key,uchar_t * in,int in_len,uchar_t * out,int is_public)6740Sstevel@tonic-gate core_rsa_encrypt(crypto_key_t *key, uchar_t *in,
675*12573SDina.Nimeh@Sun.COM     int in_len, uchar_t *out, int is_public)
6760Sstevel@tonic-gate {
6770Sstevel@tonic-gate 	int rv;
6780Sstevel@tonic-gate 	uchar_t *expo, *modulus;
6790Sstevel@tonic-gate 	ssize_t	expo_len;
6800Sstevel@tonic-gate 	ssize_t modulus_len;
681*12573SDina.Nimeh@Sun.COM 	RSAbytekey k;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	if (is_public) {
6847188Smcpowers 		if ((rv = crypto_get_key_attr(key, SUN_CKA_PUBLIC_EXPONENT,
6857188Smcpowers 		    &expo, &expo_len)) != CRYPTO_SUCCESS)
6860Sstevel@tonic-gate 			return (rv);
6870Sstevel@tonic-gate 	} else {
6880Sstevel@tonic-gate 		/*
6890Sstevel@tonic-gate 		 * SUN_CKA_PRIVATE_EXPONENT is a required attribute for a
6900Sstevel@tonic-gate 		 * RSA secret key. See the comments in core_rsa_decrypt
6910Sstevel@tonic-gate 		 * routine which calls this routine with a private key.
6920Sstevel@tonic-gate 		 */
6937188Smcpowers 		if ((rv = crypto_get_key_attr(key, SUN_CKA_PRIVATE_EXPONENT,
6947188Smcpowers 		    &expo, &expo_len)) != CRYPTO_SUCCESS)
6950Sstevel@tonic-gate 			return (rv);
6960Sstevel@tonic-gate 	}
6970Sstevel@tonic-gate 
6987188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
6990Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
7000Sstevel@tonic-gate 		return (rv);
7010Sstevel@tonic-gate 	}
7020Sstevel@tonic-gate 
703*12573SDina.Nimeh@Sun.COM 	k.modulus = modulus;
704*12573SDina.Nimeh@Sun.COM 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
705*12573SDina.Nimeh@Sun.COM 	k.pubexpo = expo;
706*12573SDina.Nimeh@Sun.COM 	k.pubexpo_bytes = expo_len;
707*12573SDina.Nimeh@Sun.COM 	k.rfunc = NULL;
7080Sstevel@tonic-gate 
709*12573SDina.Nimeh@Sun.COM 	rv = rsa_encrypt(&k, in, in_len, out);
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 	return (rv);
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate /* EXPORT DELETE END */
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate /* ARGSUSED */
7170Sstevel@tonic-gate static int
rsaprov_decrypt(crypto_ctx_t * ctx,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_req_handle_t req)718*12573SDina.Nimeh@Sun.COM rsaprov_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
7190Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_req_handle_t req)
7200Sstevel@tonic-gate {
7210Sstevel@tonic-gate 	int rv;
7220Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
7250Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
7280Sstevel@tonic-gate 
729*12573SDina.Nimeh@Sun.COM 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
7300Sstevel@tonic-gate 	rv = rsa_decrypt_common(ctxp->mech_type, ctxp->key,
731*12573SDina.Nimeh@Sun.COM 	    ciphertext, plaintext);
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
7340Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	return (rv);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate /* ARGSUSED */
7400Sstevel@tonic-gate static int
rsa_decrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)7410Sstevel@tonic-gate rsa_decrypt_atomic(crypto_provider_handle_t provider,
7420Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
7430Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
7440Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
7450Sstevel@tonic-gate {
7460Sstevel@tonic-gate 	int rv;
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
7490Sstevel@tonic-gate 		return (rv);
7500Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	return (rsa_decrypt_common(mechanism->cm_type, key, ciphertext,
753*12573SDina.Nimeh@Sun.COM 	    plaintext));
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate static int
rsa_decrypt_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext)7570Sstevel@tonic-gate rsa_decrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
758*12573SDina.Nimeh@Sun.COM     crypto_data_t *ciphertext, crypto_data_t *plaintext)
7590Sstevel@tonic-gate {
7600Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate /* EXPORT DELETE START */
7630Sstevel@tonic-gate 
764*12573SDina.Nimeh@Sun.COM 	size_t plain_len;
7650Sstevel@tonic-gate 	uchar_t *ctptr;
7660Sstevel@tonic-gate 	uchar_t *modulus;
7670Sstevel@tonic-gate 	ssize_t modulus_len;
7680Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
7690Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
7700Sstevel@tonic-gate 
7717188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
7720Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
7730Sstevel@tonic-gate 		return (rv);
7740Sstevel@tonic-gate 	}
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	/*
7770Sstevel@tonic-gate 	 * Ciphertext length must be equal to RSA modulus size.
7780Sstevel@tonic-gate 	 */
7790Sstevel@tonic-gate 	if (ciphertext->cd_length != modulus_len)
7800Sstevel@tonic-gate 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	ASSERT(ciphertext->cd_length <= sizeof (tmp_data));
7837188Smcpowers 	if ((rv = crypto_get_input_data(ciphertext, &ctptr, tmp_data))
7840Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
7850Sstevel@tonic-gate 		return (rv);
7860Sstevel@tonic-gate 
787*12573SDina.Nimeh@Sun.COM 	rv = core_rsa_decrypt(key, ctptr, modulus_len, plain_data);
7880Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
7890Sstevel@tonic-gate 		plain_len = modulus_len;
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 		if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
7920Sstevel@tonic-gate 			/* Strip off the PKCS block formatting data. */
793*12573SDina.Nimeh@Sun.COM 			rv = pkcs1_decode(PKCS1_DECRYPT, plain_data,
7940Sstevel@tonic-gate 			    &plain_len);
7950Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
7960Sstevel@tonic-gate 				return (rv);
7970Sstevel@tonic-gate 		}
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 		if (plain_len > plaintext->cd_length) {
8000Sstevel@tonic-gate 			plaintext->cd_length = plain_len;
8010Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
8020Sstevel@tonic-gate 		}
8030Sstevel@tonic-gate 
8047188Smcpowers 		if ((rv = crypto_put_output_data(
8057188Smcpowers 		    plain_data + modulus_len - plain_len,
8060Sstevel@tonic-gate 		    plaintext, plain_len)) != CRYPTO_SUCCESS)
8070Sstevel@tonic-gate 			return (rv);
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 		plaintext->cd_length = plain_len;
8100Sstevel@tonic-gate 	}
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate /* EXPORT DELETE END */
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	return (rv);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate /* EXPORT DELETE START */
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate static int
core_rsa_decrypt(crypto_key_t * key,uchar_t * in,int in_len,uchar_t * out)820*12573SDina.Nimeh@Sun.COM core_rsa_decrypt(crypto_key_t *key, uchar_t *in, int in_len, uchar_t *out)
8210Sstevel@tonic-gate {
8220Sstevel@tonic-gate 	int rv;
8230Sstevel@tonic-gate 	uchar_t *modulus, *prime1, *prime2, *expo1, *expo2, *coef;
8240Sstevel@tonic-gate 	ssize_t modulus_len;
8250Sstevel@tonic-gate 	ssize_t	prime1_len, prime2_len;
8260Sstevel@tonic-gate 	ssize_t	expo1_len, expo2_len, coef_len;
827*12573SDina.Nimeh@Sun.COM 	RSAbytekey k;
8280Sstevel@tonic-gate 
8297188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
8300Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
8310Sstevel@tonic-gate 		return (rv);
8320Sstevel@tonic-gate 	}
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	/*
8350Sstevel@tonic-gate 	 * The following attributes are not required to be
8360Sstevel@tonic-gate 	 * present in a RSA secret key. If any of them is not present
8370Sstevel@tonic-gate 	 * we call the encrypt routine with a flag indicating use of
8380Sstevel@tonic-gate 	 * private exponent (d). Note that SUN_CKA_PRIVATE_EXPONENT is
8390Sstevel@tonic-gate 	 * a required attribute for a RSA secret key.
8400Sstevel@tonic-gate 	 */
8417188Smcpowers 	if ((crypto_get_key_attr(key, SUN_CKA_PRIME_1, &prime1, &prime1_len)
8425072Smcpowers 	    != CRYPTO_SUCCESS) ||
8437188Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_PRIME_2, &prime2, &prime2_len)
8445072Smcpowers 	    != CRYPTO_SUCCESS) ||
8457188Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_EXPONENT_1, &expo1, &expo1_len)
8465072Smcpowers 	    != CRYPTO_SUCCESS) ||
8477188Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_EXPONENT_2, &expo2, &expo2_len)
8485072Smcpowers 	    != CRYPTO_SUCCESS) ||
8497188Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_COEFFICIENT, &coef, &coef_len)
8505072Smcpowers 	    != CRYPTO_SUCCESS)) {
851*12573SDina.Nimeh@Sun.COM 		return (core_rsa_encrypt(key, in, in_len, out, 0));
8520Sstevel@tonic-gate 	}
8530Sstevel@tonic-gate 
854*12573SDina.Nimeh@Sun.COM 	k.modulus = modulus;
855*12573SDina.Nimeh@Sun.COM 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
856*12573SDina.Nimeh@Sun.COM 	k.prime1 = prime1;
857*12573SDina.Nimeh@Sun.COM 	k.prime1_bytes = prime1_len;
858*12573SDina.Nimeh@Sun.COM 	k.prime2 = prime2;
859*12573SDina.Nimeh@Sun.COM 	k.prime2_bytes = prime2_len;
860*12573SDina.Nimeh@Sun.COM 	k.expo1 = expo1;
861*12573SDina.Nimeh@Sun.COM 	k.expo1_bytes = expo1_len;
862*12573SDina.Nimeh@Sun.COM 	k.expo2 = expo2;
863*12573SDina.Nimeh@Sun.COM 	k.expo2_bytes = expo2_len;
864*12573SDina.Nimeh@Sun.COM 	k.coeff = coef;
865*12573SDina.Nimeh@Sun.COM 	k.coeff_bytes = coef_len;
866*12573SDina.Nimeh@Sun.COM 	k.rfunc = NULL;
8670Sstevel@tonic-gate 
868*12573SDina.Nimeh@Sun.COM 	rv = rsa_decrypt(&k, in, in_len, out);
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	return (rv);
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate /* EXPORT DELETE END */
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate /* ARGSUSED */
8760Sstevel@tonic-gate static int
rsa_sign_verify_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)8770Sstevel@tonic-gate rsa_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
8780Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
8790Sstevel@tonic-gate     crypto_req_handle_t req)
8800Sstevel@tonic-gate {
8810Sstevel@tonic-gate 	int rv;
8820Sstevel@tonic-gate 	int kmflag;
8830Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
8840Sstevel@tonic-gate 	digest_rsa_ctx_t *dctxp;
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
8870Sstevel@tonic-gate 		return (rv);
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 	/*
8900Sstevel@tonic-gate 	 * Allocate a RSA context.
8910Sstevel@tonic-gate 	 */
8920Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
8930Sstevel@tonic-gate 	switch (mechanism->cm_type) {
8940Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
8950Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
896676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
897676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
898676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
8990Sstevel@tonic-gate 		dctxp = kmem_zalloc(sizeof (digest_rsa_ctx_t), kmflag);
9000Sstevel@tonic-gate 		ctxp = (rsa_ctx_t *)dctxp;
9010Sstevel@tonic-gate 		break;
9020Sstevel@tonic-gate 	default:
9030Sstevel@tonic-gate 		ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag);
9040Sstevel@tonic-gate 		break;
9050Sstevel@tonic-gate 	}
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	if (ctxp == NULL)
9080Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
9117188Smcpowers 	if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size,
9127188Smcpowers 	    kmflag)) != CRYPTO_SUCCESS) {
9130Sstevel@tonic-gate 		switch (mechanism->cm_type) {
9140Sstevel@tonic-gate 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
9150Sstevel@tonic-gate 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
916676Sizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
917676Sizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
918676Sizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
9190Sstevel@tonic-gate 			kmem_free(dctxp, sizeof (digest_rsa_ctx_t));
9200Sstevel@tonic-gate 			break;
9210Sstevel@tonic-gate 		default:
9220Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
9230Sstevel@tonic-gate 			break;
9240Sstevel@tonic-gate 		}
9250Sstevel@tonic-gate 		return (rv);
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	switch (mechanism->cm_type) {
9290Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
9300Sstevel@tonic-gate 		MD5Init(&(dctxp->md5_ctx));
9310Sstevel@tonic-gate 		break;
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
9340Sstevel@tonic-gate 		SHA1Init(&(dctxp->sha1_ctx));
9350Sstevel@tonic-gate 		break;
936676Sizick 
937676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
938676Sizick 		SHA2Init(SHA256, &(dctxp->sha2_ctx));
939676Sizick 		break;
940676Sizick 
941676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
942676Sizick 		SHA2Init(SHA384, &(dctxp->sha2_ctx));
943676Sizick 		break;
944676Sizick 
945676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
946676Sizick 		SHA2Init(SHA512, &(dctxp->sha2_ctx));
947676Sizick 		break;
9480Sstevel@tonic-gate 	}
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate #define	SHA1_DIGEST_SIZE 20
9560Sstevel@tonic-gate #define	MD5_DIGEST_SIZE 16
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate #define	INIT_RAW_CRYPTO_DATA(data, base, len, cd_len)	\
9590Sstevel@tonic-gate 	(data).cd_format = CRYPTO_DATA_RAW;		\
9600Sstevel@tonic-gate 	(data).cd_offset = 0;				\
9610Sstevel@tonic-gate 	(data).cd_raw.iov_base = (char *)base;		\
9620Sstevel@tonic-gate 	(data).cd_raw.iov_len = len;			\
9630Sstevel@tonic-gate 	(data).cd_length = cd_len;
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate static int
rsa_digest_svrfy_common(digest_rsa_ctx_t * ctxp,crypto_data_t * data,crypto_data_t * signature,uchar_t flag)9660Sstevel@tonic-gate rsa_digest_svrfy_common(digest_rsa_ctx_t *ctxp, crypto_data_t *data,
967*12573SDina.Nimeh@Sun.COM     crypto_data_t *signature, uchar_t flag)
9680Sstevel@tonic-gate {
9690Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate /* EXPORT DELETE START */
9720Sstevel@tonic-gate 
973676Sizick 	uchar_t digest[SHA512_DIGEST_LENGTH];
9740Sstevel@tonic-gate 	/* The der_data size is enough for MD5 also */
975676Sizick 	uchar_t der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
9760Sstevel@tonic-gate 	ulong_t der_data_len;
9770Sstevel@tonic-gate 	crypto_data_t der_cd;
9780Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
9790Sstevel@tonic-gate 
9807188Smcpowers 	ASSERT(flag & CRYPTO_DO_SIGN || flag & CRYPTO_DO_VERIFY);
9817188Smcpowers 	ASSERT(data != NULL || (flag & CRYPTO_DO_FINAL));
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
984676Sizick 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
985676Sizick 	    mech_type == RSA_X_509_MECH_INFO_TYPE)
9860Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate 	/*
9890Sstevel@tonic-gate 	 * We need to do the BUFFER_TOO_SMALL check before digesting
9900Sstevel@tonic-gate 	 * the data. No check is needed for verify as signature is not
9910Sstevel@tonic-gate 	 * an output argument for verify.
9920Sstevel@tonic-gate 	 */
9937188Smcpowers 	if (flag & CRYPTO_DO_SIGN) {
9940Sstevel@tonic-gate 		uchar_t *modulus;
9950Sstevel@tonic-gate 		ssize_t modulus_len;
9960Sstevel@tonic-gate 
9977188Smcpowers 		if ((rv = crypto_get_key_attr(ctxp->key, SUN_CKA_MODULUS,
9987188Smcpowers 		    &modulus, &modulus_len)) != CRYPTO_SUCCESS) {
9990Sstevel@tonic-gate 			return (rv);
10000Sstevel@tonic-gate 		}
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 		if (signature->cd_length < modulus_len) {
10030Sstevel@tonic-gate 			signature->cd_length = modulus_len;
10040Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
10050Sstevel@tonic-gate 		}
10060Sstevel@tonic-gate 	}
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
10097188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->md5_ctx),
10107188Smcpowers 		    digest, MD5Update, MD5Final, flag | CRYPTO_DO_MD5);
1011676Sizick 
1012676Sizick 	else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE)
10137188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
10147188Smcpowers 		    digest, SHA1Update, SHA1Final,  flag | CRYPTO_DO_SHA1);
1015676Sizick 
1016676Sizick 	else
10177188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha2_ctx),
10187188Smcpowers 		    digest, SHA2Update, SHA2Final, flag | CRYPTO_DO_SHA2);
1019676Sizick 
10200Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
10210Sstevel@tonic-gate 		return (rv);
10220Sstevel@tonic-gate 
1023676Sizick 
10240Sstevel@tonic-gate 	/*
10250Sstevel@tonic-gate 	 * Prepare the DER encoding of the DigestInfo value as follows:
10260Sstevel@tonic-gate 	 * MD5:		MD5_DER_PREFIX || H
10270Sstevel@tonic-gate 	 * SHA-1:	SHA1_DER_PREFIX || H
10280Sstevel@tonic-gate 	 *
10290Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
10300Sstevel@tonic-gate 	 */
1031676Sizick 	switch (mech_type) {
1032676Sizick 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
10330Sstevel@tonic-gate 		bcopy(MD5_DER_PREFIX, der_data, MD5_DER_PREFIX_Len);
1034676Sizick 		bcopy(digest, der_data + MD5_DER_PREFIX_Len, MD5_DIGEST_SIZE);
1035676Sizick 		der_data_len = MD5_DER_PREFIX_Len + MD5_DIGEST_SIZE;
1036676Sizick 		break;
1037676Sizick 
1038676Sizick 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
10390Sstevel@tonic-gate 		bcopy(SHA1_DER_PREFIX, der_data, SHA1_DER_PREFIX_Len);
1040676Sizick 		bcopy(digest, der_data + SHA1_DER_PREFIX_Len,
1041676Sizick 		    SHA1_DIGEST_SIZE);
1042676Sizick 		der_data_len = SHA1_DER_PREFIX_Len + SHA1_DIGEST_SIZE;
1043676Sizick 		break;
1044676Sizick 
1045676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1046676Sizick 		bcopy(SHA256_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1047676Sizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1048676Sizick 		    SHA256_DIGEST_LENGTH);
1049676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA256_DIGEST_LENGTH;
1050676Sizick 		break;
1051676Sizick 
1052676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1053676Sizick 		bcopy(SHA384_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1054676Sizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1055676Sizick 		    SHA384_DIGEST_LENGTH);
1056676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA384_DIGEST_LENGTH;
1057676Sizick 		break;
1058676Sizick 
1059676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1060676Sizick 		bcopy(SHA512_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1061676Sizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1062676Sizick 		    SHA512_DIGEST_LENGTH);
1063676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA512_DIGEST_LENGTH;
1064676Sizick 		break;
10650Sstevel@tonic-gate 	}
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	INIT_RAW_CRYPTO_DATA(der_cd, der_data, der_data_len, der_data_len);
10680Sstevel@tonic-gate 	/*
10690Sstevel@tonic-gate 	 * Now, we are ready to sign or verify the DER_ENCODED data.
10700Sstevel@tonic-gate 	 */
10717188Smcpowers 	if (flag & CRYPTO_DO_SIGN)
10720Sstevel@tonic-gate 		rv = rsa_sign_common(mech_type, ctxp->key, &der_cd,
1073*12573SDina.Nimeh@Sun.COM 		    signature);
10740Sstevel@tonic-gate 	else
10750Sstevel@tonic-gate 		rv = rsa_verify_common(mech_type, ctxp->key, &der_cd,
1076*12573SDina.Nimeh@Sun.COM 		    signature);
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate /* EXPORT DELETE END */
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	return (rv);
10810Sstevel@tonic-gate }
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate static int
rsa_sign_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature)10840Sstevel@tonic-gate rsa_sign_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1085*12573SDina.Nimeh@Sun.COM     crypto_data_t *data, crypto_data_t *signature)
10860Sstevel@tonic-gate {
10870Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate /* EXPORT DELETE START */
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate 	int dlen;
10920Sstevel@tonic-gate 	uchar_t *dataptr, *modulus;
10930Sstevel@tonic-gate 	ssize_t modulus_len;
10940Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
10950Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
10960Sstevel@tonic-gate 	uchar_t signed_data[MAX_RSA_KEYLENGTH_IN_BYTES];
10970Sstevel@tonic-gate 
10987188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
10990Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
11000Sstevel@tonic-gate 		return (rv);
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	dlen = data->cd_length;
11040Sstevel@tonic-gate 	switch (mech_type) {
11050Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
11060Sstevel@tonic-gate 		if (dlen > (modulus_len - MIN_PKCS1_PADLEN))
11070Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
11080Sstevel@tonic-gate 		break;
11090Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
11100Sstevel@tonic-gate 		if (dlen > modulus_len)
11110Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
11120Sstevel@tonic-gate 		break;
11130Sstevel@tonic-gate 	}
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	if (signature->cd_length < modulus_len) {
11160Sstevel@tonic-gate 		signature->cd_length = modulus_len;
11170Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
11180Sstevel@tonic-gate 	}
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate 	ASSERT(data->cd_length <= sizeof (tmp_data));
11217188Smcpowers 	if ((rv = crypto_get_input_data(data, &dataptr, tmp_data))
11220Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
11230Sstevel@tonic-gate 		return (rv);
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate 	switch (mech_type) {
11260Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
11270Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
11280Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1129676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1130676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1131676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
11320Sstevel@tonic-gate 		/*
11330Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
11340Sstevel@tonic-gate 		 * type "01" encryption block.
11350Sstevel@tonic-gate 		 */
1136*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_encode(PKCS1_SIGN, dataptr, dlen, plain_data,
11370Sstevel@tonic-gate 		    modulus_len);
11380Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
11390Sstevel@tonic-gate 			return (rv);
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 		break;
11420Sstevel@tonic-gate 
11430Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
11440Sstevel@tonic-gate 		bzero(plain_data, modulus_len - dlen);
11450Sstevel@tonic-gate 		bcopy(dataptr, &plain_data[modulus_len - dlen], dlen);
11460Sstevel@tonic-gate 		break;
11470Sstevel@tonic-gate 	}
11480Sstevel@tonic-gate 
1149*12573SDina.Nimeh@Sun.COM 	rv = core_rsa_decrypt(key, plain_data, modulus_len, signed_data);
11500Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
11510Sstevel@tonic-gate 		/* copy out to signature */
11527188Smcpowers 		if ((rv = crypto_put_output_data(signed_data,
11530Sstevel@tonic-gate 		    signature, modulus_len)) != CRYPTO_SUCCESS)
11540Sstevel@tonic-gate 			return (rv);
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 		signature->cd_length = modulus_len;
11570Sstevel@tonic-gate 	}
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate /* EXPORT DELETE END */
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate 	return (rv);
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate /* ARGSUSED */
11650Sstevel@tonic-gate static int
rsaprov_sign(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)1166*12573SDina.Nimeh@Sun.COM rsaprov_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
11670Sstevel@tonic-gate     crypto_req_handle_t req)
11680Sstevel@tonic-gate {
11690Sstevel@tonic-gate 	int rv;
11700Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
11730Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
11740Sstevel@tonic-gate 
1175*12573SDina.Nimeh@Sun.COM 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
11760Sstevel@tonic-gate 	switch (ctxp->mech_type) {
11770Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
11780Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1179676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1180676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1181676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
11820Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
1183*12573SDina.Nimeh@Sun.COM 		    signature, CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE |
11847188Smcpowers 		    CRYPTO_DO_FINAL);
11850Sstevel@tonic-gate 		break;
11860Sstevel@tonic-gate 	default:
11870Sstevel@tonic-gate 		rv = rsa_sign_common(ctxp->mech_type, ctxp->key, data,
1188*12573SDina.Nimeh@Sun.COM 		    signature);
11890Sstevel@tonic-gate 		break;
11900Sstevel@tonic-gate 	}
11910Sstevel@tonic-gate 
11920Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
11930Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 	return (rv);
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate /* ARGSUSED */
11990Sstevel@tonic-gate static int
rsa_sign_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)12000Sstevel@tonic-gate rsa_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
12010Sstevel@tonic-gate {
12020Sstevel@tonic-gate 	int rv;
12030Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
12040Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
12070Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
12080Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
12090Sstevel@tonic-gate 
1210676Sizick 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
1211676Sizick 	    mech_type == RSA_X_509_MECH_INFO_TYPE)
12120Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
12130Sstevel@tonic-gate 
12140Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
12157188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->md5_ctx),
12167188Smcpowers 		    NULL, MD5Update, MD5Final,
12177188Smcpowers 		    CRYPTO_DO_MD5 | CRYPTO_DO_UPDATE);
1218676Sizick 
1219676Sizick 	else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE)
12207188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
12217188Smcpowers 		    NULL, SHA1Update, SHA1Final, CRYPTO_DO_SHA1 |
12227188Smcpowers 		    CRYPTO_DO_UPDATE);
1223676Sizick 
1224676Sizick 	else
12257188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha2_ctx),
12267188Smcpowers 		    NULL, SHA2Update, SHA2Final, CRYPTO_DO_SHA2 |
12277188Smcpowers 		    CRYPTO_DO_UPDATE);
1228676Sizick 
12290Sstevel@tonic-gate 	return (rv);
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate 
1232*12573SDina.Nimeh@Sun.COM /* ARGSUSED2 */
12330Sstevel@tonic-gate static int
rsa_sign_final(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_req_handle_t req)12340Sstevel@tonic-gate rsa_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
12350Sstevel@tonic-gate     crypto_req_handle_t req)
12360Sstevel@tonic-gate {
12370Sstevel@tonic-gate 	int rv;
12380Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
12410Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
12420Sstevel@tonic-gate 
12430Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
1244*12573SDina.Nimeh@Sun.COM 	    CRYPTO_DO_SIGN | CRYPTO_DO_FINAL);
12450Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
12460Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 	return (rv);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate /* ARGSUSED */
12520Sstevel@tonic-gate static int
rsa_sign_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)12530Sstevel@tonic-gate rsa_sign_atomic(crypto_provider_handle_t provider,
12540Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
12550Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
12560Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
12570Sstevel@tonic-gate {
12580Sstevel@tonic-gate 	int rv;
12590Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
12620Sstevel@tonic-gate 		return (rv);
12630Sstevel@tonic-gate 
1264676Sizick 	if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE ||
1265676Sizick 	    mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE)
1266676Sizick 		rv = rsa_sign_common(mechanism->cm_type, key, data,
1267*12573SDina.Nimeh@Sun.COM 		    signature);
1268676Sizick 
1269676Sizick 	else {
12700Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
12710Sstevel@tonic-gate 		dctx.key = key;
1272676Sizick 		switch (mechanism->cm_type) {
1273676Sizick 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
12740Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1275676Sizick 			break;
1276676Sizick 
1277676Sizick 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
12780Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1279676Sizick 			break;
1280676Sizick 
1281676Sizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1282676Sizick 			SHA2Init(SHA256, &(dctx.sha2_ctx));
1283676Sizick 			break;
1284676Sizick 
1285676Sizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1286676Sizick 			SHA2Init(SHA384, &(dctx.sha2_ctx));
1287676Sizick 			break;
1288676Sizick 
1289676Sizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1290676Sizick 			SHA2Init(SHA512, &(dctx.sha2_ctx));
1291676Sizick 			break;
1292676Sizick 		}
1293676Sizick 
1294676Sizick 		rv = rsa_digest_svrfy_common(&dctx, data, signature,
1295*12573SDina.Nimeh@Sun.COM 		    CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL);
12960Sstevel@tonic-gate 	}
12970Sstevel@tonic-gate 
12980Sstevel@tonic-gate 	return (rv);
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate static int
rsa_verify_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature)13020Sstevel@tonic-gate rsa_verify_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1303*12573SDina.Nimeh@Sun.COM     crypto_data_t *data, crypto_data_t *signature)
13040Sstevel@tonic-gate {
13050Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate /* EXPORT DELETE START */
13080Sstevel@tonic-gate 
13090Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
13100Sstevel@tonic-gate 	ssize_t modulus_len;
13110Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
13120Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
13130Sstevel@tonic-gate 
13147188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
13150Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
13160Sstevel@tonic-gate 		return (rv);
13170Sstevel@tonic-gate 	}
13180Sstevel@tonic-gate 
13190Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
13200Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
13210Sstevel@tonic-gate 
13220Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
13237188Smcpowers 	if ((rv = crypto_get_input_data(signature, &sigptr, tmp_data))
13240Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
13250Sstevel@tonic-gate 		return (rv);
13260Sstevel@tonic-gate 
1327*12573SDina.Nimeh@Sun.COM 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, 1);
13280Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
13290Sstevel@tonic-gate 		return (rv);
13300Sstevel@tonic-gate 
1331676Sizick 	if (mech_type == RSA_X_509_MECH_INFO_TYPE) {
1332676Sizick 		if (compare_data(data, (plain_data + modulus_len
1333676Sizick 		    - data->cd_length)) != 0)
1334676Sizick 			rv = CRYPTO_SIGNATURE_INVALID;
1335676Sizick 
1336676Sizick 	} else {
1337*12573SDina.Nimeh@Sun.COM 		size_t data_len = modulus_len;
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate 		/*
13400Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
13410Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
13420Sstevel@tonic-gate 		 * the original data.
13430Sstevel@tonic-gate 		 */
1344*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
13450Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
1346676Sizick 			return (rv);
13470Sstevel@tonic-gate 
1348676Sizick 		if (data_len != data->cd_length)
1349676Sizick 			return (CRYPTO_SIGNATURE_LEN_RANGE);
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 		if (compare_data(data, (plain_data + modulus_len
13520Sstevel@tonic-gate 		    - data_len)) != 0)
13530Sstevel@tonic-gate 			rv = CRYPTO_SIGNATURE_INVALID;
13540Sstevel@tonic-gate 	}
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate /* EXPORT DELETE END */
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 	return (rv);
13590Sstevel@tonic-gate }
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate /* ARGSUSED */
13620Sstevel@tonic-gate static int
rsaprov_verify(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)1363*12573SDina.Nimeh@Sun.COM rsaprov_verify(crypto_ctx_t *ctx, crypto_data_t *data,
1364*12573SDina.Nimeh@Sun.COM     crypto_data_t *signature, crypto_req_handle_t req)
13650Sstevel@tonic-gate {
13660Sstevel@tonic-gate 	int rv;
13670Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
13700Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
13710Sstevel@tonic-gate 
1372*12573SDina.Nimeh@Sun.COM 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
13730Sstevel@tonic-gate 	switch (ctxp->mech_type) {
13740Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
13750Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1376676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1377676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1378676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
13790Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
1380*12573SDina.Nimeh@Sun.COM 		    signature, CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE |
13817188Smcpowers 		    CRYPTO_DO_FINAL);
13820Sstevel@tonic-gate 		break;
13830Sstevel@tonic-gate 	default:
13840Sstevel@tonic-gate 		rv = rsa_verify_common(ctxp->mech_type, ctxp->key, data,
1385*12573SDina.Nimeh@Sun.COM 		    signature);
13860Sstevel@tonic-gate 		break;
13870Sstevel@tonic-gate 	}
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
13900Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 	return (rv);
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate /* ARGSUSED */
13960Sstevel@tonic-gate static int
rsa_verify_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)13970Sstevel@tonic-gate rsa_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
13980Sstevel@tonic-gate     crypto_req_handle_t req)
13990Sstevel@tonic-gate {
14000Sstevel@tonic-gate 	int rv;
14010Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
14040Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
14050Sstevel@tonic-gate 
1406676Sizick 	switch (ctxp->mech_type) {
14070Sstevel@tonic-gate 
1408676Sizick 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
14097188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->md5_ctx),
14107188Smcpowers 		    NULL, MD5Update, MD5Final, CRYPTO_DO_MD5 |
14117188Smcpowers 		    CRYPTO_DO_UPDATE);
1412676Sizick 		break;
1413676Sizick 
1414676Sizick 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
14157188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
14167188Smcpowers 		    NULL, SHA1Update, SHA1Final, CRYPTO_DO_SHA1 |
14177188Smcpowers 		    CRYPTO_DO_UPDATE);
1418676Sizick 		break;
1419676Sizick 
1420676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1421676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1422676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
14237188Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha2_ctx),
14247188Smcpowers 		    NULL, SHA2Update, SHA2Final, CRYPTO_DO_SHA2 |
14257188Smcpowers 		    CRYPTO_DO_UPDATE);
1426676Sizick 		break;
1427676Sizick 
1428676Sizick 	default:
1429676Sizick 		return (CRYPTO_MECHANISM_INVALID);
1430676Sizick 	}
1431676Sizick 
14320Sstevel@tonic-gate 	return (rv);
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate 
1435*12573SDina.Nimeh@Sun.COM /* ARGSUSED2 */
14360Sstevel@tonic-gate static int
rsa_verify_final(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_req_handle_t req)14370Sstevel@tonic-gate rsa_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
14380Sstevel@tonic-gate     crypto_req_handle_t req)
14390Sstevel@tonic-gate {
14400Sstevel@tonic-gate 	int rv;
14410Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
14440Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
14450Sstevel@tonic-gate 
14460Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
1447*12573SDina.Nimeh@Sun.COM 	    CRYPTO_DO_VERIFY | CRYPTO_DO_FINAL);
14480Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
14490Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	return (rv);
14520Sstevel@tonic-gate }
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate /* ARGSUSED */
14560Sstevel@tonic-gate static int
rsa_verify_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)14570Sstevel@tonic-gate rsa_verify_atomic(crypto_provider_handle_t provider,
14580Sstevel@tonic-gate     crypto_session_id_t session_id,
14590Sstevel@tonic-gate     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
14600Sstevel@tonic-gate     crypto_data_t *signature, crypto_spi_ctx_template_t ctx_template,
14610Sstevel@tonic-gate     crypto_req_handle_t req)
14620Sstevel@tonic-gate {
14630Sstevel@tonic-gate 	int rv;
14640Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
14670Sstevel@tonic-gate 		return (rv);
14680Sstevel@tonic-gate 
1469676Sizick 	if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE ||
1470676Sizick 	    mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE)
1471676Sizick 		rv = rsa_verify_common(mechanism->cm_type, key, data,
1472*12573SDina.Nimeh@Sun.COM 		    signature);
1473676Sizick 
1474676Sizick 	else {
14750Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
14760Sstevel@tonic-gate 		dctx.key = key;
1477676Sizick 
1478676Sizick 		switch (mechanism->cm_type) {
1479676Sizick 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
14800Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1481676Sizick 			break;
1482676Sizick 
1483676Sizick 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
14840Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1485676Sizick 			break;
1486676Sizick 
1487676Sizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1488676Sizick 			SHA2Init(SHA256, &(dctx.sha2_ctx));
1489676Sizick 			break;
1490676Sizick 
1491676Sizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1492676Sizick 			SHA2Init(SHA384, &(dctx.sha2_ctx));
1493676Sizick 			break;
1494676Sizick 
1495676Sizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1496676Sizick 			SHA2Init(SHA512, &(dctx.sha2_ctx));
1497676Sizick 			break;
1498676Sizick 		}
1499676Sizick 
1500*12573SDina.Nimeh@Sun.COM 		rv = rsa_digest_svrfy_common(&dctx, data, signature,
15017188Smcpowers 		    CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL);
15020Sstevel@tonic-gate 	}
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 	return (rv);
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate static int
rsa_verify_recover_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * signature,crypto_data_t * data)15080Sstevel@tonic-gate rsa_verify_recover_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1509*12573SDina.Nimeh@Sun.COM     crypto_data_t *signature, crypto_data_t *data)
15100Sstevel@tonic-gate {
15110Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate /* EXPORT DELETE START */
15140Sstevel@tonic-gate 
1515*12573SDina.Nimeh@Sun.COM 	size_t data_len;
15160Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
15170Sstevel@tonic-gate 	ssize_t modulus_len;
15180Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
15190Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
15200Sstevel@tonic-gate 
15217188Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
15220Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
15230Sstevel@tonic-gate 		return (rv);
15240Sstevel@tonic-gate 	}
15250Sstevel@tonic-gate 
15260Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
15270Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
15280Sstevel@tonic-gate 
15290Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
15307188Smcpowers 	if ((rv = crypto_get_input_data(signature, &sigptr, tmp_data))
15310Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
15320Sstevel@tonic-gate 		return (rv);
15330Sstevel@tonic-gate 
1534*12573SDina.Nimeh@Sun.COM 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, 1);
15350Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
15360Sstevel@tonic-gate 		return (rv);
15370Sstevel@tonic-gate 
15380Sstevel@tonic-gate 	data_len = modulus_len;
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
15410Sstevel@tonic-gate 		/*
15420Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
15430Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
15440Sstevel@tonic-gate 		 * the original data.
15450Sstevel@tonic-gate 		 */
1546*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
15470Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
15480Sstevel@tonic-gate 			return (rv);
15490Sstevel@tonic-gate 	}
15500Sstevel@tonic-gate 
15510Sstevel@tonic-gate 	if (data->cd_length < data_len) {
15520Sstevel@tonic-gate 		data->cd_length = data_len;
15530Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
15540Sstevel@tonic-gate 	}
15550Sstevel@tonic-gate 
15567188Smcpowers 	if ((rv = crypto_put_output_data(plain_data + modulus_len - data_len,
15570Sstevel@tonic-gate 	    data, data_len)) != CRYPTO_SUCCESS)
15580Sstevel@tonic-gate 		return (rv);
15590Sstevel@tonic-gate 	data->cd_length = data_len;
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate /* EXPORT DELETE END */
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 	return (rv);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate /* ARGSUSED */
15670Sstevel@tonic-gate static int
rsa_verify_recover(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_data_t * data,crypto_req_handle_t req)15680Sstevel@tonic-gate rsa_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
15690Sstevel@tonic-gate     crypto_data_t *data, crypto_req_handle_t req)
15700Sstevel@tonic-gate {
15710Sstevel@tonic-gate 	int rv;
15720Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
15730Sstevel@tonic-gate 
15740Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
15750Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
15760Sstevel@tonic-gate 
1577*12573SDina.Nimeh@Sun.COM 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
15780Sstevel@tonic-gate 	rv = rsa_verify_recover_common(ctxp->mech_type, ctxp->key,
1579*12573SDina.Nimeh@Sun.COM 	    signature, data);
15800Sstevel@tonic-gate 
15810Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
15820Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	return (rv);
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate /* ARGSUSED */
15880Sstevel@tonic-gate static int
rsa_verify_recover_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * signature,crypto_data_t * data,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)15890Sstevel@tonic-gate rsa_verify_recover_atomic(crypto_provider_handle_t provider,
15900Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
15910Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
15920Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
15930Sstevel@tonic-gate {
15940Sstevel@tonic-gate 	int rv;
15950Sstevel@tonic-gate 
15960Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
15970Sstevel@tonic-gate 		return (rv);
15980Sstevel@tonic-gate 
15990Sstevel@tonic-gate 	return (rsa_verify_recover_common(mechanism->cm_type, key,
1600*12573SDina.Nimeh@Sun.COM 	    signature, data));
16010Sstevel@tonic-gate }
160210500SHai-May.Chao@Sun.COM 
160310500SHai-May.Chao@Sun.COM /*
1604*12573SDina.Nimeh@Sun.COM  * RSA Power-On Self-Test
160510500SHai-May.Chao@Sun.COM  */
160610500SHai-May.Chao@Sun.COM void
rsa_POST(int * rc)160710500SHai-May.Chao@Sun.COM rsa_POST(int *rc)
160810500SHai-May.Chao@Sun.COM {
160910500SHai-May.Chao@Sun.COM 
161010500SHai-May.Chao@Sun.COM 	*rc = fips_rsa_post();
161110500SHai-May.Chao@Sun.COM 
161210500SHai-May.Chao@Sun.COM }
1613