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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <errno.h> 29 #include <security/cryptoki.h> 30 #include <sys/crypto/ioctl.h> 31 #include "kernelGlobal.h" 32 #include "kernelSlot.h" 33 34 CK_ULONG slot_count = 0; 35 kernel_slot_t **slot_table; 36 37 static CK_RV 38 kernel_get_slot_number() 39 { 40 CK_RV rv; 41 crypto_get_provider_list_t *pl; 42 int r; 43 44 pl = malloc(sizeof (crypto_get_provider_list_t)); 45 if (pl == NULL) 46 return (CKR_HOST_MEMORY); 47 48 pl->pl_count = 0; 49 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 50 if (errno != EINTR) 51 break; 52 } 53 if (r < 0) { 54 rv = CKR_FUNCTION_FAILED; 55 } else { 56 if (pl->pl_return_value != CRYPTO_SUCCESS) { 57 rv = crypto2pkcs11_error_number(pl->pl_return_value); 58 } else { 59 rv = CKR_OK; 60 } 61 } 62 63 if (rv == CKR_OK) { 64 slot_count = pl->pl_count; 65 } 66 67 (void) free(pl); 68 return (rv); 69 } 70 71 /* 72 * This function will be used by metaslot to get the kernel 73 * provider's threshold value for the supported mechanisms. 74 */ 75 void 76 _SUNW_GetThreshold(void *thresholdp) 77 { 78 79 cipher_mechs_threshold_t *tp = (cipher_mechs_threshold_t *)thresholdp; 80 kernel_slot_t *pslot; 81 int i; 82 83 /* 84 * We alway use the 1st slot in the kernel to 85 * get the threshold because all the kernel 86 * slots will have the same threshold value 87 * with the same mechanism. 88 */ 89 pslot = slot_table[0]; 90 91 for (i = 0; i < pslot->total_threshold_count; i++) { 92 tp[i].mech_type = 93 pslot->sl_mechs_threshold[i].mech_type; 94 tp[i].mech_threshold = 95 pslot->sl_mechs_threshold[i].mech_threshold; 96 } 97 } 98 99 /* 100 * To retrieve the crypto_function_list structure with boolean entries 101 * indicating which functions are supported by the hardware provider which 102 * is specified by the slot ID. 103 */ 104 static CK_RV 105 kernel_get_func_list(kernel_slot_t *pslot) 106 { 107 CK_RV rv = CKR_OK; 108 crypto_get_function_list_t fl; 109 int r; 110 int i; 111 112 fl.fl_provider_id = pslot->sl_provider_id; 113 114 while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) { 115 if (errno != EINTR) 116 break; 117 } 118 if (r < 0) { 119 rv = CKR_FUNCTION_FAILED; 120 } else { 121 if (fl.fl_return_value == 0) { 122 rv = CKR_OK; 123 } else { 124 rv = crypto2pkcs11_error_number(fl.fl_return_value); 125 } 126 } 127 128 if (rv != CKR_OK) { 129 return (rv); 130 } 131 132 pslot->sl_func_list.fl_digest_init = fl.fl_list.fl_digest_init; 133 pslot->sl_func_list.fl_digest = fl.fl_list.fl_digest; 134 pslot->sl_func_list.fl_digest_update = fl.fl_list.fl_digest_update; 135 pslot->sl_func_list.fl_digest_key = fl.fl_list.fl_digest_key; 136 pslot->sl_func_list.fl_digest_final = fl.fl_list.fl_digest_final; 137 pslot->sl_func_list.fl_encrypt_init = fl.fl_list.fl_encrypt_init; 138 pslot->sl_func_list.fl_encrypt = fl.fl_list.fl_encrypt; 139 pslot->sl_func_list.fl_encrypt_update = fl.fl_list.fl_encrypt_update; 140 pslot->sl_func_list.fl_encrypt_final = fl.fl_list.fl_encrypt_final; 141 pslot->sl_func_list.fl_decrypt_init = fl.fl_list.fl_decrypt_init; 142 pslot->sl_func_list.fl_decrypt = fl.fl_list.fl_decrypt; 143 pslot->sl_func_list.fl_decrypt_update = fl.fl_list.fl_decrypt_update; 144 pslot->sl_func_list.fl_decrypt_final = fl.fl_list.fl_decrypt_final; 145 pslot->sl_func_list.fl_mac_init = fl.fl_list.fl_mac_init; 146 pslot->sl_func_list.fl_mac = fl.fl_list.fl_mac; 147 pslot->sl_func_list.fl_mac_update = fl.fl_list.fl_mac_update; 148 pslot->sl_func_list.fl_mac_final = fl.fl_list.fl_mac_final; 149 pslot->sl_func_list.fl_sign_init = fl.fl_list.fl_sign_init; 150 pslot->sl_func_list.fl_sign = fl.fl_list.fl_sign; 151 pslot->sl_func_list.fl_sign_update = fl.fl_list.fl_sign_update; 152 pslot->sl_func_list.fl_sign_final = fl.fl_list.fl_sign_final; 153 pslot->sl_func_list.fl_sign_recover_init = 154 fl.fl_list.fl_sign_recover_init; 155 pslot->sl_func_list.fl_sign_recover = fl.fl_list.fl_sign_recover; 156 pslot->sl_func_list.fl_digest_encrypt_update = 157 fl.fl_list.fl_digest_encrypt_update; 158 pslot->sl_func_list.fl_decrypt_digest_update = 159 fl.fl_list.fl_decrypt_digest_update; 160 pslot->sl_func_list.fl_sign_encrypt_update = 161 fl.fl_list.fl_sign_encrypt_update; 162 pslot->sl_func_list.fl_decrypt_verify_update = 163 fl.fl_list.fl_decrypt_verify_update; 164 pslot->sl_func_list.fl_seed_random = fl.fl_list.fl_seed_random; 165 pslot->sl_func_list.fl_generate_random = fl.fl_list.fl_generate_random; 166 pslot->sl_func_list.fl_session_open = fl.fl_list.fl_session_open; 167 pslot->sl_func_list.fl_session_close = fl.fl_list.fl_session_close; 168 pslot->sl_func_list.fl_session_login = fl.fl_list.fl_session_login; 169 pslot->sl_func_list.fl_session_logout = fl.fl_list.fl_session_logout; 170 pslot->sl_func_list.fl_object_create = fl.fl_list.fl_object_create; 171 pslot->sl_func_list.fl_object_copy = fl.fl_list.fl_object_copy; 172 pslot->sl_func_list.fl_object_destroy = fl.fl_list.fl_object_destroy; 173 pslot->sl_func_list.fl_object_get_size = fl.fl_list.fl_object_get_size; 174 pslot->sl_func_list.fl_object_get_attribute_value = 175 fl.fl_list.fl_object_get_attribute_value; 176 pslot->sl_func_list.fl_object_set_attribute_value = 177 fl.fl_list.fl_object_set_attribute_value; 178 pslot->sl_func_list.fl_object_find_init = 179 fl.fl_list.fl_object_find_init; 180 pslot->sl_func_list.fl_object_find = fl.fl_list.fl_object_find; 181 pslot->sl_func_list.fl_object_find_final = 182 fl.fl_list.fl_object_find_final; 183 pslot->sl_func_list.fl_key_generate = fl.fl_list.fl_key_generate; 184 pslot->sl_func_list.fl_key_generate_pair = 185 fl.fl_list.fl_key_generate_pair; 186 pslot->sl_func_list.fl_key_wrap = fl.fl_list.fl_key_wrap; 187 pslot->sl_func_list.fl_key_unwrap = fl.fl_list.fl_key_unwrap; 188 pslot->sl_func_list.fl_init_token = fl.fl_list.fl_init_token; 189 pslot->sl_func_list.fl_init_pin = fl.fl_list.fl_init_pin; 190 pslot->sl_func_list.fl_set_pin = fl.fl_list.fl_set_pin; 191 192 pslot->sl_flags = 0; 193 if (fl.fl_list.prov_is_limited) { 194 pslot->sl_flags = CRYPTO_LIMITED_HASH_SUPPORT; 195 pslot->sl_threshold = fl.fl_list.prov_hash_threshold; 196 pslot->sl_max_inlen = fl.fl_list.prov_hash_limit; 197 } 198 199 pslot->total_threshold_count = fl.fl_list.total_threshold_count; 200 201 for (i = 0; i < pslot->total_threshold_count; i++) { 202 pslot->sl_mechs_threshold[i].mech_type = 203 fl.fl_list.fl_threshold[i].mech_type; 204 pslot->sl_mechs_threshold[i].mech_threshold = 205 fl.fl_list.fl_threshold[i].mech_threshold; 206 } 207 208 return (CKR_OK); 209 } 210 211 /* 212 * Initialize the slot table. 213 * 214 * This function is called from C_Initialize() only. Since C_Initialize() 215 * holds the global mutex lock, there is no need to acquire another lock 216 * in this routine to protect the slot table. 217 */ 218 CK_RV 219 kernel_slottable_init() 220 { 221 int i, cur_slot_num = 0; 222 CK_RV rv = CKR_OK; 223 crypto_get_provider_list_t *pl = NULL; 224 int r; 225 226 /* 227 * Find out how many slots are presented from kernel hardware 228 * providers. If there is no slot presented, just return. 229 */ 230 rv = kernel_get_slot_number(); 231 if (rv != CKR_OK || slot_count == 0) { 232 return (rv); 233 } 234 235 /* Allocate space for the slot table */ 236 slot_table = malloc(sizeof (kernel_slot_t *) * slot_count); 237 if (slot_table == NULL) { 238 return (CKR_HOST_MEMORY); 239 } 240 241 /* For each slot, allocate space and initialize the slot's mutex. */ 242 for (i = 0; i < slot_count; i++) { 243 slot_table[i] = malloc(sizeof (kernel_slot_t)); 244 if (slot_table[i] == NULL) { 245 rv = CKR_HOST_MEMORY; 246 goto failed; 247 } 248 249 slot_table[i]->sl_sess_list = NULL; 250 slot_table[i]->sl_tobj_list = NULL; 251 slot_table[i]->sl_state = CKU_PUBLIC; 252 253 /* Initialize this slot's mutex */ 254 if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) { 255 rv = CKR_FUNCTION_FAILED; 256 (void) free(slot_table[i]); 257 goto failed; 258 } 259 260 cur_slot_num = i; 261 } 262 263 /* 264 * Get the provider ID for each slot from kernel and save it in the 265 * slot table. 266 */ 267 pl = malloc(slot_count * sizeof (crypto_get_provider_list_t)); 268 if (pl == NULL) { 269 rv = CKR_HOST_MEMORY; 270 goto failed; 271 } 272 273 pl->pl_count = slot_count; 274 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 275 if (errno != EINTR) 276 break; 277 } 278 if (r < 0) { 279 rv = CKR_FUNCTION_FAILED; 280 goto failed; 281 } else { 282 if (pl->pl_return_value != CRYPTO_SUCCESS) { 283 rv = crypto2pkcs11_error_number(pl->pl_return_value); 284 goto failed; 285 } else { 286 rv = CKR_OK; 287 } 288 } 289 290 for (i = 0; i < slot_count; i++) { 291 slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id; 292 } 293 294 /* 295 * Get the function list for each slot from kernel and save it in 296 * the slot table. 297 */ 298 for (i = 0; i < slot_count; i++) { 299 rv = kernel_get_func_list(slot_table[i]); 300 if (rv != CKR_OK) { 301 goto failed; 302 } 303 } 304 305 (void) free(pl); 306 return (CKR_OK); 307 308 failed: 309 for (i = 0; i < cur_slot_num; i++) { 310 (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 311 (void) free(slot_table[i]); 312 } 313 314 (void) free(slot_table); 315 (void) free(pl); 316 return (rv); 317 } 318