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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <errno.h> 27 #include <security/cryptoki.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 fl.fl_provider_id = pslot->sl_provider_id; 111 112 while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) { 113 if (errno != EINTR) 114 break; 115 } 116 if (r < 0) { 117 rv = CKR_FUNCTION_FAILED; 118 } else { 119 if (fl.fl_return_value == 0) { 120 rv = CKR_OK; 121 } else { 122 rv = crypto2pkcs11_error_number(fl.fl_return_value); 123 } 124 } 125 126 if (rv != CKR_OK) { 127 return (rv); 128 } 129 130 pslot->sl_func_list.fl_digest_init = fl.fl_list.fl_digest_init; 131 pslot->sl_func_list.fl_digest = fl.fl_list.fl_digest; 132 pslot->sl_func_list.fl_digest_update = fl.fl_list.fl_digest_update; 133 pslot->sl_func_list.fl_digest_key = fl.fl_list.fl_digest_key; 134 pslot->sl_func_list.fl_digest_final = fl.fl_list.fl_digest_final; 135 pslot->sl_func_list.fl_encrypt_init = fl.fl_list.fl_encrypt_init; 136 pslot->sl_func_list.fl_encrypt = fl.fl_list.fl_encrypt; 137 pslot->sl_func_list.fl_encrypt_update = fl.fl_list.fl_encrypt_update; 138 pslot->sl_func_list.fl_encrypt_final = fl.fl_list.fl_encrypt_final; 139 pslot->sl_func_list.fl_decrypt_init = fl.fl_list.fl_decrypt_init; 140 pslot->sl_func_list.fl_decrypt = fl.fl_list.fl_decrypt; 141 pslot->sl_func_list.fl_decrypt_update = fl.fl_list.fl_decrypt_update; 142 pslot->sl_func_list.fl_decrypt_final = fl.fl_list.fl_decrypt_final; 143 pslot->sl_func_list.fl_mac_init = fl.fl_list.fl_mac_init; 144 pslot->sl_func_list.fl_mac = fl.fl_list.fl_mac; 145 pslot->sl_func_list.fl_mac_update = fl.fl_list.fl_mac_update; 146 pslot->sl_func_list.fl_mac_final = fl.fl_list.fl_mac_final; 147 pslot->sl_func_list.fl_sign_init = fl.fl_list.fl_sign_init; 148 pslot->sl_func_list.fl_sign = fl.fl_list.fl_sign; 149 pslot->sl_func_list.fl_sign_update = fl.fl_list.fl_sign_update; 150 pslot->sl_func_list.fl_sign_final = fl.fl_list.fl_sign_final; 151 pslot->sl_func_list.fl_sign_recover_init = 152 fl.fl_list.fl_sign_recover_init; 153 pslot->sl_func_list.fl_sign_recover = fl.fl_list.fl_sign_recover; 154 pslot->sl_func_list.fl_digest_encrypt_update = 155 fl.fl_list.fl_digest_encrypt_update; 156 pslot->sl_func_list.fl_decrypt_digest_update = 157 fl.fl_list.fl_decrypt_digest_update; 158 pslot->sl_func_list.fl_sign_encrypt_update = 159 fl.fl_list.fl_sign_encrypt_update; 160 pslot->sl_func_list.fl_decrypt_verify_update = 161 fl.fl_list.fl_decrypt_verify_update; 162 pslot->sl_func_list.fl_seed_random = fl.fl_list.fl_seed_random; 163 pslot->sl_func_list.fl_generate_random = fl.fl_list.fl_generate_random; 164 pslot->sl_func_list.fl_session_open = fl.fl_list.fl_session_open; 165 pslot->sl_func_list.fl_session_close = fl.fl_list.fl_session_close; 166 pslot->sl_func_list.fl_session_login = fl.fl_list.fl_session_login; 167 pslot->sl_func_list.fl_session_logout = fl.fl_list.fl_session_logout; 168 pslot->sl_func_list.fl_object_create = fl.fl_list.fl_object_create; 169 pslot->sl_func_list.fl_object_copy = fl.fl_list.fl_object_copy; 170 pslot->sl_func_list.fl_object_destroy = fl.fl_list.fl_object_destroy; 171 pslot->sl_func_list.fl_object_get_size = fl.fl_list.fl_object_get_size; 172 pslot->sl_func_list.fl_object_get_attribute_value = 173 fl.fl_list.fl_object_get_attribute_value; 174 pslot->sl_func_list.fl_object_set_attribute_value = 175 fl.fl_list.fl_object_set_attribute_value; 176 pslot->sl_func_list.fl_object_find_init = 177 fl.fl_list.fl_object_find_init; 178 pslot->sl_func_list.fl_object_find = fl.fl_list.fl_object_find; 179 pslot->sl_func_list.fl_object_find_final = 180 fl.fl_list.fl_object_find_final; 181 pslot->sl_func_list.fl_key_generate = fl.fl_list.fl_key_generate; 182 pslot->sl_func_list.fl_key_generate_pair = 183 fl.fl_list.fl_key_generate_pair; 184 pslot->sl_func_list.fl_key_wrap = fl.fl_list.fl_key_wrap; 185 pslot->sl_func_list.fl_key_unwrap = fl.fl_list.fl_key_unwrap; 186 pslot->sl_func_list.fl_init_token = fl.fl_list.fl_init_token; 187 pslot->sl_func_list.fl_init_pin = fl.fl_list.fl_init_pin; 188 pslot->sl_func_list.fl_set_pin = fl.fl_list.fl_set_pin; 189 190 pslot->sl_flags = 0; 191 if (fl.fl_list.prov_is_hash_limited) { 192 pslot->sl_flags |= CRYPTO_LIMITED_HASH_SUPPORT; 193 pslot->sl_hash_max_inlen = fl.fl_list.prov_hash_limit; 194 } 195 196 if (fl.fl_list.prov_is_hmac_limited) { 197 pslot->sl_flags |= CRYPTO_LIMITED_HMAC_SUPPORT; 198 pslot->sl_hmac_max_inlen = fl.fl_list.prov_hmac_limit; 199 } 200 201 if (fl.fl_list.prov_is_hash_limited | fl.fl_list.prov_is_hmac_limited) { 202 pslot->sl_threshold = fl.fl_list.prov_hash_threshold; 203 } 204 205 pslot->total_threshold_count = fl.fl_list.total_threshold_count; 206 207 for (i = 0; i < pslot->total_threshold_count; i++) { 208 pslot->sl_mechs_threshold[i].mech_type = 209 fl.fl_list.fl_threshold[i].mech_type; 210 pslot->sl_mechs_threshold[i].mech_threshold = 211 fl.fl_list.fl_threshold[i].mech_threshold; 212 } 213 214 return (CKR_OK); 215 } 216 217 /* 218 * Initialize the slot table. 219 * 220 * This function is called from C_Initialize() only. Since C_Initialize() 221 * holds the global mutex lock, there is no need to acquire another lock 222 * in this routine to protect the slot table. 223 */ 224 CK_RV 225 kernel_slottable_init() 226 { 227 int i, cur_slot_num = 0; 228 CK_RV rv = CKR_OK; 229 crypto_get_provider_list_t *pl = NULL; 230 int r; 231 232 /* 233 * Find out how many slots are presented from kernel hardware 234 * providers. If there is no slot presented, just return. 235 */ 236 rv = kernel_get_slot_number(); 237 if (rv != CKR_OK || slot_count == 0) { 238 return (rv); 239 } 240 241 /* Allocate space for the slot table */ 242 slot_table = malloc(sizeof (kernel_slot_t *) * slot_count); 243 if (slot_table == NULL) { 244 return (CKR_HOST_MEMORY); 245 } 246 247 /* For each slot, allocate space and initialize the slot's mutex. */ 248 for (i = 0; i < slot_count; i++) { 249 slot_table[i] = malloc(sizeof (kernel_slot_t)); 250 if (slot_table[i] == NULL) { 251 rv = CKR_HOST_MEMORY; 252 goto failed; 253 } 254 255 slot_table[i]->sl_sess_list = NULL; 256 slot_table[i]->sl_tobj_list = NULL; 257 slot_table[i]->sl_state = CKU_PUBLIC; 258 259 /* Initialize this slot's mutex */ 260 if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) { 261 rv = CKR_FUNCTION_FAILED; 262 (void) free(slot_table[i]); 263 goto failed; 264 } 265 266 cur_slot_num = i; 267 } 268 269 /* 270 * Get the provider ID for each slot from kernel and save it in the 271 * slot table. 272 */ 273 pl = malloc(slot_count * sizeof (crypto_get_provider_list_t)); 274 if (pl == NULL) { 275 rv = CKR_HOST_MEMORY; 276 goto failed; 277 } 278 279 pl->pl_count = slot_count; 280 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 281 if (errno != EINTR) 282 break; 283 } 284 if (r < 0) { 285 rv = CKR_FUNCTION_FAILED; 286 goto failed; 287 } else { 288 if (pl->pl_return_value != CRYPTO_SUCCESS) { 289 rv = crypto2pkcs11_error_number(pl->pl_return_value); 290 goto failed; 291 } else { 292 rv = CKR_OK; 293 } 294 } 295 296 for (i = 0; i < slot_count; i++) { 297 slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id; 298 } 299 300 /* 301 * Get the function list for each slot from kernel and save it in 302 * the slot table. 303 */ 304 for (i = 0; i < slot_count; i++) { 305 rv = kernel_get_func_list(slot_table[i]); 306 if (rv != CKR_OK) { 307 goto failed; 308 } 309 } 310 311 (void) free(pl); 312 return (CKR_OK); 313 314 failed: 315 for (i = 0; i < cur_slot_num; i++) { 316 (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 317 (void) free(slot_table[i]); 318 } 319 320 (void) free(slot_table); 321 (void) free(pl); 322 return (rv); 323 } 324