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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdlib.h> 28 #include <strings.h> 29 #include <security/cryptoki.h> 30 #include <cryptoutil.h> 31 #include <errno.h> 32 #include <sys/crypto/api.h> 33 #include <sys/crypto/common.h> 34 #include <sys/crypto/ioctl.h> 35 #include <sys/crypto/spi.h> 36 #include "kernelGlobal.h" 37 #include "kernelSlot.h" 38 39 40 /* ARGSUSED */ 41 CK_RV 42 C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, 43 CK_ULONG_PTR pulCount) 44 { 45 int i; 46 47 if (!kernel_initialized) 48 return (CKR_CRYPTOKI_NOT_INITIALIZED); 49 50 if (pulCount == NULL) { 51 return (CKR_ARGUMENTS_BAD); 52 } 53 54 if (pSlotList == NULL) { 55 *pulCount = slot_count; 56 return (CKR_OK); 57 } 58 59 if (*pulCount < slot_count) { 60 *pulCount = slot_count; 61 return (CKR_BUFFER_TOO_SMALL); 62 } 63 64 *pulCount = slot_count; 65 66 /* 67 * The slotID returned to an application will be the index to 68 * the slot_table. The library will map to the provider_id when 69 * making any ioctl call. 70 */ 71 for (i = 0; i < slot_count; i++) { 72 pSlotList[i] = i; 73 } 74 75 return (CKR_OK); 76 } 77 78 79 CK_RV 80 C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) 81 { 82 CK_RV rv; 83 crypto_get_provider_info_t gi; 84 int r; 85 86 if (!kernel_initialized) 87 return (CKR_CRYPTOKI_NOT_INITIALIZED); 88 89 if (slotID >= slot_count) { 90 return (CKR_SLOT_ID_INVALID); 91 } 92 93 if (pInfo == NULL) 94 return (CKR_ARGUMENTS_BAD); 95 96 /* kernel provider numbers start with 0 */ 97 gi.gi_provider_id = slot_table[slotID]->sl_provider_id; 98 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_INFO, &gi)) < 0) { 99 if (errno != EINTR) 100 break; 101 } 102 if (r < 0) { 103 rv = CKR_FUNCTION_FAILED; 104 } else { 105 if (gi.gi_return_value != CRYPTO_SUCCESS) { 106 rv = crypto2pkcs11_error_number( 107 gi.gi_return_value); 108 } else { 109 rv = CKR_OK; 110 } 111 } 112 113 if (rv == CKR_OK) { 114 bcopy(gi.gi_provider_data.pd_prov_desc, 115 pInfo->slotDescription, CRYPTO_PROVIDER_DESCR_MAX_LEN); 116 bcopy(gi.gi_provider_data.pd_manufacturerID, 117 pInfo->manufacturerID, CRYPTO_EXT_SIZE_MANUF); 118 pInfo->flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; 119 pInfo->hardwareVersion.major = 120 gi.gi_provider_data.pd_hardware_version.cv_major; 121 pInfo->hardwareVersion.minor = 122 gi.gi_provider_data.pd_hardware_version.cv_minor; 123 pInfo->firmwareVersion.major = 124 gi.gi_provider_data.pd_firmware_version.cv_major; 125 pInfo->firmwareVersion.minor = 126 gi.gi_provider_data.pd_firmware_version.cv_minor; 127 } 128 129 return (rv); 130 } 131 132 133 CK_RV 134 C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) 135 { 136 CK_RV rv; 137 crypto_get_provider_info_t gi; 138 int r; 139 140 if (!kernel_initialized) 141 return (CKR_CRYPTOKI_NOT_INITIALIZED); 142 143 if (slotID >= slot_count) 144 return (CKR_SLOT_ID_INVALID); 145 146 if (pInfo == NULL) 147 return (CKR_ARGUMENTS_BAD); 148 149 gi.gi_provider_id = slot_table[slotID]->sl_provider_id; 150 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_INFO, &gi)) < 0) { 151 if (errno != EINTR) 152 break; 153 } 154 if (r < 0) { 155 rv = CKR_FUNCTION_FAILED; 156 } else { 157 rv = crypto2pkcs11_error_number(gi.gi_return_value); 158 } 159 160 if (rv == CKR_OK) { 161 bcopy(gi.gi_provider_data.pd_label, pInfo->label, 162 CRYPTO_EXT_SIZE_LABEL); 163 bcopy(gi.gi_provider_data.pd_manufacturerID, 164 pInfo->manufacturerID, CRYPTO_EXT_SIZE_MANUF); 165 bcopy(gi.gi_provider_data.pd_model, pInfo->model, 166 CRYPTO_EXT_SIZE_MODEL); 167 bcopy(gi.gi_provider_data.pd_serial_number, 168 pInfo->serialNumber, CRYPTO_EXT_SIZE_SERIAL); 169 pInfo->flags = gi.gi_provider_data.pd_flags; 170 pInfo->ulMaxSessionCount = 171 gi.gi_provider_data.pd_max_session_count; 172 pInfo->ulSessionCount = 173 gi.gi_provider_data.pd_session_count; 174 pInfo->ulMaxRwSessionCount = 175 gi.gi_provider_data.pd_max_rw_session_count; 176 pInfo->ulRwSessionCount = 177 gi.gi_provider_data.pd_rw_session_count; 178 pInfo->ulMaxPinLen = 179 gi.gi_provider_data.pd_max_pin_len; 180 pInfo->ulMinPinLen = 181 gi.gi_provider_data.pd_min_pin_len; 182 pInfo->ulTotalPublicMemory = 183 gi.gi_provider_data.pd_total_public_memory; 184 pInfo->ulFreePublicMemory = 185 gi.gi_provider_data.pd_free_public_memory; 186 pInfo->ulTotalPrivateMemory = 187 gi.gi_provider_data.pd_total_private_memory; 188 pInfo->ulFreePrivateMemory = 189 gi.gi_provider_data.pd_free_private_memory; 190 pInfo->hardwareVersion.major = 191 gi.gi_provider_data.pd_hardware_version.cv_major; 192 pInfo->hardwareVersion.minor = 193 gi.gi_provider_data.pd_hardware_version.cv_minor; 194 pInfo->firmwareVersion.major = 195 gi.gi_provider_data.pd_firmware_version.cv_major; 196 pInfo->firmwareVersion.minor = 197 gi.gi_provider_data.pd_firmware_version.cv_minor; 198 (void) strncpy((char *)pInfo->utcTime, 199 (const char *)gi.gi_provider_data.pd_time, 200 CRYPTO_EXT_SIZE_TIME); 201 202 } 203 204 return (rv); 205 206 207 } 208 209 /*ARGSUSED*/ 210 CK_RV 211 C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) 212 { 213 if (!kernel_initialized) 214 return (CKR_CRYPTOKI_NOT_INITIALIZED); 215 216 return (CKR_FUNCTION_NOT_SUPPORTED); 217 } 218 219 220 CK_RV 221 C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, 222 CK_ULONG_PTR pulCount) 223 { 224 CK_MECHANISM_TYPE type; 225 CK_RV rv; 226 CK_FLAGS flags; 227 CK_ULONG specified_count, count = 0; 228 crypto_get_provider_mechanisms_t *pm, tmp; 229 crypto_get_provider_mechanism_info_t mechanism_info; 230 crypto_provider_id_t provider_id; 231 size_t alloc_bytes; 232 int i, r; 233 234 if (!kernel_initialized) 235 return (CKR_CRYPTOKI_NOT_INITIALIZED); 236 237 if (slotID >= slot_count) 238 return (CKR_SLOT_ID_INVALID); 239 240 /* kernel provider numbers start with 0 */ 241 provider_id = slot_table[slotID]->sl_provider_id; 242 243 if (pMechanismList != NULL) { 244 if (pulCount == NULL) { 245 return (CKR_ARGUMENTS_BAD); 246 } else if (*pulCount == 0) { 247 return (CKR_ARGUMENTS_BAD); 248 } 249 } 250 specified_count = *pulCount; 251 tmp.pm_provider_id = provider_id; 252 tmp.pm_count = 0; 253 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISMS, 254 &tmp)) < 0) { 255 if (errno != EINTR) 256 break; 257 } 258 if (r < 0) { 259 return (CKR_FUNCTION_FAILED); 260 } else { 261 if (tmp.pm_return_value != CRYPTO_SUCCESS) { 262 rv = crypto2pkcs11_error_number(tmp.pm_return_value); 263 return (rv); 264 } 265 alloc_bytes = sizeof (crypto_get_provider_mechanisms_t) + 266 (tmp.pm_count - 1) * sizeof (crypto_mech_name_t); 267 } 268 269 pm = malloc(alloc_bytes); 270 if (pm == NULL) 271 return (CKR_HOST_MEMORY); 272 273 pm->pm_provider_id = provider_id; 274 pm->pm_count = tmp.pm_count; 275 276 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISMS, pm)) < 0) { 277 if (errno != EINTR) 278 break; 279 } 280 if (r < 0) { 281 rv = CKR_FUNCTION_FAILED; 282 } else { 283 rv = crypto2pkcs11_error_number(pm->pm_return_value); 284 } 285 286 if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL) 287 goto clean_exit; 288 289 for (i = 0; i < pm->pm_count; i++) { 290 mechanism_info.mi_provider_id = provider_id; 291 bcopy(&pm->pm_list[i][0], mechanism_info.mi_mechanism_name, 292 sizeof (crypto_mech_name_t)); 293 294 /* 295 * Get each mechanism's flags. 296 * The ioctl should not fail since the mechanism info is 297 * already in the kernel and a call doesn't have to be made 298 * to the provider. If it fails, nothing can be done other 299 * than skip the mechanism. 300 */ 301 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO, 302 &mechanism_info)) < 0) { 303 if (errno != EINTR) 304 break; 305 } 306 if (r < 0) { 307 continue; 308 } 309 310 if (mechanism_info.mi_return_value != CRYPTO_SUCCESS) 311 continue; 312 313 flags = mechanism_info.mi_flags; 314 315 /* 316 * Atomic flags are not part of PKCS#11 so we filter 317 * them out here. 318 */ 319 flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC | 320 CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC | 321 CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC | 322 CRYPTO_FG_SIGN_RECOVER_ATOMIC | 323 CRYPTO_FG_VERIFY_RECOVER_ATOMIC | 324 CRYPTO_FG_ENCRYPT_MAC_ATOMIC | 325 CRYPTO_FG_MAC_DECRYPT_ATOMIC); 326 327 /* mechanism has no PKCS#11 flags, so don't report it */ 328 if (flags == 0) 329 continue; 330 331 /* 332 * The kernel framework has a pseudo mechanism 333 * for RNG which we remove from the list of mechanisms. 334 */ 335 if (strcmp(&pm->pm_list[i][0], "random") != 0) { 336 337 if (pkcs11_str2mech(&pm->pm_list[i][0], 338 &type) != CKR_OK) 339 continue; 340 341 if (pMechanismList != NULL && rv == CKR_OK && 342 (count < specified_count)) 343 pMechanismList[count] = type; 344 345 count++; 346 } 347 348 } 349 350 if (pMechanismList != NULL && (count > specified_count)) 351 rv = CKR_BUFFER_TOO_SMALL; 352 353 *pulCount = count; 354 355 clean_exit: 356 free(pm); 357 return (rv); 358 } 359 360 361 CK_RV 362 C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 363 CK_MECHANISM_INFO_PTR pInfo) 364 { 365 uint32_t k_mi_flags; 366 CK_RV rv; 367 368 if (!kernel_initialized) 369 return (CKR_CRYPTOKI_NOT_INITIALIZED); 370 371 if (slotID >= slot_count) 372 return (CKR_SLOT_ID_INVALID); 373 374 if (pInfo == NULL) { 375 return (CKR_ARGUMENTS_BAD); 376 } 377 378 rv = get_mechanism_info(slot_table[slotID], type, pInfo, &k_mi_flags); 379 380 return (rv); 381 } 382 383 384 /*ARGSUSED*/ 385 CK_RV 386 C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, 387 CK_UTF8CHAR_PTR pLabel) 388 { 389 if (!kernel_initialized) 390 return (CKR_CRYPTOKI_NOT_INITIALIZED); 391 392 return (CKR_FUNCTION_NOT_SUPPORTED); 393 } 394 395 /*ARGSUSED*/ 396 CK_RV 397 C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) 398 { 399 if (!kernel_initialized) 400 return (CKR_CRYPTOKI_NOT_INITIALIZED); 401 402 return (CKR_FUNCTION_NOT_SUPPORTED); 403 } 404 405 406 CK_RV 407 C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, 408 CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen) 409 { 410 CK_RV rv = CKR_OK; 411 kernel_session_t *session_p; 412 boolean_t ses_lock_held = B_FALSE; 413 crypto_set_pin_t setpin; 414 int r; 415 416 if (!kernel_initialized) 417 return (CKR_CRYPTOKI_NOT_INITIALIZED); 418 419 /* 420 * Obtain the session pointer. Also, increment the session 421 * reference count. 422 */ 423 rv = handle2session(hSession, &session_p); 424 if (rv != CKR_OK) 425 return (rv); 426 427 /* Make sure it is a RW session. */ 428 if (session_p->ses_RO) { 429 rv = CKR_SESSION_READ_ONLY; 430 REFRELE(session_p, ses_lock_held); 431 return (rv); 432 } 433 434 /* Lock the session and make the CRYPTO_SET_PIN ioctl call. */ 435 (void) pthread_mutex_lock(&session_p->session_mutex); 436 ses_lock_held = B_TRUE; 437 438 setpin.sp_session = session_p->k_session; 439 setpin.sp_old_pin = (char *)pOldPin; 440 setpin.sp_old_len = ulOldLen; 441 setpin.sp_new_pin = (char *)pNewPin; 442 setpin.sp_new_len = ulNewLen; 443 444 while ((r = ioctl(kernel_fd, CRYPTO_SET_PIN, &setpin)) < 0) { 445 if (errno != EINTR) 446 break; 447 } 448 if (r < 0) { 449 rv = CKR_FUNCTION_FAILED; 450 } else { 451 rv = crypto2pkcs11_error_number(setpin.sp_return_value); 452 } 453 454 REFRELE(session_p, ses_lock_held); 455 return (rv); 456 } 457