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