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