1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <errno.h> 26 #include <security/cryptoki.h> 27 #include <strings.h> 28 #include <sys/crypto/ioctl.h> 29 #include "kernelGlobal.h" 30 #include "kernelSlot.h" 31 32 CK_ULONG slot_count = 0; 33 kernel_slot_t **slot_table; 34 35 static CK_RV 36 kernel_get_slot_number() 37 { 38 CK_RV rv; 39 crypto_get_provider_list_t *pl; 40 int r; 41 42 pl = malloc(sizeof (crypto_get_provider_list_t)); 43 if (pl == NULL) 44 return (CKR_HOST_MEMORY); 45 46 pl->pl_count = 0; 47 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 48 if (errno != EINTR) 49 break; 50 } 51 if (r < 0) { 52 rv = CKR_FUNCTION_FAILED; 53 } else { 54 if (pl->pl_return_value != CRYPTO_SUCCESS) { 55 rv = crypto2pkcs11_error_number(pl->pl_return_value); 56 } else { 57 rv = CKR_OK; 58 } 59 } 60 61 if (rv == CKR_OK) { 62 slot_count = pl->pl_count; 63 } 64 65 (void) free(pl); 66 return (rv); 67 } 68 69 /* 70 * This function will be used by metaslot to get the kernel 71 * provider's threshold value for the supported mechanisms. 72 */ 73 void 74 _SUNW_GetThreshold(void *thresholdp) 75 { 76 77 cipher_mechs_threshold_t *tp = (cipher_mechs_threshold_t *)thresholdp; 78 kernel_slot_t *pslot; 79 int i; 80 81 /* 82 * We alway use the 1st slot in the kernel to 83 * get the threshold because all the kernel 84 * slots will have the same threshold value 85 * with the same mechanism. 86 */ 87 pslot = slot_table[0]; 88 89 for (i = 0; i < pslot->total_threshold_count; i++) { 90 tp[i].mech_type = 91 pslot->sl_mechs_threshold[i].mech_type; 92 tp[i].mech_threshold = 93 pslot->sl_mechs_threshold[i].mech_threshold; 94 } 95 } 96 97 /* 98 * To retrieve the crypto_function_list structure with boolean entries 99 * indicating which functions are supported by the hardware provider which 100 * is specified by the slot ID. 101 */ 102 static CK_RV 103 kernel_get_func_list(kernel_slot_t *pslot) 104 { 105 CK_RV rv = CKR_OK; 106 crypto_get_function_list_t fl; 107 int r; 108 int i; 109 110 (void) memset(&fl, 0, sizeof (fl)); 111 fl.fl_provider_id = pslot->sl_provider_id; 112 113 while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) { 114 if (errno != EINTR) 115 break; 116 } 117 if (r < 0) { 118 rv = CKR_FUNCTION_FAILED; 119 } else { 120 if (fl.fl_return_value == 0) { 121 rv = CKR_OK; 122 } else { 123 rv = crypto2pkcs11_error_number(fl.fl_return_value); 124 } 125 } 126 127 if (rv != CKR_OK) { 128 return (rv); 129 } 130 131 /* copy data structure received from kernel */ 132 pslot->sl_func_list = fl.fl_list; 133 134 pslot->sl_flags = 0; 135 if (fl.fl_list.prov_is_hash_limited) { 136 pslot->sl_flags |= CRYPTO_LIMITED_HASH_SUPPORT; 137 pslot->sl_hash_max_inlen = fl.fl_list.prov_hash_limit; 138 } 139 140 if (fl.fl_list.prov_is_hmac_limited) { 141 pslot->sl_flags |= CRYPTO_LIMITED_HMAC_SUPPORT; 142 pslot->sl_hmac_max_inlen = fl.fl_list.prov_hmac_limit; 143 } 144 145 if (fl.fl_list.prov_is_hash_limited | fl.fl_list.prov_is_hmac_limited) { 146 pslot->sl_threshold = fl.fl_list.prov_hash_threshold; 147 } 148 149 pslot->total_threshold_count = fl.fl_list.total_threshold_count; 150 151 for (i = 0; i < pslot->total_threshold_count; i++) { 152 pslot->sl_mechs_threshold[i].mech_type = 153 fl.fl_list.fl_threshold[i].mech_type; 154 pslot->sl_mechs_threshold[i].mech_threshold = 155 fl.fl_list.fl_threshold[i].mech_threshold; 156 } 157 158 return (CKR_OK); 159 } 160 161 /* 162 * Initialize the slot table. 163 * 164 * This function is called from C_Initialize() only. Since C_Initialize() 165 * holds the global mutex lock, there is no need to acquire another lock 166 * in this routine to protect the slot table. 167 */ 168 CK_RV 169 kernel_slottable_init() 170 { 171 int i, cur_slot_num = 0; 172 CK_RV rv = CKR_OK; 173 crypto_get_provider_list_t *pl = NULL; 174 int r; 175 176 /* 177 * Find out how many slots are presented from kernel hardware 178 * providers. If there is no slot presented, just return. 179 */ 180 rv = kernel_get_slot_number(); 181 if (rv != CKR_OK || slot_count == 0) { 182 return (rv); 183 } 184 185 /* Allocate space for the slot table */ 186 slot_table = malloc(sizeof (kernel_slot_t *) * slot_count); 187 if (slot_table == NULL) { 188 return (CKR_HOST_MEMORY); 189 } 190 191 /* For each slot, allocate space and initialize the slot's mutex. */ 192 for (i = 0; i < slot_count; i++) { 193 slot_table[i] = malloc(sizeof (kernel_slot_t)); 194 if (slot_table[i] == NULL) { 195 rv = CKR_HOST_MEMORY; 196 goto failed; 197 } 198 199 slot_table[i]->sl_sess_list = NULL; 200 slot_table[i]->sl_tobj_list = NULL; 201 slot_table[i]->sl_state = CKU_PUBLIC; 202 203 /* Initialize this slot's mutex */ 204 if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) { 205 rv = CKR_FUNCTION_FAILED; 206 (void) free(slot_table[i]); 207 goto failed; 208 } 209 210 cur_slot_num = i; 211 } 212 213 /* 214 * Get the provider ID for each slot from kernel and save it in the 215 * slot table. 216 */ 217 pl = malloc(slot_count * sizeof (crypto_get_provider_list_t)); 218 if (pl == NULL) { 219 rv = CKR_HOST_MEMORY; 220 goto failed; 221 } 222 223 pl->pl_count = slot_count; 224 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 225 if (errno != EINTR) 226 break; 227 } 228 if (r < 0) { 229 rv = CKR_FUNCTION_FAILED; 230 goto failed; 231 } else { 232 if (pl->pl_return_value != CRYPTO_SUCCESS) { 233 rv = crypto2pkcs11_error_number(pl->pl_return_value); 234 goto failed; 235 } else { 236 rv = CKR_OK; 237 } 238 } 239 240 for (i = 0; i < slot_count; i++) { 241 slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id; 242 } 243 244 /* 245 * Get the function list for each slot from kernel and save it in 246 * the slot table. 247 */ 248 for (i = 0; i < slot_count; i++) { 249 rv = kernel_get_func_list(slot_table[i]); 250 if (rv != CKR_OK) { 251 goto failed; 252 } 253 } 254 255 (void) free(pl); 256 return (CKR_OK); 257 258 failed: 259 for (i = 0; i < cur_slot_num; i++) { 260 (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 261 (void) free(slot_table[i]); 262 } 263 264 (void) free(slot_table); 265 (void) free(pl); 266 return (rv); 267 } 268