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