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