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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 #include <sys/crypto/ioctl.h>
30 #include <security/cryptoki.h>
31 #include "kernelGlobal.h"
32 #include "kernelObject.h"
33 #include "kernelSession.h"
34 #include "kernelEmulate.h"
37 C_VerifyInit(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
38 CK_OBJECT_HANDLE hKey
)
41 kernel_session_t
*session_p
;
42 kernel_object_t
*key_p
;
43 boolean_t ses_lock_held
= B_FALSE
;
44 crypto_verify_init_t verify_init
;
45 crypto_mech_type_t k_mech_type
;
48 if (!kernel_initialized
)
49 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
51 if (pMechanism
== NULL
) {
52 return (CKR_ARGUMENTS_BAD
);
55 /* Get the kernel's internal mechanism number. */
56 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
60 /* Obtain the session pointer. */
61 rv
= handle2session(hSession
, &session_p
);
65 /* Obtain the object pointer. */
66 HANDLE2OBJECT(hKey
, key_p
, rv
);
68 REFRELE(session_p
, ses_lock_held
);
72 /* Check to see if key object supports verification. */
73 if (key_p
->is_lib_obj
&& !(key_p
->bool_attr_mask
& VERIFY_BOOL_ON
)) {
74 rv
= CKR_KEY_TYPE_INCONSISTENT
;
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_Verify or C_VerifyFinal to verify a signature on data.
85 session_p
->verify
.flags
= CRYPTO_OPERATION_ACTIVE
;
87 if (!key_p
->is_lib_obj
) {
88 verify_init
.vi_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
89 verify_init
.vi_key
.ck_obj_id
= key_p
->k_handle
;
91 if (key_p
->class == CKO_SECRET_KEY
) {
92 verify_init
.vi_key
.ck_format
= CRYPTO_KEY_RAW
;
93 verify_init
.vi_key
.ck_data
=
94 get_symmetric_key_value(key_p
);
95 if (verify_init
.vi_key
.ck_data
== NULL
) {
99 verify_init
.vi_key
.ck_length
=
100 OBJ_SEC(key_p
)->sk_value_len
<< 3;
102 } else if (key_p
->key_type
== CKK_RSA
) {
103 if (get_rsa_public_key(key_p
, &verify_init
.vi_key
) !=
105 rv
= CKR_HOST_MEMORY
;
108 } else if (key_p
->key_type
== CKK_DSA
) {
109 if (get_dsa_public_key(key_p
, &verify_init
.vi_key
) !=
111 rv
= CKR_HOST_MEMORY
;
114 } else if (key_p
->key_type
== CKK_EC
) {
115 if (get_ec_public_key(key_p
, &verify_init
.vi_key
) !=
117 rv
= CKR_HOST_MEMORY
;
121 rv
= CKR_KEY_TYPE_INCONSISTENT
;
126 verify_init
.vi_session
= session_p
->k_session
;
127 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
128 ses_lock_held
= B_FALSE
;
129 verify_init
.vi_mech
.cm_type
= k_mech_type
;
130 verify_init
.vi_mech
.cm_param
= pMechanism
->pParameter
;
131 verify_init
.vi_mech
.cm_param_len
= pMechanism
->ulParameterLen
;
133 while ((r
= ioctl(kernel_fd
, CRYPTO_VERIFY_INIT
, &verify_init
)) < 0) {
138 rv
= CKR_FUNCTION_FAILED
;
140 rv
= crypto2pkcs11_error_number(verify_init
.vi_return_value
);
143 if (rv
== CKR_OK
&& SLOT_HAS_LIMITED_HMAC(session_p
) &&
144 is_hmac(pMechanism
->mechanism
)) {
145 if (key_p
->is_lib_obj
&& key_p
->class == CKO_SECRET_KEY
) {
146 (void) pthread_mutex_lock(&session_p
->session_mutex
);
147 session_p
->verify
.flags
|= CRYPTO_EMULATE
;
148 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
149 rv
= emulate_init(session_p
, pMechanism
,
150 &(verify_init
.vi_key
), OP_VERIFY
);
152 rv
= CKR_FUNCTION_FAILED
;
156 /* free the memory allocated for verify_init.vi_key */
157 if (key_p
->is_lib_obj
) {
158 if (key_p
->class == CKO_SECRET_KEY
) {
159 free(verify_init
.vi_key
.ck_data
);
161 free_key_attributes(&verify_init
.vi_key
);
166 (void) pthread_mutex_lock(&session_p
->session_mutex
);
167 session_p
->verify
.flags
&= ~CRYPTO_OPERATION_ACTIVE
;
168 ses_lock_held
= B_TRUE
;
173 REFRELE(session_p
, ses_lock_held
);
179 C_Verify(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pData
, CK_ULONG ulDataLen
,
180 CK_BYTE_PTR pSignature
, CK_ULONG ulSignatureLen
)
184 kernel_session_t
*session_p
;
185 boolean_t ses_lock_held
= B_FALSE
;
186 crypto_verify_t verify
;
189 if (!kernel_initialized
)
190 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
192 /* Obatin the session pointer */
193 rv
= handle2session(hSession
, &session_p
);
197 (void) pthread_mutex_lock(&session_p
->session_mutex
);
198 ses_lock_held
= B_TRUE
;
200 /* Application must call C_VerifyInit before calling C_Verify. */
201 if (!(session_p
->verify
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
202 REFRELE(session_p
, ses_lock_held
);
203 return (CKR_OPERATION_NOT_INITIALIZED
);
207 * C_Verify must be called without intervening C_VerifyUpdate
210 if (session_p
->verify
.flags
& CRYPTO_OPERATION_UPDATE
) {
212 * C_Verify can not be used to terminate a multi-part
213 * operation, so we'll leave the active verify operation
214 * flag on and let the application continue with the
215 * verify update operation.
217 REFRELE(session_p
, ses_lock_held
);
218 return (CKR_FUNCTION_FAILED
);
221 if (session_p
->verify
.flags
& CRYPTO_EMULATE
) {
222 if ((ulDataLen
< SLOT_THRESHOLD(session_p
)) ||
223 (ulDataLen
> SLOT_HMAC_MAX_INDATA_LEN(session_p
))) {
224 session_p
->verify
.flags
|= CRYPTO_EMULATE_USING_SW
;
225 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
226 ses_lock_held
= B_FALSE
;
228 rv
= do_soft_hmac_verify(get_spp(&session_p
->verify
),
230 pSignature
, ulSignatureLen
, OP_SINGLE
);
233 free_soft_ctx(get_sp(&session_p
->verify
), OP_VERIFY
);
237 verify
.cv_session
= session_p
->k_session
;
238 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
239 ses_lock_held
= B_FALSE
;
240 verify
.cv_datalen
= ulDataLen
;
241 verify
.cv_databuf
= (char *)pData
;
242 verify
.cv_signlen
= ulSignatureLen
;
243 verify
.cv_signbuf
= (char *)pSignature
;
245 while ((r
= ioctl(kernel_fd
, CRYPTO_VERIFY
, &verify
)) < 0) {
250 rv
= CKR_FUNCTION_FAILED
;
252 rv
= crypto2pkcs11_error_number(verify
.cv_return_value
);
257 * Always terminate the active verify operation.
258 * Application needs to call C_VerifyInit again for next
261 (void) pthread_mutex_lock(&session_p
->session_mutex
);
262 ses_lock_held
= B_TRUE
;
264 REINIT_OPBUF(&session_p
->verify
);
265 session_p
->verify
.flags
= 0;
266 REFRELE(session_p
, ses_lock_held
);
273 C_VerifyUpdate(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pPart
,
278 kernel_session_t
*session_p
;
279 boolean_t ses_lock_held
= B_FALSE
;
280 crypto_verify_update_t verify_update
;
283 if (!kernel_initialized
)
284 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
286 /* Obtain the session pointer */
287 rv
= handle2session(hSession
, &session_p
);
292 rv
= CKR_ARGUMENTS_BAD
;
296 (void) pthread_mutex_lock(&session_p
->session_mutex
);
297 ses_lock_held
= B_TRUE
;
300 * Application must call C_VerifyInit before calling
303 if (!(session_p
->verify
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
304 REFRELE(session_p
, ses_lock_held
);
305 return (CKR_OPERATION_NOT_INITIALIZED
);
308 session_p
->verify
.flags
|= CRYPTO_OPERATION_UPDATE
;
310 if (session_p
->verify
.flags
& CRYPTO_EMULATE
) {
311 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
312 ses_lock_held
= B_FALSE
;
313 rv
= emulate_update(session_p
, pPart
, ulPartLen
, OP_VERIFY
);
317 verify_update
.vu_session
= session_p
->k_session
;
318 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
319 ses_lock_held
= B_FALSE
;
321 verify_update
.vu_datalen
= ulPartLen
;
322 verify_update
.vu_databuf
= (char *)pPart
;
324 while ((r
= ioctl(kernel_fd
, CRYPTO_VERIFY_UPDATE
,
325 &verify_update
)) < 0) {
330 rv
= CKR_FUNCTION_FAILED
;
332 rv
= crypto2pkcs11_error_number(verify_update
.vu_return_value
);
337 REFRELE(session_p
, ses_lock_held
);
343 * After an error occurred, terminate the current verify
344 * operation by resetting the active and update flags.
346 (void) pthread_mutex_lock(&session_p
->session_mutex
);
347 ses_lock_held
= B_TRUE
;
348 REINIT_OPBUF(&session_p
->verify
);
349 session_p
->verify
.flags
= 0;
350 REFRELE(session_p
, ses_lock_held
);
357 C_VerifyFinal(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pSignature
,
358 CK_ULONG ulSignatureLen
)
362 kernel_session_t
*session_p
;
363 boolean_t ses_lock_held
= B_FALSE
;
364 crypto_verify_final_t verify_final
;
367 if (!kernel_initialized
)
368 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
370 /* Obtain the session pointer */
371 rv
= handle2session(hSession
, &session_p
);
375 (void) pthread_mutex_lock(&session_p
->session_mutex
);
376 ses_lock_held
= B_TRUE
;
379 * Application must call C_VerifyInit before calling
382 if (!(session_p
->verify
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
383 REFRELE(session_p
, ses_lock_held
);
384 return (CKR_OPERATION_NOT_INITIALIZED
);
387 /* The order of checks is important here */
388 if (session_p
->verify
.flags
& CRYPTO_EMULATE_USING_SW
) {
389 if (session_p
->verify
.flags
& CRYPTO_EMULATE_UPDATE_DONE
) {
390 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
391 ses_lock_held
= B_FALSE
;
392 rv
= do_soft_hmac_verify(get_spp(&session_p
->verify
),
393 NULL
, 0, pSignature
, ulSignatureLen
,
397 * We should not end up here even if an earlier
398 * C_VerifyFinal() call took the C_Verify() path as
399 * it never returns CKR_BUFFER_TOO_SMALL.
401 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
402 ses_lock_held
= B_FALSE
;
403 rv
= CKR_ARGUMENTS_BAD
;
406 } else if (session_p
->verify
.flags
& CRYPTO_EMULATE
) {
407 digest_buf_t
*bufp
= session_p
->verify
.context
;
410 * We are emulating a single-part operation now.
411 * So, clear the flag.
413 session_p
->verify
.flags
&= ~CRYPTO_OPERATION_UPDATE
;
414 if (bufp
== NULL
|| bufp
->buf
== NULL
) {
415 rv
= CKR_ARGUMENTS_BAD
;
418 REFRELE(session_p
, ses_lock_held
);
419 rv
= C_Verify(hSession
, bufp
->buf
, bufp
->indata_len
,
420 pSignature
, ulSignatureLen
);
424 verify_final
.vf_session
= session_p
->k_session
;
425 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
426 ses_lock_held
= B_FALSE
;
428 verify_final
.vf_signlen
= ulSignatureLen
;
429 verify_final
.vf_signbuf
= (char *)pSignature
;
431 while ((r
= ioctl(kernel_fd
, CRYPTO_VERIFY_FINAL
, &verify_final
)) < 0) {
436 rv
= CKR_FUNCTION_FAILED
;
438 rv
= crypto2pkcs11_error_number(verify_final
.vf_return_value
);
442 /* Always terminate the active verify operation */
443 (void) pthread_mutex_lock(&session_p
->session_mutex
);
444 ses_lock_held
= B_TRUE
;
445 REINIT_OPBUF(&session_p
->verify
);
446 session_p
->verify
.flags
= 0;
447 REFRELE(session_p
, ses_lock_held
);
454 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
455 CK_OBJECT_HANDLE hKey
)
459 kernel_session_t
*session_p
;
460 kernel_object_t
*key_p
;
461 boolean_t ses_lock_held
= B_FALSE
;
462 crypto_verify_recover_init_t vr_init
;
463 crypto_mech_type_t k_mech_type
;
466 if (!kernel_initialized
)
467 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
469 if (pMechanism
== NULL
) {
470 return (CKR_ARGUMENTS_BAD
);
473 /* Get the kernel's internal mechanism number. */
474 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
478 /* Obtain the session pointer. */
479 rv
= handle2session(hSession
, &session_p
);
483 /* Obtain the object pointer. */
484 HANDLE2OBJECT(hKey
, key_p
, rv
);
486 REFRELE(session_p
, ses_lock_held
);
491 * Check to see if key object is a RSA key and if it supports
494 if (key_p
->is_lib_obj
&& !((key_p
->key_type
== CKK_RSA
) &&
495 (key_p
->bool_attr_mask
& VERIFY_RECOVER_BOOL_ON
))) {
496 rv
= CKR_KEY_TYPE_INCONSISTENT
;
500 (void) pthread_mutex_lock(&session_p
->session_mutex
);
501 ses_lock_held
= B_TRUE
;
504 * This active flag will remain ON until application calls
505 * C_VerifyRecover to verify a signature on data.
507 session_p
->verify
.flags
= CRYPTO_OPERATION_ACTIVE
;
509 /* Set up the key data */
510 if (!key_p
->is_lib_obj
) {
511 vr_init
.ri_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
512 vr_init
.ri_key
.ck_obj_id
= key_p
->k_handle
;
514 if (key_p
->key_type
== CKK_RSA
) {
515 if (get_rsa_public_key(key_p
, &vr_init
.ri_key
) !=
517 rv
= CKR_HOST_MEMORY
;
521 rv
= CKR_KEY_TYPE_INCONSISTENT
;
526 vr_init
.ri_session
= session_p
->k_session
;
527 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
528 ses_lock_held
= B_FALSE
;
529 vr_init
.ri_mech
.cm_type
= k_mech_type
;
530 vr_init
.ri_mech
.cm_param
= pMechanism
->pParameter
;
531 vr_init
.ri_mech
.cm_param_len
= pMechanism
->ulParameterLen
;
533 while ((r
= ioctl(kernel_fd
, CRYPTO_VERIFY_RECOVER_INIT
,
539 rv
= CKR_FUNCTION_FAILED
;
541 rv
= crypto2pkcs11_error_number(vr_init
.ri_return_value
);
544 /* free the memory allocated for vr_init.ri_key */
545 if (key_p
->is_lib_obj
) {
546 free_key_attributes(&vr_init
.ri_key
);
550 (void) pthread_mutex_lock(&session_p
->session_mutex
);
551 session_p
->verify
.flags
&= ~CRYPTO_OPERATION_ACTIVE
;
552 ses_lock_held
= B_TRUE
;
557 REFRELE(session_p
, ses_lock_held
);
563 C_VerifyRecover(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pSignature
,
564 CK_ULONG ulSignatureLen
, CK_BYTE_PTR pData
, CK_ULONG_PTR pulDataLen
)
568 kernel_session_t
*session_p
;
569 boolean_t ses_lock_held
= B_FALSE
;
570 crypto_verify_recover_t verify_recover
;
573 if (!kernel_initialized
)
574 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
576 /* Obtain the session pointer */
577 rv
= handle2session(hSession
, &session_p
);
581 if (pSignature
== NULL
|| pulDataLen
== NULL
) {
582 rv
= CKR_ARGUMENTS_BAD
;
586 (void) pthread_mutex_lock(&session_p
->session_mutex
);
587 ses_lock_held
= B_TRUE
;
590 * Application must call C_VerifyRecoverInit before calling
593 if (!(session_p
->verify
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
594 REFRELE(session_p
, ses_lock_held
);
595 return (CKR_OPERATION_NOT_INITIALIZED
);
598 verify_recover
.vr_session
= session_p
->k_session
;
599 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
600 ses_lock_held
= B_FALSE
;
601 verify_recover
.vr_signlen
= ulSignatureLen
;
602 verify_recover
.vr_signbuf
= (char *)pSignature
;
603 verify_recover
.vr_datalen
= *pulDataLen
;
604 verify_recover
.vr_databuf
= (char *)pData
;
606 while ((r
= ioctl(kernel_fd
, CRYPTO_VERIFY_RECOVER
,
607 &verify_recover
)) < 0) {
612 rv
= CKR_FUNCTION_FAILED
;
614 rv
= crypto2pkcs11_error_number(
615 verify_recover
.vr_return_value
);
618 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
619 *pulDataLen
= verify_recover
.vr_datalen
;
621 if ((rv
== CKR_BUFFER_TOO_SMALL
) ||
622 (rv
== CKR_OK
&& pData
== NULL
)) {
624 * We will not terminate the active verify operation flag,
625 * when the application-supplied buffer is too small, or
626 * the application asks for the length of buffer to hold
627 * the recovered data.
629 REFRELE(session_p
, ses_lock_held
);
635 * Always terminate the active verify operation.
636 * Application needs to call C_VerifyInit again for next
639 (void) pthread_mutex_lock(&session_p
->session_mutex
);
640 session_p
->verify
.flags
= 0;
641 ses_lock_held
= B_TRUE
;
642 REFRELE(session_p
, ses_lock_held
);