xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRSA.c (revision 12573:fb4ef506980f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56557Sfr41279  * Common Development and Distribution License (the "License").
66557Sfr41279  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*12573SDina.Nimeh@Sun.COM 
220Sstevel@tonic-gate /*
23*12573SDina.Nimeh@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <pthread.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <string.h>
290Sstevel@tonic-gate #include <strings.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <security/cryptoki.h>
32*12573SDina.Nimeh@Sun.COM #include <cryptoutil.h>
330Sstevel@tonic-gate #include "softGlobal.h"
340Sstevel@tonic-gate #include "softSession.h"
350Sstevel@tonic-gate #include "softObject.h"
360Sstevel@tonic-gate #include "softOps.h"
370Sstevel@tonic-gate #include "softRSA.h"
380Sstevel@tonic-gate #include "softMAC.h"
390Sstevel@tonic-gate #include "softCrypt.h"
400Sstevel@tonic-gate 
410Sstevel@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)420Sstevel@tonic-gate soft_rsa_encrypt(soft_object_t *key, CK_BYTE_PTR in, uint32_t in_len,
430Sstevel@tonic-gate     CK_BYTE_PTR out, int realpublic)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /* EXPORT DELETE START */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	uchar_t expo[MAX_KEY_ATTR_BUFLEN];
510Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
520Sstevel@tonic-gate 	uint32_t expo_len = sizeof (expo);
530Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
54*12573SDina.Nimeh@Sun.COM 	RSAbytekey k;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	if (realpublic) {
577260Smcpowers 		rv = soft_get_public_value(key, CKA_PUBLIC_EXPONENT, expo,
580Sstevel@tonic-gate 		    &expo_len);
590Sstevel@tonic-gate 		if (rv != CKR_OK) {
600Sstevel@tonic-gate 			goto clean1;
610Sstevel@tonic-gate 		}
620Sstevel@tonic-gate 	} else {
637260Smcpowers 		rv = soft_get_private_value(key, CKA_PRIVATE_EXPONENT, expo,
640Sstevel@tonic-gate 		    &expo_len);
650Sstevel@tonic-gate 		if (rv != CKR_OK) {
660Sstevel@tonic-gate 			goto clean1;
670Sstevel@tonic-gate 		}
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 
707260Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
710Sstevel@tonic-gate 	if (rv != CKR_OK) {
720Sstevel@tonic-gate 		goto clean1;
730Sstevel@tonic-gate 	}
740Sstevel@tonic-gate 
75*12573SDina.Nimeh@Sun.COM 	k.modulus = modulus;
76*12573SDina.Nimeh@Sun.COM 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
77*12573SDina.Nimeh@Sun.COM 	k.pubexpo = expo;
78*12573SDina.Nimeh@Sun.COM 	k.pubexpo_bytes = expo_len;
79*12573SDina.Nimeh@Sun.COM 	k.rfunc = NULL;
800Sstevel@tonic-gate 
81*12573SDina.Nimeh@Sun.COM 	rv = rsa_encrypt(&k, in, in_len, out);
820Sstevel@tonic-gate 
830Sstevel@tonic-gate clean1:
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /* EXPORT DELETE END */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	return (rv);
880Sstevel@tonic-gate }
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 
910Sstevel@tonic-gate CK_RV
soft_rsa_decrypt(soft_object_t * key,CK_BYTE_PTR in,uint32_t in_len,CK_BYTE_PTR out)920Sstevel@tonic-gate soft_rsa_decrypt(soft_object_t *key, CK_BYTE_PTR in, uint32_t in_len,
930Sstevel@tonic-gate     CK_BYTE_PTR out)
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /* EXPORT DELETE START */
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
1010Sstevel@tonic-gate 	uchar_t prime1[MAX_KEY_ATTR_BUFLEN];
1020Sstevel@tonic-gate 	uchar_t prime2[MAX_KEY_ATTR_BUFLEN];
1030Sstevel@tonic-gate 	uchar_t expo1[MAX_KEY_ATTR_BUFLEN];
1040Sstevel@tonic-gate 	uchar_t expo2[MAX_KEY_ATTR_BUFLEN];
1050Sstevel@tonic-gate 	uchar_t coef[MAX_KEY_ATTR_BUFLEN];
1060Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
1070Sstevel@tonic-gate 	uint32_t prime1_len = sizeof (prime1);
1080Sstevel@tonic-gate 	uint32_t prime2_len = sizeof (prime2);
1090Sstevel@tonic-gate 	uint32_t expo1_len = sizeof (expo1);
1100Sstevel@tonic-gate 	uint32_t expo2_len = sizeof (expo2);
1110Sstevel@tonic-gate 	uint32_t coef_len = sizeof (coef);
112*12573SDina.Nimeh@Sun.COM 	RSAbytekey k;
1130Sstevel@tonic-gate 
1147260Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
1150Sstevel@tonic-gate 	if (rv != CKR_OK) {
1160Sstevel@tonic-gate 		goto clean1;
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1197260Smcpowers 	rv = soft_get_private_value(key, CKA_PRIME_1, prime1, &prime1_len);
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	if ((prime1_len == 0) && (rv == CKR_OK)) {
1220Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1230Sstevel@tonic-gate 		goto clean1;
1240Sstevel@tonic-gate 	} else {
1250Sstevel@tonic-gate 		if (rv != CKR_OK)
1260Sstevel@tonic-gate 			goto clean1;
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 
1297260Smcpowers 	rv = soft_get_private_value(key, CKA_PRIME_2, prime2, &prime2_len);
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	if ((prime2_len == 0) && (rv == CKR_OK)) {
1320Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1330Sstevel@tonic-gate 		goto clean1;
1340Sstevel@tonic-gate 	} else {
1350Sstevel@tonic-gate 		if (rv != CKR_OK)
1360Sstevel@tonic-gate 			goto clean1;
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 
1397260Smcpowers 	rv = soft_get_private_value(key, CKA_EXPONENT_1, expo1, &expo1_len);
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	if ((expo1_len == 0) && (rv == CKR_OK)) {
1420Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1430Sstevel@tonic-gate 		goto clean1;
1440Sstevel@tonic-gate 	} else {
1450Sstevel@tonic-gate 		if (rv != CKR_OK)
1460Sstevel@tonic-gate 			goto clean1;
1470Sstevel@tonic-gate 	}
1480Sstevel@tonic-gate 
1497260Smcpowers 	rv = soft_get_private_value(key, CKA_EXPONENT_2, expo2, &expo2_len);
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	if ((expo2_len == 0) && (rv == CKR_OK)) {
1520Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1530Sstevel@tonic-gate 		goto clean1;
1540Sstevel@tonic-gate 	} else {
1550Sstevel@tonic-gate 		if (rv != CKR_OK)
1560Sstevel@tonic-gate 			goto clean1;
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1597260Smcpowers 	rv = soft_get_private_value(key, CKA_COEFFICIENT, coef, &coef_len);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	if ((coef_len == 0) && (rv == CKR_OK)) {
1620Sstevel@tonic-gate 		rv = soft_rsa_encrypt(key, in, in_len, out, 0);
1630Sstevel@tonic-gate 		goto clean1;
1640Sstevel@tonic-gate 	} else {
1650Sstevel@tonic-gate 		if (rv != CKR_OK)
1660Sstevel@tonic-gate 			goto clean1;
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
169*12573SDina.Nimeh@Sun.COM 	k.modulus = modulus;
170*12573SDina.Nimeh@Sun.COM 	k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len);
171*12573SDina.Nimeh@Sun.COM 	k.prime1 = prime1;
172*12573SDina.Nimeh@Sun.COM 	k.prime1_bytes = prime1_len;
173*12573SDina.Nimeh@Sun.COM 	k.prime2 = prime2;
174*12573SDina.Nimeh@Sun.COM 	k.prime2_bytes = prime2_len;
175*12573SDina.Nimeh@Sun.COM 	k.expo1 = expo1;
176*12573SDina.Nimeh@Sun.COM 	k.expo1_bytes = expo1_len;
177*12573SDina.Nimeh@Sun.COM 	k.expo2 = expo2;
178*12573SDina.Nimeh@Sun.COM 	k.expo2_bytes = expo2_len;
179*12573SDina.Nimeh@Sun.COM 	k.coeff = coef;
180*12573SDina.Nimeh@Sun.COM 	k.coeff_bytes = coef_len;
181*12573SDina.Nimeh@Sun.COM 	k.rfunc = NULL;
1820Sstevel@tonic-gate 
183*12573SDina.Nimeh@Sun.COM 	rv = rsa_decrypt(&k, in, in_len, out);
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate clean1:
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate /* EXPORT DELETE END */
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	return (rv);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate  * Allocate a RSA context for the active encryption or decryption operation.
1940Sstevel@tonic-gate  * This function is called without the session lock held.
1950Sstevel@tonic-gate  */
1960Sstevel@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)1970Sstevel@tonic-gate soft_rsa_crypt_init_common(soft_session_t *session_p,
1980Sstevel@tonic-gate     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
1990Sstevel@tonic-gate     boolean_t encrypt)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx;
2030Sstevel@tonic-gate 	soft_object_t *tmp_key = NULL;
2040Sstevel@tonic-gate 	CK_RV rv;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	rsa_ctx = calloc(1, sizeof (soft_rsa_ctx_t));
2070Sstevel@tonic-gate 	if (rsa_ctx == NULL) {
2080Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2090Sstevel@tonic-gate 	}
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	/*
2120Sstevel@tonic-gate 	 * Make a copy of the encryption or decryption key, and save it
2130Sstevel@tonic-gate 	 * in the RSA crypto context since it will be used later for
2140Sstevel@tonic-gate 	 * encryption/decryption. We don't want to hold any object reference
2150Sstevel@tonic-gate 	 * on this original key while doing encryption/decryption.
2160Sstevel@tonic-gate 	 */
2170Sstevel@tonic-gate 	(void) pthread_mutex_lock(&key_p->object_mutex);
2180Sstevel@tonic-gate 	rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH,
2190Sstevel@tonic-gate 	    NULL);
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	if ((rv != CKR_OK) || (tmp_key == NULL)) {
2220Sstevel@tonic-gate 		/* Most likely we ran out of space. */
2230Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&key_p->object_mutex);
2240Sstevel@tonic-gate 		free(rsa_ctx);
2250Sstevel@tonic-gate 		return (rv);
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	/* No need to hold the lock on the old object. */
2290Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&key_p->object_mutex);
2300Sstevel@tonic-gate 	rsa_ctx->key = tmp_key;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
2330Sstevel@tonic-gate 	if (encrypt) {
2340Sstevel@tonic-gate 		/* Called by C_EncryptInit. */
2350Sstevel@tonic-gate 		session_p->encrypt.context = rsa_ctx;
2360Sstevel@tonic-gate 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
2370Sstevel@tonic-gate 	} else {
2380Sstevel@tonic-gate 		/* Called by C_DecryptInit. */
2390Sstevel@tonic-gate 		session_p->decrypt.context = rsa_ctx;
2400Sstevel@tonic-gate 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	return (CKR_OK);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate 
2470Sstevel@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)2480Sstevel@tonic-gate soft_rsa_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
2490Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
2500Sstevel@tonic-gate     CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->encrypt.context;
2540Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
2550Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
2560Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
2570Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
2580Sstevel@tonic-gate 	CK_BYTE	cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES];
2590Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
2600Sstevel@tonic-gate 
2617260Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
2620Sstevel@tonic-gate 	if (rv != CKR_OK) {
2630Sstevel@tonic-gate 		goto clean_exit;
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	if (pEncrypted == NULL) {
2670Sstevel@tonic-gate 		/*
2680Sstevel@tonic-gate 		 * Application asks for the length of the output buffer
2690Sstevel@tonic-gate 		 * to hold the ciphertext.
2700Sstevel@tonic-gate 		 */
2710Sstevel@tonic-gate 		*pulEncryptedLen = modulus_len;
2720Sstevel@tonic-gate 		rv = CKR_OK;
2730Sstevel@tonic-gate 		goto clean1;
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	if (mechanism == CKM_RSA_PKCS) {
2770Sstevel@tonic-gate 		/*
2780Sstevel@tonic-gate 		 * Input data length needs to be <=
2790Sstevel@tonic-gate 		 * modulus length-MIN_PKCS1_PADLEN.
2800Sstevel@tonic-gate 		 */
2810Sstevel@tonic-gate 		if (ulDataLen > ((CK_ULONG)modulus_len - MIN_PKCS1_PADLEN)) {
2820Sstevel@tonic-gate 			*pulEncryptedLen = modulus_len;
2830Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
2840Sstevel@tonic-gate 			goto clean_exit;
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 	} else {
2870Sstevel@tonic-gate 		/* Input data length needs to be <= modulus length. */
2880Sstevel@tonic-gate 		if (ulDataLen > (CK_ULONG)modulus_len) {
2890Sstevel@tonic-gate 			*pulEncryptedLen = modulus_len;
2900Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
2910Sstevel@tonic-gate 			goto clean_exit;
2920Sstevel@tonic-gate 		}
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	/* Is the application-supplied buffer large enough? */
2960Sstevel@tonic-gate 	if (*pulEncryptedLen < (CK_ULONG)modulus_len) {
2970Sstevel@tonic-gate 		*pulEncryptedLen = modulus_len;
2980Sstevel@tonic-gate 		rv = CKR_BUFFER_TOO_SMALL;
2990Sstevel@tonic-gate 		goto clean1;
3000Sstevel@tonic-gate 	}
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	if (mechanism == CKM_RSA_PKCS) {
3030Sstevel@tonic-gate 		/*
3040Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
3050Sstevel@tonic-gate 		 * type "02" encryption block.
3060Sstevel@tonic-gate 		 */
307*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_encode(PKCS1_ENCRYPT, pData, ulDataLen, plain_data,
3080Sstevel@tonic-gate 		    modulus_len);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 		if (rv != CKR_OK)
3110Sstevel@tonic-gate 			goto clean_exit;
3120Sstevel@tonic-gate 	} else {
3130Sstevel@tonic-gate 		/* Pad zeros for the leading bytes of the input data. */
3140Sstevel@tonic-gate 		(void) memset(plain_data, 0x0, modulus_len - ulDataLen);
3150Sstevel@tonic-gate 		(void) memcpy(&plain_data[modulus_len - ulDataLen], pData,
3160Sstevel@tonic-gate 		    ulDataLen);
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	rv = soft_rsa_encrypt(key, plain_data, modulus_len, cipher_data, 1);
3200Sstevel@tonic-gate 	if (rv == CKR_OK) {
3210Sstevel@tonic-gate 		(void) memcpy(pEncrypted, cipher_data, modulus_len);
3220Sstevel@tonic-gate 		*pulEncryptedLen = modulus_len;
3230Sstevel@tonic-gate 	}
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate clean_exit:
3260Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
3270Sstevel@tonic-gate 	free(session_p->encrypt.context);
3280Sstevel@tonic-gate 	session_p->encrypt.context = NULL;
3290Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
3300Sstevel@tonic-gate 	soft_cleanup_object(key);
3310Sstevel@tonic-gate 	free(key);
3320Sstevel@tonic-gate clean1:
3330Sstevel@tonic-gate 	return (rv);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 
3370Sstevel@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)3380Sstevel@tonic-gate soft_rsa_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
3390Sstevel@tonic-gate     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
3400Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->decrypt.context;
3440Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
3450Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
3460Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
3470Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
3480Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
3490Sstevel@tonic-gate 
3507260Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
3510Sstevel@tonic-gate 	if (rv != CKR_OK) {
3520Sstevel@tonic-gate 		goto clean_exit;
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	if (ulEncryptedLen != (CK_ULONG)modulus_len) {
3560Sstevel@tonic-gate 		rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
3570Sstevel@tonic-gate 		goto clean_exit;
3580Sstevel@tonic-gate 	}
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if (pData == NULL) {
3610Sstevel@tonic-gate 		/*
3620Sstevel@tonic-gate 		 * Application asks for the length of the output buffer
3630Sstevel@tonic-gate 		 * to hold the recovered data.
3640Sstevel@tonic-gate 		 */
3650Sstevel@tonic-gate 		*pulDataLen = modulus_len;
3660Sstevel@tonic-gate 		rv = CKR_OK;
3670Sstevel@tonic-gate 		goto clean1;
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	if (mechanism == CKM_RSA_X_509) {
3710Sstevel@tonic-gate 		if (*pulDataLen < (CK_ULONG)modulus_len) {
3720Sstevel@tonic-gate 			*pulDataLen = modulus_len;
3730Sstevel@tonic-gate 			rv = CKR_BUFFER_TOO_SMALL;
3740Sstevel@tonic-gate 			goto clean1;
3750Sstevel@tonic-gate 		}
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	rv = soft_rsa_decrypt(key, pEncrypted, modulus_len, plain_data);
3790Sstevel@tonic-gate 	if (rv != CKR_OK) {
3800Sstevel@tonic-gate 		goto clean_exit;
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	if (mechanism == CKM_RSA_PKCS) {
384*12573SDina.Nimeh@Sun.COM 		size_t plain_len = modulus_len;
385*12573SDina.Nimeh@Sun.COM 		size_t num_padding;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 		/* Strip off the PKCS block formatting data. */
388*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_decode(PKCS1_DECRYPT, plain_data, &plain_len);
3890Sstevel@tonic-gate 		if (rv != CKR_OK)
3900Sstevel@tonic-gate 			goto clean_exit;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 		num_padding = modulus_len - plain_len;
3930Sstevel@tonic-gate 		if (ulEncryptedLen - num_padding > *pulDataLen) {
3940Sstevel@tonic-gate 			*pulDataLen = plain_len;
3950Sstevel@tonic-gate 			rv = CKR_BUFFER_TOO_SMALL;
3960Sstevel@tonic-gate 			goto clean1;
3970Sstevel@tonic-gate 		}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 		(void) memcpy(pData, &plain_data[num_padding], plain_len);
4000Sstevel@tonic-gate 		*pulDataLen = plain_len;
4010Sstevel@tonic-gate 	} else {
4020Sstevel@tonic-gate 		(void) memcpy(pData, plain_data, modulus_len);
4030Sstevel@tonic-gate 		*pulDataLen = modulus_len;
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate clean_exit:
4070Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
4080Sstevel@tonic-gate 	free(session_p->decrypt.context);
4090Sstevel@tonic-gate 	session_p->decrypt.context = NULL;
4100Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
4110Sstevel@tonic-gate 	soft_cleanup_object(key);
4120Sstevel@tonic-gate 	free(key);
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate clean1:
4150Sstevel@tonic-gate 	return (rv);
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate /*
4190Sstevel@tonic-gate  * Allocate a RSA context for the active sign or verify operation.
4200Sstevel@tonic-gate  * This function is called without the session lock held.
4210Sstevel@tonic-gate  */
4220Sstevel@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)4230Sstevel@tonic-gate soft_rsa_sign_verify_init_common(soft_session_t *session_p,
4240Sstevel@tonic-gate     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
4250Sstevel@tonic-gate     boolean_t sign)
4260Sstevel@tonic-gate {
4270Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
4280Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx;
4290Sstevel@tonic-gate 	CK_MECHANISM digest_mech;
4300Sstevel@tonic-gate 	soft_object_t *tmp_key = NULL;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	if (sign) {
4330Sstevel@tonic-gate 		if ((key_p->class != CKO_PRIVATE_KEY) ||
4340Sstevel@tonic-gate 		    (key_p->key_type != CKK_RSA))
4350Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
4360Sstevel@tonic-gate 	} else {
4370Sstevel@tonic-gate 		if ((key_p->class != CKO_PUBLIC_KEY) ||
4380Sstevel@tonic-gate 		    (key_p->key_type != CKK_RSA))
4390Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
4400Sstevel@tonic-gate 	}
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	switch (pMechanism->mechanism) {
4430Sstevel@tonic-gate 	case CKM_MD5_RSA_PKCS:
4440Sstevel@tonic-gate 		digest_mech.mechanism = CKM_MD5;
4450Sstevel@tonic-gate 		rv = soft_digest_init_internal(session_p, &digest_mech);
4460Sstevel@tonic-gate 		if (rv != CKR_OK)
4470Sstevel@tonic-gate 			return (rv);
4480Sstevel@tonic-gate 		break;
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	case CKM_SHA1_RSA_PKCS:
4510Sstevel@tonic-gate 		digest_mech.mechanism = CKM_SHA_1;
452872Sizick 		digest_mech.pParameter = pMechanism->pParameter;
453872Sizick 		digest_mech.ulParameterLen = pMechanism->ulParameterLen;
4540Sstevel@tonic-gate 		rv = soft_digest_init_internal(session_p, &digest_mech);
4550Sstevel@tonic-gate 		if (rv != CKR_OK)
4560Sstevel@tonic-gate 			return (rv);
4570Sstevel@tonic-gate 		break;
458676Sizick 
459676Sizick 	case CKM_SHA256_RSA_PKCS:
460676Sizick 		digest_mech.mechanism = CKM_SHA256;
461676Sizick 		rv = soft_digest_init_internal(session_p, &digest_mech);
462676Sizick 		if (rv != CKR_OK)
463676Sizick 			return (rv);
464676Sizick 		break;
465676Sizick 
466676Sizick 	case CKM_SHA384_RSA_PKCS:
467676Sizick 		digest_mech.mechanism = CKM_SHA384;
468676Sizick 		rv = soft_digest_init_internal(session_p, &digest_mech);
469676Sizick 		if (rv != CKR_OK)
470676Sizick 			return (rv);
471676Sizick 		break;
472676Sizick 
473676Sizick 	case CKM_SHA512_RSA_PKCS:
474676Sizick 		digest_mech.mechanism = CKM_SHA512;
475676Sizick 		rv = soft_digest_init_internal(session_p, &digest_mech);
476676Sizick 		if (rv != CKR_OK)
477676Sizick 			return (rv);
478676Sizick 		break;
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	rsa_ctx = malloc(sizeof (soft_rsa_ctx_t));
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	if (rsa_ctx == NULL) {
4840Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
4850Sstevel@tonic-gate 		goto clean_exit;
4860Sstevel@tonic-gate 	}
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	(void) pthread_mutex_lock(&key_p->object_mutex);
4890Sstevel@tonic-gate 	rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH,
4900Sstevel@tonic-gate 	    NULL);
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	if ((rv != CKR_OK) || (tmp_key == NULL)) {
4930Sstevel@tonic-gate 		/* Most likely we ran out of space. */
4940Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&key_p->object_mutex);
4950Sstevel@tonic-gate 		free(rsa_ctx);
4960Sstevel@tonic-gate 		goto clean_exit;
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	/* No need to hold the lock on the old object. */
5000Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&key_p->object_mutex);
5010Sstevel@tonic-gate 	rsa_ctx->key = tmp_key;
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	if (sign) {
5060Sstevel@tonic-gate 		session_p->sign.context = rsa_ctx;
5070Sstevel@tonic-gate 		session_p->sign.mech.mechanism = pMechanism->mechanism;
5080Sstevel@tonic-gate 	} else {
5090Sstevel@tonic-gate 		session_p->verify.context = rsa_ctx;
5100Sstevel@tonic-gate 		session_p->verify.mech.mechanism = pMechanism->mechanism;
5110Sstevel@tonic-gate 	}
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	return (CKR_OK);
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate clean_exit:
5180Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5190Sstevel@tonic-gate 	if (session_p->digest.context != NULL) {
5200Sstevel@tonic-gate 		free(session_p->digest.context);
5210Sstevel@tonic-gate 		session_p->digest.context = NULL;
5220Sstevel@tonic-gate 		session_p->digest.flags = 0;
5230Sstevel@tonic-gate 	}
5240Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
5250Sstevel@tonic-gate 	return (rv);
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 
5300Sstevel@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)5310Sstevel@tonic-gate soft_rsa_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData,
5320Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned,
5330Sstevel@tonic-gate     CK_ULONG_PTR pulSignedLen, CK_MECHANISM_TYPE mechanism)
5340Sstevel@tonic-gate {
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5370Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->sign.context;
5380Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
5390Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
5400Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
5410Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
5420Sstevel@tonic-gate 	CK_BYTE	signed_data[MAX_RSA_KEYLENGTH_IN_BYTES];
5430Sstevel@tonic-gate 
5447260Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
5450Sstevel@tonic-gate 	if (rv != CKR_OK) {
5460Sstevel@tonic-gate 		goto clean_exit;
5470Sstevel@tonic-gate 	}
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	if (pSigned == NULL) {
5500Sstevel@tonic-gate 		/* Application asks for the length of the output buffer. */
5510Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
5520Sstevel@tonic-gate 		rv = CKR_OK;
5530Sstevel@tonic-gate 		goto clean1;
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	switch (mechanism) {
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	case CKM_RSA_PKCS:
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 		/*
5610Sstevel@tonic-gate 		 * Input data length needs to be <=
5620Sstevel@tonic-gate 		 * modulus length-MIN_PKCS1_PADLEN.
5630Sstevel@tonic-gate 		 */
5640Sstevel@tonic-gate 		if (ulDataLen > ((CK_ULONG)modulus_len - MIN_PKCS1_PADLEN)) {
5650Sstevel@tonic-gate 			*pulSignedLen = modulus_len;
5660Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
5670Sstevel@tonic-gate 			goto clean_exit;
5680Sstevel@tonic-gate 		}
5690Sstevel@tonic-gate 		break;
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	case CKM_RSA_X_509:
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 		/* Input data length needs to be <= modulus length. */
5740Sstevel@tonic-gate 		if (ulDataLen > (CK_ULONG)modulus_len) {
5750Sstevel@tonic-gate 			*pulSignedLen = modulus_len;
5760Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
5770Sstevel@tonic-gate 			goto clean_exit;
5780Sstevel@tonic-gate 		}
5790Sstevel@tonic-gate 		break;
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	/* Is the application-supplied buffer large enough? */
5830Sstevel@tonic-gate 	if (*pulSignedLen < (CK_ULONG)modulus_len) {
5840Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
5850Sstevel@tonic-gate 		rv = CKR_BUFFER_TOO_SMALL;
5860Sstevel@tonic-gate 		goto clean1;
5870Sstevel@tonic-gate 	}
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	switch (mechanism) {
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	case CKM_RSA_PKCS:
5920Sstevel@tonic-gate 	case CKM_MD5_RSA_PKCS:
5930Sstevel@tonic-gate 	case CKM_SHA1_RSA_PKCS:
594676Sizick 	case CKM_SHA256_RSA_PKCS:
595676Sizick 	case CKM_SHA384_RSA_PKCS:
596676Sizick 	case CKM_SHA512_RSA_PKCS:
5970Sstevel@tonic-gate 		/*
5980Sstevel@tonic-gate 		 * Add PKCS padding to the input data to format a block
5990Sstevel@tonic-gate 		 * type "01" encryption block.
6000Sstevel@tonic-gate 		 */
601*12573SDina.Nimeh@Sun.COM 		rv = pkcs1_encode(PKCS1_SIGN, pData, ulDataLen, plain_data,
6020Sstevel@tonic-gate 		    modulus_len);
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 		if (rv != CKR_OK) {
6050Sstevel@tonic-gate 			goto clean_exit;
6060Sstevel@tonic-gate 		}
6070Sstevel@tonic-gate 		break;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	case CKM_RSA_X_509:
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 		/* Pad zeros for the leading bytes of the input data. */
6120Sstevel@tonic-gate 		(void) memset(plain_data, 0x0, modulus_len - ulDataLen);
6130Sstevel@tonic-gate 		(void) memcpy(&plain_data[modulus_len - ulDataLen], pData,
6140Sstevel@tonic-gate 		    ulDataLen);
6150Sstevel@tonic-gate 		break;
6160Sstevel@tonic-gate 	}
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	/*
6190Sstevel@tonic-gate 	 * Perform RSA encryption with the signer's RSA private key
6200Sstevel@tonic-gate 	 * for signature process.
6210Sstevel@tonic-gate 	 */
6220Sstevel@tonic-gate 	rv = soft_rsa_decrypt(key, plain_data, modulus_len, signed_data);
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	if (rv == CKR_OK) {
6250Sstevel@tonic-gate 		(void) memcpy(pSigned, signed_data, modulus_len);
6260Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate clean_exit:
6300Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
6310Sstevel@tonic-gate 	free(session_p->sign.context);
6320Sstevel@tonic-gate 	session_p->sign.context = NULL;
6330Sstevel@tonic-gate 	if (session_p->digest.context != NULL) {
6340Sstevel@tonic-gate 		free(session_p->digest.context);
6350Sstevel@tonic-gate 		session_p->digest.context = NULL;
6360Sstevel@tonic-gate 		session_p->digest.flags = 0;
6370Sstevel@tonic-gate 	}
6380Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
6390Sstevel@tonic-gate 	soft_cleanup_object(key);
6400Sstevel@tonic-gate 	free(key);
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate clean1:
6430Sstevel@tonic-gate 	return (rv);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 
6470Sstevel@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)6480Sstevel@tonic-gate soft_rsa_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
6490Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
6500Sstevel@tonic-gate     CK_ULONG ulSignatureLen, CK_MECHANISM_TYPE mechanism)
6510Sstevel@tonic-gate {
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6540Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->verify.context;
6550Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
6560Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
6570Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
6580Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
6590Sstevel@tonic-gate 
6607260Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
6610Sstevel@tonic-gate 	if (rv != CKR_OK) {
6620Sstevel@tonic-gate 		goto clean_exit;
6630Sstevel@tonic-gate 	}
6640Sstevel@tonic-gate 
665*12573SDina.Nimeh@Sun.COM 	if (ulDataLen == 0) {
666*12573SDina.Nimeh@Sun.COM 		rv = CKR_DATA_LEN_RANGE;
667*12573SDina.Nimeh@Sun.COM 		goto clean_exit;
668*12573SDina.Nimeh@Sun.COM 	}
669*12573SDina.Nimeh@Sun.COM 
6700Sstevel@tonic-gate 	if (ulSignatureLen != (CK_ULONG)modulus_len) {
6710Sstevel@tonic-gate 		rv = CKR_SIGNATURE_LEN_RANGE;
6720Sstevel@tonic-gate 		goto clean_exit;
6730Sstevel@tonic-gate 	}
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 	/*
6760Sstevel@tonic-gate 	 * Perform RSA decryption with the signer's RSA public key
6770Sstevel@tonic-gate 	 * for verification process.
6780Sstevel@tonic-gate 	 */
6790Sstevel@tonic-gate 	rv = soft_rsa_encrypt(key, pSignature, modulus_len, plain_data, 1);
6800Sstevel@tonic-gate 	if (rv == CKR_OK) {
6810Sstevel@tonic-gate 		switch (mechanism) {
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 		case CKM_RSA_PKCS:
6840Sstevel@tonic-gate 		case CKM_MD5_RSA_PKCS:
6850Sstevel@tonic-gate 		case CKM_SHA1_RSA_PKCS:
686676Sizick 		case CKM_SHA256_RSA_PKCS:
687676Sizick 		case CKM_SHA384_RSA_PKCS:
688676Sizick 		case CKM_SHA512_RSA_PKCS:
6890Sstevel@tonic-gate 		{
6900Sstevel@tonic-gate 			/*
6910Sstevel@tonic-gate 			 * Strip off the encoded padding bytes in front of the
6920Sstevel@tonic-gate 			 * recovered data, then compare the recovered data with
6930Sstevel@tonic-gate 			 * the original data.
6940Sstevel@tonic-gate 			 */
695*12573SDina.Nimeh@Sun.COM 			size_t data_len = modulus_len;
6960Sstevel@tonic-gate 
697*12573SDina.Nimeh@Sun.COM 			rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
6980Sstevel@tonic-gate 			if (rv != CKR_OK) {
6990Sstevel@tonic-gate 				goto clean_exit;
7000Sstevel@tonic-gate 			}
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 			if ((CK_ULONG)data_len != ulDataLen) {
703*12573SDina.Nimeh@Sun.COM 				rv = CKR_DATA_LEN_RANGE;
7040Sstevel@tonic-gate 				goto clean_exit;
7050Sstevel@tonic-gate 			} else if (memcmp(pData,
7060Sstevel@tonic-gate 			    &plain_data[modulus_len - data_len],
7070Sstevel@tonic-gate 			    ulDataLen) != 0) {
7080Sstevel@tonic-gate 				rv = CKR_SIGNATURE_INVALID;
7090Sstevel@tonic-gate 				goto clean_exit;
7100Sstevel@tonic-gate 			}
7110Sstevel@tonic-gate 			break;
7120Sstevel@tonic-gate 		}
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 		case CKM_RSA_X_509:
7150Sstevel@tonic-gate 			/*
7160Sstevel@tonic-gate 			 * Strip off the encoded padding bytes in front of the
7170Sstevel@tonic-gate 			 * recovered plain_data, then compare the input data
7180Sstevel@tonic-gate 			 * with the recovered data.
7190Sstevel@tonic-gate 			 */
7200Sstevel@tonic-gate 			if (memcmp(pData,
7210Sstevel@tonic-gate 			    plain_data + ulSignatureLen - ulDataLen,
7220Sstevel@tonic-gate 			    ulDataLen) != 0) {
7230Sstevel@tonic-gate 				rv = CKR_SIGNATURE_INVALID;
7240Sstevel@tonic-gate 				goto clean_exit;
7250Sstevel@tonic-gate 			}
7260Sstevel@tonic-gate 			break;
7270Sstevel@tonic-gate 		}
7280Sstevel@tonic-gate 	}
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	if (rv == CKR_DATA_LEN_RANGE) {
7310Sstevel@tonic-gate 		if ((mechanism == CKM_MD5_RSA_PKCS) ||
732676Sizick 		    (mechanism == CKM_SHA1_RSA_PKCS) ||
733676Sizick 		    (mechanism == CKM_SHA256_RSA_PKCS) ||
734676Sizick 		    (mechanism == CKM_SHA384_RSA_PKCS) ||
735676Sizick 		    (mechanism == CKM_SHA512_RSA_PKCS))
7360Sstevel@tonic-gate 			rv = CKR_SIGNATURE_INVALID;
7370Sstevel@tonic-gate 	}
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate clean_exit:
7400Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
7410Sstevel@tonic-gate 	free(session_p->verify.context);
7420Sstevel@tonic-gate 	session_p->verify.context = NULL;
7430Sstevel@tonic-gate 	if (session_p->digest.context != NULL) {
7440Sstevel@tonic-gate 		free(session_p->digest.context);
7450Sstevel@tonic-gate 		session_p->digest.context = NULL;
7460Sstevel@tonic-gate 		session_p->digest.flags = 0;
7470Sstevel@tonic-gate 	}
7480Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
7490Sstevel@tonic-gate 	soft_cleanup_object(key);
7500Sstevel@tonic-gate 	free(key);
7510Sstevel@tonic-gate 	return (rv);
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate 
7540Sstevel@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)755*12573SDina.Nimeh@Sun.COM soft_genRSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
756*12573SDina.Nimeh@Sun.COM     uchar_t *buf, uint32_t buflen, boolean_t public)
7570Sstevel@tonic-gate {
7580Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
7590Sstevel@tonic-gate 	biginteger_t *dst = NULL;
7600Sstevel@tonic-gate 	biginteger_t src;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	switch (type) {
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate 	case CKA_MODULUS:
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 		if (public)
7670Sstevel@tonic-gate 			dst = OBJ_PUB_RSA_MOD(key);
7680Sstevel@tonic-gate 		else
7690Sstevel@tonic-gate 			dst = OBJ_PRI_RSA_MOD(key);
7700Sstevel@tonic-gate 		break;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	case CKA_PUBLIC_EXPONENT:
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 		if (public)
7750Sstevel@tonic-gate 			dst = OBJ_PUB_RSA_PUBEXPO(key);
7760Sstevel@tonic-gate 		else
7770Sstevel@tonic-gate 			dst = OBJ_PRI_RSA_PUBEXPO(key);
7780Sstevel@tonic-gate 		break;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	case CKA_PRIVATE_EXPONENT:
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_PRIEXPO(key);
7830Sstevel@tonic-gate 		break;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	case CKA_PRIME_1:
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_PRIME1(key);
7880Sstevel@tonic-gate 		break;
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	case CKA_PRIME_2:
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_PRIME2(key);
7930Sstevel@tonic-gate 		break;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	case CKA_EXPONENT_1:
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_EXPO1(key);
7980Sstevel@tonic-gate 		break;
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	case CKA_EXPONENT_2:
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_EXPO2(key);
8030Sstevel@tonic-gate 		break;
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	case CKA_COEFFICIENT:
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 		dst = OBJ_PRI_RSA_COEF(key);
8080Sstevel@tonic-gate 		break;
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 
811*12573SDina.Nimeh@Sun.COM 	/* Note: no explanation found for why this is needed */
8120Sstevel@tonic-gate 	while (buf[0] == 0) {	/* remove proceeding 0x00 */
8130Sstevel@tonic-gate 		buf++;
8140Sstevel@tonic-gate 		buflen--;
8150Sstevel@tonic-gate 	}
8160Sstevel@tonic-gate 
817*12573SDina.Nimeh@Sun.COM 	if ((rv = dup_bigint_attr(&src, buf, buflen)) != CKR_OK)
8180Sstevel@tonic-gate 		goto cleanexit;
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	/* Copy the attribute in the key object. */
8210Sstevel@tonic-gate 	copy_bigint_attr(&src, dst);
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate cleanexit:
8240Sstevel@tonic-gate 	return (rv);
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate CK_RV
soft_rsa_genkey_pair(soft_object_t * pubkey,soft_object_t * prikey)8300Sstevel@tonic-gate soft_rsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey)
8310Sstevel@tonic-gate {
8320Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
833*12573SDina.Nimeh@Sun.COM 	CK_ATTRIBUTE template;
834*12573SDina.Nimeh@Sun.COM 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
8350Sstevel@tonic-gate 	uint32_t modulus_len;
836*12573SDina.Nimeh@Sun.COM 	uchar_t pub_expo[MAX_KEY_ATTR_BUFLEN];
8370Sstevel@tonic-gate 	uint32_t pub_expo_len = sizeof (pub_expo);
838*12573SDina.Nimeh@Sun.COM 	uchar_t private_exponent[MAX_KEY_ATTR_BUFLEN];
839*12573SDina.Nimeh@Sun.COM 	uint32_t private_exponent_len = sizeof (private_exponent);
840*12573SDina.Nimeh@Sun.COM 	uchar_t prime1[MAX_KEY_ATTR_BUFLEN];
841*12573SDina.Nimeh@Sun.COM 	uint32_t prime1_len = sizeof (prime1);
842*12573SDina.Nimeh@Sun.COM 	uchar_t prime2[MAX_KEY_ATTR_BUFLEN];
843*12573SDina.Nimeh@Sun.COM 	uint32_t prime2_len = sizeof (prime2);
844*12573SDina.Nimeh@Sun.COM 	uchar_t exponent1[MAX_KEY_ATTR_BUFLEN];
845*12573SDina.Nimeh@Sun.COM 	uint32_t exponent1_len = sizeof (exponent1);
846*12573SDina.Nimeh@Sun.COM 	uchar_t exponent2[MAX_KEY_ATTR_BUFLEN];
847*12573SDina.Nimeh@Sun.COM 	uint32_t exponent2_len = sizeof (exponent2);
848*12573SDina.Nimeh@Sun.COM 	uchar_t coefficient[MAX_KEY_ATTR_BUFLEN];
849*12573SDina.Nimeh@Sun.COM 	uint32_t coefficient_len = sizeof (coefficient);
850*12573SDina.Nimeh@Sun.COM 	RSAbytekey k;
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 	if ((pubkey == NULL) || (prikey == NULL)) {
8530Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
8540Sstevel@tonic-gate 	}
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	template.pValue = malloc(sizeof (CK_ULONG));
8570Sstevel@tonic-gate 	if (template.pValue == NULL) {
8580Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
8590Sstevel@tonic-gate 	}
8600Sstevel@tonic-gate 	template.ulValueLen = sizeof (CK_ULONG);
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	rv = get_ulong_attr_from_object(OBJ_PUB_RSA_MOD_BITS(pubkey),
8630Sstevel@tonic-gate 	    &template);
8640Sstevel@tonic-gate 	if (rv != CKR_OK) {
865*12573SDina.Nimeh@Sun.COM 		free(template.pValue);
8660Sstevel@tonic-gate 		goto clean0;
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate #ifdef	__sparcv9
8700Sstevel@tonic-gate 	/* LINTED */
8710Sstevel@tonic-gate 	modulus_len = (uint32_t)(*((CK_ULONG *)(template.pValue)));
8720Sstevel@tonic-gate #else	/* !__sparcv9 */
8730Sstevel@tonic-gate 	modulus_len = *((CK_ULONG *)(template.pValue));
8740Sstevel@tonic-gate #endif	/* __sparcv9 */
8750Sstevel@tonic-gate 
876*12573SDina.Nimeh@Sun.COM 	free(template.pValue);
8770Sstevel@tonic-gate 
8787260Smcpowers 	rv = soft_get_public_value(pubkey, CKA_PUBLIC_EXPONENT, pub_expo,
8790Sstevel@tonic-gate 	    &pub_expo_len);
8800Sstevel@tonic-gate 	if (rv != CKR_OK) {
8810Sstevel@tonic-gate 		goto clean0;
8820Sstevel@tonic-gate 	}
8830Sstevel@tonic-gate 
884*12573SDina.Nimeh@Sun.COM 	/* Inputs to RSA key pair generation */
885*12573SDina.Nimeh@Sun.COM 	k.modulus_bits = modulus_len;		/* save modulus len in bits  */
886*12573SDina.Nimeh@Sun.COM 	modulus_len = CRYPTO_BITS2BYTES(modulus_len);	/* convert to bytes */
887*12573SDina.Nimeh@Sun.COM 	k.modulus = modulus;
888*12573SDina.Nimeh@Sun.COM 	k.pubexpo = pub_expo;
889*12573SDina.Nimeh@Sun.COM 	k.pubexpo_bytes = pub_expo_len;
890*12573SDina.Nimeh@Sun.COM 	k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ?
891*12573SDina.Nimeh@Sun.COM 	    pkcs11_get_random : pkcs11_get_urandom;
8920Sstevel@tonic-gate 
893*12573SDina.Nimeh@Sun.COM 	/* Outputs from RSA key pair generation */
894*12573SDina.Nimeh@Sun.COM 	k.privexpo = private_exponent;
895*12573SDina.Nimeh@Sun.COM 	k.privexpo_bytes = private_exponent_len;
896*12573SDina.Nimeh@Sun.COM 	k.prime1 = prime1;
897*12573SDina.Nimeh@Sun.COM 	k.prime1_bytes = prime1_len;
898*12573SDina.Nimeh@Sun.COM 	k.prime2 = prime2;
899*12573SDina.Nimeh@Sun.COM 	k.prime2_bytes = prime2_len;
900*12573SDina.Nimeh@Sun.COM 	k.expo1 = exponent1;
901*12573SDina.Nimeh@Sun.COM 	k.expo1_bytes = exponent1_len;
902*12573SDina.Nimeh@Sun.COM 	k.expo2 = exponent2;
903*12573SDina.Nimeh@Sun.COM 	k.expo2_bytes = exponent2_len;
904*12573SDina.Nimeh@Sun.COM 	k.coeff = coefficient;
905*12573SDina.Nimeh@Sun.COM 	k.coeff_bytes = coefficient_len;
9060Sstevel@tonic-gate 
907*12573SDina.Nimeh@Sun.COM 	rv = rsa_genkey_pair(&k);
908*12573SDina.Nimeh@Sun.COM 
909*12573SDina.Nimeh@Sun.COM 	if (rv != CKR_OK) {
910*12573SDina.Nimeh@Sun.COM 		goto clean0;
9110Sstevel@tonic-gate 	}
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	/*
9140Sstevel@tonic-gate 	 * Add modulus in public template, and add all eight key fields
9150Sstevel@tonic-gate 	 * in private template.
9160Sstevel@tonic-gate 	 */
917*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(pubkey, CKA_MODULUS,
918*12573SDina.Nimeh@Sun.COM 	    modulus, CRYPTO_BITS2BYTES(k.modulus_bits), B_TRUE)) != CKR_OK) {
919*12573SDina.Nimeh@Sun.COM 		goto clean0;
9200Sstevel@tonic-gate 	}
9210Sstevel@tonic-gate 
922*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_MODULUS,
923*12573SDina.Nimeh@Sun.COM 	    modulus, CRYPTO_BITS2BYTES(k.modulus_bits), B_FALSE)) != CKR_OK) {
924*12573SDina.Nimeh@Sun.COM 		goto clean0;
9250Sstevel@tonic-gate 	}
9260Sstevel@tonic-gate 
927*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIVATE_EXPONENT,
928*12573SDina.Nimeh@Sun.COM 	    private_exponent, k.privexpo_bytes, B_FALSE)) != CKR_OK) {
929*12573SDina.Nimeh@Sun.COM 		goto clean0;
9300Sstevel@tonic-gate 	}
9310Sstevel@tonic-gate 
932*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PUBLIC_EXPONENT,
933*12573SDina.Nimeh@Sun.COM 	    pub_expo, k.pubexpo_bytes, B_FALSE)) != CKR_OK) {
934*12573SDina.Nimeh@Sun.COM 		goto clean0;
9350Sstevel@tonic-gate 	}
9360Sstevel@tonic-gate 
937*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIME_1,
938*12573SDina.Nimeh@Sun.COM 	    prime1, k.prime1_bytes, B_FALSE)) != CKR_OK) {
939*12573SDina.Nimeh@Sun.COM 		goto clean0;
9400Sstevel@tonic-gate 	}
9410Sstevel@tonic-gate 
942*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIME_2,
943*12573SDina.Nimeh@Sun.COM 	    prime2, k.prime2_bytes, B_FALSE)) != CKR_OK) {
944*12573SDina.Nimeh@Sun.COM 		goto clean0;
9450Sstevel@tonic-gate 	}
9460Sstevel@tonic-gate 
947*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_EXPONENT_1,
948*12573SDina.Nimeh@Sun.COM 	    exponent1, k.expo1_bytes, B_FALSE)) != CKR_OK) {
949*12573SDina.Nimeh@Sun.COM 		goto clean0;
9500Sstevel@tonic-gate 	}
9510Sstevel@tonic-gate 
952*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_EXPONENT_2,
953*12573SDina.Nimeh@Sun.COM 	    exponent2, k.expo2_bytes, B_FALSE)) != CKR_OK) {
954*12573SDina.Nimeh@Sun.COM 		goto clean0;
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
957*12573SDina.Nimeh@Sun.COM 	if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_COEFFICIENT,
958*12573SDina.Nimeh@Sun.COM 	    coefficient, k.coeff_bytes, B_FALSE)) != CKR_OK) {
959*12573SDina.Nimeh@Sun.COM 		goto clean0;
960*12573SDina.Nimeh@Sun.COM 	}
961*12573SDina.Nimeh@Sun.COM 
9620Sstevel@tonic-gate clean0:
9630Sstevel@tonic-gate 	return (rv);
9640Sstevel@tonic-gate }
9650Sstevel@tonic-gate 
966872Sizick 
967872Sizick CK_ULONG
get_rsa_sha1_prefix(CK_MECHANISM_PTR mech,CK_BYTE_PTR * prefix)968872Sizick get_rsa_sha1_prefix(CK_MECHANISM_PTR mech, CK_BYTE_PTR *prefix) {
969872Sizick 	if (mech->pParameter == NULL) {
970872Sizick 		*prefix = (CK_BYTE *)SHA1_DER_PREFIX;
971872Sizick 		return (SHA1_DER_PREFIX_Len);
972872Sizick 	}
973872Sizick 
974872Sizick 	*prefix = (CK_BYTE *)SHA1_DER_PREFIX_OID;
975872Sizick 	return (SHA1_DER_PREFIX_OID_Len);
976872Sizick }
977872Sizick 
9780Sstevel@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)9790Sstevel@tonic-gate soft_rsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData,
9800Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned,
9810Sstevel@tonic-gate     CK_ULONG_PTR pulSignedLen, CK_MECHANISM_TYPE mechanism, boolean_t Final)
9820Sstevel@tonic-gate {
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
985676Sizick 	CK_BYTE hash[SHA512_DIGEST_LENGTH];  /* space enough for all mechs */
986676Sizick 	CK_ULONG hash_len = SHA512_DIGEST_LENGTH;
987676Sizick 	/* space enough for all mechs */
988676Sizick 	CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
9890Sstevel@tonic-gate 	CK_ULONG der_data_len;
9900Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->sign.context;
9910Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
9920Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
9930Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
994872Sizick 	CK_ULONG der_len;
995872Sizick 	CK_BYTE_PTR der_prefix;
9960Sstevel@tonic-gate 
9977260Smcpowers 	rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len);
9980Sstevel@tonic-gate 	if (rv != CKR_OK) {
9990Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
10000Sstevel@tonic-gate 		free(session_p->digest.context);
10010Sstevel@tonic-gate 		session_p->digest.context = NULL;
10020Sstevel@tonic-gate 		session_p->digest.flags = 0;
10030Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
10040Sstevel@tonic-gate 		soft_cleanup_object(key);
10050Sstevel@tonic-gate 		free(key);
10060Sstevel@tonic-gate 		goto clean1;
10070Sstevel@tonic-gate 	}
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 	/* Check arguments before performing message digest. */
10100Sstevel@tonic-gate 	if (pSigned == NULL) {
10110Sstevel@tonic-gate 		/* Application asks for the length of the output buffer. */
10120Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
10130Sstevel@tonic-gate 		rv = CKR_OK;
10140Sstevel@tonic-gate 		goto clean1;
10150Sstevel@tonic-gate 	}
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	/* Is the application-supplied buffer large enough? */
10180Sstevel@tonic-gate 	if (*pulSignedLen < (CK_ULONG)modulus_len) {
10190Sstevel@tonic-gate 		*pulSignedLen = modulus_len;
10200Sstevel@tonic-gate 		rv = CKR_BUFFER_TOO_SMALL;
10210Sstevel@tonic-gate 		goto clean1;
10220Sstevel@tonic-gate 	}
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate 	if (Final) {
10250Sstevel@tonic-gate 		rv = soft_digest_final(session_p, hash, &hash_len);
10260Sstevel@tonic-gate 	} else {
10270Sstevel@tonic-gate 		rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len);
10280Sstevel@tonic-gate 	}
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate 	if (rv != CKR_OK) {
10310Sstevel@tonic-gate 		/* free the signature key */
10320Sstevel@tonic-gate 		soft_cleanup_object(key);
10330Sstevel@tonic-gate 		free(key);
10340Sstevel@tonic-gate 		goto clean_exit;
10350Sstevel@tonic-gate 	}
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate 	/*
1038872Sizick 	 * Prepare the DER encoding of the DigestInfo value by setting it to:
1039872Sizick 	 *	<MECH>_DER_PREFIX || H
10400Sstevel@tonic-gate 	 *
10410Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
10420Sstevel@tonic-gate 	 */
1043676Sizick 	switch (session_p->digest.mech.mechanism) {
1044676Sizick 	case CKM_MD5:
10450Sstevel@tonic-gate 		(void) memcpy(der_data, MD5_DER_PREFIX, MD5_DER_PREFIX_Len);
10460Sstevel@tonic-gate 		(void) memcpy(der_data + MD5_DER_PREFIX_Len, hash, hash_len);
10470Sstevel@tonic-gate 		der_data_len = MD5_DER_PREFIX_Len + hash_len;
1048676Sizick 		break;
1049676Sizick 	case CKM_SHA_1:
1050872Sizick 		der_len = get_rsa_sha1_prefix(&(session_p->digest.mech),
1051872Sizick 		    &der_prefix);
1052872Sizick 		(void) memcpy(der_data, der_prefix, der_len);
1053872Sizick 		(void) memcpy(der_data + der_len, hash, hash_len);
1054872Sizick 		der_data_len = der_len + hash_len;
1055676Sizick 		break;
1056676Sizick 	case CKM_SHA256:
1057676Sizick 		(void) memcpy(der_data, SHA256_DER_PREFIX,
1058676Sizick 		    SHA2_DER_PREFIX_Len);
1059676Sizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1060676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1061676Sizick 		break;
1062676Sizick 	case CKM_SHA384:
1063676Sizick 		(void) memcpy(der_data, SHA384_DER_PREFIX,
1064676Sizick 		    SHA2_DER_PREFIX_Len);
1065676Sizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1066676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1067676Sizick 		break;
1068676Sizick 	case CKM_SHA512:
1069676Sizick 		(void) memcpy(der_data, SHA512_DER_PREFIX,
1070676Sizick 		    SHA2_DER_PREFIX_Len);
1071676Sizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1072676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1073676Sizick 		break;
10740Sstevel@tonic-gate 	}
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 	/*
10770Sstevel@tonic-gate 	 * Now, we are ready to sign the DER_ENCODED data
10780Sstevel@tonic-gate 	 * soft_rsa_sign_common() will free the signature key.
10790Sstevel@tonic-gate 	 */
10800Sstevel@tonic-gate 	rv = soft_rsa_sign_common(session_p, der_data, der_data_len,
10810Sstevel@tonic-gate 	    pSigned, pulSignedLen, mechanism);
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate clean_exit:
10840Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
10850Sstevel@tonic-gate 	/* soft_digest_common() has freed the digest context */
10860Sstevel@tonic-gate 	session_p->digest.flags = 0;
10870Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate clean1:
10900Sstevel@tonic-gate 	return (rv);
10910Sstevel@tonic-gate }
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 
10940Sstevel@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)10950Sstevel@tonic-gate soft_rsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
10960Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned,
10970Sstevel@tonic-gate     CK_ULONG ulSignedLen, CK_MECHANISM_TYPE mechanism, boolean_t Final)
10980Sstevel@tonic-gate {
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1101676Sizick 	CK_BYTE hash[SHA512_DIGEST_LENGTH];  /* space for all mechs */
1102676Sizick 	CK_ULONG hash_len = SHA512_DIGEST_LENGTH;
1103676Sizick 	CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
11040Sstevel@tonic-gate 	CK_ULONG der_data_len;
11050Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->verify.context;
11060Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
1107872Sizick 	CK_ULONG der_len;
1108872Sizick 	CK_BYTE_PTR der_prefix;
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	if (Final) {
11110Sstevel@tonic-gate 		rv = soft_digest_final(session_p, hash, &hash_len);
11120Sstevel@tonic-gate 	} else {
11130Sstevel@tonic-gate 		rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len);
11140Sstevel@tonic-gate 	}
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	if (rv != CKR_OK) {
11170Sstevel@tonic-gate 		/* free the verification key */
11180Sstevel@tonic-gate 		soft_cleanup_object(key);
11190Sstevel@tonic-gate 		free(key);
11200Sstevel@tonic-gate 		goto clean_exit;
11210Sstevel@tonic-gate 	}
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 	/*
11240Sstevel@tonic-gate 	 * Prepare the DER encoding of the DigestInfo value as follows:
11250Sstevel@tonic-gate 	 * MD5:		MD5_DER_PREFIX || H
11260Sstevel@tonic-gate 	 * SHA-1:	SHA1_DER_PREFIX || H
1127676Sizick 	 * SHA2:	SHA2_DER_PREFIX || H
11280Sstevel@tonic-gate 	 *
11290Sstevel@tonic-gate 	 * See rsa_impl.c for more details.
11300Sstevel@tonic-gate 	 */
1131676Sizick 	switch (session_p->digest.mech.mechanism) {
1132676Sizick 	case CKM_MD5:
11330Sstevel@tonic-gate 		(void) memcpy(der_data, MD5_DER_PREFIX, MD5_DER_PREFIX_Len);
11340Sstevel@tonic-gate 		(void) memcpy(der_data + MD5_DER_PREFIX_Len, hash, hash_len);
11350Sstevel@tonic-gate 		der_data_len = MD5_DER_PREFIX_Len + hash_len;
1136676Sizick 		break;
1137676Sizick 	case CKM_SHA_1:
1138872Sizick 		der_len = get_rsa_sha1_prefix(&(session_p->digest.mech),
1139872Sizick 		    &der_prefix);
1140872Sizick 		(void) memcpy(der_data, der_prefix, der_len);
1141872Sizick 		(void) memcpy(der_data + der_len, hash, hash_len);
1142872Sizick 		der_data_len = der_len + hash_len;
1143676Sizick 		break;
1144676Sizick 	case CKM_SHA256:
1145676Sizick 		(void) memcpy(der_data, SHA256_DER_PREFIX,
1146676Sizick 		    SHA2_DER_PREFIX_Len);
1147676Sizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1148676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1149676Sizick 		break;
1150676Sizick 	case CKM_SHA384:
1151676Sizick 		(void) memcpy(der_data, SHA384_DER_PREFIX,
1152676Sizick 		    SHA2_DER_PREFIX_Len);
1153676Sizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1154676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1155676Sizick 		break;
1156676Sizick 	case CKM_SHA512:
1157676Sizick 		(void) memcpy(der_data, SHA512_DER_PREFIX,
1158676Sizick 		    SHA2_DER_PREFIX_Len);
1159676Sizick 		(void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
1160676Sizick 		der_data_len = SHA2_DER_PREFIX_Len + hash_len;
1161676Sizick 		break;
11620Sstevel@tonic-gate 	}
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	/*
11650Sstevel@tonic-gate 	 * Now, we are ready to verify the DER_ENCODED data using signature.
11660Sstevel@tonic-gate 	 * soft_rsa_verify_common() will free the verification key.
11670Sstevel@tonic-gate 	 */
11680Sstevel@tonic-gate 	rv = soft_rsa_verify_common(session_p, der_data, der_data_len,
11690Sstevel@tonic-gate 	    pSigned, ulSignedLen, mechanism);
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate clean_exit:
11720Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
11730Sstevel@tonic-gate 	/* soft_digest_common() has freed the digest context */
11740Sstevel@tonic-gate 	session_p->digest.flags = 0;
11750Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
11760Sstevel@tonic-gate 
11770Sstevel@tonic-gate 	return (rv);
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate }
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate 
11820Sstevel@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)11830Sstevel@tonic-gate soft_rsa_verify_recover(soft_session_t *session_p, CK_BYTE_PTR pSignature,
11840Sstevel@tonic-gate     CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
11850Sstevel@tonic-gate {
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
11880Sstevel@tonic-gate 	soft_rsa_ctx_t *rsa_ctx = session_p->verify.context;
11890Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->verify.mech.mechanism;
11900Sstevel@tonic-gate 	soft_object_t *key = rsa_ctx->key;
11910Sstevel@tonic-gate 	uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
11920Sstevel@tonic-gate 	uint32_t modulus_len = sizeof (modulus);
11930Sstevel@tonic-gate 	CK_BYTE	plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
11940Sstevel@tonic-gate 
11957260Smcpowers 	rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len);
11960Sstevel@tonic-gate 	if (rv != CKR_OK) {
11970Sstevel@tonic-gate 		goto clean_exit;
11980Sstevel@tonic-gate 	}
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	if (ulSignatureLen != (CK_ULONG)modulus_len) {
12010Sstevel@tonic-gate 		rv = CKR_SIGNATURE_LEN_RANGE;
12020Sstevel@tonic-gate 		goto clean_exit;
12030Sstevel@tonic-gate 	}
12040Sstevel@tonic-gate 
12050Sstevel@tonic-gate 	/*
12060Sstevel@tonic-gate 	 * Perform RSA decryption with the signer's RSA public key
12070Sstevel@tonic-gate 	 * for verification process.
12080Sstevel@tonic-gate 	 */
12090Sstevel@tonic-gate 	rv = soft_rsa_encrypt(key, pSignature, modulus_len, plain_data, 1);
12100Sstevel@tonic-gate 	if (rv == CKR_OK) {
12110Sstevel@tonic-gate 		switch (mechanism) {
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 		case CKM_RSA_PKCS:
12140Sstevel@tonic-gate 		{
12150Sstevel@tonic-gate 			/*
12160Sstevel@tonic-gate 			 * Strip off the encoded padding bytes in front of the
12170Sstevel@tonic-gate 			 * recovered data.
12180Sstevel@tonic-gate 			 */
1219*12573SDina.Nimeh@Sun.COM 			size_t data_len = modulus_len;
12200Sstevel@tonic-gate 
1221*12573SDina.Nimeh@Sun.COM 			rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len);
12220Sstevel@tonic-gate 			if (rv != CKR_OK) {
12230Sstevel@tonic-gate 				goto clean_exit;
12240Sstevel@tonic-gate 			}
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate 			/*
12270Sstevel@tonic-gate 			 * If application asks for the length of the output
12280Sstevel@tonic-gate 			 * buffer?
12290Sstevel@tonic-gate 			 */
12300Sstevel@tonic-gate 			if (pData == NULL) {
12310Sstevel@tonic-gate 				*pulDataLen = data_len;
12320Sstevel@tonic-gate 				rv = CKR_OK;
12330Sstevel@tonic-gate 				goto clean1;
12340Sstevel@tonic-gate 			}
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 			/* Is the application-supplied buffer large enough? */
12370Sstevel@tonic-gate 			if (*pulDataLen < (CK_ULONG)data_len) {
12380Sstevel@tonic-gate 				*pulDataLen = data_len;
12390Sstevel@tonic-gate 				rv = CKR_BUFFER_TOO_SMALL;
12400Sstevel@tonic-gate 				goto clean1;
12410Sstevel@tonic-gate 			}
12420Sstevel@tonic-gate 
12430Sstevel@tonic-gate 			(void) memcpy(pData,
12440Sstevel@tonic-gate 			    &plain_data[modulus_len - data_len], data_len);
12450Sstevel@tonic-gate 			*pulDataLen = data_len;
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 			break;
12480Sstevel@tonic-gate 		}
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 		case CKM_RSA_X_509:
12510Sstevel@tonic-gate 			/*
12520Sstevel@tonic-gate 			 * If application asks for the length of the output
12530Sstevel@tonic-gate 			 * buffer?
12540Sstevel@tonic-gate 			 */
12550Sstevel@tonic-gate 			if (pData == NULL) {
12560Sstevel@tonic-gate 				*pulDataLen = modulus_len;
12570Sstevel@tonic-gate 				rv = CKR_OK;
12580Sstevel@tonic-gate 				goto clean1;
12590Sstevel@tonic-gate 			}
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 			/* Is the application-supplied buffer large enough? */
12620Sstevel@tonic-gate 			if (*pulDataLen < (CK_ULONG)modulus_len) {
12630Sstevel@tonic-gate 				*pulDataLen = modulus_len;
12640Sstevel@tonic-gate 				rv = CKR_BUFFER_TOO_SMALL;
12650Sstevel@tonic-gate 				goto clean1;
12660Sstevel@tonic-gate 			}
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 			(void) memcpy(pData, plain_data, modulus_len);
12690Sstevel@tonic-gate 			*pulDataLen = modulus_len;
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate 			break;
12720Sstevel@tonic-gate 		}
12730Sstevel@tonic-gate 	}
12740Sstevel@tonic-gate 
12750Sstevel@tonic-gate clean_exit:
12760Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
12770Sstevel@tonic-gate 	free(session_p->verify.context);
12780Sstevel@tonic-gate 	session_p->verify.context = NULL;
12790Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
12800Sstevel@tonic-gate 	soft_cleanup_object(key);
12810Sstevel@tonic-gate 	free(key);
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate clean1:
12840Sstevel@tonic-gate 	return (rv);
12850Sstevel@tonic-gate }
1286