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