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