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 OBJ_REFRELE(key_p); 172 } 173 174 REFRELE(session_p, ses_lock_held); 175 return (rv); 176 } 177 178 179 180 /* 181 * Real decrypt work. The caller doesn't hold the session lock. 182 */ 183 CK_RV 184 kernel_decrypt(kernel_session_t *session_p, CK_BYTE_PTR pEncryptedData, 185 CK_ULONG ulEncryptedData, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 186 { 187 crypto_decrypt_t decrypt; 188 boolean_t ses_lock_held = B_FALSE; 189 CK_RV rv; 190 int r; 191 192 (void) pthread_mutex_lock(&session_p->session_mutex); 193 ses_lock_held = B_TRUE; 194 195 /* Application must call C_DecryptInit before calling C_Decrypt. */ 196 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 197 rv = CKR_OPERATION_NOT_INITIALIZED; 198 goto clean_exit; 199 } 200 201 /* 202 * C_Decrypt must be called without intervening C_DecryptUpdate 203 * calls. 204 */ 205 if (session_p->decrypt.flags & CRYPTO_OPERATION_UPDATE) { 206 /* 207 * C_Decrypt cannot be used to terminate a multiple-part 208 * operation, so we'll leave the active decrypt operation 209 * flag on and let the application continue with the 210 * decrypt update operation. 211 */ 212 rv = CKR_FUNCTION_FAILED; 213 goto clean_exit; 214 } 215 216 decrypt.cd_session = session_p->k_session; 217 (void) pthread_mutex_unlock(&session_p->session_mutex); 218 ses_lock_held = B_FALSE; 219 220 decrypt.cd_datalen = *pulDataLen; 221 decrypt.cd_databuf = (char *)pData; 222 decrypt.cd_encrlen = ulEncryptedData; 223 decrypt.cd_encrbuf = (char *)pEncryptedData; 224 225 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT, &decrypt)) < 0) { 226 if (errno != EINTR) 227 break; 228 } 229 if (r < 0) { 230 rv = CKR_FUNCTION_FAILED; 231 } else { 232 rv = crypto2pkcs11_error_number(decrypt.cd_return_value); 233 } 234 235 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 236 *pulDataLen = decrypt.cd_datalen; 237 238 clean_exit: 239 240 if (ses_lock_held) 241 (void) pthread_mutex_unlock(&session_p->session_mutex); 242 243 return (rv); 244 } 245 246 CK_RV 247 C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, 248 CK_ULONG ulEncryptedData, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 249 { 250 CK_RV rv; 251 kernel_session_t *session_p; 252 boolean_t ses_lock_held = B_FALSE; 253 254 if (!kernel_initialized) 255 return (CKR_CRYPTOKI_NOT_INITIALIZED); 256 257 /* Obtain the session pointer. */ 258 rv = handle2session(hSession, &session_p); 259 if (rv != CKR_OK) 260 return (rv); 261 262 /* 263 * No need to check pData because application might 264 * just want to know the length of decrypted data. 265 */ 266 if (pulDataLen == NULL) { 267 rv = CKR_ARGUMENTS_BAD; 268 goto clean_exit; 269 } 270 271 rv = kernel_decrypt(session_p, pEncryptedData, ulEncryptedData, pData, 272 pulDataLen); 273 274 if ((rv == CKR_BUFFER_TOO_SMALL) || 275 (rv == CKR_OK && pData == NULL)) { 276 /* 277 * We will not terminate the active decrypt operation flag, 278 * when the application-supplied buffer is too small, or 279 * the application asks for the length of buffer to hold 280 * the plaintext. 281 */ 282 REFRELE(session_p, ses_lock_held); 283 return (rv); 284 } 285 286 clean_exit: 287 /* 288 * Terminates the active decrypt operation. 289 * Application needs to call C_DecryptInit again for next 290 * decrypt operation. 291 */ 292 (void) pthread_mutex_lock(&session_p->session_mutex); 293 session_p->decrypt.flags = 0; 294 ses_lock_held = B_TRUE; 295 REFRELE(session_p, ses_lock_held); 296 297 return (rv); 298 } 299 300 301 CK_RV 302 C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, 303 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 304 CK_ULONG_PTR pulPartLen) 305 { 306 307 CK_RV rv; 308 kernel_session_t *session_p; 309 boolean_t ses_lock_held = B_FALSE; 310 crypto_decrypt_update_t decrypt_update; 311 int r; 312 313 if (!kernel_initialized) 314 return (CKR_CRYPTOKI_NOT_INITIALIZED); 315 316 /* Obtain the session pointer. */ 317 rv = handle2session(hSession, &session_p); 318 if (rv != CKR_OK) 319 return (rv); 320 321 if (pEncryptedPart == NULL) { 322 rv = CKR_ARGUMENTS_BAD; 323 goto clean_exit; 324 } 325 326 /* 327 * Only check if pulPartLen is NULL. 328 * No need to check if pPart is NULL because application 329 * might just ask for the length of buffer to hold the 330 * recovered data. 331 */ 332 if (pulPartLen == NULL) { 333 rv = CKR_ARGUMENTS_BAD; 334 goto clean_exit; 335 } 336 337 (void) pthread_mutex_lock(&session_p->session_mutex); 338 ses_lock_held = B_TRUE; 339 340 /* 341 * Application must call C_DecryptInit before calling 342 * C_DecryptUpdate. 343 */ 344 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 345 REFRELE(session_p, ses_lock_held); 346 return (CKR_OPERATION_NOT_INITIALIZED); 347 } 348 349 session_p->decrypt.flags |= CRYPTO_OPERATION_UPDATE; 350 351 decrypt_update.du_session = session_p->k_session; 352 (void) pthread_mutex_unlock(&session_p->session_mutex); 353 ses_lock_held = B_FALSE; 354 355 decrypt_update.du_datalen = *pulPartLen; 356 decrypt_update.du_databuf = (char *)pPart; 357 decrypt_update.du_encrlen = ulEncryptedPartLen; 358 decrypt_update.du_encrbuf = (char *)pEncryptedPart; 359 360 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT_UPDATE, 361 &decrypt_update)) < 0) { 362 if (errno != EINTR) 363 break; 364 } 365 if (r < 0) { 366 rv = CKR_FUNCTION_FAILED; 367 } else { 368 rv = crypto2pkcs11_error_number( 369 decrypt_update.du_return_value); 370 } 371 372 /* 373 * If CKR_OK or CKR_BUFFER_TOO_SMALL, set the output length. 374 * We don't terminate the current decryption operation. 375 */ 376 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 377 *pulPartLen = decrypt_update.du_datalen; 378 REFRELE(session_p, ses_lock_held); 379 return (rv); 380 } 381 382 clean_exit: 383 /* 384 * After an error occurred, terminate the current decrypt 385 * operation by resetting the active and update flags. 386 */ 387 (void) pthread_mutex_lock(&session_p->session_mutex); 388 session_p->decrypt.flags = 0; 389 ses_lock_held = B_TRUE; 390 REFRELE(session_p, ses_lock_held); 391 392 return (rv); 393 } 394 395 396 CK_RV 397 C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, 398 CK_ULONG_PTR pulLastPartLen) 399 { 400 401 CK_RV rv; 402 kernel_session_t *session_p; 403 boolean_t ses_lock_held = B_FALSE; 404 crypto_decrypt_final_t decrypt_final; 405 int r; 406 407 if (!kernel_initialized) 408 return (CKR_CRYPTOKI_NOT_INITIALIZED); 409 410 /* Obtain the session pointer. */ 411 rv = handle2session(hSession, &session_p); 412 if (rv != CKR_OK) 413 return (rv); 414 415 if (pulLastPartLen == NULL) { 416 rv = CKR_ARGUMENTS_BAD; 417 goto clean_exit; 418 } 419 420 (void) pthread_mutex_lock(&session_p->session_mutex); 421 ses_lock_held = B_TRUE; 422 423 /* 424 * Application must call C_DecryptInit before calling 425 * C_DecryptFinal. 426 */ 427 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 428 REFRELE(session_p, ses_lock_held); 429 return (CKR_OPERATION_NOT_INITIALIZED); 430 } 431 432 decrypt_final.df_session = session_p->k_session; 433 (void) pthread_mutex_unlock(&session_p->session_mutex); 434 ses_lock_held = B_FALSE; 435 436 decrypt_final.df_datalen = *pulLastPartLen; 437 decrypt_final.df_databuf = (char *)pLastPart; 438 439 while ((r = ioctl(kernel_fd, CRYPTO_DECRYPT_FINAL, 440 &decrypt_final)) < 0) { 441 if (errno != EINTR) 442 break; 443 } 444 if (r < 0) { 445 rv = CKR_FUNCTION_FAILED; 446 } else { 447 rv = crypto2pkcs11_error_number(decrypt_final.df_return_value); 448 } 449 450 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 451 *pulLastPartLen = decrypt_final.df_datalen; 452 453 if (rv == CKR_BUFFER_TOO_SMALL || 454 (rv == CKR_OK && pLastPart == NULL)) { 455 /* 456 * We will not terminate the active decrypt operation flag, 457 * when the application-supplied buffer is too small, or 458 * the application asks for the length of buffer to hold 459 * the plaintext. 460 */ 461 REFRELE(session_p, ses_lock_held); 462 return (rv); 463 } 464 465 clean_exit: 466 /* Terminates the active decrypt operation */ 467 (void) pthread_mutex_lock(&session_p->session_mutex); 468 session_p->decrypt.flags = 0; 469 ses_lock_held = B_TRUE; 470 REFRELE(session_p, ses_lock_held); 471 472 return (rv); 473 } 474