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
5b60f2a0bSfr  * Common Development and Distribution License (the "License").
6b60f2a0bSfr  * 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  */
21*726fad2aSDina K Nimeh 
227c478bd9Sstevel@tonic-gate /*
23*726fad2aSDina K Nimeh  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <pthread.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
32*726fad2aSDina K Nimeh #include <cryptoutil.h>
337c478bd9Sstevel@tonic-gate #include "softGlobal.h"
347c478bd9Sstevel@tonic-gate #include "softSession.h"
357c478bd9Sstevel@tonic-gate #include "softObject.h"
367c478bd9Sstevel@tonic-gate #include "softOps.h"
377c478bd9Sstevel@tonic-gate #include "softRSA.h"
387c478bd9Sstevel@tonic-gate #include "softMAC.h"
397c478bd9Sstevel@tonic-gate #include "softCrypt.h"
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_encrypt(soft_object_t * key,CK_BYTE_PTR in,uint32_t in_len,CK_BYTE_PTR out,int realpublic)427c478bd9Sstevel@tonic-gate soft_rsa_encrypt(soft_object_t *key, CK_BYTE_PTR in, uint32_t in_len,
437c478bd9Sstevel@tonic-gate     CK_BYTE_PTR out, int realpublic)
447c478bd9Sstevel@tonic-gate {
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	uchar_t expo[MAX_KEY_ATTR_BUFLEN];
497c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
507c478bd9Sstevel@tonic-gate 	uint32_t expo_len = sizeof (expo);
517c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
52*726fad2aSDina K Nimeh 	RSAbytekey k;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	if (realpublic) {
55c64d15a5Smcpowers 		rv = soft_get_public_value(key, CKA_PUBLIC_EXPONENT, expo,
567c478bd9Sstevel@tonic-gate 		    &expo_len);
577c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
587c478bd9Sstevel@tonic-gate 			goto clean1;
597c478bd9Sstevel@tonic-gate 		}
607c478bd9Sstevel@tonic-gate 	} else {
61c64d15a5Smcpowers 		rv = soft_get_private_value(key, CKA_PRIVATE_EXPONENT, expo,
627c478bd9Sstevel@tonic-gate 		    &expo_len);
637c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
647c478bd9Sstevel@tonic-gate 			goto clean1;
657c478bd9Sstevel@tonic-gate 		}
667c478bd9Sstevel@tonic-gate 	}
677c478bd9Sstevel@tonic-gate 
68c64d15a5Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
697c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
707c478bd9Sstevel@tonic-gate 		goto clean1;
717c478bd9Sstevel@tonic-gate 	}
727c478bd9Sstevel@tonic-gate 
73*726fad2aSDina K Nimeh 	k.modulus = modulus;
74*726fad2aSDina K Nimeh 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
75*726fad2aSDina K Nimeh 	k.pubexpo = expo;
76*726fad2aSDina K Nimeh 	k.pubexpo_bytes = expo_len;
77*726fad2aSDina K Nimeh 	k.rfunc = NULL;
787c478bd9Sstevel@tonic-gate 
79*726fad2aSDina K Nimeh 	rv = rsa_encrypt(&k, in, in_len, out);
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate clean1:
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	return (rv);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_decrypt(soft_object_t * key,CK_BYTE_PTR in,uint32_t in_len,CK_BYTE_PTR out)887c478bd9Sstevel@tonic-gate soft_rsa_decrypt(soft_object_t *key, CK_BYTE_PTR in, uint32_t in_len,
897c478bd9Sstevel@tonic-gate     CK_BYTE_PTR out)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
957c478bd9Sstevel@tonic-gate 	uchar_t prime1[MAX_KEY_ATTR_BUFLEN];
967c478bd9Sstevel@tonic-gate 	uchar_t prime2[MAX_KEY_ATTR_BUFLEN];
977c478bd9Sstevel@tonic-gate 	uchar_t expo1[MAX_KEY_ATTR_BUFLEN];
987c478bd9Sstevel@tonic-gate 	uchar_t expo2[MAX_KEY_ATTR_BUFLEN];
997c478bd9Sstevel@tonic-gate 	uchar_t coef[MAX_KEY_ATTR_BUFLEN];
1007c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
1017c478bd9Sstevel@tonic-gate 	uint32_t prime1_len = sizeof (prime1);
1027c478bd9Sstevel@tonic-gate 	uint32_t prime2_len = sizeof (prime2);
1037c478bd9Sstevel@tonic-gate 	uint32_t expo1_len = sizeof (expo1);
1047c478bd9Sstevel@tonic-gate 	uint32_t expo2_len = sizeof (expo2);
1057c478bd9Sstevel@tonic-gate 	uint32_t coef_len = sizeof (coef);
106*726fad2aSDina K Nimeh 	RSAbytekey k;
1077c478bd9Sstevel@tonic-gate 
108c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
1097c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1107c478bd9Sstevel@tonic-gate 		goto clean1;
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 
113c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_PRIME_1, prime1, &prime1_len);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	if ((prime1_len == 0) && (rv == CKR_OK)) {
1167c478bd9Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1177c478bd9Sstevel@tonic-gate 		goto clean1;
1187c478bd9Sstevel@tonic-gate 	} else {
1197c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1207c478bd9Sstevel@tonic-gate 			goto clean1;
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
123c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_PRIME_2, prime2, &prime2_len);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if ((prime2_len == 0) && (rv == CKR_OK)) {
1267c478bd9Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1277c478bd9Sstevel@tonic-gate 		goto clean1;
1287c478bd9Sstevel@tonic-gate 	} else {
1297c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1307c478bd9Sstevel@tonic-gate 			goto clean1;
1317c478bd9Sstevel@tonic-gate 	}
1327c478bd9Sstevel@tonic-gate 
133c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_EXPONENT_1, expo1, &expo1_len);
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if ((expo1_len == 0) && (rv == CKR_OK)) {
1367c478bd9Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1377c478bd9Sstevel@tonic-gate 		goto clean1;
1387c478bd9Sstevel@tonic-gate 	} else {
1397c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1407c478bd9Sstevel@tonic-gate 			goto clean1;
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
143c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_EXPONENT_2, expo2, &expo2_len);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if ((expo2_len == 0) && (rv == CKR_OK)) {
1467c478bd9Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1477c478bd9Sstevel@tonic-gate 		goto clean1;
1487c478bd9Sstevel@tonic-gate 	} else {
1497c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1507c478bd9Sstevel@tonic-gate 			goto clean1;
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 
153c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_COEFFICIENT, coef, &coef_len);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	if ((coef_len == 0) && (rv == CKR_OK)) {
1567c478bd9Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1577c478bd9Sstevel@tonic-gate 		goto clean1;
1587c478bd9Sstevel@tonic-gate 	} else {
1597c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1607c478bd9Sstevel@tonic-gate 			goto clean1;
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
163*726fad2aSDina K Nimeh 	k.modulus = modulus;
164*726fad2aSDina K Nimeh 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
165*726fad2aSDina K Nimeh 	k.prime1 = prime1;
166*726fad2aSDina K Nimeh 	k.prime1_bytes = prime1_len;
167*726fad2aSDina K Nimeh 	k.prime2 = prime2;
168*726fad2aSDina K Nimeh 	k.prime2_bytes = prime2_len;
169*726fad2aSDina K Nimeh 	k.expo1 = expo1;
170*726fad2aSDina K Nimeh 	k.expo1_bytes = expo1_len;
171*726fad2aSDina K Nimeh 	k.expo2 = expo2;
172*726fad2aSDina K Nimeh 	k.expo2_bytes = expo2_len;
173*726fad2aSDina K Nimeh 	k.coeff = coef;
174*726fad2aSDina K Nimeh 	k.coeff_bytes = coef_len;
175*726fad2aSDina K Nimeh 	k.rfunc = NULL;
1767c478bd9Sstevel@tonic-gate 
177*726fad2aSDina K Nimeh 	rv = rsa_decrypt(&k, in, in_len, out);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate clean1:
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	return (rv);
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  * Allocate a RSA context for the active encryption or decryption operation.
1867c478bd9Sstevel@tonic-gate  * This function is called without the session lock held.
1877c478bd9Sstevel@tonic-gate  */
1887c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)1897c478bd9Sstevel@tonic-gate soft_rsa_crypt_init_common(soft_session_t *session_p,
1907c478bd9Sstevel@tonic-gate     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
1917c478bd9Sstevel@tonic-gate     boolean_t encrypt)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx;
1957c478bd9Sstevel@tonic-gate 	soft_object_t *tmp_key = NULL;
1967c478bd9Sstevel@tonic-gate 	CK_RV rv;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	rsa_ctx = calloc(1, sizeof (soft_rsa_ctx_t));
1997c478bd9Sstevel@tonic-gate 	if (rsa_ctx == NULL) {
2007c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/*
2047c478bd9Sstevel@tonic-gate 	 * Make a copy of the encryption or decryption key, and save it
2057c478bd9Sstevel@tonic-gate 	 * in the RSA crypto context since it will be used later for
2067c478bd9Sstevel@tonic-gate 	 * encryption/decryption. We don't want to hold any object reference
2077c478bd9Sstevel@tonic-gate 	 * on this original key while doing encryption/decryption.
2087c478bd9Sstevel@tonic-gate 	 */
2097c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&key_p->object_mutex);
2107c478bd9Sstevel@tonic-gate 	rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH,
2117c478bd9Sstevel@tonic-gate 	    NULL);
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	if ((rv != CKR_OK) || (tmp_key == NULL)) {
2147c478bd9Sstevel@tonic-gate 		/* Most likely we ran out of space. */
2157c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&key_p->object_mutex);
2167c478bd9Sstevel@tonic-gate 		free(rsa_ctx);
2177c478bd9Sstevel@tonic-gate 		return (rv);
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/* No need to hold the lock on the old object. */
2217c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&key_p->object_mutex);
2227c478bd9Sstevel@tonic-gate 	rsa_ctx->key = tmp_key;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
2257c478bd9Sstevel@tonic-gate 	if (encrypt) {
2267c478bd9Sstevel@tonic-gate 		/* Called by C_EncryptInit. */
2277c478bd9Sstevel@tonic-gate 		session_p->encrypt.context = rsa_ctx;
2287c478bd9Sstevel@tonic-gate 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
2297c478bd9Sstevel@tonic-gate 	} else {
2307c478bd9Sstevel@tonic-gate 		/* Called by C_DecryptInit. */
2317c478bd9Sstevel@tonic-gate 		session_p->decrypt.context = rsa_ctx;
2327c478bd9Sstevel@tonic-gate 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	return (CKR_OK);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_encrypt_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncrypted,CK_ULONG_PTR pulEncryptedLen,CK_MECHANISM_TYPE mechanism)2407c478bd9Sstevel@tonic-gate soft_rsa_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
2417c478bd9Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
2427c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->encrypt.context;
2467c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
2477c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
2487c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
2497c478bd9Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
2507c478bd9Sstevel@tonic-gate 	CK_BYTE	cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES];
2517c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
2527c478bd9Sstevel@tonic-gate 
253c64d15a5Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
2547c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2557c478bd9Sstevel@tonic-gate 		goto clean_exit;
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	if (pEncrypted == NULL) {
2597c478bd9Sstevel@tonic-gate 		/*
2607c478bd9Sstevel@tonic-gate 		 * Application asks for the length of the output buffer
2617c478bd9Sstevel@tonic-gate 		 * to hold the ciphertext.
2627c478bd9Sstevel@tonic-gate 		 */
2637c478bd9Sstevel@tonic-gate 		*pulEncryptedLen = modulus_len;
2647c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
2657c478bd9Sstevel@tonic-gate 		goto clean1;
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	if (mechanism == CKM_RSA_PKCS) {
2697c478bd9Sstevel@tonic-gate 		/*
2707c478bd9Sstevel@tonic-gate 		 * Input data length needs to be <=
2717c478bd9Sstevel@tonic-gate 		 * modulus length-MIN_PKCS1_PADLEN.
2727c478bd9Sstevel@tonic-gate 		 */
2737c478bd9Sstevel@tonic-gate 		if (ulDataLen > ((CK_ULONG)modulus_len - MIN_PKCS1_PADLEN)) {
2747c478bd9Sstevel@tonic-gate 			*pulEncryptedLen = modulus_len;
2757c478bd9Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
2767c478bd9Sstevel@tonic-gate 			goto clean_exit;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 	} else {
2797c478bd9Sstevel@tonic-gate 		/* Input data length needs to be <= modulus length. */
2807c478bd9Sstevel@tonic-gate 		if (ulDataLen > (CK_ULONG)modulus_len) {
2817c478bd9Sstevel@tonic-gate 			*pulEncryptedLen = modulus_len;
2827c478bd9Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
2837c478bd9Sstevel@tonic-gate 			goto clean_exit;
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 	}
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	/* Is the application-supplied buffer large enough? */
2887c478bd9Sstevel@tonic-gate 	if (*pulEncryptedLen < (CK_ULONG)modulus_len) {
2897c478bd9Sstevel@tonic-gate 		*pulEncryptedLen = modulus_len;
2907c478bd9Sstevel@tonic-gate 		rv = CKR_BUFFER_TOO_SMALL;
2917c478bd9Sstevel@tonic-gate 		goto clean1;
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	if (mechanism == CKM_RSA_PKCS) {
2957c478bd9Sstevel@tonic-gate 		/*
2967c478bd9Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
2977c478bd9Sstevel@tonic-gate 		 * type "02" encryption block.
2987c478bd9Sstevel@tonic-gate 		 */
299*726fad2aSDina K Nimeh 		rv = pkcs1_encode(PKCS1_ENCRYPT, pData, ulDataLen, plain_data,
3007c478bd9Sstevel@tonic-gate 		    modulus_len);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
3037c478bd9Sstevel@tonic-gate 			goto clean_exit;
3047c478bd9Sstevel@tonic-gate 	} else {
3057c478bd9Sstevel@tonic-gate 		/* Pad zeros for the leading bytes of the input data. */
3067c478bd9Sstevel@tonic-gate 		(void) memset(plain_data, 0x0, modulus_len - ulDataLen);
3077c478bd9Sstevel@tonic-gate 		(void) memcpy(&plain_data[modulus_len - ulDataLen], pData,
3087c478bd9Sstevel@tonic-gate 		    ulDataLen);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	rv = soft_rsa_encrypt(key, plain_data, modulus_len, cipher_data, 1);
3127c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
3137c478bd9Sstevel@tonic-gate 		(void) memcpy(pEncrypted, cipher_data, modulus_len);
3147c478bd9Sstevel@tonic-gate 		*pulEncryptedLen = modulus_len;
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate clean_exit:
3187c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
3197c478bd9Sstevel@tonic-gate 	free(session_p->encrypt.context);
3207c478bd9Sstevel@tonic-gate 	session_p->encrypt.context = NULL;
3217c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
3227c478bd9Sstevel@tonic-gate 	soft_cleanup_object(key);
3237c478bd9Sstevel@tonic-gate 	free(key);
3247c478bd9Sstevel@tonic-gate clean1:
3257c478bd9Sstevel@tonic-gate 	return (rv);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_decrypt_common(soft_session_t * session_p,CK_BYTE_PTR pEncrypted,CK_ULONG ulEncryptedLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen,CK_MECHANISM_TYPE mechanism)3307c478bd9Sstevel@tonic-gate soft_rsa_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
3317c478bd9Sstevel@tonic-gate     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
3327c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->decrypt.context;
3367c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
3377c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
3387c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
3397c478bd9Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
3407c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
3417c478bd9Sstevel@tonic-gate 
342c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
3437c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3447c478bd9Sstevel@tonic-gate 		goto clean_exit;
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (ulEncryptedLen != (CK_ULONG)modulus_len) {
3487c478bd9Sstevel@tonic-gate 		rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
3497c478bd9Sstevel@tonic-gate 		goto clean_exit;
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if (pData == NULL) {
3537c478bd9Sstevel@tonic-gate 		/*
3547c478bd9Sstevel@tonic-gate 		 * Application asks for the length of the output buffer
3557c478bd9Sstevel@tonic-gate 		 * to hold the recovered data.
3567c478bd9Sstevel@tonic-gate 		 */
3577c478bd9Sstevel@tonic-gate 		*pulDataLen = modulus_len;
3587c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
3597c478bd9Sstevel@tonic-gate 		goto clean1;
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (mechanism == CKM_RSA_X_509) {
3637c478bd9Sstevel@tonic-gate 		if (*pulDataLen < (CK_ULONG)modulus_len) {
3647c478bd9Sstevel@tonic-gate 			*pulDataLen = modulus_len;
3657c478bd9Sstevel@tonic-gate 			rv = CKR_BUFFER_TOO_SMALL;
3667c478bd9Sstevel@tonic-gate 			goto clean1;
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	rv = soft_rsa_decrypt(key, pEncrypted, modulus_len, plain_data);
3717c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3727c478bd9Sstevel@tonic-gate 		goto clean_exit;
3737c478bd9Sstevel@tonic-gate 	}
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	if (mechanism == CKM_RSA_PKCS) {
376*726fad2aSDina K Nimeh 		size_t plain_len = modulus_len;
377*726fad2aSDina K Nimeh 		size_t num_padding;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 		/* Strip off the PKCS block formatting data. */
380*726fad2aSDina K Nimeh 		rv = pkcs1_decode(PKCS1_DECRYPT, plain_data, &plain_len);
3817c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
3827c478bd9Sstevel@tonic-gate 			goto clean_exit;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		num_padding = modulus_len - plain_len;
3857c478bd9Sstevel@tonic-gate 		if (ulEncryptedLen - num_padding > *pulDataLen) {
3867c478bd9Sstevel@tonic-gate 			*pulDataLen = plain_len;
3877c478bd9Sstevel@tonic-gate 			rv = CKR_BUFFER_TOO_SMALL;
3887c478bd9Sstevel@tonic-gate 			goto clean1;
3897c478bd9Sstevel@tonic-gate 		}
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		(void) memcpy(pData, &plain_data[num_padding], plain_len);
3927c478bd9Sstevel@tonic-gate 		*pulDataLen = plain_len;
3937c478bd9Sstevel@tonic-gate 	} else {
3947c478bd9Sstevel@tonic-gate 		(void) memcpy(pData, plain_data, modulus_len);
3957c478bd9Sstevel@tonic-gate 		*pulDataLen = modulus_len;
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate clean_exit:
3997c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
4007c478bd9Sstevel@tonic-gate 	free(session_p->decrypt.context);
4017c478bd9Sstevel@tonic-gate 	session_p->decrypt.context = NULL;
4027c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
4037c478bd9Sstevel@tonic-gate 	soft_cleanup_object(key);
4047c478bd9Sstevel@tonic-gate 	free(key);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate clean1:
4077c478bd9Sstevel@tonic-gate 	return (rv);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate  * Allocate a RSA context for the active sign or verify operation.
4127c478bd9Sstevel@tonic-gate  * This function is called without the session lock held.
4137c478bd9Sstevel@tonic-gate  */
4147c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_sign_verify_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t sign)4157c478bd9Sstevel@tonic-gate soft_rsa_sign_verify_init_common(soft_session_t *session_p,
4167c478bd9Sstevel@tonic-gate     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
4177c478bd9Sstevel@tonic-gate     boolean_t sign)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
4207c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx;
4217c478bd9Sstevel@tonic-gate 	CK_MECHANISM digest_mech;
4227c478bd9Sstevel@tonic-gate 	soft_object_t *tmp_key = NULL;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	if (sign) {
4257c478bd9Sstevel@tonic-gate 		if ((key_p->class != CKO_PRIVATE_KEY) ||
4267c478bd9Sstevel@tonic-gate 		    (key_p->key_type != CKK_RSA))
4277c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
4287c478bd9Sstevel@tonic-gate 	} else {
4297c478bd9Sstevel@tonic-gate 		if ((key_p->class != CKO_PUBLIC_KEY) ||
4307c478bd9Sstevel@tonic-gate 		    (key_p->key_type != CKK_RSA))
4317c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	switch (pMechanism->mechanism) {
4357c478bd9Sstevel@tonic-gate 	case CKM_MD5_RSA_PKCS:
4367c478bd9Sstevel@tonic-gate 		digest_mech.mechanism = CKM_MD5;
4377c478bd9Sstevel@tonic-gate 		rv = soft_digest_init_internal(session_p, &digest_mech);
4387c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
4397c478bd9Sstevel@tonic-gate 			return (rv);
4407c478bd9Sstevel@tonic-gate 		break;
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	case CKM_SHA1_RSA_PKCS:
4437c478bd9Sstevel@tonic-gate 		digest_mech.mechanism = CKM_SHA_1;
44460722cc8Sizick 		digest_mech.pParameter = pMechanism->pParameter;
44560722cc8Sizick 		digest_mech.ulParameterLen = pMechanism->ulParameterLen;
4467c478bd9Sstevel@tonic-gate 		rv = soft_digest_init_internal(session_p, &digest_mech);
4477c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
4487c478bd9Sstevel@tonic-gate 			return (rv);
4497c478bd9Sstevel@tonic-gate 		break;
450f66d273dSizick 
451f66d273dSizick 	case CKM_SHA256_RSA_PKCS:
452f66d273dSizick 		digest_mech.mechanism = CKM_SHA256;
453f66d273dSizick 		rv = soft_digest_init_internal(session_p, &digest_mech);
454f66d273dSizick 		if (rv != CKR_OK)
455f66d273dSizick 			return (rv);
456f66d273dSizick 		break;
457f66d273dSizick 
458f66d273dSizick 	case CKM_SHA384_RSA_PKCS:
459f66d273dSizick 		digest_mech.mechanism = CKM_SHA384;
460f66d273dSizick 		rv = soft_digest_init_internal(session_p, &digest_mech);
461f66d273dSizick 		if (rv != CKR_OK)
462f66d273dSizick 			return (rv);
463f66d273dSizick 		break;
464f66d273dSizick 
465f66d273dSizick 	case CKM_SHA512_RSA_PKCS:
466f66d273dSizick 		digest_mech.mechanism = CKM_SHA512;
467f66d273dSizick 		rv = soft_digest_init_internal(session_p, &digest_mech);
468f66d273dSizick 		if (rv != CKR_OK)
469f66d273dSizick 			return (rv);
470f66d273dSizick 		break;
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	rsa_ctx = malloc(sizeof (soft_rsa_ctx_t));
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	if (rsa_ctx == NULL) {
4767c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
4777c478bd9Sstevel@tonic-gate 		goto clean_exit;
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&key_p->object_mutex);
4817c478bd9Sstevel@tonic-gate 	rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH,
4827c478bd9Sstevel@tonic-gate 	    NULL);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	if ((rv != CKR_OK) || (tmp_key == NULL)) {
4857c478bd9Sstevel@tonic-gate 		/* Most likely we ran out of space. */
4867c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&key_p->object_mutex);
4877c478bd9Sstevel@tonic-gate 		free(rsa_ctx);
4887c478bd9Sstevel@tonic-gate 		goto clean_exit;
4897c478bd9Sstevel@tonic-gate 	}
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	/* No need to hold the lock on the old object. */
4927c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&key_p->object_mutex);
4937c478bd9Sstevel@tonic-gate 	rsa_ctx->key = tmp_key;
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	if (sign) {
4987c478bd9Sstevel@tonic-gate 		session_p->sign.context = rsa_ctx;
4997c478bd9Sstevel@tonic-gate 		session_p->sign.mech.mechanism = pMechanism->mechanism;
5007c478bd9Sstevel@tonic-gate 	} else {
5017c478bd9Sstevel@tonic-gate 		session_p->verify.context = rsa_ctx;
5027c478bd9Sstevel@tonic-gate 		session_p->verify.mech.mechanism = pMechanism->mechanism;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	return (CKR_OK);
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate clean_exit:
5107c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5117c478bd9Sstevel@tonic-gate 	if (session_p->digest.context != NULL) {
5127c478bd9Sstevel@tonic-gate 		free(session_p->digest.context);
5137c478bd9Sstevel@tonic-gate 		session_p->digest.context = NULL;
5147c478bd9Sstevel@tonic-gate 		session_p->digest.flags = 0;
5157c478bd9Sstevel@tonic-gate 	}
5167c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
5177c478bd9Sstevel@tonic-gate 	return (rv);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_sign_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSigned,CK_ULONG_PTR pulSignedLen,CK_MECHANISM_TYPE mechanism)5237c478bd9Sstevel@tonic-gate soft_rsa_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData,
5247c478bd9Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned,
5257c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulSignedLen, CK_MECHANISM_TYPE mechanism)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5297c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->sign.context;
5307c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
5317c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
5327c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
5337c478bd9Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
5347c478bd9Sstevel@tonic-gate 	CK_BYTE	signed_data[MAX_RSA_KEYLENGTH_IN_BYTES];
5357c478bd9Sstevel@tonic-gate 
536c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
5377c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
5387c478bd9Sstevel@tonic-gate 		goto clean_exit;
5397c478bd9Sstevel@tonic-gate 	}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (pSigned == NULL) {
5427c478bd9Sstevel@tonic-gate 		/* Application asks for the length of the output buffer. */
5437c478bd9Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
5447c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
5457c478bd9Sstevel@tonic-gate 		goto clean1;
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	switch (mechanism) {
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	case CKM_RSA_PKCS:
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		/*
5537c478bd9Sstevel@tonic-gate 		 * Input data length needs to be <=
5547c478bd9Sstevel@tonic-gate 		 * modulus length-MIN_PKCS1_PADLEN.
5557c478bd9Sstevel@tonic-gate 		 */
5567c478bd9Sstevel@tonic-gate 		if (ulDataLen > ((CK_ULONG)modulus_len - MIN_PKCS1_PADLEN)) {
5577c478bd9Sstevel@tonic-gate 			*pulSignedLen = modulus_len;
5587c478bd9Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
5597c478bd9Sstevel@tonic-gate 			goto clean_exit;
5607c478bd9Sstevel@tonic-gate 		}
5617c478bd9Sstevel@tonic-gate 		break;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	case CKM_RSA_X_509:
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 		/* Input data length needs to be <= modulus length. */
5667c478bd9Sstevel@tonic-gate 		if (ulDataLen > (CK_ULONG)modulus_len) {
5677c478bd9Sstevel@tonic-gate 			*pulSignedLen = modulus_len;
5687c478bd9Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
5697c478bd9Sstevel@tonic-gate 			goto clean_exit;
5707c478bd9Sstevel@tonic-gate 		}
5717c478bd9Sstevel@tonic-gate 		break;
5727c478bd9Sstevel@tonic-gate 	}
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	/* Is the application-supplied buffer large enough? */
5757c478bd9Sstevel@tonic-gate 	if (*pulSignedLen < (CK_ULONG)modulus_len) {
5767c478bd9Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
5777c478bd9Sstevel@tonic-gate 		rv = CKR_BUFFER_TOO_SMALL;
5787c478bd9Sstevel@tonic-gate 		goto clean1;
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	switch (mechanism) {
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	case CKM_RSA_PKCS:
5847c478bd9Sstevel@tonic-gate 	case CKM_MD5_RSA_PKCS:
5857c478bd9Sstevel@tonic-gate 	case CKM_SHA1_RSA_PKCS:
586f66d273dSizick 	case CKM_SHA256_RSA_PKCS:
587f66d273dSizick 	case CKM_SHA384_RSA_PKCS:
588f66d273dSizick 	case CKM_SHA512_RSA_PKCS:
5897c478bd9Sstevel@tonic-gate 		/*
5907c478bd9Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
5917c478bd9Sstevel@tonic-gate 		 * type "01" encryption block.
5927c478bd9Sstevel@tonic-gate 		 */
593*726fad2aSDina K Nimeh 		rv = pkcs1_encode(PKCS1_SIGN, pData, ulDataLen, plain_data,
5947c478bd9Sstevel@tonic-gate 		    modulus_len);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
5977c478bd9Sstevel@tonic-gate 			goto clean_exit;
5987c478bd9Sstevel@tonic-gate 		}
5997c478bd9Sstevel@tonic-gate 		break;
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	case CKM_RSA_X_509:
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 		/* Pad zeros for the leading bytes of the input data. */
6047c478bd9Sstevel@tonic-gate 		(void) memset(plain_data, 0x0, modulus_len - ulDataLen);
6057c478bd9Sstevel@tonic-gate 		(void) memcpy(&plain_data[modulus_len - ulDataLen], pData,
6067c478bd9Sstevel@tonic-gate 		    ulDataLen);
6077c478bd9Sstevel@tonic-gate 		break;
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/*
6117c478bd9Sstevel@tonic-gate 	 * Perform RSA encryption with the signer's RSA private key
6127c478bd9Sstevel@tonic-gate 	 * for signature process.
6137c478bd9Sstevel@tonic-gate 	 */
6147c478bd9Sstevel@tonic-gate 	rv = soft_rsa_decrypt(key, plain_data, modulus_len, signed_data);
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
6177c478bd9Sstevel@tonic-gate 		(void) memcpy(pSigned, signed_data, modulus_len);
6187c478bd9Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate clean_exit:
6227c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
6237c478bd9Sstevel@tonic-gate 	free(session_p->sign.context);
6247c478bd9Sstevel@tonic-gate 	session_p->sign.context = NULL;
6257c478bd9Sstevel@tonic-gate 	if (session_p->digest.context != NULL) {
6267c478bd9Sstevel@tonic-gate 		free(session_p->digest.context);
6277c478bd9Sstevel@tonic-gate 		session_p->digest.context = NULL;
6287c478bd9Sstevel@tonic-gate 		session_p->digest.flags = 0;
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
6317c478bd9Sstevel@tonic-gate 	soft_cleanup_object(key);
6327c478bd9Sstevel@tonic-gate 	free(key);
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate clean1:
6357c478bd9Sstevel@tonic-gate 	return (rv);
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_verify_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_MECHANISM_TYPE mechanism)6407c478bd9Sstevel@tonic-gate soft_rsa_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
6417c478bd9Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
6427c478bd9Sstevel@tonic-gate     CK_ULONG ulSignatureLen, CK_MECHANISM_TYPE mechanism)
6437c478bd9Sstevel@tonic-gate {
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6467c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->verify.context;
6477c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
6487c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
6497c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
6507c478bd9Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
6517c478bd9Sstevel@tonic-gate 
652c64d15a5Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
6537c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
6547c478bd9Sstevel@tonic-gate 		goto clean_exit;
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
657*726fad2aSDina K Nimeh 	if (ulDataLen == 0) {
658*726fad2aSDina K Nimeh 		rv = CKR_DATA_LEN_RANGE;
659*726fad2aSDina K Nimeh 		goto clean_exit;
660*726fad2aSDina K Nimeh 	}
661*726fad2aSDina K Nimeh 
6627c478bd9Sstevel@tonic-gate 	if (ulSignatureLen != (CK_ULONG)modulus_len) {
6637c478bd9Sstevel@tonic-gate 		rv = CKR_SIGNATURE_LEN_RANGE;
6647c478bd9Sstevel@tonic-gate 		goto clean_exit;
6657c478bd9Sstevel@tonic-gate 	}
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	/*
6687c478bd9Sstevel@tonic-gate 	 * Perform RSA decryption with the signer's RSA public key
6697c478bd9Sstevel@tonic-gate 	 * for verification process.
6707c478bd9Sstevel@tonic-gate 	 */
6717c478bd9Sstevel@tonic-gate 	rv = soft_rsa_encrypt(key, pSignature, modulus_len, plain_data, 1);
6727c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
6737c478bd9Sstevel@tonic-gate 		switch (mechanism) {
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 		case CKM_RSA_PKCS:
6767c478bd9Sstevel@tonic-gate 		case CKM_MD5_RSA_PKCS:
6777c478bd9Sstevel@tonic-gate 		case CKM_SHA1_RSA_PKCS:
678f66d273dSizick 		case CKM_SHA256_RSA_PKCS:
679f66d273dSizick 		case CKM_SHA384_RSA_PKCS:
680f66d273dSizick 		case CKM_SHA512_RSA_PKCS:
6817c478bd9Sstevel@tonic-gate 		{
6827c478bd9Sstevel@tonic-gate 			/*
6837c478bd9Sstevel@tonic-gate 			 * Strip off the encoded padding bytes in front of the
6847c478bd9Sstevel@tonic-gate 			 * recovered data, then compare the recovered data with
6857c478bd9Sstevel@tonic-gate 			 * the original data.
6867c478bd9Sstevel@tonic-gate 			 */
687*726fad2aSDina K Nimeh 			size_t data_len = modulus_len;
6887c478bd9Sstevel@tonic-gate 
689*726fad2aSDina K Nimeh 			rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
6907c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
6917c478bd9Sstevel@tonic-gate 				goto clean_exit;
6927c478bd9Sstevel@tonic-gate 			}
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 			if ((CK_ULONG)data_len != ulDataLen) {
695*726fad2aSDina K Nimeh 				rv = CKR_DATA_LEN_RANGE;
6967c478bd9Sstevel@tonic-gate 				goto clean_exit;
6977c478bd9Sstevel@tonic-gate 			} else if (memcmp(pData,
6987c478bd9Sstevel@tonic-gate 			    &plain_data[modulus_len - data_len],
6997c478bd9Sstevel@tonic-gate 			    ulDataLen) != 0) {
7007c478bd9Sstevel@tonic-gate 				rv = CKR_SIGNATURE_INVALID;
7017c478bd9Sstevel@tonic-gate 				goto clean_exit;
7027c478bd9Sstevel@tonic-gate 			}
7037c478bd9Sstevel@tonic-gate 			break;
7047c478bd9Sstevel@tonic-gate 		}
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 		case CKM_RSA_X_509:
7077c478bd9Sstevel@tonic-gate 			/*
7087c478bd9Sstevel@tonic-gate 			 * Strip off the encoded padding bytes in front of the
7097c478bd9Sstevel@tonic-gate 			 * recovered plain_data, then compare the input data
7107c478bd9Sstevel@tonic-gate 			 * with the recovered data.
7117c478bd9Sstevel@tonic-gate 			 */
7127c478bd9Sstevel@tonic-gate 			if (memcmp(pData,
7137c478bd9Sstevel@tonic-gate 			    plain_data + ulSignatureLen - ulDataLen,
7147c478bd9Sstevel@tonic-gate 			    ulDataLen) != 0) {
7157c478bd9Sstevel@tonic-gate 				rv = CKR_SIGNATURE_INVALID;
7167c478bd9Sstevel@tonic-gate 				goto clean_exit;
7177c478bd9Sstevel@tonic-gate 			}
7187c478bd9Sstevel@tonic-gate 			break;
7197c478bd9Sstevel@tonic-gate 		}
7207c478bd9Sstevel@tonic-gate 	}
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	if (rv == CKR_DATA_LEN_RANGE) {
7237c478bd9Sstevel@tonic-gate 		if ((mechanism == CKM_MD5_RSA_PKCS) ||
724f66d273dSizick 		    (mechanism == CKM_SHA1_RSA_PKCS) ||
725f66d273dSizick 		    (mechanism == CKM_SHA256_RSA_PKCS) ||
726f66d273dSizick 		    (mechanism == CKM_SHA384_RSA_PKCS) ||
727f66d273dSizick 		    (mechanism == CKM_SHA512_RSA_PKCS))
7287c478bd9Sstevel@tonic-gate 			rv = CKR_SIGNATURE_INVALID;
7297c478bd9Sstevel@tonic-gate 	}
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate clean_exit:
7327c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
7337c478bd9Sstevel@tonic-gate 	free(session_p->verify.context);
7347c478bd9Sstevel@tonic-gate 	session_p->verify.context = NULL;
7357c478bd9Sstevel@tonic-gate 	if (session_p->digest.context != NULL) {
7367c478bd9Sstevel@tonic-gate 		free(session_p->digest.context);
7377c478bd9Sstevel@tonic-gate 		session_p->digest.context = NULL;
7387c478bd9Sstevel@tonic-gate 		session_p->digest.flags = 0;
7397c478bd9Sstevel@tonic-gate 	}
7407c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
7417c478bd9Sstevel@tonic-gate 	soft_cleanup_object(key);
7427c478bd9Sstevel@tonic-gate 	free(key);
7437c478bd9Sstevel@tonic-gate 	return (rv);
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate CK_RV
soft_genRSAkey_set_attribute(soft_object_t * key,CK_ATTRIBUTE_TYPE type,uchar_t * buf,uint32_t buflen,boolean_t public)747*726fad2aSDina K Nimeh soft_genRSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
748*726fad2aSDina K Nimeh     uchar_t *buf, uint32_t buflen, boolean_t public)
7497c478bd9Sstevel@tonic-gate {
7507c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
7517c478bd9Sstevel@tonic-gate 	biginteger_t *dst = NULL;
7527c478bd9Sstevel@tonic-gate 	biginteger_t src;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	switch (type) {
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	case CKA_MODULUS:
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 		if (public)
7597c478bd9Sstevel@tonic-gate 			dst = OBJ_PUB_RSA_MOD(key);
7607c478bd9Sstevel@tonic-gate 		else
7617c478bd9Sstevel@tonic-gate 			dst = OBJ_PRI_RSA_MOD(key);
7627c478bd9Sstevel@tonic-gate 		break;
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 	case CKA_PUBLIC_EXPONENT:
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 		if (public)
7677c478bd9Sstevel@tonic-gate 			dst = OBJ_PUB_RSA_PUBEXPO(key);
7687c478bd9Sstevel@tonic-gate 		else
7697c478bd9Sstevel@tonic-gate 			dst = OBJ_PRI_RSA_PUBEXPO(key);
7707c478bd9Sstevel@tonic-gate 		break;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	case CKA_PRIVATE_EXPONENT:
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_PRIEXPO(key);
7757c478bd9Sstevel@tonic-gate 		break;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	case CKA_PRIME_1:
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_PRIME1(key);
7807c478bd9Sstevel@tonic-gate 		break;
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	case CKA_PRIME_2:
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_PRIME2(key);
7857c478bd9Sstevel@tonic-gate 		break;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	case CKA_EXPONENT_1:
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_EXPO1(key);
7907c478bd9Sstevel@tonic-gate 		break;
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 	case CKA_EXPONENT_2:
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_EXPO2(key);
7957c478bd9Sstevel@tonic-gate 		break;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	case CKA_COEFFICIENT:
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_COEF(key);
8007c478bd9Sstevel@tonic-gate 		break;
8017c478bd9Sstevel@tonic-gate 	}
8027c478bd9Sstevel@tonic-gate 
803*726fad2aSDina K Nimeh 	/* Note: no explanation found for why this is needed */
8047c478bd9Sstevel@tonic-gate 	while (buf[0] == 0) {	/* remove proceeding 0x00 */
8057c478bd9Sstevel@tonic-gate 		buf++;
8067c478bd9Sstevel@tonic-gate 		buflen--;
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 
809*726fad2aSDina K Nimeh 	if ((rv = dup_bigint_attr(&src, buf, buflen)) != CKR_OK)
8107c478bd9Sstevel@tonic-gate 		goto cleanexit;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	/* Copy the attribute in the key object. */
8137c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&src, dst);
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate cleanexit:
8167c478bd9Sstevel@tonic-gate 	return (rv);
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_genkey_pair(soft_object_t * pubkey,soft_object_t * prikey)8227c478bd9Sstevel@tonic-gate soft_rsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey)
8237c478bd9Sstevel@tonic-gate {
8247c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
825*726fad2aSDina K Nimeh 	CK_ATTRIBUTE template;
826*726fad2aSDina K Nimeh 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
8277c478bd9Sstevel@tonic-gate 	uint32_t modulus_len;
828*726fad2aSDina K Nimeh 	uchar_t pub_expo[MAX_KEY_ATTR_BUFLEN];
8297c478bd9Sstevel@tonic-gate 	uint32_t pub_expo_len = sizeof (pub_expo);
830*726fad2aSDina K Nimeh 	uchar_t private_exponent[MAX_KEY_ATTR_BUFLEN];
831*726fad2aSDina K Nimeh 	uint32_t private_exponent_len = sizeof (private_exponent);
832*726fad2aSDina K Nimeh 	uchar_t prime1[MAX_KEY_ATTR_BUFLEN];
833*726fad2aSDina K Nimeh 	uint32_t prime1_len = sizeof (prime1);
834*726fad2aSDina K Nimeh 	uchar_t prime2[MAX_KEY_ATTR_BUFLEN];
835*726fad2aSDina K Nimeh 	uint32_t prime2_len = sizeof (prime2);
836*726fad2aSDina K Nimeh 	uchar_t exponent1[MAX_KEY_ATTR_BUFLEN];
837*726fad2aSDina K Nimeh 	uint32_t exponent1_len = sizeof (exponent1);
838*726fad2aSDina K Nimeh 	uchar_t exponent2[MAX_KEY_ATTR_BUFLEN];
839*726fad2aSDina K Nimeh 	uint32_t exponent2_len = sizeof (exponent2);
840*726fad2aSDina K Nimeh 	uchar_t coefficient[MAX_KEY_ATTR_BUFLEN];
841*726fad2aSDina K Nimeh 	uint32_t coefficient_len = sizeof (coefficient);
842*726fad2aSDina K Nimeh 	RSAbytekey k;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	if ((pubkey == NULL) || (prikey == NULL)) {
8457c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	template.pValue = malloc(sizeof (CK_ULONG));
8497c478bd9Sstevel@tonic-gate 	if (template.pValue == NULL) {
8507c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
8517c478bd9Sstevel@tonic-gate 	}
8527c478bd9Sstevel@tonic-gate 	template.ulValueLen = sizeof (CK_ULONG);
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	rv = get_ulong_attr_from_object(OBJ_PUB_RSA_MOD_BITS(pubkey),
8557c478bd9Sstevel@tonic-gate 	    &template);
8567c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
857*726fad2aSDina K Nimeh 		free(template.pValue);
8587c478bd9Sstevel@tonic-gate 		goto clean0;
8597c478bd9Sstevel@tonic-gate 	}
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate #ifdef	__sparcv9
8627c478bd9Sstevel@tonic-gate 	/* LINTED */
8637c478bd9Sstevel@tonic-gate 	modulus_len = (uint32_t)(*((CK_ULONG *)(template.pValue)));
8647c478bd9Sstevel@tonic-gate #else	/* !__sparcv9 */
8657c478bd9Sstevel@tonic-gate 	modulus_len = *((CK_ULONG *)(template.pValue));
8667c478bd9Sstevel@tonic-gate #endif	/* __sparcv9 */
8677c478bd9Sstevel@tonic-gate 
868*726fad2aSDina K Nimeh 	free(template.pValue);
8697c478bd9Sstevel@tonic-gate 
870c64d15a5Smcpowers 	rv = soft_get_public_value(pubkey, CKA_PUBLIC_EXPONENT, pub_expo,
8717c478bd9Sstevel@tonic-gate 	    &pub_expo_len);
8727c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
8737c478bd9Sstevel@tonic-gate 		goto clean0;
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate 
876*726fad2aSDina K Nimeh 	/* Inputs to RSA key pair generation */
877*726fad2aSDina K Nimeh 	k.modulus_bits = modulus_len;		/* save modulus len in bits  */
878*726fad2aSDina K Nimeh 	modulus_len = CRYPTO_BITS2BYTES(modulus_len);	/* convert to bytes */
879*726fad2aSDina K Nimeh 	k.modulus = modulus;
880*726fad2aSDina K Nimeh 	k.pubexpo = pub_expo;
881*726fad2aSDina K Nimeh 	k.pubexpo_bytes = pub_expo_len;
882*726fad2aSDina K Nimeh 	k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ?
883*726fad2aSDina K Nimeh 	    pkcs11_get_random : pkcs11_get_urandom;
884*726fad2aSDina K Nimeh 
885*726fad2aSDina K Nimeh 	/* Outputs from RSA key pair generation */
886*726fad2aSDina K Nimeh 	k.privexpo = private_exponent;
887*726fad2aSDina K Nimeh 	k.privexpo_bytes = private_exponent_len;
888*726fad2aSDina K Nimeh 	k.prime1 = prime1;
889*726fad2aSDina K Nimeh 	k.prime1_bytes = prime1_len;
890*726fad2aSDina K Nimeh 	k.prime2 = prime2;
891*726fad2aSDina K Nimeh 	k.prime2_bytes = prime2_len;
892*726fad2aSDina K Nimeh 	k.expo1 = exponent1;
893*726fad2aSDina K Nimeh 	k.expo1_bytes = exponent1_len;
894*726fad2aSDina K Nimeh 	k.expo2 = exponent2;
895*726fad2aSDina K Nimeh 	k.expo2_bytes = exponent2_len;
896*726fad2aSDina K Nimeh 	k.coeff = coefficient;
897*726fad2aSDina K Nimeh 	k.coeff_bytes = coefficient_len;
898*726fad2aSDina K Nimeh 
899*726fad2aSDina K Nimeh 	rv = rsa_genkey_pair(&k);
9007c478bd9Sstevel@tonic-gate 
901*726fad2aSDina K Nimeh 	if (rv != CKR_OK) {
902*726fad2aSDina K Nimeh 		goto clean0;
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	/*
9067c478bd9Sstevel@tonic-gate 	 * Add modulus in public template, and add all eight key fields
9077c478bd9Sstevel@tonic-gate 	 * in private template.
9087c478bd9Sstevel@tonic-gate 	 */
909*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(pubkey, CKA_MODULUS,
910*726fad2aSDina K Nimeh 	    modulus, CRYPTO_BITS2BYTES(k.modulus_bits), B_TRUE)) != CKR_OK) {
911*726fad2aSDina K Nimeh 		goto clean0;
9127c478bd9Sstevel@tonic-gate 	}
9137c478bd9Sstevel@tonic-gate 
914*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_MODULUS,
915*726fad2aSDina K Nimeh 	    modulus, CRYPTO_BITS2BYTES(k.modulus_bits), B_FALSE)) != CKR_OK) {
916*726fad2aSDina K Nimeh 		goto clean0;
9177c478bd9Sstevel@tonic-gate 	}
9187c478bd9Sstevel@tonic-gate 
919*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIVATE_EXPONENT,
920*726fad2aSDina K Nimeh 	    private_exponent, k.privexpo_bytes, B_FALSE)) != CKR_OK) {
921*726fad2aSDina K Nimeh 		goto clean0;
9227c478bd9Sstevel@tonic-gate 	}
9237c478bd9Sstevel@tonic-gate 
924*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PUBLIC_EXPONENT,
925*726fad2aSDina K Nimeh 	    pub_expo, k.pubexpo_bytes, B_FALSE)) != CKR_OK) {
926*726fad2aSDina K Nimeh 		goto clean0;
9277c478bd9Sstevel@tonic-gate 	}
9287c478bd9Sstevel@tonic-gate 
929*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIME_1,
930*726fad2aSDina K Nimeh 	    prime1, k.prime1_bytes, B_FALSE)) != CKR_OK) {
931*726fad2aSDina K Nimeh 		goto clean0;
9327c478bd9Sstevel@tonic-gate 	}
9337c478bd9Sstevel@tonic-gate 
934*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIME_2,
935*726fad2aSDina K Nimeh 	    prime2, k.prime2_bytes, B_FALSE)) != CKR_OK) {
936*726fad2aSDina K Nimeh 		goto clean0;
9377c478bd9Sstevel@tonic-gate 	}
9387c478bd9Sstevel@tonic-gate 
939*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_EXPONENT_1,
940*726fad2aSDina K Nimeh 	    exponent1, k.expo1_bytes, B_FALSE)) != CKR_OK) {
941*726fad2aSDina K Nimeh 		goto clean0;
9427c478bd9Sstevel@tonic-gate 	}
9437c478bd9Sstevel@tonic-gate 
944*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_EXPONENT_2,
945*726fad2aSDina K Nimeh 	    exponent2, k.expo2_bytes, B_FALSE)) != CKR_OK) {
946*726fad2aSDina K Nimeh 		goto clean0;
9477c478bd9Sstevel@tonic-gate 	}
9487c478bd9Sstevel@tonic-gate 
949*726fad2aSDina K Nimeh 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_COEFFICIENT,
950*726fad2aSDina K Nimeh 	    coefficient, k.coeff_bytes, B_FALSE)) != CKR_OK) {
951*726fad2aSDina K Nimeh 		goto clean0;
9527c478bd9Sstevel@tonic-gate 	}
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate clean0:
9557c478bd9Sstevel@tonic-gate 	return (rv);
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate 
95860722cc8Sizick 
95960722cc8Sizick CK_ULONG
get_rsa_sha1_prefix(CK_MECHANISM_PTR mech,CK_BYTE_PTR * prefix)96060722cc8Sizick get_rsa_sha1_prefix(CK_MECHANISM_PTR mech, CK_BYTE_PTR *prefix) {
96160722cc8Sizick 	if (mech->pParameter == NULL) {
96260722cc8Sizick 		*prefix = (CK_BYTE *)SHA1_DER_PREFIX;
96360722cc8Sizick 		return (SHA1_DER_PREFIX_Len);
96460722cc8Sizick 	}
96560722cc8Sizick 
96660722cc8Sizick 	*prefix = (CK_BYTE *)SHA1_DER_PREFIX_OID;
96760722cc8Sizick 	return (SHA1_DER_PREFIX_OID_Len);
96860722cc8Sizick }
96960722cc8Sizick 
9707c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_digest_sign_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSigned,CK_ULONG_PTR pulSignedLen,CK_MECHANISM_TYPE mechanism,boolean_t Final)9717c478bd9Sstevel@tonic-gate soft_rsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData,
9727c478bd9Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned,
9737c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulSignedLen, CK_MECHANISM_TYPE mechanism, boolean_t Final)
9747c478bd9Sstevel@tonic-gate {
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
977f66d273dSizick 	CK_BYTE hash[SHA512_DIGEST_LENGTH];  /* space enough for all mechs */
978f66d273dSizick 	CK_ULONG hash_len = SHA512_DIGEST_LENGTH;
979f66d273dSizick 	/* space enough for all mechs */
980f66d273dSizick 	CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
9817c478bd9Sstevel@tonic-gate 	CK_ULONG der_data_len;
9827c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->sign.context;
9837c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
9847c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
9857c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
98660722cc8Sizick 	CK_ULONG der_len;
98760722cc8Sizick 	CK_BYTE_PTR der_prefix;
9887c478bd9Sstevel@tonic-gate 
989c64d15a5Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
9907c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
9917c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
9927c478bd9Sstevel@tonic-gate 		free(session_p->digest.context);
9937c478bd9Sstevel@tonic-gate 		session_p->digest.context = NULL;
9947c478bd9Sstevel@tonic-gate 		session_p->digest.flags = 0;
9957c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
9967c478bd9Sstevel@tonic-gate 		soft_cleanup_object(key);
9977c478bd9Sstevel@tonic-gate 		free(key);
9987c478bd9Sstevel@tonic-gate 		goto clean1;
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	/* Check arguments before performing message digest. */
10027c478bd9Sstevel@tonic-gate 	if (pSigned == NULL) {
10037c478bd9Sstevel@tonic-gate 		/* Application asks for the length of the output buffer. */
10047c478bd9Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
10057c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
10067c478bd9Sstevel@tonic-gate 		goto clean1;
10077c478bd9Sstevel@tonic-gate 	}
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	/* Is the application-supplied buffer large enough? */
10107c478bd9Sstevel@tonic-gate 	if (*pulSignedLen < (CK_ULONG)modulus_len) {
10117c478bd9Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
10127c478bd9Sstevel@tonic-gate 		rv = CKR_BUFFER_TOO_SMALL;
10137c478bd9Sstevel@tonic-gate 		goto clean1;
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	if (Final) {
10177c478bd9Sstevel@tonic-gate 		rv = soft_digest_final(session_p, hash, &hash_len);
10187c478bd9Sstevel@tonic-gate 	} else {
10197c478bd9Sstevel@tonic-gate 		rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len);
10207c478bd9Sstevel@tonic-gate 	}
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
10237c478bd9Sstevel@tonic-gate 		/* free the signature key */
10247c478bd9Sstevel@tonic-gate 		soft_cleanup_object(key);
10257c478bd9Sstevel@tonic-gate 		free(key);
10267c478bd9Sstevel@tonic-gate 		goto clean_exit;
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	/*
103060722cc8Sizick 	 * Prepare the DER encoding of the DigestInfo value by setting it to:
103160722cc8Sizick 	 *	<MECH>_DER_PREFIX || H
10327c478bd9Sstevel@tonic-gate 	 *
10337c478bd9Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
10347c478bd9Sstevel@tonic-gate 	 */
1035f66d273dSizick 	switch (session_p->digest.mech.mechanism) {
1036f66d273dSizick 	case CKM_MD5:
10377c478bd9Sstevel@tonic-gate 		(void) memcpy(der_data, MD5_DER_PREFIX, MD5_DER_PREFIX_Len);
10387c478bd9Sstevel@tonic-gate 		(void) memcpy(der_data + MD5_DER_PREFIX_Len, hash, hash_len);
10397c478bd9Sstevel@tonic-gate 		der_data_len = MD5_DER_PREFIX_Len + hash_len;
1040f66d273dSizick 		break;
1041f66d273dSizick 	case CKM_SHA_1:
104260722cc8Sizick 		der_len = get_rsa_sha1_prefix(&(session_p->digest.mech),
104360722cc8Sizick 		    &der_prefix);
104460722cc8Sizick 		(void) memcpy(der_data, der_prefix, der_len);
104560722cc8Sizick 		(void) memcpy(der_data + der_len, hash, hash_len);
104660722cc8Sizick 		der_data_len = der_len + hash_len;
1047f66d273dSizick 		break;
1048f66d273dSizick 	case CKM_SHA256:
1049f66d273dSizick 		(void) memcpy(der_data, SHA256_DER_PREFIX,
1050f66d273dSizick 		    SHA2_DER_PREFIX_Len);
1051f66d273dSizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1052f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1053f66d273dSizick 		break;
1054f66d273dSizick 	case CKM_SHA384:
1055f66d273dSizick 		(void) memcpy(der_data, SHA384_DER_PREFIX,
1056f66d273dSizick 		    SHA2_DER_PREFIX_Len);
1057f66d273dSizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1058f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1059f66d273dSizick 		break;
1060f66d273dSizick 	case CKM_SHA512:
1061f66d273dSizick 		(void) memcpy(der_data, SHA512_DER_PREFIX,
1062f66d273dSizick 		    SHA2_DER_PREFIX_Len);
1063f66d273dSizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1064f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1065f66d273dSizick 		break;
10667c478bd9Sstevel@tonic-gate 	}
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 	/*
10697c478bd9Sstevel@tonic-gate 	 * Now, we are ready to sign the DER_ENCODED data
10707c478bd9Sstevel@tonic-gate 	 * soft_rsa_sign_common() will free the signature key.
10717c478bd9Sstevel@tonic-gate 	 */
10727c478bd9Sstevel@tonic-gate 	rv = soft_rsa_sign_common(session_p, der_data, der_data_len,
10737c478bd9Sstevel@tonic-gate 	    pSigned, pulSignedLen, mechanism);
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate clean_exit:
10767c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
10777c478bd9Sstevel@tonic-gate 	/* soft_digest_common() has freed the digest context */
10787c478bd9Sstevel@tonic-gate 	session_p->digest.flags = 0;
10797c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate clean1:
10827c478bd9Sstevel@tonic-gate 	return (rv);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_digest_verify_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSigned,CK_ULONG ulSignedLen,CK_MECHANISM_TYPE mechanism,boolean_t Final)10877c478bd9Sstevel@tonic-gate soft_rsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
10887c478bd9Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned,
10897c478bd9Sstevel@tonic-gate     CK_ULONG ulSignedLen, CK_MECHANISM_TYPE mechanism, boolean_t Final)
10907c478bd9Sstevel@tonic-gate {
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1093f66d273dSizick 	CK_BYTE hash[SHA512_DIGEST_LENGTH];  /* space for all mechs */
1094f66d273dSizick 	CK_ULONG hash_len = SHA512_DIGEST_LENGTH;
1095f66d273dSizick 	CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
10967c478bd9Sstevel@tonic-gate 	CK_ULONG der_data_len;
10977c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->verify.context;
10987c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
109960722cc8Sizick 	CK_ULONG der_len;
110060722cc8Sizick 	CK_BYTE_PTR der_prefix;
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	if (Final) {
11037c478bd9Sstevel@tonic-gate 		rv = soft_digest_final(session_p, hash, &hash_len);
11047c478bd9Sstevel@tonic-gate 	} else {
11057c478bd9Sstevel@tonic-gate 		rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len);
11067c478bd9Sstevel@tonic-gate 	}
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
11097c478bd9Sstevel@tonic-gate 		/* free the verification key */
11107c478bd9Sstevel@tonic-gate 		soft_cleanup_object(key);
11117c478bd9Sstevel@tonic-gate 		free(key);
11127c478bd9Sstevel@tonic-gate 		goto clean_exit;
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	/*
11167c478bd9Sstevel@tonic-gate 	 * Prepare the DER encoding of the DigestInfo value as follows:
11177c478bd9Sstevel@tonic-gate 	 * MD5:		MD5_DER_PREFIX || H
11187c478bd9Sstevel@tonic-gate 	 * SHA-1:	SHA1_DER_PREFIX || H
1119f66d273dSizick 	 * SHA2:	SHA2_DER_PREFIX || H
11207c478bd9Sstevel@tonic-gate 	 *
11217c478bd9Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
11227c478bd9Sstevel@tonic-gate 	 */
1123f66d273dSizick 	switch (session_p->digest.mech.mechanism) {
1124f66d273dSizick 	case CKM_MD5:
11257c478bd9Sstevel@tonic-gate 		(void) memcpy(der_data, MD5_DER_PREFIX, MD5_DER_PREFIX_Len);
11267c478bd9Sstevel@tonic-gate 		(void) memcpy(der_data + MD5_DER_PREFIX_Len, hash, hash_len);
11277c478bd9Sstevel@tonic-gate 		der_data_len = MD5_DER_PREFIX_Len + hash_len;
1128f66d273dSizick 		break;
1129f66d273dSizick 	case CKM_SHA_1:
113060722cc8Sizick 		der_len = get_rsa_sha1_prefix(&(session_p->digest.mech),
113160722cc8Sizick 		    &der_prefix);
113260722cc8Sizick 		(void) memcpy(der_data, der_prefix, der_len);
113360722cc8Sizick 		(void) memcpy(der_data + der_len, hash, hash_len);
113460722cc8Sizick 		der_data_len = der_len + hash_len;
1135f66d273dSizick 		break;
1136f66d273dSizick 	case CKM_SHA256:
1137f66d273dSizick 		(void) memcpy(der_data, SHA256_DER_PREFIX,
1138f66d273dSizick 		    SHA2_DER_PREFIX_Len);
1139f66d273dSizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1140f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1141f66d273dSizick 		break;
1142f66d273dSizick 	case CKM_SHA384:
1143f66d273dSizick 		(void) memcpy(der_data, SHA384_DER_PREFIX,
1144f66d273dSizick 		    SHA2_DER_PREFIX_Len);
1145f66d273dSizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1146f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1147f66d273dSizick 		break;
1148f66d273dSizick 	case CKM_SHA512:
1149f66d273dSizick 		(void) memcpy(der_data, SHA512_DER_PREFIX,
1150f66d273dSizick 		    SHA2_DER_PREFIX_Len);
1151f66d273dSizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1152f66d273dSizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1153f66d273dSizick 		break;
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	/*
11577c478bd9Sstevel@tonic-gate 	 * Now, we are ready to verify the DER_ENCODED data using signature.
11587c478bd9Sstevel@tonic-gate 	 * soft_rsa_verify_common() will free the verification key.
11597c478bd9Sstevel@tonic-gate 	 */
11607c478bd9Sstevel@tonic-gate 	rv = soft_rsa_verify_common(session_p, der_data, der_data_len,
11617c478bd9Sstevel@tonic-gate 	    pSigned, ulSignedLen, mechanism);
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate clean_exit:
11647c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
11657c478bd9Sstevel@tonic-gate 	/* soft_digest_common() has freed the digest context */
11667c478bd9Sstevel@tonic-gate 	session_p->digest.flags = 0;
11677c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 	return (rv);
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate CK_RV
soft_rsa_verify_recover(soft_session_t * session_p,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)11757c478bd9Sstevel@tonic-gate soft_rsa_verify_recover(soft_session_t *session_p, CK_BYTE_PTR pSignature,
11767c478bd9Sstevel@tonic-gate     CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
11777c478bd9Sstevel@tonic-gate {
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
11807c478bd9Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->verify.context;
11817c478bd9Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->verify.mech.mechanism;
11827c478bd9Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
11837c478bd9Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
11847c478bd9Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
11857c478bd9Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
11867c478bd9Sstevel@tonic-gate 
1187c64d15a5Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
11887c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
11897c478bd9Sstevel@tonic-gate 		goto clean_exit;
11907c478bd9Sstevel@tonic-gate 	}
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	if (ulSignatureLen != (CK_ULONG)modulus_len) {
11937c478bd9Sstevel@tonic-gate 		rv = CKR_SIGNATURE_LEN_RANGE;
11947c478bd9Sstevel@tonic-gate 		goto clean_exit;
11957c478bd9Sstevel@tonic-gate 	}
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 	/*
11987c478bd9Sstevel@tonic-gate 	 * Perform RSA decryption with the signer's RSA public key
11997c478bd9Sstevel@tonic-gate 	 * for verification process.
12007c478bd9Sstevel@tonic-gate 	 */
12017c478bd9Sstevel@tonic-gate 	rv = soft_rsa_encrypt(key, pSignature, modulus_len, plain_data, 1);
12027c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
12037c478bd9Sstevel@tonic-gate 		switch (mechanism) {
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 		case CKM_RSA_PKCS:
12067c478bd9Sstevel@tonic-gate 		{
12077c478bd9Sstevel@tonic-gate 			/*
12087c478bd9Sstevel@tonic-gate 			 * Strip off the encoded padding bytes in front of the
12097c478bd9Sstevel@tonic-gate 			 * recovered data.
12107c478bd9Sstevel@tonic-gate 			 */
1211*726fad2aSDina K Nimeh 			size_t data_len = modulus_len;
12127c478bd9Sstevel@tonic-gate 
1213*726fad2aSDina K Nimeh 			rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
12147c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
12157c478bd9Sstevel@tonic-gate 				goto clean_exit;
12167c478bd9Sstevel@tonic-gate 			}
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 			/*
12197c478bd9Sstevel@tonic-gate 			 * If application asks for the length of the output
12207c478bd9Sstevel@tonic-gate 			 * buffer?
12217c478bd9Sstevel@tonic-gate 			 */
12227c478bd9Sstevel@tonic-gate 			if (pData == NULL) {
12237c478bd9Sstevel@tonic-gate 				*pulDataLen = data_len;
12247c478bd9Sstevel@tonic-gate 				rv = CKR_OK;
12257c478bd9Sstevel@tonic-gate 				goto clean1;
12267c478bd9Sstevel@tonic-gate 			}
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate 			/* Is the application-supplied buffer large enough? */
12297c478bd9Sstevel@tonic-gate 			if (*pulDataLen < (CK_ULONG)data_len) {
12307c478bd9Sstevel@tonic-gate 				*pulDataLen = data_len;
12317c478bd9Sstevel@tonic-gate 				rv = CKR_BUFFER_TOO_SMALL;
12327c478bd9Sstevel@tonic-gate 				goto clean1;
12337c478bd9Sstevel@tonic-gate 			}
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 			(void) memcpy(pData,
12367c478bd9Sstevel@tonic-gate 			    &plain_data[modulus_len - data_len], data_len);
12377c478bd9Sstevel@tonic-gate 			*pulDataLen = data_len;
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 			break;
12407c478bd9Sstevel@tonic-gate 		}
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 		case CKM_RSA_X_509:
12437c478bd9Sstevel@tonic-gate 			/*
12447c478bd9Sstevel@tonic-gate 			 * If application asks for the length of the output
12457c478bd9Sstevel@tonic-gate 			 * buffer?
12467c478bd9Sstevel@tonic-gate 			 */
12477c478bd9Sstevel@tonic-gate 			if (pData == NULL) {
12487c478bd9Sstevel@tonic-gate 				*pulDataLen = modulus_len;
12497c478bd9Sstevel@tonic-gate 				rv = CKR_OK;
12507c478bd9Sstevel@tonic-gate 				goto clean1;
12517c478bd9Sstevel@tonic-gate 			}
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate 			/* Is the application-supplied buffer large enough? */
12547c478bd9Sstevel@tonic-gate 			if (*pulDataLen < (CK_ULONG)modulus_len) {
12557c478bd9Sstevel@tonic-gate 				*pulDataLen = modulus_len;
12567c478bd9Sstevel@tonic-gate 				rv = CKR_BUFFER_TOO_SMALL;
12577c478bd9Sstevel@tonic-gate 				goto clean1;
12587c478bd9Sstevel@tonic-gate 			}
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 			(void) memcpy(pData, plain_data, modulus_len);
12617c478bd9Sstevel@tonic-gate 			*pulDataLen = modulus_len;
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 			break;
12647c478bd9Sstevel@tonic-gate 		}
12657c478bd9Sstevel@tonic-gate 	}
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate clean_exit:
12687c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
12697c478bd9Sstevel@tonic-gate 	free(session_p->verify.context);
12707c478bd9Sstevel@tonic-gate 	session_p->verify.context = NULL;
12717c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
12727c478bd9Sstevel@tonic-gate 	soft_cleanup_object(key);
12737c478bd9Sstevel@tonic-gate 	free(key);
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate clean1:
12767c478bd9Sstevel@tonic-gate 	return (rv);
12777c478bd9Sstevel@tonic-gate }
1278