17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53caafd89Smcpowers * Common Development and Distribution License (the "License"). 63caafd89Smcpowers * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21ba5f469cSkrishna 227c478bd9Sstevel@tonic-gate /* 23b232b5fcSZdenek Kotala * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdlib.h> 287c478bd9Sstevel@tonic-gate #include <errno.h> 297c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 307c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 317c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 327c478bd9Sstevel@tonic-gate #include "kernelObject.h" 337c478bd9Sstevel@tonic-gate #include "kernelSession.h" 34ba5f469cSkrishna #include "kernelEmulate.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate CK_RV 377c478bd9Sstevel@tonic-gate C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 387c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hKey) 397c478bd9Sstevel@tonic-gate { 407c478bd9Sstevel@tonic-gate CK_RV rv; 417c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 427c478bd9Sstevel@tonic-gate kernel_object_t *key_p; 437c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 447c478bd9Sstevel@tonic-gate crypto_verify_init_t verify_init; 457c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 467c478bd9Sstevel@tonic-gate int r; 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate if (!kernel_initialized) 497c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate if (pMechanism == NULL) { 527c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 537c478bd9Sstevel@tonic-gate } 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 567c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 577c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 587c478bd9Sstevel@tonic-gate return (rv); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 617c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 627c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 637c478bd9Sstevel@tonic-gate return (rv); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 667c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv); 677c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6801223cbaSmcpowers REFRELE(session_p, ses_lock_held); 6901223cbaSmcpowers return (rv); 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* Check to see if key object supports verification. */ 737c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj && !(key_p->bool_attr_mask & VERIFY_BOOL_ON)) { 747c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 757c478bd9Sstevel@tonic-gate goto clean_exit; 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 797c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * This active flag will remain ON until application calls either 837c478bd9Sstevel@tonic-gate * C_Verify or C_VerifyFinal to verify a signature on data. 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate session_p->verify.flags = CRYPTO_OPERATION_ACTIVE; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if (!key_p->is_lib_obj) { 887c478bd9Sstevel@tonic-gate verify_init.vi_key.ck_format = CRYPTO_KEY_REFERENCE; 897c478bd9Sstevel@tonic-gate verify_init.vi_key.ck_obj_id = key_p->k_handle; 907c478bd9Sstevel@tonic-gate } else { 917c478bd9Sstevel@tonic-gate if (key_p->class == CKO_SECRET_KEY) { 927c478bd9Sstevel@tonic-gate verify_init.vi_key.ck_format = CRYPTO_KEY_RAW; 937c478bd9Sstevel@tonic-gate verify_init.vi_key.ck_data = 947c478bd9Sstevel@tonic-gate get_symmetric_key_value(key_p); 957c478bd9Sstevel@tonic-gate if (verify_init.vi_key.ck_data == NULL) { 967c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 977c478bd9Sstevel@tonic-gate goto clean_exit; 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate verify_init.vi_key.ck_length = 1007c478bd9Sstevel@tonic-gate OBJ_SEC(key_p)->sk_value_len << 3; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate } else if (key_p->key_type == CKK_RSA) { 1037c478bd9Sstevel@tonic-gate if (get_rsa_public_key(key_p, &verify_init.vi_key) != 1047c478bd9Sstevel@tonic-gate CKR_OK) { 1057c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 1067c478bd9Sstevel@tonic-gate goto clean_exit; 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate } else if (key_p->key_type == CKK_DSA) { 1097c478bd9Sstevel@tonic-gate if (get_dsa_public_key(key_p, &verify_init.vi_key) != 1107c478bd9Sstevel@tonic-gate CKR_OK) { 1117c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 1127c478bd9Sstevel@tonic-gate goto clean_exit; 1137c478bd9Sstevel@tonic-gate } 114034448feSmcpowers } else if (key_p->key_type == CKK_EC) { 115034448feSmcpowers if (get_ec_public_key(key_p, &verify_init.vi_key) != 116034448feSmcpowers CKR_OK) { 117034448feSmcpowers rv = CKR_HOST_MEMORY; 118034448feSmcpowers goto clean_exit; 119034448feSmcpowers } 1207c478bd9Sstevel@tonic-gate } else { 1217c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 1227c478bd9Sstevel@tonic-gate goto clean_exit; 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate verify_init.vi_session = session_p->k_session; 1277c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 1287c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 1297c478bd9Sstevel@tonic-gate verify_init.vi_mech.cm_type = k_mech_type; 1307c478bd9Sstevel@tonic-gate verify_init.vi_mech.cm_param = pMechanism->pParameter; 1317c478bd9Sstevel@tonic-gate verify_init.vi_mech.cm_param_len = pMechanism->ulParameterLen; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_INIT, &verify_init)) < 0) { 1347c478bd9Sstevel@tonic-gate if (errno != EINTR) 1357c478bd9Sstevel@tonic-gate break; 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate if (r < 0) { 1387c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 1397c478bd9Sstevel@tonic-gate } else { 1407c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(verify_init.vi_return_value); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 143*4df55fdeSJanie Lu if (rv == CKR_OK && SLOT_HAS_LIMITED_HMAC(session_p) && 144ba5f469cSkrishna is_hmac(pMechanism->mechanism)) { 145ba5f469cSkrishna if (key_p->is_lib_obj && key_p->class == CKO_SECRET_KEY) { 146ba5f469cSkrishna (void) pthread_mutex_lock(&session_p->session_mutex); 147ba5f469cSkrishna session_p->verify.flags |= CRYPTO_EMULATE; 148ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex); 149ba5f469cSkrishna rv = emulate_init(session_p, pMechanism, 150ba5f469cSkrishna &(verify_init.vi_key), OP_VERIFY); 151ba5f469cSkrishna } else { 152ba5f469cSkrishna rv = CKR_FUNCTION_FAILED; 153ba5f469cSkrishna } 154ba5f469cSkrishna } 155ba5f469cSkrishna 1563caafd89Smcpowers /* free the memory allocated for verify_init.vi_key */ 1577c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj) { 1587c478bd9Sstevel@tonic-gate if (key_p->class == CKO_SECRET_KEY) { 1597c478bd9Sstevel@tonic-gate free(verify_init.vi_key.ck_data); 1603caafd89Smcpowers } else { 1617c478bd9Sstevel@tonic-gate free_key_attributes(&verify_init.vi_key); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1667c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 1677c478bd9Sstevel@tonic-gate session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE; 1687c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate clean_exit: 17201223cbaSmcpowers OBJ_REFRELE(key_p); 1737c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1747c478bd9Sstevel@tonic-gate return (rv); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate CK_RV 1797c478bd9Sstevel@tonic-gate C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 1807c478bd9Sstevel@tonic-gate CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate CK_RV rv; 1847c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 1857c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 1867c478bd9Sstevel@tonic-gate crypto_verify_t verify; 1877c478bd9Sstevel@tonic-gate int r; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (!kernel_initialized) 1907c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* Obatin the session pointer */ 1937c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 1947c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1957c478bd9Sstevel@tonic-gate return (rv); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 1987c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* Application must call C_VerifyInit before calling C_Verify. */ 2017c478bd9Sstevel@tonic-gate if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 2027c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2037c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* 2077c478bd9Sstevel@tonic-gate * C_Verify must be called without intervening C_VerifyUpdate 2087c478bd9Sstevel@tonic-gate * calls. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) { 2117c478bd9Sstevel@tonic-gate /* 2127c478bd9Sstevel@tonic-gate * C_Verify can not be used to terminate a multi-part 2137c478bd9Sstevel@tonic-gate * operation, so we'll leave the active verify operation 2147c478bd9Sstevel@tonic-gate * flag on and let the application continue with the 2157c478bd9Sstevel@tonic-gate * verify update operation. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2187c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 221ba5f469cSkrishna if (session_p->verify.flags & CRYPTO_EMULATE) { 222ba5f469cSkrishna if ((ulDataLen < SLOT_THRESHOLD(session_p)) || 223*4df55fdeSJanie Lu (ulDataLen > SLOT_HMAC_MAX_INDATA_LEN(session_p))) { 224ba5f469cSkrishna session_p->verify.flags |= CRYPTO_EMULATE_USING_SW; 225ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex); 226b232b5fcSZdenek Kotala ses_lock_held = B_FALSE; 227ba5f469cSkrishna 228ba5f469cSkrishna rv = do_soft_hmac_verify(get_spp(&session_p->verify), 229ba5f469cSkrishna pData, ulDataLen, 230ba5f469cSkrishna pSignature, ulSignatureLen, OP_SINGLE); 231ba5f469cSkrishna goto clean_exit; 232ba5f469cSkrishna } else { 233ba5f469cSkrishna free_soft_ctx(get_sp(&session_p->verify), OP_VERIFY); 234ba5f469cSkrishna } 235ba5f469cSkrishna } 236ba5f469cSkrishna 2377c478bd9Sstevel@tonic-gate verify.cv_session = session_p->k_session; 2387c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 2397c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 2407c478bd9Sstevel@tonic-gate verify.cv_datalen = ulDataLen; 2417c478bd9Sstevel@tonic-gate verify.cv_databuf = (char *)pData; 2427c478bd9Sstevel@tonic-gate verify.cv_signlen = ulSignatureLen; 2437c478bd9Sstevel@tonic-gate verify.cv_signbuf = (char *)pSignature; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_VERIFY, &verify)) < 0) { 2467c478bd9Sstevel@tonic-gate if (errno != EINTR) 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate if (r < 0) { 2507c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 2517c478bd9Sstevel@tonic-gate } else { 2527c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(verify.cv_return_value); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate clean_exit: 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Always terminate the active verify operation. 2587c478bd9Sstevel@tonic-gate * Application needs to call C_VerifyInit again for next 2597c478bd9Sstevel@tonic-gate * verify operation. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 262b232b5fcSZdenek Kotala ses_lock_held = B_TRUE; 263ba5f469cSkrishna 264ba5f469cSkrishna REINIT_OPBUF(&session_p->verify); 2657c478bd9Sstevel@tonic-gate session_p->verify.flags = 0; 2667c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate return (rv); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate CK_RV 2737c478bd9Sstevel@tonic-gate C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 2747c478bd9Sstevel@tonic-gate CK_ULONG ulPartLen) 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate CK_RV rv; 2787c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 2797c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 2807c478bd9Sstevel@tonic-gate crypto_verify_update_t verify_update; 2817c478bd9Sstevel@tonic-gate int r; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if (!kernel_initialized) 2847c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* Obtain the session pointer */ 2877c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 2887c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 2897c478bd9Sstevel@tonic-gate return (rv); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate if (pPart == NULL) { 2927c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 2937c478bd9Sstevel@tonic-gate goto clean_exit; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2977c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* 3007c478bd9Sstevel@tonic-gate * Application must call C_VerifyInit before calling 3017c478bd9Sstevel@tonic-gate * C_VerifyUpdate. 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 3047c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3057c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate session_p->verify.flags |= CRYPTO_OPERATION_UPDATE; 3097c478bd9Sstevel@tonic-gate 310ba5f469cSkrishna if (session_p->verify.flags & CRYPTO_EMULATE) { 311ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex); 312b232b5fcSZdenek Kotala ses_lock_held = B_FALSE; 313ba5f469cSkrishna rv = emulate_update(session_p, pPart, ulPartLen, OP_VERIFY); 314ba5f469cSkrishna goto done; 315ba5f469cSkrishna } 316ba5f469cSkrishna 3177c478bd9Sstevel@tonic-gate verify_update.vu_session = session_p->k_session; 3187c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 3197c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate verify_update.vu_datalen = ulPartLen; 3227c478bd9Sstevel@tonic-gate verify_update.vu_databuf = (char *)pPart; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_UPDATE, 3257c478bd9Sstevel@tonic-gate &verify_update)) < 0) { 3267c478bd9Sstevel@tonic-gate if (errno != EINTR) 3277c478bd9Sstevel@tonic-gate break; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate if (r < 0) { 3307c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 3317c478bd9Sstevel@tonic-gate } else { 3327c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(verify_update.vu_return_value); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 335ba5f469cSkrishna done: 3367c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 3377c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3387c478bd9Sstevel@tonic-gate return (rv); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate clean_exit: 3427c478bd9Sstevel@tonic-gate /* 3437c478bd9Sstevel@tonic-gate * After an error occurred, terminate the current verify 3447c478bd9Sstevel@tonic-gate * operation by resetting the active and update flags. 3457c478bd9Sstevel@tonic-gate */ 3467c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 347b232b5fcSZdenek Kotala ses_lock_held = B_TRUE; 348ba5f469cSkrishna REINIT_OPBUF(&session_p->verify); 3497c478bd9Sstevel@tonic-gate session_p->verify.flags = 0; 3507c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate return (rv); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate CK_RV 3577c478bd9Sstevel@tonic-gate C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 3587c478bd9Sstevel@tonic-gate CK_ULONG ulSignatureLen) 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate CK_RV rv; 3627c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 3637c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 3647c478bd9Sstevel@tonic-gate crypto_verify_final_t verify_final; 3657c478bd9Sstevel@tonic-gate int r; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (!kernel_initialized) 3687c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* Obtain the session pointer */ 3717c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 3727c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 3737c478bd9Sstevel@tonic-gate return (rv); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3767c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Application must call C_VerifyInit before calling 3807c478bd9Sstevel@tonic-gate * C_VerifyFinal. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 3837c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3847c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 387ba5f469cSkrishna /* The order of checks is important here */ 388ba5f469cSkrishna if (session_p->verify.flags & CRYPTO_EMULATE_USING_SW) { 389ba5f469cSkrishna if (session_p->verify.flags & CRYPTO_EMULATE_UPDATE_DONE) { 390ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex); 391b232b5fcSZdenek Kotala ses_lock_held = B_FALSE; 392ba5f469cSkrishna rv = do_soft_hmac_verify(get_spp(&session_p->verify), 393ba5f469cSkrishna NULL, 0, pSignature, ulSignatureLen, 394ba5f469cSkrishna OP_FINAL); 395ba5f469cSkrishna } else { 396ba5f469cSkrishna /* 397ba5f469cSkrishna * We should not end up here even if an earlier 398ba5f469cSkrishna * C_VerifyFinal() call took the C_Verify() path as 399ba5f469cSkrishna * it never returns CKR_BUFFER_TOO_SMALL. 400ba5f469cSkrishna */ 401b232b5fcSZdenek Kotala (void) pthread_mutex_unlock(&session_p->session_mutex); 402b232b5fcSZdenek Kotala ses_lock_held = B_FALSE; 403ba5f469cSkrishna rv = CKR_ARGUMENTS_BAD; 404ba5f469cSkrishna } 405ba5f469cSkrishna goto clean_exit; 406ba5f469cSkrishna } else if (session_p->verify.flags & CRYPTO_EMULATE) { 407ba5f469cSkrishna digest_buf_t *bufp = session_p->verify.context; 408ba5f469cSkrishna 409ba5f469cSkrishna /* 410ba5f469cSkrishna * We are emulating a single-part operation now. 411ba5f469cSkrishna * So, clear the flag. 412ba5f469cSkrishna */ 413ba5f469cSkrishna session_p->verify.flags &= ~CRYPTO_OPERATION_UPDATE; 414ba5f469cSkrishna if (bufp == NULL || bufp->buf == NULL) { 415ba5f469cSkrishna rv = CKR_ARGUMENTS_BAD; 416ba5f469cSkrishna goto clean_exit; 417ba5f469cSkrishna } 418ba5f469cSkrishna REFRELE(session_p, ses_lock_held); 419ba5f469cSkrishna rv = C_Verify(hSession, bufp->buf, bufp->indata_len, 420ba5f469cSkrishna pSignature, ulSignatureLen); 421ba5f469cSkrishna return (rv); 422ba5f469cSkrishna } 423ba5f469cSkrishna 4247c478bd9Sstevel@tonic-gate verify_final.vf_session = session_p->k_session; 4257c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 4267c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate verify_final.vf_signlen = ulSignatureLen; 4297c478bd9Sstevel@tonic-gate verify_final.vf_signbuf = (char *)pSignature; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_FINAL, &verify_final)) < 0) { 4327c478bd9Sstevel@tonic-gate if (errno != EINTR) 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate if (r < 0) { 4367c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 4377c478bd9Sstevel@tonic-gate } else { 4387c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(verify_final.vf_return_value); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate clean_exit: 4427c478bd9Sstevel@tonic-gate /* Always terminate the active verify operation */ 4437c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 444b232b5fcSZdenek Kotala ses_lock_held = B_TRUE; 445ba5f469cSkrishna REINIT_OPBUF(&session_p->verify); 4467c478bd9Sstevel@tonic-gate session_p->verify.flags = 0; 4477c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate return (rv); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate CK_RV 4547c478bd9Sstevel@tonic-gate C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 4557c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hKey) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate CK_RV rv; 4597c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 4607c478bd9Sstevel@tonic-gate kernel_object_t *key_p; 4617c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 4627c478bd9Sstevel@tonic-gate crypto_verify_recover_init_t vr_init; 4637c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 4647c478bd9Sstevel@tonic-gate int r; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (!kernel_initialized) 4677c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if (pMechanism == NULL) { 4707c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 4747c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 4757c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4767c478bd9Sstevel@tonic-gate return (rv); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 4797c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 4807c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4817c478bd9Sstevel@tonic-gate return (rv); 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 4847c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv); 4857c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 48601223cbaSmcpowers REFRELE(session_p, ses_lock_held); 48701223cbaSmcpowers return (rv); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * Check to see if key object is a RSA key and if it supports 4927c478bd9Sstevel@tonic-gate * verify_recover. 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) && 4957c478bd9Sstevel@tonic-gate (key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON))) { 4967c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 4977c478bd9Sstevel@tonic-gate goto clean_exit; 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 5017c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * This active flag will remain ON until application calls 5057c478bd9Sstevel@tonic-gate * C_VerifyRecover to verify a signature on data. 5067c478bd9Sstevel@tonic-gate */ 5077c478bd9Sstevel@tonic-gate session_p->verify.flags = CRYPTO_OPERATION_ACTIVE; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate /* Set up the key data */ 5107c478bd9Sstevel@tonic-gate if (!key_p->is_lib_obj) { 5117c478bd9Sstevel@tonic-gate vr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE; 5127c478bd9Sstevel@tonic-gate vr_init.ri_key.ck_obj_id = key_p->k_handle; 5137c478bd9Sstevel@tonic-gate } else { 5147c478bd9Sstevel@tonic-gate if (key_p->key_type == CKK_RSA) { 5157c478bd9Sstevel@tonic-gate if (get_rsa_public_key(key_p, &vr_init.ri_key) != 5167c478bd9Sstevel@tonic-gate CKR_OK) { 5177c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 5187c478bd9Sstevel@tonic-gate goto clean_exit; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate } else { 5217c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 5227c478bd9Sstevel@tonic-gate goto clean_exit; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate vr_init.ri_session = session_p->k_session; 5277c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 5287c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 5297c478bd9Sstevel@tonic-gate vr_init.ri_mech.cm_type = k_mech_type; 5307c478bd9Sstevel@tonic-gate vr_init.ri_mech.cm_param = pMechanism->pParameter; 5317c478bd9Sstevel@tonic-gate vr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen; 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER_INIT, 5347c478bd9Sstevel@tonic-gate &vr_init)) < 0) { 5357c478bd9Sstevel@tonic-gate if (errno != EINTR) 5367c478bd9Sstevel@tonic-gate break; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate if (r < 0) { 5397c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 5407c478bd9Sstevel@tonic-gate } else { 5417c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(vr_init.ri_return_value); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* free the memory allocated for vr_init.ri_key */ 5457c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj) { 5467c478bd9Sstevel@tonic-gate free_key_attributes(&vr_init.ri_key); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5507c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 5517c478bd9Sstevel@tonic-gate session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE; 5527c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate clean_exit: 55601223cbaSmcpowers OBJ_REFRELE(key_p); 5577c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5587c478bd9Sstevel@tonic-gate return (rv); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate CK_RV 5637c478bd9Sstevel@tonic-gate C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 5647c478bd9Sstevel@tonic-gate CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 5657c478bd9Sstevel@tonic-gate { 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate CK_RV rv; 5687c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 5697c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 5707c478bd9Sstevel@tonic-gate crypto_verify_recover_t verify_recover; 5717c478bd9Sstevel@tonic-gate int r; 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate if (!kernel_initialized) 5747c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* Obtain the session pointer */ 5777c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 5787c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 5797c478bd9Sstevel@tonic-gate return (rv); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if (pSignature == NULL || pulDataLen == NULL) { 5827c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 5837c478bd9Sstevel@tonic-gate goto clean_exit; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 5877c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Application must call C_VerifyRecoverInit before calling 5917c478bd9Sstevel@tonic-gate * C_Verify. 5927c478bd9Sstevel@tonic-gate */ 5937c478bd9Sstevel@tonic-gate if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 5947c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5957c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate verify_recover.vr_session = session_p->k_session; 5997c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 6007c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 6017c478bd9Sstevel@tonic-gate verify_recover.vr_signlen = ulSignatureLen; 6027c478bd9Sstevel@tonic-gate verify_recover.vr_signbuf = (char *)pSignature; 6037c478bd9Sstevel@tonic-gate verify_recover.vr_datalen = *pulDataLen; 6047c478bd9Sstevel@tonic-gate verify_recover.vr_databuf = (char *)pData; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER, 6077c478bd9Sstevel@tonic-gate &verify_recover)) < 0) { 6087c478bd9Sstevel@tonic-gate if (errno != EINTR) 6097c478bd9Sstevel@tonic-gate break; 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate if (r < 0) { 6127c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 6137c478bd9Sstevel@tonic-gate } else { 6147c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 6157c478bd9Sstevel@tonic-gate verify_recover.vr_return_value); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 6197c478bd9Sstevel@tonic-gate *pulDataLen = verify_recover.vr_datalen; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) || 6227c478bd9Sstevel@tonic-gate (rv == CKR_OK && pData == NULL)) { 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * We will not terminate the active verify operation flag, 6257c478bd9Sstevel@tonic-gate * when the application-supplied buffer is too small, or 6267c478bd9Sstevel@tonic-gate * the application asks for the length of buffer to hold 6277c478bd9Sstevel@tonic-gate * the recovered data. 6287c478bd9Sstevel@tonic-gate */ 6297c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 6307c478bd9Sstevel@tonic-gate return (rv); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate clean_exit: 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * Always terminate the active verify operation. 6367c478bd9Sstevel@tonic-gate * Application needs to call C_VerifyInit again for next 6377c478bd9Sstevel@tonic-gate * verify operation. 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 6407c478bd9Sstevel@tonic-gate session_p->verify.flags = 0; 6417c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 6427c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate return (rv); 6457c478bd9Sstevel@tonic-gate } 646