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 5d3a28a55Sdinak * Common Development and Distribution License (the "License"). 6d3a28a55Sdinak * 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 */ 217c478bd9Sstevel@tonic-gate /* 22*d288ba74SAnthony Scarpino * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Session Management Functions 287c478bd9Sstevel@tonic-gate * (as defined in PKCS#11 spec spection 11.6) 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include "metaGlobal.h" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate extern meta_session_t *meta_sessionlist_head; 357c478bd9Sstevel@tonic-gate extern pthread_rwlock_t meta_sessionlist_lock; 367c478bd9Sstevel@tonic-gate extern CK_ULONG num_meta_sessions; 377c478bd9Sstevel@tonic-gate extern CK_ULONG num_rw_meta_sessions; 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * meta_OpenSession 417c478bd9Sstevel@tonic-gate * 427c478bd9Sstevel@tonic-gate * NOTES: 437c478bd9Sstevel@tonic-gate * 1) The pApplication and Notify args are not used, as the metaslot does not 447c478bd9Sstevel@tonic-gate * support application callbacks. 457c478bd9Sstevel@tonic-gate * 2) the slotID argument is not checked or used because this function 467c478bd9Sstevel@tonic-gate * is only called from the framework. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate /* ARGSUSED */ 497c478bd9Sstevel@tonic-gate CK_RV 507c478bd9Sstevel@tonic-gate meta_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, 517c478bd9Sstevel@tonic-gate CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) 527c478bd9Sstevel@tonic-gate { 537c478bd9Sstevel@tonic-gate meta_session_t *new_session; 547c478bd9Sstevel@tonic-gate CK_RV rv; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate if (!metaslot_enabled) { 577c478bd9Sstevel@tonic-gate return (CKR_SLOT_ID_INVALID); 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate if (phSession == NULL) { 617c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 627c478bd9Sstevel@tonic-gate } 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* Check for any unknown flags. */ 657c478bd9Sstevel@tonic-gate if (flags & ~(CKF_SERIAL_SESSION | CKF_RW_SESSION)) { 667c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if (!(flags & CKF_SERIAL_SESSION)) { 707c478bd9Sstevel@tonic-gate return (CKR_SESSION_PARALLEL_NOT_SUPPORTED); 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate if (meta_slotManager_token_write_protected() && 747c478bd9Sstevel@tonic-gate (flags & CKF_RW_SESSION)) { 757c478bd9Sstevel@tonic-gate return (CKR_TOKEN_WRITE_PROTECTED); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate rv = meta_session_alloc(&new_session); 797c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 807c478bd9Sstevel@tonic-gate return (rv); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate new_session->session_flags = flags; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate rv = meta_session_activate(new_session); 857c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 867c478bd9Sstevel@tonic-gate meta_session_dealloc(new_session); 877c478bd9Sstevel@tonic-gate return (rv); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate *phSession = (CK_SESSION_HANDLE) new_session; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate num_meta_sessions++; 937c478bd9Sstevel@tonic-gate if (flags & CKF_RW_SESSION) { 947c478bd9Sstevel@tonic-gate num_rw_meta_sessions++; 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate return (CKR_OK); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * meta_CloseSession 1037c478bd9Sstevel@tonic-gate * 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate CK_RV 1067c478bd9Sstevel@tonic-gate meta_CloseSession(CK_SESSION_HANDLE hSession) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate CK_RV rv; 1097c478bd9Sstevel@tonic-gate meta_session_t *session; 1107c478bd9Sstevel@tonic-gate CK_FLAGS flags; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate rv = meta_handle2session(hSession, &session); 1137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1147c478bd9Sstevel@tonic-gate return (rv); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* save info about session flags before they are destroyed */ 1177c478bd9Sstevel@tonic-gate flags = session->session_flags; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate rv = meta_session_deactivate(session, B_FALSE); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 1227c478bd9Sstevel@tonic-gate meta_session_dealloc(session); 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate num_meta_sessions--; 1257c478bd9Sstevel@tonic-gate if (flags & CKF_RW_SESSION) { 1267c478bd9Sstevel@tonic-gate num_rw_meta_sessions--; 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate return (rv); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * meta_CloseAllSessions 1357c478bd9Sstevel@tonic-gate * 1367c478bd9Sstevel@tonic-gate * This is a simple loop that closes the sessionlist head (resulting in a 1377c478bd9Sstevel@tonic-gate * new list head) until the list is empty. 1387c478bd9Sstevel@tonic-gate * 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate CK_RV 1417c478bd9Sstevel@tonic-gate meta_CloseAllSessions(CK_SLOT_ID slotID) 1427c478bd9Sstevel@tonic-gate { 1437c478bd9Sstevel@tonic-gate CK_RV rv; 1447c478bd9Sstevel@tonic-gate meta_session_t *session; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate if (!metaslot_enabled) { 1477c478bd9Sstevel@tonic-gate return (CKR_SLOT_ID_INVALID); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate if (slotID != METASLOT_SLOTID) 1517c478bd9Sstevel@tonic-gate return (CKR_SLOT_ID_INVALID); 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&meta_sessionlist_lock); 1547c478bd9Sstevel@tonic-gate while ((session = meta_sessionlist_head) != NULL) { 1557c478bd9Sstevel@tonic-gate rv = meta_handle2session((CK_SESSION_HANDLE)session, &session); 1567c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1577c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1587c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&meta_sessionlist_lock); 1597c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate (void) meta_session_deactivate(session, B_TRUE); 1637c478bd9Sstevel@tonic-gate meta_session_dealloc(session); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&meta_sessionlist_lock); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* All open sessions should be closed, just reset the variables */ 1687c478bd9Sstevel@tonic-gate num_meta_sessions = 0; 1697c478bd9Sstevel@tonic-gate num_rw_meta_sessions = 0; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate return (CKR_OK); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * meta_GetSessionInfo 1777c478bd9Sstevel@tonic-gate * 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate CK_RV 1807c478bd9Sstevel@tonic-gate meta_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate CK_RV rv; 1837c478bd9Sstevel@tonic-gate meta_session_t *session; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (pInfo == NULL) 1867c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate rv = meta_handle2session(hSession, &session); 1897c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1907c478bd9Sstevel@tonic-gate return (rv); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate pInfo->slotID = METASLOT_SLOTID; 1937c478bd9Sstevel@tonic-gate pInfo->flags = session->session_flags; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate if (metaslot_logged_in()) { 1967c478bd9Sstevel@tonic-gate if (IS_READ_ONLY_SESSION(session->session_flags)) { 1977c478bd9Sstevel@tonic-gate pInfo->state = CKS_RO_USER_FUNCTIONS; 1987c478bd9Sstevel@tonic-gate } else { 1997c478bd9Sstevel@tonic-gate pInfo->state = CKS_RW_USER_FUNCTIONS; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate } else { 2027c478bd9Sstevel@tonic-gate if (IS_READ_ONLY_SESSION(session->session_flags)) { 2037c478bd9Sstevel@tonic-gate pInfo->state = CKS_RO_PUBLIC_SESSION; 2047c478bd9Sstevel@tonic-gate } else { 2057c478bd9Sstevel@tonic-gate pInfo->state = CKS_RW_PUBLIC_SESSION; 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate pInfo->ulDeviceError = 0; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate REFRELEASE(session); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate return (CKR_OK); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate CK_RV 2177c478bd9Sstevel@tonic-gate meta_getopstatelen(meta_session_t *session, CK_ULONG *out_length) 2187c478bd9Sstevel@tonic-gate { 2197c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 2207c478bd9Sstevel@tonic-gate slot_session_t *slot_session; 2217c478bd9Sstevel@tonic-gate CK_ULONG length; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate *out_length = sizeof (meta_opstate_t); 224d3a28a55Sdinak if (session->op1.type != 0) { 2257c478bd9Sstevel@tonic-gate slot_session = session->op1.session; 2267c478bd9Sstevel@tonic-gate rv = FUNCLIST(slot_session->fw_st_id)->C_GetOperationState( 2277c478bd9Sstevel@tonic-gate slot_session->hSession, NULL, &length); 2287c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 2297c478bd9Sstevel@tonic-gate *out_length += length; 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate return (rv); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * meta_GetOperationState 2367c478bd9Sstevel@tonic-gate * 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate CK_RV 2397c478bd9Sstevel@tonic-gate meta_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, 2407c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulOperationStateLen) 2417c478bd9Sstevel@tonic-gate { 2427c478bd9Sstevel@tonic-gate CK_RV rv; 2437c478bd9Sstevel@tonic-gate meta_session_t *session; 2447c478bd9Sstevel@tonic-gate slot_session_t *slot_session = NULL; 2457c478bd9Sstevel@tonic-gate meta_opstate_t opstate; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if (pulOperationStateLen == NULL) 2487c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate rv = meta_handle2session(hSession, &session); 2517c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 2527c478bd9Sstevel@tonic-gate return (rv); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * If no operation is active, then bail out. 2567c478bd9Sstevel@tonic-gate */ 257d3a28a55Sdinak if (session->op1.type == 0) { 2587c478bd9Sstevel@tonic-gate rv = CKR_OPERATION_NOT_INITIALIZED; 2597c478bd9Sstevel@tonic-gate goto endgetopstate; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * If the caller did not give an OpState buffer, 2647c478bd9Sstevel@tonic-gate * shortcut and just return the size needed to hold 2657c478bd9Sstevel@tonic-gate * a metaslot OpState record later. 2667c478bd9Sstevel@tonic-gate * The actual size of the returned state will be the 2677c478bd9Sstevel@tonic-gate * sizeof(meta_opstate_t) + SIZE (op1 state), 2687c478bd9Sstevel@tonic-gate * so we have to get the size of 2697c478bd9Sstevel@tonic-gate * the operation states now. 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate if (pOperationState == NULL) { 2727c478bd9Sstevel@tonic-gate rv = meta_getopstatelen(session, pulOperationStateLen); 2737c478bd9Sstevel@tonic-gate REFRELEASE(session); 2747c478bd9Sstevel@tonic-gate return (rv); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * To be here, the caller must have supplied an 2797c478bd9Sstevel@tonic-gate * already initialized meta_opstate_t pointer. 2807c478bd9Sstevel@tonic-gate * Use it to get the real state info from the operation(s). 2817c478bd9Sstevel@tonic-gate * 2827c478bd9Sstevel@tonic-gate * The format of the Metaslot Opstate record: 2837c478bd9Sstevel@tonic-gate * { 2847c478bd9Sstevel@tonic-gate * struct metaopstate 2857c478bd9Sstevel@tonic-gate * [ op1 state data ] 2867c478bd9Sstevel@tonic-gate * } 2877c478bd9Sstevel@tonic-gate */ 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * If the buffer is not even big enough for the metaslot 2917c478bd9Sstevel@tonic-gate * opstate data, return error and set the returned 2927c478bd9Sstevel@tonic-gate * state length to indicate the minimum needed. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate if (*pulOperationStateLen < sizeof (meta_opstate_t)) { 2957c478bd9Sstevel@tonic-gate rv = meta_getopstatelen(session, pulOperationStateLen); 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * Remap the error so the caller knows that they 2987c478bd9Sstevel@tonic-gate * used an invalid buffer size in the first place. 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 3017c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 3027c478bd9Sstevel@tonic-gate goto endgetopstate; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate (void) memset(&opstate, 0, sizeof (meta_opstate_t)); 3067c478bd9Sstevel@tonic-gate opstate.magic_marker = METASLOT_OPSTATE_MAGIC; 3077c478bd9Sstevel@tonic-gate 308d3a28a55Sdinak if (session->op1.type != 0) { 3097c478bd9Sstevel@tonic-gate slot_session = session->op1.session; 3107c478bd9Sstevel@tonic-gate opstate.state[0].op_type = session->op1.type; 3117c478bd9Sstevel@tonic-gate opstate.state[0].op_slotnum = slot_session->slotnum; 3127c478bd9Sstevel@tonic-gate opstate.state[0].op_state_len = *pulOperationStateLen - 3137c478bd9Sstevel@tonic-gate sizeof (meta_opstate_t); 314f4526a4aShaimay opstate.state[0].op_init_app = session->init.app; 315f4526a4aShaimay opstate.state[0].op_init_done = session->init.done; 3167c478bd9Sstevel@tonic-gate rv = FUNCLIST(slot_session->fw_st_id)->C_GetOperationState( 3177c478bd9Sstevel@tonic-gate slot_session->hSession, 3187c478bd9Sstevel@tonic-gate pOperationState + sizeof (meta_opstate_t), 3197c478bd9Sstevel@tonic-gate &(opstate.state[0].op_state_len)); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (rv == CKR_BUFFER_TOO_SMALL) { 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * This should not happen, but if it does, 3247c478bd9Sstevel@tonic-gate * recalculate the entire size needed 3257c478bd9Sstevel@tonic-gate * and return the error. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate rv = meta_getopstatelen(session, pulOperationStateLen); 3287c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 3297c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 3337c478bd9Sstevel@tonic-gate goto endgetopstate; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate endgetopstate: 3377c478bd9Sstevel@tonic-gate if (rv == CKR_OK && pOperationState != NULL) { 3387c478bd9Sstevel@tonic-gate (void) memcpy(pOperationState, (void *)&opstate, 3397c478bd9Sstevel@tonic-gate sizeof (meta_opstate_t)); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate *pulOperationStateLen = sizeof (meta_opstate_t) + 3427c478bd9Sstevel@tonic-gate opstate.state[0].op_state_len; 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate REFRELEASE(session); 3467c478bd9Sstevel@tonic-gate return (rv); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate static CK_RV 3507c478bd9Sstevel@tonic-gate meta_set_opstate(slot_session_t *slot_session, 3517c478bd9Sstevel@tonic-gate meta_object_t *meta_enc_key, 3527c478bd9Sstevel@tonic-gate meta_object_t *meta_auth_key, 3537c478bd9Sstevel@tonic-gate struct opstate_data *state, 3547c478bd9Sstevel@tonic-gate CK_BYTE *databuf) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate CK_RV rv; 357d3a28a55Sdinak static CK_ULONG encrypt_optypes = (CKF_ENCRYPT | CKF_DECRYPT); 358d3a28a55Sdinak static CK_ULONG sign_optypes = (CKF_SIGN | CKF_VERIFY | 359d3a28a55Sdinak CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER); 3607c478bd9Sstevel@tonic-gate slot_object_t *enc_key_obj = NULL, *auth_key_obj = NULL; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (state->op_type & encrypt_optypes) { 363d3a28a55Sdinak rv = meta_object_get_clone(meta_enc_key, slot_session->slotnum, 3647c478bd9Sstevel@tonic-gate slot_session, &enc_key_obj); 3657c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3667c478bd9Sstevel@tonic-gate return (rv); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate if (state->op_type & sign_optypes) { 370d3a28a55Sdinak rv = meta_object_get_clone(meta_auth_key, slot_session->slotnum, 3717c478bd9Sstevel@tonic-gate slot_session, &auth_key_obj); 3727c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3737c478bd9Sstevel@tonic-gate return (rv); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * Check to see if the keys are needed to restore the 3797c478bd9Sstevel@tonic-gate * state on the first operation. 3807c478bd9Sstevel@tonic-gate */ 3817c478bd9Sstevel@tonic-gate rv = FUNCLIST(slot_session->fw_st_id)->C_SetOperationState( 3827c478bd9Sstevel@tonic-gate slot_session->hSession, databuf, state->op_state_len, 3837c478bd9Sstevel@tonic-gate enc_key_obj ? enc_key_obj->hObject : CK_INVALID_HANDLE, 3847c478bd9Sstevel@tonic-gate auth_key_obj ? auth_key_obj->hObject : CK_INVALID_HANDLE); 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * If the operation did not need a key, try again. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate if (rv == CKR_KEY_NOT_NEEDED) { 3897c478bd9Sstevel@tonic-gate rv = FUNCLIST(slot_session->fw_st_id)->C_SetOperationState( 3907c478bd9Sstevel@tonic-gate slot_session->hSession, databuf, state->op_state_len, 3917c478bd9Sstevel@tonic-gate CK_INVALID_HANDLE, CK_INVALID_HANDLE); 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * Strange case... If the first try returned 3947c478bd9Sstevel@tonic-gate * KEY_NOT_NEEDED, and this one returns KEY_NEEDED, 3957c478bd9Sstevel@tonic-gate * we want to remap the return so the caller sees 3967c478bd9Sstevel@tonic-gate * the original "CKR_KEY_NOT_NEEDED" return value. 3977c478bd9Sstevel@tonic-gate * This ensures that a correct caller will retry 3987c478bd9Sstevel@tonic-gate * without the unnecessary key argument and this 3997c478bd9Sstevel@tonic-gate * 2nd attempt will not happen again. 4007c478bd9Sstevel@tonic-gate */ 4017c478bd9Sstevel@tonic-gate if (rv == CKR_KEY_NEEDED) { 4027c478bd9Sstevel@tonic-gate rv = CKR_KEY_NOT_NEEDED; 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate return (rv); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * meta_SetOperationState 4117c478bd9Sstevel@tonic-gate * 4127c478bd9Sstevel@tonic-gate */ 4137c478bd9Sstevel@tonic-gate CK_RV 4147c478bd9Sstevel@tonic-gate meta_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, 4157c478bd9Sstevel@tonic-gate CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, 4167c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hAuthenticationKey) 4177c478bd9Sstevel@tonic-gate { 4187c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 4197c478bd9Sstevel@tonic-gate meta_session_t *session; 4207c478bd9Sstevel@tonic-gate slot_session_t *slot_session = NULL; 4217c478bd9Sstevel@tonic-gate meta_opstate_t opstate; 4227c478bd9Sstevel@tonic-gate meta_object_t *meta_enc_key = NULL, *meta_auth_key = NULL; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Make sure the opstate info buffer is big enough to be valid. 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate if (ulOperationStateLen < sizeof (meta_opstate_t) || 4287c478bd9Sstevel@tonic-gate pOperationState == NULL) 4297c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* Copy the opstate info into the structure */ 4327c478bd9Sstevel@tonic-gate (void) memcpy(&opstate, pOperationState, sizeof (meta_opstate_t)); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* verify that a metaslot operation state was supplied */ 4357c478bd9Sstevel@tonic-gate if (opstate.magic_marker != METASLOT_OPSTATE_MAGIC) 4367c478bd9Sstevel@tonic-gate return (CKR_SAVED_STATE_INVALID); 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Now, check the size again to make sure the "real" state 4407c478bd9Sstevel@tonic-gate * data is present. Length of state provided must be exact. 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate if (ulOperationStateLen != (sizeof (meta_opstate_t) + 4437c478bd9Sstevel@tonic-gate opstate.state[0].op_state_len)) 4447c478bd9Sstevel@tonic-gate return (CKR_SAVED_STATE_INVALID); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate rv = meta_handle2session(hSession, &session); 4477c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4487c478bd9Sstevel@tonic-gate return (rv); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (hEncryptionKey != CK_INVALID_HANDLE) { 4517c478bd9Sstevel@tonic-gate rv = meta_handle2object(hEncryptionKey, &meta_enc_key); 4527c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4537c478bd9Sstevel@tonic-gate goto cleanup; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate if (hAuthenticationKey != CK_INVALID_HANDLE) { 4567c478bd9Sstevel@tonic-gate rv = meta_handle2object(hAuthenticationKey, &meta_auth_key); 4577c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4587c478bd9Sstevel@tonic-gate goto cleanup; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 461d3a28a55Sdinak if (opstate.state[0].op_type != 0) { 462d3a28a55Sdinak if (session->op1.type != 0) 4637c478bd9Sstevel@tonic-gate meta_operation_cleanup(session, session->op1.type, 4647c478bd9Sstevel@tonic-gate B_FALSE); 4657c478bd9Sstevel@tonic-gate 466504c4cfbSKrishna Yenduri if (session->op1.session != NULL) { 467504c4cfbSKrishna Yenduri slot_session = session->op1.session; 468504c4cfbSKrishna Yenduri } else { 4697c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(opstate.state[0].op_slotnum, 4707c478bd9Sstevel@tonic-gate &slot_session, session->session_flags); 4717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4727c478bd9Sstevel@tonic-gate goto cleanup; 473504c4cfbSKrishna Yenduri } 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate session->op1.type = opstate.state[0].op_type; 4767c478bd9Sstevel@tonic-gate session->op1.session = slot_session; 477f4526a4aShaimay session->init.app = opstate.state[0].op_init_app; 478f4526a4aShaimay session->init.done = opstate.state[0].op_init_done; 4797c478bd9Sstevel@tonic-gate 480d3a28a55Sdinak rv = meta_set_opstate(slot_session, meta_enc_key, 481d3a28a55Sdinak meta_auth_key, &(opstate.state[0]), 4827c478bd9Sstevel@tonic-gate pOperationState + sizeof (meta_opstate_t)); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4857c478bd9Sstevel@tonic-gate meta_operation_cleanup(session, session->op1.type, 4867c478bd9Sstevel@tonic-gate FALSE); 4877c478bd9Sstevel@tonic-gate goto cleanup; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate cleanup: 4927c478bd9Sstevel@tonic-gate if (meta_enc_key != NULL) 4937c478bd9Sstevel@tonic-gate OBJRELEASE(meta_enc_key); 4947c478bd9Sstevel@tonic-gate if (meta_auth_key != NULL) 4957c478bd9Sstevel@tonic-gate OBJRELEASE(meta_auth_key); 4967c478bd9Sstevel@tonic-gate REFRELEASE(session); 4977c478bd9Sstevel@tonic-gate return (rv); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* 5017c478bd9Sstevel@tonic-gate * meta_Login 5027c478bd9Sstevel@tonic-gate * 5037c478bd9Sstevel@tonic-gate * This allows the user to login to the object token. The metaslot itself 5047c478bd9Sstevel@tonic-gate * does not have any kind of PIN. 5057c478bd9Sstevel@tonic-gate * 5067c478bd9Sstevel@tonic-gate */ 5077c478bd9Sstevel@tonic-gate CK_RV 5087c478bd9Sstevel@tonic-gate meta_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, 5097c478bd9Sstevel@tonic-gate CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate CK_RV rv; 5127c478bd9Sstevel@tonic-gate meta_session_t *session; 5137c478bd9Sstevel@tonic-gate slot_session_t *login_session = NULL; 5147c478bd9Sstevel@tonic-gate CK_TOKEN_INFO token_info; 5157c478bd9Sstevel@tonic-gate CK_SLOT_ID true_id, fw_st_id; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate rv = meta_handle2session(hSession, &session); 5187c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 5197c478bd9Sstevel@tonic-gate return (rv); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate if (metaslot_logged_in()) { 5227c478bd9Sstevel@tonic-gate rv = CKR_USER_ALREADY_LOGGED_IN; 5237c478bd9Sstevel@tonic-gate goto finish; 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* Note: CKU_SO is not supported. */ 5277c478bd9Sstevel@tonic-gate if (userType != CKU_USER) { 5287c478bd9Sstevel@tonic-gate rv = CKR_USER_TYPE_INVALID; 5297c478bd9Sstevel@tonic-gate goto finish; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(get_keystore_slotnum(), &login_session, 5337c478bd9Sstevel@tonic-gate session->session_flags); 5347c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 5357c478bd9Sstevel@tonic-gate goto finish; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate fw_st_id = login_session->fw_st_id; 5397c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_Login(login_session->hSession, userType, 5407c478bd9Sstevel@tonic-gate pPin, ulPinLen); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5437c478bd9Sstevel@tonic-gate goto finish; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate /* 5477c478bd9Sstevel@tonic-gate * Note: 5487c478bd9Sstevel@tonic-gate * 5497c478bd9Sstevel@tonic-gate * For some slots (eg: the pkcs11_softtoken.so), C_Login() 5507c478bd9Sstevel@tonic-gate * returning OK don't mean that the login is truely 5517c478bd9Sstevel@tonic-gate * successful. For pkcs11_softtoken.so, the CKF_USER_PIN_TO_BE_CHANGED 5527c478bd9Sstevel@tonic-gate * is set to indicate that the pin needs to be changed, and 5537c478bd9Sstevel@tonic-gate * the login is not really successful. We will check 5547c478bd9Sstevel@tonic-gate * that flag for this special condition. Checking for 5557c478bd9Sstevel@tonic-gate * this flag shouldn't be harmful for other slots that doesn't 5567c478bd9Sstevel@tonic-gate * behave like pkcs11_softtoken.so. 5577c478bd9Sstevel@tonic-gate */ 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate true_id = TRUEID(fw_st_id); 5607c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetTokenInfo(true_id, &token_info); 5617c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5627c478bd9Sstevel@tonic-gate goto finish; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate metaslot_set_logged_in_flag(B_TRUE); 5667c478bd9Sstevel@tonic-gate if (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED) { 5677c478bd9Sstevel@tonic-gate metaslot_set_logged_in_flag(B_FALSE); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate finish: 5707c478bd9Sstevel@tonic-gate if (login_session) 5717c478bd9Sstevel@tonic-gate meta_release_slot_session(login_session); 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate REFRELEASE(session); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate return (rv); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * meta_Logout 5807c478bd9Sstevel@tonic-gate * 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate CK_RV 5837c478bd9Sstevel@tonic-gate meta_Logout(CK_SESSION_HANDLE hSession) 5847c478bd9Sstevel@tonic-gate { 5857c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 5867c478bd9Sstevel@tonic-gate meta_session_t *session; 5877c478bd9Sstevel@tonic-gate slot_session_t *logout_session = NULL; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate rv = meta_handle2session(hSession, &session); 5907c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 5917c478bd9Sstevel@tonic-gate return (rv); 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (!metaslot_logged_in()) { 5947c478bd9Sstevel@tonic-gate rv = CKR_USER_NOT_LOGGED_IN; 5957c478bd9Sstevel@tonic-gate goto finish; 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(get_keystore_slotnum(), &logout_session, 5997c478bd9Sstevel@tonic-gate session->session_flags); 6007c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 6017c478bd9Sstevel@tonic-gate goto finish; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate rv = FUNCLIST(logout_session->fw_st_id)->C_Logout( 6047c478bd9Sstevel@tonic-gate logout_session->hSession); 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* If the C_Logout fails, just ignore the error. */ 6077c478bd9Sstevel@tonic-gate metaslot_set_logged_in_flag(B_FALSE); 608*d288ba74SAnthony Scarpino (void) meta_token_object_deactivate(PRIVATE_TOKEN); 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate finish: 6117c478bd9Sstevel@tonic-gate if (logout_session) 6127c478bd9Sstevel@tonic-gate meta_release_slot_session(logout_session); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate REFRELEASE(session); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate return (rv); 6177c478bd9Sstevel@tonic-gate } 618