xref: /illumos-gate/usr/src/uts/common/crypto/io/rsa.c (revision b4a44cf2)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d2b32306Smcpowers  * Common Development and Distribution License (the "License").
6d2b32306Smcpowers  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21726fad2aSDina K Nimeh 
227c478bd9Sstevel@tonic-gate /*
23726fad2aSDina K Nimeh  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * RSA provider for the Kernel Cryptographic Framework (KCF)
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/systm.h>
327c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
337c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
357c478bd9Sstevel@tonic-gate #include <sys/crypto/spi.h>
367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
377c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
387c478bd9Sstevel@tonic-gate #include <sys/md5.h>
397c478bd9Sstevel@tonic-gate #include <sys/sha1.h>
40b5a2d845SHai-May Chao #define	_SHA2_IMPL
41f66d273dSizick #include <sys/sha2.h>
427c478bd9Sstevel@tonic-gate #include <sys/random.h>
4323c57df7Smcpowers #include <sys/crypto/impl.h>
44b5a2d845SHai-May Chao #include <sha1/sha1_impl.h>
45b5a2d845SHai-May Chao #include <sha2/sha2_impl.h>
46726fad2aSDina K Nimeh #include <padding/padding.h>
47b5a2d845SHai-May Chao #include <rsa/rsa_impl.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate extern struct mod_ops mod_cryptoops;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate static struct modlcrypto modlcrypto = {
557c478bd9Sstevel@tonic-gate 	&mod_cryptoops,
56d2b32306Smcpowers 	"RSA Kernel SW Provider"
577c478bd9Sstevel@tonic-gate };
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
607c478bd9Sstevel@tonic-gate 	MODREV_1,
617c478bd9Sstevel@tonic-gate 	(void *)&modlcrypto,
627c478bd9Sstevel@tonic-gate 	NULL
637c478bd9Sstevel@tonic-gate };
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * CSPI information (entry points, provider info, etc.)
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate typedef enum rsa_mech_type {
697c478bd9Sstevel@tonic-gate 	RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_RSA_PKCS */
707c478bd9Sstevel@tonic-gate 	RSA_X_509_MECH_INFO_TYPE,	/* SUN_CKM_RSA_X_509 */
717c478bd9Sstevel@tonic-gate 	MD5_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_MD5_RSA_PKCS */
72f66d273dSizick 	SHA1_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA1_RSA_PKCS */
73f66d273dSizick 	SHA256_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA256_RSA_PKCS */
74f66d273dSizick 	SHA384_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_SHA384_RSA_PKCS */
75f66d273dSizick 	SHA512_RSA_PKCS_MECH_INFO_TYPE	/* SUN_SHA512_RSA_PKCS */
767c478bd9Sstevel@tonic-gate } rsa_mech_type_t;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * Context for RSA_PKCS and RSA_X_509 mechanisms.
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate typedef struct rsa_ctx {
827c478bd9Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
837c478bd9Sstevel@tonic-gate 	crypto_key_t *key;
847c478bd9Sstevel@tonic-gate 	size_t keychunk_size;
857c478bd9Sstevel@tonic-gate } rsa_ctx_t;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
88f66d273dSizick  * Context for MD5_RSA_PKCS and SHA*_RSA_PKCS mechanisms.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate typedef struct digest_rsa_ctx {
917c478bd9Sstevel@tonic-gate 	rsa_mech_type_t	mech_type;
927c478bd9Sstevel@tonic-gate 	crypto_key_t *key;
937c478bd9Sstevel@tonic-gate 	size_t keychunk_size;
947c478bd9Sstevel@tonic-gate 	union {
957c478bd9Sstevel@tonic-gate 		MD5_CTX md5ctx;
967c478bd9Sstevel@tonic-gate 		SHA1_CTX sha1ctx;
97f66d273dSizick 		SHA2_CTX sha2ctx;
987c478bd9Sstevel@tonic-gate 	} dctx_u;
997c478bd9Sstevel@tonic-gate } digest_rsa_ctx_t;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #define	md5_ctx		dctx_u.md5ctx
1027c478bd9Sstevel@tonic-gate #define	sha1_ctx	dctx_u.sha1ctx
103f66d273dSizick #define	sha2_ctx	dctx_u.sha2ctx
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * Mechanism info structure passed to KCF during registration.
1077c478bd9Sstevel@tonic-gate  */
1087c478bd9Sstevel@tonic-gate static crypto_mech_info_t rsa_mech_info_tab[] = {
1097c478bd9Sstevel@tonic-gate 	/* RSA_PKCS */
1107c478bd9Sstevel@tonic-gate 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
1117c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1127c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1137c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1147c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
1157c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1167c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
1177c478bd9Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	/* RSA_X_509 */
1207c478bd9Sstevel@tonic-gate 	{SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
1217c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1227c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1237c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1247c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
1257c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1267c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
1277c478bd9Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	/* MD5_RSA_PKCS */
1307c478bd9Sstevel@tonic-gate 	{SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE,
1317c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1327c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1337c478bd9Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/* SHA1_RSA_PKCS */
1367c478bd9Sstevel@tonic-gate 	{SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE,
137f66d273dSizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
138f66d273dSizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
139f66d273dSizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
140f66d273dSizick 
141f66d273dSizick 	/* SHA256_RSA_PKCS */
142f66d273dSizick 	{SUN_CKM_SHA256_RSA_PKCS, SHA256_RSA_PKCS_MECH_INFO_TYPE,
143f66d273dSizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
144f66d273dSizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
145f66d273dSizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
146f66d273dSizick 
147f66d273dSizick 	/* SHA384_RSA_PKCS */
148f66d273dSizick 	{SUN_CKM_SHA384_RSA_PKCS, SHA384_RSA_PKCS_MECH_INFO_TYPE,
149f66d273dSizick 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
150f66d273dSizick 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
151f66d273dSizick 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
152f66d273dSizick 
153f66d273dSizick 	/* SHA512_RSA_PKCS */
154f66d273dSizick 	{SUN_CKM_SHA512_RSA_PKCS, SHA512_RSA_PKCS_MECH_INFO_TYPE,
1557c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1567c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1577c478bd9Sstevel@tonic-gate 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}
158f66d273dSizick 
1597c478bd9Sstevel@tonic-gate };
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #define	RSA_VALID_MECH(mech)					\
1627c478bd9Sstevel@tonic-gate 	(((mech)->cm_type == RSA_PKCS_MECH_INFO_TYPE ||		\
1637c478bd9Sstevel@tonic-gate 	(mech)->cm_type == RSA_X_509_MECH_INFO_TYPE ||		\
1647c478bd9Sstevel@tonic-gate 	(mech)->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||	\
165f66d273dSizick 	(mech)->cm_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||	\
166f66d273dSizick 	(mech)->cm_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||	\
167f66d273dSizick 	(mech)->cm_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||	\
168f66d273dSizick 	(mech)->cm_type == SHA512_RSA_PKCS_MECH_INFO_TYPE) ? 1 : 0)
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */
1717c478bd9Sstevel@tonic-gate #define	RSA_ARG_INPLACE(input, output)				\
1727c478bd9Sstevel@tonic-gate 	if ((output) == NULL)					\
1737c478bd9Sstevel@tonic-gate 		(output) = (input);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate static void rsa_provider_status(crypto_provider_handle_t, uint_t *);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate static crypto_control_ops_t rsa_control_ops = {
1787c478bd9Sstevel@tonic-gate 	rsa_provider_status
1797c478bd9Sstevel@tonic-gate };
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static int rsa_common_init(crypto_ctx_t *, crypto_mechanism_t *,
1827c478bd9Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
183726fad2aSDina K Nimeh static int rsaprov_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1847c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
1857c478bd9Sstevel@tonic-gate static int rsa_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1867c478bd9Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1877c478bd9Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
188726fad2aSDina K Nimeh static int rsaprov_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1897c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
1907c478bd9Sstevel@tonic-gate static int rsa_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1917c478bd9Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1927c478bd9Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * The RSA mechanisms do not have multiple-part cipher operations.
1967c478bd9Sstevel@tonic-gate  * So, the update and final routines are set to NULL.
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate static crypto_cipher_ops_t rsa_cipher_ops = {
1997c478bd9Sstevel@tonic-gate 	rsa_common_init,
200726fad2aSDina K Nimeh 	rsaprov_encrypt,
2017c478bd9Sstevel@tonic-gate 	NULL,
2027c478bd9Sstevel@tonic-gate 	NULL,
2037c478bd9Sstevel@tonic-gate 	rsa_encrypt_atomic,
2047c478bd9Sstevel@tonic-gate 	rsa_common_init,
205726fad2aSDina K Nimeh 	rsaprov_decrypt,
2067c478bd9Sstevel@tonic-gate 	NULL,
2077c478bd9Sstevel@tonic-gate 	NULL,
2087c478bd9Sstevel@tonic-gate 	rsa_decrypt_atomic
2097c478bd9Sstevel@tonic-gate };
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate static int rsa_sign_verify_common_init(crypto_ctx_t *, crypto_mechanism_t *,
2127c478bd9Sstevel@tonic-gate     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
213726fad2aSDina K Nimeh static int rsaprov_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
2147c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2157c478bd9Sstevel@tonic-gate static int rsa_sign_update(crypto_ctx_t *, crypto_data_t *,
2167c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2177c478bd9Sstevel@tonic-gate static int rsa_sign_final(crypto_ctx_t *, crypto_data_t *,
2187c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2197c478bd9Sstevel@tonic-gate static int rsa_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
2207c478bd9Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
2217c478bd9Sstevel@tonic-gate     crypto_spi_ctx_template_t, crypto_req_handle_t);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate  * We use the same routine for sign_init and sign_recover_init fields
2257c478bd9Sstevel@tonic-gate  * as they do the same thing. Same holds for sign and sign_recover fields,
2267c478bd9Sstevel@tonic-gate  * and sign_atomic and sign_recover_atomic fields.
2277c478bd9Sstevel@tonic-gate  */
2287c478bd9Sstevel@tonic-gate static crypto_sign_ops_t rsa_sign_ops = {
2297c478bd9Sstevel@tonic-gate 	rsa_sign_verify_common_init,
230726fad2aSDina K Nimeh 	rsaprov_sign,
2317c478bd9Sstevel@tonic-gate 	rsa_sign_update,
2327c478bd9Sstevel@tonic-gate 	rsa_sign_final,
2337c478bd9Sstevel@tonic-gate 	rsa_sign_atomic,
2347c478bd9Sstevel@tonic-gate 	rsa_sign_verify_common_init,
235726fad2aSDina K Nimeh 	rsaprov_sign,
2367c478bd9Sstevel@tonic-gate 	rsa_sign_atomic
2377c478bd9Sstevel@tonic-gate };
2387c478bd9Sstevel@tonic-gate 
239726fad2aSDina K Nimeh static int rsaprov_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
2407c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2417c478bd9Sstevel@tonic-gate static int rsa_verify_update(crypto_ctx_t *, crypto_data_t *,
2427c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2437c478bd9Sstevel@tonic-gate static int rsa_verify_final(crypto_ctx_t *, crypto_data_t *,
2447c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2457c478bd9Sstevel@tonic-gate static int rsa_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
2467c478bd9Sstevel@tonic-gate     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
2477c478bd9Sstevel@tonic-gate     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
2487c478bd9Sstevel@tonic-gate static int rsa_verify_recover(crypto_ctx_t *, crypto_data_t *,
2497c478bd9Sstevel@tonic-gate     crypto_data_t *, crypto_req_handle_t);
2507c478bd9Sstevel@tonic-gate static int rsa_verify_recover_atomic(crypto_provider_handle_t,
2517c478bd9Sstevel@tonic-gate     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2527c478bd9Sstevel@tonic-gate     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
2537c478bd9Sstevel@tonic-gate     crypto_req_handle_t);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate /*
2567c478bd9Sstevel@tonic-gate  * We use the same routine (rsa_sign_verify_common_init) for verify_init
2577c478bd9Sstevel@tonic-gate  * and verify_recover_init fields as they do the same thing.
2587c478bd9Sstevel@tonic-gate  */
2597c478bd9Sstevel@tonic-gate static crypto_verify_ops_t rsa_verify_ops = {
2607c478bd9Sstevel@tonic-gate 	rsa_sign_verify_common_init,
261726fad2aSDina K Nimeh 	rsaprov_verify,
2627c478bd9Sstevel@tonic-gate 	rsa_verify_update,
2637c478bd9Sstevel@tonic-gate 	rsa_verify_final,
2647c478bd9Sstevel@tonic-gate 	rsa_verify_atomic,
2657c478bd9Sstevel@tonic-gate 	rsa_sign_verify_common_init,
2667c478bd9Sstevel@tonic-gate 	rsa_verify_recover,
2677c478bd9Sstevel@tonic-gate 	rsa_verify_recover_atomic
2687c478bd9Sstevel@tonic-gate };
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate static int rsa_free_context(crypto_ctx_t *);
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate static crypto_ctx_ops_t rsa_ctx_ops = {
2737c478bd9Sstevel@tonic-gate 	NULL,
2747c478bd9Sstevel@tonic-gate 	rsa_free_context
2757c478bd9Sstevel@tonic-gate };
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate static crypto_ops_t rsa_crypto_ops = {
2787c478bd9Sstevel@tonic-gate 	&rsa_control_ops,
2797c478bd9Sstevel@tonic-gate 	NULL,
2807c478bd9Sstevel@tonic-gate 	&rsa_cipher_ops,
2817c478bd9Sstevel@tonic-gate 	NULL,
2827c478bd9Sstevel@tonic-gate 	&rsa_sign_ops,
2837c478bd9Sstevel@tonic-gate 	&rsa_verify_ops,
2847c478bd9Sstevel@tonic-gate 	NULL,
2857c478bd9Sstevel@tonic-gate 	NULL,
2867c478bd9Sstevel@tonic-gate 	NULL,
2877c478bd9Sstevel@tonic-gate 	NULL,
2887c478bd9Sstevel@tonic-gate 	NULL,
2897c478bd9Sstevel@tonic-gate 	NULL,
2907c478bd9Sstevel@tonic-gate 	NULL,
29173556491SAnthony Scarpino 	&rsa_ctx_ops,
29273556491SAnthony Scarpino 	NULL,
29373556491SAnthony Scarpino 	NULL,
2946ea3c060SGarrett D'Amore 	NULL,
2957c478bd9Sstevel@tonic-gate };
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate static crypto_provider_info_t rsa_prov_info = {
29873556491SAnthony Scarpino 	CRYPTO_SPI_VERSION_4,
2997c478bd9Sstevel@tonic-gate 	"RSA Software Provider",
3007c478bd9Sstevel@tonic-gate 	CRYPTO_SW_PROVIDER,
3017c478bd9Sstevel@tonic-gate 	{&modlinkage},
3027c478bd9Sstevel@tonic-gate 	NULL,
3037c478bd9Sstevel@tonic-gate 	&rsa_crypto_ops,
3047c478bd9Sstevel@tonic-gate 	sizeof (rsa_mech_info_tab)/sizeof (crypto_mech_info_t),
3057c478bd9Sstevel@tonic-gate 	rsa_mech_info_tab
3067c478bd9Sstevel@tonic-gate };
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate static int rsa_encrypt_common(rsa_mech_type_t, crypto_key_t *,
309726fad2aSDina K Nimeh     crypto_data_t *, crypto_data_t *);
3107c478bd9Sstevel@tonic-gate static int rsa_decrypt_common(rsa_mech_type_t, crypto_key_t *,
311726fad2aSDina K Nimeh     crypto_data_t *, crypto_data_t *);
3127c478bd9Sstevel@tonic-gate static int rsa_sign_common(rsa_mech_type_t, crypto_key_t *,
313726fad2aSDina K Nimeh     crypto_data_t *, crypto_data_t *);
3147c478bd9Sstevel@tonic-gate static int rsa_verify_common(rsa_mech_type_t, crypto_key_t *,
315726fad2aSDina K Nimeh     crypto_data_t *, crypto_data_t *);
3167c478bd9Sstevel@tonic-gate static int compare_data(crypto_data_t *, uchar_t *);
3177c478bd9Sstevel@tonic-gate 
318726fad2aSDina K Nimeh static int core_rsa_encrypt(crypto_key_t *, uchar_t *, int, uchar_t *, int);
319726fad2aSDina K Nimeh static int core_rsa_decrypt(crypto_key_t *, uchar_t *, int, uchar_t *);
3207c478bd9Sstevel@tonic-gate 
321*b4a44cf2SToomas Soome static crypto_kcf_provider_handle_t rsa_prov_handle = 0;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate int
_init(void)3247c478bd9Sstevel@tonic-gate _init(void)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	int ret;
3277c478bd9Sstevel@tonic-gate 
328d3b2efc7SAnthony Scarpino 	if ((ret = mod_install(&modlinkage)) != 0)
329d3b2efc7SAnthony Scarpino 		return (ret);
3307c478bd9Sstevel@tonic-gate 
331d3b2efc7SAnthony Scarpino 	/* Register with KCF.  If the registration fails, remove the module. */
332d3b2efc7SAnthony Scarpino 	if (crypto_register_provider(&rsa_prov_info, &rsa_prov_handle)) {
333d3b2efc7SAnthony Scarpino 		(void) mod_remove(&modlinkage);
334d3b2efc7SAnthony Scarpino 		return (EACCES);
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
337d3b2efc7SAnthony Scarpino 	return (0);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate int
_fini(void)3417c478bd9Sstevel@tonic-gate _fini(void)
3427c478bd9Sstevel@tonic-gate {
343d3b2efc7SAnthony Scarpino 	/* Unregister from KCF if module is registered */
344*b4a44cf2SToomas Soome 	if (rsa_prov_handle != 0) {
345d3b2efc7SAnthony Scarpino 		if (crypto_unregister_provider(rsa_prov_handle))
3467c478bd9Sstevel@tonic-gate 			return (EBUSY);
347d3b2efc7SAnthony Scarpino 
348*b4a44cf2SToomas Soome 		rsa_prov_handle = 0;
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)3557c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate /* ARGSUSED */
3617c478bd9Sstevel@tonic-gate static void
rsa_provider_status(crypto_provider_handle_t provider,uint_t * status)3627c478bd9Sstevel@tonic-gate rsa_provider_status(crypto_provider_handle_t provider, uint_t *status)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate 	*status = CRYPTO_PROVIDER_READY;
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate static int
check_mech_and_key(crypto_mechanism_t * mechanism,crypto_key_t * key)3687c478bd9Sstevel@tonic-gate check_mech_and_key(crypto_mechanism_t *mechanism, crypto_key_t *key)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	uchar_t *modulus;
3737c478bd9Sstevel@tonic-gate 	ssize_t modulus_len; /* In bytes */
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	if (!RSA_VALID_MECH(mechanism))
3767c478bd9Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	/*
3797c478bd9Sstevel@tonic-gate 	 * We only support RSA keys that are passed as a list of
3807c478bd9Sstevel@tonic-gate 	 * object attributes.
3817c478bd9Sstevel@tonic-gate 	 */
3827c478bd9Sstevel@tonic-gate 	if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
3837c478bd9Sstevel@tonic-gate 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 
38623c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
3877c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
3887c478bd9Sstevel@tonic-gate 		return (rv);
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 	if (modulus_len < MIN_RSA_KEYLENGTH_IN_BYTES ||
3917c478bd9Sstevel@tonic-gate 	    modulus_len > MAX_RSA_KEYLENGTH_IN_BYTES)
3927c478bd9Sstevel@tonic-gate 		return (CRYPTO_KEY_SIZE_RANGE);
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	return (rv);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate void
kmemset(uint8_t * buf,char pattern,size_t len)3987c478bd9Sstevel@tonic-gate kmemset(uint8_t *buf, char pattern, size_t len)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate 	int i = 0;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	while (i < len)
4037c478bd9Sstevel@tonic-gate 		buf[i++] = pattern;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate  * This function guarantees to return non-zero random numbers.
4087c478bd9Sstevel@tonic-gate  * This is needed as the /dev/urandom kernel interface,
4097c478bd9Sstevel@tonic-gate  * random_get_pseudo_bytes(), may return zeros.
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate int
knzero_random_generator(uint8_t * ran_out,size_t ran_len)4127c478bd9Sstevel@tonic-gate knzero_random_generator(uint8_t *ran_out, size_t ran_len)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	int rv;
4157c478bd9Sstevel@tonic-gate 	size_t ebc = 0; /* count of extra bytes in extrarand */
4167c478bd9Sstevel@tonic-gate 	size_t i = 0;
4177c478bd9Sstevel@tonic-gate 	uint8_t extrarand[32];
4187c478bd9Sstevel@tonic-gate 	size_t extrarand_len;
4197c478bd9Sstevel@tonic-gate 
4206ea3c060SGarrett D'Amore 	if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0)
4217c478bd9Sstevel@tonic-gate 		return (rv);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	/*
4247c478bd9Sstevel@tonic-gate 	 * Walk through the returned random numbers pointed by ran_out,
4257c478bd9Sstevel@tonic-gate 	 * and look for any random number which is zero.
4267c478bd9Sstevel@tonic-gate 	 * If we find zero, call random_get_pseudo_bytes() to generate
4277c478bd9Sstevel@tonic-gate 	 * another 32 random numbers pool. Replace any zeros in ran_out[]
4287c478bd9Sstevel@tonic-gate 	 * from the random number in pool.
4297c478bd9Sstevel@tonic-gate 	 */
4307c478bd9Sstevel@tonic-gate 	while (i < ran_len) {
4317c478bd9Sstevel@tonic-gate 		if (ran_out[i] != 0) {
4327c478bd9Sstevel@tonic-gate 			i++;
4337c478bd9Sstevel@tonic-gate 			continue;
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 		/*
4377c478bd9Sstevel@tonic-gate 		 * Note that it is 'while' so we are guaranteed a
4387c478bd9Sstevel@tonic-gate 		 * non-zero value on exit.
4397c478bd9Sstevel@tonic-gate 		 */
4407c478bd9Sstevel@tonic-gate 		if (ebc == 0) {
4417c478bd9Sstevel@tonic-gate 			/* refresh extrarand */
4427c478bd9Sstevel@tonic-gate 			extrarand_len = sizeof (extrarand);
4436ea3c060SGarrett D'Amore 			if ((rv = random_get_pseudo_bytes(extrarand,
4447c478bd9Sstevel@tonic-gate 			    extrarand_len)) != 0) {
4457c478bd9Sstevel@tonic-gate 				return (rv);
4467c478bd9Sstevel@tonic-gate 			}
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 			ebc = extrarand_len;
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 		/* Replace zero with byte from extrarand. */
4517c478bd9Sstevel@tonic-gate 		-- ebc;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 		/*
4547c478bd9Sstevel@tonic-gate 		 * The new random byte zero/non-zero will be checked in
4557c478bd9Sstevel@tonic-gate 		 * the next pass through the loop.
4567c478bd9Sstevel@tonic-gate 		 */
4577c478bd9Sstevel@tonic-gate 		ran_out[i] = extrarand[ebc];
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate static int
compare_data(crypto_data_t * data,uchar_t * buf)4647c478bd9Sstevel@tonic-gate compare_data(crypto_data_t *data, uchar_t *buf)
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate 	int len;
4677c478bd9Sstevel@tonic-gate 	uchar_t *dptr;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	len = data->cd_length;
4707c478bd9Sstevel@tonic-gate 	switch (data->cd_format) {
4717c478bd9Sstevel@tonic-gate 	case CRYPTO_DATA_RAW:
4727c478bd9Sstevel@tonic-gate 		dptr = (uchar_t *)(data->cd_raw.iov_base +
4737c478bd9Sstevel@tonic-gate 		    data->cd_offset);
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		return (bcmp(dptr, buf, len));
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	case CRYPTO_DATA_UIO:
47823c57df7Smcpowers 		return (crypto_uio_data(data, buf, len,
47923c57df7Smcpowers 		    COMPARE_TO_DATA, NULL, NULL));
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	case CRYPTO_DATA_MBLK:
48223c57df7Smcpowers 		return (crypto_mblk_data(data, buf, len,
48323c57df7Smcpowers 		    COMPARE_TO_DATA, NULL, NULL));
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	return (CRYPTO_FAILED);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate /* ARGSUSED */
4907c478bd9Sstevel@tonic-gate static int
rsa_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t template,crypto_req_handle_t req)4917c478bd9Sstevel@tonic-gate rsa_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4927c478bd9Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t template,
4937c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	int rv;
4967c478bd9Sstevel@tonic-gate 	int kmflag;
4977c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
5007c478bd9Sstevel@tonic-gate 		return (rv);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/*
5037c478bd9Sstevel@tonic-gate 	 * Allocate a RSA context.
5047c478bd9Sstevel@tonic-gate 	 */
5057c478bd9Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
5067c478bd9Sstevel@tonic-gate 	if ((ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag)) == NULL)
5077c478bd9Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
5087c478bd9Sstevel@tonic-gate 
50923c57df7Smcpowers 	if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size,
51023c57df7Smcpowers 	    kmflag)) != CRYPTO_SUCCESS) {
5117c478bd9Sstevel@tonic-gate 		kmem_free(ctxp, sizeof (rsa_ctx_t));
5127c478bd9Sstevel@tonic-gate 		return (rv);
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate /* ARGSUSED */
5227c478bd9Sstevel@tonic-gate static int
rsaprov_encrypt(crypto_ctx_t * ctx,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_req_handle_t req)523726fad2aSDina K Nimeh rsaprov_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
5247c478bd9Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_req_handle_t req)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate 	int rv;
5277c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
5307c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	/*
5357c478bd9Sstevel@tonic-gate 	 * Note on the KM_SLEEP flag passed to the routine below -
536726fad2aSDina K Nimeh 	 * rsaprov_encrypt() is a single-part encryption routine which is
5377c478bd9Sstevel@tonic-gate 	 * currently usable only by /dev/crypto. Since /dev/crypto calls are
5387c478bd9Sstevel@tonic-gate 	 * always synchronous, we can safely pass KM_SLEEP here.
5397c478bd9Sstevel@tonic-gate 	 */
5407c478bd9Sstevel@tonic-gate 	rv = rsa_encrypt_common(ctxp->mech_type, ctxp->key, plaintext,
541726fad2aSDina K Nimeh 	    ciphertext);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
5447c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	return (rv);
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate /* ARGSUSED */
5507c478bd9Sstevel@tonic-gate static int
rsa_encrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)5517c478bd9Sstevel@tonic-gate rsa_encrypt_atomic(crypto_provider_handle_t provider,
5527c478bd9Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
5537c478bd9Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
5547c478bd9Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
5557c478bd9Sstevel@tonic-gate {
5567c478bd9Sstevel@tonic-gate 	int rv;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
5597c478bd9Sstevel@tonic-gate 		return (rv);
5607c478bd9Sstevel@tonic-gate 	RSA_ARG_INPLACE(plaintext, ciphertext);
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	return (rsa_encrypt_common(mechanism->cm_type, key, plaintext,
563726fad2aSDina K Nimeh 	    ciphertext));
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate static int
rsa_free_context(crypto_ctx_t * ctx)5677c478bd9Sstevel@tonic-gate rsa_free_context(crypto_ctx_t *ctx)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp = ctx->cc_provider_private;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	if (ctxp != NULL) {
5727c478bd9Sstevel@tonic-gate 		bzero(ctxp->key, ctxp->keychunk_size);
5737c478bd9Sstevel@tonic-gate 		kmem_free(ctxp->key, ctxp->keychunk_size);
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 		if (ctxp->mech_type == RSA_PKCS_MECH_INFO_TYPE ||
5767c478bd9Sstevel@tonic-gate 		    ctxp->mech_type == RSA_X_509_MECH_INFO_TYPE)
5777c478bd9Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
5787c478bd9Sstevel@tonic-gate 		else
5797c478bd9Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (digest_rsa_ctx_t));
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 		ctx->cc_provider_private = NULL;
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate static int
rsa_encrypt_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext)5887c478bd9Sstevel@tonic-gate rsa_encrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
589726fad2aSDina K Nimeh     crypto_data_t *plaintext, crypto_data_t *ciphertext)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	int plen;
5947c478bd9Sstevel@tonic-gate 	uchar_t *ptptr;
5957c478bd9Sstevel@tonic-gate 	uchar_t *modulus;
5967c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
5977c478bd9Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
5987c478bd9Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
5997c478bd9Sstevel@tonic-gate 	uchar_t cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES];
6007c478bd9Sstevel@tonic-gate 
60123c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
6027c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
6037c478bd9Sstevel@tonic-gate 		return (rv);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	plen = plaintext->cd_length;
6077c478bd9Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
6087c478bd9Sstevel@tonic-gate 		if (plen > (modulus_len - MIN_PKCS1_PADLEN))
6097c478bd9Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
6107c478bd9Sstevel@tonic-gate 	} else {
6117c478bd9Sstevel@tonic-gate 		if (plen > modulus_len)
6127c478bd9Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	/*
6167c478bd9Sstevel@tonic-gate 	 * Output buf len must not be less than RSA modulus size.
6177c478bd9Sstevel@tonic-gate 	 */
6187c478bd9Sstevel@tonic-gate 	if (ciphertext->cd_length < modulus_len) {
6197c478bd9Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
6207c478bd9Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	ASSERT(plaintext->cd_length <= sizeof (tmp_data));
62423c57df7Smcpowers 	if ((rv = crypto_get_input_data(plaintext, &ptptr, tmp_data))
6257c478bd9Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
6267c478bd9Sstevel@tonic-gate 		return (rv);
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
629726fad2aSDina K Nimeh 		rv = pkcs1_encode(PKCS1_ENCRYPT, ptptr, plen,
6307c478bd9Sstevel@tonic-gate 		    plain_data, modulus_len);
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
6337c478bd9Sstevel@tonic-gate 			return (rv);
6347c478bd9Sstevel@tonic-gate 	} else {
6357c478bd9Sstevel@tonic-gate 		bzero(plain_data, modulus_len - plen);
6367c478bd9Sstevel@tonic-gate 		bcopy(ptptr, &plain_data[modulus_len - plen], plen);
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 
639726fad2aSDina K Nimeh 	rv = core_rsa_encrypt(key, plain_data, modulus_len, cipher_data, 1);
6407c478bd9Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
6417c478bd9Sstevel@tonic-gate 		/* copy out to ciphertext */
64223c57df7Smcpowers 		if ((rv = crypto_put_output_data(cipher_data,
6437c478bd9Sstevel@tonic-gate 		    ciphertext, modulus_len)) != CRYPTO_SUCCESS)
6447c478bd9Sstevel@tonic-gate 			return (rv);
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 		ciphertext->cd_length = modulus_len;
6477c478bd9Sstevel@tonic-gate 	}
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	return (rv);
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate static int
core_rsa_encrypt(crypto_key_t * key,uchar_t * in,int in_len,uchar_t * out,int is_public)6537c478bd9Sstevel@tonic-gate core_rsa_encrypt(crypto_key_t *key, uchar_t *in,
654726fad2aSDina K Nimeh     int in_len, uchar_t *out, int is_public)
6557c478bd9Sstevel@tonic-gate {
6567c478bd9Sstevel@tonic-gate 	int rv;
6577c478bd9Sstevel@tonic-gate 	uchar_t *expo, *modulus;
6587c478bd9Sstevel@tonic-gate 	ssize_t	expo_len;
6597c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
660726fad2aSDina K Nimeh 	RSAbytekey k;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	if (is_public) {
66323c57df7Smcpowers 		if ((rv = crypto_get_key_attr(key, SUN_CKA_PUBLIC_EXPONENT,
66423c57df7Smcpowers 		    &expo, &expo_len)) != CRYPTO_SUCCESS)
6657c478bd9Sstevel@tonic-gate 			return (rv);
6667c478bd9Sstevel@tonic-gate 	} else {
6677c478bd9Sstevel@tonic-gate 		/*
6687c478bd9Sstevel@tonic-gate 		 * SUN_CKA_PRIVATE_EXPONENT is a required attribute for a
6697c478bd9Sstevel@tonic-gate 		 * RSA secret key. See the comments in core_rsa_decrypt
6707c478bd9Sstevel@tonic-gate 		 * routine which calls this routine with a private key.
6717c478bd9Sstevel@tonic-gate 		 */
67223c57df7Smcpowers 		if ((rv = crypto_get_key_attr(key, SUN_CKA_PRIVATE_EXPONENT,
67323c57df7Smcpowers 		    &expo, &expo_len)) != CRYPTO_SUCCESS)
6747c478bd9Sstevel@tonic-gate 			return (rv);
6757c478bd9Sstevel@tonic-gate 	}
6767c478bd9Sstevel@tonic-gate 
67723c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
6787c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
6797c478bd9Sstevel@tonic-gate 		return (rv);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 
682726fad2aSDina K Nimeh 	k.modulus = modulus;
683726fad2aSDina K Nimeh 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
684726fad2aSDina K Nimeh 	k.pubexpo = expo;
685726fad2aSDina K Nimeh 	k.pubexpo_bytes = expo_len;
686726fad2aSDina K Nimeh 	k.rfunc = NULL;
6877c478bd9Sstevel@tonic-gate 
688726fad2aSDina K Nimeh 	rv = rsa_encrypt(&k, in, in_len, out);
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	return (rv);
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate /* ARGSUSED */
6947c478bd9Sstevel@tonic-gate static int
rsaprov_decrypt(crypto_ctx_t * ctx,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_req_handle_t req)695726fad2aSDina K Nimeh rsaprov_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
6967c478bd9Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_req_handle_t req)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate 	int rv;
6997c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
7027c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
7057c478bd9Sstevel@tonic-gate 
706726fad2aSDina K Nimeh 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
7077c478bd9Sstevel@tonic-gate 	rv = rsa_decrypt_common(ctxp->mech_type, ctxp->key,
708726fad2aSDina K Nimeh 	    ciphertext, plaintext);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
7117c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	return (rv);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate /* ARGSUSED */
7177c478bd9Sstevel@tonic-gate static int
rsa_decrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)7187c478bd9Sstevel@tonic-gate rsa_decrypt_atomic(crypto_provider_handle_t provider,
7197c478bd9Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
7207c478bd9Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
7217c478bd9Sstevel@tonic-gate     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate 	int rv;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
7267c478bd9Sstevel@tonic-gate 		return (rv);
7277c478bd9Sstevel@tonic-gate 	RSA_ARG_INPLACE(ciphertext, plaintext);
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	return (rsa_decrypt_common(mechanism->cm_type, key, ciphertext,
730726fad2aSDina K Nimeh 	    plaintext));
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate static int
rsa_decrypt_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext)7347c478bd9Sstevel@tonic-gate rsa_decrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key,
735726fad2aSDina K Nimeh     crypto_data_t *ciphertext, crypto_data_t *plaintext)
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
7387c478bd9Sstevel@tonic-gate 
739726fad2aSDina K Nimeh 	size_t plain_len;
7407c478bd9Sstevel@tonic-gate 	uchar_t *ctptr;
7417c478bd9Sstevel@tonic-gate 	uchar_t *modulus;
7427c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
7437c478bd9Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
7447c478bd9Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
7457c478bd9Sstevel@tonic-gate 
74623c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
7477c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
7487c478bd9Sstevel@tonic-gate 		return (rv);
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	/*
7527c478bd9Sstevel@tonic-gate 	 * Ciphertext length must be equal to RSA modulus size.
7537c478bd9Sstevel@tonic-gate 	 */
7547c478bd9Sstevel@tonic-gate 	if (ciphertext->cd_length != modulus_len)
7557c478bd9Sstevel@tonic-gate 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	ASSERT(ciphertext->cd_length <= sizeof (tmp_data));
75823c57df7Smcpowers 	if ((rv = crypto_get_input_data(ciphertext, &ctptr, tmp_data))
7597c478bd9Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
7607c478bd9Sstevel@tonic-gate 		return (rv);
7617c478bd9Sstevel@tonic-gate 
762726fad2aSDina K Nimeh 	rv = core_rsa_decrypt(key, ctptr, modulus_len, plain_data);
7637c478bd9Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
7647c478bd9Sstevel@tonic-gate 		plain_len = modulus_len;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 		if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
7677c478bd9Sstevel@tonic-gate 			/* Strip off the PKCS block formatting data. */
768726fad2aSDina K Nimeh 			rv = pkcs1_decode(PKCS1_DECRYPT, plain_data,
7697c478bd9Sstevel@tonic-gate 			    &plain_len);
7707c478bd9Sstevel@tonic-gate 			if (rv != CRYPTO_SUCCESS)
7717c478bd9Sstevel@tonic-gate 				return (rv);
7727c478bd9Sstevel@tonic-gate 		}
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 		if (plain_len > plaintext->cd_length) {
7757c478bd9Sstevel@tonic-gate 			plaintext->cd_length = plain_len;
7767c478bd9Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
7777c478bd9Sstevel@tonic-gate 		}
7787c478bd9Sstevel@tonic-gate 
77923c57df7Smcpowers 		if ((rv = crypto_put_output_data(
78023c57df7Smcpowers 		    plain_data + modulus_len - plain_len,
7817c478bd9Sstevel@tonic-gate 		    plaintext, plain_len)) != CRYPTO_SUCCESS)
7827c478bd9Sstevel@tonic-gate 			return (rv);
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		plaintext->cd_length = plain_len;
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	return (rv);
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate static int
core_rsa_decrypt(crypto_key_t * key,uchar_t * in,int in_len,uchar_t * out)791726fad2aSDina K Nimeh core_rsa_decrypt(crypto_key_t *key, uchar_t *in, int in_len, uchar_t *out)
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate 	int rv;
7947c478bd9Sstevel@tonic-gate 	uchar_t *modulus, *prime1, *prime2, *expo1, *expo2, *coef;
7957c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
7967c478bd9Sstevel@tonic-gate 	ssize_t	prime1_len, prime2_len;
7977c478bd9Sstevel@tonic-gate 	ssize_t	expo1_len, expo2_len, coef_len;
798726fad2aSDina K Nimeh 	RSAbytekey k;
7997c478bd9Sstevel@tonic-gate 
80023c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
8017c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
8027c478bd9Sstevel@tonic-gate 		return (rv);
8037c478bd9Sstevel@tonic-gate 	}
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 	/*
8067c478bd9Sstevel@tonic-gate 	 * The following attributes are not required to be
8077c478bd9Sstevel@tonic-gate 	 * present in a RSA secret key. If any of them is not present
8087c478bd9Sstevel@tonic-gate 	 * we call the encrypt routine with a flag indicating use of
8097c478bd9Sstevel@tonic-gate 	 * private exponent (d). Note that SUN_CKA_PRIVATE_EXPONENT is
8107c478bd9Sstevel@tonic-gate 	 * a required attribute for a RSA secret key.
8117c478bd9Sstevel@tonic-gate 	 */
81223c57df7Smcpowers 	if ((crypto_get_key_attr(key, SUN_CKA_PRIME_1, &prime1, &prime1_len)
813d2b32306Smcpowers 	    != CRYPTO_SUCCESS) ||
81423c57df7Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_PRIME_2, &prime2, &prime2_len)
815d2b32306Smcpowers 	    != CRYPTO_SUCCESS) ||
81623c57df7Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_EXPONENT_1, &expo1, &expo1_len)
817d2b32306Smcpowers 	    != CRYPTO_SUCCESS) ||
81823c57df7Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_EXPONENT_2, &expo2, &expo2_len)
819d2b32306Smcpowers 	    != CRYPTO_SUCCESS) ||
82023c57df7Smcpowers 	    (crypto_get_key_attr(key, SUN_CKA_COEFFICIENT, &coef, &coef_len)
821d2b32306Smcpowers 	    != CRYPTO_SUCCESS)) {
822726fad2aSDina K Nimeh 		return (core_rsa_encrypt(key, in, in_len, out, 0));
8237c478bd9Sstevel@tonic-gate 	}
8247c478bd9Sstevel@tonic-gate 
825726fad2aSDina K Nimeh 	k.modulus = modulus;
826726fad2aSDina K Nimeh 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
827726fad2aSDina K Nimeh 	k.prime1 = prime1;
828726fad2aSDina K Nimeh 	k.prime1_bytes = prime1_len;
829726fad2aSDina K Nimeh 	k.prime2 = prime2;
830726fad2aSDina K Nimeh 	k.prime2_bytes = prime2_len;
831726fad2aSDina K Nimeh 	k.expo1 = expo1;
832726fad2aSDina K Nimeh 	k.expo1_bytes = expo1_len;
833726fad2aSDina K Nimeh 	k.expo2 = expo2;
834726fad2aSDina K Nimeh 	k.expo2_bytes = expo2_len;
835726fad2aSDina K Nimeh 	k.coeff = coef;
836726fad2aSDina K Nimeh 	k.coeff_bytes = coef_len;
837726fad2aSDina K Nimeh 	k.rfunc = NULL;
838726fad2aSDina K Nimeh 
839726fad2aSDina K Nimeh 	rv = rsa_decrypt(&k, in, in_len, out);
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	return (rv);
8427c478bd9Sstevel@tonic-gate }
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate /* ARGSUSED */
8457c478bd9Sstevel@tonic-gate static int
rsa_sign_verify_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)8467c478bd9Sstevel@tonic-gate rsa_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
8477c478bd9Sstevel@tonic-gate     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
8487c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
8497c478bd9Sstevel@tonic-gate {
8507c478bd9Sstevel@tonic-gate 	int rv;
8517c478bd9Sstevel@tonic-gate 	int kmflag;
8527c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
8537c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t *dctxp;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
8567c478bd9Sstevel@tonic-gate 		return (rv);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	/*
8597c478bd9Sstevel@tonic-gate 	 * Allocate a RSA context.
8607c478bd9Sstevel@tonic-gate 	 */
8617c478bd9Sstevel@tonic-gate 	kmflag = crypto_kmflag(req);
8627c478bd9Sstevel@tonic-gate 	switch (mechanism->cm_type) {
8637c478bd9Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
8647c478bd9Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
865f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
866f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
867f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
8687c478bd9Sstevel@tonic-gate 		dctxp = kmem_zalloc(sizeof (digest_rsa_ctx_t), kmflag);
8697c478bd9Sstevel@tonic-gate 		ctxp = (rsa_ctx_t *)dctxp;
8707c478bd9Sstevel@tonic-gate 		break;
8717c478bd9Sstevel@tonic-gate 	default:
8727c478bd9Sstevel@tonic-gate 		ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag);
8737c478bd9Sstevel@tonic-gate 		break;
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	if (ctxp == NULL)
8777c478bd9Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	ctxp->mech_type = mechanism->cm_type;
88023c57df7Smcpowers 	if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size,
88123c57df7Smcpowers 	    kmflag)) != CRYPTO_SUCCESS) {
8827c478bd9Sstevel@tonic-gate 		switch (mechanism->cm_type) {
8837c478bd9Sstevel@tonic-gate 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
8847c478bd9Sstevel@tonic-gate 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
885f66d273dSizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
886f66d273dSizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
887f66d273dSizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
8887c478bd9Sstevel@tonic-gate 			kmem_free(dctxp, sizeof (digest_rsa_ctx_t));
8897c478bd9Sstevel@tonic-gate 			break;
8907c478bd9Sstevel@tonic-gate 		default:
8917c478bd9Sstevel@tonic-gate 			kmem_free(ctxp, sizeof (rsa_ctx_t));
8927c478bd9Sstevel@tonic-gate 			break;
8937c478bd9Sstevel@tonic-gate 		}
8947c478bd9Sstevel@tonic-gate 		return (rv);
8957c478bd9Sstevel@tonic-gate 	}
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	switch (mechanism->cm_type) {
8987c478bd9Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
8997c478bd9Sstevel@tonic-gate 		MD5Init(&(dctxp->md5_ctx));
9007c478bd9Sstevel@tonic-gate 		break;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
9037c478bd9Sstevel@tonic-gate 		SHA1Init(&(dctxp->sha1_ctx));
9047c478bd9Sstevel@tonic-gate 		break;
905f66d273dSizick 
906f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
907f66d273dSizick 		SHA2Init(SHA256, &(dctxp->sha2_ctx));
908f66d273dSizick 		break;
909f66d273dSizick 
910f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
911f66d273dSizick 		SHA2Init(SHA384, &(dctxp->sha2_ctx));
912f66d273dSizick 		break;
913f66d273dSizick 
914f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
915f66d273dSizick 		SHA2Init(SHA512, &(dctxp->sha2_ctx));
916f66d273dSizick 		break;
9177c478bd9Sstevel@tonic-gate 	}
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 	ctx->cc_provider_private = ctxp;
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate #define	SHA1_DIGEST_SIZE 20
9257c478bd9Sstevel@tonic-gate #define	MD5_DIGEST_SIZE 16
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate #define	INIT_RAW_CRYPTO_DATA(data, base, len, cd_len)	\
9287c478bd9Sstevel@tonic-gate 	(data).cd_format = CRYPTO_DATA_RAW;		\
9297c478bd9Sstevel@tonic-gate 	(data).cd_offset = 0;				\
9307c478bd9Sstevel@tonic-gate 	(data).cd_raw.iov_base = (char *)base;		\
9317c478bd9Sstevel@tonic-gate 	(data).cd_raw.iov_len = len;			\
9327c478bd9Sstevel@tonic-gate 	(data).cd_length = cd_len;
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate static int
rsa_digest_svrfy_common(digest_rsa_ctx_t * ctxp,crypto_data_t * data,crypto_data_t * signature,uchar_t flag)9357c478bd9Sstevel@tonic-gate rsa_digest_svrfy_common(digest_rsa_ctx_t *ctxp, crypto_data_t *data,
936726fad2aSDina K Nimeh     crypto_data_t *signature, uchar_t flag)
9377c478bd9Sstevel@tonic-gate {
9387c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
9397c478bd9Sstevel@tonic-gate 
940f66d273dSizick 	uchar_t digest[SHA512_DIGEST_LENGTH];
9417c478bd9Sstevel@tonic-gate 	/* The der_data size is enough for MD5 also */
942f66d273dSizick 	uchar_t der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
9437c478bd9Sstevel@tonic-gate 	ulong_t der_data_len;
9447c478bd9Sstevel@tonic-gate 	crypto_data_t der_cd;
9457c478bd9Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
9467c478bd9Sstevel@tonic-gate 
94723c57df7Smcpowers 	ASSERT(flag & CRYPTO_DO_SIGN || flag & CRYPTO_DO_VERIFY);
94823c57df7Smcpowers 	ASSERT(data != NULL || (flag & CRYPTO_DO_FINAL));
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
951f66d273dSizick 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
952f66d273dSizick 	    mech_type == RSA_X_509_MECH_INFO_TYPE)
9537c478bd9Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	/*
9567c478bd9Sstevel@tonic-gate 	 * We need to do the BUFFER_TOO_SMALL check before digesting
9577c478bd9Sstevel@tonic-gate 	 * the data. No check is needed for verify as signature is not
9587c478bd9Sstevel@tonic-gate 	 * an output argument for verify.
9597c478bd9Sstevel@tonic-gate 	 */
96023c57df7Smcpowers 	if (flag & CRYPTO_DO_SIGN) {
9617c478bd9Sstevel@tonic-gate 		uchar_t *modulus;
9627c478bd9Sstevel@tonic-gate 		ssize_t modulus_len;
9637c478bd9Sstevel@tonic-gate 
96423c57df7Smcpowers 		if ((rv = crypto_get_key_attr(ctxp->key, SUN_CKA_MODULUS,
96523c57df7Smcpowers 		    &modulus, &modulus_len)) != CRYPTO_SUCCESS) {
9667c478bd9Sstevel@tonic-gate 			return (rv);
9677c478bd9Sstevel@tonic-gate 		}
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 		if (signature->cd_length < modulus_len) {
9707c478bd9Sstevel@tonic-gate 			signature->cd_length = modulus_len;
9717c478bd9Sstevel@tonic-gate 			return (CRYPTO_BUFFER_TOO_SMALL);
9727c478bd9Sstevel@tonic-gate 		}
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
97623c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->md5_ctx),
97723c57df7Smcpowers 		    digest, MD5Update, MD5Final, flag | CRYPTO_DO_MD5);
978f66d273dSizick 
979f66d273dSizick 	else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE)
98023c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
98123c57df7Smcpowers 		    digest, SHA1Update, SHA1Final,  flag | CRYPTO_DO_SHA1);
982f66d273dSizick 
983f66d273dSizick 	else
98423c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha2_ctx),
98523c57df7Smcpowers 		    digest, SHA2Update, SHA2Final, flag | CRYPTO_DO_SHA2);
986f66d273dSizick 
9877c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
9887c478bd9Sstevel@tonic-gate 		return (rv);
9897c478bd9Sstevel@tonic-gate 
990f66d273dSizick 
9917c478bd9Sstevel@tonic-gate 	/*
9927c478bd9Sstevel@tonic-gate 	 * Prepare the DER encoding of the DigestInfo value as follows:
9937c478bd9Sstevel@tonic-gate 	 * MD5:		MD5_DER_PREFIX || H
9947c478bd9Sstevel@tonic-gate 	 * SHA-1:	SHA1_DER_PREFIX || H
9957c478bd9Sstevel@tonic-gate 	 *
9967c478bd9Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
9977c478bd9Sstevel@tonic-gate 	 */
998f66d273dSizick 	switch (mech_type) {
999f66d273dSizick 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
10007c478bd9Sstevel@tonic-gate 		bcopy(MD5_DER_PREFIX, der_data, MD5_DER_PREFIX_Len);
1001f66d273dSizick 		bcopy(digest, der_data + MD5_DER_PREFIX_Len, MD5_DIGEST_SIZE);
1002f66d273dSizick 		der_data_len = MD5_DER_PREFIX_Len + MD5_DIGEST_SIZE;
1003f66d273dSizick 		break;
1004f66d273dSizick 
1005f66d273dSizick 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
10067c478bd9Sstevel@tonic-gate 		bcopy(SHA1_DER_PREFIX, der_data, SHA1_DER_PREFIX_Len);
1007f66d273dSizick 		bcopy(digest, der_data + SHA1_DER_PREFIX_Len,
1008f66d273dSizick 		    SHA1_DIGEST_SIZE);
1009f66d273dSizick 		der_data_len = SHA1_DER_PREFIX_Len + SHA1_DIGEST_SIZE;
1010f66d273dSizick 		break;
1011f66d273dSizick 
1012f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1013f66d273dSizick 		bcopy(SHA256_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1014f66d273dSizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1015f66d273dSizick 		    SHA256_DIGEST_LENGTH);
1016f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA256_DIGEST_LENGTH;
1017f66d273dSizick 		break;
1018f66d273dSizick 
1019f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1020f66d273dSizick 		bcopy(SHA384_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1021f66d273dSizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1022f66d273dSizick 		    SHA384_DIGEST_LENGTH);
1023f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA384_DIGEST_LENGTH;
1024f66d273dSizick 		break;
1025f66d273dSizick 
1026f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1027f66d273dSizick 		bcopy(SHA512_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len);
1028f66d273dSizick 		bcopy(digest, der_data + SHA2_DER_PREFIX_Len,
1029f66d273dSizick 		    SHA512_DIGEST_LENGTH);
1030f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + SHA512_DIGEST_LENGTH;
1031f66d273dSizick 		break;
10327c478bd9Sstevel@tonic-gate 	}
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	INIT_RAW_CRYPTO_DATA(der_cd, der_data, der_data_len, der_data_len);
10357c478bd9Sstevel@tonic-gate 	/*
10367c478bd9Sstevel@tonic-gate 	 * Now, we are ready to sign or verify the DER_ENCODED data.
10377c478bd9Sstevel@tonic-gate 	 */
103823c57df7Smcpowers 	if (flag & CRYPTO_DO_SIGN)
10397c478bd9Sstevel@tonic-gate 		rv = rsa_sign_common(mech_type, ctxp->key, &der_cd,
1040726fad2aSDina K Nimeh 		    signature);
10417c478bd9Sstevel@tonic-gate 	else
10427c478bd9Sstevel@tonic-gate 		rv = rsa_verify_common(mech_type, ctxp->key, &der_cd,
1043726fad2aSDina K Nimeh 		    signature);
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	return (rv);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate static int
rsa_sign_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature)10497c478bd9Sstevel@tonic-gate rsa_sign_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1050726fad2aSDina K Nimeh     crypto_data_t *data, crypto_data_t *signature)
10517c478bd9Sstevel@tonic-gate {
10527c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 	int dlen;
10557c478bd9Sstevel@tonic-gate 	uchar_t *dataptr, *modulus;
10567c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
10577c478bd9Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
10587c478bd9Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
10597c478bd9Sstevel@tonic-gate 	uchar_t signed_data[MAX_RSA_KEYLENGTH_IN_BYTES];
10607c478bd9Sstevel@tonic-gate 
106123c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
10627c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
10637c478bd9Sstevel@tonic-gate 		return (rv);
10647c478bd9Sstevel@tonic-gate 	}
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	dlen = data->cd_length;
10677c478bd9Sstevel@tonic-gate 	switch (mech_type) {
10687c478bd9Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
10697c478bd9Sstevel@tonic-gate 		if (dlen > (modulus_len - MIN_PKCS1_PADLEN))
10707c478bd9Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
10717c478bd9Sstevel@tonic-gate 		break;
10727c478bd9Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
10737c478bd9Sstevel@tonic-gate 		if (dlen > modulus_len)
10747c478bd9Sstevel@tonic-gate 			return (CRYPTO_DATA_LEN_RANGE);
10757c478bd9Sstevel@tonic-gate 		break;
10767c478bd9Sstevel@tonic-gate 	}
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	if (signature->cd_length < modulus_len) {
10797c478bd9Sstevel@tonic-gate 		signature->cd_length = modulus_len;
10807c478bd9Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	ASSERT(data->cd_length <= sizeof (tmp_data));
108423c57df7Smcpowers 	if ((rv = crypto_get_input_data(data, &dataptr, tmp_data))
10857c478bd9Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
10867c478bd9Sstevel@tonic-gate 		return (rv);
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 	switch (mech_type) {
10897c478bd9Sstevel@tonic-gate 	case RSA_PKCS_MECH_INFO_TYPE:
10907c478bd9Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
10917c478bd9Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1092f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1093f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1094f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
10957c478bd9Sstevel@tonic-gate 		/*
10967c478bd9Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
10977c478bd9Sstevel@tonic-gate 		 * type "01" encryption block.
10987c478bd9Sstevel@tonic-gate 		 */
1099726fad2aSDina K Nimeh 		rv = pkcs1_encode(PKCS1_SIGN, dataptr, dlen, plain_data,
11007c478bd9Sstevel@tonic-gate 		    modulus_len);
11017c478bd9Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
11027c478bd9Sstevel@tonic-gate 			return (rv);
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 		break;
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 	case RSA_X_509_MECH_INFO_TYPE:
11077c478bd9Sstevel@tonic-gate 		bzero(plain_data, modulus_len - dlen);
11087c478bd9Sstevel@tonic-gate 		bcopy(dataptr, &plain_data[modulus_len - dlen], dlen);
11097c478bd9Sstevel@tonic-gate 		break;
11107c478bd9Sstevel@tonic-gate 	}
11117c478bd9Sstevel@tonic-gate 
1112726fad2aSDina K Nimeh 	rv = core_rsa_decrypt(key, plain_data, modulus_len, signed_data);
11137c478bd9Sstevel@tonic-gate 	if (rv == CRYPTO_SUCCESS) {
11147c478bd9Sstevel@tonic-gate 		/* copy out to signature */
111523c57df7Smcpowers 		if ((rv = crypto_put_output_data(signed_data,
11167c478bd9Sstevel@tonic-gate 		    signature, modulus_len)) != CRYPTO_SUCCESS)
11177c478bd9Sstevel@tonic-gate 			return (rv);
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 		signature->cd_length = modulus_len;
11207c478bd9Sstevel@tonic-gate 	}
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	return (rv);
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate /* ARGSUSED */
11267c478bd9Sstevel@tonic-gate static int
rsaprov_sign(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)1127726fad2aSDina K Nimeh rsaprov_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
11287c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
11297c478bd9Sstevel@tonic-gate {
11307c478bd9Sstevel@tonic-gate 	int rv;
11317c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
11347c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
11357c478bd9Sstevel@tonic-gate 
1136726fad2aSDina K Nimeh 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
11377c478bd9Sstevel@tonic-gate 	switch (ctxp->mech_type) {
11387c478bd9Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
11397c478bd9Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1140f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1141f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1142f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
11437c478bd9Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
1144726fad2aSDina K Nimeh 		    signature, CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE |
114523c57df7Smcpowers 		    CRYPTO_DO_FINAL);
11467c478bd9Sstevel@tonic-gate 		break;
11477c478bd9Sstevel@tonic-gate 	default:
11487c478bd9Sstevel@tonic-gate 		rv = rsa_sign_common(ctxp->mech_type, ctxp->key, data,
1149726fad2aSDina K Nimeh 		    signature);
11507c478bd9Sstevel@tonic-gate 		break;
11517c478bd9Sstevel@tonic-gate 	}
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
11547c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	return (rv);
11577c478bd9Sstevel@tonic-gate }
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate /* ARGSUSED */
11607c478bd9Sstevel@tonic-gate static int
rsa_sign_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)11617c478bd9Sstevel@tonic-gate rsa_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
11627c478bd9Sstevel@tonic-gate {
11637c478bd9Sstevel@tonic-gate 	int rv;
11647c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
11657c478bd9Sstevel@tonic-gate 	rsa_mech_type_t mech_type;
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
11687c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
11697c478bd9Sstevel@tonic-gate 	mech_type = ctxp->mech_type;
11707c478bd9Sstevel@tonic-gate 
1171f66d273dSizick 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
1172f66d273dSizick 	    mech_type == RSA_X_509_MECH_INFO_TYPE)
11737c478bd9Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 	if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE)
117623c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->md5_ctx),
117723c57df7Smcpowers 		    NULL, MD5Update, MD5Final,
117823c57df7Smcpowers 		    CRYPTO_DO_MD5 | CRYPTO_DO_UPDATE);
1179f66d273dSizick 
1180f66d273dSizick 	else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE)
118123c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
118223c57df7Smcpowers 		    NULL, SHA1Update, SHA1Final, CRYPTO_DO_SHA1 |
118323c57df7Smcpowers 		    CRYPTO_DO_UPDATE);
1184f66d273dSizick 
1185f66d273dSizick 	else
118623c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha2_ctx),
118723c57df7Smcpowers 		    NULL, SHA2Update, SHA2Final, CRYPTO_DO_SHA2 |
118823c57df7Smcpowers 		    CRYPTO_DO_UPDATE);
1189f66d273dSizick 
11907c478bd9Sstevel@tonic-gate 	return (rv);
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate 
1193726fad2aSDina K Nimeh /* ARGSUSED2 */
11947c478bd9Sstevel@tonic-gate static int
rsa_sign_final(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_req_handle_t req)11957c478bd9Sstevel@tonic-gate rsa_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
11967c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
11977c478bd9Sstevel@tonic-gate {
11987c478bd9Sstevel@tonic-gate 	int rv;
11997c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
12027c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
1205726fad2aSDina K Nimeh 	    CRYPTO_DO_SIGN | CRYPTO_DO_FINAL);
12067c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
12077c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 	return (rv);
12107c478bd9Sstevel@tonic-gate }
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate /* ARGSUSED */
12137c478bd9Sstevel@tonic-gate static int
rsa_sign_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)12147c478bd9Sstevel@tonic-gate rsa_sign_atomic(crypto_provider_handle_t provider,
12157c478bd9Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
12167c478bd9Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
12177c478bd9Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
12187c478bd9Sstevel@tonic-gate {
12197c478bd9Sstevel@tonic-gate 	int rv;
12207c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
12237c478bd9Sstevel@tonic-gate 		return (rv);
12247c478bd9Sstevel@tonic-gate 
1225f66d273dSizick 	if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE ||
1226f66d273dSizick 	    mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE)
1227f66d273dSizick 		rv = rsa_sign_common(mechanism->cm_type, key, data,
1228726fad2aSDina K Nimeh 		    signature);
1229f66d273dSizick 
1230f66d273dSizick 	else {
12317c478bd9Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
12327c478bd9Sstevel@tonic-gate 		dctx.key = key;
1233f66d273dSizick 		switch (mechanism->cm_type) {
1234f66d273dSizick 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
12357c478bd9Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1236f66d273dSizick 			break;
1237f66d273dSizick 
1238f66d273dSizick 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
12397c478bd9Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1240f66d273dSizick 			break;
1241f66d273dSizick 
1242f66d273dSizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1243f66d273dSizick 			SHA2Init(SHA256, &(dctx.sha2_ctx));
1244f66d273dSizick 			break;
1245f66d273dSizick 
1246f66d273dSizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1247f66d273dSizick 			SHA2Init(SHA384, &(dctx.sha2_ctx));
1248f66d273dSizick 			break;
1249f66d273dSizick 
1250f66d273dSizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1251f66d273dSizick 			SHA2Init(SHA512, &(dctx.sha2_ctx));
1252f66d273dSizick 			break;
1253f66d273dSizick 		}
1254f66d273dSizick 
1255f66d273dSizick 		rv = rsa_digest_svrfy_common(&dctx, data, signature,
1256726fad2aSDina K Nimeh 		    CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL);
12577c478bd9Sstevel@tonic-gate 	}
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	return (rv);
12607c478bd9Sstevel@tonic-gate }
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate static int
rsa_verify_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature)12637c478bd9Sstevel@tonic-gate rsa_verify_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1264726fad2aSDina K Nimeh     crypto_data_t *data, crypto_data_t *signature)
12657c478bd9Sstevel@tonic-gate {
12667c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
12697c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
12707c478bd9Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
12717c478bd9Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
12727c478bd9Sstevel@tonic-gate 
127323c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
12747c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
12757c478bd9Sstevel@tonic-gate 		return (rv);
12767c478bd9Sstevel@tonic-gate 	}
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
12797c478bd9Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
128223c57df7Smcpowers 	if ((rv = crypto_get_input_data(signature, &sigptr, tmp_data))
12837c478bd9Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
12847c478bd9Sstevel@tonic-gate 		return (rv);
12857c478bd9Sstevel@tonic-gate 
1286726fad2aSDina K Nimeh 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, 1);
12877c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
12887c478bd9Sstevel@tonic-gate 		return (rv);
12897c478bd9Sstevel@tonic-gate 
1290f66d273dSizick 	if (mech_type == RSA_X_509_MECH_INFO_TYPE) {
1291f66d273dSizick 		if (compare_data(data, (plain_data + modulus_len
1292f66d273dSizick 		    - data->cd_length)) != 0)
1293f66d273dSizick 			rv = CRYPTO_SIGNATURE_INVALID;
1294f66d273dSizick 
1295f66d273dSizick 	} else {
1296726fad2aSDina K Nimeh 		size_t data_len = modulus_len;
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 		/*
12997c478bd9Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
13007c478bd9Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
13017c478bd9Sstevel@tonic-gate 		 * the original data.
13027c478bd9Sstevel@tonic-gate 		 */
1303726fad2aSDina K Nimeh 		rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
13047c478bd9Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
1305f66d273dSizick 			return (rv);
13067c478bd9Sstevel@tonic-gate 
1307f66d273dSizick 		if (data_len != data->cd_length)
1308f66d273dSizick 			return (CRYPTO_SIGNATURE_LEN_RANGE);
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 		if (compare_data(data, (plain_data + modulus_len
13117c478bd9Sstevel@tonic-gate 		    - data_len)) != 0)
13127c478bd9Sstevel@tonic-gate 			rv = CRYPTO_SIGNATURE_INVALID;
13137c478bd9Sstevel@tonic-gate 	}
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 	return (rv);
13167c478bd9Sstevel@tonic-gate }
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate /* ARGSUSED */
13197c478bd9Sstevel@tonic-gate static int
rsaprov_verify(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)1320726fad2aSDina K Nimeh rsaprov_verify(crypto_ctx_t *ctx, crypto_data_t *data,
1321726fad2aSDina K Nimeh     crypto_data_t *signature, crypto_req_handle_t req)
13227c478bd9Sstevel@tonic-gate {
13237c478bd9Sstevel@tonic-gate 	int rv;
13247c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
13277c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
13287c478bd9Sstevel@tonic-gate 
1329726fad2aSDina K Nimeh 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
13307c478bd9Sstevel@tonic-gate 	switch (ctxp->mech_type) {
13317c478bd9Sstevel@tonic-gate 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
13327c478bd9Sstevel@tonic-gate 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
1333f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1334f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1335f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
13367c478bd9Sstevel@tonic-gate 		rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data,
1337726fad2aSDina K Nimeh 		    signature, CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE |
133823c57df7Smcpowers 		    CRYPTO_DO_FINAL);
13397c478bd9Sstevel@tonic-gate 		break;
13407c478bd9Sstevel@tonic-gate 	default:
13417c478bd9Sstevel@tonic-gate 		rv = rsa_verify_common(ctxp->mech_type, ctxp->key, data,
1342726fad2aSDina K Nimeh 		    signature);
13437c478bd9Sstevel@tonic-gate 		break;
13447c478bd9Sstevel@tonic-gate 	}
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
13477c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	return (rv);
13507c478bd9Sstevel@tonic-gate }
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate /* ARGSUSED */
13537c478bd9Sstevel@tonic-gate static int
rsa_verify_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)13547c478bd9Sstevel@tonic-gate rsa_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
13557c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
13567c478bd9Sstevel@tonic-gate {
13577c478bd9Sstevel@tonic-gate 	int rv;
13587c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
13617c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
13627c478bd9Sstevel@tonic-gate 
1363f66d273dSizick 	switch (ctxp->mech_type) {
13647c478bd9Sstevel@tonic-gate 
1365f66d273dSizick 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
136623c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->md5_ctx),
136723c57df7Smcpowers 		    NULL, MD5Update, MD5Final, CRYPTO_DO_MD5 |
136823c57df7Smcpowers 		    CRYPTO_DO_UPDATE);
1369f66d273dSizick 		break;
1370f66d273dSizick 
1371f66d273dSizick 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
137223c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
137323c57df7Smcpowers 		    NULL, SHA1Update, SHA1Final, CRYPTO_DO_SHA1 |
137423c57df7Smcpowers 		    CRYPTO_DO_UPDATE);
1375f66d273dSizick 		break;
1376f66d273dSizick 
1377f66d273dSizick 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1378f66d273dSizick 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1379f66d273dSizick 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
138023c57df7Smcpowers 		rv = crypto_digest_data(data, &(ctxp->sha2_ctx),
138123c57df7Smcpowers 		    NULL, SHA2Update, SHA2Final, CRYPTO_DO_SHA2 |
138223c57df7Smcpowers 		    CRYPTO_DO_UPDATE);
1383f66d273dSizick 		break;
1384f66d273dSizick 
1385f66d273dSizick 	default:
1386f66d273dSizick 		return (CRYPTO_MECHANISM_INVALID);
1387f66d273dSizick 	}
1388f66d273dSizick 
13897c478bd9Sstevel@tonic-gate 	return (rv);
13907c478bd9Sstevel@tonic-gate }
13917c478bd9Sstevel@tonic-gate 
1392726fad2aSDina K Nimeh /* ARGSUSED2 */
13937c478bd9Sstevel@tonic-gate static int
rsa_verify_final(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_req_handle_t req)13947c478bd9Sstevel@tonic-gate rsa_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
13957c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
13967c478bd9Sstevel@tonic-gate {
13977c478bd9Sstevel@tonic-gate 	int rv;
13987c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t *ctxp;
13997c478bd9Sstevel@tonic-gate 
14007c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
14017c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	rv = rsa_digest_svrfy_common(ctxp, NULL, signature,
1404726fad2aSDina K Nimeh 	    CRYPTO_DO_VERIFY | CRYPTO_DO_FINAL);
14057c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
14067c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 	return (rv);
14097c478bd9Sstevel@tonic-gate }
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate /* ARGSUSED */
14137c478bd9Sstevel@tonic-gate static int
rsa_verify_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)14147c478bd9Sstevel@tonic-gate rsa_verify_atomic(crypto_provider_handle_t provider,
14157c478bd9Sstevel@tonic-gate     crypto_session_id_t session_id,
14167c478bd9Sstevel@tonic-gate     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
14177c478bd9Sstevel@tonic-gate     crypto_data_t *signature, crypto_spi_ctx_template_t ctx_template,
14187c478bd9Sstevel@tonic-gate     crypto_req_handle_t req)
14197c478bd9Sstevel@tonic-gate {
14207c478bd9Sstevel@tonic-gate 	int rv;
14217c478bd9Sstevel@tonic-gate 	digest_rsa_ctx_t dctx;
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
14247c478bd9Sstevel@tonic-gate 		return (rv);
14257c478bd9Sstevel@tonic-gate 
1426f66d273dSizick 	if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE ||
1427f66d273dSizick 	    mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE)
1428f66d273dSizick 		rv = rsa_verify_common(mechanism->cm_type, key, data,
1429726fad2aSDina K Nimeh 		    signature);
1430f66d273dSizick 
1431f66d273dSizick 	else {
14327c478bd9Sstevel@tonic-gate 		dctx.mech_type = mechanism->cm_type;
14337c478bd9Sstevel@tonic-gate 		dctx.key = key;
1434f66d273dSizick 
1435f66d273dSizick 		switch (mechanism->cm_type) {
1436f66d273dSizick 		case MD5_RSA_PKCS_MECH_INFO_TYPE:
14377c478bd9Sstevel@tonic-gate 			MD5Init(&(dctx.md5_ctx));
1438f66d273dSizick 			break;
1439f66d273dSizick 
1440f66d273dSizick 		case SHA1_RSA_PKCS_MECH_INFO_TYPE:
14417c478bd9Sstevel@tonic-gate 			SHA1Init(&(dctx.sha1_ctx));
1442f66d273dSizick 			break;
1443f66d273dSizick 
1444f66d273dSizick 		case SHA256_RSA_PKCS_MECH_INFO_TYPE:
1445f66d273dSizick 			SHA2Init(SHA256, &(dctx.sha2_ctx));
1446f66d273dSizick 			break;
1447f66d273dSizick 
1448f66d273dSizick 		case SHA384_RSA_PKCS_MECH_INFO_TYPE:
1449f66d273dSizick 			SHA2Init(SHA384, &(dctx.sha2_ctx));
1450f66d273dSizick 			break;
1451f66d273dSizick 
1452f66d273dSizick 		case SHA512_RSA_PKCS_MECH_INFO_TYPE:
1453f66d273dSizick 			SHA2Init(SHA512, &(dctx.sha2_ctx));
1454f66d273dSizick 			break;
1455f66d273dSizick 		}
1456f66d273dSizick 
1457726fad2aSDina K Nimeh 		rv = rsa_digest_svrfy_common(&dctx, data, signature,
145823c57df7Smcpowers 		    CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL);
14597c478bd9Sstevel@tonic-gate 	}
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 	return (rv);
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate static int
rsa_verify_recover_common(rsa_mech_type_t mech_type,crypto_key_t * key,crypto_data_t * signature,crypto_data_t * data)14657c478bd9Sstevel@tonic-gate rsa_verify_recover_common(rsa_mech_type_t mech_type, crypto_key_t *key,
1466726fad2aSDina K Nimeh     crypto_data_t *signature, crypto_data_t *data)
14677c478bd9Sstevel@tonic-gate {
14687c478bd9Sstevel@tonic-gate 	int rv = CRYPTO_FAILED;
14697c478bd9Sstevel@tonic-gate 
1470726fad2aSDina K Nimeh 	size_t data_len;
14717c478bd9Sstevel@tonic-gate 	uchar_t *sigptr, *modulus;
14727c478bd9Sstevel@tonic-gate 	ssize_t modulus_len;
14737c478bd9Sstevel@tonic-gate 	uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
14747c478bd9Sstevel@tonic-gate 	uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES];
14757c478bd9Sstevel@tonic-gate 
147623c57df7Smcpowers 	if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus,
14777c478bd9Sstevel@tonic-gate 	    &modulus_len)) != CRYPTO_SUCCESS) {
14787c478bd9Sstevel@tonic-gate 		return (rv);
14797c478bd9Sstevel@tonic-gate 	}
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	if (signature->cd_length != modulus_len)
14827c478bd9Sstevel@tonic-gate 		return (CRYPTO_SIGNATURE_LEN_RANGE);
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate 	ASSERT(signature->cd_length <= sizeof (tmp_data));
148523c57df7Smcpowers 	if ((rv = crypto_get_input_data(signature, &sigptr, tmp_data))
14867c478bd9Sstevel@tonic-gate 	    != CRYPTO_SUCCESS)
14877c478bd9Sstevel@tonic-gate 		return (rv);
14887c478bd9Sstevel@tonic-gate 
1489726fad2aSDina K Nimeh 	rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, 1);
14907c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_SUCCESS)
14917c478bd9Sstevel@tonic-gate 		return (rv);
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	data_len = modulus_len;
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 	if (mech_type == RSA_PKCS_MECH_INFO_TYPE) {
14967c478bd9Sstevel@tonic-gate 		/*
14977c478bd9Sstevel@tonic-gate 		 * Strip off the encoded padding bytes in front of the
14987c478bd9Sstevel@tonic-gate 		 * recovered data, then compare the recovered data with
14997c478bd9Sstevel@tonic-gate 		 * the original data.
15007c478bd9Sstevel@tonic-gate 		 */
1501726fad2aSDina K Nimeh 		rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
15027c478bd9Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS)
15037c478bd9Sstevel@tonic-gate 			return (rv);
15047c478bd9Sstevel@tonic-gate 	}
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 	if (data->cd_length < data_len) {
15077c478bd9Sstevel@tonic-gate 		data->cd_length = data_len;
15087c478bd9Sstevel@tonic-gate 		return (CRYPTO_BUFFER_TOO_SMALL);
15097c478bd9Sstevel@tonic-gate 	}
15107c478bd9Sstevel@tonic-gate 
151123c57df7Smcpowers 	if ((rv = crypto_put_output_data(plain_data + modulus_len - data_len,
15127c478bd9Sstevel@tonic-gate 	    data, data_len)) != CRYPTO_SUCCESS)
15137c478bd9Sstevel@tonic-gate 		return (rv);
15147c478bd9Sstevel@tonic-gate 	data->cd_length = data_len;
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate 	return (rv);
15177c478bd9Sstevel@tonic-gate }
15187c478bd9Sstevel@tonic-gate 
15197c478bd9Sstevel@tonic-gate /* ARGSUSED */
15207c478bd9Sstevel@tonic-gate static int
rsa_verify_recover(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_data_t * data,crypto_req_handle_t req)15217c478bd9Sstevel@tonic-gate rsa_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
15227c478bd9Sstevel@tonic-gate     crypto_data_t *data, crypto_req_handle_t req)
15237c478bd9Sstevel@tonic-gate {
15247c478bd9Sstevel@tonic-gate 	int rv;
15257c478bd9Sstevel@tonic-gate 	rsa_ctx_t *ctxp;
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	ASSERT(ctx->cc_provider_private != NULL);
15287c478bd9Sstevel@tonic-gate 	ctxp = ctx->cc_provider_private;
15297c478bd9Sstevel@tonic-gate 
1530726fad2aSDina K Nimeh 	/* See the comments on KM_SLEEP flag in rsaprov_encrypt() */
15317c478bd9Sstevel@tonic-gate 	rv = rsa_verify_recover_common(ctxp->mech_type, ctxp->key,
1532726fad2aSDina K Nimeh 	    signature, data);
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
15357c478bd9Sstevel@tonic-gate 		(void) rsa_free_context(ctx);
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 	return (rv);
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate /* ARGSUSED */
15417c478bd9Sstevel@tonic-gate static int
rsa_verify_recover_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * signature,crypto_data_t * data,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)15427c478bd9Sstevel@tonic-gate rsa_verify_recover_atomic(crypto_provider_handle_t provider,
15437c478bd9Sstevel@tonic-gate     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
15447c478bd9Sstevel@tonic-gate     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
15457c478bd9Sstevel@tonic-gate     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
15467c478bd9Sstevel@tonic-gate {
15477c478bd9Sstevel@tonic-gate 	int rv;
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate 	if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS)
15507c478bd9Sstevel@tonic-gate 		return (rv);
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 	return (rsa_verify_recover_common(mechanism->cm_type, key,
1553726fad2aSDina K Nimeh 	    signature, data));
15547c478bd9Sstevel@tonic-gate }
1555