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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
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"
35
36 CK_RV
C_VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)37 C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
38 CK_OBJECT_HANDLE hKey)
39 {
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;
47
48 if (!kernel_initialized)
49 return (CKR_CRYPTOKI_NOT_INITIALIZED);
50
51 if (pMechanism == NULL) {
52 return (CKR_ARGUMENTS_BAD);
53 }
54
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);
59
60 /* Obtain the session pointer. */
61 rv = handle2session(hSession, &session_p);
62 if (rv != CKR_OK)
63 return (rv);
64
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);
70 }
71
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;
76 }
77
78 (void) pthread_mutex_lock(&session_p->session_mutex);
79 ses_lock_held = B_TRUE;
80
81 /*
82 * This active flag will remain ON until application calls either
83 * C_Verify or C_VerifyFinal to verify a signature on data.
84 */
85 session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
86
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;
98 }
99 verify_init.vi_key.ck_length =
100 OBJ_SEC(key_p)->sk_value_len << 3;
101
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;
107 }
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;
113 }
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;
119 }
120 } else {
121 rv = CKR_KEY_TYPE_INCONSISTENT;
122 goto clean_exit;
123 }
124 }
125
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;
132
133 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_INIT, &verify_init)) < 0) {
134 if (errno != EINTR)
135 break;
136 }
137 if (r < 0) {
138 rv = CKR_FUNCTION_FAILED;
139 } else {
140 rv = crypto2pkcs11_error_number(verify_init.vi_return_value);
141 }
142
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;
153 }
154 }
155
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);
162 }
163 }
164
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;
169 }
170
171 clean_exit:
172 OBJ_REFRELE(key_p);
173 REFRELE(session_p, ses_lock_held);
174 return (rv);
175 }
176
177
178 CK_RV
C_Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)179 C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
180 CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
181 {
182
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;
188
189 if (!kernel_initialized)
190 return (CKR_CRYPTOKI_NOT_INITIALIZED);
191
192 /* Obatin the session pointer */
193 rv = handle2session(hSession, &session_p);
194 if (rv != CKR_OK)
195 return (rv);
196
197 (void) pthread_mutex_lock(&session_p->session_mutex);
198 ses_lock_held = B_TRUE;
199
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);
204 }
205
206 /*
207 * C_Verify must be called without intervening C_VerifyUpdate
208 * calls.
209 */
210 if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) {
211 /*
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.
216 */
217 REFRELE(session_p, ses_lock_held);
218 return (CKR_FUNCTION_FAILED);
219 }
220
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;
227
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);
234 }
235 }
236
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;
244
245 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY, &verify)) < 0) {
246 if (errno != EINTR)
247 break;
248 }
249 if (r < 0) {
250 rv = CKR_FUNCTION_FAILED;
251 } else {
252 rv = crypto2pkcs11_error_number(verify.cv_return_value);
253 }
254
255 clean_exit:
256 /*
257 * Always terminate the active verify operation.
258 * Application needs to call C_VerifyInit again for next
259 * verify operation.
260 */
261 (void) pthread_mutex_lock(&session_p->session_mutex);
262 ses_lock_held = B_TRUE;
263
264 REINIT_OPBUF(&session_p->verify);
265 session_p->verify.flags = 0;
266 REFRELE(session_p, ses_lock_held);
267
268 return (rv);
269 }
270
271
272 CK_RV
C_VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)273 C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
274 CK_ULONG ulPartLen)
275 {
276
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;
282
283 if (!kernel_initialized)
284 return (CKR_CRYPTOKI_NOT_INITIALIZED);
285
286 /* Obtain the session pointer */
287 rv = handle2session(hSession, &session_p);
288 if (rv != CKR_OK)
289 return (rv);
290
291 if (pPart == NULL) {
292 rv = CKR_ARGUMENTS_BAD;
293 goto clean_exit;
294 }
295
296 (void) pthread_mutex_lock(&session_p->session_mutex);
297 ses_lock_held = B_TRUE;
298
299 /*
300 * Application must call C_VerifyInit before calling
301 * C_VerifyUpdate.
302 */
303 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
304 REFRELE(session_p, ses_lock_held);
305 return (CKR_OPERATION_NOT_INITIALIZED);
306 }
307
308 session_p->verify.flags |= CRYPTO_OPERATION_UPDATE;
309
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;
315 }
316
317 verify_update.vu_session = session_p->k_session;
318 (void) pthread_mutex_unlock(&session_p->session_mutex);
319 ses_lock_held = B_FALSE;
320
321 verify_update.vu_datalen = ulPartLen;
322 verify_update.vu_databuf = (char *)pPart;
323
324 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_UPDATE,
325 &verify_update)) < 0) {
326 if (errno != EINTR)
327 break;
328 }
329 if (r < 0) {
330 rv = CKR_FUNCTION_FAILED;
331 } else {
332 rv = crypto2pkcs11_error_number(verify_update.vu_return_value);
333 }
334
335 done:
336 if (rv == CKR_OK) {
337 REFRELE(session_p, ses_lock_held);
338 return (rv);
339 }
340
341 clean_exit:
342 /*
343 * After an error occurred, terminate the current verify
344 * operation by resetting the active and update flags.
345 */
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);
351
352 return (rv);
353 }
354
355
356 CK_RV
C_VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)357 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
358 CK_ULONG ulSignatureLen)
359 {
360
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;
366
367 if (!kernel_initialized)
368 return (CKR_CRYPTOKI_NOT_INITIALIZED);
369
370 /* Obtain the session pointer */
371 rv = handle2session(hSession, &session_p);
372 if (rv != CKR_OK)
373 return (rv);
374
375 (void) pthread_mutex_lock(&session_p->session_mutex);
376 ses_lock_held = B_TRUE;
377
378 /*
379 * Application must call C_VerifyInit before calling
380 * C_VerifyFinal.
381 */
382 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
383 REFRELE(session_p, ses_lock_held);
384 return (CKR_OPERATION_NOT_INITIALIZED);
385 }
386
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 {
396 /*
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.
400 */
401 (void) pthread_mutex_unlock(&session_p->session_mutex);
402 ses_lock_held = B_FALSE;
403 rv = CKR_ARGUMENTS_BAD;
404 }
405 goto clean_exit;
406 } else if (session_p->verify.flags & CRYPTO_EMULATE) {
407 digest_buf_t *bufp = session_p->verify.context;
408
409 /*
410 * We are emulating a single-part operation now.
411 * So, clear the flag.
412 */
413 session_p->verify.flags &= ~CRYPTO_OPERATION_UPDATE;
414 if (bufp == NULL || bufp->buf == NULL) {
415 rv = CKR_ARGUMENTS_BAD;
416 goto clean_exit;
417 }
418 REFRELE(session_p, ses_lock_held);
419 rv = C_Verify(hSession, bufp->buf, bufp->indata_len,
420 pSignature, ulSignatureLen);
421 return (rv);
422 }
423
424 verify_final.vf_session = session_p->k_session;
425 (void) pthread_mutex_unlock(&session_p->session_mutex);
426 ses_lock_held = B_FALSE;
427
428 verify_final.vf_signlen = ulSignatureLen;
429 verify_final.vf_signbuf = (char *)pSignature;
430
431 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_FINAL, &verify_final)) < 0) {
432 if (errno != EINTR)
433 break;
434 }
435 if (r < 0) {
436 rv = CKR_FUNCTION_FAILED;
437 } else {
438 rv = crypto2pkcs11_error_number(verify_final.vf_return_value);
439 }
440
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);
448
449 return (rv);
450 }
451
452
453 CK_RV
C_VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)454 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
455 CK_OBJECT_HANDLE hKey)
456 {
457
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;
465
466 if (!kernel_initialized)
467 return (CKR_CRYPTOKI_NOT_INITIALIZED);
468
469 if (pMechanism == NULL) {
470 return (CKR_ARGUMENTS_BAD);
471 }
472
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);
477
478 /* Obtain the session pointer. */
479 rv = handle2session(hSession, &session_p);
480 if (rv != CKR_OK)
481 return (rv);
482
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);
488 }
489
490 /*
491 * Check to see if key object is a RSA key and if it supports
492 * verify_recover.
493 */
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;
498 }
499
500 (void) pthread_mutex_lock(&session_p->session_mutex);
501 ses_lock_held = B_TRUE;
502
503 /*
504 * This active flag will remain ON until application calls
505 * C_VerifyRecover to verify a signature on data.
506 */
507 session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
508
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;
519 }
520 } else {
521 rv = CKR_KEY_TYPE_INCONSISTENT;
522 goto clean_exit;
523 }
524 }
525
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;
532
533 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER_INIT,
534 &vr_init)) < 0) {
535 if (errno != EINTR)
536 break;
537 }
538 if (r < 0) {
539 rv = CKR_FUNCTION_FAILED;
540 } else {
541 rv = crypto2pkcs11_error_number(vr_init.ri_return_value);
542 }
543
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);
547 }
548
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;
553 }
554
555 clean_exit:
556 OBJ_REFRELE(key_p);
557 REFRELE(session_p, ses_lock_held);
558 return (rv);
559 }
560
561
562 CK_RV
C_VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)563 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
564 CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
565 {
566
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;
572
573 if (!kernel_initialized)
574 return (CKR_CRYPTOKI_NOT_INITIALIZED);
575
576 /* Obtain the session pointer */
577 rv = handle2session(hSession, &session_p);
578 if (rv != CKR_OK)
579 return (rv);
580
581 if (pSignature == NULL || pulDataLen == NULL) {
582 rv = CKR_ARGUMENTS_BAD;
583 goto clean_exit;
584 }
585
586 (void) pthread_mutex_lock(&session_p->session_mutex);
587 ses_lock_held = B_TRUE;
588
589 /*
590 * Application must call C_VerifyRecoverInit before calling
591 * C_Verify.
592 */
593 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
594 REFRELE(session_p, ses_lock_held);
595 return (CKR_OPERATION_NOT_INITIALIZED);
596 }
597
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;
605
606 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER,
607 &verify_recover)) < 0) {
608 if (errno != EINTR)
609 break;
610 }
611 if (r < 0) {
612 rv = CKR_FUNCTION_FAILED;
613 } else {
614 rv = crypto2pkcs11_error_number(
615 verify_recover.vr_return_value);
616 }
617
618 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
619 *pulDataLen = verify_recover.vr_datalen;
620
621 if ((rv == CKR_BUFFER_TOO_SMALL) ||
622 (rv == CKR_OK && pData == NULL)) {
623 /*
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.
628 */
629 REFRELE(session_p, ses_lock_held);
630 return (rv);
631 }
632
633 clean_exit:
634 /*
635 * Always terminate the active verify operation.
636 * Application needs to call C_VerifyInit again for next
637 * verify operation.
638 */
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);
643
644 return (rv);
645 }
646