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