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