10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54072Skrishna  * Common Development and Distribution License (the "License").
64072Skrishna  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12856SZdenek.Kotala@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <errno.h>
260Sstevel@tonic-gate #include <security/cryptoki.h>
27*12856SZdenek.Kotala@Sun.COM #include <strings.h>
280Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
290Sstevel@tonic-gate #include "kernelGlobal.h"
300Sstevel@tonic-gate #include "kernelSlot.h"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate CK_ULONG	slot_count = 0;
330Sstevel@tonic-gate kernel_slot_t	**slot_table;
340Sstevel@tonic-gate 
350Sstevel@tonic-gate static CK_RV
kernel_get_slot_number()360Sstevel@tonic-gate kernel_get_slot_number()
370Sstevel@tonic-gate {
380Sstevel@tonic-gate 	CK_RV rv;
390Sstevel@tonic-gate 	crypto_get_provider_list_t *pl;
400Sstevel@tonic-gate 	int r;
410Sstevel@tonic-gate 
420Sstevel@tonic-gate 	pl = malloc(sizeof (crypto_get_provider_list_t));
430Sstevel@tonic-gate 	if (pl == NULL)
440Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 	pl->pl_count = 0;
470Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) {
480Sstevel@tonic-gate 		if (errno != EINTR)
490Sstevel@tonic-gate 			break;
500Sstevel@tonic-gate 	}
510Sstevel@tonic-gate 	if (r < 0) {
520Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
530Sstevel@tonic-gate 	} else {
540Sstevel@tonic-gate 		if (pl->pl_return_value != CRYPTO_SUCCESS) {
550Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(pl->pl_return_value);
560Sstevel@tonic-gate 		} else {
570Sstevel@tonic-gate 			rv = CKR_OK;
580Sstevel@tonic-gate 		}
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	if (rv == CKR_OK) {
620Sstevel@tonic-gate 		slot_count = pl->pl_count;
630Sstevel@tonic-gate 	}
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 	(void) free(pl);
660Sstevel@tonic-gate 	return (rv);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /*
704841Shaimay  * This function will be used by metaslot to get the kernel
715093Shaimay  * provider's threshold value for the supported mechanisms.
724841Shaimay  */
735093Shaimay void
_SUNW_GetThreshold(void * thresholdp)745093Shaimay _SUNW_GetThreshold(void *thresholdp)
754841Shaimay {
764841Shaimay 
775093Shaimay 	cipher_mechs_threshold_t *tp = (cipher_mechs_threshold_t *)thresholdp;
784841Shaimay 	kernel_slot_t *pslot;
794841Shaimay 	int i;
804841Shaimay 
814841Shaimay 	/*
824841Shaimay 	 * We alway use the 1st slot in the kernel to
834841Shaimay 	 * get the threshold because all the kernel
844841Shaimay 	 * slots will have the same threshold value
854841Shaimay 	 * with the same mechanism.
864841Shaimay 	 */
874841Shaimay 	pslot = slot_table[0];
884841Shaimay 
894841Shaimay 	for (i = 0; i < pslot->total_threshold_count; i++) {
905093Shaimay 		tp[i].mech_type =
915093Shaimay 		    pslot->sl_mechs_threshold[i].mech_type;
925093Shaimay 		tp[i].mech_threshold =
935093Shaimay 		    pslot->sl_mechs_threshold[i].mech_threshold;
944841Shaimay 	}
954841Shaimay }
964841Shaimay 
974841Shaimay /*
980Sstevel@tonic-gate  * To retrieve the crypto_function_list structure with boolean entries
990Sstevel@tonic-gate  * indicating which functions are supported by the hardware provider which
1000Sstevel@tonic-gate  * is specified by the slot ID.
1010Sstevel@tonic-gate  */
1020Sstevel@tonic-gate static CK_RV
kernel_get_func_list(kernel_slot_t * pslot)1030Sstevel@tonic-gate kernel_get_func_list(kernel_slot_t *pslot)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1060Sstevel@tonic-gate 	crypto_get_function_list_t  fl;
1070Sstevel@tonic-gate 	int r;
1084841Shaimay 	int i;
1090Sstevel@tonic-gate 
110*12856SZdenek.Kotala@Sun.COM 	(void) memset(&fl, 0, sizeof (fl));
1110Sstevel@tonic-gate 	fl.fl_provider_id = pslot->sl_provider_id;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) {
1140Sstevel@tonic-gate 		if (errno != EINTR)
1150Sstevel@tonic-gate 			break;
1160Sstevel@tonic-gate 	}
1170Sstevel@tonic-gate 	if (r < 0) {
1180Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
1190Sstevel@tonic-gate 	} else {
1200Sstevel@tonic-gate 		if (fl.fl_return_value == 0) {
1210Sstevel@tonic-gate 			rv = CKR_OK;
1220Sstevel@tonic-gate 		} else {
1230Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(fl.fl_return_value);
1240Sstevel@tonic-gate 		}
1250Sstevel@tonic-gate 	}
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	if (rv != CKR_OK) {
1280Sstevel@tonic-gate 		return (rv);
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate 
131*12856SZdenek.Kotala@Sun.COM 	/* copy data structure received from kernel */
132*12856SZdenek.Kotala@Sun.COM 	pslot->sl_func_list = fl.fl_list;
1330Sstevel@tonic-gate 
1344072Skrishna 	pslot->sl_flags = 0;
13511304SJanie.Lu@Sun.COM 	if (fl.fl_list.prov_is_hash_limited) {
13611304SJanie.Lu@Sun.COM 		pslot->sl_flags |= CRYPTO_LIMITED_HASH_SUPPORT;
13711304SJanie.Lu@Sun.COM 		pslot->sl_hash_max_inlen = fl.fl_list.prov_hash_limit;
13811304SJanie.Lu@Sun.COM 	}
13911304SJanie.Lu@Sun.COM 
14011304SJanie.Lu@Sun.COM 	if (fl.fl_list.prov_is_hmac_limited) {
14111304SJanie.Lu@Sun.COM 		pslot->sl_flags |= CRYPTO_LIMITED_HMAC_SUPPORT;
14211304SJanie.Lu@Sun.COM 		pslot->sl_hmac_max_inlen = fl.fl_list.prov_hmac_limit;
14311304SJanie.Lu@Sun.COM 	}
14411304SJanie.Lu@Sun.COM 
14511304SJanie.Lu@Sun.COM 	if (fl.fl_list.prov_is_hash_limited | fl.fl_list.prov_is_hmac_limited) {
1464072Skrishna 		pslot->sl_threshold = fl.fl_list.prov_hash_threshold;
1474072Skrishna 	}
1484072Skrishna 
1494841Shaimay 	pslot->total_threshold_count = fl.fl_list.total_threshold_count;
1504841Shaimay 
1514841Shaimay 	for (i = 0; i < pslot->total_threshold_count; i++) {
1524841Shaimay 		pslot->sl_mechs_threshold[i].mech_type =
1534841Shaimay 		    fl.fl_list.fl_threshold[i].mech_type;
1544841Shaimay 		pslot->sl_mechs_threshold[i].mech_threshold =
1554841Shaimay 		    fl.fl_list.fl_threshold[i].mech_threshold;
1564841Shaimay 	}
1574841Shaimay 
1580Sstevel@tonic-gate 	return (CKR_OK);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate  * Initialize the slot table.
1630Sstevel@tonic-gate  *
1640Sstevel@tonic-gate  * This function is called from C_Initialize() only.  Since C_Initialize()
1650Sstevel@tonic-gate  * holds the global mutex lock, there is no need to acquire another lock
1660Sstevel@tonic-gate  * in this routine to protect the slot table.
1670Sstevel@tonic-gate  */
1680Sstevel@tonic-gate CK_RV
kernel_slottable_init()1690Sstevel@tonic-gate kernel_slottable_init()
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate 	int i, cur_slot_num = 0;
1720Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1730Sstevel@tonic-gate 	crypto_get_provider_list_t *pl = NULL;
1740Sstevel@tonic-gate 	int r;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	/*
1770Sstevel@tonic-gate 	 * Find out how many slots are presented from kernel hardware
1780Sstevel@tonic-gate 	 * providers. If there is no slot presented, just return.
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 	rv = kernel_get_slot_number();
1810Sstevel@tonic-gate 	if (rv != CKR_OK || slot_count == 0) {
1820Sstevel@tonic-gate 		return (rv);
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	/* Allocate space for the slot table */
1860Sstevel@tonic-gate 	slot_table = malloc(sizeof (kernel_slot_t *) * slot_count);
1870Sstevel@tonic-gate 	if (slot_table == NULL) {
1880Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1890Sstevel@tonic-gate 	}
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	/* For each slot, allocate space and initialize the slot's mutex. */
1920Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
1930Sstevel@tonic-gate 		slot_table[i] = malloc(sizeof (kernel_slot_t));
1940Sstevel@tonic-gate 		if (slot_table[i] == NULL) {
1950Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
1960Sstevel@tonic-gate 			goto failed;
1970Sstevel@tonic-gate 		}
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 		slot_table[i]->sl_sess_list = NULL;
2000Sstevel@tonic-gate 		slot_table[i]->sl_tobj_list = NULL;
2010Sstevel@tonic-gate 		slot_table[i]->sl_state = CKU_PUBLIC;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 		/* Initialize this slot's mutex */
2040Sstevel@tonic-gate 		if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) {
2050Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
2060Sstevel@tonic-gate 			(void) free(slot_table[i]);
2070Sstevel@tonic-gate 			goto failed;
2080Sstevel@tonic-gate 		}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 		cur_slot_num = i;
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	/*
2140Sstevel@tonic-gate 	 * Get the provider ID for each slot from kernel and save it in the
2150Sstevel@tonic-gate 	 * slot table.
2160Sstevel@tonic-gate 	 */
2170Sstevel@tonic-gate 	pl = malloc(slot_count * sizeof (crypto_get_provider_list_t));
2180Sstevel@tonic-gate 	if (pl == NULL) {
2190Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
2200Sstevel@tonic-gate 		goto failed;
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	pl->pl_count = slot_count;
2240Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) {
2250Sstevel@tonic-gate 		if (errno != EINTR)
2260Sstevel@tonic-gate 			break;
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 	if (r < 0) {
2290Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
2300Sstevel@tonic-gate 		goto failed;
2310Sstevel@tonic-gate 	} else {
2320Sstevel@tonic-gate 		if (pl->pl_return_value != CRYPTO_SUCCESS) {
2330Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(pl->pl_return_value);
2340Sstevel@tonic-gate 			goto failed;
2350Sstevel@tonic-gate 		} else {
2360Sstevel@tonic-gate 			rv = CKR_OK;
2370Sstevel@tonic-gate 		}
2380Sstevel@tonic-gate 	}
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
2410Sstevel@tonic-gate 		slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id;
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	/*
2450Sstevel@tonic-gate 	 * Get the function list for each slot from kernel and save it in
2460Sstevel@tonic-gate 	 * the slot table.
2470Sstevel@tonic-gate 	 */
2480Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
2490Sstevel@tonic-gate 		rv = kernel_get_func_list(slot_table[i]);
2500Sstevel@tonic-gate 		if (rv != CKR_OK) {
2510Sstevel@tonic-gate 			goto failed;
2520Sstevel@tonic-gate 		}
2530Sstevel@tonic-gate 	}
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	(void) free(pl);
2560Sstevel@tonic-gate 	return (CKR_OK);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate failed:
2590Sstevel@tonic-gate 	for (i = 0; i < cur_slot_num; i++) {
2600Sstevel@tonic-gate 		(void) pthread_mutex_destroy(&slot_table[i]->sl_mutex);
2610Sstevel@tonic-gate 		(void) free(slot_table[i]);
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	(void) free(slot_table);
2650Sstevel@tonic-gate 	(void) free(pl);
2660Sstevel@tonic-gate 	return (rv);
2670Sstevel@tonic-gate }
268