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