xref: /titanic_41/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelSlottable.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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