xref: /onnv-gate/usr/src/uts/common/crypto/io/rsa.c (revision 6557:c6c4f66aed66)
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  */
210Sstevel@tonic-gate /*
22*6557Sfr41279  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * RSA provider for the Kernel Cryptographic Framework (KCF)
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/systm.h>
340Sstevel@tonic-gate #include <sys/modctl.h>
350Sstevel@tonic-gate #include <sys/cmn_err.h>
360Sstevel@tonic-gate #include <sys/ddi.h>
370Sstevel@tonic-gate #include <sys/crypto/spi.h>
380Sstevel@tonic-gate #include <sys/sysmacros.h>
390Sstevel@tonic-gate #include <sys/strsun.h>
400Sstevel@tonic-gate #include <sys/md5.h>
410Sstevel@tonic-gate #include <sys/sha1.h>
42676Sizick #include <sys/sha2.h>
430Sstevel@tonic-gate #include <sys/random.h>
440Sstevel@tonic-gate #include "rsa_impl.h"
450Sstevel@tonic-gate 
460Sstevel@tonic-gate extern struct mod_ops mod_cryptoops;
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate  * Module linkage information for the kernel.
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate static struct modlcrypto modlcrypto = {
520Sstevel@tonic-gate 	&mod_cryptoops,
535072Smcpowers 	"RSA Kernel SW Provider"
540Sstevel@tonic-gate };
550Sstevel@tonic-gate 
560Sstevel@tonic-gate static struct modlinkage modlinkage = {
570Sstevel@tonic-gate 	MODREV_1,
580Sstevel@tonic-gate 	(void *)&modlcrypto,
590Sstevel@tonic-gate 	NULL
600Sstevel@tonic-gate };
610Sstevel@tonic-gate 
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate  * CSPI information (entry points, provider info, etc.)
640Sstevel@tonic-gate  */
650Sstevel@tonic-gate typedef enum rsa_mech_type {
660Sstevel@tonic-gate 	RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_RSA_PKCS */
670Sstevel@tonic-gate 	RSA_X_509_MECH_INFO_TYPE,	/* SUN_CKM_RSA_X_509 */
680Sstevel@tonic-gate 	MD5_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_MD5_RSA_PKCS */
69676Sizick 	SHA1_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA1_RSA_PKCS */
70676Sizick 	SHA256_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA256_RSA_PKCS */
71676Sizick 	SHA384_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA384_RSA_PKCS */
72676Sizick 	SHA512_RSA_PKCS_MECH_INFO_TYPE	/* SUN_SHA512_RSA_PKCS */
730Sstevel@tonic-gate } rsa_mech_type_t;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate  * Context for RSA_PKCS and RSA_X_509 mechanisms.
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate typedef struct rsa_ctx {
790Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
800Sstevel@tonic-gate 	crypto_key_t *key;
810Sstevel@tonic-gate 	size_t keychunk_size;
820Sstevel@tonic-gate } rsa_ctx_t;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*
85676Sizick  * Context for MD5_RSA_PKCS and SHA*_RSA_PKCS mechanisms.
860Sstevel@tonic-gate  */
870Sstevel@tonic-gate typedef struct digest_rsa_ctx {
880Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
890Sstevel@tonic-gate 	crypto_key_t *key;
900Sstevel@tonic-gate 	size_t keychunk_size;
910Sstevel@tonic-gate 	union {
920Sstevel@tonic-gate 		MD5_CTX md5ctx;
930Sstevel@tonic-gate 		SHA1_CTX sha1ctx;
94676Sizick 		SHA2_CTX sha2ctx;
950Sstevel@tonic-gate 	} dctx_u;
960Sstevel@tonic-gate } digest_rsa_ctx_t;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate #define	md5_ctx		dctx_u.md5ctx
990Sstevel@tonic-gate #define	sha1_ctx	dctx_u.sha1ctx
100676Sizick #define	sha2_ctx	dctx_u.sha2ctx
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate  * Mechanism info structure passed to KCF during registration.
1040Sstevel@tonic-gate  */
1050Sstevel@tonic-gate static crypto_mech_info_t rsa_mech_info_tab[] = {
1060Sstevel@tonic-gate 	/* RSA_PKCS */
1070Sstevel@tonic-gate 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
1080Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1090Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1100Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1110Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
1120Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1130Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
1140Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	/* RSA_X_509 */
1170Sstevel@tonic-gate 	{SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
1180Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1190Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1200Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1210Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
1220Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1230Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
1240Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	/* MD5_RSA_PKCS */
1270Sstevel@tonic-gate 	{SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE,
1280Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1290Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1300Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	/* SHA1_RSA_PKCS */
1330Sstevel@tonic-gate 	{SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE,
1340Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1350Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
136676Sizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
137676Sizick 
138676Sizick 	/* SHA256_RSA_PKCS */
139676Sizick 	{SUN_CKM_SHA256_RSA_PKCS, SHA256_RSA_PKCS_MECH_INFO_TYPE,
140676Sizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
141676Sizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
142676Sizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
143676Sizick 
144676Sizick 	/* SHA384_RSA_PKCS */
145676Sizick 	{SUN_CKM_SHA384_RSA_PKCS, SHA384_RSA_PKCS_MECH_INFO_TYPE,
146676Sizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
147676Sizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
148676Sizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
149676Sizick 
150676Sizick 	/* SHA512_RSA_PKCS */
151676Sizick 	{SUN_CKM_SHA512_RSA_PKCS, SHA512_RSA_PKCS_MECH_INFO_TYPE,
152676Sizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
153676Sizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1540Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}
155676Sizick 
1560Sstevel@tonic-gate };
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate #define	RSA_VALID_MECH(mech)					\
1590Sstevel@tonic-gate 	(((mech)->cm_type == RSA_PKCS_MECH_INFO_TYPE ||		\
1600Sstevel@tonic-gate 	(mech)->cm_type == RSA_X_509_MECH_INFO_TYPE ||		\
1610Sstevel@tonic-gate 	(mech)->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||	\
162676Sizick 	(mech)->cm_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||	\
163676Sizick 	(mech)->cm_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||	\
164676Sizick 	(mech)->cm_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||	\
165676Sizick 	(mech)->cm_type == SHA512_RSA_PKCS_MECH_INFO_TYPE) ? 1 : 0)
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */
1680Sstevel@tonic-gate #define	RSA_ARG_INPLACE(input, output)				\
1690Sstevel@tonic-gate 	if ((output) == NULL)					\
1700Sstevel@tonic-gate 		(output) = (input);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate static void rsa_provider_status(crypto_provider_handle_t, uint_t *);
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate static crypto_control_ops_t rsa_control_ops = {
1750Sstevel@tonic-gate 	rsa_provider_status
1760Sstevel@tonic-gate };
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate static int rsa_common_init(crypto_ctx_t *, crypto_mechanism_t *,
1790Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1800Sstevel@tonic-gate static int rsa_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1810Sstevel@tonic-gate     crypto_req_handle_t);
1820Sstevel@tonic-gate static int rsa_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1830Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1840Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1850Sstevel@tonic-gate static int rsa_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1860Sstevel@tonic-gate     crypto_req_handle_t);
1870Sstevel@tonic-gate static int rsa_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1880Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1890Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate  * The RSA mechanisms do not have multiple-part cipher operations.
1930Sstevel@tonic-gate  * So, the update and final routines are set to NULL.
1940Sstevel@tonic-gate  */
1950Sstevel@tonic-gate static crypto_cipher_ops_t rsa_cipher_ops = {
1960Sstevel@tonic-gate 	rsa_common_init,
1970Sstevel@tonic-gate 	rsa_encrypt,
1980Sstevel@tonic-gate 	NULL,
1990Sstevel@tonic-gate 	NULL,
2000Sstevel@tonic-gate 	rsa_encrypt_atomic,
2010Sstevel@tonic-gate 	rsa_common_init,
2020Sstevel@tonic-gate 	rsa_decrypt,
2030Sstevel@tonic-gate 	NULL,
2040Sstevel@tonic-gate 	NULL,
2050Sstevel@tonic-gate 	rsa_decrypt_atomic
2060Sstevel@tonic-gate };
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate static int rsa_sign_verify_common_init(crypto_ctx_t *, crypto_mechanism_t *,
2090Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
2100Sstevel@tonic-gate static int rsa_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
2110Sstevel@tonic-gate     crypto_req_handle_t);
2120Sstevel@tonic-gate static int rsa_sign_update(crypto_ctx_t *, crypto_data_t *,
2130Sstevel@tonic-gate     crypto_req_handle_t);
2140Sstevel@tonic-gate static int rsa_sign_final(crypto_ctx_t *, crypto_data_t *,
2150Sstevel@tonic-gate     crypto_req_handle_t);
2160Sstevel@tonic-gate static int rsa_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
2170Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
2180Sstevel@tonic-gate     crypto_spi_ctx_template_t, crypto_req_handle_t);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate  * We use the same routine for sign_init and sign_recover_init fields
2220Sstevel@tonic-gate  * as they do the same thing. Same holds for sign and sign_recover fields,
2230Sstevel@tonic-gate  * and sign_atomic and sign_recover_atomic fields.
2240Sstevel@tonic-gate  */
2250Sstevel@tonic-gate static crypto_sign_ops_t rsa_sign_ops = {
2260Sstevel@tonic-gate 	rsa_sign_verify_common_init,
2270Sstevel@tonic-gate 	rsa_sign,
2280Sstevel@tonic-gate 	rsa_sign_update,
2290Sstevel@tonic-gate 	rsa_sign_final,
2300Sstevel@tonic-gate 	rsa_sign_atomic,
2310Sstevel@tonic-gate 	rsa_sign_verify_common_init,
2320Sstevel@tonic-gate 	rsa_sign,
2330Sstevel@tonic-gate 	rsa_sign_atomic
2340Sstevel@tonic-gate };
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate static int rsa_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
2370Sstevel@tonic-gate     crypto_req_handle_t);
2380Sstevel@tonic-gate static int rsa_verify_update(crypto_ctx_t *, crypto_data_t *,
2390Sstevel@tonic-gate     crypto_req_handle_t);
2400Sstevel@tonic-gate static int rsa_verify_final(crypto_ctx_t *, crypto_data_t *,
2410Sstevel@tonic-gate     crypto_req_handle_t);
2420Sstevel@tonic-gate static int rsa_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
2430Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
2440Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
2450Sstevel@tonic-gate static int rsa_verify_recover(crypto_ctx_t *, crypto_data_t *,
2460Sstevel@tonic-gate     crypto_data_t *, crypto_req_handle_t);
2470Sstevel@tonic-gate static int rsa_verify_recover_atomic(crypto_provider_handle_t,
2480Sstevel@tonic-gate     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2490Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
2500Sstevel@tonic-gate     crypto_req_handle_t);
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate  * We use the same routine (rsa_sign_verify_common_init) for verify_init
2540Sstevel@tonic-gate  * and verify_recover_init fields as they do the same thing.
2550Sstevel@tonic-gate  */
2560Sstevel@tonic-gate static crypto_verify_ops_t rsa_verify_ops = {
2570Sstevel@tonic-gate 	rsa_sign_verify_common_init,
2580Sstevel@tonic-gate 	rsa_verify,
2590Sstevel@tonic-gate 	rsa_verify_update,
2600Sstevel@tonic-gate 	rsa_verify_final,
2610Sstevel@tonic-gate 	rsa_verify_atomic,
2620Sstevel@tonic-gate 	rsa_sign_verify_common_init,
2630Sstevel@tonic-gate 	rsa_verify_recover,
2640Sstevel@tonic-gate 	rsa_verify_recover_atomic
2650Sstevel@tonic-gate };
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate static int rsa_free_context(crypto_ctx_t *);
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate static crypto_ctx_ops_t rsa_ctx_ops = {
2700Sstevel@tonic-gate 	NULL,
2710Sstevel@tonic-gate 	rsa_free_context
2720Sstevel@tonic-gate };
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate static crypto_ops_t rsa_crypto_ops = {
2750Sstevel@tonic-gate 	&rsa_control_ops,
2760Sstevel@tonic-gate 	NULL,
2770Sstevel@tonic-gate 	&rsa_cipher_ops,
2780Sstevel@tonic-gate 	NULL,
2790Sstevel@tonic-gate 	&rsa_sign_ops,
2800Sstevel@tonic-gate 	&rsa_verify_ops,
2810Sstevel@tonic-gate 	NULL,
2820Sstevel@tonic-gate 	NULL,
2830Sstevel@tonic-gate 	NULL,
2840Sstevel@tonic-gate 	NULL,
2850Sstevel@tonic-gate 	NULL,
2860Sstevel@tonic-gate 	NULL,
2870Sstevel@tonic-gate 	NULL,
2880Sstevel@tonic-gate 	&rsa_ctx_ops
2890Sstevel@tonic-gate };
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate static crypto_provider_info_t rsa_prov_info = {
2920Sstevel@tonic-gate 	CRYPTO_SPI_VERSION_1,
2930Sstevel@tonic-gate 	"RSA Software Provider",
2940Sstevel@tonic-gate 	CRYPTO_SW_PROVIDER,
2950Sstevel@tonic-gate 	{&modlinkage},
2960Sstevel@tonic-gate 	NULL,
2970Sstevel@tonic-gate 	&rsa_crypto_ops,
2980Sstevel@tonic-gate 	sizeof (rsa_mech_info_tab)/sizeof (crypto_mech_info_t),
2990Sstevel@tonic-gate 	rsa_mech_info_tab
3000Sstevel@tonic-gate };
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate static int rsa_encrypt_common(rsa_mech_type_t, crypto_key_t *,
3030Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
3040Sstevel@tonic-gate static int rsa_decrypt_common(rsa_mech_type_t, crypto_key_t *,
3050Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
3060Sstevel@tonic-gate static int rsa_sign_common(rsa_mech_type_t, crypto_key_t *,
3070Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
3080Sstevel@tonic-gate static int rsa_verify_common(rsa_mech_type_t, crypto_key_t *,
3090Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, int);
3100Sstevel@tonic-gate static int compare_data(crypto_data_t *, uchar_t *);
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate /* EXPORT DELETE START */
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate static int core_rsa_encrypt(crypto_key_t *, uchar_t *,
3150Sstevel@tonic-gate     int, uchar_t *, int, int);
3160Sstevel@tonic-gate static int core_rsa_decrypt(crypto_key_t *, uchar_t *, int,
3170Sstevel@tonic-gate     uchar_t *, int);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate /* EXPORT DELETE END */
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate static crypto_kcf_provider_handle_t rsa_prov_handle = NULL;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate int
3240Sstevel@tonic-gate _init(void)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate 	int ret;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	/*
3290Sstevel@tonic-gate 	 * Register with KCF. If the registration fails, return error.
3300Sstevel@tonic-gate 	 */
3310Sstevel@tonic-gate 	if ((ret = crypto_register_provider(&rsa_prov_info,
3320Sstevel@tonic-gate 	    &rsa_prov_handle)) != CRYPTO_SUCCESS) {
3330Sstevel@tonic-gate 		cmn_err(CE_WARN, "rsa _init: crypto_register_provider()"
3340Sstevel@tonic-gate 		    "failed (0x%x)", ret);
3350Sstevel@tonic-gate 		return (EACCES);
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if ((ret = mod_install(&modlinkage)) != 0) {
3390Sstevel@tonic-gate 		int rv;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 		ASSERT(rsa_prov_handle != NULL);
3420Sstevel@tonic-gate 		/* We should not return if the unregister returns busy. */
3430Sstevel@tonic-gate 		while ((rv = crypto_unregister_provider(rsa_prov_handle))
3440Sstevel@tonic-gate 		    == CRYPTO_BUSY) {
3450Sstevel@tonic-gate 			cmn_err(CE_WARN, "rsa _init: "
3460Sstevel@tonic-gate 			    "crypto_unregister_provider() "
3470Sstevel@tonic-gate 			    "failed (0x%x). Retrying.", rv);
3480Sstevel@tonic-gate 			/* wait 10 seconds and try again. */
3490Sstevel@tonic-gate 			delay(10 * drv_usectohz(1000000));
3500Sstevel@tonic-gate 		}
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	return (ret);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate int
3570Sstevel@tonic-gate _fini(void)
3580Sstevel@tonic-gate {
3590Sstevel@tonic-gate 	int ret;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	/*
3620Sstevel@tonic-gate 	 * Unregister from KCF if previous registration succeeded.
3630Sstevel@tonic-gate 	 */
3640Sstevel@tonic-gate 	if (rsa_prov_handle != NULL) {
3650Sstevel@tonic-gate 		if ((ret = crypto_unregister_provider(rsa_prov_handle)) !=
3660Sstevel@tonic-gate 		    CRYPTO_SUCCESS) {
3670Sstevel@tonic-gate 			cmn_err(CE_WARN, "rsa _fini: "
3680Sstevel@tonic-gate 			    "crypto_unregister_provider() "
3690Sstevel@tonic-gate 			    "failed (0x%x)", ret);
3700Sstevel@tonic-gate 			return (EBUSY);
3710Sstevel@tonic-gate 		}
3720Sstevel@tonic-gate 		rsa_prov_handle = NULL;
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate int
3790Sstevel@tonic-gate _info(struct modinfo *modinfop)
3800Sstevel@tonic-gate {
3810Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate /* ARGSUSED */
3850Sstevel@tonic-gate static void
3860Sstevel@tonic-gate rsa_provider_status(crypto_provider_handle_t provider, uint_t *status)
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate 	*status = CRYPTO_PROVIDER_READY;
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate /*
3920Sstevel@tonic-gate  * Utility routine to look up a attribute of type, 'type',
3930Sstevel@tonic-gate  * in the key.
3940Sstevel@tonic-gate  */
3950Sstevel@tonic-gate static int
3960Sstevel@tonic-gate get_key_attr(crypto_key_t *key, crypto_attr_type_t type,
3970Sstevel@tonic-gate     uchar_t **value, ssize_t *value_len)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate 	int i;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
4020Sstevel@tonic-gate 	for (i = 0; i < key->ck_count; i++) {
4030Sstevel@tonic-gate 		if (key->ck_attrs[i].oa_type == type) {
4040Sstevel@tonic-gate 			*value = (uchar_t *)key->ck_attrs[i].oa_value;
4050Sstevel@tonic-gate 			*value_len = key->ck_attrs[i].oa_value_len;
4060Sstevel@tonic-gate 			return (CRYPTO_SUCCESS);
4070Sstevel@tonic-gate 		}
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	return (CRYPTO_FAILED);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate static int
4140Sstevel@tonic-gate check_mech_and_key(crypto_mechanism_t *mechanism, crypto_key_t *key)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate /* EXPORT DELETE START */
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	uchar_t *modulus;
4210Sstevel@tonic-gate 	ssize_t modulus_len; /* In bytes */
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	if (!RSA_VALID_MECH(mechanism))
4240Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	/*
4270Sstevel@tonic-gate 	 * We only support RSA keys that are passed as a list of
4280Sstevel@tonic-gate 	 * object attributes.
4290Sstevel@tonic-gate 	 */
4300Sstevel@tonic-gate 	if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
4310Sstevel@tonic-gate 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
4320Sstevel@tonic-gate 	}
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
4350Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
4360Sstevel@tonic-gate 		return (rv);
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 	if (modulus_len < MIN_RSA_KEYLENGTH_IN_BYTES ||
4390Sstevel@tonic-gate 	    modulus_len > MAX_RSA_KEYLENGTH_IN_BYTES)
4400Sstevel@tonic-gate 		return (CRYPTO_KEY_SIZE_RANGE);
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate /* EXPORT DELETE END */
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	return (rv);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate void
4480Sstevel@tonic-gate kmemset(uint8_t *buf, char pattern, size_t len)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate 	int i = 0;
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	while (i < len)
4530Sstevel@tonic-gate 		buf[i++] = pattern;
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate  * This function guarantees to return non-zero random numbers.
4580Sstevel@tonic-gate  * This is needed as the /dev/urandom kernel interface,
4590Sstevel@tonic-gate  * random_get_pseudo_bytes(), may return zeros.
4600Sstevel@tonic-gate  */
4610Sstevel@tonic-gate int
4620Sstevel@tonic-gate knzero_random_generator(uint8_t *ran_out, size_t ran_len)
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate 	int rv;
4650Sstevel@tonic-gate 	size_t ebc = 0; /* count of extra bytes in extrarand */
4660Sstevel@tonic-gate 	size_t i = 0;
4670Sstevel@tonic-gate 	uint8_t extrarand[32];
4680Sstevel@tonic-gate 	size_t extrarand_len;
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0)
4710Sstevel@tonic-gate 		return (rv);
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	/*
4740Sstevel@tonic-gate 	 * Walk through the returned random numbers pointed by ran_out,
4750Sstevel@tonic-gate 	 * and look for any random number which is zero.
4760Sstevel@tonic-gate 	 * If we find zero, call random_get_pseudo_bytes() to generate
4770Sstevel@tonic-gate 	 * another 32 random numbers pool. Replace any zeros in ran_out[]
4780Sstevel@tonic-gate 	 * from the random number in pool.
4790Sstevel@tonic-gate 	 */
4800Sstevel@tonic-gate 	while (i < ran_len) {
4810Sstevel@tonic-gate 		if (ran_out[i] != 0) {
4820Sstevel@tonic-gate 			i++;
4830Sstevel@tonic-gate 			continue;
4840Sstevel@tonic-gate 		}
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 		/*
4870Sstevel@tonic-gate 		 * Note that it is 'while' so we are guaranteed a
4880Sstevel@tonic-gate 		 * non-zero value on exit.
4890Sstevel@tonic-gate 		 */
4900Sstevel@tonic-gate 		if (ebc == 0) {
4910Sstevel@tonic-gate 			/* refresh extrarand */
4920Sstevel@tonic-gate 			extrarand_len = sizeof (extrarand);
4930Sstevel@tonic-gate 			if ((rv = random_get_pseudo_bytes(extrarand,
4940Sstevel@tonic-gate 			    extrarand_len)) != 0) {
4950Sstevel@tonic-gate 				return (rv);
4960Sstevel@tonic-gate 			}
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 			ebc = extrarand_len;
4990Sstevel@tonic-gate 		}
5000Sstevel@tonic-gate 		/* Replace zero with byte from extrarand. */
5010Sstevel@tonic-gate 		-- ebc;
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 		/*
5040Sstevel@tonic-gate 		 * The new random byte zero/non-zero will be checked in
5050Sstevel@tonic-gate 		 * the next pass through the loop.
5060Sstevel@tonic-gate 		 */
5070Sstevel@tonic-gate 		ran_out[i] = extrarand[ebc];
5080Sstevel@tonic-gate 	}
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate typedef enum cmd_type {
5140Sstevel@tonic-gate 	COPY_FROM_DATA,
5150Sstevel@tonic-gate 	COPY_TO_DATA,
5160Sstevel@tonic-gate 	COMPARE_TO_DATA,
5170Sstevel@tonic-gate 	MD5_DIGEST_DATA,
518676Sizick 	SHA1_DIGEST_DATA,
519676Sizick 	SHA2_DIGEST_DATA
5200Sstevel@tonic-gate } cmd_type_t;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate /*
5230Sstevel@tonic-gate  * Utility routine to apply the command, 'cmd', to the
5240Sstevel@tonic-gate  * data in the uio structure.
5250Sstevel@tonic-gate  */
5260Sstevel@tonic-gate static int
5270Sstevel@tonic-gate process_uio_data(crypto_data_t *data, uchar_t *buf, int len,
5280Sstevel@tonic-gate     cmd_type_t cmd, void *digest_ctx)
5290Sstevel@tonic-gate {
5300Sstevel@tonic-gate 	uio_t *uiop = data->cd_uio;
5310Sstevel@tonic-gate 	off_t offset = data->cd_offset;
5320Sstevel@tonic-gate 	size_t length = len;
5330Sstevel@tonic-gate 	uint_t vec_idx;
5340Sstevel@tonic-gate 	size_t cur_len;
5350Sstevel@tonic-gate 	uchar_t *datap;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	ASSERT(data->cd_format == CRYPTO_DATA_UIO);
5380Sstevel@tonic-gate 	if (uiop->uio_segflg != UIO_SYSSPACE) {
5390Sstevel@tonic-gate 		return (CRYPTO_ARGUMENTS_BAD);
5400Sstevel@tonic-gate 	}
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	/*
5430Sstevel@tonic-gate 	 * Jump to the first iovec containing data to be
5440Sstevel@tonic-gate 	 * processed.
5450Sstevel@tonic-gate 	 */
5460Sstevel@tonic-gate 	for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
5470Sstevel@tonic-gate 	    offset >= uiop->uio_iov[vec_idx].iov_len;
5485072Smcpowers 	    offset -= uiop->uio_iov[vec_idx++].iov_len)
5495072Smcpowers 		;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	if (vec_idx == uiop->uio_iovcnt) {
5520Sstevel@tonic-gate 		/*
5530Sstevel@tonic-gate 		 * The caller specified an offset that is larger than
5540Sstevel@tonic-gate 		 * the total size of the buffers it provided.
5550Sstevel@tonic-gate 		 */
5560Sstevel@tonic-gate 		return (CRYPTO_DATA_LEN_RANGE);
5570Sstevel@tonic-gate 	}
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	while (vec_idx < uiop->uio_iovcnt && length > 0) {
5600Sstevel@tonic-gate 		cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
5610Sstevel@tonic-gate 		    offset, length);
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 		datap = (uchar_t *)(uiop->uio_iov[vec_idx].iov_base +
5640Sstevel@tonic-gate 		    offset);
5650Sstevel@tonic-gate 		switch (cmd) {
5660Sstevel@tonic-gate 		case COPY_FROM_DATA:
5670Sstevel@tonic-gate 			bcopy(datap, buf, cur_len);
5680Sstevel@tonic-gate 			buf += cur_len;
5690Sstevel@tonic-gate 			break;
5700Sstevel@tonic-gate 		case COPY_TO_DATA:
5710Sstevel@tonic-gate 			bcopy(buf, datap, cur_len);
5720Sstevel@tonic-gate 			buf += cur_len;
5730Sstevel@tonic-gate 			break;
5740Sstevel@tonic-gate 		case COMPARE_TO_DATA:
5750Sstevel@tonic-gate 			if (bcmp(datap, buf, cur_len))
5760Sstevel@tonic-gate 				return (CRYPTO_SIGNATURE_INVALID);
5770Sstevel@tonic-gate 			buf += cur_len;
5780Sstevel@tonic-gate 			break;
5790Sstevel@tonic-gate 		case MD5_DIGEST_DATA:
5800Sstevel@tonic-gate 			MD5Update(digest_ctx, datap, cur_len);
5810Sstevel@tonic-gate 			break;
5820Sstevel@tonic-gate 		case SHA1_DIGEST_DATA:
5830Sstevel@tonic-gate 			SHA1Update(digest_ctx, datap, cur_len);
5840Sstevel@tonic-gate 			break;
585676Sizick 		case SHA2_DIGEST_DATA:
586676Sizick 			SHA2Update(digest_ctx, datap, cur_len);
587676Sizick 			break;
5880Sstevel@tonic-gate 		}
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 		length -= cur_len;
5910Sstevel@tonic-gate 		vec_idx++;
5920Sstevel@tonic-gate 		offset = 0;
5930Sstevel@tonic-gate 	}
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
5960Sstevel@tonic-gate 		/*
5970Sstevel@tonic-gate 		 * The end of the specified iovec's was reached but
5980Sstevel@tonic-gate 		 * the length requested could not be processed.
5990Sstevel@tonic-gate 		 */
6000Sstevel@tonic-gate 		switch (cmd) {
6010Sstevel@tonic-gate 		case COPY_TO_DATA:
6020Sstevel@tonic-gate 			data->cd_length = len;
6030Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
6040Sstevel@tonic-gate 		default:
6050Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
6060Sstevel@tonic-gate 		}
6070Sstevel@tonic-gate 	}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate /*
6130Sstevel@tonic-gate  * Utility routine to apply the command, 'cmd', to the
6140Sstevel@tonic-gate  * data in the mblk structure.
6150Sstevel@tonic-gate  */
6160Sstevel@tonic-gate static int
6170Sstevel@tonic-gate process_mblk_data(crypto_data_t *data, uchar_t *buf, int len,
6180Sstevel@tonic-gate     cmd_type_t cmd, void *digest_ctx)
6190Sstevel@tonic-gate {
6200Sstevel@tonic-gate 	off_t offset = data->cd_offset;
6210Sstevel@tonic-gate 	size_t length = len;
6220Sstevel@tonic-gate 	mblk_t *mp;
6230Sstevel@tonic-gate 	size_t cur_len;
6240Sstevel@tonic-gate 	uchar_t *datap;
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	ASSERT(data->cd_format == CRYPTO_DATA_MBLK);
6270Sstevel@tonic-gate 	/*
6280Sstevel@tonic-gate 	 * Jump to the first mblk_t containing data to be processed.
6290Sstevel@tonic-gate 	 */
6300Sstevel@tonic-gate 	for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
6315072Smcpowers 	    offset -= MBLKL(mp), mp = mp->b_cont)
6325072Smcpowers 		;
6330Sstevel@tonic-gate 	if (mp == NULL) {
6340Sstevel@tonic-gate 		/*
6350Sstevel@tonic-gate 		 * The caller specified an offset that is larger
6360Sstevel@tonic-gate 		 * than the total size of the buffers it provided.
6370Sstevel@tonic-gate 		 */
6380Sstevel@tonic-gate 		return (CRYPTO_DATA_LEN_RANGE);
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	/*
6420Sstevel@tonic-gate 	 * Now do the processing on the mblk chain.
6430Sstevel@tonic-gate 	 */
6440Sstevel@tonic-gate 	while (mp != NULL && length > 0) {
6450Sstevel@tonic-gate 		cur_len = MIN(MBLKL(mp) - offset, length);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		datap = (uchar_t *)(mp->b_rptr + offset);
6480Sstevel@tonic-gate 		switch (cmd) {
6490Sstevel@tonic-gate 		case COPY_FROM_DATA:
6500Sstevel@tonic-gate 			bcopy(datap, buf, cur_len);
6510Sstevel@tonic-gate 			buf += cur_len;
6520Sstevel@tonic-gate 			break;
6530Sstevel@tonic-gate 		case COPY_TO_DATA:
6540Sstevel@tonic-gate 			bcopy(buf, datap, cur_len);
6550Sstevel@tonic-gate 			buf += cur_len;
6560Sstevel@tonic-gate 			break;
6570Sstevel@tonic-gate 		case COMPARE_TO_DATA:
6580Sstevel@tonic-gate 			if (bcmp(datap, buf, cur_len))
6590Sstevel@tonic-gate 				return (CRYPTO_SIGNATURE_INVALID);
6600Sstevel@tonic-gate 			buf += cur_len;
6610Sstevel@tonic-gate 			break;
6620Sstevel@tonic-gate 		case MD5_DIGEST_DATA:
6630Sstevel@tonic-gate 			MD5Update(digest_ctx, datap, cur_len);
6640Sstevel@tonic-gate 			break;
6650Sstevel@tonic-gate 		case SHA1_DIGEST_DATA:
6660Sstevel@tonic-gate 			SHA1Update(digest_ctx, datap, cur_len);
6670Sstevel@tonic-gate 			break;
668676Sizick 		case SHA2_DIGEST_DATA:
669676Sizick 			SHA2Update(digest_ctx, datap, cur_len);
670676Sizick 			break;
6710Sstevel@tonic-gate 		}
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 		length -= cur_len;
6740Sstevel@tonic-gate 		offset = 0;
6750Sstevel@tonic-gate 		mp = mp->b_cont;
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 	if (mp == NULL && length > 0) {
6790Sstevel@tonic-gate 		/*
6800Sstevel@tonic-gate 		 * The end of the mblk was reached but the length
6810Sstevel@tonic-gate 		 * requested could not be processed.
6820Sstevel@tonic-gate 		 */
6830Sstevel@tonic-gate 		switch (cmd) {
6840Sstevel@tonic-gate 		case COPY_TO_DATA:
6850Sstevel@tonic-gate 			data->cd_length = len;
6860Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
6870Sstevel@tonic-gate 		default:
6880Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
6890Sstevel@tonic-gate 		}
6900Sstevel@tonic-gate 	}
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate static int
6960Sstevel@tonic-gate compare_data(crypto_data_t *data, uchar_t *buf)
6970Sstevel@tonic-gate {
6980Sstevel@tonic-gate 	int len;
6990Sstevel@tonic-gate 	uchar_t *dptr;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	len = data->cd_length;
7020Sstevel@tonic-gate 	switch (data->cd_format) {
7030Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
7040Sstevel@tonic-gate 		dptr = (uchar_t *)(data->cd_raw.iov_base +
7050Sstevel@tonic-gate 		    data->cd_offset);
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 		return (bcmp(dptr, buf, len));
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
7100Sstevel@tonic-gate 		return (process_uio_data(data, buf, len,
7110Sstevel@tonic-gate 		    COMPARE_TO_DATA, NULL));
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
7140Sstevel@tonic-gate 		return (process_mblk_data(data, buf, len,
7150Sstevel@tonic-gate 		    COMPARE_TO_DATA, NULL));
7160Sstevel@tonic-gate 	}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	return (CRYPTO_FAILED);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate /*
7220Sstevel@tonic-gate  * Utility routine to copy a buffer to a crypto_data structure.
7230Sstevel@tonic-gate  */
7240Sstevel@tonic-gate static int
7250Sstevel@tonic-gate put_output_data(uchar_t *buf, crypto_data_t *output, int len)
7260Sstevel@tonic-gate {
7270Sstevel@tonic-gate 	switch (output->cd_format) {
7280Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
7290Sstevel@tonic-gate 		if (output->cd_raw.iov_len < len) {
7300Sstevel@tonic-gate 			output->cd_length = len;
7310Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
7320Sstevel@tonic-gate 		}
7330Sstevel@tonic-gate 		bcopy(buf, (uchar_t *)(output->cd_raw.iov_base +
7340Sstevel@tonic-gate 		    output->cd_offset), len);
7350Sstevel@tonic-gate 		break;
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
7380Sstevel@tonic-gate 		return (process_uio_data(output, buf, len, COPY_TO_DATA, NULL));
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
7410Sstevel@tonic-gate 		return (process_mblk_data(output, buf, len,
7420Sstevel@tonic-gate 		    COPY_TO_DATA, NULL));
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	default:
7450Sstevel@tonic-gate 		return (CRYPTO_ARGUMENTS_BAD);
7460Sstevel@tonic-gate 	}
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate /*
7520Sstevel@tonic-gate  * Utility routine to get data from a crypto_data structure.
7530Sstevel@tonic-gate  *
7540Sstevel@tonic-gate  * '*dptr' contains a pointer to a buffer on return. 'buf'
7550Sstevel@tonic-gate  * is allocated by the caller and is ignored for CRYPTO_DATA_RAW case.
7560Sstevel@tonic-gate  */
7570Sstevel@tonic-gate static int
7580Sstevel@tonic-gate get_input_data(crypto_data_t *input, uchar_t **dptr, uchar_t *buf)
7590Sstevel@tonic-gate {
7600Sstevel@tonic-gate 	int rv;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	switch (input->cd_format) {
7630Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
7640Sstevel@tonic-gate 		if (input->cd_raw.iov_len < input->cd_length)
7650Sstevel@tonic-gate 			return (CRYPTO_ARGUMENTS_BAD);
7660Sstevel@tonic-gate 		*dptr = (uchar_t *)(input->cd_raw.iov_base +
7670Sstevel@tonic-gate 		    input->cd_offset);
7680Sstevel@tonic-gate 		break;
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
7710Sstevel@tonic-gate 		if ((rv = process_uio_data(input, buf, input->cd_length,
7720Sstevel@tonic-gate 		    COPY_FROM_DATA, NULL)) != CRYPTO_SUCCESS)
7730Sstevel@tonic-gate 			return (rv);
7740Sstevel@tonic-gate 		*dptr = buf;
7750Sstevel@tonic-gate 		break;
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
7780Sstevel@tonic-gate 		if ((rv = process_mblk_data(input, buf, input->cd_length,
7790Sstevel@tonic-gate 		    COPY_FROM_DATA, NULL)) != CRYPTO_SUCCESS)
7800Sstevel@tonic-gate 			return (rv);
7810Sstevel@tonic-gate 		*dptr = buf;
7820Sstevel@tonic-gate 		break;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	default:
7850Sstevel@tonic-gate 		return (CRYPTO_ARGUMENTS_BAD);
7860Sstevel@tonic-gate 	}
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate static int
7920Sstevel@tonic-gate copy_key_to_ctx(crypto_key_t *in_key, rsa_ctx_t *ctx, int kmflag)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate 	int i, count;
7950Sstevel@tonic-gate 	size_t len;
7960Sstevel@tonic-gate 	caddr_t attr_val;
7970Sstevel@tonic-gate 	crypto_object_attribute_t *k_attrs = NULL;
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 	ASSERT(in_key->ck_format == CRYPTO_KEY_ATTR_LIST);
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 	count = in_key->ck_count;
8020Sstevel@tonic-gate 	/* figure out how much memory to allocate for everything */
8030Sstevel@tonic-gate 	len = sizeof (crypto_key_t) +
8040Sstevel@tonic-gate 	    count * sizeof (crypto_object_attribute_t);
8050Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
8060Sstevel@tonic-gate 		len += roundup(in_key->ck_attrs[i].oa_value_len,
8070Sstevel@tonic-gate 		    sizeof (caddr_t));
8080Sstevel@tonic-gate 	}
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	/* one big allocation for everything */
8110Sstevel@tonic-gate 	ctx->key = kmem_alloc(len, kmflag);
8120Sstevel@tonic-gate 	if (ctx->key == NULL)
8130Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
8140Sstevel@tonic-gate 	k_attrs = (crypto_object_attribute_t *)((caddr_t)(ctx->key) +
8150Sstevel@tonic-gate 	    sizeof (crypto_key_t));
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 	attr_val = (caddr_t)k_attrs +
8180Sstevel@tonic-gate 	    count * sizeof (crypto_object_attribute_t);
8190Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
8200Sstevel@tonic-gate 		k_attrs[i].oa_type = in_key->ck_attrs[i].oa_type;
8210Sstevel@tonic-gate 		bcopy(in_key->ck_attrs[i].oa_value, attr_val,
8220Sstevel@tonic-gate 		    in_key->ck_attrs[i].oa_value_len);
8230Sstevel@tonic-gate 		k_attrs[i].oa_value = attr_val;
8240Sstevel@tonic-gate 		k_attrs[i].oa_value_len = in_key->ck_attrs[i].oa_value_len;
8250Sstevel@tonic-gate 		attr_val += roundup(k_attrs[i].oa_value_len, sizeof (caddr_t));
8260Sstevel@tonic-gate 	}
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	ctx->keychunk_size = len;	/* save the size to be freed */
8290Sstevel@tonic-gate 	ctx->key->ck_format = CRYPTO_KEY_ATTR_LIST;
8300Sstevel@tonic-gate 	ctx->key->ck_count = count;
8310Sstevel@tonic-gate 	ctx->key->ck_attrs = k_attrs;
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate /* ARGSUSED */
8370Sstevel@tonic-gate static int
8380Sstevel@tonic-gate rsa_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
8390Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t template,
8400Sstevel@tonic-gate     crypto_req_handle_t req)
8410Sstevel@tonic-gate {
8420Sstevel@tonic-gate 	int rv;
8430Sstevel@tonic-gate 	int kmflag;
8440Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
8470Sstevel@tonic-gate 		return (rv);
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	/*
8500Sstevel@tonic-gate 	 * Allocate a RSA context.
8510Sstevel@tonic-gate 	 */
8520Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
8530Sstevel@tonic-gate 	if ((ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag)) == NULL)
8540Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	if ((rv = copy_key_to_ctx(key, ctxp, kmflag)) != CRYPTO_SUCCESS) {
8570Sstevel@tonic-gate 		kmem_free(ctxp, sizeof (rsa_ctx_t));
8580Sstevel@tonic-gate 		return (rv);
8590Sstevel@tonic-gate 	}
8600Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate /* ARGSUSED */
8680Sstevel@tonic-gate static int
8690Sstevel@tonic-gate rsa_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
8700Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_req_handle_t req)
8710Sstevel@tonic-gate {
8720Sstevel@tonic-gate 	int rv;
8730Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
8760Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	/*
8810Sstevel@tonic-gate 	 * Note on the KM_SLEEP flag passed to the routine below -
8820Sstevel@tonic-gate 	 * rsa_encrypt() is a single-part encryption routine which is
8830Sstevel@tonic-gate 	 * currently usable only by /dev/crypto. Since /dev/crypto calls are
8840Sstevel@tonic-gate 	 * always synchronous, we can safely pass KM_SLEEP here.
8850Sstevel@tonic-gate 	 */
8860Sstevel@tonic-gate 	rv = rsa_encrypt_common(ctxp->mech_type, ctxp->key, plaintext,
8870Sstevel@tonic-gate 	    ciphertext, KM_SLEEP);
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
8900Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
8910Sstevel@tonic-gate 
8920Sstevel@tonic-gate 	return (rv);
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate /* ARGSUSED */
8960Sstevel@tonic-gate static int
8970Sstevel@tonic-gate rsa_encrypt_atomic(crypto_provider_handle_t provider,
8980Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
8990Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
9000Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
9010Sstevel@tonic-gate {
9020Sstevel@tonic-gate 	int rv;
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
9050Sstevel@tonic-gate 		return (rv);
9060Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	return (rsa_encrypt_common(mechanism->cm_type, key, plaintext,
9090Sstevel@tonic-gate 	    ciphertext, crypto_kmflag(req)));
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate static int
9130Sstevel@tonic-gate rsa_free_context(crypto_ctx_t *ctx)
9140Sstevel@tonic-gate {
9150Sstevel@tonic-gate 	rsa_ctx_t *ctxp = ctx->cc_provider_private;
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	if (ctxp != NULL) {
9180Sstevel@tonic-gate 		bzero(ctxp->key, ctxp->keychunk_size);
9190Sstevel@tonic-gate 		kmem_free(ctxp->key, ctxp->keychunk_size);
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 		if (ctxp->mech_type == RSA_PKCS_MECH_INFO_TYPE ||
9220Sstevel@tonic-gate 		    ctxp->mech_type == RSA_X_509_MECH_INFO_TYPE)
9230Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
9240Sstevel@tonic-gate 		else
9250Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (digest_rsa_ctx_t));
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 		ctx->cc_provider_private = NULL;
9280Sstevel@tonic-gate 	}
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate static int
9340Sstevel@tonic-gate rsa_encrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
9350Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_data_t *ciphertext, int kmflag)
9360Sstevel@tonic-gate {
9370Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate /* EXPORT DELETE START */
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate 	int plen;
9420Sstevel@tonic-gate 	uchar_t *ptptr;
9430Sstevel@tonic-gate 	uchar_t *modulus;
9440Sstevel@tonic-gate 	ssize_t modulus_len;
9450Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
9460Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
9470Sstevel@tonic-gate 	uchar_t cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES];
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
9500Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
9510Sstevel@tonic-gate 		return (rv);
9520Sstevel@tonic-gate 	}
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate 	plen = plaintext->cd_length;
9550Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
9560Sstevel@tonic-gate 		if (plen > (modulus_len - MIN_PKCS1_PADLEN))
9570Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
9580Sstevel@tonic-gate 	} else {
9590Sstevel@tonic-gate 		if (plen > modulus_len)
9600Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
9610Sstevel@tonic-gate 	}
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	/*
9640Sstevel@tonic-gate 	 * Output buf len must not be less than RSA modulus size.
9650Sstevel@tonic-gate 	 */
9660Sstevel@tonic-gate 	if (ciphertext->cd_length < modulus_len) {
9670Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
9680Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
9690Sstevel@tonic-gate 	}
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 	ASSERT(plaintext->cd_length <= sizeof (tmp_data));
9720Sstevel@tonic-gate 	if ((rv = get_input_data(plaintext, &ptptr, tmp_data))
9730Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
9740Sstevel@tonic-gate 		return (rv);
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
9770Sstevel@tonic-gate 		rv = soft_encrypt_rsa_pkcs_encode(ptptr, plen,
9780Sstevel@tonic-gate 		    plain_data, modulus_len);
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
9810Sstevel@tonic-gate 			return (rv);
9820Sstevel@tonic-gate 	} else {
9830Sstevel@tonic-gate 		bzero(plain_data, modulus_len - plen);
9840Sstevel@tonic-gate 		bcopy(ptptr, &plain_data[modulus_len - plen], plen);
9850Sstevel@tonic-gate 	}
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 	rv = core_rsa_encrypt(key, plain_data, modulus_len,
9880Sstevel@tonic-gate 	    cipher_data, kmflag, 1);
9890Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
9900Sstevel@tonic-gate 		/* copy out to ciphertext */
9910Sstevel@tonic-gate 		if ((rv = put_output_data(cipher_data,
9920Sstevel@tonic-gate 		    ciphertext, modulus_len)) != CRYPTO_SUCCESS)
9930Sstevel@tonic-gate 			return (rv);
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
9960Sstevel@tonic-gate 	}
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate /* EXPORT DELETE END */
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 	return (rv);
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate /* EXPORT DELETE START */
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate static int
10060Sstevel@tonic-gate core_rsa_encrypt(crypto_key_t *key, uchar_t *in,
10070Sstevel@tonic-gate     int in_len, uchar_t *out, int kmflag, int is_public)
10080Sstevel@tonic-gate {
10090Sstevel@tonic-gate 	int rv;
10100Sstevel@tonic-gate 	uchar_t *expo, *modulus;
10110Sstevel@tonic-gate 	ssize_t	expo_len;
10120Sstevel@tonic-gate 	ssize_t modulus_len;
10130Sstevel@tonic-gate 	BIGNUM msg;
10140Sstevel@tonic-gate 	RSAkey *rsakey;
10150Sstevel@tonic-gate 
10160Sstevel@tonic-gate 	if (is_public) {
10170Sstevel@tonic-gate 		if ((rv = get_key_attr(key, SUN_CKA_PUBLIC_EXPONENT, &expo,
10180Sstevel@tonic-gate 		    &expo_len)) != CRYPTO_SUCCESS)
10190Sstevel@tonic-gate 			return (rv);
10200Sstevel@tonic-gate 	} else {
10210Sstevel@tonic-gate 		/*
10220Sstevel@tonic-gate 		 * SUN_CKA_PRIVATE_EXPONENT is a required attribute for a
10230Sstevel@tonic-gate 		 * RSA secret key. See the comments in core_rsa_decrypt
10240Sstevel@tonic-gate 		 * routine which calls this routine with a private key.
10250Sstevel@tonic-gate 		 */
10260Sstevel@tonic-gate 		if ((rv = get_key_attr(key, SUN_CKA_PRIVATE_EXPONENT, &expo,
10270Sstevel@tonic-gate 		    &expo_len)) != CRYPTO_SUCCESS)
10280Sstevel@tonic-gate 			return (rv);
10290Sstevel@tonic-gate 	}
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
10320Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
10330Sstevel@tonic-gate 		return (rv);
10340Sstevel@tonic-gate 	}
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	rsakey = kmem_alloc(sizeof (RSAkey), kmflag);
10370Sstevel@tonic-gate 	if (rsakey == NULL)
10380Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	/* psize and qsize for RSA_key_init is in bits. */
10410Sstevel@tonic-gate 	if (RSA_key_init(rsakey, modulus_len * 4, modulus_len * 4) != BIG_OK) {
10420Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
10430Sstevel@tonic-gate 		goto clean1;
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 
1046*6557Sfr41279 	/* Size for big_init is in BIG_CHUNK_TYPE words. */
1047*6557Sfr41279 	if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
10480Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
10490Sstevel@tonic-gate 		goto clean2;
10500Sstevel@tonic-gate 	}
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 	/* Convert octet string exponent to big integer format. */
10530Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->e), expo, expo_len);
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 	/* Convert octet string modulus to big integer format. */
10560Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->n), modulus, modulus_len);
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 	/* Convert octet string input data to big integer format. */
10590Sstevel@tonic-gate 	bytestring2bignum(&msg, in, in_len);
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	if (big_cmp_abs(&msg, &(rsakey->n)) > 0) {
10620Sstevel@tonic-gate 		rv = CRYPTO_DATA_LEN_RANGE;
10630Sstevel@tonic-gate 		goto clean3;
10640Sstevel@tonic-gate 	}
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	/* Perform RSA computation on big integer input data. */
10670Sstevel@tonic-gate 	if (big_modexp(&msg, &msg, &(rsakey->e), &(rsakey->n), NULL)
10680Sstevel@tonic-gate 	    != BIG_OK) {
10690Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
10700Sstevel@tonic-gate 		goto clean3;
10710Sstevel@tonic-gate 	}
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate 	/* Convert the big integer output data to octet string. */
10740Sstevel@tonic-gate 	bignum2bytestring(out, &msg, modulus_len);
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 	/*
10770Sstevel@tonic-gate 	 * Should not free modulus and expo as both are just pointers
10780Sstevel@tonic-gate 	 * to an attribute value buffer from the caller.
10790Sstevel@tonic-gate 	 */
10800Sstevel@tonic-gate clean3:
10810Sstevel@tonic-gate 	big_finish(&msg);
10820Sstevel@tonic-gate clean2:
10830Sstevel@tonic-gate 	RSA_key_finish(rsakey);
10840Sstevel@tonic-gate clean1:
10850Sstevel@tonic-gate 	kmem_free(rsakey, sizeof (RSAkey));
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	return (rv);
10880Sstevel@tonic-gate }
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate /* EXPORT DELETE END */
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate /* ARGSUSED */
10930Sstevel@tonic-gate static int
10940Sstevel@tonic-gate rsa_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
10950Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_req_handle_t req)
10960Sstevel@tonic-gate {
10970Sstevel@tonic-gate 	int rv;
10980Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
11010Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
11060Sstevel@tonic-gate 	rv = rsa_decrypt_common(ctxp->mech_type, ctxp->key,
11070Sstevel@tonic-gate 	    ciphertext, plaintext, KM_SLEEP);
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
11100Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
11110Sstevel@tonic-gate 
11120Sstevel@tonic-gate 	return (rv);
11130Sstevel@tonic-gate }
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate /* ARGSUSED */
11160Sstevel@tonic-gate static int
11170Sstevel@tonic-gate rsa_decrypt_atomic(crypto_provider_handle_t provider,
11180Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
11190Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
11200Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
11210Sstevel@tonic-gate {
11220Sstevel@tonic-gate 	int rv;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
11250Sstevel@tonic-gate 		return (rv);
11260Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	return (rsa_decrypt_common(mechanism->cm_type, key, ciphertext,
11290Sstevel@tonic-gate 	    plaintext, crypto_kmflag(req)));
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate static int
11330Sstevel@tonic-gate rsa_decrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
11340Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_data_t *plaintext, int kmflag)
11350Sstevel@tonic-gate {
11360Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate /* EXPORT DELETE START */
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate 	int plain_len;
11410Sstevel@tonic-gate 	uchar_t *ctptr;
11420Sstevel@tonic-gate 	uchar_t *modulus;
11430Sstevel@tonic-gate 	ssize_t modulus_len;
11440Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
11450Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
11480Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
11490Sstevel@tonic-gate 		return (rv);
11500Sstevel@tonic-gate 	}
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 	/*
11530Sstevel@tonic-gate 	 * Ciphertext length must be equal to RSA modulus size.
11540Sstevel@tonic-gate 	 */
11550Sstevel@tonic-gate 	if (ciphertext->cd_length != modulus_len)
11560Sstevel@tonic-gate 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
11570Sstevel@tonic-gate 
11580Sstevel@tonic-gate 	ASSERT(ciphertext->cd_length <= sizeof (tmp_data));
11590Sstevel@tonic-gate 	if ((rv = get_input_data(ciphertext, &ctptr, tmp_data))
11600Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
11610Sstevel@tonic-gate 		return (rv);
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 	rv = core_rsa_decrypt(key, ctptr, modulus_len, plain_data, kmflag);
11640Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
11650Sstevel@tonic-gate 		plain_len = modulus_len;
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 		if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
11680Sstevel@tonic-gate 			/* Strip off the PKCS block formatting data. */
11690Sstevel@tonic-gate 			rv = soft_decrypt_rsa_pkcs_decode(plain_data,
11700Sstevel@tonic-gate 			    &plain_len);
11710Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
11720Sstevel@tonic-gate 				return (rv);
11730Sstevel@tonic-gate 		}
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 		if (plain_len > plaintext->cd_length) {
11760Sstevel@tonic-gate 			plaintext->cd_length = plain_len;
11770Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
11780Sstevel@tonic-gate 		}
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate 		if ((rv = put_output_data(plain_data + modulus_len - plain_len,
11810Sstevel@tonic-gate 		    plaintext, plain_len)) != CRYPTO_SUCCESS)
11820Sstevel@tonic-gate 			return (rv);
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 		plaintext->cd_length = plain_len;
11850Sstevel@tonic-gate 	}
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate /* EXPORT DELETE END */
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	return (rv);
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate 
11920Sstevel@tonic-gate /* EXPORT DELETE START */
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate static int
11950Sstevel@tonic-gate core_rsa_decrypt(crypto_key_t *key, uchar_t *in, int in_len,
11960Sstevel@tonic-gate     uchar_t *out, int kmflag)
11970Sstevel@tonic-gate {
11980Sstevel@tonic-gate 	int rv;
11990Sstevel@tonic-gate 	uchar_t *modulus, *prime1, *prime2, *expo1, *expo2, *coef;
12000Sstevel@tonic-gate 	ssize_t modulus_len;
12010Sstevel@tonic-gate 	ssize_t	prime1_len, prime2_len;
12020Sstevel@tonic-gate 	ssize_t	expo1_len, expo2_len, coef_len;
12030Sstevel@tonic-gate 	BIGNUM msg;
12040Sstevel@tonic-gate 	RSAkey *rsakey;
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
12070Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
12080Sstevel@tonic-gate 		return (rv);
12090Sstevel@tonic-gate 	}
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 	/*
12120Sstevel@tonic-gate 	 * The following attributes are not required to be
12130Sstevel@tonic-gate 	 * present in a RSA secret key. If any of them is not present
12140Sstevel@tonic-gate 	 * we call the encrypt routine with a flag indicating use of
12150Sstevel@tonic-gate 	 * private exponent (d). Note that SUN_CKA_PRIVATE_EXPONENT is
12160Sstevel@tonic-gate 	 * a required attribute for a RSA secret key.
12170Sstevel@tonic-gate 	 */
12180Sstevel@tonic-gate 	if ((get_key_attr(key, SUN_CKA_PRIME_1, &prime1, &prime1_len)
12195072Smcpowers 	    != CRYPTO_SUCCESS) ||
12200Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_PRIME_2, &prime2, &prime2_len)
12215072Smcpowers 	    != CRYPTO_SUCCESS) ||
12220Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_EXPONENT_1, &expo1, &expo1_len)
12235072Smcpowers 	    != CRYPTO_SUCCESS) ||
12240Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_EXPONENT_2, &expo2, &expo2_len)
12255072Smcpowers 	    != CRYPTO_SUCCESS) ||
12260Sstevel@tonic-gate 	    (get_key_attr(key, SUN_CKA_COEFFICIENT, &coef, &coef_len)
12275072Smcpowers 	    != CRYPTO_SUCCESS)) {
12280Sstevel@tonic-gate 		return (core_rsa_encrypt(key, in, in_len, out, kmflag, 0));
12290Sstevel@tonic-gate 	}
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	rsakey = kmem_alloc(sizeof (RSAkey), kmflag);
12320Sstevel@tonic-gate 	if (rsakey == NULL)
12330Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	/* psize and qsize for RSA_key_init is in bits. */
12360Sstevel@tonic-gate 	if (RSA_key_init(rsakey, prime2_len * 8, prime1_len * 8) != BIG_OK) {
12370Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
12380Sstevel@tonic-gate 		goto clean1;
12390Sstevel@tonic-gate 	}
12400Sstevel@tonic-gate 
1241*6557Sfr41279 	/* Size for big_init is in BIG_CHUNK_TYPE words. */
1242*6557Sfr41279 	if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
12430Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
12440Sstevel@tonic-gate 		goto clean2;
12450Sstevel@tonic-gate 	}
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 	/* Convert octet string input data to big integer format. */
12480Sstevel@tonic-gate 	bytestring2bignum(&msg, in, in_len);
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	/* Convert octet string modulus to big integer format. */
12510Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->n), modulus, modulus_len);
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	if (big_cmp_abs(&msg, &(rsakey->n)) > 0) {
12540Sstevel@tonic-gate 		rv = CRYPTO_DATA_LEN_RANGE;
12550Sstevel@tonic-gate 		goto clean3;
12560Sstevel@tonic-gate 	}
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	/* Convert the rest of private key attributes to big integer format. */
12590Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->dmodpminus1), expo2, expo2_len);
12600Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->dmodqminus1), expo1, expo1_len);
12610Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->p), prime2, prime2_len);
12620Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->q), prime1, prime1_len);
12630Sstevel@tonic-gate 	bytestring2bignum(&(rsakey->pinvmodq), coef, coef_len);
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	if ((big_cmp_abs(&(rsakey->dmodpminus1), &(rsakey->p)) > 0) ||
12660Sstevel@tonic-gate 	    (big_cmp_abs(&(rsakey->dmodqminus1), &(rsakey->q)) > 0) ||
12670Sstevel@tonic-gate 	    (big_cmp_abs(&(rsakey->pinvmodq), &(rsakey->q)) > 0)) {
12680Sstevel@tonic-gate 		rv = CRYPTO_KEY_SIZE_RANGE;
12690Sstevel@tonic-gate 		goto clean3;
12700Sstevel@tonic-gate 	}
12710Sstevel@tonic-gate 
12720Sstevel@tonic-gate 	/* Perform RSA computation on big integer input data. */
12730Sstevel@tonic-gate 	if (big_modexp_crt(&msg, &msg, &(rsakey->dmodpminus1),
12740Sstevel@tonic-gate 	    &(rsakey->dmodqminus1), &(rsakey->p), &(rsakey->q),
12750Sstevel@tonic-gate 	    &(rsakey->pinvmodq), NULL, NULL) != BIG_OK) {
12760Sstevel@tonic-gate 		rv = CRYPTO_HOST_MEMORY;
12770Sstevel@tonic-gate 		goto clean3;
12780Sstevel@tonic-gate 	}
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 	/* Convert the big integer output data to octet string. */
12810Sstevel@tonic-gate 	bignum2bytestring(out, &msg, modulus_len);
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate 	/*
12840Sstevel@tonic-gate 	 * Should not free modulus and friends as they are just pointers
12850Sstevel@tonic-gate 	 * to an attribute value buffer from the caller.
12860Sstevel@tonic-gate 	 */
12870Sstevel@tonic-gate clean3:
12880Sstevel@tonic-gate 	big_finish(&msg);
12890Sstevel@tonic-gate clean2:
12900Sstevel@tonic-gate 	RSA_key_finish(rsakey);
12910Sstevel@tonic-gate clean1:
12920Sstevel@tonic-gate 	kmem_free(rsakey, sizeof (RSAkey));
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	return (rv);
12950Sstevel@tonic-gate }
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate /* EXPORT DELETE END */
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate /* ARGSUSED */
13000Sstevel@tonic-gate static int
13010Sstevel@tonic-gate rsa_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
13020Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
13030Sstevel@tonic-gate     crypto_req_handle_t req)
13040Sstevel@tonic-gate {
13050Sstevel@tonic-gate 	int rv;
13060Sstevel@tonic-gate 	int kmflag;
13070Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
13080Sstevel@tonic-gate 	digest_rsa_ctx_t *dctxp;
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
13110Sstevel@tonic-gate 		return (rv);
13120Sstevel@tonic-gate 
13130Sstevel@tonic-gate 	/*
13140Sstevel@tonic-gate 	 * Allocate a RSA context.
13150Sstevel@tonic-gate 	 */
13160Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
13170Sstevel@tonic-gate 	switch (mechanism->cm_type) {
13180Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
13190Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1320676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1321676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1322676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
13230Sstevel@tonic-gate 		dctxp = kmem_zalloc(sizeof (digest_rsa_ctx_t), kmflag);
13240Sstevel@tonic-gate 		ctxp = (rsa_ctx_t *)dctxp;
13250Sstevel@tonic-gate 		break;
13260Sstevel@tonic-gate 	default:
13270Sstevel@tonic-gate 		ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag);
13280Sstevel@tonic-gate 		break;
13290Sstevel@tonic-gate 	}
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 	if (ctxp == NULL)
13320Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
13330Sstevel@tonic-gate 
13340Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
13350Sstevel@tonic-gate 	if ((rv = copy_key_to_ctx(key, ctxp, kmflag)) != CRYPTO_SUCCESS) {
13360Sstevel@tonic-gate 		switch (mechanism->cm_type) {
13370Sstevel@tonic-gate 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
13380Sstevel@tonic-gate 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1339676Sizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1340676Sizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1341676Sizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
13420Sstevel@tonic-gate 			kmem_free(dctxp, sizeof (digest_rsa_ctx_t));
13430Sstevel@tonic-gate 			break;
13440Sstevel@tonic-gate 		default:
13450Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
13460Sstevel@tonic-gate 			break;
13470Sstevel@tonic-gate 		}
13480Sstevel@tonic-gate 		return (rv);
13490Sstevel@tonic-gate 	}
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	switch (mechanism->cm_type) {
13520Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
13530Sstevel@tonic-gate 		MD5Init(&(dctxp->md5_ctx));
13540Sstevel@tonic-gate 		break;
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
13570Sstevel@tonic-gate 		SHA1Init(&(dctxp->sha1_ctx));
13580Sstevel@tonic-gate 		break;
1359676Sizick 
1360676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1361676Sizick 		SHA2Init(SHA256, &(dctxp->sha2_ctx));
1362676Sizick 		break;
1363676Sizick 
1364676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1365676Sizick 		SHA2Init(SHA384, &(dctxp->sha2_ctx));
1366676Sizick 		break;
1367676Sizick 
1368676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1369676Sizick 		SHA2Init(SHA512, &(dctxp->sha2_ctx));
1370676Sizick 		break;
13710Sstevel@tonic-gate 	}
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate #define	SHA1_DIGEST_SIZE 20
13790Sstevel@tonic-gate #define	MD5_DIGEST_SIZE 16
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate #define	INIT_RAW_CRYPTO_DATA(data, base, len, cd_len)	\
13820Sstevel@tonic-gate 	(data).cd_format = CRYPTO_DATA_RAW;		\
13830Sstevel@tonic-gate 	(data).cd_offset = 0;				\
13840Sstevel@tonic-gate 	(data).cd_raw.iov_base = (char *)base;		\
13850Sstevel@tonic-gate 	(data).cd_raw.iov_len = len;			\
13860Sstevel@tonic-gate 	(data).cd_length = cd_len;
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate #define	DO_UPDATE	0x01
13890Sstevel@tonic-gate #define	DO_FINAL	0x02
13900Sstevel@tonic-gate #define	DO_MD5		0x04
13910Sstevel@tonic-gate #define	DO_SHA1		0x08
13920Sstevel@tonic-gate #define	DO_SIGN		0x10
13930Sstevel@tonic-gate #define	DO_VERIFY	0x20
1394676Sizick #define	DO_SHA2		0x40
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate static int
13970Sstevel@tonic-gate digest_data(crypto_data_t *data, void *dctx, uchar_t *digest,
13980Sstevel@tonic-gate     uchar_t flag)
13990Sstevel@tonic-gate {
14000Sstevel@tonic-gate 	int rv, dlen;
14010Sstevel@tonic-gate 	uchar_t *dptr;
14020Sstevel@tonic-gate 
1403676Sizick 	ASSERT(flag & DO_MD5 || flag & DO_SHA1 || flag & DO_SHA2);
14040Sstevel@tonic-gate 	if (data == NULL) {
14050Sstevel@tonic-gate 		ASSERT((flag & DO_UPDATE) == 0);
14060Sstevel@tonic-gate 		goto dofinal;
14070Sstevel@tonic-gate 	}
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	dlen = data->cd_length;
14100Sstevel@tonic-gate 
1411676Sizick 	if (flag & DO_UPDATE) {
1412676Sizick 
1413676Sizick 		switch (data->cd_format) {
1414676Sizick 		case CRYPTO_DATA_RAW:
1415676Sizick 			dptr = (uchar_t *)(data->cd_raw.iov_base +
1416676Sizick 			    data->cd_offset);
14170Sstevel@tonic-gate 
1418676Sizick 			if (flag & DO_MD5)
14190Sstevel@tonic-gate 				MD5Update(dctx, dptr, dlen);
1420676Sizick 
1421676Sizick 			else if (flag & DO_SHA1)
14220Sstevel@tonic-gate 				SHA1Update(dctx, dptr, dlen);
1423676Sizick 
1424676Sizick 			else
1425676Sizick 				SHA2Update(dctx, dptr, dlen);
1426676Sizick 
14270Sstevel@tonic-gate 		break;
14280Sstevel@tonic-gate 
1429676Sizick 		case CRYPTO_DATA_UIO:
1430676Sizick 			if (flag & DO_MD5)
1431676Sizick 				rv = process_uio_data(data, NULL, dlen,
1432676Sizick 				    MD5_DIGEST_DATA, dctx);
1433676Sizick 
1434676Sizick 			else if (flag & DO_SHA1)
1435676Sizick 				rv = process_uio_data(data, NULL, dlen,
1436676Sizick 				    SHA1_DIGEST_DATA, dctx);
1437676Sizick 
1438676Sizick 			else
1439676Sizick 				rv = process_uio_data(data, NULL, dlen,
1440676Sizick 				    SHA2_DIGEST_DATA, dctx);
1441676Sizick 
14420Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
14430Sstevel@tonic-gate 				return (rv);
1444676Sizick 
1445676Sizick 			break;
1446676Sizick 
1447676Sizick 		case CRYPTO_DATA_MBLK:
1448676Sizick 			if (flag & DO_MD5)
1449676Sizick 				rv = process_mblk_data(data, NULL, dlen,
1450676Sizick 				    MD5_DIGEST_DATA, dctx);
14510Sstevel@tonic-gate 
1452676Sizick 			else if (flag & DO_SHA1)
1453676Sizick 				rv = process_mblk_data(data, NULL, dlen,
1454676Sizick 				    SHA1_DIGEST_DATA, dctx);
1455676Sizick 
1456676Sizick 			else
1457676Sizick 				rv = process_mblk_data(data, NULL, dlen,
1458676Sizick 				    SHA2_DIGEST_DATA, dctx);
1459676Sizick 
14600Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
14610Sstevel@tonic-gate 				return (rv);
1462676Sizick 
1463676Sizick 			break;
14640Sstevel@tonic-gate 		}
14650Sstevel@tonic-gate 	}
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate dofinal:
14680Sstevel@tonic-gate 	if (flag & DO_FINAL) {
14690Sstevel@tonic-gate 		if (flag & DO_MD5)
14700Sstevel@tonic-gate 			MD5Final(digest, dctx);
1471676Sizick 
1472676Sizick 		else if (flag & DO_SHA1)
1473676Sizick 			SHA1Final(digest, dctx);
1474676Sizick 
14750Sstevel@tonic-gate 		else
1476676Sizick 			SHA2Final(digest, dctx);
14770Sstevel@tonic-gate 	}
14780Sstevel@tonic-gate 
14790Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate static int
14830Sstevel@tonic-gate rsa_digest_svrfy_common(digest_rsa_ctx_t *ctxp, crypto_data_t *data,
14840Sstevel@tonic-gate     crypto_data_t *signature, int kmflag, uchar_t flag)
14850Sstevel@tonic-gate {
14860Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate /* EXPORT DELETE START */
14890Sstevel@tonic-gate 
1490676Sizick 	uchar_t digest[SHA512_DIGEST_LENGTH];
14910Sstevel@tonic-gate 	/* The der_data size is enough for MD5 also */
1492676Sizick 	uchar_t der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
14930Sstevel@tonic-gate 	ulong_t der_data_len;
14940Sstevel@tonic-gate 	crypto_data_t der_cd;
14950Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 	ASSERT(flag & DO_SIGN || flag & DO_VERIFY);
14980Sstevel@tonic-gate 	ASSERT(data != NULL || (flag & DO_FINAL));
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
1501676Sizick 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
1502676Sizick 	    mech_type == RSA_X_509_MECH_INFO_TYPE)
15030Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 	/*
15060Sstevel@tonic-gate 	 * We need to do the BUFFER_TOO_SMALL check before digesting
15070Sstevel@tonic-gate 	 * the data. No check is needed for verify as signature is not
15080Sstevel@tonic-gate 	 * an output argument for verify.
15090Sstevel@tonic-gate 	 */
15100Sstevel@tonic-gate 	if (flag & DO_SIGN) {
15110Sstevel@tonic-gate 		uchar_t *modulus;
15120Sstevel@tonic-gate 		ssize_t modulus_len;
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 		if ((rv = get_key_attr(ctxp->key, SUN_CKA_MODULUS, &modulus,
15150Sstevel@tonic-gate 		    &modulus_len)) != CRYPTO_SUCCESS) {
15160Sstevel@tonic-gate 			return (rv);
15170Sstevel@tonic-gate 		}
15180Sstevel@tonic-gate 
15190Sstevel@tonic-gate 		if (signature->cd_length < modulus_len) {
15200Sstevel@tonic-gate 			signature->cd_length = modulus_len;
15210Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
15220Sstevel@tonic-gate 		}
15230Sstevel@tonic-gate 	}
15240Sstevel@tonic-gate 
15250Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
15260Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->md5_ctx),
15270Sstevel@tonic-gate 		    digest, flag | DO_MD5);
1528676Sizick 
1529676Sizick 	else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE)
15300Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->sha1_ctx),
15310Sstevel@tonic-gate 		    digest, flag | DO_SHA1);
1532676Sizick 
1533676Sizick 	else
1534676Sizick 		rv = digest_data(data, &(ctxp->sha2_ctx),
1535676Sizick 		    digest, flag | DO_SHA2);
1536676Sizick 
15370Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
15380Sstevel@tonic-gate 		return (rv);
15390Sstevel@tonic-gate 
1540676Sizick 
15410Sstevel@tonic-gate 	/*
15420Sstevel@tonic-gate 	 * Prepare the DER encoding of the DigestInfo value as follows:
15430Sstevel@tonic-gate 	 * MD5:		MD5_DER_PREFIX || H
15440Sstevel@tonic-gate 	 * SHA-1:	SHA1_DER_PREFIX || H
15450Sstevel@tonic-gate 	 *
15460Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
15470Sstevel@tonic-gate 	 */
1548676Sizick 	switch (mech_type) {
1549676Sizick 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
15500Sstevel@tonic-gate 		bcopy(MD5_DER_PREFIX, der_data, MD5_DER_PREFIX_Len);
1551676Sizick 		bcopy(digest, der_data + MD5_DER_PREFIX_Len, MD5_DIGEST_SIZE);
1552676Sizick 		der_data_len = MD5_DER_PREFIX_Len + MD5_DIGEST_SIZE;
1553676Sizick 		break;
1554676Sizick 
1555676Sizick 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
15560Sstevel@tonic-gate 		bcopy(SHA1_DER_PREFIX, der_data, SHA1_DER_PREFIX_Len);
1557676Sizick 		bcopy(digest, der_data + SHA1_DER_PREFIX_Len,
1558676Sizick 		    SHA1_DIGEST_SIZE);
1559676Sizick 		der_data_len = SHA1_DER_PREFIX_Len + SHA1_DIGEST_SIZE;
1560676Sizick 		break;
1561676Sizick 
1562676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1563676Sizick 		bcopy(SHA256_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1564676Sizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1565676Sizick 		    SHA256_DIGEST_LENGTH);
1566676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA256_DIGEST_LENGTH;
1567676Sizick 		break;
1568676Sizick 
1569676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1570676Sizick 		bcopy(SHA384_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1571676Sizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1572676Sizick 		    SHA384_DIGEST_LENGTH);
1573676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA384_DIGEST_LENGTH;
1574676Sizick 		break;
1575676Sizick 
1576676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1577676Sizick 		bcopy(SHA512_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1578676Sizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1579676Sizick 		    SHA512_DIGEST_LENGTH);
1580676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA512_DIGEST_LENGTH;
1581676Sizick 		break;
15820Sstevel@tonic-gate 	}
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	INIT_RAW_CRYPTO_DATA(der_cd, der_data, der_data_len, der_data_len);
15850Sstevel@tonic-gate 	/*
15860Sstevel@tonic-gate 	 * Now, we are ready to sign or verify the DER_ENCODED data.
15870Sstevel@tonic-gate 	 */
15880Sstevel@tonic-gate 	if (flag & DO_SIGN)
15890Sstevel@tonic-gate 		rv = rsa_sign_common(mech_type, ctxp->key, &der_cd,
15900Sstevel@tonic-gate 		    signature, kmflag);
15910Sstevel@tonic-gate 	else
15920Sstevel@tonic-gate 		rv = rsa_verify_common(mech_type, ctxp->key, &der_cd,
15930Sstevel@tonic-gate 		    signature, kmflag);
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate /* EXPORT DELETE END */
15960Sstevel@tonic-gate 
15970Sstevel@tonic-gate 	return (rv);
15980Sstevel@tonic-gate }
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate static int
16010Sstevel@tonic-gate rsa_sign_common(rsa_mech_type_t mech_type, crypto_key_t *key,
16020Sstevel@tonic-gate     crypto_data_t *data, crypto_data_t *signature, int kmflag)
16030Sstevel@tonic-gate {
16040Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate /* EXPORT DELETE START */
16070Sstevel@tonic-gate 
16080Sstevel@tonic-gate 	int dlen;
16090Sstevel@tonic-gate 	uchar_t *dataptr, *modulus;
16100Sstevel@tonic-gate 	ssize_t modulus_len;
16110Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
16120Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
16130Sstevel@tonic-gate 	uchar_t signed_data[MAX_RSA_KEYLENGTH_IN_BYTES];
16140Sstevel@tonic-gate 
16150Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
16160Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
16170Sstevel@tonic-gate 		return (rv);
16180Sstevel@tonic-gate 	}
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 	dlen = data->cd_length;
16210Sstevel@tonic-gate 	switch (mech_type) {
16220Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
16230Sstevel@tonic-gate 		if (dlen > (modulus_len - MIN_PKCS1_PADLEN))
16240Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
16250Sstevel@tonic-gate 		break;
16260Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
16270Sstevel@tonic-gate 		if (dlen > modulus_len)
16280Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
16290Sstevel@tonic-gate 		break;
16300Sstevel@tonic-gate 	}
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 	if (signature->cd_length < modulus_len) {
16330Sstevel@tonic-gate 		signature->cd_length = modulus_len;
16340Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
16350Sstevel@tonic-gate 	}
16360Sstevel@tonic-gate 
16370Sstevel@tonic-gate 	ASSERT(data->cd_length <= sizeof (tmp_data));
16380Sstevel@tonic-gate 	if ((rv = get_input_data(data, &dataptr, tmp_data))
16390Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
16400Sstevel@tonic-gate 		return (rv);
16410Sstevel@tonic-gate 
16420Sstevel@tonic-gate 	switch (mech_type) {
16430Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
16440Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
16450Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1646676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1647676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1648676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
16490Sstevel@tonic-gate 		/*
16500Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
16510Sstevel@tonic-gate 		 * type "01" encryption block.
16520Sstevel@tonic-gate 		 */
16530Sstevel@tonic-gate 		rv = soft_sign_rsa_pkcs_encode(dataptr, dlen, plain_data,
16540Sstevel@tonic-gate 		    modulus_len);
16550Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
16560Sstevel@tonic-gate 			return (rv);
16570Sstevel@tonic-gate 
16580Sstevel@tonic-gate 		break;
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
16610Sstevel@tonic-gate 		bzero(plain_data, modulus_len - dlen);
16620Sstevel@tonic-gate 		bcopy(dataptr, &plain_data[modulus_len - dlen], dlen);
16630Sstevel@tonic-gate 		break;
16640Sstevel@tonic-gate 	}
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 	rv = core_rsa_decrypt(key, plain_data, modulus_len, signed_data,
16670Sstevel@tonic-gate 	    kmflag);
16680Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
16690Sstevel@tonic-gate 		/* copy out to signature */
16700Sstevel@tonic-gate 		if ((rv = put_output_data(signed_data,
16710Sstevel@tonic-gate 		    signature, modulus_len)) != CRYPTO_SUCCESS)
16720Sstevel@tonic-gate 			return (rv);
16730Sstevel@tonic-gate 
16740Sstevel@tonic-gate 		signature->cd_length = modulus_len;
16750Sstevel@tonic-gate 	}
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate /* EXPORT DELETE END */
16780Sstevel@tonic-gate 
16790Sstevel@tonic-gate 	return (rv);
16800Sstevel@tonic-gate }
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate /* ARGSUSED */
16830Sstevel@tonic-gate static int
16840Sstevel@tonic-gate rsa_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
16850Sstevel@tonic-gate     crypto_req_handle_t req)
16860Sstevel@tonic-gate {
16870Sstevel@tonic-gate 	int rv;
16880Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
16890Sstevel@tonic-gate 
16900Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
16910Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
16920Sstevel@tonic-gate 
16930Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
16940Sstevel@tonic-gate 	switch (ctxp->mech_type) {
16950Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
16960Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1697676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1698676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1699676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
17000Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
17010Sstevel@tonic-gate 		    signature, KM_SLEEP, DO_SIGN | DO_UPDATE | DO_FINAL);
17020Sstevel@tonic-gate 		break;
17030Sstevel@tonic-gate 	default:
17040Sstevel@tonic-gate 		rv = rsa_sign_common(ctxp->mech_type, ctxp->key, data,
17050Sstevel@tonic-gate 		    signature, KM_SLEEP);
17060Sstevel@tonic-gate 		break;
17070Sstevel@tonic-gate 	}
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
17100Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
17110Sstevel@tonic-gate 
17120Sstevel@tonic-gate 	return (rv);
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate /* ARGSUSED */
17160Sstevel@tonic-gate static int
17170Sstevel@tonic-gate rsa_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
17180Sstevel@tonic-gate {
17190Sstevel@tonic-gate 	int rv;
17200Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
17210Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
17220Sstevel@tonic-gate 
17230Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
17240Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
17250Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
17260Sstevel@tonic-gate 
1727676Sizick 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
1728676Sizick 	    mech_type == RSA_X_509_MECH_INFO_TYPE)
17290Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
17320Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->md5_ctx),
17330Sstevel@tonic-gate 		    NULL, DO_MD5 | DO_UPDATE);
1734676Sizick 
1735676Sizick 	else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE)
17360Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->sha1_ctx),
17370Sstevel@tonic-gate 		    NULL, DO_SHA1 | DO_UPDATE);
1738676Sizick 
1739676Sizick 	else
1740676Sizick 		rv = digest_data(data, &(ctxp->sha2_ctx),
1741676Sizick 		    NULL, DO_SHA2 | DO_UPDATE);
1742676Sizick 
17430Sstevel@tonic-gate 	return (rv);
17440Sstevel@tonic-gate }
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate static int
17470Sstevel@tonic-gate rsa_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
17480Sstevel@tonic-gate     crypto_req_handle_t req)
17490Sstevel@tonic-gate {
17500Sstevel@tonic-gate 	int rv;
17510Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
17520Sstevel@tonic-gate 
17530Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
17540Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
17570Sstevel@tonic-gate 	    crypto_kmflag(req), DO_SIGN | DO_FINAL);
17580Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
17590Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 	return (rv);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate 
17640Sstevel@tonic-gate /* ARGSUSED */
17650Sstevel@tonic-gate static int
17660Sstevel@tonic-gate rsa_sign_atomic(crypto_provider_handle_t provider,
17670Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
17680Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
17690Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
17700Sstevel@tonic-gate {
17710Sstevel@tonic-gate 	int rv;
17720Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
17750Sstevel@tonic-gate 		return (rv);
17760Sstevel@tonic-gate 
1777676Sizick 	if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE ||
1778676Sizick 	    mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE)
1779676Sizick 		rv = rsa_sign_common(mechanism->cm_type, key, data,
1780676Sizick 		    signature, crypto_kmflag(req));
1781676Sizick 
1782676Sizick 	else {
17830Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
17840Sstevel@tonic-gate 		dctx.key = key;
1785676Sizick 		switch (mechanism->cm_type) {
1786676Sizick 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
17870Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1788676Sizick 			break;
1789676Sizick 
1790676Sizick 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
17910Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1792676Sizick 			break;
1793676Sizick 
1794676Sizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1795676Sizick 			SHA2Init(SHA256, &(dctx.sha2_ctx));
1796676Sizick 			break;
1797676Sizick 
1798676Sizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1799676Sizick 			SHA2Init(SHA384, &(dctx.sha2_ctx));
1800676Sizick 			break;
1801676Sizick 
1802676Sizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1803676Sizick 			SHA2Init(SHA512, &(dctx.sha2_ctx));
1804676Sizick 			break;
1805676Sizick 		}
1806676Sizick 
1807676Sizick 		rv = rsa_digest_svrfy_common(&dctx, data, signature,
1808676Sizick 		    crypto_kmflag(req), DO_SIGN | DO_UPDATE | DO_FINAL);
18090Sstevel@tonic-gate 	}
18100Sstevel@tonic-gate 
18110Sstevel@tonic-gate 	return (rv);
18120Sstevel@tonic-gate }
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate static int
18150Sstevel@tonic-gate rsa_verify_common(rsa_mech_type_t mech_type, crypto_key_t *key,
18160Sstevel@tonic-gate     crypto_data_t *data, crypto_data_t *signature, int kmflag)
18170Sstevel@tonic-gate {
18180Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate /* EXPORT DELETE START */
18210Sstevel@tonic-gate 
18220Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
18230Sstevel@tonic-gate 	ssize_t modulus_len;
18240Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
18250Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
18260Sstevel@tonic-gate 
18270Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
18280Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
18290Sstevel@tonic-gate 		return (rv);
18300Sstevel@tonic-gate 	}
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
18330Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
18340Sstevel@tonic-gate 
18350Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
18360Sstevel@tonic-gate 	if ((rv = get_input_data(signature, &sigptr, tmp_data))
18370Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
18380Sstevel@tonic-gate 		return (rv);
18390Sstevel@tonic-gate 
18400Sstevel@tonic-gate 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, kmflag, 1);
18410Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
18420Sstevel@tonic-gate 		return (rv);
18430Sstevel@tonic-gate 
1844676Sizick 	if (mech_type == RSA_X_509_MECH_INFO_TYPE) {
1845676Sizick 		if (compare_data(data, (plain_data + modulus_len
1846676Sizick 		    - data->cd_length)) != 0)
1847676Sizick 			rv = CRYPTO_SIGNATURE_INVALID;
1848676Sizick 
1849676Sizick 	} else {
18500Sstevel@tonic-gate 		int data_len = modulus_len;
18510Sstevel@tonic-gate 
18520Sstevel@tonic-gate 		/*
18530Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
18540Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
18550Sstevel@tonic-gate 		 * the original data.
18560Sstevel@tonic-gate 		 */
18570Sstevel@tonic-gate 		rv = soft_verify_rsa_pkcs_decode(plain_data, &data_len);
18580Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
1859676Sizick 			return (rv);
18600Sstevel@tonic-gate 
1861676Sizick 		if (data_len != data->cd_length)
1862676Sizick 			return (CRYPTO_SIGNATURE_LEN_RANGE);
18630Sstevel@tonic-gate 
18640Sstevel@tonic-gate 		if (compare_data(data, (plain_data + modulus_len
18650Sstevel@tonic-gate 		    - data_len)) != 0)
18660Sstevel@tonic-gate 			rv = CRYPTO_SIGNATURE_INVALID;
18670Sstevel@tonic-gate 	}
18680Sstevel@tonic-gate 
18690Sstevel@tonic-gate /* EXPORT DELETE END */
18700Sstevel@tonic-gate 
18710Sstevel@tonic-gate 	return (rv);
18720Sstevel@tonic-gate }
18730Sstevel@tonic-gate 
18740Sstevel@tonic-gate /* ARGSUSED */
18750Sstevel@tonic-gate static int
18760Sstevel@tonic-gate rsa_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
18770Sstevel@tonic-gate     crypto_req_handle_t req)
18780Sstevel@tonic-gate {
18790Sstevel@tonic-gate 	int rv;
18800Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
18810Sstevel@tonic-gate 
18820Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
18830Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
18840Sstevel@tonic-gate 
18850Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
18860Sstevel@tonic-gate 	switch (ctxp->mech_type) {
18870Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
18880Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1889676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1890676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1891676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
18920Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
18930Sstevel@tonic-gate 		    signature, KM_SLEEP, DO_VERIFY | DO_UPDATE | DO_FINAL);
18940Sstevel@tonic-gate 		break;
18950Sstevel@tonic-gate 	default:
18960Sstevel@tonic-gate 		rv = rsa_verify_common(ctxp->mech_type, ctxp->key, data,
18970Sstevel@tonic-gate 		    signature, KM_SLEEP);
18980Sstevel@tonic-gate 		break;
18990Sstevel@tonic-gate 	}
19000Sstevel@tonic-gate 
19010Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
19020Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
19030Sstevel@tonic-gate 
19040Sstevel@tonic-gate 	return (rv);
19050Sstevel@tonic-gate }
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate /* ARGSUSED */
19080Sstevel@tonic-gate static int
19090Sstevel@tonic-gate rsa_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
19100Sstevel@tonic-gate     crypto_req_handle_t req)
19110Sstevel@tonic-gate {
19120Sstevel@tonic-gate 	int rv;
19130Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
19140Sstevel@tonic-gate 
19150Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
19160Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
19170Sstevel@tonic-gate 
1918676Sizick 	switch (ctxp->mech_type) {
19190Sstevel@tonic-gate 
1920676Sizick 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
19210Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->md5_ctx),
19220Sstevel@tonic-gate 		    NULL, DO_MD5 | DO_UPDATE);
1923676Sizick 		break;
1924676Sizick 
1925676Sizick 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
19260Sstevel@tonic-gate 		rv = digest_data(data, &(ctxp->sha1_ctx),
19270Sstevel@tonic-gate 		    NULL, DO_SHA1 | DO_UPDATE);
1928676Sizick 		break;
1929676Sizick 
1930676Sizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1931676Sizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1932676Sizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1933676Sizick 		rv = digest_data(data, &(ctxp->sha2_ctx),
1934676Sizick 		    NULL, DO_SHA2 | DO_UPDATE);
1935676Sizick 		break;
1936676Sizick 
1937676Sizick 	default:
1938676Sizick 		return (CRYPTO_MECHANISM_INVALID);
1939676Sizick 	}
1940676Sizick 
19410Sstevel@tonic-gate 	return (rv);
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate static int
19450Sstevel@tonic-gate rsa_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
19460Sstevel@tonic-gate     crypto_req_handle_t req)
19470Sstevel@tonic-gate {
19480Sstevel@tonic-gate 	int rv;
19490Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
19520Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
19530Sstevel@tonic-gate 
19540Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
19550Sstevel@tonic-gate 	    crypto_kmflag(req), DO_VERIFY | DO_FINAL);
19560Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
19570Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
19580Sstevel@tonic-gate 
19590Sstevel@tonic-gate 	return (rv);
19600Sstevel@tonic-gate }
19610Sstevel@tonic-gate 
19620Sstevel@tonic-gate 
19630Sstevel@tonic-gate /* ARGSUSED */
19640Sstevel@tonic-gate static int
19650Sstevel@tonic-gate rsa_verify_atomic(crypto_provider_handle_t provider,
19660Sstevel@tonic-gate     crypto_session_id_t session_id,
19670Sstevel@tonic-gate     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
19680Sstevel@tonic-gate     crypto_data_t *signature, crypto_spi_ctx_template_t ctx_template,
19690Sstevel@tonic-gate     crypto_req_handle_t req)
19700Sstevel@tonic-gate {
19710Sstevel@tonic-gate 	int rv;
19720Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
19730Sstevel@tonic-gate 
19740Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
19750Sstevel@tonic-gate 		return (rv);
19760Sstevel@tonic-gate 
1977676Sizick 	if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE ||
1978676Sizick 	    mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE)
1979676Sizick 		rv = rsa_verify_common(mechanism->cm_type, key, data,
1980676Sizick 		    signature, crypto_kmflag(req));
1981676Sizick 
1982676Sizick 	else {
19830Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
19840Sstevel@tonic-gate 		dctx.key = key;
1985676Sizick 
1986676Sizick 		switch (mechanism->cm_type) {
1987676Sizick 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
19880Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1989676Sizick 			break;
1990676Sizick 
1991676Sizick 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
19920Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1993676Sizick 			break;
1994676Sizick 
1995676Sizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1996676Sizick 			SHA2Init(SHA256, &(dctx.sha2_ctx));
1997676Sizick 			break;
1998676Sizick 
1999676Sizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
2000676Sizick 			SHA2Init(SHA384, &(dctx.sha2_ctx));
2001676Sizick 			break;
2002676Sizick 
2003676Sizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
2004676Sizick 			SHA2Init(SHA512, &(dctx.sha2_ctx));
2005676Sizick 			break;
2006676Sizick 		}
2007676Sizick 
20080Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common(&dctx, data,
20090Sstevel@tonic-gate 		    signature, crypto_kmflag(req),
20100Sstevel@tonic-gate 		    DO_VERIFY | DO_UPDATE | DO_FINAL);
20110Sstevel@tonic-gate 	}
20120Sstevel@tonic-gate 
20130Sstevel@tonic-gate 	return (rv);
20140Sstevel@tonic-gate }
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate static int
20170Sstevel@tonic-gate rsa_verify_recover_common(rsa_mech_type_t mech_type, crypto_key_t *key,
20180Sstevel@tonic-gate     crypto_data_t *signature, crypto_data_t *data, int kmflag)
20190Sstevel@tonic-gate {
20200Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
20210Sstevel@tonic-gate 
20220Sstevel@tonic-gate /* EXPORT DELETE START */
20230Sstevel@tonic-gate 
20240Sstevel@tonic-gate 	int data_len;
20250Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
20260Sstevel@tonic-gate 	ssize_t modulus_len;
20270Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
20280Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
20290Sstevel@tonic-gate 
20300Sstevel@tonic-gate 	if ((rv = get_key_attr(key, SUN_CKA_MODULUS, &modulus,
20310Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
20320Sstevel@tonic-gate 		return (rv);
20330Sstevel@tonic-gate 	}
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
20360Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
20390Sstevel@tonic-gate 	if ((rv = get_input_data(signature, &sigptr, tmp_data))
20400Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
20410Sstevel@tonic-gate 		return (rv);
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, kmflag, 1);
20440Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
20450Sstevel@tonic-gate 		return (rv);
20460Sstevel@tonic-gate 
20470Sstevel@tonic-gate 	data_len = modulus_len;
20480Sstevel@tonic-gate 
20490Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
20500Sstevel@tonic-gate 		/*
20510Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
20520Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
20530Sstevel@tonic-gate 		 * the original data.
20540Sstevel@tonic-gate 		 */
20550Sstevel@tonic-gate 		rv = soft_verify_rsa_pkcs_decode(plain_data, &data_len);
20560Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
20570Sstevel@tonic-gate 			return (rv);
20580Sstevel@tonic-gate 	}
20590Sstevel@tonic-gate 
20600Sstevel@tonic-gate 	if (data->cd_length < data_len) {
20610Sstevel@tonic-gate 		data->cd_length = data_len;
20620Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
20630Sstevel@tonic-gate 	}
20640Sstevel@tonic-gate 
20650Sstevel@tonic-gate 	if ((rv = put_output_data(plain_data + modulus_len - data_len,
20660Sstevel@tonic-gate 	    data, data_len)) != CRYPTO_SUCCESS)
20670Sstevel@tonic-gate 		return (rv);
20680Sstevel@tonic-gate 	data->cd_length = data_len;
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate /* EXPORT DELETE END */
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 	return (rv);
20730Sstevel@tonic-gate }
20740Sstevel@tonic-gate 
20750Sstevel@tonic-gate /* ARGSUSED */
20760Sstevel@tonic-gate static int
20770Sstevel@tonic-gate rsa_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
20780Sstevel@tonic-gate     crypto_data_t *data, crypto_req_handle_t req)
20790Sstevel@tonic-gate {
20800Sstevel@tonic-gate 	int rv;
20810Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
20820Sstevel@tonic-gate 
20830Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
20840Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
20850Sstevel@tonic-gate 
20860Sstevel@tonic-gate 	/* See the comments on KM_SLEEP flag in rsa_encrypt() */
20870Sstevel@tonic-gate 	rv = rsa_verify_recover_common(ctxp->mech_type, ctxp->key,
20880Sstevel@tonic-gate 	    signature, data, KM_SLEEP);
20890Sstevel@tonic-gate 
20900Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
20910Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
20920Sstevel@tonic-gate 
20930Sstevel@tonic-gate 	return (rv);
20940Sstevel@tonic-gate }
20950Sstevel@tonic-gate 
20960Sstevel@tonic-gate /* ARGSUSED */
20970Sstevel@tonic-gate static int
20980Sstevel@tonic-gate rsa_verify_recover_atomic(crypto_provider_handle_t provider,
20990Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
21000Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
21010Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
21020Sstevel@tonic-gate {
21030Sstevel@tonic-gate 	int rv;
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
21060Sstevel@tonic-gate 		return (rv);
21070Sstevel@tonic-gate 
21080Sstevel@tonic-gate 	return (rsa_verify_recover_common(mechanism->cm_type, key,
21090Sstevel@tonic-gate 	    signature, data, crypto_kmflag(req)));
21100Sstevel@tonic-gate }
2111