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