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
kernel_get_slot_number()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
_SUNW_GetThreshold(void * thresholdp)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
kernel_get_func_list(kernel_slot_t * pslot)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
kernel_slottable_init()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