xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerify.c (revision 33efde4275d24731ef87927237b0ffb0630b6b2d)
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
C_VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)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
C_Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)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
C_VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)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
C_VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)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 	/* Clear contexts, free key, and release session counter */
256 	soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE);
257 	return (rv);
258 }
259 
260 
261 CK_RV
C_VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)262 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
263     CK_OBJECT_HANDLE hKey)
264 {
265 
266 	CK_RV		rv;
267 	soft_session_t	*session_p;
268 	soft_object_t	*key_p;
269 	boolean_t	lock_held = B_FALSE;
270 
271 	if (!softtoken_initialized)
272 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
273 
274 	/* Obtain the session pointer. */
275 	rv = handle2session(hSession, &session_p);
276 	if (rv != CKR_OK)
277 		return (rv);
278 
279 	if (pMechanism == NULL) {
280 		rv = CKR_ARGUMENTS_BAD;
281 		goto clean_exit;
282 	}
283 
284 	/* Obtain the object pointer. */
285 	HANDLE2OBJECT(hKey, key_p, rv);
286 	if (rv != CKR_OK) {
287 		goto clean_exit;
288 	}
289 
290 	/* Check to see if key object supports verify_recover. */
291 	if (!(key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON)) {
292 		rv = CKR_KEY_FUNCTION_NOT_PERMITTED;
293 		goto clean_exit1;
294 	}
295 
296 	(void) pthread_mutex_lock(&session_p->session_mutex);
297 	lock_held = B_TRUE;
298 
299 	/* Check to see if verify operation is already active. */
300 	if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) {
301 		/* free the memory to avoid memory leak */
302 		soft_sign_verify_cleanup(session_p, B_FALSE, B_TRUE);
303 	}
304 
305 	/*
306 	 * This active flag will remain ON until application calls either
307 	 * C_VerifyRecover to actually obtain the recovered message.
308 	 */
309 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
310 
311 	(void) pthread_mutex_unlock(&session_p->session_mutex);
312 	lock_held = B_FALSE;
313 
314 	rv = soft_verify_recover_init(session_p, pMechanism, key_p);
315 
316 	if (rv != CKR_OK) {
317 		(void) pthread_mutex_lock(&session_p->session_mutex);
318 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
319 		lock_held = B_TRUE;
320 	}
321 
322 clean_exit1:
323 	OBJ_REFRELE(key_p);
324 clean_exit:
325 	SES_REFRELE(session_p, lock_held);
326 	return (rv);
327 }
328 
329 
330 CK_RV
C_VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)331 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
332     CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
333 {
334 
335 	CK_RV		rv;
336 	soft_session_t	*session_p;
337 	boolean_t	lock_held = B_FALSE;
338 
339 	if (!softtoken_initialized)
340 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
341 
342 	/* Obatin the session pointer */
343 	rv = handle2session(hSession, &session_p);
344 	if (rv != CKR_OK)
345 		return (rv);
346 
347 	if ((pSignature == NULL) || (pulDataLen == NULL)) {
348 		rv = CKR_ARGUMENTS_BAD;
349 		goto clean_exit;
350 	}
351 
352 	(void) pthread_mutex_lock(&session_p->session_mutex);
353 	lock_held = B_TRUE;
354 
355 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
356 		SES_REFRELE(session_p, lock_held);
357 		return (CKR_OPERATION_NOT_INITIALIZED);
358 	}
359 
360 	(void) pthread_mutex_unlock(&session_p->session_mutex);
361 	lock_held = B_FALSE;
362 
363 	rv = soft_verify_recover(session_p, pSignature,
364 	    ulSignatureLen, pData, pulDataLen);
365 
366 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
367 	    (pData == NULL && rv == CKR_OK)) {
368 		/*
369 		 * We will not terminate the active verify operation flag,
370 		 * when the application-supplied buffer is too small, or
371 		 * the application asks for the length of buffer to hold
372 		 * the signature.
373 		 */
374 		SES_REFRELE(session_p, lock_held);
375 		return (rv);
376 	}
377 
378 clean_exit:
379 	/* Clear context, free key, and release session counter */
380 	soft_sign_verify_cleanup(session_p, B_FALSE, B_FALSE);
381 	return (rv);
382 }
383