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 2005 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 <errno.h>
30 #include <security/cryptoki.h>
31 #include <sys/crypto/ioctl.h>
32 #include "kernelGlobal.h"
33 #include "kernelObject.h"
34 #include "kernelSession.h"
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 	kernel_session_t *session_p;
43 	kernel_object_t *key_p;
44 	boolean_t ses_lock_held = B_FALSE;
45 	crypto_sign_init_t sign_init;
46 	crypto_mech_type_t k_mech_type;
47 	int r;
48 
49 	if (!kernel_initialized)
50 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
51 
52 	if (pMechanism == NULL) {
53 		return (CKR_ARGUMENTS_BAD);
54 	}
55 
56 	/* Get the kernel's internal mechanism number. */
57 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
58 	if (rv != CKR_OK) {
59 		return (rv);
60 	}
61 
62 	/* Obtain the session pointer. */
63 	rv = handle2session(hSession, &session_p);
64 	if (rv != CKR_OK)
65 		return (rv);
66 
67 	/* Obtain the object pointer. */
68 	HANDLE2OBJECT(hKey, key_p, rv);
69 	if (rv != CKR_OK) {
70 		goto clean_exit;
71 	}
72 
73 	/* Check to see if key object supports signature. */
74 	if (key_p->is_lib_obj && !(key_p->bool_attr_mask & SIGN_BOOL_ON)) {
75 		rv = CKR_KEY_TYPE_INCONSISTENT;
76 		goto clean_exit;
77 	}
78 
79 	(void) pthread_mutex_lock(&session_p->session_mutex);
80 	ses_lock_held = B_TRUE;
81 
82 	/*
83 	 * This active flag will remain ON until application calls either
84 	 * C_Sign or C_SignFinal to actually obtain the signature.
85 	 */
86 	session_p->sign.flags = CRYPTO_OPERATION_ACTIVE;
87 	sign_init.si_session = session_p->k_session;
88 	(void) pthread_mutex_unlock(&session_p->session_mutex);
89 	ses_lock_held = B_FALSE;
90 
91 	if (!key_p->is_lib_obj) {
92 		sign_init.si_key.ck_format = CRYPTO_KEY_REFERENCE;
93 		sign_init.si_key.ck_obj_id = key_p->k_handle;
94 	} else {
95 		if (key_p->class == CKO_SECRET_KEY) {
96 			sign_init.si_key.ck_format = CRYPTO_KEY_RAW;
97 			sign_init.si_key.ck_data =
98 			    get_symmetric_key_value(key_p);
99 			if (sign_init.si_key.ck_data == NULL) {
100 				rv = CKR_HOST_MEMORY;
101 				goto clean_exit;
102 			}
103 			sign_init.si_key.ck_length =
104 			    OBJ_SEC(key_p)->sk_value_len << 3;
105 
106 		} else if (key_p->key_type == CKK_RSA) {
107 			rv = get_rsa_private_key(key_p, &sign_init.si_key);
108 			if (rv != CKR_OK) {
109 				goto clean_exit;
110 			}
111 		} else if (key_p->key_type == CKK_DSA) {
112 			rv = get_dsa_private_key(key_p, &sign_init.si_key);
113 			if (rv != CKR_OK) {
114 				goto clean_exit;
115 			}
116 		} else {
117 			rv = CKR_KEY_TYPE_INCONSISTENT;
118 			goto clean_exit;
119 		}
120 	}
121 
122 	sign_init.si_mech.cm_type = k_mech_type;
123 	sign_init.si_mech.cm_param = pMechanism->pParameter;
124 	sign_init.si_mech.cm_param_len = pMechanism->ulParameterLen;
125 
126 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_INIT, &sign_init)) < 0) {
127 		if (errno != EINTR)
128 			break;
129 	}
130 	if (r < 0) {
131 		rv = CKR_FUNCTION_FAILED;
132 	} else {
133 		rv = crypto2pkcs11_error_number(sign_init.si_return_value);
134 	}
135 
136 	if (key_p->is_lib_obj) {
137 		if (key_p->class == CKO_SECRET_KEY) {
138 			free(sign_init.si_key.ck_data);
139 		} else if (key_p->key_type == CKK_RSA) {
140 			free_key_attributes(&sign_init.si_key);
141 		} else if (key_p->key_type == CKK_DSA) {
142 			free_key_attributes(&sign_init.si_key);
143 		}
144 	}
145 
146 	if (rv != CKR_OK) {
147 		(void) pthread_mutex_lock(&session_p->session_mutex);
148 		session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
149 		ses_lock_held = B_TRUE;
150 	}
151 
152 clean_exit:
153 	REFRELE(session_p, ses_lock_held);
154 	return (rv);
155 }
156 
157 
158 CK_RV
159 C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
160     CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
161 {
162 
163 	CK_RV rv;
164 	kernel_session_t *session_p;
165 	boolean_t ses_lock_held = B_FALSE;
166 	crypto_sign_t sign;
167 	int r;
168 
169 	if (!kernel_initialized)
170 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
171 
172 	/* Obtain the session pointer */
173 	rv = handle2session(hSession, &session_p);
174 	if (rv != CKR_OK)
175 		return (rv);
176 
177 	if (pulSignatureLen == NULL) {
178 		rv = CKR_ARGUMENTS_BAD;
179 		goto clean_exit;
180 	}
181 
182 	(void) pthread_mutex_lock(&session_p->session_mutex);
183 	ses_lock_held = B_TRUE;
184 
185 	/* Application must call C_SignInit before calling C_Sign. */
186 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
187 		REFRELE(session_p, ses_lock_held);
188 		return (CKR_OPERATION_NOT_INITIALIZED);
189 	}
190 
191 	/*
192 	 * C_Sign must be called without intervening C_SignUpdate
193 	 * calls.
194 	 */
195 	if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) {
196 		/*
197 		 * C_Sign can not be used to terminate a multi-part
198 		 * operation, so we'll leave the active sign operation
199 		 * flag on and let the application continue with the
200 		 * sign update operation.
201 		 */
202 		REFRELE(session_p, ses_lock_held);
203 		return (CKR_FUNCTION_FAILED);
204 	}
205 
206 	sign.cs_session = session_p->k_session;
207 	(void) pthread_mutex_unlock(&session_p->session_mutex);
208 	ses_lock_held = B_FALSE;
209 
210 	sign.cs_datalen = ulDataLen;
211 	sign.cs_databuf = (char *)pData;
212 	sign.cs_signlen = *pulSignatureLen;
213 	sign.cs_signbuf = (char *)pSignature;
214 
215 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN, &sign)) < 0) {
216 		if (errno != EINTR)
217 			break;
218 	}
219 	if (r < 0) {
220 		rv = CKR_FUNCTION_FAILED;
221 	} else {
222 		rv = crypto2pkcs11_error_number(sign.cs_return_value);
223 	}
224 
225 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
226 		*pulSignatureLen = sign.cs_signlen;
227 
228 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
229 	    (rv == CKR_OK && pSignature == NULL)) {
230 		/*
231 		 * We will not terminate the active sign operation flag,
232 		 * when the application-supplied buffer is too small, or
233 		 * the application asks for the length of buffer to hold
234 		 * the signature.
235 		 */
236 		REFRELE(session_p, ses_lock_held);
237 		return (rv);
238 	}
239 
240 clean_exit:
241 	/*
242 	 * Terminates the active sign operation.
243 	 * Application needs to call C_SignInit again for next
244 	 * sign operation.
245 	 */
246 	(void) pthread_mutex_lock(&session_p->session_mutex);
247 	session_p->sign.flags = 0;
248 	ses_lock_held = B_TRUE;
249 	REFRELE(session_p, ses_lock_held);
250 
251 	return (rv);
252 }
253 
254 
255 CK_RV
256 C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
257     CK_ULONG ulPartLen)
258 {
259 
260 	CK_RV rv;
261 	kernel_session_t *session_p;
262 	boolean_t ses_lock_held = B_FALSE;
263 	crypto_sign_update_t sign_update;
264 	int r;
265 
266 	if (!kernel_initialized)
267 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
268 
269 	/* Obtain the session pointer */
270 	rv = handle2session(hSession, &session_p);
271 	if (rv != CKR_OK)
272 		return (rv);
273 
274 	if (pPart == NULL) {
275 		rv = CKR_ARGUMENTS_BAD;
276 		goto clean_exit;
277 	}
278 
279 	(void) pthread_mutex_lock(&session_p->session_mutex);
280 	ses_lock_held = B_TRUE;
281 
282 	/*
283 	 * Application must call C_SignInit before calling
284 	 * C_SignUpdate.
285 	 */
286 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
287 		REFRELE(session_p, ses_lock_held);
288 		return (CKR_OPERATION_NOT_INITIALIZED);
289 	}
290 
291 	session_p->sign.flags |= CRYPTO_OPERATION_UPDATE;
292 
293 	sign_update.su_session = session_p->k_session;
294 	(void) pthread_mutex_unlock(&session_p->session_mutex);
295 	ses_lock_held = B_FALSE;
296 
297 	sign_update.su_datalen = ulPartLen;
298 	sign_update.su_databuf = (char *)pPart;
299 
300 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_UPDATE, &sign_update)) < 0) {
301 		if (errno != EINTR)
302 			break;
303 	}
304 	if (r < 0) {
305 		rv = CKR_FUNCTION_FAILED;
306 	} else {
307 		rv = crypto2pkcs11_error_number(sign_update.su_return_value);
308 	}
309 
310 	if (rv == CKR_OK) {
311 		REFRELE(session_p, ses_lock_held);
312 		return (rv);
313 	}
314 
315 clean_exit:
316 	/*
317 	 * After an error occurred, terminate the current sign
318 	 * operation by resetting the active and update flags.
319 	 */
320 	(void) pthread_mutex_lock(&session_p->session_mutex);
321 	session_p->sign.flags = 0;
322 	ses_lock_held = B_TRUE;
323 	REFRELE(session_p, ses_lock_held);
324 
325 	return (rv);
326 }
327 
328 
329 CK_RV
330 C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
331     CK_ULONG_PTR pulSignatureLen)
332 {
333 
334 	CK_RV rv;
335 	kernel_session_t *session_p;
336 	boolean_t ses_lock_held = B_FALSE;
337 	crypto_sign_final_t sign_final;
338 	int r;
339 
340 	if (!kernel_initialized)
341 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
342 
343 	/* Obtain the session pointer */
344 	rv = handle2session(hSession, &session_p);
345 	if (rv != CKR_OK)
346 		return (rv);
347 
348 	if (pulSignatureLen == NULL) {
349 		rv = CKR_ARGUMENTS_BAD;
350 		goto clean_exit;
351 	}
352 
353 	(void) pthread_mutex_lock(&session_p->session_mutex);
354 	ses_lock_held = B_TRUE;
355 
356 	/*
357 	 * Application must call C_SignInit before calling
358 	 * C_SignFinal.
359 	 */
360 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
361 		REFRELE(session_p, ses_lock_held);
362 		return (CKR_OPERATION_NOT_INITIALIZED);
363 	}
364 
365 	sign_final.sf_session = session_p->k_session;
366 	(void) pthread_mutex_unlock(&session_p->session_mutex);
367 	ses_lock_held = B_FALSE;
368 
369 	sign_final.sf_signlen = *pulSignatureLen;
370 	sign_final.sf_signbuf = (char *)pSignature;
371 
372 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_FINAL, &sign_final)) < 0) {
373 		if (errno != EINTR)
374 			break;
375 	}
376 	if (r < 0) {
377 		rv = CKR_FUNCTION_FAILED;
378 	} else {
379 		rv = crypto2pkcs11_error_number(sign_final.sf_return_value);
380 	}
381 
382 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
383 		*pulSignatureLen = sign_final.sf_signlen;
384 
385 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
386 	    (rv == CKR_OK && pSignature == NULL)) {
387 		/*
388 		 * We will not terminate the active sign operation flag,
389 		 * when the application-supplied buffer is too small, or
390 		 * the application asks for the length of buffer to hold
391 		 * the signature.
392 		 */
393 		REFRELE(session_p, ses_lock_held);
394 		return (rv);
395 	}
396 
397 clean_exit:
398 	/* Terminates the active sign operation */
399 	(void) pthread_mutex_lock(&session_p->session_mutex);
400 	session_p->sign.flags = 0;
401 	ses_lock_held = B_TRUE;
402 	REFRELE(session_p, ses_lock_held);
403 
404 	return (rv);
405 }
406 
407 
408 CK_RV
409 C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
410     CK_OBJECT_HANDLE hKey)
411 {
412 
413 	CK_RV rv;
414 	kernel_session_t *session_p;
415 	kernel_object_t *key_p;
416 	boolean_t ses_lock_held = B_FALSE;
417 	crypto_sign_recover_init_t sr_init;
418 	crypto_mech_type_t k_mech_type;
419 	int r;
420 
421 	if (!kernel_initialized)
422 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
423 
424 	if (pMechanism == NULL) {
425 		return (CKR_ARGUMENTS_BAD);
426 	}
427 
428 	/* Get the kernel's internal mechanism number. */
429 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
430 	if (rv != CKR_OK)
431 		return (rv);
432 
433 	/* Obtain the session pointer. */
434 	rv = handle2session(hSession, &session_p);
435 	if (rv != CKR_OK)
436 		return (rv);
437 
438 	/* Obtain the object pointer. */
439 	HANDLE2OBJECT(hKey, key_p, rv);
440 	if (rv != CKR_OK) {
441 		goto clean_exit;
442 	}
443 
444 	/*
445 	 * Check to see if key object is a RSA key and if it supports
446 	 * sign_recover.
447 	 */
448 	if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) &&
449 	    (key_p->bool_attr_mask & SIGN_RECOVER_BOOL_ON))) {
450 		rv = CKR_KEY_TYPE_INCONSISTENT;
451 		goto clean_exit;
452 	}
453 
454 	(void) pthread_mutex_lock(&session_p->session_mutex);
455 	ses_lock_held = B_TRUE;
456 
457 	/*
458 	 * This active flag will remain ON until application calls
459 	 * C_SignRecover to actually obtain the signature.
460 	 */
461 	session_p->sign.flags = CRYPTO_OPERATION_ACTIVE;
462 
463 	/* Set up the key data */
464 	if (!key_p->is_lib_obj) {
465 		sr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE;
466 		sr_init.ri_key.ck_obj_id = key_p->k_handle;
467 	} else {
468 		if (key_p->key_type == CKK_RSA) {
469 			if (get_rsa_private_key(key_p, &sr_init.ri_key) !=
470 			    CKR_OK) {
471 				rv = CKR_HOST_MEMORY;
472 				goto clean_exit;
473 			}
474 		} else {
475 			rv = CKR_KEY_TYPE_INCONSISTENT;
476 			goto clean_exit;
477 		}
478 	}
479 
480 	sr_init.ri_session = session_p->k_session;
481 	(void) pthread_mutex_unlock(&session_p->session_mutex);
482 	ses_lock_held = B_FALSE;
483 	sr_init.ri_mech.cm_type = k_mech_type;
484 	sr_init.ri_mech.cm_param = pMechanism->pParameter;
485 	sr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen;
486 
487 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER_INIT, &sr_init)) < 0) {
488 		if (errno != EINTR)
489 			break;
490 	}
491 	if (r < 0) {
492 		rv = CKR_FUNCTION_FAILED;
493 	} else {
494 		rv = crypto2pkcs11_error_number(sr_init.ri_return_value);
495 	}
496 
497 	if (key_p->is_lib_obj) {
498 		free_key_attributes(&sr_init.ri_key);
499 	}
500 
501 	if (rv != CKR_OK) {
502 		(void) pthread_mutex_lock(&session_p->session_mutex);
503 		session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
504 		ses_lock_held = B_TRUE;
505 	}
506 
507 clean_exit:
508 	REFRELE(session_p, ses_lock_held);
509 	return (rv);
510 }
511 
512 
513 CK_RV
514 C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
515     CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
516 {
517 
518 	CK_RV rv;
519 	kernel_session_t *session_p;
520 	boolean_t ses_lock_held = B_FALSE;
521 	crypto_sign_recover_t sign_recover;
522 	int r;
523 
524 	if (!kernel_initialized)
525 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
526 
527 	/* Obatin the session pointer */
528 	rv = handle2session(hSession, &session_p);
529 	if (rv != CKR_OK)
530 		return (rv);
531 
532 	if (pulSignatureLen == NULL) {
533 		rv = CKR_ARGUMENTS_BAD;
534 		goto clean_exit;
535 	}
536 
537 	(void) pthread_mutex_lock(&session_p->session_mutex);
538 	ses_lock_held = B_TRUE;
539 
540 	/* Application must call C_SignInit before calling C_Sign. */
541 	if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
542 		REFRELE(session_p, ses_lock_held);
543 		return (CKR_OPERATION_NOT_INITIALIZED);
544 	}
545 
546 	sign_recover.sr_session = session_p->k_session;
547 	(void) pthread_mutex_unlock(&session_p->session_mutex);
548 	ses_lock_held = B_FALSE;
549 
550 	sign_recover.sr_datalen = ulDataLen;
551 	sign_recover.sr_databuf = (char *)pData;
552 	sign_recover.sr_signlen = *pulSignatureLen;
553 	sign_recover.sr_signbuf = (char *)pSignature;
554 
555 	while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER, &sign_recover)) < 0) {
556 		if (errno != EINTR)
557 			break;
558 	}
559 	if (r < 0) {
560 		rv = CKR_FUNCTION_FAILED;
561 	} else {
562 		rv = crypto2pkcs11_error_number(sign_recover.sr_return_value);
563 	}
564 
565 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
566 		*pulSignatureLen = sign_recover.sr_signlen;
567 
568 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
569 	    (rv == CKR_OK && pSignature == NULL)) {
570 		/*
571 		 * We will not terminate the active sign operation flag,
572 		 * when the application-supplied buffer is too small, or
573 		 * the application asks for the length of buffer to hold
574 		 * the signature.
575 		 */
576 		REFRELE(session_p, ses_lock_held);
577 		return (rv);
578 	}
579 
580 clean_exit:
581 	/*
582 	 * Terminates the active sign operation.
583 	 * Application needs to call C_SignInit again for next
584 	 * sign operation.
585 	 */
586 	(void) pthread_mutex_lock(&session_p->session_mutex);
587 	session_p->sign.flags = 0;
588 	ses_lock_held = B_TRUE;
589 	REFRELE(session_p, ses_lock_held);
590 
591 	return (rv);
592 }
593