8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_kernel / common / kernelSign.c
blob1e4dd7056f7e64c28f2ff09d8744c953b5d61f67
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <errno.h>
28 #include <security/cryptoki.h>
29 #include <sys/crypto/ioctl.h>
30 #include "kernelGlobal.h"
31 #include "kernelObject.h"
32 #include "kernelSession.h"
33 #include "kernelEmulate.h"
35 CK_RV
36 C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
37 CK_OBJECT_HANDLE hKey)
39 CK_RV rv;
40 kernel_session_t *session_p;
41 kernel_object_t *key_p;
42 boolean_t ses_lock_held = B_FALSE;
43 crypto_sign_init_t sign_init;
44 crypto_mech_type_t k_mech_type;
45 int r;
47 if (!kernel_initialized)
48 return (CKR_CRYPTOKI_NOT_INITIALIZED);
50 if (pMechanism == NULL) {
51 return (CKR_ARGUMENTS_BAD);
54 /* Get the kernel's internal mechanism number. */
55 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
56 if (rv != CKR_OK) {
57 return (rv);
60 /* Obtain the session pointer. */
61 rv = handle2session(hSession, &session_p);
62 if (rv != CKR_OK)
63 return (rv);
65 /* Obtain the object pointer. */
66 HANDLE2OBJECT(hKey, key_p, rv);
67 if (rv != CKR_OK) {
68 REFRELE(session_p, ses_lock_held);
69 return (rv);
72 /* Check to see if key object supports signature. */
73 if (key_p->is_lib_obj && !(key_p->bool_attr_mask & SIGN_BOOL_ON)) {
74 rv = CKR_KEY_TYPE_INCONSISTENT;
75 goto clean_exit;
78 (void) pthread_mutex_lock(&session_p->session_mutex);
79 ses_lock_held = B_TRUE;
82 * This active flag will remain ON until application calls either
83 * C_Sign or C_SignFinal to actually obtain the signature.
85 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE;
86 sign_init.si_session = session_p->k_session;
87 (void) pthread_mutex_unlock(&session_p->session_mutex);
88 ses_lock_held = B_FALSE;
90 if (!key_p->is_lib_obj) {
91 sign_init.si_key.ck_format = CRYPTO_KEY_REFERENCE;
92 sign_init.si_key.ck_obj_id = key_p->k_handle;
93 } else {
94 if (key_p->class == CKO_SECRET_KEY) {
95 sign_init.si_key.ck_format = CRYPTO_KEY_RAW;
96 sign_init.si_key.ck_data =
97 get_symmetric_key_value(key_p);
98 if (sign_init.si_key.ck_data == NULL) {
99 rv = CKR_HOST_MEMORY;
100 goto clean_exit;
102 sign_init.si_key.ck_length =
103 OBJ_SEC(key_p)->sk_value_len << 3;
105 } else if (key_p->key_type == CKK_RSA) {
106 rv = get_rsa_private_key(key_p, &sign_init.si_key);
107 if (rv != CKR_OK) {
108 goto clean_exit;
110 } else if (key_p->key_type == CKK_DSA) {
111 rv = get_dsa_private_key(key_p, &sign_init.si_key);
112 if (rv != CKR_OK) {
113 goto clean_exit;
115 } else if (key_p->key_type == CKK_EC) {
116 rv = get_ec_private_key(key_p, &sign_init.si_key);
117 if (rv != CKR_OK) {
118 goto clean_exit;
120 } else {
121 rv = CKR_KEY_TYPE_INCONSISTENT;
122 goto clean_exit;
126 sign_init.si_mech.cm_type = k_mech_type;
127 sign_init.si_mech.cm_param = pMechanism->pParameter;
128 sign_init.si_mech.cm_param_len = pMechanism->ulParameterLen;
130 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_INIT, &sign_init)) < 0) {
131 if (errno != EINTR)
132 break;
134 if (r < 0) {
135 rv = CKR_FUNCTION_FAILED;
136 } else {
137 rv = crypto2pkcs11_error_number(sign_init.si_return_value);
140 if (rv == CKR_OK && SLOT_HAS_LIMITED_HMAC(session_p) &&
141 is_hmac(pMechanism->mechanism)) {
142 if (key_p->is_lib_obj && key_p->class == CKO_SECRET_KEY) {
143 (void) pthread_mutex_lock(&session_p->session_mutex);
144 session_p->sign.flags |= CRYPTO_EMULATE;
145 (void) pthread_mutex_unlock(&session_p->session_mutex);
146 rv = emulate_init(session_p, pMechanism,
147 &(sign_init.si_key), OP_SIGN);
148 } else {
149 rv = CKR_ARGUMENTS_BAD;
153 if (key_p->is_lib_obj) {
154 if (key_p->class == CKO_SECRET_KEY) {
155 free(sign_init.si_key.ck_data);
156 } else {
157 free_key_attributes(&sign_init.si_key);
161 if (rv != CKR_OK) {
162 (void) pthread_mutex_lock(&session_p->session_mutex);
163 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
164 ses_lock_held = B_TRUE;
167 clean_exit:
168 OBJ_REFRELE(key_p);
169 REFRELE(session_p, ses_lock_held);
170 return (rv);
174 CK_RV
175 C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
176 CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
179 CK_RV rv;
180 kernel_session_t *session_p;
181 boolean_t ses_lock_held = B_FALSE;
182 crypto_sign_t sign;
183 int r;
185 if (!kernel_initialized)
186 return (CKR_CRYPTOKI_NOT_INITIALIZED);
188 /* Obtain the session pointer */
189 rv = handle2session(hSession, &session_p);
190 if (rv != CKR_OK)
191 return (rv);
193 if (pulSignatureLen == NULL) {
194 rv = CKR_ARGUMENTS_BAD;
195 goto clean_exit;
198 (void) pthread_mutex_lock(&session_p->session_mutex);
199 ses_lock_held = B_TRUE;
201 /* Application must call C_SignInit before calling C_Sign. */
202 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
203 REFRELE(session_p, ses_lock_held);
204 return (CKR_OPERATION_NOT_INITIALIZED);
208 * C_Sign must be called without intervening C_SignUpdate
209 * calls.
211 if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) {
213 * C_Sign can not be used to terminate a multi-part
214 * operation, so we'll leave the active sign operation
215 * flag on and let the application continue with the
216 * sign update operation.
218 REFRELE(session_p, ses_lock_held);
219 return (CKR_FUNCTION_FAILED);
222 if (session_p->sign.flags & CRYPTO_EMULATE) {
223 if ((ulDataLen < SLOT_THRESHOLD(session_p)) ||
224 (ulDataLen > SLOT_HMAC_MAX_INDATA_LEN(session_p))) {
225 session_p->sign.flags |= CRYPTO_EMULATE_USING_SW;
226 (void) pthread_mutex_unlock(&session_p->session_mutex);
227 ses_lock_held = B_FALSE;
229 rv = do_soft_hmac_sign(get_spp(&session_p->sign),
230 pData, ulDataLen,
231 pSignature, pulSignatureLen, OP_SINGLE);
232 goto done;
233 } else {
234 free_soft_ctx(get_sp(&session_p->sign), OP_SIGN);
238 sign.cs_session = session_p->k_session;
239 (void) pthread_mutex_unlock(&session_p->session_mutex);
240 ses_lock_held = B_FALSE;
242 sign.cs_datalen = ulDataLen;
243 sign.cs_databuf = (char *)pData;
244 sign.cs_signlen = *pulSignatureLen;
245 sign.cs_signbuf = (char *)pSignature;
247 while ((r = ioctl(kernel_fd, CRYPTO_SIGN, &sign)) < 0) {
248 if (errno != EINTR)
249 break;
251 if (r < 0) {
252 rv = CKR_FUNCTION_FAILED;
253 } else {
254 rv = crypto2pkcs11_error_number(sign.cs_return_value);
257 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
258 *pulSignatureLen = sign.cs_signlen;
260 done:
261 if ((rv == CKR_BUFFER_TOO_SMALL) ||
262 (rv == CKR_OK && pSignature == NULL)) {
264 * We will not terminate the active sign operation flag,
265 * when the application-supplied buffer is too small, or
266 * the application asks for the length of buffer to hold
267 * the signature.
269 REFRELE(session_p, ses_lock_held);
270 return (rv);
273 clean_exit:
275 * Terminates the active sign operation.
276 * Application needs to call C_SignInit again for next
277 * sign operation.
279 (void) pthread_mutex_lock(&session_p->session_mutex);
280 ses_lock_held = B_TRUE;
282 REINIT_OPBUF(&session_p->sign);
283 session_p->sign.flags = 0;
284 REFRELE(session_p, ses_lock_held);
286 return (rv);
290 CK_RV
291 C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
292 CK_ULONG ulPartLen)
295 CK_RV rv;
296 kernel_session_t *session_p;
297 boolean_t ses_lock_held = B_FALSE;
298 crypto_sign_update_t sign_update;
299 int r;
301 if (!kernel_initialized)
302 return (CKR_CRYPTOKI_NOT_INITIALIZED);
304 /* Obtain the session pointer */
305 rv = handle2session(hSession, &session_p);
306 if (rv != CKR_OK)
307 return (rv);
309 if (pPart == NULL) {
310 rv = CKR_ARGUMENTS_BAD;
311 goto clean_exit;
314 (void) pthread_mutex_lock(&session_p->session_mutex);
315 ses_lock_held = B_TRUE;
318 * Application must call C_SignInit before calling
319 * C_SignUpdate.
321 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
322 REFRELE(session_p, ses_lock_held);
323 return (CKR_OPERATION_NOT_INITIALIZED);
326 session_p->sign.flags |= CRYPTO_OPERATION_UPDATE;
328 if (session_p->sign.flags & CRYPTO_EMULATE) {
329 (void) pthread_mutex_unlock(&session_p->session_mutex);
330 ses_lock_held = B_FALSE;
331 rv = emulate_update(session_p, pPart, ulPartLen, OP_SIGN);
332 goto done;
335 sign_update.su_session = session_p->k_session;
336 (void) pthread_mutex_unlock(&session_p->session_mutex);
337 ses_lock_held = B_FALSE;
339 sign_update.su_datalen = ulPartLen;
340 sign_update.su_databuf = (char *)pPart;
342 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_UPDATE, &sign_update)) < 0) {
343 if (errno != EINTR)
344 break;
346 if (r < 0) {
347 rv = CKR_FUNCTION_FAILED;
348 } else {
349 rv = crypto2pkcs11_error_number(sign_update.su_return_value);
352 done:
353 if (rv == CKR_OK) {
354 REFRELE(session_p, ses_lock_held);
355 return (rv);
358 clean_exit:
360 * After an error occurred, terminate the current sign
361 * operation by resetting the active and update flags.
363 (void) pthread_mutex_lock(&session_p->session_mutex);
364 ses_lock_held = B_TRUE;
365 REINIT_OPBUF(&session_p->sign);
366 session_p->sign.flags = 0;
367 REFRELE(session_p, ses_lock_held);
369 return (rv);
373 CK_RV
374 C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
375 CK_ULONG_PTR pulSignatureLen)
378 CK_RV rv;
379 kernel_session_t *session_p;
380 boolean_t ses_lock_held = B_FALSE;
381 crypto_sign_final_t sign_final;
382 int r;
384 if (!kernel_initialized)
385 return (CKR_CRYPTOKI_NOT_INITIALIZED);
387 /* Obtain the session pointer */
388 rv = handle2session(hSession, &session_p);
389 if (rv != CKR_OK)
390 return (rv);
392 if (pulSignatureLen == NULL) {
393 rv = CKR_ARGUMENTS_BAD;
394 goto clean_exit;
397 (void) pthread_mutex_lock(&session_p->session_mutex);
398 ses_lock_held = B_TRUE;
401 * Application must call C_SignInit before calling
402 * C_SignFinal.
404 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
405 REFRELE(session_p, ses_lock_held);
406 return (CKR_OPERATION_NOT_INITIALIZED);
409 /* The order of checks is important here */
410 if (session_p->sign.flags & CRYPTO_EMULATE_USING_SW) {
411 if (session_p->sign.flags & CRYPTO_EMULATE_UPDATE_DONE) {
412 (void) pthread_mutex_unlock(&session_p->session_mutex);
413 ses_lock_held = B_FALSE;
414 rv = do_soft_hmac_sign(get_spp(&session_p->sign),
415 NULL, 0, pSignature, pulSignatureLen, OP_FINAL);
416 } else {
418 * We end up here if an earlier C_SignFinal() call
419 * took the C_Sign() path and it had returned
420 * CKR_BUFFER_TOO_SMALL.
422 digest_buf_t *bufp = session_p->sign.context;
423 (void) pthread_mutex_unlock(&session_p->session_mutex);
424 ses_lock_held = B_FALSE;
425 if (bufp == NULL || bufp->buf == NULL) {
426 rv = CKR_ARGUMENTS_BAD;
427 goto clean_exit;
429 rv = do_soft_hmac_sign(get_spp(&session_p->sign),
430 bufp->buf, bufp->indata_len,
431 pSignature, pulSignatureLen, OP_SINGLE);
433 goto done;
434 } else if (session_p->sign.flags & CRYPTO_EMULATE) {
435 digest_buf_t *bufp = session_p->sign.context;
438 * We are emulating a single-part operation now.
439 * So, clear the flag.
441 session_p->sign.flags &= ~CRYPTO_OPERATION_UPDATE;
442 if (bufp == NULL || bufp->buf == NULL) {
443 rv = CKR_ARGUMENTS_BAD;
444 goto clean_exit;
446 REFRELE(session_p, ses_lock_held);
447 rv = C_Sign(hSession, bufp->buf, bufp->indata_len,
448 pSignature, pulSignatureLen);
449 return (rv);
452 sign_final.sf_session = session_p->k_session;
453 (void) pthread_mutex_unlock(&session_p->session_mutex);
454 ses_lock_held = B_FALSE;
456 sign_final.sf_signlen = *pulSignatureLen;
457 sign_final.sf_signbuf = (char *)pSignature;
459 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_FINAL, &sign_final)) < 0) {
460 if (errno != EINTR)
461 break;
463 if (r < 0) {
464 rv = CKR_FUNCTION_FAILED;
465 } else {
466 rv = crypto2pkcs11_error_number(sign_final.sf_return_value);
469 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
470 *pulSignatureLen = sign_final.sf_signlen;
472 done:
473 if ((rv == CKR_BUFFER_TOO_SMALL) ||
474 (rv == CKR_OK && pSignature == NULL)) {
476 * We will not terminate the active sign operation flag,
477 * when the application-supplied buffer is too small, or
478 * the application asks for the length of buffer to hold
479 * the signature.
481 REFRELE(session_p, ses_lock_held);
482 return (rv);
485 clean_exit:
486 /* Terminates the active sign operation */
487 (void) pthread_mutex_lock(&session_p->session_mutex);
488 ses_lock_held = B_TRUE;
489 REINIT_OPBUF(&session_p->sign);
490 session_p->sign.flags = 0;
491 REFRELE(session_p, ses_lock_held);
493 return (rv);
497 CK_RV
498 C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
499 CK_OBJECT_HANDLE hKey)
502 CK_RV rv;
503 kernel_session_t *session_p;
504 kernel_object_t *key_p;
505 boolean_t ses_lock_held = B_FALSE;
506 crypto_sign_recover_init_t sr_init;
507 crypto_mech_type_t k_mech_type;
508 int r;
510 if (!kernel_initialized)
511 return (CKR_CRYPTOKI_NOT_INITIALIZED);
513 if (pMechanism == NULL) {
514 return (CKR_ARGUMENTS_BAD);
517 /* Get the kernel's internal mechanism number. */
518 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
519 if (rv != CKR_OK)
520 return (rv);
522 /* Obtain the session pointer. */
523 rv = handle2session(hSession, &session_p);
524 if (rv != CKR_OK)
525 return (rv);
527 /* Obtain the object pointer. */
528 HANDLE2OBJECT(hKey, key_p, rv);
529 if (rv != CKR_OK) {
530 REFRELE(session_p, ses_lock_held);
531 return (rv);
535 * Check to see if key object is a RSA key and if it supports
536 * sign_recover.
538 if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) &&
539 (key_p->bool_attr_mask & SIGN_RECOVER_BOOL_ON))) {
540 rv = CKR_KEY_TYPE_INCONSISTENT;
541 goto clean_exit;
544 (void) pthread_mutex_lock(&session_p->session_mutex);
545 ses_lock_held = B_TRUE;
548 * This active flag will remain ON until application calls
549 * C_SignRecover to actually obtain the signature.
551 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE;
553 /* Set up the key data */
554 if (!key_p->is_lib_obj) {
555 sr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE;
556 sr_init.ri_key.ck_obj_id = key_p->k_handle;
557 } else {
558 if (key_p->key_type == CKK_RSA) {
559 if (get_rsa_private_key(key_p, &sr_init.ri_key) !=
560 CKR_OK) {
561 rv = CKR_HOST_MEMORY;
562 goto clean_exit;
564 } else {
565 rv = CKR_KEY_TYPE_INCONSISTENT;
566 goto clean_exit;
570 sr_init.ri_session = session_p->k_session;
571 (void) pthread_mutex_unlock(&session_p->session_mutex);
572 ses_lock_held = B_FALSE;
573 sr_init.ri_mech.cm_type = k_mech_type;
574 sr_init.ri_mech.cm_param = pMechanism->pParameter;
575 sr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen;
577 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER_INIT, &sr_init)) < 0) {
578 if (errno != EINTR)
579 break;
581 if (r < 0) {
582 rv = CKR_FUNCTION_FAILED;
583 } else {
584 rv = crypto2pkcs11_error_number(sr_init.ri_return_value);
587 if (key_p->is_lib_obj) {
588 free_key_attributes(&sr_init.ri_key);
591 if (rv != CKR_OK) {
592 (void) pthread_mutex_lock(&session_p->session_mutex);
593 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
594 ses_lock_held = B_TRUE;
597 clean_exit:
598 OBJ_REFRELE(key_p);
599 REFRELE(session_p, ses_lock_held);
600 return (rv);
604 CK_RV
605 C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
606 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
609 CK_RV rv;
610 kernel_session_t *session_p;
611 boolean_t ses_lock_held = B_FALSE;
612 crypto_sign_recover_t sign_recover;
613 int r;
615 if (!kernel_initialized)
616 return (CKR_CRYPTOKI_NOT_INITIALIZED);
618 /* Obatin the session pointer */
619 rv = handle2session(hSession, &session_p);
620 if (rv != CKR_OK)
621 return (rv);
623 if (pulSignatureLen == NULL) {
624 rv = CKR_ARGUMENTS_BAD;
625 goto clean_exit;
628 (void) pthread_mutex_lock(&session_p->session_mutex);
629 ses_lock_held = B_TRUE;
631 /* Application must call C_SignInit before calling C_Sign. */
632 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) {
633 REFRELE(session_p, ses_lock_held);
634 return (CKR_OPERATION_NOT_INITIALIZED);
637 sign_recover.sr_session = session_p->k_session;
638 (void) pthread_mutex_unlock(&session_p->session_mutex);
639 ses_lock_held = B_FALSE;
641 sign_recover.sr_datalen = ulDataLen;
642 sign_recover.sr_databuf = (char *)pData;
643 sign_recover.sr_signlen = *pulSignatureLen;
644 sign_recover.sr_signbuf = (char *)pSignature;
646 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER, &sign_recover)) < 0) {
647 if (errno != EINTR)
648 break;
650 if (r < 0) {
651 rv = CKR_FUNCTION_FAILED;
652 } else {
653 rv = crypto2pkcs11_error_number(sign_recover.sr_return_value);
656 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
657 *pulSignatureLen = sign_recover.sr_signlen;
659 if ((rv == CKR_BUFFER_TOO_SMALL) ||
660 (rv == CKR_OK && pSignature == NULL)) {
662 * We will not terminate the active sign operation flag,
663 * when the application-supplied buffer is too small, or
664 * the application asks for the length of buffer to hold
665 * the signature.
667 REFRELE(session_p, ses_lock_held);
668 return (rv);
671 clean_exit:
673 * Terminates the active sign operation.
674 * Application needs to call C_SignInit again for next
675 * sign operation.
677 (void) pthread_mutex_lock(&session_p->session_mutex);
678 ses_lock_held = B_TRUE;
679 session_p->sign.flags = 0;
680 REFRELE(session_p, ses_lock_held);
682 return (rv);