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