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 5ba5f469cSkrishna * Common Development and Distribution License (the "License"). 6ba5f469cSkrishna * 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*e8ab7b17SZdenek Kotala * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <errno.h> 267c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 27*e8ab7b17SZdenek Kotala #include <strings.h> 287c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 297c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 307c478bd9Sstevel@tonic-gate #include "kernelSlot.h" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate CK_ULONG slot_count = 0; 337c478bd9Sstevel@tonic-gate kernel_slot_t **slot_table; 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate static CK_RV 367c478bd9Sstevel@tonic-gate kernel_get_slot_number() 377c478bd9Sstevel@tonic-gate { 387c478bd9Sstevel@tonic-gate CK_RV rv; 397c478bd9Sstevel@tonic-gate crypto_get_provider_list_t *pl; 407c478bd9Sstevel@tonic-gate int r; 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate pl = malloc(sizeof (crypto_get_provider_list_t)); 437c478bd9Sstevel@tonic-gate if (pl == NULL) 447c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate pl->pl_count = 0; 477c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 487c478bd9Sstevel@tonic-gate if (errno != EINTR) 497c478bd9Sstevel@tonic-gate break; 507c478bd9Sstevel@tonic-gate } 517c478bd9Sstevel@tonic-gate if (r < 0) { 527c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 537c478bd9Sstevel@tonic-gate } else { 547c478bd9Sstevel@tonic-gate if (pl->pl_return_value != CRYPTO_SUCCESS) { 557c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(pl->pl_return_value); 567c478bd9Sstevel@tonic-gate } else { 577c478bd9Sstevel@tonic-gate rv = CKR_OK; 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate } 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 627c478bd9Sstevel@tonic-gate slot_count = pl->pl_count; 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate (void) free(pl); 667c478bd9Sstevel@tonic-gate return (rv); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 704a5b2e70Shaimay * This function will be used by metaslot to get the kernel 71a039cd31Shaimay * provider's threshold value for the supported mechanisms. 724a5b2e70Shaimay */ 73a039cd31Shaimay void 74a039cd31Shaimay _SUNW_GetThreshold(void *thresholdp) 754a5b2e70Shaimay { 764a5b2e70Shaimay 77a039cd31Shaimay cipher_mechs_threshold_t *tp = (cipher_mechs_threshold_t *)thresholdp; 784a5b2e70Shaimay kernel_slot_t *pslot; 794a5b2e70Shaimay int i; 804a5b2e70Shaimay 814a5b2e70Shaimay /* 824a5b2e70Shaimay * We alway use the 1st slot in the kernel to 834a5b2e70Shaimay * get the threshold because all the kernel 844a5b2e70Shaimay * slots will have the same threshold value 854a5b2e70Shaimay * with the same mechanism. 864a5b2e70Shaimay */ 874a5b2e70Shaimay pslot = slot_table[0]; 884a5b2e70Shaimay 894a5b2e70Shaimay for (i = 0; i < pslot->total_threshold_count; i++) { 90a039cd31Shaimay tp[i].mech_type = 91a039cd31Shaimay pslot->sl_mechs_threshold[i].mech_type; 92a039cd31Shaimay tp[i].mech_threshold = 93a039cd31Shaimay pslot->sl_mechs_threshold[i].mech_threshold; 944a5b2e70Shaimay } 954a5b2e70Shaimay } 964a5b2e70Shaimay 974a5b2e70Shaimay /* 987c478bd9Sstevel@tonic-gate * To retrieve the crypto_function_list structure with boolean entries 997c478bd9Sstevel@tonic-gate * indicating which functions are supported by the hardware provider which 1007c478bd9Sstevel@tonic-gate * is specified by the slot ID. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate static CK_RV 1037c478bd9Sstevel@tonic-gate kernel_get_func_list(kernel_slot_t *pslot) 1047c478bd9Sstevel@tonic-gate { 1057c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 1067c478bd9Sstevel@tonic-gate crypto_get_function_list_t fl; 1077c478bd9Sstevel@tonic-gate int r; 1084a5b2e70Shaimay int i; 1097c478bd9Sstevel@tonic-gate 110*e8ab7b17SZdenek Kotala (void) memset(&fl, 0, sizeof (fl)); 1117c478bd9Sstevel@tonic-gate fl.fl_provider_id = pslot->sl_provider_id; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) { 1147c478bd9Sstevel@tonic-gate if (errno != EINTR) 1157c478bd9Sstevel@tonic-gate break; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate if (r < 0) { 1187c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 1197c478bd9Sstevel@tonic-gate } else { 1207c478bd9Sstevel@tonic-gate if (fl.fl_return_value == 0) { 1217c478bd9Sstevel@tonic-gate rv = CKR_OK; 1227c478bd9Sstevel@tonic-gate } else { 1237c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(fl.fl_return_value); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1287c478bd9Sstevel@tonic-gate return (rv); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 131*e8ab7b17SZdenek Kotala /* copy data structure received from kernel */ 132*e8ab7b17SZdenek Kotala pslot->sl_func_list = fl.fl_list; 1337c478bd9Sstevel@tonic-gate 134ba5f469cSkrishna pslot->sl_flags = 0; 1354df55fdeSJanie Lu if (fl.fl_list.prov_is_hash_limited) { 1364df55fdeSJanie Lu pslot->sl_flags |= CRYPTO_LIMITED_HASH_SUPPORT; 1374df55fdeSJanie Lu pslot->sl_hash_max_inlen = fl.fl_list.prov_hash_limit; 1384df55fdeSJanie Lu } 1394df55fdeSJanie Lu 1404df55fdeSJanie Lu if (fl.fl_list.prov_is_hmac_limited) { 1414df55fdeSJanie Lu pslot->sl_flags |= CRYPTO_LIMITED_HMAC_SUPPORT; 1424df55fdeSJanie Lu pslot->sl_hmac_max_inlen = fl.fl_list.prov_hmac_limit; 1434df55fdeSJanie Lu } 1444df55fdeSJanie Lu 1454df55fdeSJanie Lu if (fl.fl_list.prov_is_hash_limited | fl.fl_list.prov_is_hmac_limited) { 146ba5f469cSkrishna pslot->sl_threshold = fl.fl_list.prov_hash_threshold; 147ba5f469cSkrishna } 148ba5f469cSkrishna 1494a5b2e70Shaimay pslot->total_threshold_count = fl.fl_list.total_threshold_count; 1504a5b2e70Shaimay 1514a5b2e70Shaimay for (i = 0; i < pslot->total_threshold_count; i++) { 1524a5b2e70Shaimay pslot->sl_mechs_threshold[i].mech_type = 1534a5b2e70Shaimay fl.fl_list.fl_threshold[i].mech_type; 1544a5b2e70Shaimay pslot->sl_mechs_threshold[i].mech_threshold = 1554a5b2e70Shaimay fl.fl_list.fl_threshold[i].mech_threshold; 1564a5b2e70Shaimay } 1574a5b2e70Shaimay 1587c478bd9Sstevel@tonic-gate return (CKR_OK); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Initialize the slot table. 1637c478bd9Sstevel@tonic-gate * 1647c478bd9Sstevel@tonic-gate * This function is called from C_Initialize() only. Since C_Initialize() 1657c478bd9Sstevel@tonic-gate * holds the global mutex lock, there is no need to acquire another lock 1667c478bd9Sstevel@tonic-gate * in this routine to protect the slot table. 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate CK_RV 1697c478bd9Sstevel@tonic-gate kernel_slottable_init() 1707c478bd9Sstevel@tonic-gate { 1717c478bd9Sstevel@tonic-gate int i, cur_slot_num = 0; 1727c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 1737c478bd9Sstevel@tonic-gate crypto_get_provider_list_t *pl = NULL; 1747c478bd9Sstevel@tonic-gate int r; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* 1777c478bd9Sstevel@tonic-gate * Find out how many slots are presented from kernel hardware 1787c478bd9Sstevel@tonic-gate * providers. If there is no slot presented, just return. 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate rv = kernel_get_slot_number(); 1817c478bd9Sstevel@tonic-gate if (rv != CKR_OK || slot_count == 0) { 1827c478bd9Sstevel@tonic-gate return (rv); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* Allocate space for the slot table */ 1867c478bd9Sstevel@tonic-gate slot_table = malloc(sizeof (kernel_slot_t *) * slot_count); 1877c478bd9Sstevel@tonic-gate if (slot_table == NULL) { 1887c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* For each slot, allocate space and initialize the slot's mutex. */ 1927c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 1937c478bd9Sstevel@tonic-gate slot_table[i] = malloc(sizeof (kernel_slot_t)); 1947c478bd9Sstevel@tonic-gate if (slot_table[i] == NULL) { 1957c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 1967c478bd9Sstevel@tonic-gate goto failed; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate slot_table[i]->sl_sess_list = NULL; 2007c478bd9Sstevel@tonic-gate slot_table[i]->sl_tobj_list = NULL; 2017c478bd9Sstevel@tonic-gate slot_table[i]->sl_state = CKU_PUBLIC; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* Initialize this slot's mutex */ 2047c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) { 2057c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 2067c478bd9Sstevel@tonic-gate (void) free(slot_table[i]); 2077c478bd9Sstevel@tonic-gate goto failed; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate cur_slot_num = i; 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * Get the provider ID for each slot from kernel and save it in the 2157c478bd9Sstevel@tonic-gate * slot table. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate pl = malloc(slot_count * sizeof (crypto_get_provider_list_t)); 2187c478bd9Sstevel@tonic-gate if (pl == NULL) { 2197c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 2207c478bd9Sstevel@tonic-gate goto failed; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate pl->pl_count = slot_count; 2247c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 2257c478bd9Sstevel@tonic-gate if (errno != EINTR) 2267c478bd9Sstevel@tonic-gate break; 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate if (r < 0) { 2297c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 2307c478bd9Sstevel@tonic-gate goto failed; 2317c478bd9Sstevel@tonic-gate } else { 2327c478bd9Sstevel@tonic-gate if (pl->pl_return_value != CRYPTO_SUCCESS) { 2337c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(pl->pl_return_value); 2347c478bd9Sstevel@tonic-gate goto failed; 2357c478bd9Sstevel@tonic-gate } else { 2367c478bd9Sstevel@tonic-gate rv = CKR_OK; 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 2417c478bd9Sstevel@tonic-gate slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * Get the function list for each slot from kernel and save it in 2467c478bd9Sstevel@tonic-gate * the slot table. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 2497c478bd9Sstevel@tonic-gate rv = kernel_get_func_list(slot_table[i]); 2507c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2517c478bd9Sstevel@tonic-gate goto failed; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate (void) free(pl); 2567c478bd9Sstevel@tonic-gate return (CKR_OK); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate failed: 2597c478bd9Sstevel@tonic-gate for (i = 0; i < cur_slot_num; i++) { 2607c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 2617c478bd9Sstevel@tonic-gate (void) free(slot_table[i]); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate (void) free(slot_table); 2657c478bd9Sstevel@tonic-gate (void) free(pl); 2667c478bd9Sstevel@tonic-gate return (rv); 2677c478bd9Sstevel@tonic-gate } 268