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 * To retrieve the crypto_function_list structure with boolean entries 73 * indicating which functions are supported by the hardware provider which 74 * is specified by the slot ID. 75 */ 76 static CK_RV 77 kernel_get_func_list(kernel_slot_t *pslot) 78 { 79 CK_RV rv = CKR_OK; 80 crypto_get_function_list_t fl; 81 int r; 82 83 fl.fl_provider_id = pslot->sl_provider_id; 84 85 while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) { 86 if (errno != EINTR) 87 break; 88 } 89 if (r < 0) { 90 rv = CKR_FUNCTION_FAILED; 91 } else { 92 if (fl.fl_return_value == 0) { 93 rv = CKR_OK; 94 } else { 95 rv = crypto2pkcs11_error_number(fl.fl_return_value); 96 } 97 } 98 99 if (rv != CKR_OK) { 100 return (rv); 101 } 102 103 pslot->sl_func_list.fl_digest_init = fl.fl_list.fl_digest_init; 104 pslot->sl_func_list.fl_digest = fl.fl_list.fl_digest; 105 pslot->sl_func_list.fl_digest_update = fl.fl_list.fl_digest_update; 106 pslot->sl_func_list.fl_digest_key = fl.fl_list.fl_digest_key; 107 pslot->sl_func_list.fl_digest_final = fl.fl_list.fl_digest_final; 108 pslot->sl_func_list.fl_encrypt_init = fl.fl_list.fl_encrypt_init; 109 pslot->sl_func_list.fl_encrypt = fl.fl_list.fl_encrypt; 110 pslot->sl_func_list.fl_encrypt_update = fl.fl_list.fl_encrypt_update; 111 pslot->sl_func_list.fl_encrypt_final = fl.fl_list.fl_encrypt_final; 112 pslot->sl_func_list.fl_decrypt_init = fl.fl_list.fl_decrypt_init; 113 pslot->sl_func_list.fl_decrypt = fl.fl_list.fl_decrypt; 114 pslot->sl_func_list.fl_decrypt_update = fl.fl_list.fl_decrypt_update; 115 pslot->sl_func_list.fl_decrypt_final = fl.fl_list.fl_decrypt_final; 116 pslot->sl_func_list.fl_mac_init = fl.fl_list.fl_mac_init; 117 pslot->sl_func_list.fl_mac = fl.fl_list.fl_mac; 118 pslot->sl_func_list.fl_mac_update = fl.fl_list.fl_mac_update; 119 pslot->sl_func_list.fl_mac_final = fl.fl_list.fl_mac_final; 120 pslot->sl_func_list.fl_sign_init = fl.fl_list.fl_sign_init; 121 pslot->sl_func_list.fl_sign = fl.fl_list.fl_sign; 122 pslot->sl_func_list.fl_sign_update = fl.fl_list.fl_sign_update; 123 pslot->sl_func_list.fl_sign_final = fl.fl_list.fl_sign_final; 124 pslot->sl_func_list.fl_sign_recover_init = 125 fl.fl_list.fl_sign_recover_init; 126 pslot->sl_func_list.fl_sign_recover = fl.fl_list.fl_sign_recover; 127 pslot->sl_func_list.fl_digest_encrypt_update = 128 fl.fl_list.fl_digest_encrypt_update; 129 pslot->sl_func_list.fl_decrypt_digest_update = 130 fl.fl_list.fl_decrypt_digest_update; 131 pslot->sl_func_list.fl_sign_encrypt_update = 132 fl.fl_list.fl_sign_encrypt_update; 133 pslot->sl_func_list.fl_decrypt_verify_update = 134 fl.fl_list.fl_decrypt_verify_update; 135 pslot->sl_func_list.fl_seed_random = fl.fl_list.fl_seed_random; 136 pslot->sl_func_list.fl_generate_random = fl.fl_list.fl_generate_random; 137 pslot->sl_func_list.fl_session_open = fl.fl_list.fl_session_open; 138 pslot->sl_func_list.fl_session_close = fl.fl_list.fl_session_close; 139 pslot->sl_func_list.fl_session_login = fl.fl_list.fl_session_login; 140 pslot->sl_func_list.fl_session_logout = fl.fl_list.fl_session_logout; 141 pslot->sl_func_list.fl_object_create = fl.fl_list.fl_object_create; 142 pslot->sl_func_list.fl_object_copy = fl.fl_list.fl_object_copy; 143 pslot->sl_func_list.fl_object_destroy = fl.fl_list.fl_object_destroy; 144 pslot->sl_func_list.fl_object_get_size = fl.fl_list.fl_object_get_size; 145 pslot->sl_func_list.fl_object_get_attribute_value = 146 fl.fl_list.fl_object_get_attribute_value; 147 pslot->sl_func_list.fl_object_set_attribute_value = 148 fl.fl_list.fl_object_set_attribute_value; 149 pslot->sl_func_list.fl_object_find_init = 150 fl.fl_list.fl_object_find_init; 151 pslot->sl_func_list.fl_object_find = fl.fl_list.fl_object_find; 152 pslot->sl_func_list.fl_object_find_final = 153 fl.fl_list.fl_object_find_final; 154 pslot->sl_func_list.fl_key_generate = fl.fl_list.fl_key_generate; 155 pslot->sl_func_list.fl_key_generate_pair = 156 fl.fl_list.fl_key_generate_pair; 157 pslot->sl_func_list.fl_key_wrap = fl.fl_list.fl_key_wrap; 158 pslot->sl_func_list.fl_key_unwrap = fl.fl_list.fl_key_unwrap; 159 pslot->sl_func_list.fl_init_token = fl.fl_list.fl_init_token; 160 pslot->sl_func_list.fl_init_pin = fl.fl_list.fl_init_pin; 161 pslot->sl_func_list.fl_set_pin = fl.fl_list.fl_set_pin; 162 163 pslot->sl_flags = 0; 164 if (fl.fl_list.prov_is_limited) { 165 pslot->sl_flags = CRYPTO_LIMITED_HASH_SUPPORT; 166 pslot->sl_threshold = fl.fl_list.prov_hash_threshold; 167 pslot->sl_max_inlen = fl.fl_list.prov_hash_limit; 168 } 169 170 return (CKR_OK); 171 } 172 173 /* 174 * Initialize the slot table. 175 * 176 * This function is called from C_Initialize() only. Since C_Initialize() 177 * holds the global mutex lock, there is no need to acquire another lock 178 * in this routine to protect the slot table. 179 */ 180 CK_RV 181 kernel_slottable_init() 182 { 183 int i, cur_slot_num = 0; 184 CK_RV rv = CKR_OK; 185 crypto_get_provider_list_t *pl = NULL; 186 int r; 187 188 /* 189 * Find out how many slots are presented from kernel hardware 190 * providers. If there is no slot presented, just return. 191 */ 192 rv = kernel_get_slot_number(); 193 if (rv != CKR_OK || slot_count == 0) { 194 return (rv); 195 } 196 197 /* Allocate space for the slot table */ 198 slot_table = malloc(sizeof (kernel_slot_t *) * slot_count); 199 if (slot_table == NULL) { 200 return (CKR_HOST_MEMORY); 201 } 202 203 /* For each slot, allocate space and initialize the slot's mutex. */ 204 for (i = 0; i < slot_count; i++) { 205 slot_table[i] = malloc(sizeof (kernel_slot_t)); 206 if (slot_table[i] == NULL) { 207 rv = CKR_HOST_MEMORY; 208 goto failed; 209 } 210 211 slot_table[i]->sl_sess_list = NULL; 212 slot_table[i]->sl_tobj_list = NULL; 213 slot_table[i]->sl_state = CKU_PUBLIC; 214 215 /* Initialize this slot's mutex */ 216 if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) { 217 rv = CKR_FUNCTION_FAILED; 218 (void) free(slot_table[i]); 219 goto failed; 220 } 221 222 cur_slot_num = i; 223 } 224 225 /* 226 * Get the provider ID for each slot from kernel and save it in the 227 * slot table. 228 */ 229 pl = malloc(slot_count * sizeof (crypto_get_provider_list_t)); 230 if (pl == NULL) { 231 rv = CKR_HOST_MEMORY; 232 goto failed; 233 } 234 235 pl->pl_count = slot_count; 236 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) { 237 if (errno != EINTR) 238 break; 239 } 240 if (r < 0) { 241 rv = CKR_FUNCTION_FAILED; 242 goto failed; 243 } else { 244 if (pl->pl_return_value != CRYPTO_SUCCESS) { 245 rv = crypto2pkcs11_error_number(pl->pl_return_value); 246 goto failed; 247 } else { 248 rv = CKR_OK; 249 } 250 } 251 252 for (i = 0; i < slot_count; i++) { 253 slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id; 254 } 255 256 /* 257 * Get the function list for each slot from kernel and save it in 258 * the slot table. 259 */ 260 for (i = 0; i < slot_count; i++) { 261 rv = kernel_get_func_list(slot_table[i]); 262 if (rv != CKR_OK) { 263 goto failed; 264 } 265 } 266 267 (void) free(pl); 268 return (CKR_OK); 269 270 failed: 271 for (i = 0; i < cur_slot_num; i++) { 272 (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 273 (void) free(slot_table[i]); 274 } 275 276 (void) free(slot_table); 277 (void) free(pl); 278 return (rv); 279 } 280