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