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