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 5034448feSmcpowers * Common Development and Distribution License (the "License"). 6034448feSmcpowers * 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*8cae6764SAnthony 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 #include <cryptoutil.h> 277c478bd9Sstevel@tonic-gate #include <errno.h> 287c478bd9Sstevel@tonic-gate #include <fcntl.h> 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <strings.h> 317c478bd9Sstevel@tonic-gate #include "metaGlobal.h" 327c478bd9Sstevel@tonic-gate 33a039cd31Shaimay extern cipher_mechs_threshold_t meta_mechs_threshold[]; 34cd7d5fafSJan Pechanec static boolean_t threshold_chk_enabled = B_FALSE; 35a039cd31Shaimay 364a5b2e70Shaimay CK_RV 374a5b2e70Shaimay meta_operation_init_defer(CK_FLAGS optype, meta_session_t *session, 384a5b2e70Shaimay CK_MECHANISM *pMechanism, meta_object_t *key) 394a5b2e70Shaimay { 404a5b2e70Shaimay 414a5b2e70Shaimay if (session->init.pMech == NULL) { 424a5b2e70Shaimay session->init.pMech = malloc(sizeof (CK_MECHANISM)); 434a5b2e70Shaimay if (session->init.pMech == NULL) 444a5b2e70Shaimay return (CKR_HOST_MEMORY); 454a5b2e70Shaimay 464a5b2e70Shaimay (void) memcpy(session->init.pMech, pMechanism, 474a5b2e70Shaimay sizeof (CK_MECHANISM)); 484a5b2e70Shaimay 494a5b2e70Shaimay if ((pMechanism->ulParameterLen > 0) && 504a5b2e70Shaimay (pMechanism->pParameter != NULL)) { 514a5b2e70Shaimay session->init.pMech->pParameter = 524a5b2e70Shaimay malloc(pMechanism->ulParameterLen); 534a5b2e70Shaimay if (session->init.pMech->pParameter == NULL) { 544a5b2e70Shaimay free(session->init.pMech); 554a5b2e70Shaimay session->init.pMech = NULL; 564a5b2e70Shaimay return (CKR_HOST_MEMORY); 574a5b2e70Shaimay } 584a5b2e70Shaimay (void) memcpy(session->init.pMech->pParameter, 594a5b2e70Shaimay pMechanism->pParameter, pMechanism->ulParameterLen); 604a5b2e70Shaimay } else { 614a5b2e70Shaimay session->init.pMech->pParameter = NULL; 624a5b2e70Shaimay } 634a5b2e70Shaimay } else { /* reuse it */ 644a5b2e70Shaimay if ((pMechanism->ulParameterLen > 0) && 654a5b2e70Shaimay (pMechanism->pParameter != NULL)) { 664a5b2e70Shaimay if (pMechanism->ulParameterLen != 674a5b2e70Shaimay session->init.pMech->ulParameterLen) { 684a5b2e70Shaimay if (session->init.pMech->pParameter != NULL) 694a5b2e70Shaimay free(session->init.pMech->pParameter); 704a5b2e70Shaimay session->init.pMech->pParameter = 714a5b2e70Shaimay malloc(pMechanism->ulParameterLen); 724a5b2e70Shaimay if (session->init.pMech->pParameter == NULL) { 734a5b2e70Shaimay free(session->init.pMech); 744a5b2e70Shaimay session->init.pMech = NULL; 754a5b2e70Shaimay return (CKR_HOST_MEMORY); 764a5b2e70Shaimay } 774a5b2e70Shaimay } /* otherwise reuse it */ 784a5b2e70Shaimay (void) memcpy(session->init.pMech->pParameter, 794a5b2e70Shaimay pMechanism->pParameter, pMechanism->ulParameterLen); 804a5b2e70Shaimay } else { 814a5b2e70Shaimay /* 824a5b2e70Shaimay * free the previous pParameter if not yet freed 834a5b2e70Shaimay * because we don't need it now. 844a5b2e70Shaimay */ 854a5b2e70Shaimay if (session->init.pMech->pParameter != NULL) { 864a5b2e70Shaimay free(session->init.pMech->pParameter); 874a5b2e70Shaimay session->init.pMech->pParameter = NULL; 884a5b2e70Shaimay } 894a5b2e70Shaimay } 904a5b2e70Shaimay /* copy the rest of data */ 914a5b2e70Shaimay session->init.pMech->mechanism = 924a5b2e70Shaimay pMechanism->mechanism; 934a5b2e70Shaimay session->init.pMech->ulParameterLen = 944a5b2e70Shaimay pMechanism->ulParameterLen; 954a5b2e70Shaimay } 964a5b2e70Shaimay 974a5b2e70Shaimay session->init.session = session; 984a5b2e70Shaimay session->init.optype = optype; 994a5b2e70Shaimay session->init.key = key; 1004a5b2e70Shaimay session->init.done = B_FALSE; 1014a5b2e70Shaimay session->init.app = B_TRUE; 1024a5b2e70Shaimay return (CKR_OK); 1034a5b2e70Shaimay } 1044a5b2e70Shaimay 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * meta_operation_init 1077c478bd9Sstevel@tonic-gate * 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate CK_RV 110d3a28a55Sdinak meta_operation_init(CK_FLAGS optype, meta_session_t *session, 1117c478bd9Sstevel@tonic-gate CK_MECHANISM *pMechanism, meta_object_t *key) 1127c478bd9Sstevel@tonic-gate { 1137c478bd9Sstevel@tonic-gate CK_RV rv, save_rv; 1147c478bd9Sstevel@tonic-gate mechinfo_t **supporting_slots; 1157c478bd9Sstevel@tonic-gate CK_ULONG slotnum; 1167c478bd9Sstevel@tonic-gate unsigned long i, slotCount = 0; 1177c478bd9Sstevel@tonic-gate slot_session_t *init_session = NULL; 118d3a28a55Sdinak CK_MECHANISM_INFO mech_info; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * If an operation is already active, cleanup existing operation 1227c478bd9Sstevel@tonic-gate * and start a new one. 1237c478bd9Sstevel@tonic-gate */ 124d3a28a55Sdinak if (session->op1.type != 0) { 125142e971fShaimay CK_MECHANISM mech; 1264a5b2e70Shaimay if ((optype == CKF_ENCRYPT) || (optype == CKF_DECRYPT) || 1274a5b2e70Shaimay (optype == CKF_DIGEST)) { 128142e971fShaimay mech = *pMechanism; 129142e971fShaimay 130142e971fShaimay if ((pMechanism->ulParameterLen > 0) && 131142e971fShaimay (pMechanism->pParameter != NULL)) { 132142e971fShaimay mech.pParameter = 133142e971fShaimay malloc(pMechanism->ulParameterLen); 134142e971fShaimay if (mech.pParameter == NULL) { 135142e971fShaimay return (CKR_HOST_MEMORY); 136142e971fShaimay } 137142e971fShaimay (void) memcpy(mech.pParameter, 138142e971fShaimay pMechanism->pParameter, 139142e971fShaimay pMechanism->ulParameterLen); 140142e971fShaimay } else { 141142e971fShaimay mech.pParameter = NULL; 142142e971fShaimay mech.ulParameterLen = 0; 143142e971fShaimay } 144142e971fShaimay 145142e971fShaimay meta_operation_cleanup(session, session->op1.type, 146142e971fShaimay B_FALSE); 1474a5b2e70Shaimay rv = meta_operation_init_defer(optype, session, 148142e971fShaimay &mech, key); 149142e971fShaimay if (mech.pParameter != NULL) { 150142e971fShaimay free(mech.pParameter); 151142e971fShaimay } 1524a5b2e70Shaimay if (rv != CKR_OK) 1534a5b2e70Shaimay return (rv); 154142e971fShaimay } else { 155142e971fShaimay meta_operation_cleanup(session, session->op1.type, 156142e971fShaimay B_FALSE); 1574a5b2e70Shaimay } 158142e971fShaimay 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 161d3a28a55Sdinak mech_info.flags = optype; 162d3a28a55Sdinak 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * Get a list of capable slots. 1657c478bd9Sstevel@tonic-gate * 1667c478bd9Sstevel@tonic-gate * If the specified mechanism is used in this session last time, 1677c478bd9Sstevel@tonic-gate * the list of capable slots is already retrieved. We can save 1687c478bd9Sstevel@tonic-gate * some processing, and just use that list of slots. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate if (((session->mech_support_info).mech != pMechanism->mechanism) || 1717c478bd9Sstevel@tonic-gate ((session->mech_support_info).num_supporting_slots == 0)) { 1727c478bd9Sstevel@tonic-gate (session->mech_support_info).mech = pMechanism->mechanism; 1737c478bd9Sstevel@tonic-gate rv = meta_mechManager_get_slots(&(session->mech_support_info), 174d3a28a55Sdinak B_FALSE, &mech_info); 1757c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1767c478bd9Sstevel@tonic-gate goto finish; 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* The following 2 assignment is just to make the code more readable */ 1837c478bd9Sstevel@tonic-gate slotCount = (session->mech_support_info).num_supporting_slots; 1847c478bd9Sstevel@tonic-gate supporting_slots = (session->mech_support_info).supporting_slots; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* Attempt to initialize operation on slots until one succeeds. */ 1877c478bd9Sstevel@tonic-gate for (i = 0; i < slotCount; i++) { 1887c478bd9Sstevel@tonic-gate slot_object_t *init_key; 1897c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate init_session = NULL; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate slotnum = supporting_slots[i]->slotnum; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * An actual session with the underlying slot is required 1977c478bd9Sstevel@tonic-gate * for the operation. When the operation is successfully 1987c478bd9Sstevel@tonic-gate * completed, the underlying session with the slot 1997c478bd9Sstevel@tonic-gate * is not released back to the list of available sessions 2007c478bd9Sstevel@tonic-gate * pool. This will help if the next operation can 2017c478bd9Sstevel@tonic-gate * also be done on the same slot, because it avoids 2027c478bd9Sstevel@tonic-gate * one extra trip to the session pool to get an idle session. 2037c478bd9Sstevel@tonic-gate * If the operation can't be done on that slot, 2047c478bd9Sstevel@tonic-gate * we release the session back to the session pool then. 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate if (session->op1.session != NULL) { 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if ((session->op1.session)->slotnum == slotnum) { 2097c478bd9Sstevel@tonic-gate init_session = session->op1.session; 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * set it to NULL for now, assign it to 2127c478bd9Sstevel@tonic-gate * init_session again if it is successful 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate session->op1.session = NULL; 2157c478bd9Sstevel@tonic-gate } else { 2167c478bd9Sstevel@tonic-gate init_session = NULL; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (!init_session) { 2227c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(slotnum, &init_session, 2237c478bd9Sstevel@tonic-gate session->session_flags); 2247c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2257c478bd9Sstevel@tonic-gate goto loop_cleanup; 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* if necessary, ensure a clone of the obj exists in slot */ 230d3a28a55Sdinak if (optype != CKF_DIGEST) { 2317c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(key, slotnum, init_session, 2327c478bd9Sstevel@tonic-gate &init_key); 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2357c478bd9Sstevel@tonic-gate goto loop_cleanup; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate fw_st_id = init_session->fw_st_id; 2407c478bd9Sstevel@tonic-gate switch (optype) { 241d3a28a55Sdinak case CKF_ENCRYPT: 2427c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_EncryptInit( 2437c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism, 2447c478bd9Sstevel@tonic-gate init_key->hObject); 2457c478bd9Sstevel@tonic-gate break; 246d3a28a55Sdinak case CKF_DECRYPT: 2477c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DecryptInit( 2487c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism, 2497c478bd9Sstevel@tonic-gate init_key->hObject); 2507c478bd9Sstevel@tonic-gate break; 251d3a28a55Sdinak case CKF_DIGEST: 2527c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DigestInit( 2537c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism); 2547c478bd9Sstevel@tonic-gate break; 255d3a28a55Sdinak case CKF_SIGN: 2567c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_SignInit( 2577c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism, 2587c478bd9Sstevel@tonic-gate init_key->hObject); 2597c478bd9Sstevel@tonic-gate break; 260d3a28a55Sdinak case CKF_VERIFY: 2617c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_VerifyInit( 2627c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism, 2637c478bd9Sstevel@tonic-gate init_key->hObject); 2647c478bd9Sstevel@tonic-gate break; 265d3a28a55Sdinak case CKF_SIGN_RECOVER: 2667c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_SignRecoverInit( 2677c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism, 2687c478bd9Sstevel@tonic-gate init_key->hObject); 2697c478bd9Sstevel@tonic-gate break; 270d3a28a55Sdinak case CKF_VERIFY_RECOVER: 2717c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_VerifyRecoverInit( 2727c478bd9Sstevel@tonic-gate init_session->hSession, pMechanism, 2737c478bd9Sstevel@tonic-gate init_key->hObject); 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate default: 2777c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2787c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 2797c478bd9Sstevel@tonic-gate break; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 2837c478bd9Sstevel@tonic-gate break; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate loop_cleanup: 2867c478bd9Sstevel@tonic-gate if (i == 0) { 2877c478bd9Sstevel@tonic-gate save_rv = rv; 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (init_session) { 2917c478bd9Sstevel@tonic-gate meta_release_slot_session(init_session); 2927c478bd9Sstevel@tonic-gate init_session = NULL; 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* 3007c478bd9Sstevel@tonic-gate * If currently stored session is not the one being in use now, 3017c478bd9Sstevel@tonic-gate * release the previous one and store the current one 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate if ((session->op1.session) && 3047c478bd9Sstevel@tonic-gate (session->op1.session != init_session)) { 3057c478bd9Sstevel@tonic-gate meta_release_slot_session(session->op1.session); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* Save the session */ 3097c478bd9Sstevel@tonic-gate session->op1.session = init_session; 3107c478bd9Sstevel@tonic-gate session->op1.type = optype; 3114a5b2e70Shaimay 3124a5b2e70Shaimay session->init.slotnum = slotnum; 3134a5b2e70Shaimay session->init.done = B_TRUE; 3147c478bd9Sstevel@tonic-gate } else { 3157c478bd9Sstevel@tonic-gate rv = save_rv; 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate finish: 3197c478bd9Sstevel@tonic-gate return (rv); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3234a5b2e70Shaimay * meta_operation_init_softtoken() 3244a5b2e70Shaimay * It will always do the crypto init operation on softtoken slot. 3254a5b2e70Shaimay */ 3264a5b2e70Shaimay CK_RV 3274a5b2e70Shaimay meta_operation_init_softtoken(CK_FLAGS optype, meta_session_t *session, 3284a5b2e70Shaimay CK_MECHANISM *pMechanism, meta_object_t *key) 3294a5b2e70Shaimay { 3304a5b2e70Shaimay CK_RV rv = CKR_FUNCTION_FAILED; 3314a5b2e70Shaimay slot_session_t *init_session = NULL; 3324a5b2e70Shaimay slot_object_t *init_key; 3334a5b2e70Shaimay CK_SLOT_ID fw_st_id; 3344a5b2e70Shaimay CK_ULONG softtoken_slot_num; 3354a5b2e70Shaimay 3364a5b2e70Shaimay softtoken_slot_num = get_softtoken_slotnum(); 3374a5b2e70Shaimay /* 3384a5b2e70Shaimay * If an operation is already active, cleanup existing operation 3394a5b2e70Shaimay * and start a new one. 3404a5b2e70Shaimay */ 3414a5b2e70Shaimay if (session->op1.type != 0) { 342142e971fShaimay CK_MECHANISM mech; 343142e971fShaimay mech = *pMechanism; 344142e971fShaimay 345142e971fShaimay if ((pMechanism->ulParameterLen > 0) && 346142e971fShaimay (pMechanism->pParameter != NULL)) { 347142e971fShaimay mech.pParameter = 348142e971fShaimay malloc(pMechanism->ulParameterLen); 349142e971fShaimay if (mech.pParameter == NULL) { 350142e971fShaimay return (CKR_HOST_MEMORY); 351142e971fShaimay } 352142e971fShaimay (void) memcpy(mech.pParameter, 353142e971fShaimay pMechanism->pParameter, pMechanism->ulParameterLen); 354142e971fShaimay } else { 355142e971fShaimay mech.pParameter = NULL; 356142e971fShaimay mech.ulParameterLen = 0; 357142e971fShaimay } 358142e971fShaimay 3594a5b2e70Shaimay meta_operation_cleanup(session, session->op1.type, B_FALSE); 360142e971fShaimay rv = meta_operation_init_defer(optype, session, &mech, 3614a5b2e70Shaimay key); 362142e971fShaimay if (mech.pParameter != NULL) { 363142e971fShaimay free(mech.pParameter); 364142e971fShaimay } 3654a5b2e70Shaimay if (rv != CKR_OK) 3664a5b2e70Shaimay return (rv); 3674a5b2e70Shaimay } 3684a5b2e70Shaimay 3694a5b2e70Shaimay /* 3704a5b2e70Shaimay * An actual session with the underlying slot is required 3714a5b2e70Shaimay * for the operation. When the operation is successfully 3724a5b2e70Shaimay * completed, the underlying session with the slot 3734a5b2e70Shaimay * is not released back to the list of available sessions 3744a5b2e70Shaimay * pool. This will help if the next operation can 3754a5b2e70Shaimay * also be done on the same slot, because it avoids 3764a5b2e70Shaimay * one extra trip to the session pool to get an idle session. 3774a5b2e70Shaimay * If the operation can't be done on that slot, 3784a5b2e70Shaimay * we release the session back to the session pool. 3794a5b2e70Shaimay */ 3804a5b2e70Shaimay if (session->op1.session != NULL) { 3814a5b2e70Shaimay if ((session->op1.session)->slotnum == 3824a5b2e70Shaimay softtoken_slot_num) { 3834a5b2e70Shaimay init_session = session->op1.session; 3844a5b2e70Shaimay /* 3854a5b2e70Shaimay * set it to NULL for now, assign it to 3864a5b2e70Shaimay * init_session again if it is successful 3874a5b2e70Shaimay */ 3884a5b2e70Shaimay session->op1.session = NULL; 3894a5b2e70Shaimay } else { 3904a5b2e70Shaimay init_session = NULL; 3914a5b2e70Shaimay } 3924a5b2e70Shaimay } 3934a5b2e70Shaimay 3944a5b2e70Shaimay if (init_session == NULL) { 3954a5b2e70Shaimay /* get the active session from softtoken slot */ 3964a5b2e70Shaimay rv = meta_get_slot_session(softtoken_slot_num, 3974a5b2e70Shaimay &init_session, session->session_flags); 3984a5b2e70Shaimay if (rv != CKR_OK) { 3994a5b2e70Shaimay goto finish; 4004a5b2e70Shaimay } 4014a5b2e70Shaimay } 4024a5b2e70Shaimay 4034a5b2e70Shaimay /* if necessary, ensure a clone of the obj exists in softtoken slot */ 4044a5b2e70Shaimay if (optype != CKF_DIGEST) { 4054a5b2e70Shaimay rv = meta_object_get_clone(key, softtoken_slot_num, 4064a5b2e70Shaimay init_session, &init_key); 4074a5b2e70Shaimay 4084a5b2e70Shaimay if (rv != CKR_OK) { 4094a5b2e70Shaimay if (init_session != NULL) { 4104a5b2e70Shaimay meta_release_slot_session(init_session); 4114a5b2e70Shaimay init_session = NULL; 4124a5b2e70Shaimay } 4134a5b2e70Shaimay goto finish; 4144a5b2e70Shaimay } 4154a5b2e70Shaimay } 4164a5b2e70Shaimay 4174a5b2e70Shaimay fw_st_id = init_session->fw_st_id; 4184a5b2e70Shaimay 4194a5b2e70Shaimay /* 4204a5b2e70Shaimay * Currently, we only support offloading encrypt, decrypt 4214a5b2e70Shaimay * and digest operations to softtoken based on kernel 4224a5b2e70Shaimay * threshold for the supported mechanisms. 4234a5b2e70Shaimay */ 4244a5b2e70Shaimay switch (optype) { 4254a5b2e70Shaimay case CKF_ENCRYPT: 4264a5b2e70Shaimay rv = FUNCLIST(fw_st_id)->C_EncryptInit( 4274a5b2e70Shaimay init_session->hSession, pMechanism, 4284a5b2e70Shaimay init_key->hObject); 4294a5b2e70Shaimay break; 4304a5b2e70Shaimay case CKF_DECRYPT: 4314a5b2e70Shaimay rv = FUNCLIST(fw_st_id)->C_DecryptInit( 4324a5b2e70Shaimay init_session->hSession, pMechanism, 4334a5b2e70Shaimay init_key->hObject); 4344a5b2e70Shaimay break; 4354a5b2e70Shaimay case CKF_DIGEST: 4364a5b2e70Shaimay rv = FUNCLIST(fw_st_id)->C_DigestInit( 4374a5b2e70Shaimay init_session->hSession, pMechanism); 4384a5b2e70Shaimay break; 4394a5b2e70Shaimay 4404a5b2e70Shaimay default: 4414a5b2e70Shaimay /*NOTREACHED*/ 4424a5b2e70Shaimay rv = CKR_FUNCTION_FAILED; 4434a5b2e70Shaimay break; 4444a5b2e70Shaimay } 4454a5b2e70Shaimay 4464a5b2e70Shaimay if (rv == CKR_OK) { 4474a5b2e70Shaimay 4484a5b2e70Shaimay /* 4494a5b2e70Shaimay * If currently stored session is not the one being in use now, 4504a5b2e70Shaimay * release the previous one and store the current one 4514a5b2e70Shaimay */ 4524a5b2e70Shaimay if ((session->op1.session) && 4534a5b2e70Shaimay (session->op1.session != init_session)) { 4544a5b2e70Shaimay meta_release_slot_session(session->op1.session); 4554a5b2e70Shaimay } 4564a5b2e70Shaimay 4574a5b2e70Shaimay /* Save the session */ 4584a5b2e70Shaimay session->op1.session = init_session; 4594a5b2e70Shaimay session->op1.type = optype; 4604a5b2e70Shaimay /* 4614a5b2e70Shaimay * The init.done flag will be checked by the meta_do_operation() 4624a5b2e70Shaimay * to indicate whether the C_xxxInit has been done against 4634a5b2e70Shaimay * softtoken. 4644a5b2e70Shaimay */ 4654a5b2e70Shaimay session->init.done = B_TRUE; 4664a5b2e70Shaimay session->init.slotnum = softtoken_slot_num; 4674a5b2e70Shaimay } 4684a5b2e70Shaimay 4694a5b2e70Shaimay finish: 4704a5b2e70Shaimay return (rv); 4714a5b2e70Shaimay } 4724a5b2e70Shaimay 473a039cd31Shaimay int 474a039cd31Shaimay meta_GetThreshold(CK_MECHANISM_TYPE mechanism) 475a039cd31Shaimay { 476a039cd31Shaimay 477a039cd31Shaimay int i; 478a039cd31Shaimay 479a039cd31Shaimay for (i = 0; i < MAX_NUM_THRESHOLD; i++) { 480a039cd31Shaimay if (mechanism == meta_mechs_threshold[i].mech_type) 481a039cd31Shaimay return (meta_mechs_threshold[i].mech_threshold); 482a039cd31Shaimay } 483a039cd31Shaimay 484a039cd31Shaimay /* no matching mechanism */ 485a039cd31Shaimay return (0); 486a039cd31Shaimay } 487a039cd31Shaimay 4884a5b2e70Shaimay /* 4897c478bd9Sstevel@tonic-gate * meta_do_operation 4907c478bd9Sstevel@tonic-gate * 4917c478bd9Sstevel@tonic-gate * NOTES: 4927c478bd9Sstevel@tonic-gate * 4937c478bd9Sstevel@tonic-gate * 1) The spec says you cannot do a C_Encrypt after a C_EncUpdate, 4947c478bd9Sstevel@tonic-gate * but we don't explicitly enforce it here (ie, disallow doing MODE_SINGLE 4957c478bd9Sstevel@tonic-gate * after a MODE_UPDATE). Instead, we just assume the underlying provider 4967c478bd9Sstevel@tonic-gate * will catch the problem and return an appropriate error. 4977c478bd9Sstevel@tonic-gate * 4987c478bd9Sstevel@tonic-gate * 2) Note that the Verify operations are a little unusual, due to the 4997c478bd9Sstevel@tonic-gate * PKCS#11 API. For C_Verify, the last two arguments are used as inputs, 5007c478bd9Sstevel@tonic-gate * unlike the other single pass operations (where they are outputs). For 5017c478bd9Sstevel@tonic-gate * C_VerifyFinal, in/inLen are passed instead of out/outLen like the other 5027c478bd9Sstevel@tonic-gate * Final operations. 5037c478bd9Sstevel@tonic-gate * 5047c478bd9Sstevel@tonic-gate * 3) C_DigestKey is the only crypto operation that uses an object after 5057c478bd9Sstevel@tonic-gate * the operation has been initialized. No other callers should provide 5067c478bd9Sstevel@tonic-gate * this argument (use NULL). 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate CK_RV 509d3a28a55Sdinak meta_do_operation(CK_FLAGS optype, int mode, 5107c478bd9Sstevel@tonic-gate meta_session_t *session, meta_object_t *object, 5117c478bd9Sstevel@tonic-gate CK_BYTE *in, CK_ULONG inLen, CK_BYTE *out, CK_ULONG *outLen) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate CK_RV rv; 5147c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE hSession; 5157c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id; 5167c478bd9Sstevel@tonic-gate slot_session_t *slot_session = NULL; 5177c478bd9Sstevel@tonic-gate slot_object_t *slot_object = NULL; 5184a5b2e70Shaimay int threshold = 0; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate boolean_t shutdown, finished_normally; 5217c478bd9Sstevel@tonic-gate 5224a5b2e70Shaimay /* 5234a5b2e70Shaimay * We've deferred the init for encrypt, decrypt and digest 5244a5b2e70Shaimay * operations. As we know the size of the input data now, we 5254a5b2e70Shaimay * can decide where to perform the real init operation based 5264a5b2e70Shaimay * on the kernel cipher-specific thresholds for certain 5274a5b2e70Shaimay * supported mechanisms. 5284a5b2e70Shaimay */ 5294a5b2e70Shaimay if ((optype == CKF_ENCRYPT) || (optype == CKF_DECRYPT) || 5304a5b2e70Shaimay (optype == CKF_DIGEST)) { 5314a5b2e70Shaimay if (Tmp_GetThreshold != NULL) { 5324a5b2e70Shaimay if (!session->init.app) { 5334a5b2e70Shaimay return (CKR_OPERATION_NOT_INITIALIZED); 5344a5b2e70Shaimay } 535a039cd31Shaimay threshold = meta_GetThreshold( 5364a5b2e70Shaimay session->init.pMech->mechanism); 5374a5b2e70Shaimay } 5384a5b2e70Shaimay 539cd7d5fafSJan Pechanec if ((threshold_chk_enabled == B_FALSE) || (inLen > threshold)) { 5404a5b2e70Shaimay if ((session->init.app) && (!session->init.done)) { 5414a5b2e70Shaimay /* 5424a5b2e70Shaimay * Call real init operation only if the 5434a5b2e70Shaimay * application has called C_xxxInit 5444a5b2e70Shaimay * but the real init operation has not 5454a5b2e70Shaimay * been done. 5464a5b2e70Shaimay */ 5474a5b2e70Shaimay rv = meta_operation_init(optype, 5484a5b2e70Shaimay session->init.session, 5494a5b2e70Shaimay session->init.pMech, 5504a5b2e70Shaimay session->init.key); 5514a5b2e70Shaimay if (rv != CKR_OK) 5524a5b2e70Shaimay goto exit; 5534a5b2e70Shaimay } else if (!session->init.app) { 5544a5b2e70Shaimay /* 5554a5b2e70Shaimay * This checking detects the case that 5564a5b2e70Shaimay * application calls C_En(De)Crypt/Digest 5574a5b2e70Shaimay * directly without calling C_xxxInit. 5584a5b2e70Shaimay */ 5594a5b2e70Shaimay return (CKR_OPERATION_NOT_INITIALIZED); 5604a5b2e70Shaimay } 5614a5b2e70Shaimay } else { 5624a5b2e70Shaimay /* 5634a5b2e70Shaimay * The size of the input data is smaller than the 5644a5b2e70Shaimay * threshold so we'll use softoken to perform the 5654a5b2e70Shaimay * crypto operation for better performance reason. 5664a5b2e70Shaimay */ 5674a5b2e70Shaimay if ((session->init.app) && (!session->init.done)) { 5684a5b2e70Shaimay /* 5694a5b2e70Shaimay * Call real init operation only if the 5704a5b2e70Shaimay * application has called C_xxxInit 5714a5b2e70Shaimay * but the real init operation has not 5724a5b2e70Shaimay * been done. 5734a5b2e70Shaimay */ 5744a5b2e70Shaimay rv = meta_operation_init_softtoken(optype, 5754a5b2e70Shaimay session->init.session, 5764a5b2e70Shaimay session->init.pMech, 5774a5b2e70Shaimay session->init.key); 5784a5b2e70Shaimay if (rv != CKR_OK) { 5794a5b2e70Shaimay /* 5804a5b2e70Shaimay * In case the operation fails in 5814a5b2e70Shaimay * softtoken, go back to use the 5824a5b2e70Shaimay * original slot again. 5834a5b2e70Shaimay */ 5844a5b2e70Shaimay rv = meta_operation_init(optype, 5854a5b2e70Shaimay session->init.session, 5864a5b2e70Shaimay session->init.pMech, 5874a5b2e70Shaimay session->init.key); 5884a5b2e70Shaimay if (rv != CKR_OK) 5894a5b2e70Shaimay goto exit; 5904a5b2e70Shaimay } 5914a5b2e70Shaimay } else if (!session->init.app) { 5924a5b2e70Shaimay /* 5934a5b2e70Shaimay * This checking detects the case that 5944a5b2e70Shaimay * application calls C_En(De)Crypt/Digest 5954a5b2e70Shaimay * directly without calling C_xxxInit. 5964a5b2e70Shaimay */ 5974a5b2e70Shaimay return (CKR_OPERATION_NOT_INITIALIZED); 5984a5b2e70Shaimay } 5994a5b2e70Shaimay } 6004a5b2e70Shaimay } else if (optype != session->op1.type) { 6017c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate slot_session = session->op1.session; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate if (slot_session) { 6077c478bd9Sstevel@tonic-gate hSession = slot_session->hSession; 6087c478bd9Sstevel@tonic-gate fw_st_id = slot_session->fw_st_id; 6097c478bd9Sstevel@tonic-gate } else { 6107c478bd9Sstevel@tonic-gate /* should never be here */ 6114a5b2e70Shaimay rv = CKR_FUNCTION_FAILED; 6124a5b2e70Shaimay goto exit; 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* Do the operation... */ 616d3a28a55Sdinak if (optype == CKF_ENCRYPT && mode == MODE_SINGLE) { 6177c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_Encrypt(hSession, in, 6187c478bd9Sstevel@tonic-gate inLen, out, outLen); 619d3a28a55Sdinak } else if (optype == CKF_ENCRYPT && mode == MODE_UPDATE) { 6207c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_EncryptUpdate(hSession, in, 6217c478bd9Sstevel@tonic-gate inLen, out, outLen); 622d3a28a55Sdinak } else if (optype == CKF_ENCRYPT && mode == MODE_FINAL) { 6237c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_EncryptFinal(hSession, out, 6247c478bd9Sstevel@tonic-gate outLen); 6257c478bd9Sstevel@tonic-gate 626d3a28a55Sdinak } else if (optype == CKF_DECRYPT && mode == MODE_SINGLE) { 6277c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_Decrypt(hSession, in, 6287c478bd9Sstevel@tonic-gate inLen, out, outLen); 629d3a28a55Sdinak } else if (optype == CKF_DECRYPT && mode == MODE_UPDATE) { 6307c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DecryptUpdate(hSession, in, 6317c478bd9Sstevel@tonic-gate inLen, out, outLen); 632d3a28a55Sdinak } else if (optype == CKF_DECRYPT && mode == MODE_FINAL) { 6337c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DecryptFinal(hSession, out, 6347c478bd9Sstevel@tonic-gate outLen); 6357c478bd9Sstevel@tonic-gate 636d3a28a55Sdinak } else if (optype == CKF_DIGEST && mode == MODE_SINGLE) { 6377c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_Digest(hSession, in, inLen, 6387c478bd9Sstevel@tonic-gate out, outLen); 639d3a28a55Sdinak } else if (optype == CKF_DIGEST && mode == MODE_UPDATE) { 6407c478bd9Sstevel@tonic-gate /* noOutputForOp = TRUE; */ 6417c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DigestUpdate(hSession, in, 6427c478bd9Sstevel@tonic-gate inLen); 643d3a28a55Sdinak } else if (optype == CKF_DIGEST && mode == MODE_UPDATE_WITHKEY) { 6447c478bd9Sstevel@tonic-gate /* noOutputForOp = TRUE; */ 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * For C_DigestKey, a key is provided and 6477c478bd9Sstevel@tonic-gate * we need the clone. 6487c478bd9Sstevel@tonic-gate */ 6497c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(object, 6507c478bd9Sstevel@tonic-gate slot_session->slotnum, slot_session, &slot_object); 6517c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 6527c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DigestKey(hSession, 6537c478bd9Sstevel@tonic-gate slot_object->hObject); 654d3a28a55Sdinak } else if (optype == CKF_DIGEST && mode == MODE_FINAL) { 6557c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_DigestFinal(hSession, out, 6567c478bd9Sstevel@tonic-gate outLen); 6577c478bd9Sstevel@tonic-gate 658d3a28a55Sdinak } else if (optype == CKF_SIGN && mode == MODE_SINGLE) { 6597c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_Sign(hSession, in, inLen, 6607c478bd9Sstevel@tonic-gate out, outLen); 661d3a28a55Sdinak } else if (optype == CKF_SIGN && mode == MODE_UPDATE) { 6627c478bd9Sstevel@tonic-gate /* noOutputForOp = TRUE; */ 6637c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_SignUpdate(hSession, in, 6647c478bd9Sstevel@tonic-gate inLen); 665d3a28a55Sdinak } else if (optype == CKF_SIGN && mode == MODE_FINAL) { 6667c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_SignFinal(hSession, out, 6677c478bd9Sstevel@tonic-gate outLen); 6687c478bd9Sstevel@tonic-gate 669d3a28a55Sdinak } else if (optype == CKF_VERIFY && mode == MODE_SINGLE) { 6707c478bd9Sstevel@tonic-gate /* noOutputForOp = TRUE; */ 6717c478bd9Sstevel@tonic-gate /* Yes, use *outLen not outLen (think in2/in2Len) */ 6727c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_Verify(hSession, in, 6737c478bd9Sstevel@tonic-gate inLen, out, *outLen); 674d3a28a55Sdinak } else if (optype == CKF_VERIFY && mode == MODE_UPDATE) { 6757c478bd9Sstevel@tonic-gate /* noOutputForOp = TRUE; */ 6767c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_VerifyUpdate(hSession, in, 6777c478bd9Sstevel@tonic-gate inLen); 678d3a28a55Sdinak } else if (optype == CKF_VERIFY && mode == MODE_FINAL) { 6797c478bd9Sstevel@tonic-gate /* noOutputForOp = TRUE; */ 6807c478bd9Sstevel@tonic-gate /* Yes, use in/inLen instead of out/outLen */ 6817c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_VerifyFinal(hSession, in, 6827c478bd9Sstevel@tonic-gate inLen); 6837c478bd9Sstevel@tonic-gate 684d3a28a55Sdinak } else if (optype == CKF_SIGN_RECOVER && mode == MODE_SINGLE) { 6857c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_SignRecover(hSession, in, 6867c478bd9Sstevel@tonic-gate inLen, out, outLen); 687d3a28a55Sdinak } else if (optype == CKF_VERIFY_RECOVER && mode == MODE_SINGLE) { 6887c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_VerifyRecover(hSession, in, 6897c478bd9Sstevel@tonic-gate inLen, out, outLen); 6907c478bd9Sstevel@tonic-gate 691d3a28a55Sdinak } else { 6927c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* 6977c478bd9Sstevel@tonic-gate * Mark the operation type as inactive if an abnormal error 6987c478bd9Sstevel@tonic-gate * happens, or if the operation normally results in an inactive 6997c478bd9Sstevel@tonic-gate * operation state. 7007c478bd9Sstevel@tonic-gate * 7017c478bd9Sstevel@tonic-gate * NOTE: The spec isn't very explicit about what happens when you 7027c478bd9Sstevel@tonic-gate * call C_FooFinal (or C_Foo) with a NULL output buffer (to get the 7037c478bd9Sstevel@tonic-gate * output size), but there is no output. Technically this should be 7047c478bd9Sstevel@tonic-gate * no different than the normal case (ie, when there is output), and 7057c478bd9Sstevel@tonic-gate * the operation should remain active until the second call actually 7067c478bd9Sstevel@tonic-gate * terminates it. However, one could make the case that there is no 7077c478bd9Sstevel@tonic-gate * need for a second call, since no data is available. This presents 7087c478bd9Sstevel@tonic-gate * dilemma for metaslot, because we don't know if the operation is 7097c478bd9Sstevel@tonic-gate * going to remain active or not. We will assume a strict reading of 7107c478bd9Sstevel@tonic-gate * the spec, the operation will remain active. 7117c478bd9Sstevel@tonic-gate */ 7124a5b2e70Shaimay exit: 7137c478bd9Sstevel@tonic-gate if (rv == CKR_BUFFER_TOO_SMALL || 714d3a28a55Sdinak (rv == CKR_OK && out == NULL && optype != CKF_VERIFY)) { 7157c478bd9Sstevel@tonic-gate /* Leave op active for retry (with larger buffer). */ 7167c478bd9Sstevel@tonic-gate shutdown = B_FALSE; 7177c478bd9Sstevel@tonic-gate } else if (rv != CKR_OK) { 7187c478bd9Sstevel@tonic-gate shutdown = B_TRUE; 7197c478bd9Sstevel@tonic-gate finished_normally = B_FALSE; 7207c478bd9Sstevel@tonic-gate } else { /* CKR_OK */ 7217c478bd9Sstevel@tonic-gate if (mode == MODE_SINGLE || mode == MODE_FINAL) { 7227c478bd9Sstevel@tonic-gate shutdown = B_TRUE; 7237c478bd9Sstevel@tonic-gate finished_normally = B_TRUE; 7247c478bd9Sstevel@tonic-gate } else { /* mode == MODE_UPDATE */ 7257c478bd9Sstevel@tonic-gate shutdown = B_FALSE; 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7294a5b2e70Shaimay if (shutdown) { 7304a5b2e70Shaimay if (mode == MODE_SINGLE || mode == MODE_FINAL) { 7314a5b2e70Shaimay session->init.app = B_FALSE; 7324a5b2e70Shaimay } 7334a5b2e70Shaimay 7347c478bd9Sstevel@tonic-gate meta_operation_cleanup(session, optype, finished_normally); 7354a5b2e70Shaimay } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate return (rv); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7404a5b2e70Shaimay void 7414a5b2e70Shaimay free_session_mechanism(meta_session_t *session) 7424a5b2e70Shaimay { 7434a5b2e70Shaimay if (session->init.pMech != NULL) { 7444a5b2e70Shaimay if (session->init.pMech->pParameter != NULL) { 7454a5b2e70Shaimay free(session->init.pMech->pParameter); 7464a5b2e70Shaimay session->init.pMech->pParameter = NULL; 747f2b9e082Shaimay session->init.pMech->ulParameterLen = 0; 7484a5b2e70Shaimay } 7494a5b2e70Shaimay free(session->init.pMech); 7504a5b2e70Shaimay session->init.pMech = NULL; 7514a5b2e70Shaimay } 7524a5b2e70Shaimay } 7534a5b2e70Shaimay 7547c478bd9Sstevel@tonic-gate /* 7557c478bd9Sstevel@tonic-gate * meta_operation_cleanup 7567c478bd9Sstevel@tonic-gate * 7577c478bd9Sstevel@tonic-gate * Cleans up an operation in the specified session. 7587c478bd9Sstevel@tonic-gate * If the operation did not finish normally, it will force 7597c478bd9Sstevel@tonic-gate * the operation to terminate. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate void 762d3a28a55Sdinak meta_operation_cleanup(meta_session_t *session, CK_FLAGS optype, 7637c478bd9Sstevel@tonic-gate boolean_t finished_normally) 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate operation_info_t *op; 7667c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE hSession; 7677c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id; 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate if (!finished_normally) { 7707c478bd9Sstevel@tonic-gate CK_BYTE dummy_buf[8]; 7717c478bd9Sstevel@tonic-gate 7724a5b2e70Shaimay if (session->op1.type == optype) { 7737c478bd9Sstevel@tonic-gate op = &session->op1; 7744a5b2e70Shaimay } else { 7754a5b2e70Shaimay if ((optype == CKF_ENCRYPT) || 7764a5b2e70Shaimay (optype == CKF_DECRYPT) || 7774a5b2e70Shaimay (optype == CKF_DIGEST)) { 7784a5b2e70Shaimay session->op1.type = 0; 7794a5b2e70Shaimay session->init.app = B_FALSE; 7804a5b2e70Shaimay session->init.done = B_FALSE; 7814a5b2e70Shaimay free_session_mechanism(session); 7824a5b2e70Shaimay } 7837c478bd9Sstevel@tonic-gate return; 7844a5b2e70Shaimay } 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate hSession = op->session->hSession; 7877c478bd9Sstevel@tonic-gate fw_st_id = op->session->fw_st_id; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate /* 7907c478bd9Sstevel@tonic-gate * There's no simple, reliable way to abort an 7917c478bd9Sstevel@tonic-gate * operation. So, we'll force the operation to finish. 7927c478bd9Sstevel@tonic-gate * 7937c478bd9Sstevel@tonic-gate * We are here either because we need to abort either after 7947c478bd9Sstevel@tonic-gate * C_xxxxxInit() or C_xxxxxUpdate(). 7957c478bd9Sstevel@tonic-gate * 7967c478bd9Sstevel@tonic-gate * We will call C_xxxxxUpdate() with invalid argument to 7977c478bd9Sstevel@tonic-gate * force the operation to abort. According to the PKCS#11 7987c478bd9Sstevel@tonic-gate * spec, any call to C_xxxxxUpdate() returns in an error 7997c478bd9Sstevel@tonic-gate * will terminate the current operation. 8007c478bd9Sstevel@tonic-gate */ 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate switch (optype) { 803d3a28a55Sdinak case CKF_ENCRYPT: 8047c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_EncryptUpdate(hSession, 8057c478bd9Sstevel@tonic-gate NULL, 8, dummy_buf, NULL); 8067c478bd9Sstevel@tonic-gate break; 807d3a28a55Sdinak case CKF_DECRYPT: 8087c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_DecryptUpdate(hSession, 8097c478bd9Sstevel@tonic-gate NULL, 8, dummy_buf, NULL); 8107c478bd9Sstevel@tonic-gate break; 811d3a28a55Sdinak case CKF_DIGEST: 8127c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_DigestUpdate(hSession, 8137c478bd9Sstevel@tonic-gate NULL, 8); 8147c478bd9Sstevel@tonic-gate break; 815d3a28a55Sdinak case CKF_SIGN: 8167c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_SignUpdate(hSession, 8177c478bd9Sstevel@tonic-gate NULL, 8); 8187c478bd9Sstevel@tonic-gate break; 819d3a28a55Sdinak case CKF_SIGN_RECOVER: 8207c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_SignRecover(hSession, 8217c478bd9Sstevel@tonic-gate NULL, 8, dummy_buf, NULL); 8227c478bd9Sstevel@tonic-gate break; 823d3a28a55Sdinak case CKF_VERIFY: 8247c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_VerifyUpdate(hSession, 8257c478bd9Sstevel@tonic-gate NULL, 8); 8267c478bd9Sstevel@tonic-gate break; 827d3a28a55Sdinak case CKF_VERIFY_RECOVER: 8287c478bd9Sstevel@tonic-gate (void) FUNCLIST(fw_st_id)->C_VerifyRecover(hSession, 8297c478bd9Sstevel@tonic-gate NULL, 8, dummy_buf, NULL); 8307c478bd9Sstevel@tonic-gate break; 8317c478bd9Sstevel@tonic-gate default: 8327c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 8337c478bd9Sstevel@tonic-gate break; 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate meta_release_slot_session(session->op1.session); 8367c478bd9Sstevel@tonic-gate session->op1.session = NULL; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8394a5b2e70Shaimay if ((optype == CKF_ENCRYPT) || (optype == CKF_DECRYPT) || 8404a5b2e70Shaimay (optype == CKF_DIGEST)) { 8414a5b2e70Shaimay session->init.done = B_FALSE; 8424a5b2e70Shaimay free_session_mechanism(session); 8434a5b2e70Shaimay } 844d3a28a55Sdinak session->op1.type = 0; 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* 8487c478bd9Sstevel@tonic-gate * Gets the list of slots that supports the specified mechanism. 8497c478bd9Sstevel@tonic-gate * 8507c478bd9Sstevel@tonic-gate * If "token_only", check if the keystore slot supports the specified mech, 8517c478bd9Sstevel@tonic-gate * if so, return that slot only 8527c478bd9Sstevel@tonic-gate * 8537c478bd9Sstevel@tonic-gate * Otherwise, get list of all slots that support the mech. 8547c478bd9Sstevel@tonic-gate * 8557c478bd9Sstevel@tonic-gate */ 8567c478bd9Sstevel@tonic-gate static CK_RV 8577c478bd9Sstevel@tonic-gate get_slotlist_for_mech(CK_MECHANISM_TYPE mech_type, 8587c478bd9Sstevel@tonic-gate mech_support_info_t *mech_support_info, 859d3a28a55Sdinak mechinfo_t ***slots, unsigned long *slot_count, boolean_t token_only, 860d3a28a55Sdinak CK_MECHANISM_INFO *mech_info) 8617c478bd9Sstevel@tonic-gate { 8627c478bd9Sstevel@tonic-gate boolean_t mech_supported = B_FALSE; 8637c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate if (token_only) { 8667c478bd9Sstevel@tonic-gate rv = meta_mechManager_slot_supports_mech(mech_type, 8677c478bd9Sstevel@tonic-gate get_keystore_slotnum(), &mech_supported, 868d3a28a55Sdinak &((mech_support_info->supporting_slots)[0]), B_FALSE, 869d3a28a55Sdinak mech_info); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 8727c478bd9Sstevel@tonic-gate return (rv); 8737c478bd9Sstevel@tonic-gate } 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate if (mech_supported) { 8767c478bd9Sstevel@tonic-gate mech_support_info->mech = mech_type; 8777c478bd9Sstevel@tonic-gate /* 8787c478bd9Sstevel@tonic-gate * Want to leave this at 0, that way, when 8797c478bd9Sstevel@tonic-gate * other operation needs to 8807c478bd9Sstevel@tonic-gate * use this mechanism, but not just for the 8817c478bd9Sstevel@tonic-gate * keystore slot, we will look at other slots 8827c478bd9Sstevel@tonic-gate */ 8837c478bd9Sstevel@tonic-gate mech_support_info->num_supporting_slots = 0; 8847c478bd9Sstevel@tonic-gate *slots = mech_support_info->supporting_slots; 8857c478bd9Sstevel@tonic-gate *slot_count = 1; 8867c478bd9Sstevel@tonic-gate } else { 8877c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate } else { 8907c478bd9Sstevel@tonic-gate /* 8917c478bd9Sstevel@tonic-gate * Get a list of slots that support this mech . 8927c478bd9Sstevel@tonic-gate * 8937c478bd9Sstevel@tonic-gate * If the specified mechanism is used last time, 8947c478bd9Sstevel@tonic-gate * the list of capable slots is already retrieved. 8957c478bd9Sstevel@tonic-gate * We can save some processing, and just use that list of slots. 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate if ((mech_support_info->mech != mech_type) || 8987c478bd9Sstevel@tonic-gate (mech_support_info->num_supporting_slots == 0)) { 8997c478bd9Sstevel@tonic-gate mech_support_info->mech = mech_type; 9007c478bd9Sstevel@tonic-gate rv = meta_mechManager_get_slots(mech_support_info, 901d3a28a55Sdinak B_FALSE, mech_info); 9027c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 9037c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate *slots = mech_support_info->supporting_slots; 9077c478bd9Sstevel@tonic-gate *slot_count = mech_support_info->num_supporting_slots; 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate return (rv); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /* 9137c478bd9Sstevel@tonic-gate * meta_generate_keys 9147c478bd9Sstevel@tonic-gate * 9157c478bd9Sstevel@tonic-gate * Generates symmetric (k1=key, k2=null) or asymmetric (k1=pub, k2=priv) keys. 9167c478bd9Sstevel@tonic-gate * 9177c478bd9Sstevel@tonic-gate */ 9187c478bd9Sstevel@tonic-gate CK_RV 9197c478bd9Sstevel@tonic-gate meta_generate_keys(meta_session_t *session, CK_MECHANISM *pMechanism, 9207c478bd9Sstevel@tonic-gate CK_ATTRIBUTE *k1Template, CK_ULONG k1AttrCount, meta_object_t *key1, 9217c478bd9Sstevel@tonic-gate CK_ATTRIBUTE *k2Template, CK_ULONG k2AttrCount, meta_object_t *key2) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate CK_RV rv, save_rv; 9247c478bd9Sstevel@tonic-gate slot_session_t *gen_session = NULL; 9257c478bd9Sstevel@tonic-gate slot_object_t *slot_key1 = NULL, *slot_key2 = NULL; 9267c478bd9Sstevel@tonic-gate mechinfo_t **slots = NULL; 9277c478bd9Sstevel@tonic-gate unsigned long i, slotCount = 0; 9287c478bd9Sstevel@tonic-gate boolean_t doKeyPair = B_FALSE, token_only = B_FALSE; 9297c478bd9Sstevel@tonic-gate CK_ULONG slotnum; 930d3a28a55Sdinak CK_MECHANISM_INFO mech_info; 931034448feSmcpowers /* 932034448feSmcpowers * Since the keygen call is in a loop, it is performance-wise useful 933034448feSmcpowers * to keep track of the token value 934034448feSmcpowers */ 935034448feSmcpowers CK_BBOOL current_token1_value = FALSE, current_token2_value = FALSE; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate (void) get_template_boolean(CKA_TOKEN, k1Template, k1AttrCount, 9387c478bd9Sstevel@tonic-gate &(key1->isToken)); 939034448feSmcpowers (void) get_template_boolean(CKA_SENSITIVE, k1Template, k1AttrCount, 940034448feSmcpowers &(key1->isSensitive)); 941034448feSmcpowers (void) get_template_boolean(CKA_PRIVATE, k1Template, k1AttrCount, 942034448feSmcpowers &(key1->isPrivate)); 943034448feSmcpowers 944034448feSmcpowers if (!get_template_boolean(CKA_EXTRACTABLE, k1Template, k1AttrCount, 945034448feSmcpowers &(key1->isExtractable))) 946034448feSmcpowers key1->isExtractable = B_TRUE; 947034448feSmcpowers 948034448feSmcpowers if (key1->isToken) 949034448feSmcpowers current_token1_value = TRUE; 950034448feSmcpowers 951d3a28a55Sdinak mech_info.flags = CKF_GENERATE; 952d3a28a55Sdinak 9537c478bd9Sstevel@tonic-gate if (key2) { 9547c478bd9Sstevel@tonic-gate (void) get_template_boolean(CKA_TOKEN, k2Template, k2AttrCount, 9557c478bd9Sstevel@tonic-gate &(key2->isToken)); 956034448feSmcpowers (void) get_template_boolean(CKA_SENSITIVE, k2Template, 957034448feSmcpowers k2AttrCount, &(key2->isSensitive)); 958034448feSmcpowers (void) get_template_boolean(CKA_PRIVATE, k2Template, 959034448feSmcpowers k2AttrCount, &(key2->isPrivate)); 960034448feSmcpowers 961034448feSmcpowers if (!get_template_boolean(CKA_EXTRACTABLE, k2Template, 962034448feSmcpowers k2AttrCount, &(key2->isExtractable))) 963034448feSmcpowers key2->isExtractable = B_TRUE; 964034448feSmcpowers 965034448feSmcpowers if (key2->isToken) 966034448feSmcpowers current_token2_value = TRUE; 967034448feSmcpowers 9687c478bd9Sstevel@tonic-gate doKeyPair = B_TRUE; 969d3a28a55Sdinak mech_info.flags = CKF_GENERATE_KEY_PAIR; 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate 972034448feSmcpowers 9737c478bd9Sstevel@tonic-gate /* Can't create token objects in a read-only session. */ 9747c478bd9Sstevel@tonic-gate if ((IS_READ_ONLY_SESSION(session->session_flags)) && 9757c478bd9Sstevel@tonic-gate ((key1->isToken) || ((key2) && (key2->isToken)))) { 9767c478bd9Sstevel@tonic-gate return (CKR_SESSION_READ_ONLY); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 979034448feSmcpowers if (meta_freeobject_check(session, key1, pMechanism, k1Template, 980034448feSmcpowers k1AttrCount, NULL)) { 981034448feSmcpowers 982034448feSmcpowers if ((key1->isPrivate || (doKeyPair && key2->isPrivate)) && 983034448feSmcpowers !metaslot_logged_in()) 984034448feSmcpowers return (CKR_USER_NOT_LOGGED_IN); 985034448feSmcpowers 986034448feSmcpowers if (!meta_freeobject_set(key1, k1Template, k1AttrCount, 987034448feSmcpowers B_FALSE)) 988034448feSmcpowers return (CKR_FUNCTION_FAILED); 989034448feSmcpowers 990034448feSmcpowers if (doKeyPair) { 991034448feSmcpowers key2->isFreeObject = FREE_ALLOWED_KEY; 992034448feSmcpowers if (!meta_freeobject_set(key2, k2Template, k2AttrCount, 993034448feSmcpowers B_FALSE)) 994034448feSmcpowers return (CKR_FUNCTION_FAILED); 995034448feSmcpowers } 996034448feSmcpowers 997034448feSmcpowers } else if (doKeyPair) { 998034448feSmcpowers /* 999034448feSmcpowers * If this is a keypair operation, the second key cannot be 1000034448feSmcpowers * a FreeObject if the first is not. Both keys will have the 1001034448feSmcpowers * same fate when it comes to provider choices 1002034448feSmcpowers */ 1003034448feSmcpowers key2->isFreeObject = FREE_DISABLED; 1004034448feSmcpowers key2->isFreeToken = FREE_DISABLED; 1005034448feSmcpowers } 1006034448feSmcpowers 10077c478bd9Sstevel@tonic-gate if ((key1->isToken) || ((doKeyPair) && (key2->isToken))) { 10087c478bd9Sstevel@tonic-gate /* 10097c478bd9Sstevel@tonic-gate * Token objects can only be generated in the token object 10107c478bd9Sstevel@tonic-gate * slot. If token object slot doesn't support generating 1011034448feSmcpowers * the key, it will just not be done. 10127c478bd9Sstevel@tonic-gate */ 10137c478bd9Sstevel@tonic-gate token_only = B_TRUE; 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate rv = get_slotlist_for_mech(pMechanism->mechanism, 1017d3a28a55Sdinak &(session->mech_support_info), &slots, &slotCount, token_only, 1018d3a28a55Sdinak &mech_info); 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 10217c478bd9Sstevel@tonic-gate goto finish; 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slot_key1); 10257c478bd9Sstevel@tonic-gate if (doKeyPair && rv == CKR_OK) 10267c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slot_key2); 10277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 10287c478bd9Sstevel@tonic-gate goto finish; 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate /* Attempt to generate key on slots until one succeeds. */ 10317c478bd9Sstevel@tonic-gate for (i = 0; i < slotCount; i++) { 10327c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE hSession; 10337c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id; 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate gen_session = NULL; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate slotnum = slots[i]->slotnum; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate if (session->op1.session != NULL) { 10407c478bd9Sstevel@tonic-gate if ((session->op1.session)->slotnum == slotnum) { 10417c478bd9Sstevel@tonic-gate gen_session = session->op1.session; 10427c478bd9Sstevel@tonic-gate /* 10437c478bd9Sstevel@tonic-gate * set it to NULL for now, assign it to 10447c478bd9Sstevel@tonic-gate * gen_session again if it is successful 10457c478bd9Sstevel@tonic-gate */ 10467c478bd9Sstevel@tonic-gate session->op1.session = NULL; 10477c478bd9Sstevel@tonic-gate } else { 10487c478bd9Sstevel@tonic-gate gen_session = NULL; 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate } 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if (gen_session == NULL) { 10537c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(slotnum, &gen_session, 10547c478bd9Sstevel@tonic-gate session->session_flags); 10557c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 10567c478bd9Sstevel@tonic-gate goto loop_cleanup; 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate 1060034448feSmcpowers /* 1061034448feSmcpowers * If this is a freetoken, make sure the templates are 1062034448feSmcpowers * approriate for the slot being used. 1063034448feSmcpowers */ 1064034448feSmcpowers if (key1->isFreeToken == FREE_ENABLED) { 1065034448feSmcpowers rv = meta_freetoken_set(slotnum, 1066034448feSmcpowers ¤t_token1_value, k1Template, k1AttrCount); 1067034448feSmcpowers if (rv != CKR_OK) 1068034448feSmcpowers goto loop_cleanup; 1069034448feSmcpowers } 1070034448feSmcpowers 1071034448feSmcpowers if (doKeyPair && key2->isFreeToken == FREE_ENABLED) { 1072034448feSmcpowers rv = meta_freetoken_set(slotnum, 1073034448feSmcpowers ¤t_token2_value, k2Template, k2AttrCount); 1074034448feSmcpowers if (rv != CKR_OK) 1075034448feSmcpowers goto loop_cleanup; 1076034448feSmcpowers } 1077034448feSmcpowers 10787c478bd9Sstevel@tonic-gate fw_st_id = gen_session->fw_st_id; 10797c478bd9Sstevel@tonic-gate hSession = gen_session->hSession; 1080034448feSmcpowers 10817c478bd9Sstevel@tonic-gate if (doKeyPair) { 10827c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GenerateKeyPair(hSession, 10837c478bd9Sstevel@tonic-gate pMechanism, k1Template, k1AttrCount, 10847c478bd9Sstevel@tonic-gate k2Template, k2AttrCount, 10857c478bd9Sstevel@tonic-gate &slot_key1->hObject, &slot_key2->hObject); 10867c478bd9Sstevel@tonic-gate } else { 10877c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GenerateKey(hSession, 10887c478bd9Sstevel@tonic-gate pMechanism, k1Template, k1AttrCount, 10897c478bd9Sstevel@tonic-gate &slot_key1->hObject); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 10937c478bd9Sstevel@tonic-gate break; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate loop_cleanup: 10967c478bd9Sstevel@tonic-gate if (i == 0) { 10977c478bd9Sstevel@tonic-gate save_rv = rv; 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate if (gen_session) { 11017c478bd9Sstevel@tonic-gate meta_release_slot_session(gen_session); 11027c478bd9Sstevel@tonic-gate gen_session = NULL; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 11067c478bd9Sstevel@tonic-gate rv = save_rv; 11077c478bd9Sstevel@tonic-gate goto finish; 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(gen_session, slot_key1->hObject, key1); 11117c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 11127c478bd9Sstevel@tonic-gate goto finish; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate if (key2) { 11167c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(gen_session, slot_key2->hObject, 11177c478bd9Sstevel@tonic-gate key2); 11187c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 11197c478bd9Sstevel@tonic-gate goto finish; 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 1123*8cae6764SAnthony Scarpino /* Allow FreeToken to activate onto token obj list */ 1124*8cae6764SAnthony Scarpino if (key1->isFreeToken == FREE_ENABLED) 1125*8cae6764SAnthony Scarpino key1->isToken = B_TRUE; 1126*8cae6764SAnthony Scarpino 11277c478bd9Sstevel@tonic-gate meta_slot_object_activate(slot_key1, gen_session, key1->isToken); 11287c478bd9Sstevel@tonic-gate key1->clones[slotnum] = slot_key1; 11297c478bd9Sstevel@tonic-gate key1->master_clone_slotnum = slotnum; 11307c478bd9Sstevel@tonic-gate slot_key1 = NULL; 1131034448feSmcpowers if (key1->isFreeObject == FREE_ENABLED) { 1132034448feSmcpowers rv = meta_freeobject_clone(session, key1); 1133034448feSmcpowers if (rv != CKR_OK) 1134034448feSmcpowers goto finish; 1135034448feSmcpowers } 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate if (doKeyPair) { 1138*8cae6764SAnthony Scarpino /* Allow FreeToken to activate onto token obj list */ 1139*8cae6764SAnthony Scarpino if (key2->isFreeToken == FREE_ENABLED) 1140*8cae6764SAnthony Scarpino key2->isToken = B_TRUE; 1141*8cae6764SAnthony Scarpino 11427c478bd9Sstevel@tonic-gate meta_slot_object_activate(slot_key2, gen_session, 11437c478bd9Sstevel@tonic-gate key2->isToken); 11447c478bd9Sstevel@tonic-gate key2->clones[slotnum] = slot_key2; 11457c478bd9Sstevel@tonic-gate key2->master_clone_slotnum = slotnum; 11467c478bd9Sstevel@tonic-gate slot_key2 = NULL; 1147034448feSmcpowers if (key2->isFreeObject == FREE_ENABLED) { 1148034448feSmcpowers rv = meta_freeobject_clone(session, key2); 1149034448feSmcpowers if (rv != CKR_OK) 1150034448feSmcpowers goto finish; 1151034448feSmcpowers } 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate finish: 11557c478bd9Sstevel@tonic-gate if (slot_key1) { 11567c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slot_key1); 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate if (slot_key2) { 11607c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slot_key2); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate /* Save the session in case it can be used later */ 11647c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 11657c478bd9Sstevel@tonic-gate /* 11667c478bd9Sstevel@tonic-gate * If currently stored session is not the one being in use now, 11677c478bd9Sstevel@tonic-gate * release the previous one and store the current one 11687c478bd9Sstevel@tonic-gate */ 11697c478bd9Sstevel@tonic-gate if ((session->op1.session) && 11707c478bd9Sstevel@tonic-gate (session->op1.session != gen_session)) { 11717c478bd9Sstevel@tonic-gate meta_release_slot_session(session->op1.session); 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate /* Save the session */ 11757c478bd9Sstevel@tonic-gate session->op1.session = gen_session; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate return (rv); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate /* 11837c478bd9Sstevel@tonic-gate * meta_wrap_key 11847c478bd9Sstevel@tonic-gate * 11857c478bd9Sstevel@tonic-gate */ 11867c478bd9Sstevel@tonic-gate CK_RV 11877c478bd9Sstevel@tonic-gate meta_wrap_key(meta_session_t *session, CK_MECHANISM *pMechanism, 11887c478bd9Sstevel@tonic-gate meta_object_t *wrappingkey, meta_object_t *inputkey, CK_BYTE *wrapped_key, 11897c478bd9Sstevel@tonic-gate CK_ULONG *wrapped_key_len) 11907c478bd9Sstevel@tonic-gate { 11917c478bd9Sstevel@tonic-gate CK_RV rv, save_rv; 11927c478bd9Sstevel@tonic-gate slot_session_t *wrap_session = NULL; 11937c478bd9Sstevel@tonic-gate slot_object_t *slot_wrappingkey, *slot_inputkey; 11947c478bd9Sstevel@tonic-gate mechinfo_t **slots = NULL; 11957c478bd9Sstevel@tonic-gate unsigned long i, slotCount = 0; 11967c478bd9Sstevel@tonic-gate CK_ULONG slotnum; 1197d3a28a55Sdinak CK_MECHANISM_INFO mech_info; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate /* 12007c478bd9Sstevel@tonic-gate * If the key to be wrapped is a token object, 12017c478bd9Sstevel@tonic-gate * the operation can only be done in the token object slot. 12027c478bd9Sstevel@tonic-gate */ 1203d3a28a55Sdinak mech_info.flags = CKF_WRAP; 12047c478bd9Sstevel@tonic-gate rv = get_slotlist_for_mech(pMechanism->mechanism, 12057c478bd9Sstevel@tonic-gate &(session->mech_support_info), &slots, &slotCount, 1206d3a28a55Sdinak inputkey->isToken, &mech_info); 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 12097c478bd9Sstevel@tonic-gate return (rv); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* Attempt to wrap key on slots until one succeeds. */ 12137c478bd9Sstevel@tonic-gate for (i = 0; i < slotCount; i++) { 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate slotnum = slots[i]->slotnum; 12167c478bd9Sstevel@tonic-gate wrap_session = NULL; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate if (session->op1.session != NULL) { 12197c478bd9Sstevel@tonic-gate if ((session->op1.session)->slotnum == slotnum) { 12207c478bd9Sstevel@tonic-gate wrap_session = session->op1.session; 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * set it to NULL for now, assign it to 12237c478bd9Sstevel@tonic-gate * wrap_session again if it is successful 12247c478bd9Sstevel@tonic-gate */ 12257c478bd9Sstevel@tonic-gate session->op1.session = NULL; 12267c478bd9Sstevel@tonic-gate } else { 12277c478bd9Sstevel@tonic-gate wrap_session = NULL; 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate if (wrap_session == NULL) { 12327c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(slotnum, &wrap_session, 12337c478bd9Sstevel@tonic-gate session->session_flags); 12347c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 12357c478bd9Sstevel@tonic-gate goto loop_cleanup; 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(wrappingkey, slotnum, 12407c478bd9Sstevel@tonic-gate wrap_session, &slot_wrappingkey); 12417c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 12427c478bd9Sstevel@tonic-gate goto loop_cleanup; 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(inputkey, slotnum, 12457c478bd9Sstevel@tonic-gate wrap_session, &slot_inputkey); 12467c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 12477c478bd9Sstevel@tonic-gate goto loop_cleanup; 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate rv = FUNCLIST(wrap_session->fw_st_id)->C_WrapKey( 12507c478bd9Sstevel@tonic-gate wrap_session->hSession, pMechanism, 12517c478bd9Sstevel@tonic-gate slot_wrappingkey->hObject, slot_inputkey->hObject, 12527c478bd9Sstevel@tonic-gate wrapped_key, wrapped_key_len); 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 12557c478bd9Sstevel@tonic-gate break; 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate loop_cleanup: 12587c478bd9Sstevel@tonic-gate if (i == 0) { 12597c478bd9Sstevel@tonic-gate save_rv = rv; 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate if (wrap_session) { 12637c478bd9Sstevel@tonic-gate meta_release_slot_session(wrap_session); 12647c478bd9Sstevel@tonic-gate wrap_session = NULL; 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 12687c478bd9Sstevel@tonic-gate if (rv != CKR_BUFFER_TOO_SMALL) { 12697c478bd9Sstevel@tonic-gate if (i == slotCount) { 12707c478bd9Sstevel@tonic-gate rv = save_rv; 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate finish: 12767c478bd9Sstevel@tonic-gate /* Save the session in case it can be used later */ 12777c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 12787c478bd9Sstevel@tonic-gate /* 12797c478bd9Sstevel@tonic-gate * If currently stored session is not the one being in use now, 12807c478bd9Sstevel@tonic-gate * release the previous one and store the current one 12817c478bd9Sstevel@tonic-gate */ 12827c478bd9Sstevel@tonic-gate if ((session->op1.session) && 12837c478bd9Sstevel@tonic-gate (session->op1.session != wrap_session)) { 12847c478bd9Sstevel@tonic-gate meta_release_slot_session(session->op1.session); 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate /* Save the session */ 12887c478bd9Sstevel@tonic-gate session->op1.session = wrap_session; 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate return (rv); 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate /* 12967c478bd9Sstevel@tonic-gate * meta_unwrap_key 12977c478bd9Sstevel@tonic-gate * 12987c478bd9Sstevel@tonic-gate */ 12997c478bd9Sstevel@tonic-gate CK_RV 13007c478bd9Sstevel@tonic-gate meta_unwrap_key(meta_session_t *session, 13017c478bd9Sstevel@tonic-gate CK_MECHANISM *pMechanism, meta_object_t *unwrapping_key, 13027c478bd9Sstevel@tonic-gate CK_BYTE *wrapped_key, CK_ULONG wrapped_key_len, 13037c478bd9Sstevel@tonic-gate CK_ATTRIBUTE *template, CK_ULONG template_size, 13047c478bd9Sstevel@tonic-gate meta_object_t *unwrapped_key) 13057c478bd9Sstevel@tonic-gate { 13067c478bd9Sstevel@tonic-gate CK_RV rv, save_rv; 13077c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hUnwrappedKey; 13087c478bd9Sstevel@tonic-gate slot_session_t *unwrap_session = NULL; 13097c478bd9Sstevel@tonic-gate slot_object_t *slot_unwrappingkey, *slot_unwrapped_key; 13107c478bd9Sstevel@tonic-gate mechinfo_t **slots = NULL; 13117c478bd9Sstevel@tonic-gate unsigned long i, slotCount = 0; 13127c478bd9Sstevel@tonic-gate CK_ULONG slotnum; 1313d3a28a55Sdinak CK_MECHANISM_INFO mech_info; 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate /* Can't create token objects in a read-only session. */ 13167c478bd9Sstevel@tonic-gate if ((IS_READ_ONLY_SESSION(session->session_flags)) && 13177c478bd9Sstevel@tonic-gate unwrapped_key->isToken) { 13187c478bd9Sstevel@tonic-gate return (CKR_SESSION_READ_ONLY); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate /* 13227c478bd9Sstevel@tonic-gate * If the the resulting unwrapped key 13237c478bd9Sstevel@tonic-gate * needs to be a token object, the operation can only 13247c478bd9Sstevel@tonic-gate * be performed in the token slot, if it is supported. 13257c478bd9Sstevel@tonic-gate */ 1326d3a28a55Sdinak mech_info.flags = CKF_UNWRAP; 13277c478bd9Sstevel@tonic-gate rv = get_slotlist_for_mech(pMechanism->mechanism, 13287c478bd9Sstevel@tonic-gate &(session->mech_support_info), &slots, &slotCount, 1329d3a28a55Sdinak unwrapped_key->isToken, &mech_info); 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 13327c478bd9Sstevel@tonic-gate return (rv); 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slot_unwrapped_key); 13367c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 13377c478bd9Sstevel@tonic-gate goto finish; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate /* Attempt to unwrap key on slots until one succeeds. */ 13417c478bd9Sstevel@tonic-gate for (i = 0; i < slotCount; i++) { 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate slotnum = slots[i]->slotnum; 13447c478bd9Sstevel@tonic-gate unwrap_session = NULL; 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate if (session->op1.session != NULL) { 13477c478bd9Sstevel@tonic-gate if ((session->op1.session)->slotnum == slotnum) { 13487c478bd9Sstevel@tonic-gate unwrap_session = session->op1.session; 13497c478bd9Sstevel@tonic-gate /* 13507c478bd9Sstevel@tonic-gate * set it to NULL for now, assign it to 13517c478bd9Sstevel@tonic-gate * unwrap_session again if it is successful 13527c478bd9Sstevel@tonic-gate */ 13537c478bd9Sstevel@tonic-gate session->op1.session = NULL; 13547c478bd9Sstevel@tonic-gate } else { 13557c478bd9Sstevel@tonic-gate unwrap_session = NULL; 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate if (unwrap_session == NULL) { 13607c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(slotnum, &unwrap_session, 13617c478bd9Sstevel@tonic-gate session->session_flags); 13627c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 13637c478bd9Sstevel@tonic-gate goto loop_cleanup; 13647c478bd9Sstevel@tonic-gate } 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(unwrapping_key, slotnum, 13687c478bd9Sstevel@tonic-gate unwrap_session, &slot_unwrappingkey); 13697c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 13707c478bd9Sstevel@tonic-gate goto loop_cleanup; 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate rv = FUNCLIST(unwrap_session->fw_st_id)->C_UnwrapKey( 13737c478bd9Sstevel@tonic-gate unwrap_session->hSession, pMechanism, 13747c478bd9Sstevel@tonic-gate slot_unwrappingkey->hObject, wrapped_key, wrapped_key_len, 13757c478bd9Sstevel@tonic-gate template, template_size, &hUnwrappedKey); 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 13787c478bd9Sstevel@tonic-gate break; 13797c478bd9Sstevel@tonic-gate loop_cleanup: 13807c478bd9Sstevel@tonic-gate if (i == 0) { 13817c478bd9Sstevel@tonic-gate save_rv = rv; 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate if (unwrap_session) { 13857c478bd9Sstevel@tonic-gate meta_release_slot_session(unwrap_session); 13867c478bd9Sstevel@tonic-gate unwrap_session = NULL; 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 13927c478bd9Sstevel@tonic-gate if (rv != CKR_BUFFER_TOO_SMALL) { 13937c478bd9Sstevel@tonic-gate rv = save_rv; 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate goto finish; 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate slot_unwrapped_key->hObject = hUnwrappedKey; 14007c478bd9Sstevel@tonic-gate unwrapped_key->clones[slotnum] = slot_unwrapped_key; 14017c478bd9Sstevel@tonic-gate unwrapped_key->master_clone_slotnum = slotnum; 14027c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(unwrap_session, 14037c478bd9Sstevel@tonic-gate slot_unwrapped_key->hObject, unwrapped_key); 14047c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 14057c478bd9Sstevel@tonic-gate goto finish; 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate meta_slot_object_activate(slot_unwrapped_key, unwrap_session, 14087c478bd9Sstevel@tonic-gate unwrapped_key->isToken); 14097c478bd9Sstevel@tonic-gate slot_unwrapped_key = NULL; 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate finish: 14127c478bd9Sstevel@tonic-gate if (slot_unwrapped_key) { 14137c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slot_unwrapped_key); 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate /* Save the session in case it can be used later */ 14177c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 14187c478bd9Sstevel@tonic-gate /* 14197c478bd9Sstevel@tonic-gate * If currently stored session is not the one being in use now, 14207c478bd9Sstevel@tonic-gate * release the previous one and store the current one 14217c478bd9Sstevel@tonic-gate */ 14227c478bd9Sstevel@tonic-gate if ((session->op1.session) && 14237c478bd9Sstevel@tonic-gate (session->op1.session != unwrap_session)) { 14247c478bd9Sstevel@tonic-gate meta_release_slot_session(session->op1.session); 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate /* Save the session */ 14287c478bd9Sstevel@tonic-gate session->op1.session = unwrap_session; 14297c478bd9Sstevel@tonic-gate } 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate return (rv); 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate /* 14367c478bd9Sstevel@tonic-gate * meta_derive_key 14377c478bd9Sstevel@tonic-gate * 14387c478bd9Sstevel@tonic-gate * Core implementation for C_DeriveKey. This function is a bit gross because 14397c478bd9Sstevel@tonic-gate * of PKCS#11 kludges that pass extra object handles in the mechanism 14407c478bd9Sstevel@tonic-gate * parameters. Normally C_DeriveKey takes a single existing key as input, 14417c478bd9Sstevel@tonic-gate * and creates a single new key as output. But a few mechanisms take 2 keys 14427c478bd9Sstevel@tonic-gate * as input, and the two SSL/TLS mechanisms create 4 keys as output. 14437c478bd9Sstevel@tonic-gate * 14447c478bd9Sstevel@tonic-gate * When an extra input key (basekey2) is set, we set *phBaseKey2 to the clone's 14457c478bd9Sstevel@tonic-gate * object handle. phBaseKey2 is provided by the caller so we don't have to 14467c478bd9Sstevel@tonic-gate * trudge down into different mechanism parameters to set it when issuing the 14477c478bd9Sstevel@tonic-gate * operation. 14487c478bd9Sstevel@tonic-gate * 14497c478bd9Sstevel@tonic-gate * For the SSL/TLS mechanisms, newKey2/newKey3/newKey4 will be set. We pull 14507c478bd9Sstevel@tonic-gate * the new handles from pMech->pParameter in order to fill in the appropriate 14517c478bd9Sstevel@tonic-gate * meta_object fields. 14527c478bd9Sstevel@tonic-gate */ 14537c478bd9Sstevel@tonic-gate CK_RV 14547c478bd9Sstevel@tonic-gate meta_derive_key(meta_session_t *session, CK_MECHANISM *pMechanism, 14557c478bd9Sstevel@tonic-gate meta_object_t *basekey1, meta_object_t *basekey2, 14567c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE *phBaseKey2, 14577c478bd9Sstevel@tonic-gate CK_ATTRIBUTE *pTemplate, CK_ULONG ulAttributeCount, 14587c478bd9Sstevel@tonic-gate meta_object_t *newKey1, meta_object_t *newKey2, 14597c478bd9Sstevel@tonic-gate meta_object_t *newKey3, meta_object_t *newKey4) 14607c478bd9Sstevel@tonic-gate { 14617c478bd9Sstevel@tonic-gate CK_RV rv, save_rv; 14627c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hDerivedKey; 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate CK_ULONG slotnum; 14657c478bd9Sstevel@tonic-gate boolean_t isSSL = B_FALSE; 146660722cc8Sizick boolean_t isTLSPRF = B_FALSE; 14677c478bd9Sstevel@tonic-gate mechinfo_t **slots = NULL; 14687c478bd9Sstevel@tonic-gate unsigned long i, slot_count = 0; 14697c478bd9Sstevel@tonic-gate slot_session_t *derive_session = NULL; 14707c478bd9Sstevel@tonic-gate slot_object_t *slot_basekey1 = NULL, *slot_basekey2 = NULL; 1471d3a28a55Sdinak slot_object_t *slotkey1 = NULL, *slotkey2 = NULL, *slotkey3 = NULL, 1472d3a28a55Sdinak *slotkey4 = NULL; 1473d3a28a55Sdinak CK_MECHANISM_INFO mech_info; 1474034448feSmcpowers CK_BBOOL current_token_value = FALSE; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate /* 14777c478bd9Sstevel@tonic-gate * if the derived key needs to be a token object, can only 14787c478bd9Sstevel@tonic-gate * perform the derive operation in the token slot 14797c478bd9Sstevel@tonic-gate */ 14807c478bd9Sstevel@tonic-gate (void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount, 14817c478bd9Sstevel@tonic-gate &(newKey1->isToken)); 1482034448feSmcpowers (void) get_template_boolean(CKA_PRIVATE, pTemplate, ulAttributeCount, 1483034448feSmcpowers &(newKey1->isPrivate)); 1484034448feSmcpowers (void) get_template_boolean(CKA_SENSITIVE, pTemplate, ulAttributeCount, 1485034448feSmcpowers &(newKey1->isSensitive)); 1486034448feSmcpowers 1487034448feSmcpowers if (newKey1->isToken) 1488034448feSmcpowers current_token_value = TRUE; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate /* Can't create token objects in a read-only session. */ 14917c478bd9Sstevel@tonic-gate if ((IS_READ_ONLY_SESSION(session->session_flags)) && 14927c478bd9Sstevel@tonic-gate newKey1->isToken) { 14937c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 14947c478bd9Sstevel@tonic-gate goto finish; 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate 1497034448feSmcpowers if (meta_freeobject_check(session, newKey1, pMechanism, pTemplate, 1498034448feSmcpowers ulAttributeCount, NULL)) { 1499034448feSmcpowers 1500034448feSmcpowers if (newKey1->isPrivate && !metaslot_logged_in()) 1501034448feSmcpowers return (CKR_USER_NOT_LOGGED_IN); 1502034448feSmcpowers 1503034448feSmcpowers if (!meta_freeobject_set(newKey1, pTemplate, ulAttributeCount, 1504034448feSmcpowers B_FALSE)) 1505034448feSmcpowers return (CKR_FUNCTION_FAILED); 1506034448feSmcpowers } 1507034448feSmcpowers 1508d3a28a55Sdinak mech_info.flags = CKF_DERIVE; 15097c478bd9Sstevel@tonic-gate rv = get_slotlist_for_mech(pMechanism->mechanism, 15107c478bd9Sstevel@tonic-gate &(session->mech_support_info), &slots, &slot_count, 1511d3a28a55Sdinak newKey1->isToken, &mech_info); 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15147c478bd9Sstevel@tonic-gate return (rv); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate if (pMechanism->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE || 151860722cc8Sizick pMechanism->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE) 15197c478bd9Sstevel@tonic-gate isSSL = B_TRUE; 152060722cc8Sizick 152160722cc8Sizick else if (pMechanism->mechanism == CKM_TLS_PRF) 152260722cc8Sizick isTLSPRF = B_TRUE; 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slotkey1); 15257c478bd9Sstevel@tonic-gate if (isSSL) { 15267c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 15277c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slotkey2); 15287c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 15297c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slotkey3); 15307c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 15317c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&slotkey4); 15327c478bd9Sstevel@tonic-gate } 15337c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15347c478bd9Sstevel@tonic-gate goto finish; 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 15387c478bd9Sstevel@tonic-gate slotnum = slots[i]->slotnum; 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate derive_session = NULL; 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate if (session->op1.session != NULL) { 15437c478bd9Sstevel@tonic-gate if ((session->op1.session)->slotnum == slotnum) { 15447c478bd9Sstevel@tonic-gate derive_session = session->op1.session; 15457c478bd9Sstevel@tonic-gate /* 15467c478bd9Sstevel@tonic-gate * set it to NULL for now, assign it to 15477c478bd9Sstevel@tonic-gate * derive_session again if it is successful 15487c478bd9Sstevel@tonic-gate */ 15497c478bd9Sstevel@tonic-gate session->op1.session = NULL; 15507c478bd9Sstevel@tonic-gate } else { 15517c478bd9Sstevel@tonic-gate derive_session = NULL; 15527c478bd9Sstevel@tonic-gate } 15537c478bd9Sstevel@tonic-gate } 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate if (derive_session == NULL) { 15567c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(slotnum, &derive_session, 15577c478bd9Sstevel@tonic-gate session->session_flags); 15587c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15597c478bd9Sstevel@tonic-gate goto loop_cleanup; 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate } 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(basekey1, slotnum, 15647c478bd9Sstevel@tonic-gate derive_session, &slot_basekey1); 15657c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 15667c478bd9Sstevel@tonic-gate goto loop_cleanup; 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate if (basekey2) { 15697c478bd9Sstevel@tonic-gate rv = meta_object_get_clone(basekey2, slotnum, 15707c478bd9Sstevel@tonic-gate derive_session, &slot_basekey2); 15717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 15727c478bd9Sstevel@tonic-gate goto loop_cleanup; 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate /* Pass the handle somewhere in the mech params. */ 15757c478bd9Sstevel@tonic-gate *phBaseKey2 = slot_basekey2->hObject; 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 1578034448feSmcpowers if (newKey1->isFreeToken == FREE_ENABLED) { 1579034448feSmcpowers rv = meta_freetoken_set(slotnum, ¤t_token_value, 1580034448feSmcpowers pTemplate, ulAttributeCount); 1581034448feSmcpowers if (rv != CKR_OK) 1582034448feSmcpowers goto loop_cleanup; 1583034448feSmcpowers } 1584034448feSmcpowers 15857c478bd9Sstevel@tonic-gate rv = FUNCLIST(derive_session->fw_st_id)->C_DeriveKey( 15867c478bd9Sstevel@tonic-gate derive_session->hSession, pMechanism, 15877c478bd9Sstevel@tonic-gate slot_basekey1->hObject, pTemplate, ulAttributeCount, 158860722cc8Sizick (isSSL || isTLSPRF) ? NULL : &hDerivedKey); 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 15917c478bd9Sstevel@tonic-gate break; 15927c478bd9Sstevel@tonic-gate loop_cleanup: 15937c478bd9Sstevel@tonic-gate if (i == 0) { 15947c478bd9Sstevel@tonic-gate save_rv = rv; 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate if (derive_session) { 15987c478bd9Sstevel@tonic-gate meta_release_slot_session(derive_session); 15997c478bd9Sstevel@tonic-gate derive_session = NULL; 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate /* No need to cleanup clones, so we can reuse them later. */ 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16057c478bd9Sstevel@tonic-gate rv = save_rv; 16067c478bd9Sstevel@tonic-gate goto finish; 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 160960722cc8Sizick if (isTLSPRF) 161060722cc8Sizick goto finish; 161160722cc8Sizick 16127c478bd9Sstevel@tonic-gate /* 16137c478bd9Sstevel@tonic-gate * These SSL/TLS are unique in that the parameter in the API for 16147c478bd9Sstevel@tonic-gate * the new key is unused (NULL). Instead, there are 4 keys which 16157c478bd9Sstevel@tonic-gate * are derived, and are passed back through the mechanism params. 16167c478bd9Sstevel@tonic-gate * Both mechs use the same mechanism parameter type. 16177c478bd9Sstevel@tonic-gate */ 16187c478bd9Sstevel@tonic-gate if (isSSL) { 16197c478bd9Sstevel@tonic-gate CK_SSL3_KEY_MAT_PARAMS *keyparams; 16207c478bd9Sstevel@tonic-gate CK_SSL3_KEY_MAT_OUT *keys; 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate /* NULL checks already done by caller */ 16237c478bd9Sstevel@tonic-gate keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMechanism->pParameter; 16247c478bd9Sstevel@tonic-gate keys = keyparams->pReturnedKeyMaterial; 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate slotkey1->hObject = keys->hClientMacSecret; 16277c478bd9Sstevel@tonic-gate slotkey2->hObject = keys->hServerMacSecret; 16287c478bd9Sstevel@tonic-gate slotkey3->hObject = keys->hClientKey; 16297c478bd9Sstevel@tonic-gate slotkey4->hObject = keys->hServerKey; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(derive_session, 16327c478bd9Sstevel@tonic-gate slotkey1->hObject, newKey1); 16337c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16347c478bd9Sstevel@tonic-gate goto finish; 16357c478bd9Sstevel@tonic-gate } 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(derive_session, 16387c478bd9Sstevel@tonic-gate slotkey2->hObject, newKey2); 16397c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16407c478bd9Sstevel@tonic-gate goto finish; 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(derive_session, 16447c478bd9Sstevel@tonic-gate slotkey3->hObject, newKey3); 16457c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16467c478bd9Sstevel@tonic-gate goto finish; 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(derive_session, 16507c478bd9Sstevel@tonic-gate slotkey4->hObject, newKey4); 16517c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16527c478bd9Sstevel@tonic-gate goto finish; 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate newKey1->clones[slotnum] = slotkey1; 16567c478bd9Sstevel@tonic-gate newKey2->clones[slotnum] = slotkey2; 16577c478bd9Sstevel@tonic-gate newKey3->clones[slotnum] = slotkey3; 16587c478bd9Sstevel@tonic-gate newKey4->clones[slotnum] = slotkey4; 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate newKey1->master_clone_slotnum = slotnum; 16617c478bd9Sstevel@tonic-gate newKey2->master_clone_slotnum = slotnum; 16627c478bd9Sstevel@tonic-gate newKey3->master_clone_slotnum = slotnum; 16637c478bd9Sstevel@tonic-gate newKey4->master_clone_slotnum = slotnum; 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate meta_slot_object_activate(slotkey1, derive_session, 16667c478bd9Sstevel@tonic-gate newKey1->isToken); 16677c478bd9Sstevel@tonic-gate slotkey1 = NULL; 16687c478bd9Sstevel@tonic-gate meta_slot_object_activate(slotkey2, derive_session, 16697c478bd9Sstevel@tonic-gate newKey2->isToken); 16707c478bd9Sstevel@tonic-gate slotkey2 = NULL; 16717c478bd9Sstevel@tonic-gate meta_slot_object_activate(slotkey3, derive_session, 16727c478bd9Sstevel@tonic-gate newKey3->isToken); 16737c478bd9Sstevel@tonic-gate slotkey3 = NULL; 16747c478bd9Sstevel@tonic-gate meta_slot_object_activate(slotkey4, derive_session, 16757c478bd9Sstevel@tonic-gate newKey4->isToken); 16767c478bd9Sstevel@tonic-gate slotkey4 = NULL; 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate } else { 16797c478bd9Sstevel@tonic-gate slotkey1->hObject = hDerivedKey; 16807c478bd9Sstevel@tonic-gate newKey1->clones[slotnum] = slotkey1; 16817c478bd9Sstevel@tonic-gate newKey1->master_clone_slotnum = slotnum; 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate rv = meta_object_get_attr(derive_session, 16847c478bd9Sstevel@tonic-gate slotkey1->hObject, newKey1); 16857c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16867c478bd9Sstevel@tonic-gate goto finish; 16877c478bd9Sstevel@tonic-gate } 1688034448feSmcpowers 1689*8cae6764SAnthony Scarpino /* Allow FreeToken to activate onto token obj list */ 1690*8cae6764SAnthony Scarpino if (newKey1->isFreeToken == FREE_ENABLED) 1691*8cae6764SAnthony Scarpino newKey1->isToken = B_TRUE; 1692*8cae6764SAnthony Scarpino 16937c478bd9Sstevel@tonic-gate meta_slot_object_activate(slotkey1, derive_session, 16947c478bd9Sstevel@tonic-gate newKey1->isToken); 16957c478bd9Sstevel@tonic-gate slotkey1 = NULL; 16967c478bd9Sstevel@tonic-gate } 16977c478bd9Sstevel@tonic-gate 1698034448feSmcpowers if (newKey1->isFreeObject == FREE_ENABLED) 1699034448feSmcpowers (void) meta_freeobject_clone(session, newKey1); 1700034448feSmcpowers 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate finish: 17037c478bd9Sstevel@tonic-gate if (slotkey1) { 17047c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slotkey1); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate if (slotkey2) { 17077c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slotkey2); 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate if (slotkey3) { 17107c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slotkey3); 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate if (slotkey4) { 17137c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slotkey4); 17147c478bd9Sstevel@tonic-gate } 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate /* Save the session in case it can be used later */ 17177c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 17187c478bd9Sstevel@tonic-gate /* 17197c478bd9Sstevel@tonic-gate * If currently stored session is not the one being in use now, 17207c478bd9Sstevel@tonic-gate * release the previous one and store the current one 17217c478bd9Sstevel@tonic-gate */ 17227c478bd9Sstevel@tonic-gate if ((session->op1.session) && 17237c478bd9Sstevel@tonic-gate (session->op1.session != derive_session)) { 17247c478bd9Sstevel@tonic-gate meta_release_slot_session(session->op1.session); 17257c478bd9Sstevel@tonic-gate } 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate /* Save the session */ 17287c478bd9Sstevel@tonic-gate session->op1.session = derive_session; 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate return (rv); 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate /* 17367c478bd9Sstevel@tonic-gate * Check the following 4 environment variables for user/application's 17377c478bd9Sstevel@tonic-gate * configuration for metaslot. User's configuration takes precedence 17387c478bd9Sstevel@tonic-gate * over the system wide configuration for metaslot 17397c478bd9Sstevel@tonic-gate * 17407c478bd9Sstevel@tonic-gate * ${METASLOT_ENABLED} 17417c478bd9Sstevel@tonic-gate * ${METASLOT_OBJECTSTORE_SLOT} 17427c478bd9Sstevel@tonic-gate * ${METASLOT_OBJECTSTORE_TOKEN} 17437c478bd9Sstevel@tonic-gate * ${METASLOT_AUTO_KEY_MIGRATE} 17447c478bd9Sstevel@tonic-gate * 1745cd7d5fafSJan Pechanec * ${_METASLOT_ENABLE_THRESHOLD} - private environmental variable to 1746cd7d5fafSJan Pechanec * enable the treshold checking which is disabled by default. 1747cd7d5fafSJan Pechanec * 17487c478bd9Sstevel@tonic-gate * values defined in these environment variables will be stored in the 1749cd7d5fafSJan Pechanec * global variable "metaslot_config". Variable threshold_chk_disabled is an 1750cd7d5fafSJan Pechanec * exception. 17517c478bd9Sstevel@tonic-gate */ 17527c478bd9Sstevel@tonic-gate void 17537c478bd9Sstevel@tonic-gate get_user_metaslot_config() 17547c478bd9Sstevel@tonic-gate { 17557c478bd9Sstevel@tonic-gate char *env_val = NULL; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate /* 17587c478bd9Sstevel@tonic-gate * Check to see if any environment variable is defined 17597c478bd9Sstevel@tonic-gate * by the user for configuring metaslot. 17607c478bd9Sstevel@tonic-gate */ 17617c478bd9Sstevel@tonic-gate bzero(&metaslot_config, sizeof (metaslot_config)); 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate /* METASLOT_ENABLED */ 17647c478bd9Sstevel@tonic-gate env_val = getenv("METASLOT_ENABLED"); 17657c478bd9Sstevel@tonic-gate if (env_val) { 17667c478bd9Sstevel@tonic-gate metaslot_config.enabled_specified = B_TRUE; 17677c478bd9Sstevel@tonic-gate if (strcasecmp(env_val, TRUE_STRING) == 0) { 17687c478bd9Sstevel@tonic-gate metaslot_config.enabled = B_TRUE; 17697c478bd9Sstevel@tonic-gate } else if (strcasecmp(env_val, FALSE_STRING) == 0) { 17707c478bd9Sstevel@tonic-gate metaslot_config.enabled = B_FALSE; 17717c478bd9Sstevel@tonic-gate } else { 17727c478bd9Sstevel@tonic-gate /* value is neither 1 or 0, ignore this value */ 17737c478bd9Sstevel@tonic-gate metaslot_config.enabled_specified = B_FALSE; 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate /* METASLOT_AUTO_KEY_MIGRATE */ 17787c478bd9Sstevel@tonic-gate env_val = getenv("METASLOT_AUTO_KEY_MIGRATE"); 17797c478bd9Sstevel@tonic-gate if (env_val) { 17807c478bd9Sstevel@tonic-gate metaslot_config.auto_key_migrate_specified = B_TRUE; 17817c478bd9Sstevel@tonic-gate if (strcasecmp(env_val, TRUE_STRING) == 0) { 17827c478bd9Sstevel@tonic-gate metaslot_config.auto_key_migrate = B_TRUE; 17837c478bd9Sstevel@tonic-gate } else if (strcasecmp(env_val, FALSE_STRING) == 0) { 17847c478bd9Sstevel@tonic-gate metaslot_config.auto_key_migrate = B_FALSE; 17857c478bd9Sstevel@tonic-gate } else { 17867c478bd9Sstevel@tonic-gate /* value is neither 1 or 0, ignore this value */ 17877c478bd9Sstevel@tonic-gate metaslot_config.auto_key_migrate_specified = B_FALSE; 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate } 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate /* METASLOT_OBJECTSTORE_SLOT */ 17927c478bd9Sstevel@tonic-gate env_val = getenv("METASLOT_OBJECTSTORE_SLOT"); 17937c478bd9Sstevel@tonic-gate if (env_val) { 17947c478bd9Sstevel@tonic-gate metaslot_config.keystore_slot_specified = B_TRUE; 17957c478bd9Sstevel@tonic-gate (void) strlcpy((char *)metaslot_config.keystore_slot, env_val, 17967c478bd9Sstevel@tonic-gate SLOT_DESCRIPTION_SIZE); 17977c478bd9Sstevel@tonic-gate } 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate /* METASLOT_OBJECTSTORE_TOKEN */ 18007c478bd9Sstevel@tonic-gate env_val = getenv("METASLOT_OBJECTSTORE_TOKEN"); 18017c478bd9Sstevel@tonic-gate if (env_val) { 18027c478bd9Sstevel@tonic-gate metaslot_config.keystore_token_specified = B_TRUE; 18037c478bd9Sstevel@tonic-gate (void) strlcpy((char *)metaslot_config.keystore_token, env_val, 18047c478bd9Sstevel@tonic-gate TOKEN_LABEL_SIZE); 18057c478bd9Sstevel@tonic-gate } 1806cd7d5fafSJan Pechanec 1807cd7d5fafSJan Pechanec /* _METASLOT_ENABLE_THRESHOLD */ 1808cd7d5fafSJan Pechanec env_val = getenv("_METASLOT_ENABLE_THRESHOLD"); 1809cd7d5fafSJan Pechanec if (env_val) { 1810cd7d5fafSJan Pechanec threshold_chk_enabled = B_TRUE; 1811cd7d5fafSJan Pechanec } 18127c478bd9Sstevel@tonic-gate } 1813