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 <security/cryptoki.h> 31 #include "softGlobal.h" 32 #include "softOps.h" 33 #include "softSession.h" 34 35 36 CK_RV 37 C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) 38 { 39 40 CK_RV rv; 41 soft_session_t *session_p; 42 boolean_t lock_held = B_TRUE; 43 44 if (!softtoken_initialized) 45 return (CKR_CRYPTOKI_NOT_INITIALIZED); 46 47 /* 48 * Obtain the session pointer. Also, increment the session 49 * reference count. 50 */ 51 rv = handle2session(hSession, &session_p); 52 if (rv != CKR_OK) 53 return (rv); 54 55 if (pMechanism == NULL) { 56 rv = CKR_ARGUMENTS_BAD; 57 goto clean_exit; 58 } 59 60 /* Acquire the session lock */ 61 (void) pthread_mutex_lock(&session_p->session_mutex); 62 63 /* Check to see if digest operation is already active */ 64 if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) { 65 /* 66 * Free the memory to avoid memory leak. 67 * digest.context is only a flat structure. 68 */ 69 70 if (session_p->digest.context) 71 free(session_p->digest.context); 72 } 73 74 /* 75 * This active flag will remain ON until application calls either 76 * C_Digest or C_DigestFinal to actually obtain the value of 77 * the message digest. 78 */ 79 session_p->digest.flags = CRYPTO_OPERATION_ACTIVE; 80 81 (void) pthread_mutex_unlock(&session_p->session_mutex); 82 83 rv = soft_digest_init(session_p, pMechanism); 84 85 if (rv != CKR_OK) { 86 (void) pthread_mutex_lock(&session_p->session_mutex); 87 session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE; 88 /* 89 * Decrement the session reference count. 90 * We hold the session lock, and SES_REFRELE() 91 * will release the session lock for us. 92 */ 93 SES_REFRELE(session_p, lock_held); 94 return (rv); 95 } 96 97 clean_exit: 98 /* 99 * Decrement the session reference count. 100 * We do not hold the session lock. 101 */ 102 lock_held = B_FALSE; 103 SES_REFRELE(session_p, lock_held); 104 return (rv); 105 } 106 107 108 CK_RV 109 C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 110 CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) 111 { 112 113 CK_RV rv; 114 soft_session_t *session_p; 115 boolean_t lock_held = B_TRUE; 116 117 if (!softtoken_initialized) 118 return (CKR_CRYPTOKI_NOT_INITIALIZED); 119 120 /* 121 * Obtain the session pointer. Also, increment the session 122 * reference count. 123 */ 124 rv = handle2session(hSession, &session_p); 125 if (rv != CKR_OK) 126 return (rv); 127 128 if (pData == NULL || pulDigestLen == NULL) { 129 rv = CKR_ARGUMENTS_BAD; 130 goto clean_exit; 131 } 132 133 /* Acquire the session lock */ 134 (void) pthread_mutex_lock(&session_p->session_mutex); 135 136 /* Application must call C_DigestInit before calling C_Digest */ 137 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) { 138 /* 139 * Decrement the session reference count. 140 * We hold the session lock, and SES_REFRELE() 141 * will release the session lock for us. 142 */ 143 SES_REFRELE(session_p, lock_held); 144 return (CKR_OPERATION_NOT_INITIALIZED); 145 } 146 147 /* 148 * C_Digest must be called without intervening C_DigestUpdate 149 * calls. 150 */ 151 if (session_p->digest.flags & CRYPTO_OPERATION_UPDATE) { 152 /* 153 * C_Digest can not be used to terminate a multi-part 154 * operation, so we'll leave the active digest operation 155 * flag on and let the application continue with the 156 * digest update operation. 157 * 158 * Decrement the session reference count. 159 * We hold the session lock, and SES_REFRELE() 160 * will release the session lock for us. 161 */ 162 SES_REFRELE(session_p, lock_held); 163 return (CKR_FUNCTION_FAILED); 164 } 165 166 (void) pthread_mutex_unlock(&session_p->session_mutex); 167 168 rv = soft_digest(session_p, pData, ulDataLen, pDigest, pulDigestLen); 169 170 if ((rv == CKR_BUFFER_TOO_SMALL) || 171 (pDigest == NULL && rv == CKR_OK)) { 172 /* 173 * We will not terminate the active digest operation flag, 174 * when the application-supplied buffer is too small, or 175 * the application asks for the length of buffer to hold 176 * the message digest. 177 * 178 * Decrement the session reference count. 179 * We do not hold the session lock. 180 */ 181 lock_held = B_FALSE; 182 SES_REFRELE(session_p, lock_held); 183 return (rv); 184 } 185 186 clean_exit: 187 /* 188 * Terminates the active digest operation. 189 * Application needs to call C_DigestInit again for next 190 * digest operation. 191 */ 192 (void) pthread_mutex_lock(&session_p->session_mutex); 193 session_p->digest.flags = 0; 194 195 /* 196 * Decrement the session reference count. 197 * We hold the session lock, and SES_REFRELE() 198 * will release the session lock for us. 199 */ 200 SES_REFRELE(session_p, lock_held); 201 202 return (rv); 203 } 204 205 206 CK_RV 207 C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 208 CK_ULONG ulPartLen) 209 { 210 211 CK_RV rv; 212 soft_session_t *session_p; 213 boolean_t lock_held = B_TRUE; 214 215 if (!softtoken_initialized) 216 return (CKR_CRYPTOKI_NOT_INITIALIZED); 217 218 /* 219 * Obtain the session pointer. Also, increment the session 220 * reference count. 221 */ 222 rv = handle2session(hSession, &session_p); 223 if (rv != CKR_OK) 224 return (rv); 225 226 if (pPart == NULL) { 227 rv = CKR_ARGUMENTS_BAD; 228 goto clean_exit; 229 } 230 231 /* Acquire the session lock */ 232 (void) pthread_mutex_lock(&session_p->session_mutex); 233 234 /* 235 * Application must call C_DigestInit before calling 236 * C_DigestUpdate. 237 */ 238 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) { 239 /* 240 * Decrement the session reference count. 241 * We hold the session lock, and SES_REFRELE() 242 * will release the session lock for us. 243 */ 244 SES_REFRELE(session_p, lock_held); 245 return (CKR_OPERATION_NOT_INITIALIZED); 246 } 247 248 /* Set update flag to protect C_Digest */ 249 session_p->digest.flags |= CRYPTO_OPERATION_UPDATE; 250 251 (void) pthread_mutex_unlock(&session_p->session_mutex); 252 253 rv = soft_digest_update(session_p, pPart, ulPartLen); 254 255 if (rv == CKR_OK) { 256 /* 257 * Decrement the session reference count. 258 * We do not hold the session lock. 259 */ 260 lock_held = B_FALSE; 261 SES_REFRELE(session_p, lock_held); 262 return (CKR_OK); 263 } 264 265 clean_exit: 266 /* 267 * After an error occurred, terminate the current digest 268 * operation by resetting the active and update flags. 269 */ 270 (void) pthread_mutex_lock(&session_p->session_mutex); 271 session_p->digest.flags = 0; 272 273 /* 274 * Decrement the session reference count. 275 * We hold the session lock, and SES_REFRELE() 276 * will release the session lock for us. 277 */ 278 SES_REFRELE(session_p, lock_held); 279 280 return (rv); 281 } 282 283 284 CK_RV 285 C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) 286 { 287 288 CK_RV rv; 289 soft_session_t *session_p; 290 soft_object_t *key_p; 291 boolean_t lock_held = B_TRUE; 292 293 if (!softtoken_initialized) 294 return (CKR_CRYPTOKI_NOT_INITIALIZED); 295 296 /* 297 * Obtain the session pointer. Also, increment the session 298 * reference count. 299 */ 300 rv = handle2session(hSession, &session_p); 301 if (rv != CKR_OK) 302 return (rv); 303 304 /* Obtain the object pointer. */ 305 HANDLE2OBJECT(hKey, key_p, rv); 306 if (rv != CKR_OK) 307 goto clean_exit; 308 309 (void) pthread_mutex_lock(&session_p->session_mutex); 310 311 /* 312 * Application must call C_DigestInit before calling 313 * C_DigestKey. 314 */ 315 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) { 316 /* 317 * Decrement the session reference count. 318 * We hold the session lock, and SES_REFRELE() 319 * will release the session lock for us. 320 */ 321 OBJ_REFRELE(key_p); 322 SES_REFRELE(session_p, lock_held); 323 return (CKR_OPERATION_NOT_INITIALIZED); 324 } 325 326 /* 327 * Remember the fact that a key was thrown into the mix, so that 328 * C_DigestFinal bzero()'s the digest context before freeing it. 329 */ 330 session_p->digest.flags |= (CRYPTO_KEY_DIGESTED | 331 CRYPTO_OPERATION_UPDATE); 332 333 (void) pthread_mutex_unlock(&session_p->session_mutex); 334 335 rv = soft_digest_key(session_p, key_p); 336 337 if (rv == CKR_OK) { 338 /* 339 * Decrement the session reference count. 340 * We do not hold the session lock. 341 */ 342 lock_held = B_FALSE; 343 OBJ_REFRELE(key_p); 344 SES_REFRELE(session_p, lock_held); 345 return (CKR_OK); 346 } 347 348 OBJ_REFRELE(key_p); 349 clean_exit: 350 /* 351 * After an error occurred, terminate the current digest 352 * operation by resetting the active and update flags. 353 */ 354 (void) pthread_mutex_lock(&session_p->session_mutex); 355 session_p->digest.flags = 0; 356 357 /* 358 * Decrement the session reference count. 359 * We hold the session lock, and SES_REFRELE() 360 * will release the session lock for us. 361 */ 362 SES_REFRELE(session_p, lock_held); 363 return (rv); 364 } 365 366 367 CK_RV 368 C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, 369 CK_ULONG_PTR pulDigestLen) 370 { 371 372 CK_RV rv; 373 soft_session_t *session_p; 374 boolean_t lock_held = B_TRUE; 375 376 if (!softtoken_initialized) 377 return (CKR_CRYPTOKI_NOT_INITIALIZED); 378 379 /* 380 * Obtain the session pointer. Also, increment the session 381 * reference count. 382 */ 383 rv = handle2session(hSession, &session_p); 384 if (rv != CKR_OK) 385 return (rv); 386 387 if (pulDigestLen == NULL) { 388 rv = CKR_ARGUMENTS_BAD; 389 goto clean_exit; 390 } 391 392 /* Acquire the session lock */ 393 (void) pthread_mutex_lock(&session_p->session_mutex); 394 395 /* 396 * Application must call C_DigestInit before calling 397 * C_DigestFinal. 398 */ 399 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) { 400 /* 401 * Decrement the session reference count. 402 * We hold the session lock, and SES_REFRELE() 403 * will release the session lock for us. 404 */ 405 SES_REFRELE(session_p, lock_held); 406 return (CKR_OPERATION_NOT_INITIALIZED); 407 } 408 409 (void) pthread_mutex_unlock(&session_p->session_mutex); 410 411 rv = soft_digest_final(session_p, pDigest, pulDigestLen); 412 413 if ((rv == CKR_BUFFER_TOO_SMALL) || 414 (pDigest == NULL && rv == CKR_OK)) { 415 /* 416 * We will not terminate the active digest operation flag, 417 * when the application-supplied buffer is too small, or 418 * the application asks for the length of buffer to hold 419 * the message digest. 420 * 421 * Decrement the session reference count. 422 * We do not hold the session lock. 423 */ 424 lock_held = B_FALSE; 425 SES_REFRELE(session_p, lock_held); 426 return (rv); 427 } 428 429 clean_exit: 430 /* Terminates the active digest operation */ 431 (void) pthread_mutex_lock(&session_p->session_mutex); 432 session_p->digest.flags = 0; 433 434 /* 435 * Decrement the session reference count. 436 * We hold the session lock, and SES_REFRELE() 437 * will release the session lock for us. 438 */ 439 SES_REFRELE(session_p, lock_held); 440 441 return (rv); 442 } 443