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 * Copyright 2018, Joyent, Inc. 25 */ 26 27 #include <pthread.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 #include <sys/crypto/ioctl.h> 31 #include <security/cryptoki.h> 32 #include "kernelGlobal.h" 33 #include "kernelSession.h" 34 #include "kernelObject.h" 35 36 37 /* 38 * Real decryptInit work. The caller doesn't hold the session lock. 39 */ 40 CK_RV 41 kernel_decrypt_init(kernel_session_t *session_p, kernel_object_t *key_p, 42 CK_MECHANISM_PTR pMechanism) 43 { 44 CK_RV rv; 45 crypto_decrypt_init_t decrypt_init; 46 crypto_mech_type_t k_mech_type; 47 boolean_t ses_lock_held = B_FALSE; 48 int r; 49 CK_AES_CCM_PARAMS ccm_params = { 0 }; 50 51 /* Check to see if key object allows for decryption. */ 52 if (key_p->is_lib_obj && !(key_p->bool_attr_mask & DECRYPT_BOOL_ON)) { 53 return (CKR_KEY_TYPE_INCONSISTENT); 54 } 55 56 /* Get the kernel's internal mechanism number. */ 57 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 58 if (rv != CKR_OK) 59 return (rv); 60 61 (void) pthread_mutex_lock(&session_p->session_mutex); 62 ses_lock_held = B_TRUE; 63 64 /* 65 * This active flag will remain ON until application calls either 66 * C_Decrypt or C_DecryptFinal to actually obtain the final piece 67 * of plaintext. 68 */ 69 session_p->decrypt.flags = CRYPTO_OPERATION_ACTIVE; 70 71 /* set up key data */ 72 if (!key_p->is_lib_obj) { 73 decrypt_init.di_key.ck_format = CRYPTO_KEY_REFERENCE; 74 decrypt_init.di_key.ck_obj_id = key_p->k_handle; 75 } else { 76 if (key_p->class == CKO_SECRET_KEY) { 77 decrypt_init.di_key.ck_format = CRYPTO_KEY_RAW; 78 decrypt_init.di_key.ck_data = 79 get_symmetric_key_value(key_p); 80 if (decrypt_init.di_key.ck_data == NULL) { 81 rv = CKR_HOST_MEMORY; 82 goto clean_exit; 83 } 84 /* KEF key lengths are expressed in bits */ 85 decrypt_init.di_key.ck_length = 86 OBJ_SEC(key_p)->sk_value_len << 3; 87 88 } else if (key_p->key_type == CKK_RSA) { 89 if (get_rsa_private_key(key_p, &decrypt_init.di_key) != 90 CKR_OK) { 91 rv = CKR_HOST_MEMORY; 92 goto clean_exit; 93 } 94 } else { 95 rv = CKR_KEY_TYPE_INCONSISTENT; 96 goto clean_exit; 97 } 98 } 99 100 decrypt_init.di_session = session_p->k_session; 101 session_p->decrypt.mech = *pMechanism; 102 103 /* Cache this capability value for efficiency */ 104 if (INPLACE_MECHANISM(session_p->decrypt.mech.mechanism)) { 105 session_p->decrypt.flags |= CRYPTO_OPERATION_INPLACE_OK; 106 } 107 (void) pthread_mutex_unlock(&session_p->session_mutex); 108 109 ses_lock_held = B_FALSE; 110 decrypt_init.di_mech.cm_type = k_mech_type; 111 decrypt_init.di_mech.cm_param = pMechanism->pParameter; 112 decrypt_init.di_mech.cm_param_len = pMechanism->ulParameterLen; 113 114 /* 115 * PKCS#11 uses CK_CCM_PARAMS as its mechanism parameter, while the 116 * kernel uses CK_AES_CCM_PARAMS. Unlike 117 * CK_GCM_PARAMS / CK_AES_GCM_PARAMS, the two definitions are not 118 * equivalent -- the fields are defined in different orders, so 119 * we must translate. 120 */ 121 if (session_p->decrypt.mech.mechanism == CKM_AES_CCM) { 122 if (pMechanism->ulParameterLen != sizeof (CK_CCM_PARAMS)) { 123 rv = CKR_MECHANISM_PARAM_INVALID; 124 goto clean_exit; 125 } 126 p11_to_kernel_ccm_params(pMechanism->pParameter, &ccm_params); 127 decrypt_init.di_mech.cm_param = (caddr_t)&ccm_params; 128 decrypt_init.di_mech.cm_param_len = sizeof (ccm_params); 129 } 130 131 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT_INIT, &decrypt_init)) < 0) { 132 if (errno != EINTR) 133 break; 134 } 135 if (r < 0) { 136 rv = CKR_FUNCTION_FAILED; 137 } else { 138 rv = crypto2pkcs11_error_number(decrypt_init.di_return_value); 139 } 140 141 /* Free memory allocated for decrypt_init.di_key */ 142 if (key_p->is_lib_obj) { 143 if (key_p->class == CKO_SECRET_KEY) { 144 free(decrypt_init.di_key.ck_data); 145 } else if (key_p->key_type == CKK_RSA) { 146 free_key_attributes(&decrypt_init.di_key); 147 } 148 } 149 150 clean_exit: 151 /* 152 * ccm_params does not contain any key material -- just lengths and 153 * pointers, therefore it does not need to be zeroed on exit. 154 */ 155 if (!ses_lock_held) { 156 (void) pthread_mutex_lock(&session_p->session_mutex); 157 ses_lock_held = B_TRUE; 158 } 159 160 if (rv != CKR_OK) 161 session_p->decrypt.flags &= ~CRYPTO_OPERATION_ACTIVE; 162 163 if (ses_lock_held) { 164 (void) pthread_mutex_unlock(&session_p->session_mutex); 165 ses_lock_held = B_FALSE; 166 } 167 168 return (rv); 169 } 170 171 CK_RV 172 C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 173 CK_OBJECT_HANDLE hKey) 174 { 175 176 CK_RV rv; 177 kernel_session_t *session_p; 178 kernel_object_t *key_p; 179 boolean_t ses_lock_held = B_FALSE; 180 181 if (!kernel_initialized) 182 return (CKR_CRYPTOKI_NOT_INITIALIZED); 183 184 if (pMechanism == NULL) { 185 return (CKR_ARGUMENTS_BAD); 186 } 187 188 /* Obtain the session pointer. */ 189 rv = handle2session(hSession, &session_p); 190 if (rv != CKR_OK) 191 return (rv); 192 193 /* Obtain the object pointer. */ 194 HANDLE2OBJECT(hKey, key_p, rv); 195 if (rv == CKR_OK) { 196 rv = kernel_decrypt_init(session_p, key_p, pMechanism); 197 OBJ_REFRELE(key_p); 198 } 199 200 REFRELE(session_p, ses_lock_held); 201 return (rv); 202 } 203 204 205 206 /* 207 * Real decrypt work. The caller doesn't hold the session lock. 208 */ 209 CK_RV 210 kernel_decrypt(kernel_session_t *session_p, CK_BYTE_PTR pEncryptedData, 211 CK_ULONG ulEncryptedData, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 212 { 213 crypto_decrypt_t decrypt; 214 boolean_t ses_lock_held = B_FALSE; 215 boolean_t inplace; 216 CK_RV rv; 217 int r; 218 219 (void) pthread_mutex_lock(&session_p->session_mutex); 220 ses_lock_held = B_TRUE; 221 222 /* Application must call C_DecryptInit before calling C_Decrypt. */ 223 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 224 rv = CKR_OPERATION_NOT_INITIALIZED; 225 goto clean_exit; 226 } 227 228 /* 229 * C_Decrypt must be called without intervening C_DecryptUpdate 230 * calls. 231 */ 232 if (session_p->decrypt.flags & CRYPTO_OPERATION_UPDATE) { 233 /* 234 * C_Decrypt cannot be used to terminate a multiple-part 235 * operation, so we'll leave the active decrypt operation 236 * flag on and let the application continue with the 237 * decrypt update operation. 238 */ 239 rv = CKR_FUNCTION_FAILED; 240 goto clean_exit; 241 } 242 243 decrypt.cd_session = session_p->k_session; 244 245 /* 246 * Certain mechanisms, where the length of the plaintext is 247 * same as the transformed ciphertext, can be optimized 248 * by the kernel into an in-place operation. Unfortunately, 249 * some applications use a plaintext buffer that is larger 250 * than it needs to be. We fix that here. 251 */ 252 inplace = (session_p->decrypt.flags & CRYPTO_OPERATION_INPLACE_OK) != 0; 253 254 if (ulEncryptedData < *pulDataLen && inplace) { 255 decrypt.cd_datalen = ulEncryptedData; 256 } else { 257 decrypt.cd_datalen = *pulDataLen; 258 } 259 (void) pthread_mutex_unlock(&session_p->session_mutex); 260 ses_lock_held = B_FALSE; 261 262 decrypt.cd_databuf = (char *)pData; 263 decrypt.cd_encrlen = ulEncryptedData; 264 decrypt.cd_encrbuf = (char *)pEncryptedData; 265 decrypt.cd_flags = 266 ((inplace && (pData != NULL)) || (pData == pEncryptedData)) && 267 (decrypt.cd_datalen == decrypt.cd_encrlen) ? 268 CRYPTO_INPLACE_OPERATION : 0; 269 270 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT, &decrypt)) < 0) { 271 if (errno != EINTR) 272 break; 273 } 274 if (r < 0) { 275 rv = CKR_FUNCTION_FAILED; 276 } else { 277 rv = crypto2pkcs11_error_number(decrypt.cd_return_value); 278 } 279 280 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 281 *pulDataLen = decrypt.cd_datalen; 282 283 clean_exit: 284 285 if (ses_lock_held) 286 (void) pthread_mutex_unlock(&session_p->session_mutex); 287 288 return (rv); 289 } 290 291 CK_RV 292 C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, 293 CK_ULONG ulEncryptedData, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 294 { 295 CK_RV rv; 296 kernel_session_t *session_p; 297 boolean_t ses_lock_held = B_FALSE; 298 299 if (!kernel_initialized) 300 return (CKR_CRYPTOKI_NOT_INITIALIZED); 301 302 /* Obtain the session pointer. */ 303 rv = handle2session(hSession, &session_p); 304 if (rv != CKR_OK) 305 return (rv); 306 307 /* 308 * No need to check pData because application might 309 * just want to know the length of decrypted data. 310 */ 311 if (pulDataLen == NULL) { 312 rv = CKR_ARGUMENTS_BAD; 313 goto clean_exit; 314 } 315 316 rv = kernel_decrypt(session_p, pEncryptedData, ulEncryptedData, pData, 317 pulDataLen); 318 319 if ((rv == CKR_BUFFER_TOO_SMALL) || 320 (rv == CKR_OK && pData == NULL)) { 321 /* 322 * We will not terminate the active decrypt operation flag, 323 * when the application-supplied buffer is too small, or 324 * the application asks for the length of buffer to hold 325 * the plaintext. 326 */ 327 REFRELE(session_p, ses_lock_held); 328 return (rv); 329 } 330 331 clean_exit: 332 /* 333 * Terminates the active decrypt operation. 334 * Application needs to call C_DecryptInit again for next 335 * decrypt operation. 336 */ 337 (void) pthread_mutex_lock(&session_p->session_mutex); 338 session_p->decrypt.flags = 0; 339 ses_lock_held = B_TRUE; 340 REFRELE(session_p, ses_lock_held); 341 342 return (rv); 343 } 344 345 346 CK_RV 347 C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, 348 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 349 CK_ULONG_PTR pulPartLen) 350 { 351 352 CK_RV rv; 353 kernel_session_t *session_p; 354 boolean_t ses_lock_held = B_FALSE; 355 boolean_t inplace; 356 crypto_decrypt_update_t decrypt_update; 357 int r; 358 359 if (!kernel_initialized) 360 return (CKR_CRYPTOKI_NOT_INITIALIZED); 361 362 /* Obtain the session pointer. */ 363 rv = handle2session(hSession, &session_p); 364 if (rv != CKR_OK) 365 return (rv); 366 367 if (pEncryptedPart == NULL) { 368 rv = CKR_ARGUMENTS_BAD; 369 goto clean_exit; 370 } 371 372 /* 373 * Only check if pulPartLen is NULL. 374 * No need to check if pPart is NULL because application 375 * might just ask for the length of buffer to hold the 376 * recovered data. 377 */ 378 if (pulPartLen == NULL) { 379 rv = CKR_ARGUMENTS_BAD; 380 goto clean_exit; 381 } 382 383 (void) pthread_mutex_lock(&session_p->session_mutex); 384 ses_lock_held = B_TRUE; 385 386 /* 387 * Application must call C_DecryptInit before calling 388 * C_DecryptUpdate. 389 */ 390 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 391 REFRELE(session_p, ses_lock_held); 392 return (CKR_OPERATION_NOT_INITIALIZED); 393 } 394 395 session_p->decrypt.flags |= CRYPTO_OPERATION_UPDATE; 396 397 decrypt_update.du_session = session_p->k_session; 398 (void) pthread_mutex_unlock(&session_p->session_mutex); 399 ses_lock_held = B_FALSE; 400 401 decrypt_update.du_datalen = *pulPartLen; 402 decrypt_update.du_databuf = (char *)pPart; 403 decrypt_update.du_encrlen = ulEncryptedPartLen; 404 decrypt_update.du_encrbuf = (char *)pEncryptedPart; 405 406 inplace = (session_p->decrypt.flags & CRYPTO_OPERATION_INPLACE_OK) != 0; 407 decrypt_update.du_flags = 408 ((inplace && (pPart != NULL)) || (pPart == pEncryptedPart)) && 409 (decrypt_update.du_datalen == decrypt_update.du_encrlen) ? 410 CRYPTO_INPLACE_OPERATION : 0; 411 412 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT_UPDATE, 413 &decrypt_update)) < 0) { 414 if (errno != EINTR) 415 break; 416 } 417 if (r < 0) { 418 rv = CKR_FUNCTION_FAILED; 419 } else { 420 rv = crypto2pkcs11_error_number( 421 decrypt_update.du_return_value); 422 } 423 424 /* 425 * If CKR_OK or CKR_BUFFER_TOO_SMALL, set the output length. 426 * We don't terminate the current decryption operation. 427 */ 428 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 429 *pulPartLen = decrypt_update.du_datalen; 430 REFRELE(session_p, ses_lock_held); 431 return (rv); 432 } 433 434 clean_exit: 435 /* 436 * After an error occurred, terminate the current decrypt 437 * operation by resetting the active and update flags. 438 */ 439 (void) pthread_mutex_lock(&session_p->session_mutex); 440 session_p->decrypt.flags = 0; 441 ses_lock_held = B_TRUE; 442 REFRELE(session_p, ses_lock_held); 443 444 return (rv); 445 } 446 447 448 CK_RV 449 C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, 450 CK_ULONG_PTR pulLastPartLen) 451 { 452 453 CK_RV rv; 454 kernel_session_t *session_p; 455 boolean_t ses_lock_held = B_FALSE; 456 crypto_decrypt_final_t decrypt_final; 457 int r; 458 459 if (!kernel_initialized) 460 return (CKR_CRYPTOKI_NOT_INITIALIZED); 461 462 /* Obtain the session pointer. */ 463 rv = handle2session(hSession, &session_p); 464 if (rv != CKR_OK) 465 return (rv); 466 467 if (pulLastPartLen == NULL) { 468 rv = CKR_ARGUMENTS_BAD; 469 goto clean_exit; 470 } 471 472 (void) pthread_mutex_lock(&session_p->session_mutex); 473 ses_lock_held = B_TRUE; 474 475 /* 476 * Application must call C_DecryptInit before calling 477 * C_DecryptFinal. 478 */ 479 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 480 REFRELE(session_p, ses_lock_held); 481 return (CKR_OPERATION_NOT_INITIALIZED); 482 } 483 484 decrypt_final.df_session = session_p->k_session; 485 (void) pthread_mutex_unlock(&session_p->session_mutex); 486 ses_lock_held = B_FALSE; 487 488 decrypt_final.df_datalen = *pulLastPartLen; 489 decrypt_final.df_databuf = (char *)pLastPart; 490 491 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT_FINAL, 492 &decrypt_final)) < 0) { 493 if (errno != EINTR) 494 break; 495 } 496 if (r < 0) { 497 rv = CKR_FUNCTION_FAILED; 498 } else { 499 rv = crypto2pkcs11_error_number(decrypt_final.df_return_value); 500 } 501 502 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 503 *pulLastPartLen = decrypt_final.df_datalen; 504 505 if (rv == CKR_BUFFER_TOO_SMALL || 506 (rv == CKR_OK && pLastPart == NULL)) { 507 /* 508 * We will not terminate the active decrypt operation flag, 509 * when the application-supplied buffer is too small, or 510 * the application asks for the length of buffer to hold 511 * the plaintext. 512 */ 513 REFRELE(session_p, ses_lock_held); 514 return (rv); 515 } 516 517 clean_exit: 518 /* Terminates the active decrypt operation */ 519 (void) pthread_mutex_lock(&session_p->session_mutex); 520 session_p->decrypt.flags = 0; 521 ses_lock_held = B_TRUE; 522 REFRELE(session_p, ses_lock_held); 523 524 return (rv); 525 } 526