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_VerifyInit(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 verification. */ 66 if (!(key_p->bool_attr_mask & VERIFY_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 verify operation is already active. */ 75 if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) { 76 /* free the memory to avoid memory leak */ 77 soft_sign_verify_cleanup(session_p, B_FALSE, B_TRUE); 78 } 79 80 /* 81 * This active flag will remain ON until application calls either 82 * C_Verify or C_VerifyFinal to verify a signature on data. 83 */ 84 session_p->verify.flags = CRYPTO_OPERATION_ACTIVE; 85 86 (void) pthread_mutex_unlock(&session_p->session_mutex); 87 lock_held = B_FALSE; 88 89 rv = soft_verify_init(session_p, pMechanism, key_p); 90 91 if (rv != CKR_OK) { 92 (void) pthread_mutex_lock(&session_p->session_mutex); 93 session_p->verify.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_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 107 CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) 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) { 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_VerifyInit before calling C_Verify. */ 131 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 132 SES_REFRELE(session_p, lock_held); 133 return (CKR_OPERATION_NOT_INITIALIZED); 134 } 135 136 /* 137 * C_Verify must be called without intervening C_VerifyUpdate 138 * calls. 139 */ 140 if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) { 141 /* 142 * C_Verify can not be used to terminate a multi-part 143 * operation, so we'll leave the active verify operation 144 * flag on and let the application continue with the 145 * verify 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_verify(session_p, pData, ulDataLen, pSignature, 155 ulSignatureLen); 156 157 clean_exit: 158 /* Clear context, free key, and release session counter */ 159 soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE); 160 return (rv); 161 } 162 163 164 CK_RV 165 C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 166 CK_ULONG ulPartLen) 167 { 168 169 CK_RV rv; 170 soft_session_t *session_p; 171 boolean_t lock_held = B_FALSE; 172 173 if (!softtoken_initialized) 174 return (CKR_CRYPTOKI_NOT_INITIALIZED); 175 176 /* Obtain the session pointer */ 177 rv = handle2session(hSession, &session_p); 178 if (rv != CKR_OK) 179 return (rv); 180 181 if (ulPartLen == 0) { 182 SES_REFRELE(session_p, lock_held); 183 return (CKR_OK); 184 } 185 186 if (pPart == NULL) { 187 rv = CKR_ARGUMENTS_BAD; 188 goto clean_exit; 189 } 190 191 (void) pthread_mutex_lock(&session_p->session_mutex); 192 lock_held = B_TRUE; 193 194 /* 195 * Application must call C_VerifyInit before calling 196 * C_VerifyUpdate. 197 */ 198 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 199 SES_REFRELE(session_p, lock_held); 200 return (CKR_OPERATION_NOT_INITIALIZED); 201 } 202 203 session_p->verify.flags |= CRYPTO_OPERATION_UPDATE; 204 205 (void) pthread_mutex_unlock(&session_p->session_mutex); 206 lock_held = B_FALSE; 207 208 rv = soft_verify_update(session_p, pPart, ulPartLen); 209 210 if (rv == CKR_OK) { 211 SES_REFRELE(session_p, lock_held); 212 return (rv); 213 } 214 215 clean_exit: 216 /* After error, clear context, free key, & release session counter */ 217 soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE); 218 219 return (rv); 220 } 221 222 223 CK_RV 224 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 225 CK_ULONG ulSignatureLen) 226 { 227 228 CK_RV rv; 229 soft_session_t *session_p; 230 boolean_t lock_held = B_FALSE; 231 232 if (!softtoken_initialized) 233 return (CKR_CRYPTOKI_NOT_INITIALIZED); 234 235 /* Obtain the session pointer */ 236 rv = handle2session(hSession, &session_p); 237 if (rv != CKR_OK) 238 return (rv); 239 240 (void) pthread_mutex_lock(&session_p->session_mutex); 241 lock_held = B_TRUE; 242 243 /* 244 * Application must call C_VerifyInit before calling 245 * C_VerifyFinal. 246 */ 247 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 248 SES_REFRELE(session_p, lock_held); 249 return (CKR_OPERATION_NOT_INITIALIZED); 250 } 251 252 (void) pthread_mutex_unlock(&session_p->session_mutex); 253 lock_held = B_FALSE; 254 255 rv = soft_verify_final(session_p, pSignature, ulSignatureLen); 256 257 clean_exit: 258 /* Clear contexts, free key, and release session counter */ 259 soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE); 260 return (rv); 261 } 262 263 264 CK_RV 265 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 266 CK_OBJECT_HANDLE hKey) 267 { 268 269 CK_RV rv; 270 soft_session_t *session_p; 271 soft_object_t *key_p; 272 boolean_t lock_held = B_FALSE; 273 274 if (!softtoken_initialized) 275 return (CKR_CRYPTOKI_NOT_INITIALIZED); 276 277 /* Obtain the session pointer. */ 278 rv = handle2session(hSession, &session_p); 279 if (rv != CKR_OK) 280 return (rv); 281 282 if (pMechanism == NULL) { 283 rv = CKR_ARGUMENTS_BAD; 284 goto clean_exit; 285 } 286 287 /* Obtain the object pointer. */ 288 HANDLE2OBJECT(hKey, key_p, rv); 289 if (rv != CKR_OK) { 290 goto clean_exit; 291 } 292 293 /* Check to see if key object supports verify_recover. */ 294 if (!(key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON)) { 295 rv = CKR_KEY_TYPE_INCONSISTENT; 296 goto clean_exit1; 297 } 298 299 (void) pthread_mutex_lock(&session_p->session_mutex); 300 lock_held = B_TRUE; 301 302 /* Check to see if verify operation is already active. */ 303 if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) { 304 /* free the memory to avoid memory leak */ 305 soft_sign_verify_cleanup(session_p, B_FALSE, B_TRUE); 306 } 307 308 /* 309 * This active flag will remain ON until application calls either 310 * C_VerifyRecover to actually obtain the recovered message. 311 */ 312 session_p->verify.flags = CRYPTO_OPERATION_ACTIVE; 313 314 (void) pthread_mutex_unlock(&session_p->session_mutex); 315 lock_held = B_FALSE; 316 317 rv = soft_verify_recover_init(session_p, pMechanism, key_p); 318 319 if (rv != CKR_OK) { 320 (void) pthread_mutex_lock(&session_p->session_mutex); 321 session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE; 322 lock_held = B_TRUE; 323 } 324 325 clean_exit1: 326 OBJ_REFRELE(key_p); 327 clean_exit: 328 SES_REFRELE(session_p, lock_held); 329 return (rv); 330 } 331 332 333 CK_RV 334 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 335 CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 336 { 337 338 CK_RV rv; 339 soft_session_t *session_p; 340 boolean_t lock_held = B_FALSE; 341 342 if (!softtoken_initialized) 343 return (CKR_CRYPTOKI_NOT_INITIALIZED); 344 345 /* Obatin the session pointer */ 346 rv = handle2session(hSession, &session_p); 347 if (rv != CKR_OK) 348 return (rv); 349 350 if ((pSignature == NULL) || (pulDataLen == NULL)) { 351 rv = CKR_ARGUMENTS_BAD; 352 goto clean_exit; 353 } 354 355 (void) pthread_mutex_lock(&session_p->session_mutex); 356 lock_held = B_TRUE; 357 358 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 359 SES_REFRELE(session_p, lock_held); 360 return (CKR_OPERATION_NOT_INITIALIZED); 361 } 362 363 (void) pthread_mutex_unlock(&session_p->session_mutex); 364 lock_held = B_FALSE; 365 366 rv = soft_verify_recover(session_p, pSignature, 367 ulSignatureLen, pData, pulDataLen); 368 369 if ((rv == CKR_BUFFER_TOO_SMALL) || 370 (pData == NULL && rv == CKR_OK)) { 371 /* 372 * We will not terminate the active verify operation flag, 373 * when the application-supplied buffer is too small, or 374 * the application asks for the length of buffer to hold 375 * the signature. 376 */ 377 SES_REFRELE(session_p, lock_held); 378 return (rv); 379 } 380 381 clean_exit: 382 /* Clear context, free key, and release session counter */ 383 soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE); 384 return (rv); 385 } 386