xref: /titanic_44/usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerify.c (revision c28749e97052f09388969427adf7df641cdcdc22)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <pthread.h>
30 #include <security/cryptoki.h>
31 #include "softGlobal.h"
32 #include "softObject.h"
33 #include "softOps.h"
34 #include "softSession.h"
35 
36 
37 CK_RV
38 C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
39     CK_OBJECT_HANDLE hKey)
40 {
41 
42 	CK_RV		rv;
43 	soft_session_t	*session_p;
44 	soft_object_t	*key_p;
45 	boolean_t	lock_held = B_FALSE;
46 
47 	if (!softtoken_initialized)
48 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
49 
50 	/* Obtain the session pointer. */
51 	rv = handle2session(hSession, &session_p);
52 	if (rv != CKR_OK)
53 		return (rv);
54 
55 	if (pMechanism == NULL) {
56 		rv = CKR_ARGUMENTS_BAD;
57 		goto clean_exit;
58 	}
59 
60 	/* Obtain the object pointer. */
61 	HANDLE2OBJECT(hKey, key_p, rv);
62 	if (rv != CKR_OK) {
63 		goto clean_exit;
64 	}
65 
66 	/* Check to see if key object supports verification. */
67 	if (!(key_p->bool_attr_mask & VERIFY_BOOL_ON)) {
68 		rv = CKR_KEY_TYPE_INCONSISTENT;
69 		goto clean_exit1;
70 	}
71 
72 	(void) pthread_mutex_lock(&session_p->session_mutex);
73 	lock_held = B_TRUE;
74 
75 	/* Check to see if verify operation is already active. */
76 	if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) {
77 		/* free the memory to avoid memory leak */
78 		soft_sign_verify_cleanup(session_p, B_FALSE, B_TRUE);
79 	}
80 
81 	/*
82 	 * This active flag will remain ON until application calls either
83 	 * C_Verify or C_VerifyFinal to verify a signature on data.
84 	 */
85 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
86 
87 	(void) pthread_mutex_unlock(&session_p->session_mutex);
88 	lock_held = B_FALSE;
89 
90 	rv = soft_verify_init(session_p, pMechanism, key_p);
91 
92 	if (rv != CKR_OK) {
93 		(void) pthread_mutex_lock(&session_p->session_mutex);
94 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
95 		lock_held = B_TRUE;
96 	}
97 
98 clean_exit1:
99 	OBJ_REFRELE(key_p);
100 clean_exit:
101 	SES_REFRELE(session_p, lock_held);
102 	return (rv);
103 }
104 
105 
106 CK_RV
107 C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
108     CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
109 {
110 
111 	CK_RV		rv;
112 	soft_session_t	*session_p;
113 	boolean_t	lock_held = B_FALSE;
114 
115 	if (!softtoken_initialized)
116 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
117 
118 	/* Obatin the session pointer */
119 	rv = handle2session(hSession, &session_p);
120 	if (rv != CKR_OK)
121 		return (rv);
122 
123 	if (pData == NULL) {
124 		rv = CKR_ARGUMENTS_BAD;
125 		goto clean_exit;
126 	}
127 
128 	(void) pthread_mutex_lock(&session_p->session_mutex);
129 	lock_held = B_TRUE;
130 
131 	/* Application must call C_VerifyInit before calling C_Verify. */
132 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
133 		SES_REFRELE(session_p, lock_held);
134 		return (CKR_OPERATION_NOT_INITIALIZED);
135 	}
136 
137 	/*
138 	 * C_Verify must be called without intervening C_VerifyUpdate
139 	 * calls.
140 	 */
141 	if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) {
142 		/*
143 		 * C_Verify can not be used to terminate a multi-part
144 		 * operation, so we'll leave the active verify operation
145 		 * flag on and let the application continue with the
146 		 * verify update operation.
147 		 */
148 		SES_REFRELE(session_p, lock_held);
149 		return (CKR_FUNCTION_FAILED);
150 	}
151 
152 	(void) pthread_mutex_unlock(&session_p->session_mutex);
153 	lock_held = B_FALSE;
154 
155 	rv = soft_verify(session_p, pData, ulDataLen, pSignature,
156 	    ulSignatureLen);
157 	/*
158 	 * Always terminate the active verify operation.
159 	 * Application needs to call C_VerifyInit again for next
160 	 * verify operation.
161 	 */
162 	(void) pthread_mutex_lock(&session_p->session_mutex);
163 	session_p->verify.flags = 0;
164 	lock_held = B_TRUE;
165 	SES_REFRELE(session_p, lock_held);
166 	return (rv);
167 
168 clean_exit:
169 	soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE);
170 	return (rv);
171 }
172 
173 
174 CK_RV
175 C_VerifyUpdate(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_VerifyInit before calling
206 	 * C_VerifyUpdate.
207 	 */
208 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
209 		SES_REFRELE(session_p, lock_held);
210 		return (CKR_OPERATION_NOT_INITIALIZED);
211 	}
212 
213 	session_p->verify.flags |= CRYPTO_OPERATION_UPDATE;
214 
215 	(void) pthread_mutex_unlock(&session_p->session_mutex);
216 	lock_held = B_FALSE;
217 
218 	rv = soft_verify_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 	/*
227 	 * After an error occurred, terminate the current verify
228 	 * operation by resetting the active and update flags.
229 	 */
230 	soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE);
231 
232 	return (rv);
233 }
234 
235 
236 CK_RV
237 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
238     CK_ULONG ulSignatureLen)
239 {
240 
241 	CK_RV		rv;
242 	soft_session_t	*session_p;
243 	boolean_t	lock_held = B_FALSE;
244 
245 	if (!softtoken_initialized)
246 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
247 
248 	/* Obtain the session pointer */
249 	rv = handle2session(hSession, &session_p);
250 	if (rv != CKR_OK)
251 		return (rv);
252 
253 	(void) pthread_mutex_lock(&session_p->session_mutex);
254 	lock_held = B_TRUE;
255 
256 	/*
257 	 * Application must call C_VerifyInit before calling
258 	 * C_VerifyFinal.
259 	 */
260 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
261 		SES_REFRELE(session_p, lock_held);
262 		return (CKR_OPERATION_NOT_INITIALIZED);
263 	}
264 
265 	(void) pthread_mutex_unlock(&session_p->session_mutex);
266 	lock_held = B_FALSE;
267 
268 	rv = soft_verify_final(session_p, pSignature, ulSignatureLen);
269 
270 clean_exit:
271 	/* Always terminate the active verify operation */
272 	(void) pthread_mutex_lock(&session_p->session_mutex);
273 	session_p->verify.flags = 0;
274 	lock_held = B_TRUE;
275 	SES_REFRELE(session_p, lock_held);
276 
277 	return (rv);
278 }
279 
280 
281 CK_RV
282 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
283     CK_OBJECT_HANDLE hKey)
284 {
285 
286 	CK_RV		rv;
287 	soft_session_t	*session_p;
288 	soft_object_t	*key_p;
289 	boolean_t	lock_held = B_FALSE;
290 
291 	if (!softtoken_initialized)
292 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
293 
294 	/* Obtain the session pointer. */
295 	rv = handle2session(hSession, &session_p);
296 	if (rv != CKR_OK)
297 		return (rv);
298 
299 	if (pMechanism == NULL) {
300 		rv = CKR_ARGUMENTS_BAD;
301 		goto clean_exit;
302 	}
303 
304 	/* Obtain the object pointer. */
305 	HANDLE2OBJECT(hKey, key_p, rv);
306 	if (rv != CKR_OK) {
307 		goto clean_exit;
308 	}
309 
310 	/* Check to see if key object supports verify_recover. */
311 	if (!(key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON)) {
312 		rv = CKR_KEY_TYPE_INCONSISTENT;
313 		goto clean_exit1;
314 	}
315 
316 	(void) pthread_mutex_lock(&session_p->session_mutex);
317 	lock_held = B_TRUE;
318 
319 	/* Check to see if verify operation is already active. */
320 	if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) {
321 		/* free the memory to avoid memory leak */
322 		soft_sign_verify_cleanup(session_p, B_FALSE, B_TRUE);
323 	}
324 
325 	/*
326 	 * This active flag will remain ON until application calls either
327 	 * C_VerifyRecover to actually obtain the recovered message.
328 	 */
329 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
330 
331 	(void) pthread_mutex_unlock(&session_p->session_mutex);
332 	lock_held = B_FALSE;
333 
334 	rv = soft_verify_recover_init(session_p, pMechanism, key_p);
335 
336 	if (rv != CKR_OK) {
337 		(void) pthread_mutex_lock(&session_p->session_mutex);
338 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
339 		lock_held = B_TRUE;
340 	}
341 
342 clean_exit1:
343 	OBJ_REFRELE(key_p);
344 clean_exit:
345 	SES_REFRELE(session_p, lock_held);
346 	return (rv);
347 }
348 
349 
350 CK_RV
351 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
352     CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
353 {
354 
355 	CK_RV		rv;
356 	soft_session_t	*session_p;
357 	boolean_t	lock_held = B_FALSE;
358 
359 	if (!softtoken_initialized)
360 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
361 
362 	/* Obatin the session pointer */
363 	rv = handle2session(hSession, &session_p);
364 	if (rv != CKR_OK)
365 		return (rv);
366 
367 	if ((pSignature == NULL) || (pulDataLen == NULL)) {
368 		rv = CKR_ARGUMENTS_BAD;
369 		goto clean_exit;
370 	}
371 
372 	(void) pthread_mutex_lock(&session_p->session_mutex);
373 	lock_held = B_TRUE;
374 
375 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
376 		SES_REFRELE(session_p, lock_held);
377 		return (CKR_OPERATION_NOT_INITIALIZED);
378 	}
379 
380 	(void) pthread_mutex_unlock(&session_p->session_mutex);
381 	lock_held = B_FALSE;
382 
383 	rv = soft_verify_recover(session_p, pSignature,
384 	    ulSignatureLen, pData, pulDataLen);
385 
386 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
387 	    (pData == NULL && rv == CKR_OK)) {
388 		/*
389 		 * We will not terminate the active verify operation flag,
390 		 * when the application-supplied buffer is too small, or
391 		 * the application asks for the length of buffer to hold
392 		 * the signature.
393 		 */
394 		SES_REFRELE(session_p, lock_held);
395 		return (rv);
396 	}
397 
398 clean_exit:
399 	(void) pthread_mutex_lock(&session_p->session_mutex);
400 	lock_held = B_TRUE;
401 	session_p->verify.flags = 0;
402 	/*
403 	 * Free the active context right here. We don't need to call
404 	 * soft_sign_verify_cleanup() because this function is only
405 	 * applicable to CKM_RSA_PKCS and CKM_RSA_X_509 that only has
406 	 * one active context.
407 	 */
408 	if (session_p->verify.context != NULL) {
409 		free(session_p->verify.context);
410 		session_p->verify.context = NULL;
411 	}
412 	SES_REFRELE(session_p, lock_held);
413 
414 	return (rv);
415 }
416