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 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
C_VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)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
C_VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)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