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 (pulSignatureLen == NULL || 121 ((*pulSignatureLen != 0) && (pSignature == NULL))) { 122 rv = CKR_ARGUMENTS_BAD; 123 goto clean_exit; 124 } 125 126 (void) pthread_mutex_lock(&session_p->session_mutex); 127 lock_held = B_TRUE; 128 129 /* Application must call C_SignInit before calling C_Sign. */ 130 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 131 SES_REFRELE(session_p, lock_held); 132 return (CKR_OPERATION_NOT_INITIALIZED); 133 } 134 135 /* 136 * C_Sign must be called without intervening C_SignUpdate 137 * calls. 138 */ 139 if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) { 140 /* 141 * C_Sign can not be used to terminate a multi-part 142 * operation, so we'll leave the active sign operation 143 * flag on and let the application continue with the 144 * sign update operation. 145 */ 146 SES_REFRELE(session_p, lock_held); 147 return (CKR_FUNCTION_FAILED); 148 } 149 150 (void) pthread_mutex_unlock(&session_p->session_mutex); 151 lock_held = B_FALSE; 152 153 rv = soft_sign(session_p, pData, ulDataLen, pSignature, 154 pulSignatureLen); 155 156 if ((rv == CKR_BUFFER_TOO_SMALL) || 157 (pSignature == NULL && rv == CKR_OK)) { 158 /* 159 * We will not terminate the active sign operation flag, 160 * when the application-supplied buffer is too small, or 161 * the application asks for the length of buffer to hold 162 * the signature. 163 */ 164 SES_REFRELE(session_p, lock_held); 165 return (rv); 166 } 167 168 clean_exit: 169 /* Clear contexts, free key, and release session counter */ 170 soft_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); 171 return (rv); 172 } 173 174 175 CK_RV 176 C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 177 CK_ULONG ulPartLen) 178 { 179 180 CK_RV rv; 181 soft_session_t *session_p; 182 boolean_t lock_held = B_FALSE; 183 184 if (!softtoken_initialized) 185 return (CKR_CRYPTOKI_NOT_INITIALIZED); 186 187 /* Obtain the session pointer */ 188 rv = handle2session(hSession, &session_p); 189 if (rv != CKR_OK) 190 return (rv); 191 192 if (ulPartLen == 0) { 193 SES_REFRELE(session_p, lock_held); 194 return (CKR_OK); 195 } 196 197 if (pPart == NULL) { 198 rv = CKR_ARGUMENTS_BAD; 199 goto clean_exit; 200 } 201 202 (void) pthread_mutex_lock(&session_p->session_mutex); 203 lock_held = B_TRUE; 204 205 /* 206 * Application must call C_SignInit before calling 207 * C_SignUpdate. 208 */ 209 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 210 SES_REFRELE(session_p, lock_held); 211 return (CKR_OPERATION_NOT_INITIALIZED); 212 } 213 214 session_p->sign.flags |= CRYPTO_OPERATION_UPDATE; 215 216 (void) pthread_mutex_unlock(&session_p->session_mutex); 217 lock_held = B_FALSE; 218 219 rv = soft_sign_update(session_p, pPart, ulPartLen); 220 221 if (rv == CKR_OK) { 222 SES_REFRELE(session_p, lock_held); 223 return (rv); 224 } 225 226 clean_exit: 227 /* After error, clear context, free key, & release session counter */ 228 soft_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); 229 return (rv); 230 231 } 232 233 234 CK_RV 235 C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 236 CK_ULONG_PTR pulSignatureLen) 237 { 238 239 CK_RV rv; 240 soft_session_t *session_p; 241 boolean_t lock_held = B_FALSE; 242 243 if (!softtoken_initialized) 244 return (CKR_CRYPTOKI_NOT_INITIALIZED); 245 246 /* Obtain the session pointer */ 247 rv = handle2session(hSession, &session_p); 248 if (rv != CKR_OK) 249 return (rv); 250 251 if (pulSignatureLen == NULL) { 252 rv = CKR_ARGUMENTS_BAD; 253 goto clean_exit; 254 } 255 256 (void) pthread_mutex_lock(&session_p->session_mutex); 257 lock_held = B_TRUE; 258 259 /* 260 * Application must call C_SignInit before calling 261 * C_SignFinal. 262 */ 263 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 264 SES_REFRELE(session_p, lock_held); 265 return (CKR_OPERATION_NOT_INITIALIZED); 266 } 267 268 (void) pthread_mutex_unlock(&session_p->session_mutex); 269 lock_held = B_FALSE; 270 271 rv = soft_sign_final(session_p, pSignature, pulSignatureLen); 272 273 if ((rv == CKR_BUFFER_TOO_SMALL) || 274 (pSignature == NULL && rv == CKR_OK)) { 275 /* 276 * We will not terminate the active sign operation flag, 277 * when the application-supplied buffer is too small, or 278 * the application asks for the length of buffer to hold 279 * the signature. 280 */ 281 SES_REFRELE(session_p, lock_held); 282 return (rv); 283 } 284 285 clean_exit: 286 /* Clear contexts, free key, and release session counter */ 287 soft_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); 288 return (rv); 289 } 290 291 292 CK_RV 293 C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 294 CK_OBJECT_HANDLE hKey) 295 { 296 297 CK_RV rv; 298 soft_session_t *session_p; 299 soft_object_t *key_p; 300 boolean_t lock_held = B_FALSE; 301 302 if (!softtoken_initialized) 303 return (CKR_CRYPTOKI_NOT_INITIALIZED); 304 305 /* Obtain the session pointer. */ 306 rv = handle2session(hSession, &session_p); 307 if (rv != CKR_OK) 308 return (rv); 309 310 if (pMechanism == NULL) { 311 rv = CKR_ARGUMENTS_BAD; 312 goto clean_exit; 313 } 314 315 /* Obtain the object pointer. */ 316 HANDLE2OBJECT(hKey, key_p, rv); 317 if (rv != CKR_OK) { 318 goto clean_exit; 319 } 320 321 /* Check to see if key object supports sign_recover. */ 322 if (!(key_p->bool_attr_mask & SIGN_RECOVER_BOOL_ON)) { 323 rv = CKR_KEY_FUNCTION_NOT_PERMITTED; 324 goto clean_exit1; 325 } 326 327 (void) pthread_mutex_lock(&session_p->session_mutex); 328 lock_held = B_TRUE; 329 330 /* Check to see if sign operation is already active. */ 331 if (session_p->sign.flags & CRYPTO_OPERATION_ACTIVE) { 332 /* free the memory to avoid memory leak */ 333 soft_sign_verify_cleanup(session_p, B_TRUE, B_TRUE); 334 } 335 336 /* 337 * This active flag will remain ON until application calls either 338 * C_SignRecover to actually obtain the signature. 339 */ 340 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE; 341 342 (void) pthread_mutex_unlock(&session_p->session_mutex); 343 lock_held = B_FALSE; 344 345 rv = soft_sign_recover_init(session_p, pMechanism, key_p); 346 347 if (rv != CKR_OK) { 348 (void) pthread_mutex_lock(&session_p->session_mutex); 349 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE; 350 lock_held = B_TRUE; 351 } 352 353 clean_exit1: 354 OBJ_REFRELE(key_p); 355 clean_exit: 356 SES_REFRELE(session_p, lock_held); 357 return (rv); 358 } 359 360 361 CK_RV 362 C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 363 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 364 { 365 366 CK_RV rv; 367 soft_session_t *session_p; 368 boolean_t lock_held = B_FALSE; 369 370 if (!softtoken_initialized) 371 return (CKR_CRYPTOKI_NOT_INITIALIZED); 372 373 /* Obatin the session pointer */ 374 rv = handle2session(hSession, &session_p); 375 if (rv != CKR_OK) 376 return (rv); 377 378 if ((pData == NULL) || (pulSignatureLen == NULL)) { 379 rv = CKR_ARGUMENTS_BAD; 380 goto clean_exit; 381 } 382 383 (void) pthread_mutex_lock(&session_p->session_mutex); 384 lock_held = B_TRUE; 385 386 /* Application must call C_SignRecoverInit before C_SignRecover. */ 387 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 388 SES_REFRELE(session_p, lock_held); 389 return (CKR_OPERATION_NOT_INITIALIZED); 390 } 391 392 (void) pthread_mutex_unlock(&session_p->session_mutex); 393 lock_held = B_FALSE; 394 395 rv = soft_sign_recover(session_p, pData, ulDataLen, pSignature, 396 pulSignatureLen); 397 398 if ((rv == CKR_BUFFER_TOO_SMALL) || 399 (pSignature == NULL && rv == CKR_OK)) { 400 /* 401 * We will not terminate the active sign operation flag, 402 * when the application-supplied buffer is too small, or 403 * the application asks for the length of buffer to hold 404 * the signature. 405 */ 406 SES_REFRELE(session_p, lock_held); 407 return (rv); 408 } 409 410 clean_exit: 411 /* Clear contexts, free key, and release session counter */ 412 soft_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); 413 return (rv); 414 } 415