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