8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_kernel / common / kernelVerify.c
blobb5da2e44fc2b5f8e9b1b0201d3be943427b756dc
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 <stdlib.h>
28 #include <errno.h>
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"
36 CK_RV
37 C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
38 CK_OBJECT_HANDLE hKey)
40 CK_RV rv;
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;
46 int r;
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);
57 if (rv != CKR_OK)
58 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 verification. */
73 if (key_p->is_lib_obj && !(key_p->bool_attr_mask & VERIFY_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_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;
90 } else {
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) {
96 rv = CKR_HOST_MEMORY;
97 goto clean_exit;
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) !=
104 CKR_OK) {
105 rv = CKR_HOST_MEMORY;
106 goto clean_exit;
108 } else if (key_p->key_type == CKK_DSA) {
109 if (get_dsa_public_key(key_p, &verify_init.vi_key) !=
110 CKR_OK) {
111 rv = CKR_HOST_MEMORY;
112 goto clean_exit;
114 } else if (key_p->key_type == CKK_EC) {
115 if (get_ec_public_key(key_p, &verify_init.vi_key) !=
116 CKR_OK) {
117 rv = CKR_HOST_MEMORY;
118 goto clean_exit;
120 } else {
121 rv = CKR_KEY_TYPE_INCONSISTENT;
122 goto clean_exit;
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) {
134 if (errno != EINTR)
135 break;
137 if (r < 0) {
138 rv = CKR_FUNCTION_FAILED;
139 } else {
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);
151 } else {
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);
160 } else {
161 free_key_attributes(&verify_init.vi_key);
165 if (rv != CKR_OK) {
166 (void) pthread_mutex_lock(&session_p->session_mutex);
167 session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
168 ses_lock_held = B_TRUE;
171 clean_exit:
172 OBJ_REFRELE(key_p);
173 REFRELE(session_p, ses_lock_held);
174 return (rv);
178 CK_RV
179 C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
180 CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
183 CK_RV rv;
184 kernel_session_t *session_p;
185 boolean_t ses_lock_held = B_FALSE;
186 crypto_verify_t verify;
187 int r;
189 if (!kernel_initialized)
190 return (CKR_CRYPTOKI_NOT_INITIALIZED);
192 /* Obatin the session pointer */
193 rv = handle2session(hSession, &session_p);
194 if (rv != CKR_OK)
195 return (rv);
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
208 * calls.
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),
229 pData, ulDataLen,
230 pSignature, ulSignatureLen, OP_SINGLE);
231 goto clean_exit;
232 } else {
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) {
246 if (errno != EINTR)
247 break;
249 if (r < 0) {
250 rv = CKR_FUNCTION_FAILED;
251 } else {
252 rv = crypto2pkcs11_error_number(verify.cv_return_value);
255 clean_exit:
257 * Always terminate the active verify operation.
258 * Application needs to call C_VerifyInit again for next
259 * verify operation.
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);
268 return (rv);
272 CK_RV
273 C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
274 CK_ULONG ulPartLen)
277 CK_RV rv;
278 kernel_session_t *session_p;
279 boolean_t ses_lock_held = B_FALSE;
280 crypto_verify_update_t verify_update;
281 int r;
283 if (!kernel_initialized)
284 return (CKR_CRYPTOKI_NOT_INITIALIZED);
286 /* Obtain the session pointer */
287 rv = handle2session(hSession, &session_p);
288 if (rv != CKR_OK)
289 return (rv);
291 if (pPart == NULL) {
292 rv = CKR_ARGUMENTS_BAD;
293 goto clean_exit;
296 (void) pthread_mutex_lock(&session_p->session_mutex);
297 ses_lock_held = B_TRUE;
300 * Application must call C_VerifyInit before calling
301 * C_VerifyUpdate.
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);
314 goto done;
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) {
326 if (errno != EINTR)
327 break;
329 if (r < 0) {
330 rv = CKR_FUNCTION_FAILED;
331 } else {
332 rv = crypto2pkcs11_error_number(verify_update.vu_return_value);
335 done:
336 if (rv == CKR_OK) {
337 REFRELE(session_p, ses_lock_held);
338 return (rv);
341 clean_exit:
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);
352 return (rv);
356 CK_RV
357 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
358 CK_ULONG ulSignatureLen)
361 CK_RV rv;
362 kernel_session_t *session_p;
363 boolean_t ses_lock_held = B_FALSE;
364 crypto_verify_final_t verify_final;
365 int r;
367 if (!kernel_initialized)
368 return (CKR_CRYPTOKI_NOT_INITIALIZED);
370 /* Obtain the session pointer */
371 rv = handle2session(hSession, &session_p);
372 if (rv != CKR_OK)
373 return (rv);
375 (void) pthread_mutex_lock(&session_p->session_mutex);
376 ses_lock_held = B_TRUE;
379 * Application must call C_VerifyInit before calling
380 * C_VerifyFinal.
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,
394 OP_FINAL);
395 } else {
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;
405 goto clean_exit;
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;
416 goto clean_exit;
418 REFRELE(session_p, ses_lock_held);
419 rv = C_Verify(hSession, bufp->buf, bufp->indata_len,
420 pSignature, ulSignatureLen);
421 return (rv);
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) {
432 if (errno != EINTR)
433 break;
435 if (r < 0) {
436 rv = CKR_FUNCTION_FAILED;
437 } else {
438 rv = crypto2pkcs11_error_number(verify_final.vf_return_value);
441 clean_exit:
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);
449 return (rv);
453 CK_RV
454 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
455 CK_OBJECT_HANDLE hKey)
458 CK_RV rv;
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;
464 int r;
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);
475 if (rv != CKR_OK)
476 return (rv);
478 /* Obtain the session pointer. */
479 rv = handle2session(hSession, &session_p);
480 if (rv != CKR_OK)
481 return (rv);
483 /* Obtain the object pointer. */
484 HANDLE2OBJECT(hKey, key_p, rv);
485 if (rv != CKR_OK) {
486 REFRELE(session_p, ses_lock_held);
487 return (rv);
491 * Check to see if key object is a RSA key and if it supports
492 * verify_recover.
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;
497 goto clean_exit;
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;
513 } else {
514 if (key_p->key_type == CKK_RSA) {
515 if (get_rsa_public_key(key_p, &vr_init.ri_key) !=
516 CKR_OK) {
517 rv = CKR_HOST_MEMORY;
518 goto clean_exit;
520 } else {
521 rv = CKR_KEY_TYPE_INCONSISTENT;
522 goto clean_exit;
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,
534 &vr_init)) < 0) {
535 if (errno != EINTR)
536 break;
538 if (r < 0) {
539 rv = CKR_FUNCTION_FAILED;
540 } else {
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);
549 if (rv != CKR_OK) {
550 (void) pthread_mutex_lock(&session_p->session_mutex);
551 session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
552 ses_lock_held = B_TRUE;
555 clean_exit:
556 OBJ_REFRELE(key_p);
557 REFRELE(session_p, ses_lock_held);
558 return (rv);
562 CK_RV
563 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
564 CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
567 CK_RV rv;
568 kernel_session_t *session_p;
569 boolean_t ses_lock_held = B_FALSE;
570 crypto_verify_recover_t verify_recover;
571 int r;
573 if (!kernel_initialized)
574 return (CKR_CRYPTOKI_NOT_INITIALIZED);
576 /* Obtain the session pointer */
577 rv = handle2session(hSession, &session_p);
578 if (rv != CKR_OK)
579 return (rv);
581 if (pSignature == NULL || pulDataLen == NULL) {
582 rv = CKR_ARGUMENTS_BAD;
583 goto clean_exit;
586 (void) pthread_mutex_lock(&session_p->session_mutex);
587 ses_lock_held = B_TRUE;
590 * Application must call C_VerifyRecoverInit before calling
591 * C_Verify.
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) {
608 if (errno != EINTR)
609 break;
611 if (r < 0) {
612 rv = CKR_FUNCTION_FAILED;
613 } else {
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);
630 return (rv);
633 clean_exit:
635 * Always terminate the active verify operation.
636 * Application needs to call C_VerifyInit again for next
637 * verify operation.
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);
644 return (rv);