xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelSign.c (revision 11304:3092d1e303d6)
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
52969Smcpowers  * Common Development and Distribution License (the "License").
62969Smcpowers  * 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  */
214072Skrishna 
220Sstevel@tonic-gate /*
239800SZdenek.Kotala@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <errno.h>
280Sstevel@tonic-gate #include <security/cryptoki.h>
290Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
300Sstevel@tonic-gate #include "kernelGlobal.h"
310Sstevel@tonic-gate #include "kernelObject.h"
320Sstevel@tonic-gate #include "kernelSession.h"
334072Skrishna #include "kernelEmulate.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate CK_RV
C_SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)360Sstevel@tonic-gate C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
370Sstevel@tonic-gate     CK_OBJECT_HANDLE hKey)
380Sstevel@tonic-gate {
390Sstevel@tonic-gate 	CK_RV rv;
400Sstevel@tonic-gate 	kernel_session_t *session_p;
410Sstevel@tonic-gate 	kernel_object_t *key_p;
420Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
430Sstevel@tonic-gate 	crypto_sign_init_t sign_init;
440Sstevel@tonic-gate 	crypto_mech_type_t k_mech_type;
450Sstevel@tonic-gate 	int r;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 	if (!kernel_initialized)
480Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	if (pMechanism == NULL) {
510Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
520Sstevel@tonic-gate 	}
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	/* Get the kernel's internal mechanism number. */
550Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
560Sstevel@tonic-gate 	if (rv != CKR_OK) {
570Sstevel@tonic-gate 		return (rv);
580Sstevel@tonic-gate 	}
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	/* Obtain the session pointer. */
610Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
620Sstevel@tonic-gate 	if (rv != CKR_OK)
630Sstevel@tonic-gate 		return (rv);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 	/* Obtain the object pointer. */
660Sstevel@tonic-gate 	HANDLE2OBJECT(hKey, key_p, rv);
670Sstevel@tonic-gate 	if (rv != CKR_OK) {
68214Smcpowers 		REFRELE(session_p, ses_lock_held);
69214Smcpowers 		return (rv);
700Sstevel@tonic-gate 	}
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	/* Check to see if key object supports signature. */
730Sstevel@tonic-gate 	if (key_p->is_lib_obj && !(key_p->bool_attr_mask & SIGN_BOOL_ON)) {
740Sstevel@tonic-gate 		rv = CKR_KEY_TYPE_INCONSISTENT;
750Sstevel@tonic-gate 		goto clean_exit;
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
790Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	/*
820Sstevel@tonic-gate 	 * This active flag will remain ON until application calls either
830Sstevel@tonic-gate 	 * C_Sign or C_SignFinal to actually obtain the signature.
840Sstevel@tonic-gate 	 */
850Sstevel@tonic-gate 	session_p->sign.flags = CRYPTO_OPERATION_ACTIVE;
860Sstevel@tonic-gate 	sign_init.si_session = session_p->k_session;
870Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
880Sstevel@tonic-gate 	ses_lock_held = B_FALSE;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	if (!key_p->is_lib_obj) {
910Sstevel@tonic-gate 		sign_init.si_key.ck_format = CRYPTO_KEY_REFERENCE;
920Sstevel@tonic-gate 		sign_init.si_key.ck_obj_id = key_p->k_handle;
930Sstevel@tonic-gate 	} else {
940Sstevel@tonic-gate 		if (key_p->class == CKO_SECRET_KEY) {
950Sstevel@tonic-gate 			sign_init.si_key.ck_format = CRYPTO_KEY_RAW;
960Sstevel@tonic-gate 			sign_init.si_key.ck_data =
970Sstevel@tonic-gate 			    get_symmetric_key_value(key_p);
980Sstevel@tonic-gate 			if (sign_init.si_key.ck_data == NULL) {
990Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
1000Sstevel@tonic-gate 				goto clean_exit;
1010Sstevel@tonic-gate 			}
1020Sstevel@tonic-gate 			sign_init.si_key.ck_length =
1030Sstevel@tonic-gate 			    OBJ_SEC(key_p)->sk_value_len << 3;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 		} else if (key_p->key_type == CKK_RSA) {
1060Sstevel@tonic-gate 			rv = get_rsa_private_key(key_p, &sign_init.si_key);
1070Sstevel@tonic-gate 			if (rv != CKR_OK) {
1080Sstevel@tonic-gate 				goto clean_exit;
1090Sstevel@tonic-gate 			}
1100Sstevel@tonic-gate 		} else if (key_p->key_type == CKK_DSA) {
1110Sstevel@tonic-gate 			rv = get_dsa_private_key(key_p, &sign_init.si_key);
1120Sstevel@tonic-gate 			if (rv != CKR_OK) {
1130Sstevel@tonic-gate 				goto clean_exit;
1140Sstevel@tonic-gate 			}
1154219Smcpowers 		} else if (key_p->key_type == CKK_EC) {
1164219Smcpowers 			rv = get_ec_private_key(key_p, &sign_init.si_key);
1174219Smcpowers 			if (rv != CKR_OK) {
1184219Smcpowers 				goto clean_exit;
1194219Smcpowers 			}
1200Sstevel@tonic-gate 		} else {
1210Sstevel@tonic-gate 			rv = CKR_KEY_TYPE_INCONSISTENT;
1220Sstevel@tonic-gate 			goto clean_exit;
1230Sstevel@tonic-gate 		}
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	sign_init.si_mech.cm_type = k_mech_type;
1270Sstevel@tonic-gate 	sign_init.si_mech.cm_param = pMechanism->pParameter;
1280Sstevel@tonic-gate 	sign_init.si_mech.cm_param_len = pMechanism->ulParameterLen;
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_INIT, &sign_init)) < 0) {
1310Sstevel@tonic-gate 		if (errno != EINTR)
1320Sstevel@tonic-gate 			break;
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 	if (r < 0) {
1350Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
1360Sstevel@tonic-gate 	} else {
1370Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(sign_init.si_return_value);
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
140*11304SJanie.Lu@Sun.COM 	if (rv == CKR_OK && SLOT_HAS_LIMITED_HMAC(session_p) &&
1414072Skrishna 	    is_hmac(pMechanism->mechanism)) {
1424072Skrishna 		if (key_p->is_lib_obj && key_p->class == CKO_SECRET_KEY) {
1434072Skrishna 			(void) pthread_mutex_lock(&session_p->session_mutex);
1444072Skrishna 			session_p->sign.flags |= CRYPTO_EMULATE;
1454072Skrishna 			(void) pthread_mutex_unlock(&session_p->session_mutex);
1464072Skrishna 			rv = emulate_init(session_p, pMechanism,
1474072Skrishna 			    &(sign_init.si_key), OP_SIGN);
1484072Skrishna 		} else {
1494072Skrishna 			rv = CKR_ARGUMENTS_BAD;
1504072Skrishna 		}
1514072Skrishna 	}
1524072Skrishna 
1530Sstevel@tonic-gate 	if (key_p->is_lib_obj) {
1540Sstevel@tonic-gate 		if (key_p->class == CKO_SECRET_KEY) {
1550Sstevel@tonic-gate 			free(sign_init.si_key.ck_data);
1562969Smcpowers 		} else {
1570Sstevel@tonic-gate 			free_key_attributes(&sign_init.si_key);
1580Sstevel@tonic-gate 		}
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	if (rv != CKR_OK) {
1620Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
1630Sstevel@tonic-gate 		session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
1640Sstevel@tonic-gate 		ses_lock_held = B_TRUE;
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate clean_exit:
168214Smcpowers 	OBJ_REFRELE(key_p);
1690Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
1700Sstevel@tonic-gate 	return (rv);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate CK_RV
C_Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)1750Sstevel@tonic-gate C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
1760Sstevel@tonic-gate     CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
1770Sstevel@tonic-gate {
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	CK_RV rv;
1800Sstevel@tonic-gate 	kernel_session_t *session_p;
1810Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
1820Sstevel@tonic-gate 	crypto_sign_t sign;
1830Sstevel@tonic-gate 	int r;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	if (!kernel_initialized)
1860Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	/* Obtain the session pointer */
1890Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
1900Sstevel@tonic-gate 	if (rv != CKR_OK)
1910Sstevel@tonic-gate 		return (rv);
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	if (pulSignatureLen == NULL) {
1940Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
1950Sstevel@tonic-gate 		goto clean_exit;
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
1990Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	/* Application must call C_SignInit before calling C_Sign. */
2020Sstevel@tonic-gate 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
2030Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
2040Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/*
2080Sstevel@tonic-gate 	 * C_Sign must be called without intervening C_SignUpdate
2090Sstevel@tonic-gate 	 * calls.
2100Sstevel@tonic-gate 	 */
2110Sstevel@tonic-gate 	if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) {
2120Sstevel@tonic-gate 		/*
2130Sstevel@tonic-gate 		 * C_Sign can not be used to terminate a multi-part
2140Sstevel@tonic-gate 		 * operation, so we'll leave the active sign operation
2150Sstevel@tonic-gate 		 * flag on and let the application continue with the
2160Sstevel@tonic-gate 		 * sign update operation.
2170Sstevel@tonic-gate 		 */
2180Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
2190Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2224072Skrishna 	if (session_p->sign.flags & CRYPTO_EMULATE) {
2234072Skrishna 		if ((ulDataLen < SLOT_THRESHOLD(session_p)) ||
224*11304SJanie.Lu@Sun.COM 		    (ulDataLen > SLOT_HMAC_MAX_INDATA_LEN(session_p))) {
2254072Skrishna 			session_p->sign.flags |= CRYPTO_EMULATE_USING_SW;
2264072Skrishna 			(void) pthread_mutex_unlock(&session_p->session_mutex);
2279800SZdenek.Kotala@Sun.COM 			ses_lock_held = B_FALSE;
2284072Skrishna 
2294072Skrishna 			rv = do_soft_hmac_sign(get_spp(&session_p->sign),
2304072Skrishna 			    pData, ulDataLen,
2314072Skrishna 			    pSignature, pulSignatureLen, OP_SINGLE);
2324072Skrishna 			goto done;
2334072Skrishna 		} else {
2344072Skrishna 			free_soft_ctx(get_sp(&session_p->sign), OP_SIGN);
2354072Skrishna 		}
2364072Skrishna 	}
2374072Skrishna 
2380Sstevel@tonic-gate 	sign.cs_session = session_p->k_session;
2390Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
2400Sstevel@tonic-gate 	ses_lock_held = B_FALSE;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	sign.cs_datalen = ulDataLen;
2430Sstevel@tonic-gate 	sign.cs_databuf = (char *)pData;
2440Sstevel@tonic-gate 	sign.cs_signlen = *pulSignatureLen;
2450Sstevel@tonic-gate 	sign.cs_signbuf = (char *)pSignature;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN, &sign)) < 0) {
2480Sstevel@tonic-gate 		if (errno != EINTR)
2490Sstevel@tonic-gate 			break;
2500Sstevel@tonic-gate 	}
2510Sstevel@tonic-gate 	if (r < 0) {
2520Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
2530Sstevel@tonic-gate 	} else {
2540Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(sign.cs_return_value);
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
2580Sstevel@tonic-gate 		*pulSignatureLen = sign.cs_signlen;
2590Sstevel@tonic-gate 
2604072Skrishna done:
2610Sstevel@tonic-gate 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
2620Sstevel@tonic-gate 	    (rv == CKR_OK && pSignature == NULL)) {
2630Sstevel@tonic-gate 		/*
2640Sstevel@tonic-gate 		 * We will not terminate the active sign operation flag,
2650Sstevel@tonic-gate 		 * when the application-supplied buffer is too small, or
2660Sstevel@tonic-gate 		 * the application asks for the length of buffer to hold
2670Sstevel@tonic-gate 		 * the signature.
2680Sstevel@tonic-gate 		 */
2690Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
2700Sstevel@tonic-gate 		return (rv);
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate clean_exit:
2740Sstevel@tonic-gate 	/*
2750Sstevel@tonic-gate 	 * Terminates the active sign operation.
2760Sstevel@tonic-gate 	 * Application needs to call C_SignInit again for next
2770Sstevel@tonic-gate 	 * sign operation.
2780Sstevel@tonic-gate 	 */
2790Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
2809800SZdenek.Kotala@Sun.COM 	ses_lock_held = B_TRUE;
2814072Skrishna 
2824072Skrishna 	REINIT_OPBUF(&session_p->sign);
2830Sstevel@tonic-gate 	session_p->sign.flags = 0;
2840Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	return (rv);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate CK_RV
C_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)2910Sstevel@tonic-gate C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2920Sstevel@tonic-gate     CK_ULONG ulPartLen)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	CK_RV rv;
2960Sstevel@tonic-gate 	kernel_session_t *session_p;
2970Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
2980Sstevel@tonic-gate 	crypto_sign_update_t sign_update;
2990Sstevel@tonic-gate 	int r;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	if (!kernel_initialized)
3020Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	/* Obtain the session pointer */
3050Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
3060Sstevel@tonic-gate 	if (rv != CKR_OK)
3070Sstevel@tonic-gate 		return (rv);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if (pPart == NULL) {
3100Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
3110Sstevel@tonic-gate 		goto clean_exit;
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
3150Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	/*
3180Sstevel@tonic-gate 	 * Application must call C_SignInit before calling
3190Sstevel@tonic-gate 	 * C_SignUpdate.
3200Sstevel@tonic-gate 	 */
3210Sstevel@tonic-gate 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
3220Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
3230Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	session_p->sign.flags |= CRYPTO_OPERATION_UPDATE;
3270Sstevel@tonic-gate 
3284072Skrishna 	if (session_p->sign.flags & CRYPTO_EMULATE) {
3294072Skrishna 		(void) pthread_mutex_unlock(&session_p->session_mutex);
3309800SZdenek.Kotala@Sun.COM 		ses_lock_held = B_FALSE;
3314072Skrishna 		rv = emulate_update(session_p, pPart, ulPartLen, OP_SIGN);
3324072Skrishna 		goto done;
3334072Skrishna 	}
3344072Skrishna 
3350Sstevel@tonic-gate 	sign_update.su_session = session_p->k_session;
3360Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
3370Sstevel@tonic-gate 	ses_lock_held = B_FALSE;
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	sign_update.su_datalen = ulPartLen;
3400Sstevel@tonic-gate 	sign_update.su_databuf = (char *)pPart;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_UPDATE, &sign_update)) < 0) {
3430Sstevel@tonic-gate 		if (errno != EINTR)
3440Sstevel@tonic-gate 			break;
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 	if (r < 0) {
3470Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
3480Sstevel@tonic-gate 	} else {
3490Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(sign_update.su_return_value);
3500Sstevel@tonic-gate 	}
3510Sstevel@tonic-gate 
3524072Skrishna done:
3530Sstevel@tonic-gate 	if (rv == CKR_OK) {
3540Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
3550Sstevel@tonic-gate 		return (rv);
3560Sstevel@tonic-gate 	}
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate clean_exit:
3590Sstevel@tonic-gate 	/*
3600Sstevel@tonic-gate 	 * After an error occurred, terminate the current sign
3610Sstevel@tonic-gate 	 * operation by resetting the active and update flags.
3620Sstevel@tonic-gate 	 */
3630Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
3649800SZdenek.Kotala@Sun.COM 	ses_lock_held = B_TRUE;
3654072Skrishna 	REINIT_OPBUF(&session_p->sign);
3660Sstevel@tonic-gate 	session_p->sign.flags = 0;
3670Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	return (rv);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate CK_RV
C_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)3740Sstevel@tonic-gate C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
3750Sstevel@tonic-gate     CK_ULONG_PTR pulSignatureLen)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	CK_RV rv;
3790Sstevel@tonic-gate 	kernel_session_t *session_p;
3800Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
3810Sstevel@tonic-gate 	crypto_sign_final_t sign_final;
3820Sstevel@tonic-gate 	int r;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	if (!kernel_initialized)
3850Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	/* Obtain the session pointer */
3880Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
3890Sstevel@tonic-gate 	if (rv != CKR_OK)
3900Sstevel@tonic-gate 		return (rv);
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	if (pulSignatureLen == NULL) {
3930Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
3940Sstevel@tonic-gate 		goto clean_exit;
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
3980Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/*
4010Sstevel@tonic-gate 	 * Application must call C_SignInit before calling
4020Sstevel@tonic-gate 	 * C_SignFinal.
4030Sstevel@tonic-gate 	 */
4040Sstevel@tonic-gate 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
4050Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
4060Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
4070Sstevel@tonic-gate 	}
4080Sstevel@tonic-gate 
4094072Skrishna 	/* The order of checks is important here */
4104072Skrishna 	if (session_p->sign.flags & CRYPTO_EMULATE_USING_SW) {
4114072Skrishna 		if (session_p->sign.flags & CRYPTO_EMULATE_UPDATE_DONE) {
4124072Skrishna 			(void) pthread_mutex_unlock(&session_p->session_mutex);
4139800SZdenek.Kotala@Sun.COM 			ses_lock_held = B_FALSE;
4144072Skrishna 			rv = do_soft_hmac_sign(get_spp(&session_p->sign),
4154072Skrishna 			    NULL, 0, pSignature, pulSignatureLen, OP_FINAL);
4164072Skrishna 		} else {
4174072Skrishna 			/*
4184072Skrishna 			 * We end up here if an earlier C_SignFinal() call
4194072Skrishna 			 * took the C_Sign() path and it had returned
4204072Skrishna 			 * CKR_BUFFER_TOO_SMALL.
4214072Skrishna 			 */
4224072Skrishna 			digest_buf_t *bufp = session_p->sign.context;
4234072Skrishna 			(void) pthread_mutex_unlock(&session_p->session_mutex);
4249800SZdenek.Kotala@Sun.COM 			ses_lock_held = B_FALSE;
4254072Skrishna 			if (bufp == NULL || bufp->buf == NULL) {
4264072Skrishna 				rv = CKR_ARGUMENTS_BAD;
4274072Skrishna 				goto clean_exit;
4284072Skrishna 			}
4294072Skrishna 			rv = do_soft_hmac_sign(get_spp(&session_p->sign),
4304072Skrishna 			    bufp->buf, bufp->indata_len,
4314072Skrishna 			    pSignature, pulSignatureLen, OP_SINGLE);
4324072Skrishna 		}
4334072Skrishna 		goto done;
4344072Skrishna 	} else if (session_p->sign.flags & CRYPTO_EMULATE) {
4354072Skrishna 		digest_buf_t *bufp = session_p->sign.context;
4364072Skrishna 
4374072Skrishna 		/*
4384072Skrishna 		 * We are emulating a single-part operation now.
4394072Skrishna 		 * So, clear the flag.
4404072Skrishna 		 */
4414072Skrishna 		session_p->sign.flags &= ~CRYPTO_OPERATION_UPDATE;
4424072Skrishna 		if (bufp == NULL || bufp->buf == NULL) {
4434072Skrishna 			rv = CKR_ARGUMENTS_BAD;
4444072Skrishna 			goto clean_exit;
4454072Skrishna 		}
4464072Skrishna 		REFRELE(session_p, ses_lock_held);
4474072Skrishna 		rv = C_Sign(hSession, bufp->buf, bufp->indata_len,
4484072Skrishna 		    pSignature, pulSignatureLen);
4494072Skrishna 		return (rv);
4504072Skrishna 	}
4514072Skrishna 
4520Sstevel@tonic-gate 	sign_final.sf_session = session_p->k_session;
4530Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
4540Sstevel@tonic-gate 	ses_lock_held = B_FALSE;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	sign_final.sf_signlen = *pulSignatureLen;
4570Sstevel@tonic-gate 	sign_final.sf_signbuf = (char *)pSignature;
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_FINAL, &sign_final)) < 0) {
4600Sstevel@tonic-gate 		if (errno != EINTR)
4610Sstevel@tonic-gate 			break;
4620Sstevel@tonic-gate 	}
4630Sstevel@tonic-gate 	if (r < 0) {
4640Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
4650Sstevel@tonic-gate 	} else {
4660Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(sign_final.sf_return_value);
4670Sstevel@tonic-gate 	}
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
4700Sstevel@tonic-gate 		*pulSignatureLen = sign_final.sf_signlen;
4710Sstevel@tonic-gate 
4724072Skrishna done:
4730Sstevel@tonic-gate 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
4740Sstevel@tonic-gate 	    (rv == CKR_OK && pSignature == NULL)) {
4750Sstevel@tonic-gate 		/*
4760Sstevel@tonic-gate 		 * We will not terminate the active sign operation flag,
4770Sstevel@tonic-gate 		 * when the application-supplied buffer is too small, or
4780Sstevel@tonic-gate 		 * the application asks for the length of buffer to hold
4790Sstevel@tonic-gate 		 * the signature.
4800Sstevel@tonic-gate 		 */
4810Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
4820Sstevel@tonic-gate 		return (rv);
4830Sstevel@tonic-gate 	}
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate clean_exit:
4860Sstevel@tonic-gate 	/* Terminates the active sign operation */
4870Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
4889800SZdenek.Kotala@Sun.COM 	ses_lock_held = B_TRUE;
4894072Skrishna 	REINIT_OPBUF(&session_p->sign);
4900Sstevel@tonic-gate 	session_p->sign.flags = 0;
4910Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	return (rv);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate CK_RV
C_SignRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)4980Sstevel@tonic-gate C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4990Sstevel@tonic-gate     CK_OBJECT_HANDLE hKey)
5000Sstevel@tonic-gate {
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	CK_RV rv;
5030Sstevel@tonic-gate 	kernel_session_t *session_p;
5040Sstevel@tonic-gate 	kernel_object_t *key_p;
5050Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
5060Sstevel@tonic-gate 	crypto_sign_recover_init_t sr_init;
5070Sstevel@tonic-gate 	crypto_mech_type_t k_mech_type;
5080Sstevel@tonic-gate 	int r;
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	if (!kernel_initialized)
5110Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	if (pMechanism == NULL) {
5140Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	/* Get the kernel's internal mechanism number. */
5180Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
5190Sstevel@tonic-gate 	if (rv != CKR_OK)
5200Sstevel@tonic-gate 		return (rv);
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	/* Obtain the session pointer. */
5230Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
5240Sstevel@tonic-gate 	if (rv != CKR_OK)
5250Sstevel@tonic-gate 		return (rv);
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	/* Obtain the object pointer. */
5280Sstevel@tonic-gate 	HANDLE2OBJECT(hKey, key_p, rv);
5290Sstevel@tonic-gate 	if (rv != CKR_OK) {
530214Smcpowers 		REFRELE(session_p, ses_lock_held);
531214Smcpowers 		return (rv);
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	/*
5350Sstevel@tonic-gate 	 * Check to see if key object is a RSA key and if it supports
5360Sstevel@tonic-gate 	 * sign_recover.
5370Sstevel@tonic-gate 	 */
5380Sstevel@tonic-gate 	if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) &&
5390Sstevel@tonic-gate 	    (key_p->bool_attr_mask & SIGN_RECOVER_BOOL_ON))) {
5400Sstevel@tonic-gate 		rv = CKR_KEY_TYPE_INCONSISTENT;
5410Sstevel@tonic-gate 		goto clean_exit;
5420Sstevel@tonic-gate 	}
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5450Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	/*
5480Sstevel@tonic-gate 	 * This active flag will remain ON until application calls
5490Sstevel@tonic-gate 	 * C_SignRecover to actually obtain the signature.
5500Sstevel@tonic-gate 	 */
5510Sstevel@tonic-gate 	session_p->sign.flags = CRYPTO_OPERATION_ACTIVE;
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	/* Set up the key data */
5540Sstevel@tonic-gate 	if (!key_p->is_lib_obj) {
5550Sstevel@tonic-gate 		sr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE;
5560Sstevel@tonic-gate 		sr_init.ri_key.ck_obj_id = key_p->k_handle;
5570Sstevel@tonic-gate 	} else {
5580Sstevel@tonic-gate 		if (key_p->key_type == CKK_RSA) {
5590Sstevel@tonic-gate 			if (get_rsa_private_key(key_p, &sr_init.ri_key) !=
5600Sstevel@tonic-gate 			    CKR_OK) {
5610Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
5620Sstevel@tonic-gate 				goto clean_exit;
5630Sstevel@tonic-gate 			}
5640Sstevel@tonic-gate 		} else {
5650Sstevel@tonic-gate 			rv = CKR_KEY_TYPE_INCONSISTENT;
5660Sstevel@tonic-gate 			goto clean_exit;
5670Sstevel@tonic-gate 		}
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	sr_init.ri_session = session_p->k_session;
5710Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
5720Sstevel@tonic-gate 	ses_lock_held = B_FALSE;
5730Sstevel@tonic-gate 	sr_init.ri_mech.cm_type = k_mech_type;
5740Sstevel@tonic-gate 	sr_init.ri_mech.cm_param = pMechanism->pParameter;
5750Sstevel@tonic-gate 	sr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen;
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER_INIT, &sr_init)) < 0) {
5780Sstevel@tonic-gate 		if (errno != EINTR)
5790Sstevel@tonic-gate 			break;
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 	if (r < 0) {
5820Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
5830Sstevel@tonic-gate 	} else {
5840Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(sr_init.ri_return_value);
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	if (key_p->is_lib_obj) {
5880Sstevel@tonic-gate 		free_key_attributes(&sr_init.ri_key);
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	if (rv != CKR_OK) {
5920Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
5930Sstevel@tonic-gate 		session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
5940Sstevel@tonic-gate 		ses_lock_held = B_TRUE;
5950Sstevel@tonic-gate 	}
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate clean_exit:
598214Smcpowers 	OBJ_REFRELE(key_p);
5990Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
6000Sstevel@tonic-gate 	return (rv);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate CK_RV
C_SignRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)6050Sstevel@tonic-gate C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
6060Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
6070Sstevel@tonic-gate {
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	CK_RV rv;
6100Sstevel@tonic-gate 	kernel_session_t *session_p;
6110Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
6120Sstevel@tonic-gate 	crypto_sign_recover_t sign_recover;
6130Sstevel@tonic-gate 	int r;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	if (!kernel_initialized)
6160Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	/* Obatin the session pointer */
6190Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
6200Sstevel@tonic-gate 	if (rv != CKR_OK)
6210Sstevel@tonic-gate 		return (rv);
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	if (pulSignatureLen == NULL) {
6240Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
6250Sstevel@tonic-gate 		goto clean_exit;
6260Sstevel@tonic-gate 	}
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
6290Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	/* Application must call C_SignInit before calling C_Sign. */
6320Sstevel@tonic-gate 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
6330Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
6340Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
6350Sstevel@tonic-gate 	}
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	sign_recover.sr_session = session_p->k_session;
6380Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
6390Sstevel@tonic-gate 	ses_lock_held = B_FALSE;
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	sign_recover.sr_datalen = ulDataLen;
6420Sstevel@tonic-gate 	sign_recover.sr_databuf = (char *)pData;
6430Sstevel@tonic-gate 	sign_recover.sr_signlen = *pulSignatureLen;
6440Sstevel@tonic-gate 	sign_recover.sr_signbuf = (char *)pSignature;
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER, &sign_recover)) < 0) {
6470Sstevel@tonic-gate 		if (errno != EINTR)
6480Sstevel@tonic-gate 			break;
6490Sstevel@tonic-gate 	}
6500Sstevel@tonic-gate 	if (r < 0) {
6510Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
6520Sstevel@tonic-gate 	} else {
6530Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(sign_recover.sr_return_value);
6540Sstevel@tonic-gate 	}
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
6570Sstevel@tonic-gate 		*pulSignatureLen = sign_recover.sr_signlen;
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
6600Sstevel@tonic-gate 	    (rv == CKR_OK && pSignature == NULL)) {
6610Sstevel@tonic-gate 		/*
6620Sstevel@tonic-gate 		 * We will not terminate the active sign operation flag,
6630Sstevel@tonic-gate 		 * when the application-supplied buffer is too small, or
6640Sstevel@tonic-gate 		 * the application asks for the length of buffer to hold
6650Sstevel@tonic-gate 		 * the signature.
6660Sstevel@tonic-gate 		 */
6670Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
6680Sstevel@tonic-gate 		return (rv);
6690Sstevel@tonic-gate 	}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate clean_exit:
6720Sstevel@tonic-gate 	/*
6730Sstevel@tonic-gate 	 * Terminates the active sign operation.
6740Sstevel@tonic-gate 	 * Application needs to call C_SignInit again for next
6750Sstevel@tonic-gate 	 * sign operation.
6760Sstevel@tonic-gate 	 */
6770Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
6789800SZdenek.Kotala@Sun.COM 	ses_lock_held = B_TRUE;
6790Sstevel@tonic-gate 	session_p->sign.flags = 0;
6800Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	return (rv);
6830Sstevel@tonic-gate }
684