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]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
28 * The ioctl interface for cryptographic commands.
31 #include <sys/types.h>
32 #include <sys/modctl.h>
36 #include <sys/sunddi.h>
38 #include <sys/errno.h>
39 #include <sys/ksynch.h>
45 #include <sys/mkdev.h>
46 #include <sys/model.h>
47 #include <sys/sysmacros.h>
48 #include <sys/crypto/common.h>
49 #include <sys/crypto/api.h>
50 #include <sys/crypto/impl.h>
51 #include <sys/crypto/sched_impl.h>
52 #include <sys/crypto/ioctl.h>
54 extern int kcf_des3_threshold
;
55 extern int kcf_aes_threshold
;
56 extern int kcf_rc4_threshold
;
57 extern int kcf_md5_threshold
;
58 extern int kcf_sha1_threshold
;
63 * crypto_locks protects the global array of minor structures.
64 * crypto_locks is an array of locks indexed by the cpuid. A reader needs
65 * to hold a single lock while a writer needs to hold all locks.
66 * krwlock_t is not an option here because the hold time
67 * is very small for these locks.
69 * The fields in the minor structure are protected by the cm_lock member
70 * of the minor structure. The cm_cv is used to signal decrements
71 * in the cm_refcnt, and is used with the cm_lock.
73 * The locking order is crypto_locks followed by cm_lock.
79 static int crypto_attach(dev_info_t
*, ddi_attach_cmd_t
);
80 static int crypto_detach(dev_info_t
*, ddi_detach_cmd_t
);
81 static int crypto_getinfo(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
82 static int crypto_open(dev_t
*, int, int, cred_t
*);
83 static int crypto_close(dev_t
, int, int, cred_t
*);
84 static int crypto_ioctl(dev_t
, int, intptr_t, int, cred_t
*, int *);
86 static int cipher_init(dev_t
, caddr_t
, int, int (*)(crypto_provider_t
,
87 crypto_session_id_t
, crypto_mechanism_t
*, crypto_key_t
*,
88 crypto_ctx_template_t
, crypto_context_t
*, crypto_call_req_t
*));
90 static int common_digest(dev_t
, caddr_t
, int, int (*)(crypto_context_t
,
91 crypto_data_t
*, crypto_data_t
*, crypto_call_req_t
*));
93 static int cipher(dev_t
, caddr_t
, int, int (*)(crypto_context_t
,
94 crypto_data_t
*, crypto_data_t
*, crypto_call_req_t
*));
96 static int cipher_update(dev_t
, caddr_t
, int, int (*)(crypto_context_t
,
97 crypto_data_t
*, crypto_data_t
*, crypto_call_req_t
*));
99 static int common_final(dev_t
, caddr_t
, int, int (*)(crypto_context_t
,
100 crypto_data_t
*, crypto_call_req_t
*));
102 static int sign_verify_init(dev_t
, caddr_t
, int, int (*)(crypto_provider_t
,
103 crypto_session_id_t
, crypto_mechanism_t
*, crypto_key_t
*,
104 crypto_ctx_template_t
, crypto_context_t
*, crypto_call_req_t
*));
106 static int sign_verify_update(dev_t dev
, caddr_t arg
, int mode
,
107 int (*)(crypto_context_t
, crypto_data_t
*, crypto_call_req_t
*));
109 static void crypto_release_provider_session(crypto_minor_t
*,
110 crypto_provider_session_t
*);
111 static int crypto_buffer_check(size_t);
112 static int crypto_free_find_ctx(crypto_session_data_t
*);
113 static int crypto_get_provider_list(crypto_minor_t
*, uint_t
*,
114 crypto_provider_entry_t
**, boolean_t
);
116 static int crypto_create_provider_session(crypto_minor_t
*,
117 kcf_provider_desc_t
*, crypto_session_id_t
, crypto_provider_session_t
**,
118 kcf_provider_desc_t
*);
119 static int crypto_create_session_ptr(crypto_minor_t
*, kcf_provider_desc_t
*,
120 crypto_provider_session_t
*, crypto_session_id_t
*);
122 /* number of minor numbers to allocate at a time */
123 #define CRYPTO_MINOR_CHUNK 16
126 * There are two limits associated with kernel memory. The first,
127 * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be
128 * allocated for a single copyin/copyout buffer. The second limit is
129 * the total number of bytes that can be allocated by a process
130 * for copyin/copyout buffers. The latter is enforced by the
131 * project.max-crypto-memory resource control.
134 #define CRYPTO_MAX_BUFFER_LEN (2 * 1024 * 1024)
135 #define CRYPTO_MAX_FIND_COUNT 512
138 * We preapprove some bytes for each session to avoid making the costly
139 * crypto_buffer_check() calls. The preapproval is done when a new session
140 * is created and that cost is amortized over later crypto calls.
141 * Most applications create a session and then do a bunch of crypto calls
142 * in that session. So, they benefit from this optimization.
144 * Note that we may hit the project.max-crypto-memory limit a bit sooner
145 * because of this preapproval. But it is acceptable since the preapproved
146 * amount is insignificant compared to the default max-crypto-memory limit
147 * which is quarter of the machine's memory. The preapproved amount is
148 * roughly 2 * 16K(maximum SSL record size).
150 #define CRYPTO_PRE_APPROVED_LIMIT (32 * 1024)
152 /* The session table grows by CRYPTO_SESSION_CHUNK increments */
153 #define CRYPTO_SESSION_CHUNK 100
155 size_t crypto_max_buffer_len
= CRYPTO_MAX_BUFFER_LEN
;
156 size_t crypto_pre_approved_limit
= CRYPTO_PRE_APPROVED_LIMIT
;
158 #define INIT_RAW_CRYPTO_DATA(data, len) \
159 (data).cd_format = CRYPTO_DATA_RAW; \
160 (data).cd_raw.iov_base = kmem_alloc(len, KM_SLEEP); \
161 (data).cd_raw.iov_len = len; \
162 (data).cd_offset = 0; \
163 (data).cd_length = len;
165 static struct kmem_cache
*crypto_session_cache
;
166 static crypto_minor_t
**crypto_minors
= NULL
;
167 static dev_info_t
*crypto_dip
= NULL
;
168 static minor_t crypto_minor_chunk
= CRYPTO_MINOR_CHUNK
;
169 static minor_t crypto_minors_table_count
= 0;
172 * Minors are started from 1 because vmem_alloc()
173 * returns 0 in case of failure.
175 static vmem_t
*crypto_arena
= NULL
; /* Arena for device minors */
176 static minor_t crypto_minors_count
= 0;
177 static kcf_lock_withpad_t
*crypto_locks
;
179 #define CRYPTO_ENTER_ALL_LOCKS() \
180 for (i = 0; i < max_ncpus; i++) \
181 mutex_enter(&crypto_locks[i].kl_lock);
183 #define CRYPTO_EXIT_ALL_LOCKS() \
184 for (i = 0; i < max_ncpus; i++) \
185 mutex_exit(&crypto_locks[i].kl_lock);
187 #define RETURN_LIST B_TRUE
188 #define DONT_RETURN_LIST B_FALSE
190 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
191 #define CRYPTO_RANDOM_OFFSET(f) offsetof(crypto_random_number_ops_t, f)
192 #define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f)
193 #define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f)
194 #define CRYPTO_PROVIDER_OFFSET(f) \
195 offsetof(crypto_provider_management_ops_t, f)
197 #define CRYPTO_CANCEL_CTX(spp) { \
198 crypto_cancel_ctx(*(spp)); \
202 #define CRYPTO_CANCEL_ALL_CTX(sp) { \
203 if ((sp)->sd_digest_ctx != NULL) { \
204 crypto_cancel_ctx((sp)->sd_digest_ctx); \
205 (sp)->sd_digest_ctx = NULL; \
207 if ((sp)->sd_encr_ctx != NULL) { \
208 crypto_cancel_ctx((sp)->sd_encr_ctx); \
209 (sp)->sd_encr_ctx = NULL; \
211 if ((sp)->sd_decr_ctx != NULL) { \
212 crypto_cancel_ctx((sp)->sd_decr_ctx); \
213 (sp)->sd_decr_ctx = NULL; \
215 if ((sp)->sd_sign_ctx != NULL) { \
216 crypto_cancel_ctx((sp)->sd_sign_ctx); \
217 (sp)->sd_sign_ctx = NULL; \
219 if ((sp)->sd_verify_ctx != NULL) { \
220 crypto_cancel_ctx((sp)->sd_verify_ctx); \
221 (sp)->sd_verify_ctx = NULL; \
223 if ((sp)->sd_sign_recover_ctx != NULL) { \
224 crypto_cancel_ctx((sp)->sd_sign_recover_ctx); \
225 (sp)->sd_sign_recover_ctx = NULL; \
227 if ((sp)->sd_verify_recover_ctx != NULL) { \
228 crypto_cancel_ctx((sp)->sd_verify_recover_ctx); \
229 (sp)->sd_verify_recover_ctx = NULL; \
231 if ((sp)->sd_mac_ctx != NULL) { \
232 crypto_cancel_ctx((sp)->sd_mac_ctx); \
233 (sp)->sd_mac_ctx = NULL; \
237 #define CRYPTO_DECREMENT_RCTL(val) if ((val) != 0) { \
239 mutex_enter(&curproc->p_lock); \
240 projp = curproc->p_task->tk_proj; \
241 ASSERT(projp != NULL); \
242 mutex_enter(&(projp->kpj_data.kpd_crypto_lock)); \
243 projp->kpj_data.kpd_crypto_mem -= (val); \
244 mutex_exit(&(projp->kpj_data.kpd_crypto_lock)); \
245 curproc->p_crypto_mem -= (val); \
246 mutex_exit(&curproc->p_lock); \
250 * We do not need to hold sd_lock in the macros below
251 * as they are called after doing a get_session_ptr() which
252 * sets the CRYPTO_SESSION_IS_BUSY flag.
254 #define CRYPTO_DECREMENT_RCTL_SESSION(sp, val, rctl_chk) \
255 if (((val) != 0) && ((sp) != NULL)) { \
256 ASSERT(((sp)->sd_flags & CRYPTO_SESSION_IS_BUSY) != 0); \
258 CRYPTO_DECREMENT_RCTL(val); \
260 (sp)->sd_pre_approved_amount += (val); \
264 #define CRYPTO_BUFFER_CHECK(sp, need, rctl_chk) \
265 ((sp->sd_pre_approved_amount >= need) ? \
266 (sp->sd_pre_approved_amount -= need, \
267 rctl_chk = B_FALSE, CRYPTO_SUCCESS) : \
268 (rctl_chk = B_TRUE, crypto_buffer_check(need)))
273 static struct cb_ops cbops
= {
274 crypto_open
, /* cb_open */
275 crypto_close
, /* cb_close */
276 nodev
, /* cb_strategy */
277 nodev
, /* cb_print */
280 nodev
, /* cb_write */
281 crypto_ioctl
, /* cb_ioctl */
282 nodev
, /* cb_devmap */
284 nodev
, /* cb_segmap */
285 nochpoll
, /* cb_chpoll */
286 ddi_prop_op
, /* cb_prop_op */
287 NULL
, /* cb_streamtab */
290 nodev
, /* cb_aread */
291 nodev
, /* cb_awrite */
294 static struct dev_ops devops
= {
295 DEVO_REV
, /* devo_rev */
297 crypto_getinfo
, /* devo_getinfo */
298 nulldev
, /* devo_identify */
299 nulldev
, /* devo_probe */
300 crypto_attach
, /* devo_attach */
301 crypto_detach
, /* devo_detach */
302 nodev
, /* devo_reset */
303 &cbops
, /* devo_cb_ops */
304 NULL
, /* devo_bus_ops */
305 NULL
, /* devo_power */
306 ddi_quiesce_not_needed
, /* devo_quiesce */
309 static struct modldrv modldrv
= {
310 &mod_driverops
, /* drv_modops */
311 "Cryptographic Library Interface", /* drv_linkinfo */
315 static struct modlinkage modlinkage
= {
316 MODREV_1
, /* ml_rev */
317 &modldrv
, /* ml_linkage */
327 return (mod_install(&modlinkage
));
333 return (mod_remove(&modlinkage
));
337 _info(struct modinfo
*modinfop
)
339 return (mod_info(&modlinkage
, modinfop
));
344 crypto_getinfo(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
, void **result
)
347 case DDI_INFO_DEVT2DEVINFO
:
348 *result
= crypto_dip
;
349 return (DDI_SUCCESS
);
351 case DDI_INFO_DEVT2INSTANCE
:
353 return (DDI_SUCCESS
);
355 return (DDI_FAILURE
);
359 crypto_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
363 if (cmd
!= DDI_ATTACH
) {
364 return (DDI_FAILURE
);
367 if (ddi_get_instance(dip
) != 0) {
368 /* we only allow instance 0 to attach */
369 return (DDI_FAILURE
);
372 crypto_session_cache
= kmem_cache_create("crypto_session_cache",
373 sizeof (crypto_session_data_t
), 0, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
375 if (crypto_session_cache
== NULL
)
376 return (DDI_FAILURE
);
378 /* create the minor node */
379 if (ddi_create_minor_node(dip
, "crypto", S_IFCHR
, 0,
380 DDI_PSEUDO
, 0) != DDI_SUCCESS
) {
381 kmem_cache_destroy(crypto_session_cache
);
382 crypto_session_cache
= NULL
;
383 cmn_err(CE_WARN
, "crypto_attach: failed creating minor node");
384 ddi_remove_minor_node(dip
, NULL
);
385 return (DDI_FAILURE
);
388 crypto_locks
= kmem_zalloc(max_ncpus
* sizeof (kcf_lock_withpad_t
),
390 for (i
= 0; i
< max_ncpus
; i
++)
391 mutex_init(&crypto_locks
[i
].kl_lock
, NULL
, MUTEX_DRIVER
, NULL
);
395 /* allocate integer space for minor numbers */
396 crypto_arena
= vmem_create("crypto", (void *)1,
397 CRYPTO_MINOR_CHUNK
, 1, NULL
, NULL
, NULL
, 0,
398 VM_SLEEP
| VMC_IDENTIFIER
);
400 return (DDI_SUCCESS
);
404 crypto_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
407 kcf_lock_withpad_t
*mp
;
409 if (cmd
!= DDI_DETACH
)
410 return (DDI_FAILURE
);
412 mp
= &crypto_locks
[CPU_SEQID
];
413 mutex_enter(&mp
->kl_lock
);
415 /* check if device is open */
416 for (i
= 0; i
< crypto_minors_table_count
; i
++) {
417 if (crypto_minors
[i
] != NULL
) {
418 mutex_exit(&mp
->kl_lock
);
419 return (DDI_FAILURE
);
422 mutex_exit(&mp
->kl_lock
);
425 ddi_remove_minor_node(dip
, NULL
);
427 kmem_cache_destroy(crypto_session_cache
);
428 crypto_session_cache
= NULL
;
430 kmem_free(crypto_minors
,
431 sizeof (crypto_minor_t
*) * crypto_minors_table_count
);
432 crypto_minors
= NULL
;
433 crypto_minors_table_count
= 0;
434 for (i
= 0; i
< max_ncpus
; i
++)
435 mutex_destroy(&crypto_locks
[i
].kl_lock
);
436 kmem_free(crypto_locks
, max_ncpus
* sizeof (kcf_lock_withpad_t
));
439 vmem_destroy(crypto_arena
);
442 return (DDI_SUCCESS
);
447 crypto_open(dev_t
*devp
, int flag
, int otyp
, cred_t
*credp
)
449 crypto_minor_t
*cm
= NULL
;
451 kcf_lock_withpad_t
*mp
;
454 if (otyp
!= OTYP_CHR
)
457 if (crypto_dip
== NULL
)
460 /* exclusive opens are not supported */
465 mp
= &crypto_locks
[CPU_SEQID
];
466 mutex_enter(&mp
->kl_lock
);
468 /* grow the minors table if needed */
469 if (crypto_minors_count
>= crypto_minors_table_count
) {
470 crypto_minor_t
**newtable
;
471 minor_t chunk
= crypto_minor_chunk
;
476 big_count
= crypto_minors_count
+ chunk
;
477 if (big_count
> MAXMIN
) {
478 mutex_exit(&mp
->kl_lock
);
482 saved_count
= crypto_minors_table_count
;
483 new_size
= sizeof (crypto_minor_t
*) *
484 (crypto_minors_table_count
+ chunk
);
486 mutex_exit(&mp
->kl_lock
);
488 newtable
= kmem_zalloc(new_size
, KM_SLEEP
);
489 CRYPTO_ENTER_ALL_LOCKS();
491 * Check if table grew while we were sleeping.
492 * The minors table never shrinks.
494 if (crypto_minors_table_count
> saved_count
) {
495 CRYPTO_EXIT_ALL_LOCKS();
496 kmem_free(newtable
, new_size
);
500 /* we assume that bcopy() will return if count is 0 */
501 bcopy(crypto_minors
, newtable
,
502 sizeof (crypto_minor_t
*) * crypto_minors_table_count
);
504 kmem_free(crypto_minors
,
505 sizeof (crypto_minor_t
*) * crypto_minors_table_count
);
507 /* grow the minors number space */
508 if (crypto_minors_table_count
!= 0) {
509 (void) vmem_add(crypto_arena
,
510 (void *)(uintptr_t)(crypto_minors_table_count
+ 1),
511 crypto_minor_chunk
, VM_SLEEP
);
514 crypto_minors
= newtable
;
515 crypto_minors_table_count
+= chunk
;
516 CRYPTO_EXIT_ALL_LOCKS();
518 mutex_exit(&mp
->kl_lock
);
521 /* allocate a new minor number starting with 1 */
522 mn
= (minor_t
)(uintptr_t)vmem_alloc(crypto_arena
, 1, VM_SLEEP
);
524 cm
= kmem_zalloc(sizeof (crypto_minor_t
), KM_SLEEP
);
525 mutex_init(&cm
->cm_lock
, NULL
, MUTEX_DRIVER
, NULL
);
526 cv_init(&cm
->cm_cv
, NULL
, CV_DRIVER
, NULL
);
528 CRYPTO_ENTER_ALL_LOCKS();
530 crypto_minors
[mn
- 1] = cm
;
531 crypto_minors_count
++;
532 CRYPTO_EXIT_ALL_LOCKS();
534 *devp
= makedevice(getmajor(*devp
), mn
);
541 crypto_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
543 crypto_minor_t
*cm
= NULL
;
544 crypto_session_data_t
*sp
;
545 minor_t mn
= getminor(dev
);
548 kcf_lock_withpad_t
*mp
;
550 mp
= &crypto_locks
[CPU_SEQID
];
551 mutex_enter(&mp
->kl_lock
);
553 if (mn
> crypto_minors_table_count
) {
554 mutex_exit(&mp
->kl_lock
);
555 cmn_err(CE_WARN
, "crypto_close: bad minor (too big) %d", mn
);
559 cm
= crypto_minors
[mn
- 1];
561 mutex_exit(&mp
->kl_lock
);
562 cmn_err(CE_WARN
, "crypto_close: duplicate close of minor %d",
567 mutex_exit(&mp
->kl_lock
);
569 CRYPTO_ENTER_ALL_LOCKS();
571 * We free the minor number, mn, from the crypto_arena
572 * only later. This ensures that we won't race with another
573 * thread in crypto_open with the same minor number.
575 crypto_minors
[mn
- 1] = NULL
;
576 crypto_minors_count
--;
577 CRYPTO_EXIT_ALL_LOCKS();
579 mutex_enter(&cm
->cm_lock
);
580 cm
->cm_refcnt
--; /* decrement refcnt held in open */
581 while (cm
->cm_refcnt
> 0) {
582 cv_wait(&cm
->cm_cv
, &cm
->cm_lock
);
585 vmem_free(crypto_arena
, (void *)(uintptr_t)mn
, 1);
587 /* free all session table entries starting with 1 */
588 for (i
= 1; i
< cm
->cm_session_table_count
; i
++) {
589 if (cm
->cm_session_table
[i
] == NULL
)
592 sp
= cm
->cm_session_table
[i
];
593 ASSERT((sp
->sd_flags
& CRYPTO_SESSION_IS_BUSY
) == 0);
594 ASSERT(sp
->sd_pre_approved_amount
== 0 ||
595 sp
->sd_pre_approved_amount
== crypto_pre_approved_limit
);
596 total
+= sp
->sd_pre_approved_amount
;
597 if (sp
->sd_find_init_cookie
!= NULL
) {
598 (void) crypto_free_find_ctx(sp
);
600 crypto_release_provider_session(cm
, sp
->sd_provider_session
);
601 KCF_PROV_REFRELE(sp
->sd_provider
);
602 CRYPTO_CANCEL_ALL_CTX(sp
);
603 mutex_destroy(&sp
->sd_lock
);
604 cv_destroy(&sp
->sd_cv
);
605 kmem_cache_free(crypto_session_cache
, sp
);
606 cm
->cm_session_table
[i
] = NULL
;
609 /* free the session table */
610 if (cm
->cm_session_table
!= NULL
&& cm
->cm_session_table_count
> 0)
611 kmem_free(cm
->cm_session_table
, cm
->cm_session_table_count
*
614 total
+= (cm
->cm_session_table_count
* sizeof (void *));
615 CRYPTO_DECREMENT_RCTL(total
);
617 kcf_free_provider_tab(cm
->cm_provider_count
,
618 cm
->cm_provider_array
);
620 mutex_exit(&cm
->cm_lock
);
621 mutex_destroy(&cm
->cm_lock
);
622 cv_destroy(&cm
->cm_cv
);
623 kmem_free(cm
, sizeof (crypto_minor_t
));
628 static crypto_minor_t
*
629 crypto_hold_minor(minor_t minor
)
632 kcf_lock_withpad_t
*mp
;
634 if (minor
> crypto_minors_table_count
)
637 mp
= &crypto_locks
[CPU_SEQID
];
638 mutex_enter(&mp
->kl_lock
);
640 if ((cm
= crypto_minors
[minor
- 1]) != NULL
) {
641 atomic_inc_32(&cm
->cm_refcnt
);
643 mutex_exit(&mp
->kl_lock
);
648 crypto_release_minor(crypto_minor_t
*cm
)
650 if (atomic_dec_32_nv(&cm
->cm_refcnt
) == 0) {
651 cv_signal(&cm
->cm_cv
);
656 * Build a list of functions and other information for the provider, pd.
659 crypto_build_function_list(crypto_function_list_t
*fl
, kcf_provider_desc_t
*pd
)
662 crypto_digest_ops_t
*digest_ops
;
663 crypto_cipher_ops_t
*cipher_ops
;
664 crypto_mac_ops_t
*mac_ops
;
665 crypto_sign_ops_t
*sign_ops
;
666 crypto_verify_ops_t
*verify_ops
;
667 crypto_dual_ops_t
*dual_ops
;
668 crypto_random_number_ops_t
*random_number_ops
;
669 crypto_session_ops_t
*session_ops
;
670 crypto_object_ops_t
*object_ops
;
671 crypto_key_ops_t
*key_ops
;
672 crypto_provider_management_ops_t
*provider_ops
;
674 if ((ops
= pd
->pd_ops_vector
) == NULL
)
677 if ((digest_ops
= ops
->co_digest_ops
) != NULL
) {
678 if (digest_ops
->digest_init
!= NULL
)
679 fl
->fl_digest_init
= B_TRUE
;
680 if (digest_ops
->digest
!= NULL
)
681 fl
->fl_digest
= B_TRUE
;
682 if (digest_ops
->digest_update
!= NULL
)
683 fl
->fl_digest_update
= B_TRUE
;
684 if (digest_ops
->digest_key
!= NULL
)
685 fl
->fl_digest_key
= B_TRUE
;
686 if (digest_ops
->digest_final
!= NULL
)
687 fl
->fl_digest_final
= B_TRUE
;
689 if ((cipher_ops
= ops
->co_cipher_ops
) != NULL
) {
690 if (cipher_ops
->encrypt_init
!= NULL
)
691 fl
->fl_encrypt_init
= B_TRUE
;
692 if (cipher_ops
->encrypt
!= NULL
)
693 fl
->fl_encrypt
= B_TRUE
;
694 if (cipher_ops
->encrypt_update
!= NULL
)
695 fl
->fl_encrypt_update
= B_TRUE
;
696 if (cipher_ops
->encrypt_final
!= NULL
)
697 fl
->fl_encrypt_final
= B_TRUE
;
698 if (cipher_ops
->decrypt_init
!= NULL
)
699 fl
->fl_decrypt_init
= B_TRUE
;
700 if (cipher_ops
->decrypt
!= NULL
)
701 fl
->fl_decrypt
= B_TRUE
;
702 if (cipher_ops
->decrypt_update
!= NULL
)
703 fl
->fl_decrypt_update
= B_TRUE
;
704 if (cipher_ops
->decrypt_final
!= NULL
)
705 fl
->fl_decrypt_final
= B_TRUE
;
707 if ((mac_ops
= ops
->co_mac_ops
) != NULL
) {
708 if (mac_ops
->mac_init
!= NULL
)
709 fl
->fl_mac_init
= B_TRUE
;
710 if (mac_ops
->mac
!= NULL
)
712 if (mac_ops
->mac_update
!= NULL
)
713 fl
->fl_mac_update
= B_TRUE
;
714 if (mac_ops
->mac_final
!= NULL
)
715 fl
->fl_mac_final
= B_TRUE
;
717 if ((sign_ops
= ops
->co_sign_ops
) != NULL
) {
718 if (sign_ops
->sign_init
!= NULL
)
719 fl
->fl_sign_init
= B_TRUE
;
720 if (sign_ops
->sign
!= NULL
)
721 fl
->fl_sign
= B_TRUE
;
722 if (sign_ops
->sign_update
!= NULL
)
723 fl
->fl_sign_update
= B_TRUE
;
724 if (sign_ops
->sign_final
!= NULL
)
725 fl
->fl_sign_final
= B_TRUE
;
726 if (sign_ops
->sign_recover_init
!= NULL
)
727 fl
->fl_sign_recover_init
= B_TRUE
;
728 if (sign_ops
->sign_recover
!= NULL
)
729 fl
->fl_sign_recover
= B_TRUE
;
731 if ((verify_ops
= ops
->co_verify_ops
) != NULL
) {
732 if (verify_ops
->verify_init
!= NULL
)
733 fl
->fl_verify_init
= B_TRUE
;
734 if (verify_ops
->verify
!= NULL
)
735 fl
->fl_verify
= B_TRUE
;
736 if (verify_ops
->verify_update
!= NULL
)
737 fl
->fl_verify_update
= B_TRUE
;
738 if (verify_ops
->verify_final
!= NULL
)
739 fl
->fl_verify_final
= B_TRUE
;
740 if (verify_ops
->verify_recover_init
!= NULL
)
741 fl
->fl_verify_recover_init
= B_TRUE
;
742 if (verify_ops
->verify_recover
!= NULL
)
743 fl
->fl_verify_recover
= B_TRUE
;
745 if ((dual_ops
= ops
->co_dual_ops
) != NULL
) {
746 if (dual_ops
->digest_encrypt_update
!= NULL
)
747 fl
->fl_digest_encrypt_update
= B_TRUE
;
748 if (dual_ops
->decrypt_digest_update
!= NULL
)
749 fl
->fl_decrypt_digest_update
= B_TRUE
;
750 if (dual_ops
->sign_encrypt_update
!= NULL
)
751 fl
->fl_sign_encrypt_update
= B_TRUE
;
752 if (dual_ops
->decrypt_verify_update
!= NULL
)
753 fl
->fl_decrypt_verify_update
= B_TRUE
;
755 if ((random_number_ops
= ops
->co_random_ops
) != NULL
) {
756 if (random_number_ops
->seed_random
!= NULL
)
757 fl
->fl_seed_random
= B_TRUE
;
758 if (random_number_ops
->generate_random
!= NULL
)
759 fl
->fl_generate_random
= B_TRUE
;
761 if ((session_ops
= ops
->co_session_ops
) != NULL
) {
762 if (session_ops
->session_open
!= NULL
)
763 fl
->fl_session_open
= B_TRUE
;
764 if (session_ops
->session_close
!= NULL
)
765 fl
->fl_session_close
= B_TRUE
;
766 if (session_ops
->session_login
!= NULL
)
767 fl
->fl_session_login
= B_TRUE
;
768 if (session_ops
->session_logout
!= NULL
)
769 fl
->fl_session_logout
= B_TRUE
;
771 if ((object_ops
= ops
->co_object_ops
) != NULL
) {
772 if (object_ops
->object_create
!= NULL
)
773 fl
->fl_object_create
= B_TRUE
;
774 if (object_ops
->object_copy
!= NULL
)
775 fl
->fl_object_copy
= B_TRUE
;
776 if (object_ops
->object_destroy
!= NULL
)
777 fl
->fl_object_destroy
= B_TRUE
;
778 if (object_ops
->object_get_size
!= NULL
)
779 fl
->fl_object_get_size
= B_TRUE
;
780 if (object_ops
->object_get_attribute_value
!= NULL
)
781 fl
->fl_object_get_attribute_value
= B_TRUE
;
782 if (object_ops
->object_set_attribute_value
!= NULL
)
783 fl
->fl_object_set_attribute_value
= B_TRUE
;
784 if (object_ops
->object_find_init
!= NULL
)
785 fl
->fl_object_find_init
= B_TRUE
;
786 if (object_ops
->object_find
!= NULL
)
787 fl
->fl_object_find
= B_TRUE
;
788 if (object_ops
->object_find_final
!= NULL
)
789 fl
->fl_object_find_final
= B_TRUE
;
791 if ((key_ops
= ops
->co_key_ops
) != NULL
) {
792 if (key_ops
->key_generate
!= NULL
)
793 fl
->fl_key_generate
= B_TRUE
;
794 if (key_ops
->key_generate_pair
!= NULL
)
795 fl
->fl_key_generate_pair
= B_TRUE
;
796 if (key_ops
->key_wrap
!= NULL
)
797 fl
->fl_key_wrap
= B_TRUE
;
798 if (key_ops
->key_unwrap
!= NULL
)
799 fl
->fl_key_unwrap
= B_TRUE
;
800 if (key_ops
->key_derive
!= NULL
)
801 fl
->fl_key_derive
= B_TRUE
;
803 if ((provider_ops
= ops
->co_provider_ops
) != NULL
) {
804 if (provider_ops
->init_token
!= NULL
)
805 fl
->fl_init_token
= B_TRUE
;
806 if (provider_ops
->init_pin
!= NULL
)
807 fl
->fl_init_pin
= B_TRUE
;
808 if (provider_ops
->set_pin
!= NULL
)
809 fl
->fl_set_pin
= B_TRUE
;
812 fl
->prov_is_hash_limited
= pd
->pd_flags
& CRYPTO_HASH_NO_UPDATE
;
813 if (fl
->prov_is_hash_limited
) {
814 fl
->prov_hash_limit
= min(pd
->pd_hash_limit
,
815 min(CRYPTO_MAX_BUFFER_LEN
,
816 curproc
->p_task
->tk_proj
->kpj_data
.kpd_crypto_mem_ctl
));
819 fl
->prov_is_hmac_limited
= pd
->pd_flags
& CRYPTO_HMAC_NO_UPDATE
;
820 if (fl
->prov_is_hmac_limited
) {
821 fl
->prov_hmac_limit
= min(pd
->pd_hmac_limit
,
822 min(CRYPTO_MAX_BUFFER_LEN
,
823 curproc
->p_task
->tk_proj
->kpj_data
.kpd_crypto_mem_ctl
));
826 if (fl
->prov_is_hash_limited
|| fl
->prov_is_hmac_limited
) {
828 * XXX - The threshold should ideally be per hash/HMAC
829 * mechanism. For now, we use the same value for all
830 * hash/HMAC mechanisms. Empirical evidence suggests this
833 fl
->prov_hash_threshold
= kcf_md5_threshold
;
836 fl
->total_threshold_count
= MAX_NUM_THRESHOLD
;
837 fl
->fl_threshold
[0].mech_type
= CKM_DES3_CBC
;
838 fl
->fl_threshold
[0].mech_threshold
= kcf_des3_threshold
;
839 fl
->fl_threshold
[1].mech_type
= CKM_DES3_ECB
;
840 fl
->fl_threshold
[1].mech_threshold
= kcf_des3_threshold
;
841 fl
->fl_threshold
[2].mech_type
= CKM_AES_CBC
;
842 fl
->fl_threshold
[2].mech_threshold
= kcf_aes_threshold
;
843 fl
->fl_threshold
[3].mech_type
= CKM_AES_ECB
;
844 fl
->fl_threshold
[3].mech_threshold
= kcf_aes_threshold
;
845 fl
->fl_threshold
[4].mech_type
= CKM_RC4
;
846 fl
->fl_threshold
[4].mech_threshold
= kcf_rc4_threshold
;
847 fl
->fl_threshold
[5].mech_type
= CKM_MD5
;
848 fl
->fl_threshold
[5].mech_threshold
= kcf_md5_threshold
;
849 fl
->fl_threshold
[6].mech_type
= CKM_SHA_1
;
850 fl
->fl_threshold
[6].mech_threshold
= kcf_sha1_threshold
;
855 get_function_list(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
857 crypto_get_function_list_t get_function_list
;
859 crypto_provider_id_t provider_id
;
860 crypto_function_list_t
*fl
;
861 kcf_provider_desc_t
*provider
;
864 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
865 cmn_err(CE_WARN
, "get_function_list: failed holding minor");
869 if (copyin(arg
, &get_function_list
, sizeof (get_function_list
)) != 0) {
870 crypto_release_minor(cm
);
874 /* initialize provider_array */
875 if (cm
->cm_provider_array
== NULL
) {
876 rv
= crypto_get_provider_list(cm
, NULL
, NULL
, DONT_RETURN_LIST
);
877 if (rv
!= CRYPTO_SUCCESS
) {
882 provider_id
= get_function_list
.fl_provider_id
;
883 mutex_enter(&cm
->cm_lock
);
884 /* index must be less than count of providers */
885 if (provider_id
>= cm
->cm_provider_count
) {
886 mutex_exit(&cm
->cm_lock
);
887 rv
= CRYPTO_ARGUMENTS_BAD
;
891 ASSERT(cm
->cm_provider_array
!= NULL
);
892 provider
= cm
->cm_provider_array
[provider_id
];
893 mutex_exit(&cm
->cm_lock
);
895 fl
= &get_function_list
.fl_list
;
896 bzero(fl
, sizeof (crypto_function_list_t
));
898 if (provider
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
) {
899 crypto_build_function_list(fl
, provider
);
901 kcf_provider_desc_t
*prev
= NULL
, *pd
;
903 mutex_enter(&provider
->pd_lock
);
904 while (kcf_get_next_logical_provider_member(provider
,
907 crypto_build_function_list(fl
, pd
);
908 KCF_PROV_REFRELE(pd
);
910 mutex_exit(&provider
->pd_lock
);
916 crypto_release_minor(cm
);
918 get_function_list
.fl_return_value
= rv
;
920 if (copyout(&get_function_list
, arg
, sizeof (get_function_list
)) != 0) {
927 * This ioctl maps a PKCS#11 mechanism string into an internal number
928 * that is used by the kernel. pn_internal_number is set to the
933 get_mechanism_number(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
935 STRUCT_DECL(crypto_get_mechanism_number
, get_number
);
936 crypto_mech_type_t number
;
938 char *mechanism_name
;
941 STRUCT_INIT(get_number
, mode
);
943 if (copyin(arg
, STRUCT_BUF(get_number
), STRUCT_SIZE(get_number
)) != 0)
946 len
= STRUCT_FGET(get_number
, pn_mechanism_len
);
947 if (len
== 0 || len
> CRYPTO_MAX_MECH_NAME
) {
948 rv
= CRYPTO_ARGUMENTS_BAD
;
951 mechanism_name
= kmem_alloc(len
, KM_SLEEP
);
953 if (copyin(STRUCT_FGETP(get_number
, pn_mechanism_string
),
954 mechanism_name
, len
) != 0) {
955 kmem_free(mechanism_name
, len
);
960 * Get mechanism number from kcf. We set the load_module
961 * flag to false since we use only hardware providers.
963 number
= crypto_mech2id_common(mechanism_name
, B_FALSE
);
964 kmem_free(mechanism_name
, len
);
965 if (number
== CRYPTO_MECH_INVALID
) {
966 rv
= CRYPTO_ARGUMENTS_BAD
;
970 bcopy((char *)&number
, (char *)STRUCT_FADDR(get_number
,
971 pn_internal_number
), sizeof (number
));
975 STRUCT_FSET(get_number
, pn_return_value
, rv
);
977 if (copyout(STRUCT_BUF(get_number
), arg
,
978 STRUCT_SIZE(get_number
)) != 0) {
985 * This ioctl returns an array of crypto_mech_name_t entries.
986 * It lists all the PKCS#11 mechanisms available in the kernel.
990 get_mechanism_list(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
992 STRUCT_DECL(crypto_get_mechanism_list
, get_list
);
993 crypto_mech_name_t
*entries
;
1000 STRUCT_INIT(get_list
, mode
);
1002 if (copyin(arg
, STRUCT_BUF(get_list
), STRUCT_SIZE(get_list
)) != 0) {
1006 entries
= crypto_get_mech_list(&count
, KM_SLEEP
);
1008 /* Number of entries caller thinks we have */
1009 req_count
= STRUCT_FGET(get_list
, ml_count
);
1011 STRUCT_FSET(get_list
, ml_count
, count
);
1012 STRUCT_FSET(get_list
, ml_return_value
, CRYPTO_SUCCESS
);
1014 /* check if buffer is too small */
1015 if (count
> req_count
) {
1016 STRUCT_FSET(get_list
, ml_return_value
, CRYPTO_BUFFER_TOO_SMALL
);
1019 /* copyout the first stuff */
1020 if (copyout(STRUCT_BUF(get_list
), arg
, STRUCT_SIZE(get_list
)) != 0) {
1025 * If only requesting number of entries or buffer too small or an
1026 * error occurred, stop here
1028 if (req_count
== 0 || count
> req_count
|| error
!= 0) {
1032 copyout_size
= count
* sizeof (crypto_mech_name_t
);
1034 /* copyout entries */
1035 offset
= (ulong_t
)STRUCT_FADDR(get_list
, ml_list
);
1036 offset
-= (ulong_t
)STRUCT_BUF(get_list
);
1037 if (copyout(entries
, arg
+ offset
, copyout_size
) != 0) {
1042 crypto_free_mech_list(entries
, count
);
1047 * Copyout kernel array of mech_infos to user space.
1051 copyout_mechinfos(int mode
, caddr_t out
, uint_t count
,
1052 crypto_mechanism_info_t
*k_minfos
, caddr_t u_minfos
)
1054 STRUCT_DECL(crypto_mechanism_info
, mi
);
1062 STRUCT_INIT(mi
, mode
);
1064 len
= count
* STRUCT_SIZE(mi
);
1066 ASSERT(u_minfos
!= NULL
);
1068 for (i
= 0; i
< count
; i
++) {
1069 STRUCT_FSET(mi
, mi_min_key_size
, k_minfos
[i
].mi_min_key_size
);
1070 STRUCT_FSET(mi
, mi_max_key_size
, k_minfos
[i
].mi_max_key_size
);
1071 STRUCT_FSET(mi
, mi_keysize_unit
, k_minfos
[i
].mi_keysize_unit
);
1072 STRUCT_FSET(mi
, mi_usage
, k_minfos
[i
].mi_usage
);
1073 bcopy(STRUCT_BUF(mi
), p
, STRUCT_SIZE(mi
));
1074 p
+= STRUCT_SIZE(mi
);
1077 if (copyout(u_minfos
, out
, len
) != 0)
1084 * This ioctl returns information for the specified mechanism.
1088 get_all_mechanism_info(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
1090 STRUCT_DECL(crypto_get_all_mechanism_info
, get_all_mech
);
1092 STRUCT_DECL(crypto_mechanism_info
, mi
);
1094 /* LINTED E_FUNC_SET_NOT_USED */
1095 STRUCT_DECL(crypto_mechanism_info
, mi
);
1097 crypto_mech_name_t mech_name
;
1098 crypto_mech_type_t mech_type
;
1099 crypto_mechanism_info_t
*mech_infos
= NULL
;
1100 uint_t num_mech_infos
= 0;
1107 STRUCT_INIT(get_all_mech
, mode
);
1108 STRUCT_INIT(mi
, mode
);
1110 if (copyin(arg
, STRUCT_BUF(get_all_mech
),
1111 STRUCT_SIZE(get_all_mech
)) != 0) {
1115 (void) strncpy(mech_name
, STRUCT_FGET(get_all_mech
, mi_mechanism_name
),
1116 CRYPTO_MAX_MECH_NAME
);
1117 mech_type
= crypto_mech2id(mech_name
);
1119 if (mech_type
== CRYPTO_MECH_INVALID
) {
1120 rv
= CRYPTO_ARGUMENTS_BAD
;
1124 rv
= crypto_get_all_mech_info(mech_type
, &mech_infos
, &num_mech_infos
,
1126 if (rv
!= CRYPTO_SUCCESS
) {
1129 /* rv is CRYPTO_SUCCESS at this point */
1131 /* Number of entries caller thinks we have */
1132 req_count
= STRUCT_FGET(get_all_mech
, mi_count
);
1134 STRUCT_FSET(get_all_mech
, mi_count
, num_mech_infos
);
1136 /* check if buffer is too small */
1137 if (num_mech_infos
> req_count
) {
1138 rv
= CRYPTO_BUFFER_TOO_SMALL
;
1142 STRUCT_FSET(get_all_mech
, mi_return_value
, rv
);
1144 /* copy the first part */
1145 if (copyout(STRUCT_BUF(get_all_mech
), arg
,
1146 STRUCT_SIZE(get_all_mech
)) != 0) {
1151 * If only requesting number of entries, or there are no entries,
1152 * or rv is not CRYPTO_SUCCESS due to buffer too small or some other
1153 * crypto error, or an error occurred with copyout, stop here
1155 if (req_count
== 0 || num_mech_infos
== 0 || rv
!= CRYPTO_SUCCESS
||
1160 /* copyout mech_infos */
1161 offset
= (ulong_t
)STRUCT_FADDR(get_all_mech
, mi_list
);
1162 offset
-= (ulong_t
)STRUCT_BUF(get_all_mech
);
1164 u_minfos
= kmem_alloc(num_mech_infos
* STRUCT_SIZE(mi
), KM_SLEEP
);
1165 error
= copyout_mechinfos(mode
, arg
+ offset
, num_mech_infos
,
1166 mech_infos
, u_minfos
);
1167 kmem_free(u_minfos
, num_mech_infos
* STRUCT_SIZE(mi
));
1169 if (mech_infos
!= NULL
)
1170 crypto_free_all_mech_info(mech_infos
, num_mech_infos
);
1176 * 1. This routine stores provider descriptor pointers in an array
1177 * and increments each descriptor's reference count. The array
1178 * is stored in per-minor number storage.
1179 * 2. Destroys the old array and creates a new one every time
1180 * this routine is called.
1183 crypto_get_provider_list(crypto_minor_t
*cm
, uint_t
*count
,
1184 crypto_provider_entry_t
**array
, boolean_t return_slot_list
)
1186 kcf_provider_desc_t
**provider_array
;
1187 crypto_provider_entry_t
*p
= NULL
;
1188 uint_t provider_count
;
1193 * Take snapshot of provider table returning only HW entries
1194 * that are in a usable state. Also returns logical provider entries.
1196 rval
= kcf_get_slot_list(&provider_count
, &provider_array
, B_FALSE
);
1197 if (rval
!= CRYPTO_SUCCESS
)
1200 /* allocate memory before taking cm->cm_lock */
1201 if (return_slot_list
) {
1202 if (provider_count
!= 0) {
1203 p
= kmem_alloc(provider_count
*
1204 sizeof (crypto_provider_entry_t
), KM_SLEEP
);
1205 for (i
= 0; i
< provider_count
; i
++) {
1206 p
[i
].pe_provider_id
= i
;
1207 p
[i
].pe_mechanism_count
=
1208 provider_array
[i
]->pd_mech_list_count
;
1212 *count
= provider_count
;
1216 * Free existing array of providers and replace with new list.
1218 mutex_enter(&cm
->cm_lock
);
1219 if (cm
->cm_provider_array
!= NULL
) {
1220 ASSERT(cm
->cm_provider_count
> 0);
1221 kcf_free_provider_tab(cm
->cm_provider_count
,
1222 cm
->cm_provider_array
);
1225 cm
->cm_provider_array
= provider_array
;
1226 cm
->cm_provider_count
= provider_count
;
1227 mutex_exit(&cm
->cm_lock
);
1229 return (CRYPTO_SUCCESS
);
1233 * This ioctl returns an array of crypto_provider_entry_t entries.
1234 * This is how consumers learn which hardware providers are available.
1238 get_provider_list(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
1240 STRUCT_DECL(crypto_get_provider_list
, get_list
);
1241 crypto_provider_entry_t
*entries
;
1243 size_t copyout_size
;
1249 STRUCT_INIT(get_list
, mode
);
1251 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
1252 cmn_err(CE_WARN
, "get_provider_list: failed holding minor");
1256 if (copyin(arg
, STRUCT_BUF(get_list
), STRUCT_SIZE(get_list
)) != 0) {
1257 crypto_release_minor(cm
);
1261 rv
= crypto_get_provider_list(cm
, &count
, &entries
, RETURN_LIST
);
1262 if (rv
!= CRYPTO_SUCCESS
) {
1263 crypto_release_minor(cm
);
1264 STRUCT_FSET(get_list
, pl_return_value
, rv
);
1265 if (copyout(STRUCT_BUF(get_list
), arg
,
1266 STRUCT_SIZE(get_list
)) != 0) {
1271 crypto_release_minor(cm
);
1273 /* Number of slots caller thinks we have */
1274 req_count
= STRUCT_FGET(get_list
, pl_count
);
1276 /* Check if only requesting number of slots */
1277 if (req_count
== 0) {
1279 STRUCT_FSET(get_list
, pl_count
, count
);
1280 STRUCT_FSET(get_list
, pl_return_value
, CRYPTO_SUCCESS
);
1282 crypto_free_provider_list(entries
, count
);
1283 if (copyout(STRUCT_BUF(get_list
), arg
,
1284 STRUCT_SIZE(get_list
)) != 0) {
1290 /* check if buffer is too small */
1291 req_count
= STRUCT_FGET(get_list
, pl_count
);
1292 if (count
> req_count
) {
1293 STRUCT_FSET(get_list
, pl_count
, count
);
1294 STRUCT_FSET(get_list
, pl_return_value
, CRYPTO_BUFFER_TOO_SMALL
);
1295 crypto_free_provider_list(entries
, count
);
1296 if (copyout(STRUCT_BUF(get_list
), arg
,
1297 STRUCT_SIZE(get_list
)) != 0) {
1303 STRUCT_FSET(get_list
, pl_count
, count
);
1304 STRUCT_FSET(get_list
, pl_return_value
, CRYPTO_SUCCESS
);
1306 copyout_size
= count
* sizeof (crypto_provider_entry_t
);
1308 /* copyout the first stuff */
1309 if (copyout(STRUCT_BUF(get_list
), arg
, STRUCT_SIZE(get_list
)) != 0) {
1310 crypto_free_provider_list(entries
, count
);
1315 crypto_free_provider_list(entries
, count
);
1319 /* copyout entries */
1320 offset
= (ulong_t
)STRUCT_FADDR(get_list
, pl_list
);
1321 offset
-= (ulong_t
)STRUCT_BUF(get_list
);
1322 if (copyout(entries
, arg
+ offset
, copyout_size
) != 0) {
1323 crypto_free_provider_list(entries
, count
);
1327 crypto_free_provider_list(entries
, count
);
1332 ext_to_provider_data(int mode
, kcf_provider_desc_t
*provider
,
1333 crypto_provider_ext_info_t
*ei
, void *out
)
1335 STRUCT_DECL(crypto_provider_data
, pd
);
1336 STRUCT_DECL(crypto_version
, version
);
1338 STRUCT_INIT(pd
, mode
);
1339 STRUCT_INIT(version
, mode
);
1341 bcopy(provider
->pd_description
, STRUCT_FGET(pd
, pd_prov_desc
),
1342 CRYPTO_PROVIDER_DESCR_MAX_LEN
);
1344 bcopy(ei
->ei_label
, STRUCT_FGET(pd
, pd_label
), CRYPTO_EXT_SIZE_LABEL
);
1345 bcopy(ei
->ei_manufacturerID
, STRUCT_FGET(pd
, pd_manufacturerID
),
1346 CRYPTO_EXT_SIZE_MANUF
);
1347 bcopy(ei
->ei_model
, STRUCT_FGET(pd
, pd_model
), CRYPTO_EXT_SIZE_MODEL
);
1348 bcopy(ei
->ei_serial_number
, STRUCT_FGET(pd
, pd_serial_number
),
1349 CRYPTO_EXT_SIZE_SERIAL
);
1351 * We do not support ioctls for dual-function crypto operations yet.
1352 * So, we clear this flag as it might have been set by a provider.
1354 ei
->ei_flags
&= ~CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS
;
1356 STRUCT_FSET(pd
, pd_flags
, ei
->ei_flags
);
1357 STRUCT_FSET(pd
, pd_max_session_count
, ei
->ei_max_session_count
);
1358 STRUCT_FSET(pd
, pd_session_count
, (int)CRYPTO_UNAVAILABLE_INFO
);
1359 STRUCT_FSET(pd
, pd_max_rw_session_count
, ei
->ei_max_session_count
);
1360 STRUCT_FSET(pd
, pd_rw_session_count
, (int)CRYPTO_UNAVAILABLE_INFO
);
1361 STRUCT_FSET(pd
, pd_max_pin_len
, ei
->ei_max_pin_len
);
1362 STRUCT_FSET(pd
, pd_min_pin_len
, ei
->ei_min_pin_len
);
1363 STRUCT_FSET(pd
, pd_total_public_memory
, ei
->ei_total_public_memory
);
1364 STRUCT_FSET(pd
, pd_free_public_memory
, ei
->ei_free_public_memory
);
1365 STRUCT_FSET(pd
, pd_total_private_memory
, ei
->ei_total_private_memory
);
1366 STRUCT_FSET(pd
, pd_free_private_memory
, ei
->ei_free_private_memory
);
1367 STRUCT_FSET(version
, cv_major
, ei
->ei_hardware_version
.cv_major
);
1368 STRUCT_FSET(version
, cv_minor
, ei
->ei_hardware_version
.cv_minor
);
1369 bcopy(STRUCT_BUF(version
), STRUCT_FADDR(pd
, pd_hardware_version
),
1370 STRUCT_SIZE(version
));
1371 STRUCT_FSET(version
, cv_major
, ei
->ei_firmware_version
.cv_major
);
1372 STRUCT_FSET(version
, cv_minor
, ei
->ei_firmware_version
.cv_minor
);
1373 bcopy(STRUCT_BUF(version
), STRUCT_FADDR(pd
, pd_firmware_version
),
1374 STRUCT_SIZE(version
));
1375 bcopy(ei
->ei_time
, STRUCT_FGET(pd
, pd_time
), CRYPTO_EXT_SIZE_TIME
);
1376 bcopy(STRUCT_BUF(pd
), out
, STRUCT_SIZE(pd
));
1380 * Utility routine to construct a crypto_provider_ext_info structure. Some
1381 * of the fields are constructed from information in the provider structure.
1382 * The rest of the fields have default values. We need to do this for
1383 * providers which do not support crypto_provider_management_ops routines.
1386 fabricate_ext_info(kcf_provider_desc_t
*provider
,
1387 crypto_provider_ext_info_t
*ei
)
1390 (void) memset(ei
->ei_label
, ' ', CRYPTO_EXT_SIZE_LABEL
);
1392 (void) memset(ei
->ei_manufacturerID
, ' ', CRYPTO_EXT_SIZE_MANUF
);
1393 (void) strncpy((char *)ei
->ei_manufacturerID
, "Unknown", 7);
1395 (void) memset(ei
->ei_model
, ' ', CRYPTO_EXT_SIZE_MODEL
);
1396 (void) strncpy((char *)ei
->ei_model
, "Unknown", 7);
1398 (void) memset(ei
->ei_serial_number
, ' ', CRYPTO_EXT_SIZE_SERIAL
);
1399 (void) strncpy((char *)ei
->ei_serial_number
, "Unknown", 7);
1401 if (KCF_PROV_RANDOM_OPS(provider
) != NULL
)
1402 ei
->ei_flags
|= CRYPTO_EXTF_RNG
;
1403 if (KCF_PROV_DUAL_OPS(provider
) != NULL
)
1404 ei
->ei_flags
|= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS
;
1406 ei
->ei_max_session_count
= CRYPTO_UNAVAILABLE_INFO
;
1407 ei
->ei_max_pin_len
= 0;
1408 ei
->ei_min_pin_len
= 0;
1409 ei
->ei_total_public_memory
= CRYPTO_UNAVAILABLE_INFO
;
1410 ei
->ei_free_public_memory
= CRYPTO_UNAVAILABLE_INFO
;
1411 ei
->ei_total_private_memory
= CRYPTO_UNAVAILABLE_INFO
;
1412 ei
->ei_free_private_memory
= CRYPTO_UNAVAILABLE_INFO
;
1413 ei
->ei_hardware_version
.cv_major
= 1;
1414 ei
->ei_hardware_version
.cv_minor
= 0;
1415 ei
->ei_firmware_version
.cv_major
= 1;
1416 ei
->ei_firmware_version
.cv_minor
= 0;
1421 get_provider_info(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
1423 STRUCT_DECL(crypto_get_provider_info
, get_info
);
1425 crypto_provider_id_t provider_id
;
1426 kcf_provider_desc_t
*provider
, *real_provider
;
1427 crypto_provider_ext_info_t
*ext_info
= NULL
;
1431 kcf_req_params_t params
;
1433 STRUCT_INIT(get_info
, mode
);
1435 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
1436 cmn_err(CE_WARN
, "get_provider_info: failed holding minor");
1440 if (copyin(arg
, STRUCT_BUF(get_info
), STRUCT_SIZE(get_info
)) != 0) {
1441 crypto_release_minor(cm
);
1445 need
= sizeof (crypto_provider_ext_info_t
);
1446 if ((rv
= crypto_buffer_check(need
)) != CRYPTO_SUCCESS
) {
1451 /* initialize provider_array */
1452 if (cm
->cm_provider_array
== NULL
) {
1453 rv
= crypto_get_provider_list(cm
, NULL
, NULL
, DONT_RETURN_LIST
);
1454 if (rv
!= CRYPTO_SUCCESS
) {
1459 ext_info
= kmem_zalloc(need
, KM_SLEEP
);
1461 provider_id
= STRUCT_FGET(get_info
, gi_provider_id
);
1462 mutex_enter(&cm
->cm_lock
);
1463 /* index must be less than count of providers */
1464 if (provider_id
>= cm
->cm_provider_count
) {
1465 mutex_exit(&cm
->cm_lock
);
1466 rv
= CRYPTO_ARGUMENTS_BAD
;
1470 ASSERT(cm
->cm_provider_array
!= NULL
);
1471 provider
= cm
->cm_provider_array
[provider_id
];
1472 KCF_PROV_REFHOLD(provider
);
1473 mutex_exit(&cm
->cm_lock
);
1475 (void) kcf_get_hardware_provider_nomech(
1476 CRYPTO_OPS_OFFSET(provider_ops
), CRYPTO_PROVIDER_OFFSET(ext_info
),
1477 provider
, &real_provider
);
1479 if (real_provider
!= NULL
) {
1480 ASSERT(real_provider
== provider
||
1481 provider
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
);
1482 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms
, KCF_OP_MGMT_EXTINFO
,
1483 0, NULL
, 0, NULL
, 0, NULL
, ext_info
, provider
);
1484 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
,
1486 ASSERT(rv
!= CRYPTO_NOT_SUPPORTED
);
1487 KCF_PROV_REFRELE(real_provider
);
1489 /* do the best we can */
1490 fabricate_ext_info(provider
, ext_info
);
1491 rv
= CRYPTO_SUCCESS
;
1493 KCF_PROV_REFRELE(provider
);
1495 if (rv
== CRYPTO_SUCCESS
) {
1496 ext_to_provider_data(mode
, provider
, ext_info
,
1497 STRUCT_FADDR(get_info
, gi_provider_data
));
1501 CRYPTO_DECREMENT_RCTL(need
);
1502 crypto_release_minor(cm
);
1504 if (ext_info
!= NULL
)
1505 kmem_free(ext_info
, sizeof (crypto_provider_ext_info_t
));
1510 STRUCT_FSET(get_info
, gi_return_value
, rv
);
1511 if (copyout(STRUCT_BUF(get_info
), arg
, STRUCT_SIZE(get_info
)) != 0) {
1518 * This ioctl returns an array of crypto_mech_name_t entries.
1519 * This is how consumers learn which mechanisms are permitted
1524 get_provider_mechanisms(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
1526 STRUCT_DECL(crypto_get_provider_mechanisms
, get_mechanisms
);
1527 crypto_mech_name_t
*entries
;
1529 size_t copyout_size
;
1535 STRUCT_INIT(get_mechanisms
, mode
);
1537 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
1539 "get_provider_mechanisms: failed holding minor");
1543 if (copyin(arg
, STRUCT_BUF(get_mechanisms
),
1544 STRUCT_SIZE(get_mechanisms
)) != 0) {
1545 crypto_release_minor(cm
);
1549 /* get array of mechanisms from the core module */
1550 if ((err
= crypto_get_provider_mechanisms(cm
,
1551 STRUCT_FGET(get_mechanisms
, pm_provider_id
),
1552 &count
, &entries
)) != 0) {
1553 crypto_release_minor(cm
);
1554 STRUCT_FSET(get_mechanisms
, pm_return_value
, err
);
1555 if (copyout(STRUCT_BUF(get_mechanisms
), arg
,
1556 STRUCT_SIZE(get_mechanisms
)) != 0) {
1561 crypto_release_minor(cm
);
1562 /* Number of mechs caller thinks we have */
1563 req_count
= STRUCT_FGET(get_mechanisms
, pm_count
);
1565 /* Check if caller is just requesting a count of mechanisms */
1566 if (req_count
== 0) {
1567 STRUCT_FSET(get_mechanisms
, pm_count
, count
);
1568 STRUCT_FSET(get_mechanisms
, pm_return_value
, CRYPTO_SUCCESS
);
1570 crypto_free_mech_list(entries
, count
);
1571 if (copyout(STRUCT_BUF(get_mechanisms
), arg
,
1572 STRUCT_SIZE(get_mechanisms
)) != 0) {
1578 /* check if buffer is too small */
1579 if (count
> req_count
) {
1580 STRUCT_FSET(get_mechanisms
, pm_count
, count
);
1581 STRUCT_FSET(get_mechanisms
, pm_return_value
,
1582 CRYPTO_BUFFER_TOO_SMALL
);
1583 crypto_free_mech_list(entries
, count
);
1584 if (copyout(STRUCT_BUF(get_mechanisms
), arg
,
1585 STRUCT_SIZE(get_mechanisms
)) != 0) {
1591 STRUCT_FSET(get_mechanisms
, pm_count
, count
);
1592 STRUCT_FSET(get_mechanisms
, pm_return_value
, CRYPTO_SUCCESS
);
1594 copyout_size
= count
* sizeof (crypto_mech_name_t
);
1596 /* copyout the first stuff */
1597 if (copyout(STRUCT_BUF(get_mechanisms
), arg
,
1598 STRUCT_SIZE(get_mechanisms
)) != 0) {
1599 crypto_free_mech_list(entries
, count
);
1607 /* copyout entries */
1608 offset
= (ulong_t
)STRUCT_FADDR(get_mechanisms
, pm_list
);
1609 offset
-= (ulong_t
)STRUCT_BUF(get_mechanisms
);
1610 if (copyout(entries
, arg
+ offset
, copyout_size
) != 0) {
1611 crypto_free_mech_list(entries
, count
);
1615 crypto_free_mech_list(entries
, count
);
1620 * This ioctl returns information about a provider's mechanism.
1624 get_provider_mechanism_info(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
1626 crypto_get_provider_mechanism_info_t mechanism_info
;
1628 kcf_provider_desc_t
*pd
;
1629 crypto_mech_info_t
*mi
= NULL
;
1630 int rv
= CRYPTO_SUCCESS
;
1633 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
1635 "get_provider_mechanism_info: failed holding minor");
1639 if (copyin(arg
, &mechanism_info
, sizeof (mechanism_info
)) != 0) {
1640 crypto_release_minor(cm
);
1644 /* initialize provider table */
1645 if (cm
->cm_provider_array
== NULL
) {
1646 rv
= crypto_get_provider_list(cm
, NULL
, NULL
, DONT_RETURN_LIST
);
1647 if (rv
!= CRYPTO_SUCCESS
) {
1648 mutex_enter(&cm
->cm_lock
);
1654 * Provider ID must be less than the count of providers
1655 * obtained by calling get_provider_list().
1657 mutex_enter(&cm
->cm_lock
);
1658 if (mechanism_info
.mi_provider_id
>= cm
->cm_provider_count
) {
1659 rv
= CRYPTO_ARGUMENTS_BAD
;
1663 pd
= cm
->cm_provider_array
[mechanism_info
.mi_provider_id
];
1665 /* First check if the provider supports the mechanism. */
1666 for (i
= 0; i
< pd
->pd_mech_list_count
; i
++) {
1667 if (strncmp(pd
->pd_mechanisms
[i
].cm_mech_name
,
1668 mechanism_info
.mi_mechanism_name
,
1669 CRYPTO_MAX_MECH_NAME
) == 0) {
1670 mi
= &pd
->pd_mechanisms
[i
];
1676 rv
= CRYPTO_ARGUMENTS_BAD
;
1680 /* Now check if the mechanism is enabled for the provider. */
1681 if (is_mech_disabled(pd
, mechanism_info
.mi_mechanism_name
)) {
1682 rv
= CRYPTO_MECHANISM_INVALID
;
1686 mechanism_info
.mi_min_key_size
= mi
->cm_min_key_length
;
1687 mechanism_info
.mi_max_key_size
= mi
->cm_max_key_length
;
1688 mechanism_info
.mi_flags
= mi
->cm_func_group_mask
;
1691 mutex_exit(&cm
->cm_lock
);
1692 crypto_release_minor(cm
);
1693 mechanism_info
.mi_return_value
= rv
;
1694 if (copyout(&mechanism_info
, arg
, sizeof (mechanism_info
)) != 0) {
1702 * Every open of /dev/crypto multiplexes all PKCS#11 sessions across
1703 * a single session to each provider. Calls to open and close session
1704 * are not made to providers that do not support sessions. For these
1705 * providers, a session number of 0 is passed during subsequent operations,
1706 * and it is ignored by the provider.
1709 crypto_get_provider_session(crypto_minor_t
*cm
,
1710 crypto_provider_id_t provider_index
, crypto_provider_session_t
**output_ps
)
1712 kcf_provider_desc_t
*pd
, *real_provider
;
1713 kcf_req_params_t params
;
1714 crypto_provider_session_t
*ps
;
1715 crypto_session_id_t provider_session_id
= 0;
1718 ASSERT(MUTEX_HELD(&cm
->cm_lock
));
1720 /* pd may be a logical provider */
1721 pd
= cm
->cm_provider_array
[provider_index
];
1725 * Check if there is already a session to the provider.
1726 * Sessions may be to a logical provider or a real provider.
1728 for (ps
= cm
->cm_provider_session
; ps
!= NULL
; ps
= ps
->ps_next
) {
1729 if (ps
->ps_provider
== pd
)
1733 /* found existing session */
1737 return (CRYPTO_SUCCESS
);
1739 mutex_exit(&cm
->cm_lock
);
1741 /* find a hardware provider that supports session ops */
1742 (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops
),
1743 CRYPTO_SESSION_OFFSET(session_open
), pd
, &real_provider
);
1745 if (real_provider
!= NULL
) {
1746 ASSERT(real_provider
== pd
||
1747 pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
);
1748 /* open session to provider */
1749 KCF_WRAP_SESSION_OPS_PARAMS(¶ms
, KCF_OP_SESSION_OPEN
,
1750 &provider_session_id
, 0, CRYPTO_USER
, NULL
, 0, pd
);
1751 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
,
1753 if (rv
!= CRYPTO_SUCCESS
) {
1754 mutex_enter(&cm
->cm_lock
);
1755 KCF_PROV_REFRELE(real_provider
);
1761 * Check if someone opened a session to the provider
1762 * while we dropped the lock.
1764 mutex_enter(&cm
->cm_lock
);
1765 for (ps
= cm
->cm_provider_session
; ps
!= NULL
; ps
= ps
->ps_next
) {
1766 if (ps
->ps_provider
== pd
) {
1767 mutex_exit(&cm
->cm_lock
);
1768 if (real_provider
!= NULL
) {
1769 KCF_WRAP_SESSION_OPS_PARAMS(¶ms
,
1770 KCF_OP_SESSION_CLOSE
, NULL
,
1771 provider_session_id
, CRYPTO_USER
, NULL
, 0,
1773 (void) kcf_submit_request(real_provider
, NULL
,
1774 NULL
, ¶ms
, B_FALSE
);
1775 KCF_PROV_REFRELE(real_provider
);
1777 mutex_enter(&cm
->cm_lock
);
1783 return (crypto_create_provider_session(cm
, pd
, provider_session_id
,
1784 output_ps
, real_provider
));
1788 crypto_create_provider_session(crypto_minor_t
*cm
, kcf_provider_desc_t
*pd
,
1789 crypto_session_id_t sid
, crypto_provider_session_t
**out_ps
,
1790 kcf_provider_desc_t
*real
)
1792 crypto_provider_session_t
*ps
;
1794 /* allocate crypto_provider_session structure */
1795 ps
= kmem_zalloc(sizeof (crypto_provider_session_t
), KM_SLEEP
);
1797 /* increment refcnt and attach to crypto_minor structure */
1798 ps
->ps_session
= sid
;
1800 KCF_PROV_REFHOLD(pd
);
1801 ps
->ps_provider
= pd
;
1803 ps
->ps_real_provider
= real
;
1805 ps
->ps_next
= cm
->cm_provider_session
;
1806 cm
->cm_provider_session
= ps
;
1809 return (CRYPTO_SUCCESS
);
1813 * Release a provider session.
1814 * If the reference count goes to zero, then close the session
1818 crypto_release_provider_session(crypto_minor_t
*cm
,
1819 crypto_provider_session_t
*provider_session
)
1821 kcf_req_params_t params
;
1822 crypto_provider_session_t
*ps
= NULL
, **prev
;
1824 ASSERT(MUTEX_HELD(&cm
->cm_lock
));
1826 /* verify that provider_session is valid */
1827 for (ps
= cm
->cm_provider_session
, prev
= &cm
->cm_provider_session
;
1828 ps
!= NULL
; prev
= &ps
->ps_next
, ps
= ps
->ps_next
) {
1829 if (ps
== provider_session
) {
1839 if (ps
->ps_refcnt
> 0)
1842 if (ps
->ps_real_provider
!= NULL
) {
1843 /* close session with provider */
1844 KCF_WRAP_SESSION_OPS_PARAMS(¶ms
, KCF_OP_SESSION_CLOSE
, NULL
,
1845 ps
->ps_session
, CRYPTO_USER
, NULL
, 0, ps
->ps_provider
);
1846 (void) kcf_submit_request(ps
->ps_real_provider
,
1847 NULL
, NULL
, ¶ms
, B_FALSE
);
1848 KCF_PROV_REFRELE(ps
->ps_real_provider
);
1850 KCF_PROV_REFRELE(ps
->ps_provider
);
1851 *prev
= ps
->ps_next
;
1852 kmem_free(ps
, sizeof (*ps
));
1856 grow_session_table(crypto_minor_t
*cm
)
1858 crypto_session_data_t
**session_table
;
1859 crypto_session_data_t
**new;
1860 uint_t session_table_count
;
1862 size_t current_allocation
;
1863 size_t new_allocation
;
1866 ASSERT(MUTEX_HELD(&cm
->cm_lock
));
1868 session_table_count
= cm
->cm_session_table_count
;
1869 session_table
= cm
->cm_session_table
;
1870 need
= session_table_count
+ CRYPTO_SESSION_CHUNK
;
1872 current_allocation
= session_table_count
* sizeof (void *);
1873 new_allocation
= need
* sizeof (void *);
1876 * Memory needed to grow the session table is checked
1877 * against the project.max-crypto-memory resource control.
1879 if ((rv
= crypto_buffer_check(new_allocation
- current_allocation
)) !=
1884 /* drop lock while we allocate memory */
1885 mutex_exit(&cm
->cm_lock
);
1886 new = kmem_zalloc(new_allocation
, KM_SLEEP
);
1887 mutex_enter(&cm
->cm_lock
);
1889 /* check if another thread increased the table size */
1890 if (session_table_count
!= cm
->cm_session_table_count
) {
1891 kmem_free(new, new_allocation
);
1892 return (CRYPTO_SUCCESS
);
1895 bcopy(session_table
, new, current_allocation
);
1896 kmem_free(session_table
, current_allocation
);
1897 cm
->cm_session_table
= new;
1898 cm
->cm_session_table_count
+= CRYPTO_SESSION_CHUNK
;
1900 return (CRYPTO_SUCCESS
);
1904 * Find unused entry in session table and return its index.
1905 * Initialize session table entry.
1909 crypto_open_session(dev_t dev
, uint_t flags
, crypto_session_id_t
*session_index
,
1910 crypto_provider_id_t provider_id
)
1914 crypto_provider_session_t
*ps
;
1915 kcf_provider_desc_t
*provider
;
1917 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
1918 cmn_err(CE_WARN
, "crypto_open_session: failed holding minor");
1919 return (CRYPTO_FAILED
);
1922 /* initialize provider_array */
1923 if (cm
->cm_provider_array
== NULL
) {
1924 rv
= crypto_get_provider_list(cm
, NULL
, NULL
, DONT_RETURN_LIST
);
1926 crypto_release_minor(cm
);
1931 mutex_enter(&cm
->cm_lock
);
1932 /* index must be less than count of providers */
1933 if (provider_id
>= cm
->cm_provider_count
) {
1934 mutex_exit(&cm
->cm_lock
);
1935 crypto_release_minor(cm
);
1936 return (CRYPTO_INVALID_PROVIDER_ID
);
1938 ASSERT(cm
->cm_provider_array
!= NULL
);
1940 rv
= crypto_get_provider_session(cm
, provider_id
, &ps
);
1941 if (rv
!= CRYPTO_SUCCESS
) {
1942 mutex_exit(&cm
->cm_lock
);
1943 crypto_release_minor(cm
);
1946 provider
= cm
->cm_provider_array
[provider_id
];
1948 rv
= crypto_create_session_ptr(cm
, provider
, ps
, session_index
);
1949 mutex_exit(&cm
->cm_lock
);
1950 crypto_release_minor(cm
);
1956 crypto_create_session_ptr(crypto_minor_t
*cm
, kcf_provider_desc_t
*provider
,
1957 crypto_provider_session_t
*ps
, crypto_session_id_t
*session_index
)
1959 crypto_session_data_t
**session_table
;
1960 crypto_session_data_t
*sp
;
1961 uint_t session_table_count
;
1965 ASSERT(MUTEX_HELD(&cm
->cm_lock
));
1968 session_table_count
= cm
->cm_session_table_count
;
1969 session_table
= cm
->cm_session_table
;
1971 /* session handles start with 1 */
1972 for (i
= 1; i
< session_table_count
; i
++) {
1973 if (session_table
[i
] == NULL
)
1977 if (i
== session_table_count
|| session_table_count
== 0) {
1978 if ((rv
= grow_session_table(cm
)) != CRYPTO_SUCCESS
) {
1979 crypto_release_provider_session(cm
, ps
);
1985 sp
= kmem_cache_alloc(crypto_session_cache
, KM_SLEEP
);
1987 sp
->sd_find_init_cookie
= NULL
;
1988 sp
->sd_digest_ctx
= NULL
;
1989 sp
->sd_encr_ctx
= NULL
;
1990 sp
->sd_decr_ctx
= NULL
;
1991 sp
->sd_sign_ctx
= NULL
;
1992 sp
->sd_verify_ctx
= NULL
;
1993 sp
->sd_mac_ctx
= NULL
;
1994 sp
->sd_sign_recover_ctx
= NULL
;
1995 sp
->sd_verify_recover_ctx
= NULL
;
1996 mutex_init(&sp
->sd_lock
, NULL
, MUTEX_DRIVER
, NULL
);
1997 cv_init(&sp
->sd_cv
, NULL
, CV_DRIVER
, NULL
);
1998 KCF_PROV_REFHOLD(provider
);
1999 sp
->sd_provider
= provider
;
2000 sp
->sd_provider_session
= ps
;
2002 /* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */
2003 if ((rv
= crypto_buffer_check(crypto_pre_approved_limit
)) !=
2005 sp
->sd_pre_approved_amount
= 0;
2007 sp
->sd_pre_approved_amount
= (int)crypto_pre_approved_limit
;
2010 cm
->cm_session_table
[i
] = sp
;
2011 if (session_index
!= NULL
)
2014 return (CRYPTO_SUCCESS
);
2021 crypto_close_session(dev_t dev
, crypto_session_id_t session_index
)
2023 crypto_session_data_t
**session_table
;
2024 crypto_session_data_t
*sp
;
2027 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
2028 cmn_err(CE_WARN
, "crypto_close_session: failed holding minor");
2029 return (CRYPTO_FAILED
);
2032 mutex_enter(&cm
->cm_lock
);
2033 session_table
= cm
->cm_session_table
;
2035 if ((session_index
) == 0 ||
2036 (session_index
>= cm
->cm_session_table_count
)) {
2037 mutex_exit(&cm
->cm_lock
);
2038 crypto_release_minor(cm
);
2039 return (CRYPTO_SESSION_HANDLE_INVALID
);
2042 sp
= session_table
[session_index
];
2044 mutex_exit(&cm
->cm_lock
);
2045 crypto_release_minor(cm
);
2046 return (CRYPTO_SESSION_HANDLE_INVALID
);
2049 * If session is in use, free it when the thread
2050 * finishes with the session.
2052 mutex_enter(&sp
->sd_lock
);
2053 if (sp
->sd_flags
& CRYPTO_SESSION_IS_BUSY
) {
2054 sp
->sd_flags
|= CRYPTO_SESSION_IS_CLOSED
;
2055 mutex_exit(&sp
->sd_lock
);
2057 ASSERT(sp
->sd_pre_approved_amount
== 0 ||
2058 sp
->sd_pre_approved_amount
== crypto_pre_approved_limit
);
2059 CRYPTO_DECREMENT_RCTL(sp
->sd_pre_approved_amount
);
2061 if (sp
->sd_find_init_cookie
!= NULL
) {
2062 (void) crypto_free_find_ctx(sp
);
2065 crypto_release_provider_session(cm
, sp
->sd_provider_session
);
2066 KCF_PROV_REFRELE(sp
->sd_provider
);
2067 CRYPTO_CANCEL_ALL_CTX(sp
);
2068 mutex_destroy(&sp
->sd_lock
);
2069 cv_destroy(&sp
->sd_cv
);
2070 kmem_cache_free(crypto_session_cache
, sp
);
2071 session_table
[session_index
] = NULL
;
2074 mutex_exit(&cm
->cm_lock
);
2075 crypto_release_minor(cm
);
2077 return (CRYPTO_SUCCESS
);
2081 * This ioctl opens a session and returns the session ID in os_session.
2085 open_session(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2087 crypto_open_session_t open_session
;
2088 crypto_session_id_t session
;
2091 if (copyin(arg
, &open_session
, sizeof (open_session
)) != 0)
2094 rv
= crypto_open_session(dev
, open_session
.os_flags
,
2095 &session
, open_session
.os_provider_id
);
2096 if (rv
!= CRYPTO_SUCCESS
) {
2097 open_session
.os_return_value
= rv
;
2098 if (copyout(&open_session
, arg
, sizeof (open_session
)) != 0) {
2104 open_session
.os_session
= session
;
2105 open_session
.os_return_value
= CRYPTO_SUCCESS
;
2107 if (copyout(&open_session
, arg
, sizeof (open_session
)) != 0) {
2114 * This ioctl closes a session.
2118 close_session(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2120 crypto_close_session_t close_session
;
2123 if (copyin(arg
, &close_session
, sizeof (close_session
)) != 0)
2126 rv
= crypto_close_session(dev
, close_session
.cs_session
);
2127 close_session
.cs_return_value
= rv
;
2128 if (copyout(&close_session
, arg
, sizeof (close_session
)) != 0) {
2135 * Copy data model dependent mechanism structure into a kernel mechanism
2136 * structure. Allocate param storage if necessary.
2139 copyin_mech(int mode
, crypto_session_data_t
*sp
, crypto_mechanism_t
*in_mech
,
2140 crypto_mechanism_t
*out_mech
, size_t *out_rctl_bytes
,
2141 boolean_t
*out_rctl_chk
, int *out_rv
, int *out_error
)
2143 STRUCT_DECL(crypto_mechanism
, mech
);
2146 size_t rctl_bytes
= 0;
2150 STRUCT_INIT(mech
, mode
);
2151 bcopy(in_mech
, STRUCT_BUF(mech
), STRUCT_SIZE(mech
));
2152 param
= STRUCT_FGETP(mech
, cm_param
);
2153 param_len
= STRUCT_FGET(mech
, cm_param_len
);
2154 out_mech
->cm_type
= STRUCT_FGET(mech
, cm_type
);
2155 out_mech
->cm_param
= NULL
;
2156 out_mech
->cm_param_len
= 0;
2157 if (param
!= NULL
&& param_len
!= 0) {
2158 if (param_len
> crypto_max_buffer_len
) {
2159 cmn_err(CE_NOTE
, "copyin_mech: buffer greater than "
2160 "%ld bytes, pid = %d", crypto_max_buffer_len
,
2162 rv
= CRYPTO_ARGUMENTS_BAD
;
2166 rv
= CRYPTO_BUFFER_CHECK(sp
, param_len
, *out_rctl_chk
);
2167 if (rv
!= CRYPTO_SUCCESS
) {
2170 rctl_bytes
= param_len
;
2172 out_mech
->cm_param
= kmem_alloc(param_len
, KM_SLEEP
);
2173 if (copyin((char *)param
, out_mech
->cm_param
, param_len
) != 0) {
2174 kmem_free(out_mech
->cm_param
, param_len
);
2175 out_mech
->cm_param
= NULL
;
2179 out_mech
->cm_param_len
= param_len
;
2182 *out_rctl_bytes
= rctl_bytes
;
2185 return ((rv
| error
) ? B_FALSE
: B_TRUE
);
2189 * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST.
2190 * The crypto_key structure is not freed.
2193 crypto_free_key_attributes(crypto_key_t
*key
)
2195 crypto_object_attribute_t
*attrs
;
2199 ASSERT(key
->ck_format
== CRYPTO_KEY_ATTR_LIST
);
2200 if (key
->ck_count
== 0 || key
->ck_attrs
== NULL
)
2203 /* compute the size of the container */
2204 len
= key
->ck_count
* sizeof (crypto_object_attribute_t
);
2206 /* total up the size of all attributes in the container */
2207 for (i
= 0; i
< key
->ck_count
; i
++) {
2208 attrs
= &key
->ck_attrs
[i
];
2209 if (attrs
->oa_value_len
!= 0 &&
2210 attrs
->oa_value
!= NULL
) {
2211 len
+= roundup(attrs
->oa_value_len
, sizeof (caddr_t
));
2215 bzero(key
->ck_attrs
, len
);
2216 kmem_free(key
->ck_attrs
, len
);
2220 * Frees allocated storage in the key structure, but doesn't free
2221 * the key structure.
2224 free_crypto_key(crypto_key_t
*key
)
2226 switch (key
->ck_format
) {
2227 case CRYPTO_KEY_RAW
: {
2230 if (key
->ck_length
== 0 || key
->ck_data
== NULL
)
2233 len
= CRYPTO_BITS2BYTES(key
->ck_length
);
2234 bzero(key
->ck_data
, len
);
2235 kmem_free(key
->ck_data
, len
);
2239 case CRYPTO_KEY_ATTR_LIST
:
2240 crypto_free_key_attributes(key
);
2249 * Copy in an array of crypto_object_attribute structures from user-space.
2250 * Kernel memory is allocated for the array and the value of each attribute
2251 * in the array. Since unprivileged users can specify the size of attributes,
2252 * the amount of memory needed is charged against the
2253 * project.max-crypto-memory resource control.
2255 * Attribute values are copied in from user-space if copyin_value is set to
2256 * B_TRUE. This routine returns B_TRUE if the copyin was successful.
2259 copyin_attributes(int mode
, crypto_session_data_t
*sp
,
2260 uint_t count
, caddr_t oc_attributes
,
2261 crypto_object_attribute_t
**k_attrs_out
, size_t *k_attrs_size_out
,
2262 caddr_t
*u_attrs_out
, int *out_rv
, int *out_error
, size_t *out_rctl_bytes
,
2263 boolean_t
*out_rctl_chk
, boolean_t copyin_value
)
2265 STRUCT_DECL(crypto_object_attribute
, oa
);
2266 crypto_object_attribute_t
*k_attrs
= NULL
;
2267 caddr_t attrs
= NULL
, ap
, p
, value
;
2268 caddr_t k_attrs_buf
;
2270 size_t k_attrs_buf_len
= 0;
2271 size_t k_attrs_total_len
= 0;
2273 size_t rctl_bytes
= 0;
2280 STRUCT_INIT(oa
, mode
);
2283 rv
= CRYPTO_SUCCESS
;
2287 if (count
> CRYPTO_MAX_ATTRIBUTE_COUNT
) {
2288 rv
= CRYPTO_ARGUMENTS_BAD
;
2292 /* compute size of crypto_object_attribute array */
2293 len
= count
* STRUCT_SIZE(oa
);
2295 /* this allocation is not charged against the user's resource limit */
2296 attrs
= kmem_alloc(len
, KM_SLEEP
);
2297 if (copyin(oc_attributes
, attrs
, len
) != 0) {
2302 /* figure out how much memory to allocate for all of the attributes */
2304 for (i
= 0; i
< count
; i
++) {
2305 bcopy(ap
, STRUCT_BUF(oa
), STRUCT_SIZE(oa
));
2306 tmp_len
= roundup(STRUCT_FGET(oa
, oa_value_len
),
2308 if (tmp_len
> crypto_max_buffer_len
) {
2309 cmn_err(CE_NOTE
, "copyin_attributes: buffer greater "
2310 "than %ld bytes, pid = %d", crypto_max_buffer_len
,
2312 rv
= CRYPTO_ARGUMENTS_BAD
;
2315 if (STRUCT_FGETP(oa
, oa_value
) != NULL
)
2316 k_attrs_buf_len
+= tmp_len
;
2317 ap
+= STRUCT_SIZE(oa
);
2320 k_attrs_len
= count
* sizeof (crypto_object_attribute_t
);
2321 k_attrs_total_len
= k_attrs_buf_len
+ k_attrs_len
;
2323 rv
= CRYPTO_BUFFER_CHECK(sp
, k_attrs_total_len
, *out_rctl_chk
);
2324 if (rv
!= CRYPTO_SUCCESS
) {
2327 rctl_bytes
= k_attrs_total_len
;
2329 /* one big allocation for everything */
2330 k_attrs
= kmem_alloc(k_attrs_total_len
, KM_SLEEP
);
2331 k_attrs_buf
= (char *)k_attrs
+ k_attrs_len
;
2335 for (i
= 0; i
< count
; i
++) {
2336 bcopy(ap
, STRUCT_BUF(oa
), STRUCT_SIZE(oa
));
2337 k_attrs
[i
].oa_type
= STRUCT_FGET(oa
, oa_type
);
2338 value
= STRUCT_FGETP(oa
, oa_value
);
2339 value_len
= STRUCT_FGET(oa
, oa_value_len
);
2340 if (value
!= NULL
&& value_len
!= 0 && copyin_value
) {
2341 if (copyin(value
, p
, value_len
) != 0) {
2342 kmem_free(k_attrs
, k_attrs_total_len
);
2349 if (value
!= NULL
) {
2350 k_attrs
[i
].oa_value
= p
;
2351 p
+= roundup(value_len
, sizeof (caddr_t
));
2353 k_attrs
[i
].oa_value
= NULL
;
2355 k_attrs
[i
].oa_value_len
= value_len
;
2356 ap
+= STRUCT_SIZE(oa
);
2359 if (attrs
!= NULL
) {
2361 * Free the array if there is a failure or the caller
2362 * doesn't want the array to be returned.
2364 if (error
!= 0 || rv
!= CRYPTO_SUCCESS
|| u_attrs_out
== NULL
) {
2365 kmem_free(attrs
, len
);
2370 if (u_attrs_out
!= NULL
)
2371 *u_attrs_out
= attrs
;
2372 if (k_attrs_size_out
!= NULL
)
2373 *k_attrs_size_out
= k_attrs_total_len
;
2374 *k_attrs_out
= k_attrs
;
2375 *out_rctl_bytes
= rctl_bytes
;
2378 return ((rv
| error
) ? B_FALSE
: B_TRUE
);
2382 * Copy data model dependent raw key into a kernel key
2383 * structure. Checks key length or attribute lengths against
2384 * resource controls before allocating memory. Returns B_TRUE
2385 * if both error and rv are set to 0.
2388 copyin_key(int mode
, crypto_session_data_t
*sp
, crypto_key_t
*in_key
,
2389 crypto_key_t
*out_key
, size_t *out_rctl_bytes
,
2390 boolean_t
*out_rctl_chk
, int *out_rv
, int *out_error
)
2392 STRUCT_DECL(crypto_key
, key
);
2393 crypto_object_attribute_t
*k_attrs
= NULL
;
2395 size_t key_bytes
= 0;
2396 size_t rctl_bytes
= 0;
2399 int rv
= CRYPTO_SUCCESS
;
2401 STRUCT_INIT(key
, mode
);
2402 bcopy(in_key
, STRUCT_BUF(key
), STRUCT_SIZE(key
));
2403 out_key
->ck_format
= STRUCT_FGET(key
, ck_format
);
2404 switch (out_key
->ck_format
) {
2405 case CRYPTO_KEY_RAW
:
2406 key_bits
= STRUCT_FGET(key
, ck_length
);
2407 if (key_bits
!= 0) {
2409 (CRYPTO_BYTES2BITS(crypto_max_buffer_len
))) {
2410 cmn_err(CE_NOTE
, "copyin_key: buffer greater "
2411 "than %ld bytes, pid = %d",
2412 crypto_max_buffer_len
, curproc
->p_pid
);
2413 rv
= CRYPTO_ARGUMENTS_BAD
;
2416 key_bytes
= CRYPTO_BITS2BYTES(key_bits
);
2418 rv
= CRYPTO_BUFFER_CHECK(sp
, key_bytes
,
2420 if (rv
!= CRYPTO_SUCCESS
) {
2423 rctl_bytes
= key_bytes
;
2425 out_key
->ck_data
= kmem_alloc(key_bytes
, KM_SLEEP
);
2427 if (copyin((char *)STRUCT_FGETP(key
, ck_data
),
2428 out_key
->ck_data
, key_bytes
) != 0) {
2429 kmem_free(out_key
->ck_data
, key_bytes
);
2430 out_key
->ck_data
= NULL
;
2431 out_key
->ck_length
= 0;
2436 out_key
->ck_length
= (ulong_t
)key_bits
;
2439 case CRYPTO_KEY_ATTR_LIST
:
2440 count
= STRUCT_FGET(key
, ck_count
);
2442 if (copyin_attributes(mode
, sp
, count
,
2443 (caddr_t
)STRUCT_FGETP(key
, ck_attrs
), &k_attrs
, NULL
, NULL
,
2444 &rv
, &error
, &rctl_bytes
, out_rctl_chk
, B_TRUE
)) {
2445 out_key
->ck_count
= count
;
2446 out_key
->ck_attrs
= k_attrs
;
2449 out_key
->ck_count
= 0;
2450 out_key
->ck_attrs
= NULL
;
2454 case CRYPTO_KEY_REFERENCE
:
2455 out_key
->ck_obj_id
= STRUCT_FGET(key
, ck_obj_id
);
2459 rv
= CRYPTO_ARGUMENTS_BAD
;
2463 *out_rctl_bytes
= rctl_bytes
;
2466 return ((rv
| error
) ? B_FALSE
: B_TRUE
);
2470 * This routine does two things:
2471 * 1. Given a crypto_minor structure and a session ID, it returns
2472 * a valid session pointer.
2473 * 2. It checks that the provider, to which the session has been opened,
2474 * has not been removed.
2477 get_session_ptr(crypto_session_id_t i
, crypto_minor_t
*cm
,
2478 crypto_session_data_t
**session_ptr
, int *out_error
, int *out_rv
)
2480 crypto_session_data_t
*sp
= NULL
;
2481 int rv
= CRYPTO_SESSION_HANDLE_INVALID
;
2484 mutex_enter(&cm
->cm_lock
);
2485 if ((i
< cm
->cm_session_table_count
) &&
2486 (cm
->cm_session_table
[i
] != NULL
)) {
2487 sp
= cm
->cm_session_table
[i
];
2488 mutex_enter(&sp
->sd_lock
);
2489 mutex_exit(&cm
->cm_lock
);
2490 while (sp
->sd_flags
& CRYPTO_SESSION_IS_BUSY
) {
2491 if (cv_wait_sig(&sp
->sd_cv
, &sp
->sd_lock
) == 0) {
2492 mutex_exit(&sp
->sd_lock
);
2499 if (sp
->sd_flags
& CRYPTO_SESSION_IS_CLOSED
) {
2500 mutex_exit(&sp
->sd_lock
);
2505 if (KCF_IS_PROV_REMOVED(sp
->sd_provider
)) {
2506 mutex_exit(&sp
->sd_lock
);
2508 rv
= CRYPTO_DEVICE_ERROR
;
2512 rv
= CRYPTO_SUCCESS
;
2513 sp
->sd_flags
|= CRYPTO_SESSION_IS_BUSY
;
2514 mutex_exit(&sp
->sd_lock
);
2516 mutex_exit(&cm
->cm_lock
);
2522 return ((rv
== CRYPTO_SUCCESS
&& error
== 0) ? B_TRUE
: B_FALSE
);
2525 #define CRYPTO_SESSION_RELE(s) if ((s) != NULL) { \
2526 mutex_enter(&((s)->sd_lock)); \
2527 (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \
2528 cv_broadcast(&(s)->sd_cv); \
2529 mutex_exit(&((s)->sd_lock)); \
2534 encrypt_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2536 return (cipher_init(dev
, arg
, mode
, crypto_encrypt_init_prov
));
2541 decrypt_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2543 return (cipher_init(dev
, arg
, mode
, crypto_decrypt_init_prov
));
2547 * umech is a mechanism structure that has been copied from user address
2548 * space into kernel address space. Only one copyin has been done.
2549 * The mechanism parameter, if non-null, still points to user address space.
2550 * If the mechanism parameter contains pointers, they are pointers into
2551 * user address space.
2553 * kmech is a umech with all pointers and structures in kernel address space.
2555 * This routine calls the provider's entry point to copy a umech parameter
2556 * into kernel address space. Kernel memory is allocated by the provider.
2559 crypto_provider_copyin_mech_param(kcf_provider_desc_t
*pd
,
2560 crypto_mechanism_t
*umech
, crypto_mechanism_t
*kmech
, int mode
, int *error
)
2562 crypto_mech_type_t provider_mech_type
;
2565 /* get the provider's mech number */
2566 provider_mech_type
= KCF_TO_PROV_MECHNUM(pd
, umech
->cm_type
);
2568 kmech
->cm_param
= NULL
;
2569 kmech
->cm_param_len
= 0;
2570 kmech
->cm_type
= provider_mech_type
;
2571 rv
= KCF_PROV_COPYIN_MECH(pd
, umech
, kmech
, error
, mode
);
2572 kmech
->cm_type
= umech
->cm_type
;
2578 * umech is a mechanism structure that has been copied from user address
2579 * space into kernel address space. Only one copyin has been done.
2580 * The mechanism parameter, if non-null, still points to user address space.
2581 * If the mechanism parameter contains pointers, they are pointers into
2582 * user address space.
2584 * kmech is a umech with all pointers and structures in kernel address space.
2586 * This routine calls the provider's entry point to copy a kmech parameter
2587 * into user address space using umech as a template containing
2588 * user address pointers.
2591 crypto_provider_copyout_mech_param(kcf_provider_desc_t
*pd
,
2592 crypto_mechanism_t
*kmech
, crypto_mechanism_t
*umech
, int mode
, int *error
)
2594 crypto_mech_type_t provider_mech_type
;
2597 /* get the provider's mech number */
2598 provider_mech_type
= KCF_TO_PROV_MECHNUM(pd
, umech
->cm_type
);
2600 kmech
->cm_type
= provider_mech_type
;
2601 rv
= KCF_PROV_COPYOUT_MECH(pd
, kmech
, umech
, error
, mode
);
2602 kmech
->cm_type
= umech
->cm_type
;
2608 * Call the provider's entry point to free kernel memory that has been
2609 * allocated for the mechanism's parameter.
2612 crypto_free_mech(kcf_provider_desc_t
*pd
, boolean_t allocated_by_crypto_module
,
2613 crypto_mechanism_t
*mech
)
2615 crypto_mech_type_t provider_mech_type
;
2617 if (allocated_by_crypto_module
) {
2618 if (mech
->cm_param
!= NULL
)
2619 kmem_free(mech
->cm_param
, mech
->cm_param_len
);
2621 /* get the provider's mech number */
2622 provider_mech_type
= KCF_TO_PROV_MECHNUM(pd
, mech
->cm_type
);
2624 if (mech
->cm_param
!= NULL
&& mech
->cm_param_len
!= 0) {
2625 mech
->cm_type
= provider_mech_type
;
2626 (void) KCF_PROV_FREE_MECH(pd
, mech
);
2632 * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init
2633 * structures are identical except for field names.
2636 cipher_init(dev_t dev
, caddr_t arg
, int mode
, int (*init
)(crypto_provider_t
,
2637 crypto_session_id_t
, crypto_mechanism_t
*, crypto_key_t
*,
2638 crypto_ctx_template_t
, crypto_context_t
*, crypto_call_req_t
*))
2640 STRUCT_DECL(crypto_encrypt_init
, encrypt_init
);
2641 kcf_provider_desc_t
*real_provider
= NULL
;
2642 crypto_session_id_t session_id
;
2643 crypto_mechanism_t mech
;
2646 crypto_session_data_t
*sp
= NULL
;
2647 crypto_context_t cc
;
2648 crypto_ctx_t
**ctxpp
;
2649 size_t mech_rctl_bytes
= 0;
2650 boolean_t mech_rctl_chk
= B_FALSE
;
2651 size_t key_rctl_bytes
= 0;
2652 boolean_t key_rctl_chk
= B_FALSE
;
2655 boolean_t allocated_by_crypto_module
= B_FALSE
;
2656 crypto_func_group_t fg
;
2658 STRUCT_INIT(encrypt_init
, mode
);
2660 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
2661 cmn_err(CE_WARN
, "cipher_init: failed holding minor");
2665 if (copyin(arg
, STRUCT_BUF(encrypt_init
),
2666 STRUCT_SIZE(encrypt_init
)) != 0) {
2667 crypto_release_minor(cm
);
2671 mech
.cm_param
= NULL
;
2672 bzero(&key
, sizeof (crypto_key_t
));
2674 session_id
= STRUCT_FGET(encrypt_init
, ei_session
);
2676 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
2680 bcopy(STRUCT_FADDR(encrypt_init
, ei_mech
), &mech
.cm_type
,
2681 sizeof (crypto_mech_type_t
));
2683 if (init
== crypto_encrypt_init_prov
) {
2684 fg
= CRYPTO_FG_ENCRYPT
;
2686 fg
= CRYPTO_FG_DECRYPT
;
2689 /* We need the key length for provider selection so copy it in now. */
2690 if (!copyin_key(mode
, sp
, STRUCT_FADDR(encrypt_init
, ei_key
), &key
,
2691 &key_rctl_bytes
, &key_rctl_chk
, &rv
, &error
)) {
2695 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, &key
,
2696 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
, &real_provider
, fg
))
2697 != CRYPTO_SUCCESS
) {
2701 rv
= crypto_provider_copyin_mech_param(real_provider
,
2702 STRUCT_FADDR(encrypt_init
, ei_mech
), &mech
, mode
, &error
);
2704 if (rv
== CRYPTO_NOT_SUPPORTED
) {
2705 allocated_by_crypto_module
= B_TRUE
;
2706 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(encrypt_init
, ei_mech
),
2707 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
2711 if (rv
!= CRYPTO_SUCCESS
)
2715 rv
= (init
)(real_provider
, sp
->sd_provider_session
->ps_session
,
2716 &mech
, &key
, NULL
, &cc
, NULL
);
2719 * Check if a context already exists. If so, it means it is being
2720 * abandoned. So, cancel it to avoid leaking it.
2722 ctxpp
= (init
== crypto_encrypt_init_prov
) ?
2723 &sp
->sd_encr_ctx
: &sp
->sd_decr_ctx
;
2726 CRYPTO_CANCEL_CTX(ctxpp
);
2727 *ctxpp
= (rv
== CRYPTO_SUCCESS
) ? cc
: NULL
;
2730 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
2731 CRYPTO_DECREMENT_RCTL_SESSION(sp
, key_rctl_bytes
, key_rctl_chk
);
2732 CRYPTO_SESSION_RELE(sp
);
2733 crypto_release_minor(cm
);
2735 if (real_provider
!= NULL
) {
2736 crypto_free_mech(real_provider
,
2737 allocated_by_crypto_module
, &mech
);
2738 KCF_PROV_REFRELE(real_provider
);
2741 free_crypto_key(&key
);
2744 /* XXX free context */
2747 STRUCT_FSET(encrypt_init
, ei_return_value
, rv
);
2748 if (copyout(STRUCT_BUF(encrypt_init
), arg
,
2749 STRUCT_SIZE(encrypt_init
)) != 0) {
2750 /* XXX free context */
2758 encrypt(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2760 return (cipher(dev
, arg
, mode
, crypto_encrypt_single
));
2765 decrypt(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2767 return (cipher(dev
, arg
, mode
, crypto_decrypt_single
));
2771 * ASSUMPTION: crypto_encrypt and crypto_decrypt structures
2772 * are identical except for field names.
2775 cipher(dev_t dev
, caddr_t arg
, int mode
,
2776 int (*single
)(crypto_context_t
, crypto_data_t
*, crypto_data_t
*,
2777 crypto_call_req_t
*))
2779 STRUCT_DECL(crypto_encrypt
, encrypt
);
2780 crypto_session_id_t session_id
;
2782 crypto_session_data_t
*sp
= NULL
;
2783 crypto_ctx_t
**ctxpp
;
2784 crypto_data_t data
, encr
;
2785 size_t datalen
, encrlen
, need
= 0;
2786 boolean_t do_inplace
;
2790 boolean_t rctl_chk
= B_FALSE
;
2792 STRUCT_INIT(encrypt
, mode
);
2794 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
2795 cmn_err(CE_WARN
, "cipher: failed holding minor");
2799 if (copyin(arg
, STRUCT_BUF(encrypt
), STRUCT_SIZE(encrypt
)) != 0) {
2800 crypto_release_minor(cm
);
2804 data
.cd_raw
.iov_base
= NULL
;
2805 encr
.cd_raw
.iov_base
= NULL
;
2807 datalen
= STRUCT_FGET(encrypt
, ce_datalen
);
2808 encrlen
= STRUCT_FGET(encrypt
, ce_encrlen
);
2811 * Don't allocate output buffer unless both buffer pointer and
2812 * buffer length are not NULL or 0 (length).
2814 encrbuf
= STRUCT_FGETP(encrypt
, ce_encrbuf
);
2815 if (encrbuf
== NULL
|| encrlen
== 0) {
2819 if (datalen
> crypto_max_buffer_len
||
2820 encrlen
> crypto_max_buffer_len
) {
2821 cmn_err(CE_NOTE
, "cipher: buffer greater than %ld bytes, "
2822 "pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
2823 rv
= CRYPTO_ARGUMENTS_BAD
;
2827 session_id
= STRUCT_FGET(encrypt
, ce_session
);
2829 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
2833 do_inplace
= (STRUCT_FGET(encrypt
, ce_flags
) &
2834 CRYPTO_INPLACE_OPERATION
) != 0;
2835 need
= do_inplace
? datalen
: datalen
+ encrlen
;
2837 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, need
, rctl_chk
)) !=
2843 INIT_RAW_CRYPTO_DATA(data
, datalen
);
2844 data
.cd_miscdata
= NULL
;
2846 if (datalen
!= 0 && copyin(STRUCT_FGETP(encrypt
, ce_databuf
),
2847 data
.cd_raw
.iov_base
, datalen
) != 0) {
2853 /* set out = in for in-place */
2856 INIT_RAW_CRYPTO_DATA(encr
, encrlen
);
2859 ctxpp
= (single
== crypto_encrypt_single
) ?
2860 &sp
->sd_encr_ctx
: &sp
->sd_decr_ctx
;
2863 /* specify in-place buffers with output = NULL */
2864 rv
= (single
)(*ctxpp
, &encr
, NULL
, NULL
);
2866 rv
= (single
)(*ctxpp
, &data
, &encr
, NULL
);
2868 if (KCF_CONTEXT_DONE(rv
))
2871 if (rv
== CRYPTO_SUCCESS
) {
2872 ASSERT(encr
.cd_length
<= encrlen
);
2873 if (encr
.cd_length
!= 0 && copyout(encr
.cd_raw
.iov_base
,
2874 encrbuf
, encr
.cd_length
) != 0) {
2878 STRUCT_FSET(encrypt
, ce_encrlen
,
2879 (ulong_t
)encr
.cd_length
);
2882 if (rv
== CRYPTO_BUFFER_TOO_SMALL
) {
2884 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
2885 * of section 11.2 of the pkcs11 spec. We catch it here and
2886 * provide the correct pkcs11 return value.
2888 if (STRUCT_FGETP(encrypt
, ce_encrbuf
) == NULL
)
2889 rv
= CRYPTO_SUCCESS
;
2890 STRUCT_FSET(encrypt
, ce_encrlen
,
2891 (ulong_t
)encr
.cd_length
);
2895 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
2896 CRYPTO_SESSION_RELE(sp
);
2897 crypto_release_minor(cm
);
2899 if (data
.cd_raw
.iov_base
!= NULL
)
2900 kmem_free(data
.cd_raw
.iov_base
, datalen
);
2902 if (!do_inplace
&& encr
.cd_raw
.iov_base
!= NULL
)
2903 kmem_free(encr
.cd_raw
.iov_base
, encrlen
);
2908 STRUCT_FSET(encrypt
, ce_return_value
, rv
);
2909 if (copyout(STRUCT_BUF(encrypt
), arg
, STRUCT_SIZE(encrypt
)) != 0) {
2917 encrypt_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2919 return (cipher_update(dev
, arg
, mode
, crypto_encrypt_update
));
2924 decrypt_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
2926 return (cipher_update(dev
, arg
, mode
, crypto_decrypt_update
));
2930 * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update
2931 * structures are identical except for field names.
2934 cipher_update(dev_t dev
, caddr_t arg
, int mode
,
2935 int (*update
)(crypto_context_t
, crypto_data_t
*, crypto_data_t
*,
2936 crypto_call_req_t
*))
2938 STRUCT_DECL(crypto_encrypt_update
, encrypt_update
);
2939 crypto_session_id_t session_id
;
2941 crypto_session_data_t
*sp
= NULL
;
2942 crypto_ctx_t
**ctxpp
;
2943 crypto_data_t data
, encr
;
2944 size_t datalen
, encrlen
, need
= 0;
2945 boolean_t do_inplace
;
2949 boolean_t rctl_chk
= B_FALSE
;
2951 STRUCT_INIT(encrypt_update
, mode
);
2953 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
2954 cmn_err(CE_WARN
, "cipher_update: failed holding minor");
2958 if (copyin(arg
, STRUCT_BUF(encrypt_update
),
2959 STRUCT_SIZE(encrypt_update
)) != 0) {
2960 crypto_release_minor(cm
);
2964 data
.cd_raw
.iov_base
= NULL
;
2965 encr
.cd_raw
.iov_base
= NULL
;
2967 datalen
= STRUCT_FGET(encrypt_update
, eu_datalen
);
2968 encrlen
= STRUCT_FGET(encrypt_update
, eu_encrlen
);
2971 * Don't allocate output buffer unless both buffer pointer and
2972 * buffer length are not NULL or 0 (length).
2974 encrbuf
= STRUCT_FGETP(encrypt_update
, eu_encrbuf
);
2975 if (encrbuf
== NULL
|| encrlen
== 0) {
2979 if (datalen
> crypto_max_buffer_len
||
2980 encrlen
> crypto_max_buffer_len
) {
2981 cmn_err(CE_NOTE
, "cipher_update: buffer greater than %ld "
2982 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
2983 rv
= CRYPTO_ARGUMENTS_BAD
;
2987 session_id
= STRUCT_FGET(encrypt_update
, eu_session
);
2989 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
2993 do_inplace
= (STRUCT_FGET(encrypt_update
, eu_flags
) &
2994 CRYPTO_INPLACE_OPERATION
) != 0;
2995 need
= do_inplace
? datalen
: datalen
+ encrlen
;
2997 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, need
, rctl_chk
)) !=
3003 INIT_RAW_CRYPTO_DATA(data
, datalen
);
3004 data
.cd_miscdata
= NULL
;
3006 if (datalen
!= 0 && copyin(STRUCT_FGETP(encrypt_update
, eu_databuf
),
3007 data
.cd_raw
.iov_base
, datalen
) != 0) {
3013 /* specify in-place buffers with output = input */
3016 INIT_RAW_CRYPTO_DATA(encr
, encrlen
);
3019 ctxpp
= (update
== crypto_encrypt_update
) ?
3020 &sp
->sd_encr_ctx
: &sp
->sd_decr_ctx
;
3023 /* specify in-place buffers with output = NULL */
3024 rv
= (update
)(*ctxpp
, &encr
, NULL
, NULL
);
3026 rv
= (update
)(*ctxpp
, &data
, &encr
, NULL
);
3028 if (rv
== CRYPTO_SUCCESS
|| rv
== CRYPTO_BUFFER_TOO_SMALL
) {
3029 if (rv
== CRYPTO_SUCCESS
) {
3030 ASSERT(encr
.cd_length
<= encrlen
);
3031 if (encr
.cd_length
!= 0 && copyout(encr
.cd_raw
.iov_base
,
3032 encrbuf
, encr
.cd_length
) != 0) {
3038 * The providers return CRYPTO_BUFFER_TOO_SMALL even
3039 * for case 1 of section 11.2 of the pkcs11 spec.
3040 * We catch it here and provide the correct pkcs11
3043 if (STRUCT_FGETP(encrypt_update
, eu_encrbuf
) == NULL
)
3044 rv
= CRYPTO_SUCCESS
;
3046 STRUCT_FSET(encrypt_update
, eu_encrlen
,
3047 (ulong_t
)encr
.cd_length
);
3049 CRYPTO_CANCEL_CTX(ctxpp
);
3052 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
3053 CRYPTO_SESSION_RELE(sp
);
3054 crypto_release_minor(cm
);
3056 if (data
.cd_raw
.iov_base
!= NULL
)
3057 kmem_free(data
.cd_raw
.iov_base
, datalen
);
3059 if (!do_inplace
&& (encr
.cd_raw
.iov_base
!= NULL
))
3060 kmem_free(encr
.cd_raw
.iov_base
, encrlen
);
3065 STRUCT_FSET(encrypt_update
, eu_return_value
, rv
);
3066 if (copyout(STRUCT_BUF(encrypt_update
), arg
,
3067 STRUCT_SIZE(encrypt_update
)) != 0) {
3075 encrypt_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3077 return (common_final(dev
, arg
, mode
, crypto_encrypt_final
));
3082 decrypt_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3084 return (common_final(dev
, arg
, mode
, crypto_decrypt_final
));
3088 * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final,
3089 * and crypto_digest_final structures are identical except for field names.
3092 common_final(dev_t dev
, caddr_t arg
, int mode
,
3093 int (*final
)(crypto_context_t
, crypto_data_t
*, crypto_call_req_t
*))
3095 STRUCT_DECL(crypto_encrypt_final
, encrypt_final
);
3096 crypto_session_id_t session_id
;
3098 crypto_session_data_t
*sp
= NULL
;
3099 crypto_ctx_t
**ctxpp
;
3101 size_t encrlen
, need
= 0;
3105 boolean_t rctl_chk
= B_FALSE
;
3107 STRUCT_INIT(encrypt_final
, mode
);
3109 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3110 cmn_err(CE_WARN
, "common_final: failed holding minor");
3114 if (copyin(arg
, STRUCT_BUF(encrypt_final
),
3115 STRUCT_SIZE(encrypt_final
)) != 0) {
3116 crypto_release_minor(cm
);
3120 encr
.cd_format
= CRYPTO_DATA_RAW
;
3121 encr
.cd_raw
.iov_base
= NULL
;
3123 encrlen
= STRUCT_FGET(encrypt_final
, ef_encrlen
);
3126 * Don't allocate output buffer unless both buffer pointer and
3127 * buffer length are not NULL or 0 (length).
3129 encrbuf
= STRUCT_FGETP(encrypt_final
, ef_encrbuf
);
3130 if (encrbuf
== NULL
|| encrlen
== 0) {
3134 if (encrlen
> crypto_max_buffer_len
) {
3135 cmn_err(CE_NOTE
, "common_final: buffer greater than %ld "
3136 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
3137 rv
= CRYPTO_ARGUMENTS_BAD
;
3141 session_id
= STRUCT_FGET(encrypt_final
, ef_session
);
3143 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
3147 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, encrlen
, rctl_chk
)) !=
3152 encr
.cd_raw
.iov_base
= kmem_alloc(encrlen
, KM_SLEEP
);
3153 encr
.cd_raw
.iov_len
= encrlen
;
3156 encr
.cd_length
= encrlen
;
3158 ASSERT(final
== crypto_encrypt_final
||
3159 final
== crypto_decrypt_final
|| final
== crypto_sign_final
||
3160 final
== crypto_digest_final
|| final
== crypto_mac_final
);
3162 if (final
== crypto_encrypt_final
) {
3163 ctxpp
= &sp
->sd_encr_ctx
;
3164 } else if (final
== crypto_decrypt_final
) {
3165 ctxpp
= &sp
->sd_decr_ctx
;
3166 } else if (final
== crypto_sign_final
) {
3167 ctxpp
= &sp
->sd_sign_ctx
;
3168 } else if (final
== crypto_mac_final
) {
3169 ctxpp
= &sp
->sd_mac_ctx
;
3171 ctxpp
= &sp
->sd_digest_ctx
;
3174 rv
= (final
)(*ctxpp
, &encr
, NULL
);
3175 if (KCF_CONTEXT_DONE(rv
))
3178 if (rv
== CRYPTO_SUCCESS
) {
3179 ASSERT(encr
.cd_length
<= encrlen
);
3180 if (encr
.cd_length
!= 0 && copyout(encr
.cd_raw
.iov_base
,
3181 encrbuf
, encr
.cd_length
) != 0) {
3185 STRUCT_FSET(encrypt_final
, ef_encrlen
,
3186 (ulong_t
)encr
.cd_length
);
3189 if (rv
== CRYPTO_BUFFER_TOO_SMALL
) {
3191 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3192 * of section 11.2 of the pkcs11 spec. We catch it here and
3193 * provide the correct pkcs11 return value.
3195 if (STRUCT_FGETP(encrypt_final
, ef_encrbuf
) == NULL
)
3196 rv
= CRYPTO_SUCCESS
;
3197 STRUCT_FSET(encrypt_final
, ef_encrlen
,
3198 (ulong_t
)encr
.cd_length
);
3202 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
3203 CRYPTO_SESSION_RELE(sp
);
3204 crypto_release_minor(cm
);
3206 if (encr
.cd_raw
.iov_base
!= NULL
)
3207 kmem_free(encr
.cd_raw
.iov_base
, encrlen
);
3212 STRUCT_FSET(encrypt_final
, ef_return_value
, rv
);
3213 if (copyout(STRUCT_BUF(encrypt_final
), arg
,
3214 STRUCT_SIZE(encrypt_final
)) != 0) {
3222 digest_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3224 STRUCT_DECL(crypto_digest_init
, digest_init
);
3225 kcf_provider_desc_t
*real_provider
= NULL
;
3226 crypto_session_id_t session_id
;
3227 crypto_mechanism_t mech
;
3229 crypto_session_data_t
*sp
= NULL
;
3230 crypto_context_t cc
;
3231 size_t rctl_bytes
= 0;
3232 boolean_t rctl_chk
= B_FALSE
;
3236 STRUCT_INIT(digest_init
, mode
);
3238 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3239 cmn_err(CE_WARN
, "digest_init: failed holding minor");
3243 if (copyin(arg
, STRUCT_BUF(digest_init
),
3244 STRUCT_SIZE(digest_init
)) != 0) {
3245 crypto_release_minor(cm
);
3249 mech
.cm_param
= NULL
;
3251 session_id
= STRUCT_FGET(digest_init
, di_session
);
3253 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
3257 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(digest_init
, di_mech
), &mech
,
3258 &rctl_bytes
, &rctl_chk
, &rv
, &error
)) {
3262 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, NULL
,
3263 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
, &real_provider
,
3264 CRYPTO_FG_DIGEST
)) != CRYPTO_SUCCESS
) {
3268 rv
= crypto_digest_init_prov(real_provider
,
3269 sp
->sd_provider_session
->ps_session
, &mech
, &cc
, NULL
);
3272 * Check if a context already exists. If so, it means it is being
3273 * abandoned. So, cancel it to avoid leaking it.
3275 if (sp
->sd_digest_ctx
!= NULL
)
3276 CRYPTO_CANCEL_CTX(&sp
->sd_digest_ctx
);
3277 sp
->sd_digest_ctx
= (rv
== CRYPTO_SUCCESS
) ? cc
: NULL
;
3279 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
3280 CRYPTO_SESSION_RELE(sp
);
3281 crypto_release_minor(cm
);
3283 if (real_provider
!= NULL
)
3284 KCF_PROV_REFRELE(real_provider
);
3286 if (mech
.cm_param
!= NULL
)
3287 kmem_free(mech
.cm_param
, mech
.cm_param_len
);
3292 STRUCT_FSET(digest_init
, di_return_value
, rv
);
3293 if (copyout(STRUCT_BUF(digest_init
), arg
,
3294 STRUCT_SIZE(digest_init
)) != 0) {
3302 digest_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3304 STRUCT_DECL(crypto_digest_update
, digest_update
);
3305 crypto_session_id_t session_id
;
3307 crypto_session_data_t
*sp
= NULL
;
3309 size_t datalen
, need
= 0;
3312 boolean_t rctl_chk
= B_FALSE
;
3314 STRUCT_INIT(digest_update
, mode
);
3316 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3317 cmn_err(CE_WARN
, "digest_update: failed holding minor");
3321 if (copyin(arg
, STRUCT_BUF(digest_update
),
3322 STRUCT_SIZE(digest_update
)) != 0) {
3323 crypto_release_minor(cm
);
3327 data
.cd_format
= CRYPTO_DATA_RAW
;
3328 data
.cd_raw
.iov_base
= NULL
;
3330 datalen
= STRUCT_FGET(digest_update
, du_datalen
);
3331 if (datalen
> crypto_max_buffer_len
) {
3332 cmn_err(CE_NOTE
, "digest_update: buffer greater than %ld "
3333 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
3334 rv
= CRYPTO_ARGUMENTS_BAD
;
3338 session_id
= STRUCT_FGET(digest_update
, du_session
);
3340 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
3344 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, datalen
, rctl_chk
)) !=
3350 data
.cd_raw
.iov_base
= kmem_alloc(datalen
, KM_SLEEP
);
3351 data
.cd_raw
.iov_len
= datalen
;
3353 if (datalen
!= 0 && copyin(STRUCT_FGETP(digest_update
, du_databuf
),
3354 data
.cd_raw
.iov_base
, datalen
) != 0) {
3360 data
.cd_length
= datalen
;
3362 rv
= crypto_digest_update(sp
->sd_digest_ctx
, &data
, NULL
);
3363 if (rv
!= CRYPTO_SUCCESS
)
3364 CRYPTO_CANCEL_CTX(&sp
->sd_digest_ctx
);
3367 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
3368 CRYPTO_SESSION_RELE(sp
);
3369 crypto_release_minor(cm
);
3371 if (data
.cd_raw
.iov_base
!= NULL
)
3372 kmem_free(data
.cd_raw
.iov_base
, datalen
);
3377 STRUCT_FSET(digest_update
, du_return_value
, rv
);
3378 if (copyout(STRUCT_BUF(digest_update
), arg
,
3379 STRUCT_SIZE(digest_update
)) != 0) {
3387 digest_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3389 STRUCT_DECL(crypto_digest_key
, digest_key
);
3390 crypto_session_id_t session_id
;
3393 crypto_session_data_t
*sp
= NULL
;
3394 size_t rctl_bytes
= 0;
3395 boolean_t key_rctl_chk
= B_FALSE
;
3399 STRUCT_INIT(digest_key
, mode
);
3401 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3402 cmn_err(CE_WARN
, "digest_key: failed holding minor");
3406 if (copyin(arg
, STRUCT_BUF(digest_key
), STRUCT_SIZE(digest_key
)) != 0) {
3407 crypto_release_minor(cm
);
3411 bzero(&key
, sizeof (crypto_key_t
));
3413 session_id
= STRUCT_FGET(digest_key
, dk_session
);
3415 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
3419 if (!copyin_key(mode
, sp
, STRUCT_FADDR(digest_key
, dk_key
), &key
,
3420 &rctl_bytes
, &key_rctl_chk
, &rv
, &error
)) {
3424 rv
= crypto_digest_key_prov(sp
->sd_digest_ctx
, &key
, NULL
);
3425 if (rv
!= CRYPTO_SUCCESS
)
3426 CRYPTO_CANCEL_CTX(&sp
->sd_digest_ctx
);
3428 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, key_rctl_chk
);
3429 CRYPTO_SESSION_RELE(sp
);
3430 crypto_release_minor(cm
);
3432 free_crypto_key(&key
);
3437 STRUCT_FSET(digest_key
, dk_return_value
, rv
);
3438 if (copyout(STRUCT_BUF(digest_key
), arg
,
3439 STRUCT_SIZE(digest_key
)) != 0) {
3447 digest_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3449 return (common_final(dev
, arg
, mode
, crypto_digest_final
));
3454 digest(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3456 return (common_digest(dev
, arg
, mode
, crypto_digest_single
));
3460 mac_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3462 _NOTE(ARGUNUSED(rval
))
3463 return (sign_verify_init(dev
, arg
, mode
, crypto_mac_init_prov
));
3467 mac_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3469 _NOTE(ARGUNUSED(rval
))
3470 return (sign_verify_update(dev
, arg
, mode
, crypto_mac_update
));
3474 mac_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3476 _NOTE(ARGUNUSED(rval
))
3477 return (common_final(dev
, arg
, mode
, crypto_mac_final
));
3482 mac(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3484 _NOTE(ARGUNUSED(rval
))
3485 return (common_digest(dev
, arg
, mode
, crypto_mac_single
));
3489 * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
3490 * and crypto_verify_recover are identical except for field names.
3493 common_digest(dev_t dev
, caddr_t arg
, int mode
,
3494 int (*single
)(crypto_context_t
, crypto_data_t
*, crypto_data_t
*,
3495 crypto_call_req_t
*))
3497 STRUCT_DECL(crypto_digest
, crypto_digest
);
3498 crypto_session_id_t session_id
;
3500 crypto_session_data_t
*sp
= NULL
;
3501 crypto_data_t data
, digest
;
3502 crypto_ctx_t
**ctxpp
;
3503 size_t datalen
, digestlen
, need
= 0;
3507 boolean_t rctl_chk
= B_FALSE
;
3509 STRUCT_INIT(crypto_digest
, mode
);
3511 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3512 cmn_err(CE_WARN
, "common_digest: failed holding minor");
3516 if (copyin(arg
, STRUCT_BUF(crypto_digest
),
3517 STRUCT_SIZE(crypto_digest
)) != 0) {
3518 crypto_release_minor(cm
);
3522 data
.cd_raw
.iov_base
= NULL
;
3523 digest
.cd_raw
.iov_base
= NULL
;
3524 data
.cd_miscdata
= NULL
;
3525 digest
.cd_miscdata
= NULL
;
3527 datalen
= STRUCT_FGET(crypto_digest
, cd_datalen
);
3528 digestlen
= STRUCT_FGET(crypto_digest
, cd_digestlen
);
3531 * Don't allocate output buffer unless both buffer pointer and
3532 * buffer length are not NULL or 0 (length).
3534 digestbuf
= STRUCT_FGETP(crypto_digest
, cd_digestbuf
);
3535 if (digestbuf
== NULL
|| digestlen
== 0) {
3539 if (datalen
> crypto_max_buffer_len
||
3540 digestlen
> crypto_max_buffer_len
) {
3541 cmn_err(CE_NOTE
, "common_digest: buffer greater than %ld "
3542 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
3543 rv
= CRYPTO_ARGUMENTS_BAD
;
3547 session_id
= STRUCT_FGET(crypto_digest
, cd_session
);
3549 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
3553 need
= datalen
+ digestlen
;
3554 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, need
, rctl_chk
)) !=
3560 INIT_RAW_CRYPTO_DATA(data
, datalen
);
3562 if (datalen
!= 0 && copyin(STRUCT_FGETP(crypto_digest
, cd_databuf
),
3563 data
.cd_raw
.iov_base
, datalen
) != 0) {
3568 INIT_RAW_CRYPTO_DATA(digest
, digestlen
);
3570 ASSERT(single
== crypto_digest_single
||
3571 single
== crypto_sign_single
||
3572 single
== crypto_verify_recover_single
||
3573 single
== crypto_sign_recover_single
||
3574 single
== crypto_mac_single
);
3576 if (single
== crypto_digest_single
) {
3577 ctxpp
= &sp
->sd_digest_ctx
;
3578 } else if (single
== crypto_sign_single
) {
3579 ctxpp
= &sp
->sd_sign_ctx
;
3580 } else if (single
== crypto_verify_recover_single
) {
3581 ctxpp
= &sp
->sd_verify_recover_ctx
;
3582 } else if (single
== crypto_mac_single
) {
3583 ctxpp
= &sp
->sd_mac_ctx
;
3585 ctxpp
= &sp
->sd_sign_recover_ctx
;
3587 rv
= (single
)(*ctxpp
, &data
, &digest
, NULL
);
3588 if (KCF_CONTEXT_DONE(rv
))
3591 if (rv
== CRYPTO_SUCCESS
) {
3592 ASSERT(digest
.cd_length
<= digestlen
);
3593 if (digest
.cd_length
!= 0 && copyout(digest
.cd_raw
.iov_base
,
3594 digestbuf
, digest
.cd_length
) != 0) {
3598 STRUCT_FSET(crypto_digest
, cd_digestlen
,
3599 (ulong_t
)digest
.cd_length
);
3602 if (rv
== CRYPTO_BUFFER_TOO_SMALL
) {
3604 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3605 * of section 11.2 of the pkcs11 spec. We catch it here and
3606 * provide the correct pkcs11 return value.
3608 if (STRUCT_FGETP(crypto_digest
, cd_digestbuf
) == NULL
)
3609 rv
= CRYPTO_SUCCESS
;
3610 STRUCT_FSET(crypto_digest
, cd_digestlen
,
3611 (ulong_t
)digest
.cd_length
);
3615 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
3616 CRYPTO_SESSION_RELE(sp
);
3617 crypto_release_minor(cm
);
3619 if (data
.cd_raw
.iov_base
!= NULL
)
3620 kmem_free(data
.cd_raw
.iov_base
, datalen
);
3622 if (digest
.cd_raw
.iov_base
!= NULL
)
3623 kmem_free(digest
.cd_raw
.iov_base
, digestlen
);
3628 STRUCT_FSET(crypto_digest
, cd_return_value
, rv
);
3629 if (copyout(STRUCT_BUF(crypto_digest
), arg
,
3630 STRUCT_SIZE(crypto_digest
)) != 0) {
3637 * A helper function that does what the name suggests.
3638 * Returns 0 on success and non-zero otherwise.
3639 * On failure, out_pin is set to 0.
3642 get_pin_and_session_ptr(char *in_pin
, char **out_pin
, size_t pin_len
,
3643 crypto_minor_t
*cm
, crypto_session_id_t sid
, crypto_session_data_t
**sp
,
3644 int *rv
, int *error
)
3646 char *tmp_pin
= NULL
;
3647 int tmp_error
= 0, tmp_rv
= 0;
3649 if (pin_len
> KCF_MAX_PIN_LEN
) {
3650 tmp_rv
= CRYPTO_PIN_LEN_RANGE
;
3653 tmp_pin
= kmem_alloc(pin_len
, KM_SLEEP
);
3655 if (pin_len
!= 0 && copyin(in_pin
, tmp_pin
, pin_len
) != 0) {
3660 (void) get_session_ptr(sid
, cm
, sp
, &tmp_error
, &tmp_rv
);
3665 return (tmp_rv
| tmp_error
);
3670 set_pin(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3672 STRUCT_DECL(crypto_set_pin
, set_pin
);
3673 kcf_provider_desc_t
*real_provider
;
3674 kcf_req_params_t params
;
3676 crypto_session_data_t
*sp
;
3677 char *old_pin
= NULL
;
3678 char *new_pin
= NULL
;
3684 STRUCT_INIT(set_pin
, mode
);
3686 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3687 cmn_err(CE_WARN
, "set_pin: failed holding minor");
3691 if (copyin(arg
, STRUCT_BUF(set_pin
),
3692 STRUCT_SIZE(set_pin
)) != 0) {
3693 crypto_release_minor(cm
);
3697 old_pin_len
= STRUCT_FGET(set_pin
, sp_old_len
);
3699 if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin
, sp_old_pin
),
3700 &old_pin
, old_pin_len
, cm
, STRUCT_FGET(set_pin
, sp_session
),
3701 &sp
, &rv
, &error
) != 0)
3704 new_pin_len
= STRUCT_FGET(set_pin
, sp_new_len
);
3705 if (new_pin_len
> KCF_MAX_PIN_LEN
) {
3706 rv
= CRYPTO_PIN_LEN_RANGE
;
3709 new_pin
= kmem_alloc(new_pin_len
, KM_SLEEP
);
3711 if (new_pin_len
!= 0 && copyin(STRUCT_FGETP(set_pin
, sp_new_pin
),
3712 new_pin
, new_pin_len
) != 0) {
3717 if ((rv
= kcf_get_hardware_provider_nomech(
3718 CRYPTO_OPS_OFFSET(provider_ops
), CRYPTO_PROVIDER_OFFSET(set_pin
),
3719 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
3723 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms
, KCF_OP_MGMT_SETPIN
,
3724 sp
->sd_provider_session
->ps_session
, old_pin
, old_pin_len
,
3725 new_pin
, new_pin_len
, NULL
, NULL
, real_provider
);
3727 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
3728 KCF_PROV_REFRELE(real_provider
);
3731 CRYPTO_SESSION_RELE(sp
);
3734 crypto_release_minor(cm
);
3736 if (old_pin
!= NULL
) {
3737 bzero(old_pin
, old_pin_len
);
3738 kmem_free(old_pin
, old_pin_len
);
3741 if (new_pin
!= NULL
) {
3742 bzero(new_pin
, new_pin_len
);
3743 kmem_free(new_pin
, new_pin_len
);
3749 STRUCT_FSET(set_pin
, sp_return_value
, rv
);
3750 if (copyout(STRUCT_BUF(set_pin
), arg
, STRUCT_SIZE(set_pin
)) != 0) {
3758 login(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3760 STRUCT_DECL(crypto_login
, login
);
3761 kcf_provider_desc_t
*real_provider
;
3762 kcf_req_params_t params
;
3764 crypto_session_data_t
*sp
;
3771 STRUCT_INIT(login
, mode
);
3773 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3774 cmn_err(CE_WARN
, "login: failed holding minor");
3778 if (copyin(arg
, STRUCT_BUF(login
), STRUCT_SIZE(login
)) != 0) {
3779 crypto_release_minor(cm
);
3783 user_type
= STRUCT_FGET(login
, co_user_type
);
3785 pin_len
= STRUCT_FGET(login
, co_pin_len
);
3787 if (get_pin_and_session_ptr(STRUCT_FGETP(login
, co_pin
),
3788 &pin
, pin_len
, cm
, STRUCT_FGET(login
, co_session
),
3789 &sp
, &rv
, &error
) != 0) {
3790 if (rv
== CRYPTO_PIN_LEN_RANGE
)
3791 rv
= CRYPTO_PIN_INCORRECT
;
3795 if ((rv
= kcf_get_hardware_provider_nomech(
3796 CRYPTO_OPS_OFFSET(session_ops
),
3797 CRYPTO_SESSION_OFFSET(session_login
), sp
->sd_provider
,
3798 &real_provider
)) != CRYPTO_SUCCESS
) {
3802 KCF_WRAP_SESSION_OPS_PARAMS(¶ms
, KCF_OP_SESSION_LOGIN
, NULL
,
3803 sp
->sd_provider_session
->ps_session
, user_type
, pin
, pin_len
,
3806 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
3807 KCF_PROV_REFRELE(real_provider
);
3810 CRYPTO_SESSION_RELE(sp
);
3813 crypto_release_minor(cm
);
3816 bzero(pin
, pin_len
);
3817 kmem_free(pin
, pin_len
);
3823 STRUCT_FSET(login
, co_return_value
, rv
);
3824 if (copyout(STRUCT_BUF(login
), arg
, STRUCT_SIZE(login
)) != 0) {
3832 logout(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3834 crypto_logout_t logout
;
3835 kcf_provider_desc_t
*real_provider
;
3836 kcf_req_params_t params
;
3838 crypto_session_data_t
*sp
;
3842 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3843 cmn_err(CE_WARN
, "logout: failed holding minor");
3847 if (copyin(arg
, &logout
, sizeof (logout
)) != 0) {
3848 crypto_release_minor(cm
);
3852 if (!get_session_ptr(logout
.cl_session
, cm
, &sp
, &error
, &rv
)) {
3856 if ((rv
= kcf_get_hardware_provider_nomech(
3857 CRYPTO_OPS_OFFSET(session_ops
),
3858 CRYPTO_SESSION_OFFSET(session_logout
), sp
->sd_provider
,
3859 &real_provider
)) != CRYPTO_SUCCESS
) {
3863 KCF_WRAP_SESSION_OPS_PARAMS(¶ms
, KCF_OP_SESSION_LOGOUT
, NULL
,
3864 sp
->sd_provider_session
->ps_session
, 0, NULL
, 0, real_provider
);
3865 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
3866 KCF_PROV_REFRELE(real_provider
);
3869 CRYPTO_SESSION_RELE(sp
);
3872 crypto_release_minor(cm
);
3877 logout
.cl_return_value
= rv
;
3878 if (copyout(&logout
, arg
, sizeof (logout
)) != 0) {
3886 sign_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3888 return (sign_verify_init(dev
, arg
, mode
, crypto_sign_init_prov
));
3893 sign_recover_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3895 return (sign_verify_init(dev
, arg
, mode
,
3896 crypto_sign_recover_init_prov
));
3901 verify_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3903 return (sign_verify_init(dev
, arg
, mode
, crypto_verify_init_prov
));
3908 verify_recover_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
3910 return (sign_verify_init(dev
, arg
, mode
,
3911 crypto_verify_recover_init_prov
));
3915 * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init,
3916 * and crypto_verify_recover_init structures are identical
3917 * except for field names.
3920 sign_verify_init(dev_t dev
, caddr_t arg
, int mode
,
3921 int (*init
)(crypto_provider_t
, crypto_session_id_t
,
3922 crypto_mechanism_t
*, crypto_key_t
*, crypto_ctx_template_t
,
3923 crypto_context_t
*, crypto_call_req_t
*))
3925 STRUCT_DECL(crypto_sign_init
, sign_init
);
3926 kcf_provider_desc_t
*real_provider
= NULL
;
3927 crypto_session_id_t session_id
;
3928 crypto_mechanism_t mech
;
3931 crypto_session_data_t
*sp
= NULL
;
3932 crypto_context_t cc
;
3933 crypto_ctx_t
**ctxpp
;
3934 size_t mech_rctl_bytes
= 0;
3935 boolean_t mech_rctl_chk
= B_FALSE
;
3936 size_t key_rctl_bytes
= 0;
3937 boolean_t key_rctl_chk
= B_FALSE
;
3940 boolean_t allocated_by_crypto_module
= B_FALSE
;
3941 crypto_func_group_t fg
;
3943 STRUCT_INIT(sign_init
, mode
);
3945 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
3946 cmn_err(CE_WARN
, "sign_verify_init: failed holding minor");
3950 if (copyin(arg
, STRUCT_BUF(sign_init
), STRUCT_SIZE(sign_init
)) != 0) {
3951 crypto_release_minor(cm
);
3955 mech
.cm_param
= NULL
;
3956 bzero(&key
, sizeof (key
));
3958 session_id
= STRUCT_FGET(sign_init
, si_session
);
3960 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
3964 bcopy(STRUCT_FADDR(sign_init
, si_mech
), &mech
.cm_type
,
3965 sizeof (crypto_mech_type_t
));
3967 ASSERT(init
== crypto_sign_init_prov
||
3968 init
== crypto_verify_init_prov
||
3969 init
== crypto_sign_recover_init_prov
||
3970 init
== crypto_verify_recover_init_prov
||
3971 init
== crypto_mac_init_prov
);
3973 if (init
== crypto_sign_init_prov
) {
3974 fg
= CRYPTO_FG_SIGN
;
3975 ctxpp
= &sp
->sd_sign_ctx
;
3976 } else if (init
== crypto_verify_init_prov
) {
3977 fg
= CRYPTO_FG_VERIFY
;
3978 ctxpp
= &sp
->sd_verify_ctx
;
3979 } else if (init
== crypto_sign_recover_init_prov
) {
3980 fg
= CRYPTO_FG_SIGN_RECOVER
;
3981 ctxpp
= &sp
->sd_sign_recover_ctx
;
3982 } else if (init
== crypto_mac_init_prov
) {
3984 ctxpp
= &sp
->sd_mac_ctx
;
3986 fg
= CRYPTO_FG_VERIFY_RECOVER
;
3987 ctxpp
= &sp
->sd_verify_recover_ctx
;
3990 /* We need the key length for provider selection so copy it in now. */
3991 if (!copyin_key(mode
, sp
, STRUCT_FADDR(sign_init
, si_key
), &key
,
3992 &key_rctl_bytes
, &key_rctl_chk
, &rv
, &error
)) {
3996 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, &key
,
3997 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
, &real_provider
,
3998 fg
)) != CRYPTO_SUCCESS
) {
4002 rv
= crypto_provider_copyin_mech_param(real_provider
,
4003 STRUCT_FADDR(sign_init
, si_mech
), &mech
, mode
, &error
);
4005 if (rv
== CRYPTO_NOT_SUPPORTED
) {
4006 allocated_by_crypto_module
= B_TRUE
;
4007 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(sign_init
, si_mech
),
4008 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
4012 if (rv
!= CRYPTO_SUCCESS
)
4016 rv
= (init
)(real_provider
, sp
->sd_provider_session
->ps_session
,
4017 &mech
, &key
, NULL
, &cc
, NULL
);
4020 * Check if a context already exists. If so, it means it is being
4021 * abandoned. So, cancel it to avoid leaking it.
4024 CRYPTO_CANCEL_CTX(ctxpp
);
4025 *ctxpp
= (rv
== CRYPTO_SUCCESS
) ? cc
: NULL
;
4028 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
4029 CRYPTO_DECREMENT_RCTL_SESSION(sp
, key_rctl_bytes
, key_rctl_chk
);
4030 CRYPTO_SESSION_RELE(sp
);
4031 crypto_release_minor(cm
);
4033 if (real_provider
!= NULL
) {
4034 crypto_free_mech(real_provider
,
4035 allocated_by_crypto_module
, &mech
);
4036 KCF_PROV_REFRELE(real_provider
);
4039 free_crypto_key(&key
);
4044 STRUCT_FSET(sign_init
, si_return_value
, rv
);
4045 if (copyout(STRUCT_BUF(sign_init
), arg
, STRUCT_SIZE(sign_init
)) != 0) {
4053 sign(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4055 return (common_digest(dev
, arg
, mode
, crypto_sign_single
));
4060 sign_recover(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4062 return (common_digest(dev
, arg
, mode
, crypto_sign_recover_single
));
4067 verify(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4069 STRUCT_DECL(crypto_verify
, verify
);
4070 crypto_session_id_t session_id
;
4072 crypto_session_data_t
*sp
= NULL
;
4073 crypto_data_t data
, sign
;
4074 size_t datalen
, signlen
, need
= 0;
4077 boolean_t rctl_chk
= B_FALSE
;
4079 STRUCT_INIT(verify
, mode
);
4081 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4082 cmn_err(CE_WARN
, "verify: failed holding minor");
4086 if (copyin(arg
, STRUCT_BUF(verify
), STRUCT_SIZE(verify
)) != 0) {
4087 crypto_release_minor(cm
);
4091 data
.cd_raw
.iov_base
= NULL
;
4092 sign
.cd_raw
.iov_base
= NULL
;
4094 datalen
= STRUCT_FGET(verify
, cv_datalen
);
4095 signlen
= STRUCT_FGET(verify
, cv_signlen
);
4096 if (datalen
> crypto_max_buffer_len
||
4097 signlen
> crypto_max_buffer_len
) {
4098 cmn_err(CE_NOTE
, "verify: buffer greater than %ld bytes, "
4099 "pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
4100 rv
= CRYPTO_ARGUMENTS_BAD
;
4104 session_id
= STRUCT_FGET(verify
, cv_session
);
4106 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4110 need
= datalen
+ signlen
;
4111 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, need
, rctl_chk
)) !=
4117 INIT_RAW_CRYPTO_DATA(data
, datalen
);
4118 INIT_RAW_CRYPTO_DATA(sign
, signlen
);
4120 if (datalen
!= 0 && copyin(STRUCT_FGETP(verify
, cv_databuf
),
4121 data
.cd_raw
.iov_base
, datalen
) != 0) {
4126 if (signlen
!= 0 && copyin(STRUCT_FGETP(verify
, cv_signbuf
),
4127 sign
.cd_raw
.iov_base
, signlen
) != 0) {
4132 rv
= crypto_verify_single(sp
->sd_verify_ctx
, &data
, &sign
, NULL
);
4133 if (KCF_CONTEXT_DONE(rv
))
4134 sp
->sd_verify_ctx
= NULL
;
4137 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
4138 CRYPTO_SESSION_RELE(sp
);
4139 crypto_release_minor(cm
);
4141 if (data
.cd_raw
.iov_base
!= NULL
)
4142 kmem_free(data
.cd_raw
.iov_base
, datalen
);
4144 if (sign
.cd_raw
.iov_base
!= NULL
)
4145 kmem_free(sign
.cd_raw
.iov_base
, signlen
);
4150 STRUCT_FSET(verify
, cv_return_value
, rv
);
4151 if (copyout(STRUCT_BUF(verify
), arg
, STRUCT_SIZE(verify
)) != 0) {
4159 verify_recover(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4161 return (common_digest(dev
, arg
, mode
, crypto_verify_recover_single
));
4166 sign_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4168 return (sign_verify_update(dev
, arg
, mode
, crypto_sign_update
));
4173 verify_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4175 return (sign_verify_update(dev
, arg
, mode
, crypto_verify_update
));
4179 * ASSUMPTION: crypto_sign_update and crypto_verify_update structures
4180 * are identical except for field names.
4183 sign_verify_update(dev_t dev
, caddr_t arg
, int mode
,
4184 int (*update
)(crypto_context_t
, crypto_data_t
*, crypto_call_req_t
*))
4186 STRUCT_DECL(crypto_sign_update
, sign_update
);
4187 crypto_session_id_t session_id
;
4189 crypto_session_data_t
*sp
= NULL
;
4190 crypto_ctx_t
**ctxpp
;
4192 size_t datalen
, need
= 0;
4195 boolean_t rctl_chk
= B_FALSE
;
4197 STRUCT_INIT(sign_update
, mode
);
4199 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4200 cmn_err(CE_WARN
, "sign_verify_update: failed holding minor");
4204 if (copyin(arg
, STRUCT_BUF(sign_update
),
4205 STRUCT_SIZE(sign_update
)) != 0) {
4206 crypto_release_minor(cm
);
4210 data
.cd_raw
.iov_base
= NULL
;
4211 data
.cd_miscdata
= NULL
;
4213 datalen
= STRUCT_FGET(sign_update
, su_datalen
);
4214 if (datalen
> crypto_max_buffer_len
) {
4215 cmn_err(CE_NOTE
, "sign_verify_update: buffer greater than %ld "
4216 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
4217 rv
= CRYPTO_ARGUMENTS_BAD
;
4221 session_id
= STRUCT_FGET(sign_update
, su_session
);
4223 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4227 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, datalen
, rctl_chk
)) !=
4233 INIT_RAW_CRYPTO_DATA(data
, datalen
);
4235 if (datalen
!= 0 && copyin(STRUCT_FGETP(sign_update
, su_databuf
),
4236 data
.cd_raw
.iov_base
, datalen
) != 0) {
4241 ASSERT(update
== crypto_sign_update
||
4242 update
== crypto_verify_update
||
4243 update
== crypto_mac_update
);
4245 if (update
== crypto_sign_update
)
4246 ctxpp
= &sp
->sd_sign_ctx
;
4247 else if (update
== crypto_verify_update
)
4248 ctxpp
= &sp
->sd_verify_ctx
;
4250 ctxpp
= &sp
->sd_mac_ctx
;
4252 rv
= (update
)(*ctxpp
, &data
, NULL
);
4253 if (rv
!= CRYPTO_SUCCESS
)
4254 CRYPTO_CANCEL_CTX(ctxpp
);
4257 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
4258 CRYPTO_SESSION_RELE(sp
);
4259 crypto_release_minor(cm
);
4261 if (data
.cd_raw
.iov_base
!= NULL
)
4262 kmem_free(data
.cd_raw
.iov_base
, datalen
);
4267 STRUCT_FSET(sign_update
, su_return_value
, rv
);
4268 if (copyout(STRUCT_BUF(sign_update
), arg
,
4269 STRUCT_SIZE(sign_update
)) != 0) {
4277 sign_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4279 return (common_final(dev
, arg
, mode
, crypto_sign_final
));
4283 * Can't use the common final because it does a copyout of
4288 verify_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4290 STRUCT_DECL(crypto_verify_final
, verify_final
);
4291 crypto_session_id_t session_id
;
4293 crypto_session_data_t
*sp
= NULL
;
4295 size_t signlen
, need
= 0;
4298 boolean_t rctl_chk
= B_FALSE
;
4300 STRUCT_INIT(verify_final
, mode
);
4302 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4303 cmn_err(CE_WARN
, "verify_final: failed holding minor");
4307 if (copyin(arg
, STRUCT_BUF(verify_final
),
4308 STRUCT_SIZE(verify_final
)) != 0) {
4309 crypto_release_minor(cm
);
4313 sign
.cd_raw
.iov_base
= NULL
;
4315 signlen
= STRUCT_FGET(verify_final
, vf_signlen
);
4316 if (signlen
> crypto_max_buffer_len
) {
4317 cmn_err(CE_NOTE
, "verify_final: buffer greater than %ld "
4318 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
4319 rv
= CRYPTO_ARGUMENTS_BAD
;
4323 session_id
= STRUCT_FGET(verify_final
, vf_session
);
4325 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4329 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, signlen
, rctl_chk
)) !=
4335 INIT_RAW_CRYPTO_DATA(sign
, signlen
);
4337 if (signlen
!= 0 && copyin(STRUCT_FGETP(verify_final
, vf_signbuf
),
4338 sign
.cd_raw
.iov_base
, signlen
) != 0) {
4343 rv
= crypto_verify_final(sp
->sd_verify_ctx
, &sign
, NULL
);
4344 if (KCF_CONTEXT_DONE(rv
))
4345 sp
->sd_verify_ctx
= NULL
;
4348 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
4349 CRYPTO_SESSION_RELE(sp
);
4350 crypto_release_minor(cm
);
4352 if (sign
.cd_raw
.iov_base
!= NULL
)
4353 kmem_free(sign
.cd_raw
.iov_base
, signlen
);
4358 STRUCT_FSET(verify_final
, vf_return_value
, rv
);
4359 if (copyout(STRUCT_BUF(verify_final
), arg
,
4360 STRUCT_SIZE(verify_final
)) != 0) {
4368 seed_random(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4370 STRUCT_DECL(crypto_seed_random
, seed_random
);
4371 kcf_provider_desc_t
*real_provider
= NULL
;
4372 kcf_req_params_t params
;
4373 crypto_session_id_t session_id
;
4375 crypto_session_data_t
*sp
= NULL
;
4376 uchar_t
*seed_buffer
= NULL
;
4381 boolean_t rctl_chk
= B_FALSE
;
4383 STRUCT_INIT(seed_random
, mode
);
4385 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4386 cmn_err(CE_WARN
, "seed_random: failed holding minor");
4390 if (copyin(arg
, STRUCT_BUF(seed_random
),
4391 STRUCT_SIZE(seed_random
)) != 0) {
4392 crypto_release_minor(cm
);
4396 seed_len
= STRUCT_FGET(seed_random
, sr_seedlen
);
4397 if (seed_len
> crypto_max_buffer_len
) {
4398 cmn_err(CE_NOTE
, "seed_random: buffer greater than %ld "
4399 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
4400 rv
= CRYPTO_ARGUMENTS_BAD
;
4404 session_id
= STRUCT_FGET(seed_random
, sr_session
);
4406 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4410 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, seed_len
, rctl_chk
)) !=
4415 seed_buffer
= kmem_alloc(seed_len
, KM_SLEEP
);
4417 if (seed_len
!= 0 && copyin(STRUCT_FGETP(seed_random
, sr_seedbuf
),
4418 seed_buffer
, seed_len
) != 0) {
4423 if ((rv
= kcf_get_hardware_provider_nomech(
4424 CRYPTO_OPS_OFFSET(random_ops
), CRYPTO_RANDOM_OFFSET(seed_random
),
4425 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
4429 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms
, KCF_OP_RANDOM_SEED
,
4430 sp
->sd_provider_session
->ps_session
, seed_buffer
, seed_len
, 0,
4433 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
4436 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
4437 CRYPTO_SESSION_RELE(sp
);
4438 crypto_release_minor(cm
);
4440 if (real_provider
!= NULL
)
4441 KCF_PROV_REFRELE(real_provider
);
4443 if (seed_buffer
!= NULL
)
4444 kmem_free(seed_buffer
, seed_len
);
4449 STRUCT_FSET(seed_random
, sr_return_value
, rv
);
4450 if (copyout(STRUCT_BUF(seed_random
), arg
,
4451 STRUCT_SIZE(seed_random
)) != 0) {
4459 generate_random(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4461 STRUCT_DECL(crypto_generate_random
, generate_random
);
4462 kcf_provider_desc_t
*real_provider
= NULL
;
4463 kcf_req_params_t params
;
4464 crypto_session_id_t session_id
;
4466 crypto_session_data_t
*sp
= NULL
;
4467 uchar_t
*buffer
= NULL
;
4472 boolean_t rctl_chk
= B_FALSE
;
4474 STRUCT_INIT(generate_random
, mode
);
4476 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4477 cmn_err(CE_WARN
, "generate_random: failed holding minor");
4481 if (copyin(arg
, STRUCT_BUF(generate_random
),
4482 STRUCT_SIZE(generate_random
)) != 0) {
4483 crypto_release_minor(cm
);
4487 len
= STRUCT_FGET(generate_random
, gr_buflen
);
4488 if (len
> crypto_max_buffer_len
) {
4489 cmn_err(CE_NOTE
, "generate_random: buffer greater than %ld "
4490 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
4491 rv
= CRYPTO_ARGUMENTS_BAD
;
4495 session_id
= STRUCT_FGET(generate_random
, gr_session
);
4497 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4501 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, len
, rctl_chk
)) !=
4506 buffer
= kmem_alloc(len
, KM_SLEEP
);
4508 if ((rv
= kcf_get_hardware_provider_nomech(
4509 CRYPTO_OPS_OFFSET(random_ops
),
4510 CRYPTO_RANDOM_OFFSET(generate_random
), sp
->sd_provider
,
4511 &real_provider
)) != CRYPTO_SUCCESS
) {
4515 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms
, KCF_OP_RANDOM_GENERATE
,
4516 sp
->sd_provider_session
->ps_session
, buffer
, len
, 0, 0);
4518 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
4520 if (rv
== CRYPTO_SUCCESS
) {
4521 if (len
!= 0 && copyout(buffer
,
4522 STRUCT_FGETP(generate_random
, gr_buf
), len
) != 0) {
4528 CRYPTO_DECREMENT_RCTL_SESSION(sp
, need
, rctl_chk
);
4529 CRYPTO_SESSION_RELE(sp
);
4530 crypto_release_minor(cm
);
4532 if (real_provider
!= NULL
)
4533 KCF_PROV_REFRELE(real_provider
);
4535 if (buffer
!= NULL
) {
4536 /* random numbers are often used to create keys */
4538 kmem_free(buffer
, len
);
4544 STRUCT_FSET(generate_random
, gr_return_value
, rv
);
4545 if (copyout(STRUCT_BUF(generate_random
), arg
,
4546 STRUCT_SIZE(generate_random
)) != 0) {
4553 * Copyout a kernel array of attributes to user space.
4554 * u_attrs is the corresponding user space array containing
4555 * user space pointers necessary for the copyout.
4559 copyout_attributes(int mode
, caddr_t out
, uint_t count
,
4560 crypto_object_attribute_t
*k_attrs
, caddr_t u_attrs
)
4562 STRUCT_DECL(crypto_object_attribute
, oa
);
4572 STRUCT_INIT(oa
, mode
);
4574 len
= count
* STRUCT_SIZE(oa
);
4576 ASSERT(u_attrs
!= NULL
);
4578 for (i
= 0; i
< count
; i
++) {
4579 /* can this bcopy be eliminated? */
4580 bcopy(p
, STRUCT_BUF(oa
), STRUCT_SIZE(oa
));
4581 value_len
= k_attrs
[i
].oa_value_len
;
4582 STRUCT_FSET(oa
, oa_type
, k_attrs
[i
].oa_type
);
4583 STRUCT_FSET(oa
, oa_value_len
, (ssize_t
)value_len
);
4584 valuep
= STRUCT_FGETP(oa
, oa_value
);
4585 if ((valuep
!= NULL
) && (value_len
!= (size_t)-1)) {
4586 if (copyout(k_attrs
[i
].oa_value
,
4587 valuep
, value_len
) != 0) {
4592 bcopy(STRUCT_BUF(oa
), p
, STRUCT_SIZE(oa
));
4593 p
+= STRUCT_SIZE(oa
);
4595 if (copyout(u_attrs
, out
, len
)) {
4605 object_create(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4607 STRUCT_DECL(crypto_object_create
, object_create
);
4608 kcf_provider_desc_t
*real_provider
= NULL
;
4609 kcf_req_params_t params
;
4610 crypto_object_attribute_t
*k_attrs
= NULL
;
4611 crypto_session_id_t session_id
;
4613 crypto_session_data_t
*sp
= NULL
;
4614 crypto_object_id_t object_handle
;
4615 caddr_t oc_attributes
;
4616 size_t k_attrs_size
;
4617 size_t rctl_bytes
= 0;
4618 boolean_t rctl_chk
= B_FALSE
;
4623 STRUCT_INIT(object_create
, mode
);
4625 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4626 cmn_err(CE_WARN
, "object_create: failed holding minor");
4630 if (copyin(arg
, STRUCT_BUF(object_create
),
4631 STRUCT_SIZE(object_create
)) != 0) {
4632 crypto_release_minor(cm
);
4636 count
= STRUCT_FGET(object_create
, oc_count
);
4637 oc_attributes
= STRUCT_FGETP(object_create
, oc_attributes
);
4639 session_id
= STRUCT_FGET(object_create
, oc_session
);
4640 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4643 if (!copyin_attributes(mode
, sp
, count
, oc_attributes
, &k_attrs
,
4644 &k_attrs_size
, NULL
, &rv
, &error
, &rctl_bytes
,
4645 &rctl_chk
, B_TRUE
)) {
4649 if ((rv
= kcf_get_hardware_provider_nomech(
4650 CRYPTO_OPS_OFFSET(object_ops
),
4651 CRYPTO_OBJECT_OFFSET(object_create
), sp
->sd_provider
,
4652 &real_provider
)) != CRYPTO_SUCCESS
) {
4656 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_CREATE
,
4657 sp
->sd_provider_session
->ps_session
, 0, k_attrs
, count
,
4658 &object_handle
, 0, NULL
, NULL
, 0, NULL
);
4660 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
4662 if (rv
== CRYPTO_SUCCESS
)
4663 STRUCT_FSET(object_create
, oc_handle
, object_handle
);
4666 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
4668 if (k_attrs
!= NULL
)
4669 kmem_free(k_attrs
, k_attrs_size
);
4674 STRUCT_FSET(object_create
, oc_return_value
, rv
);
4675 if (copyout(STRUCT_BUF(object_create
), arg
,
4676 STRUCT_SIZE(object_create
)) != 0) {
4677 if (rv
== CRYPTO_SUCCESS
) {
4678 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
,
4679 KCF_OP_OBJECT_DESTROY
,
4680 sp
->sd_provider_session
->ps_session
, object_handle
,
4681 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
4683 (void) kcf_submit_request(real_provider
, NULL
,
4684 NULL
, ¶ms
, B_FALSE
);
4690 CRYPTO_SESSION_RELE(sp
);
4691 crypto_release_minor(cm
);
4692 if (real_provider
!= NULL
)
4693 KCF_PROV_REFRELE(real_provider
);
4699 object_copy(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4701 STRUCT_DECL(crypto_object_copy
, object_copy
);
4702 kcf_provider_desc_t
*real_provider
= NULL
;
4703 kcf_req_params_t params
;
4704 crypto_object_attribute_t
*k_attrs
= NULL
;
4705 crypto_session_id_t session_id
;
4707 crypto_session_data_t
*sp
= NULL
;
4708 crypto_object_id_t handle
, new_handle
;
4709 caddr_t oc_new_attributes
;
4710 size_t k_attrs_size
;
4711 size_t rctl_bytes
= 0;
4712 boolean_t rctl_chk
= B_FALSE
;
4717 STRUCT_INIT(object_copy
, mode
);
4719 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4720 cmn_err(CE_WARN
, "object_copy: failed holding minor");
4724 if (copyin(arg
, STRUCT_BUF(object_copy
),
4725 STRUCT_SIZE(object_copy
)) != 0) {
4726 crypto_release_minor(cm
);
4730 count
= STRUCT_FGET(object_copy
, oc_count
);
4731 oc_new_attributes
= STRUCT_FGETP(object_copy
, oc_new_attributes
);
4733 session_id
= STRUCT_FGET(object_copy
, oc_session
);
4735 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4738 if (!copyin_attributes(mode
, sp
, count
, oc_new_attributes
, &k_attrs
,
4739 &k_attrs_size
, NULL
, &rv
, &error
, &rctl_bytes
,
4740 &rctl_chk
, B_TRUE
)) {
4744 if ((rv
= kcf_get_hardware_provider_nomech(
4745 CRYPTO_OPS_OFFSET(object_ops
),
4746 CRYPTO_OBJECT_OFFSET(object_copy
), sp
->sd_provider
,
4747 &real_provider
)) != CRYPTO_SUCCESS
) {
4751 handle
= STRUCT_FGET(object_copy
, oc_handle
);
4752 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_COPY
,
4753 sp
->sd_provider_session
->ps_session
, handle
, k_attrs
, count
,
4754 &new_handle
, 0, NULL
, NULL
, 0, NULL
);
4756 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
4758 if (rv
== CRYPTO_SUCCESS
)
4759 STRUCT_FSET(object_copy
, oc_new_handle
, new_handle
);
4762 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
4764 if (k_attrs
!= NULL
)
4765 kmem_free(k_attrs
, k_attrs_size
);
4770 STRUCT_FSET(object_copy
, oc_return_value
, rv
);
4771 if (copyout(STRUCT_BUF(object_copy
), arg
,
4772 STRUCT_SIZE(object_copy
)) != 0) {
4773 if (rv
== CRYPTO_SUCCESS
) {
4774 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
,
4775 KCF_OP_OBJECT_DESTROY
,
4776 sp
->sd_provider_session
->ps_session
, new_handle
,
4777 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
4779 (void) kcf_submit_request(real_provider
, NULL
,
4780 NULL
, ¶ms
, B_FALSE
);
4786 CRYPTO_SESSION_RELE(sp
);
4787 crypto_release_minor(cm
);
4788 if (real_provider
!= NULL
)
4789 KCF_PROV_REFRELE(real_provider
);
4795 object_destroy(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4797 STRUCT_DECL(crypto_object_destroy
, object_destroy
);
4798 kcf_provider_desc_t
*real_provider
;
4799 kcf_req_params_t params
;
4800 crypto_session_id_t session_id
;
4802 crypto_session_data_t
*sp
;
4803 crypto_object_id_t handle
;
4807 STRUCT_INIT(object_destroy
, mode
);
4809 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4810 cmn_err(CE_WARN
, "object_destroy: failed holding minor");
4814 if (copyin(arg
, STRUCT_BUF(object_destroy
),
4815 STRUCT_SIZE(object_destroy
)) != 0) {
4816 crypto_release_minor(cm
);
4820 session_id
= STRUCT_FGET(object_destroy
, od_session
);
4822 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4826 if ((rv
= kcf_get_hardware_provider_nomech(
4827 CRYPTO_OPS_OFFSET(object_ops
),
4828 CRYPTO_OBJECT_OFFSET(object_destroy
), sp
->sd_provider
,
4829 &real_provider
)) != CRYPTO_SUCCESS
) {
4833 handle
= STRUCT_FGET(object_destroy
, od_handle
);
4834 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_DESTROY
,
4835 sp
->sd_provider_session
->ps_session
, handle
, NULL
, 0, NULL
, 0,
4836 NULL
, NULL
, 0, NULL
);
4838 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
4839 KCF_PROV_REFRELE(real_provider
);
4842 CRYPTO_SESSION_RELE(sp
);
4845 crypto_release_minor(cm
);
4850 STRUCT_FSET(object_destroy
, od_return_value
, rv
);
4852 if (copyout(STRUCT_BUF(object_destroy
), arg
,
4853 STRUCT_SIZE(object_destroy
)) != 0) {
4861 object_get_attribute_value(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4863 STRUCT_DECL(crypto_object_get_attribute_value
, get_attribute_value
);
4865 STRUCT_DECL(crypto_object_attribute
, oa
);
4867 /* LINTED E_FUNC_SET_NOT_USED */
4868 STRUCT_DECL(crypto_object_attribute
, oa
);
4870 kcf_provider_desc_t
*real_provider
;
4871 kcf_req_params_t params
;
4872 crypto_object_attribute_t
*k_attrs
= NULL
;
4873 crypto_session_id_t session_id
;
4875 crypto_session_data_t
*sp
= NULL
;
4876 crypto_object_id_t handle
;
4877 caddr_t og_attributes
;
4878 caddr_t u_attrs
= NULL
;
4879 size_t k_attrs_size
;
4880 size_t rctl_bytes
= 0;
4881 boolean_t rctl_chk
= B_FALSE
;
4886 STRUCT_INIT(get_attribute_value
, mode
);
4887 STRUCT_INIT(oa
, mode
);
4889 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4891 "object_get_attribute_value: failed holding minor");
4895 if (copyin(arg
, STRUCT_BUF(get_attribute_value
),
4896 STRUCT_SIZE(get_attribute_value
)) != 0) {
4897 crypto_release_minor(cm
);
4901 count
= STRUCT_FGET(get_attribute_value
, og_count
);
4902 og_attributes
= STRUCT_FGETP(get_attribute_value
, og_attributes
);
4904 session_id
= STRUCT_FGET(get_attribute_value
, og_session
);
4906 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4909 if (!copyin_attributes(mode
, sp
, count
, og_attributes
, &k_attrs
,
4910 &k_attrs_size
, &u_attrs
, &rv
, &error
, &rctl_bytes
,
4911 &rctl_chk
, B_FALSE
)) {
4915 if ((rv
= kcf_get_hardware_provider_nomech(
4916 CRYPTO_OPS_OFFSET(object_ops
),
4917 CRYPTO_OBJECT_OFFSET(object_get_attribute_value
),
4918 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
4922 handle
= STRUCT_FGET(get_attribute_value
, og_handle
);
4923 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE
,
4924 sp
->sd_provider_session
->ps_session
, handle
, k_attrs
, count
, NULL
,
4925 0, NULL
, NULL
, 0, NULL
);
4927 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
4928 KCF_PROV_REFRELE(real_provider
);
4931 if (rv
== CRYPTO_SUCCESS
|| rv
== CRYPTO_ATTRIBUTE_SENSITIVE
||
4932 rv
== CRYPTO_ATTRIBUTE_TYPE_INVALID
||
4933 rv
== CRYPTO_BUFFER_TOO_SMALL
) {
4934 error
= copyout_attributes(mode
,
4935 STRUCT_FGETP(get_attribute_value
, og_attributes
),
4936 count
, k_attrs
, u_attrs
);
4940 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
4941 CRYPTO_SESSION_RELE(sp
);
4942 crypto_release_minor(cm
);
4944 if (k_attrs
!= NULL
)
4945 kmem_free(k_attrs
, k_attrs_size
);
4947 if (u_attrs
!= NULL
)
4948 kmem_free(u_attrs
, count
* STRUCT_SIZE(oa
));
4953 STRUCT_FSET(get_attribute_value
, og_return_value
, rv
);
4954 if (copyout(STRUCT_BUF(get_attribute_value
), arg
,
4955 STRUCT_SIZE(get_attribute_value
)) != 0) {
4963 object_get_size(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
4965 STRUCT_DECL(crypto_object_get_size
, object_get_size
);
4966 kcf_provider_desc_t
*real_provider
;
4967 kcf_req_params_t params
;
4968 crypto_session_id_t session_id
;
4970 crypto_session_data_t
*sp
= NULL
;
4971 crypto_object_id_t handle
;
4976 STRUCT_INIT(object_get_size
, mode
);
4978 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
4979 cmn_err(CE_WARN
, "object_get_size: failed holding minor");
4983 if (copyin(arg
, STRUCT_BUF(object_get_size
),
4984 STRUCT_SIZE(object_get_size
)) != 0) {
4985 crypto_release_minor(cm
);
4989 session_id
= STRUCT_FGET(object_get_size
, gs_session
);
4991 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
4995 if ((rv
= kcf_get_hardware_provider_nomech(
4996 CRYPTO_OPS_OFFSET(object_ops
),
4997 CRYPTO_OBJECT_OFFSET(object_get_size
),
4998 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
5002 handle
= STRUCT_FGET(object_get_size
, gs_handle
);
5003 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_GET_SIZE
,
5004 sp
->sd_provider_session
->ps_session
, handle
, NULL
, 0, NULL
, &size
,
5005 NULL
, NULL
, 0, NULL
);
5007 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5008 KCF_PROV_REFRELE(real_provider
);
5010 if (rv
== CRYPTO_SUCCESS
) {
5011 STRUCT_FSET(object_get_size
, gs_size
, (ulong_t
)size
);
5015 crypto_release_minor(cm
);
5016 CRYPTO_SESSION_RELE(sp
);
5021 STRUCT_FSET(object_get_size
, gs_return_value
, rv
);
5022 if (copyout(STRUCT_BUF(object_get_size
), arg
,
5023 STRUCT_SIZE(object_get_size
)) != 0) {
5031 object_set_attribute_value(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5033 STRUCT_DECL(crypto_object_set_attribute_value
, set_attribute_value
);
5034 kcf_provider_desc_t
*real_provider
;
5035 kcf_req_params_t params
;
5036 crypto_object_attribute_t
*k_attrs
= NULL
;
5037 crypto_session_id_t session_id
;
5039 crypto_session_data_t
*sp
= NULL
;
5040 crypto_object_id_t object_handle
;
5041 caddr_t sa_attributes
;
5042 size_t k_attrs_size
;
5043 size_t rctl_bytes
= 0;
5044 boolean_t rctl_chk
= B_FALSE
;
5049 STRUCT_INIT(set_attribute_value
, mode
);
5051 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5053 "object_set_attribute_value: failed holding minor");
5057 if (copyin(arg
, STRUCT_BUF(set_attribute_value
),
5058 STRUCT_SIZE(set_attribute_value
)) != 0) {
5059 crypto_release_minor(cm
);
5063 count
= STRUCT_FGET(set_attribute_value
, sa_count
);
5064 sa_attributes
= STRUCT_FGETP(set_attribute_value
, sa_attributes
);
5066 session_id
= STRUCT_FGET(set_attribute_value
, sa_session
);
5068 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5071 if (!copyin_attributes(mode
, sp
, count
, sa_attributes
, &k_attrs
,
5072 &k_attrs_size
, NULL
, &rv
, &error
, &rctl_bytes
,
5073 &rctl_chk
, B_TRUE
)) {
5077 if ((rv
= kcf_get_hardware_provider_nomech(
5078 CRYPTO_OPS_OFFSET(object_ops
),
5079 CRYPTO_OBJECT_OFFSET(object_set_attribute_value
),
5080 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
5084 object_handle
= STRUCT_FGET(set_attribute_value
, sa_handle
);
5085 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE
,
5086 sp
->sd_provider_session
->ps_session
, object_handle
, k_attrs
, count
,
5087 NULL
, 0, NULL
, NULL
, 0, NULL
);
5089 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5090 KCF_PROV_REFRELE(real_provider
);
5093 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
5094 CRYPTO_SESSION_RELE(sp
);
5095 crypto_release_minor(cm
);
5097 if (k_attrs
!= NULL
)
5098 kmem_free(k_attrs
, k_attrs_size
);
5103 STRUCT_FSET(set_attribute_value
, sa_return_value
, rv
);
5104 if (copyout(STRUCT_BUF(set_attribute_value
), arg
,
5105 STRUCT_SIZE(set_attribute_value
)) != 0) {
5113 object_find_init(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5115 STRUCT_DECL(crypto_object_find_init
, find_init
);
5116 kcf_provider_desc_t
*real_provider
= NULL
;
5117 kcf_req_params_t params
;
5118 crypto_object_attribute_t
*k_attrs
= NULL
;
5119 crypto_session_id_t session_id
;
5121 crypto_session_data_t
*sp
= NULL
;
5123 size_t k_attrs_size
;
5124 size_t rctl_bytes
= 0;
5125 boolean_t rctl_chk
= B_FALSE
;
5131 STRUCT_INIT(find_init
, mode
);
5133 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5134 cmn_err(CE_WARN
, "object_find_init: failed holding minor");
5138 if (copyin(arg
, STRUCT_BUF(find_init
), STRUCT_SIZE(find_init
)) != 0) {
5139 crypto_release_minor(cm
);
5143 count
= STRUCT_FGET(find_init
, fi_count
);
5144 attributes
= STRUCT_FGETP(find_init
, fi_attributes
);
5146 session_id
= STRUCT_FGET(find_init
, fi_session
);
5148 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5151 if (!copyin_attributes(mode
, sp
, count
, attributes
, &k_attrs
,
5152 &k_attrs_size
, NULL
, &rv
, &error
, &rctl_bytes
,
5153 &rctl_chk
, B_TRUE
)) {
5157 if ((rv
= kcf_get_hardware_provider_nomech(
5158 CRYPTO_OPS_OFFSET(object_ops
),
5159 CRYPTO_OBJECT_OFFSET(object_find_init
),
5160 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
5164 /* check for an active find */
5165 if (sp
->sd_find_init_cookie
!= NULL
) {
5166 rv
= CRYPTO_OPERATION_IS_ACTIVE
;
5170 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_FIND_INIT
,
5171 sp
->sd_provider_session
->ps_session
, 0, k_attrs
, count
, NULL
, 0,
5172 &cookie
, NULL
, 0, NULL
);
5174 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5176 if (rv
== CRYPTO_SUCCESS
) {
5178 * The cookie is allocated by a provider at the start of an
5179 * object search. It is freed when the search is terminated
5180 * by a final operation, or when the session is closed.
5181 * It contains state information about which object handles
5182 * have been returned to the caller.
5184 sp
->sd_find_init_cookie
= cookie
;
5188 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
5189 CRYPTO_SESSION_RELE(sp
);
5190 crypto_release_minor(cm
);
5192 if (real_provider
!= NULL
)
5193 KCF_PROV_REFRELE(real_provider
);
5195 if (k_attrs
!= NULL
)
5196 kmem_free(k_attrs
, k_attrs_size
);
5201 STRUCT_FSET(find_init
, fi_return_value
, rv
);
5202 if (copyout(STRUCT_BUF(find_init
), arg
, STRUCT_SIZE(find_init
)) != 0) {
5210 object_find_update(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5212 STRUCT_DECL(crypto_object_find_update
, find_update
);
5213 kcf_provider_desc_t
*real_provider
;
5214 kcf_req_params_t params
;
5216 crypto_session_data_t
*sp
= NULL
;
5217 crypto_object_id_t
*buffer
= NULL
;
5218 crypto_session_id_t session_id
;
5219 size_t len
, rctl_bytes
= 0;
5220 uint_t count
, max_count
;
5222 boolean_t rctl_chk
= B_FALSE
;
5224 STRUCT_INIT(find_update
, mode
);
5226 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5227 cmn_err(CE_WARN
, "object_find_update: failed holding minor");
5231 if (copyin(arg
, STRUCT_BUF(find_update
),
5232 STRUCT_SIZE(find_update
)) != 0) {
5233 crypto_release_minor(cm
);
5237 max_count
= STRUCT_FGET(find_update
, fu_max_count
);
5238 if (max_count
> CRYPTO_MAX_FIND_COUNT
) {
5239 cmn_err(CE_NOTE
, "object_find_update: count greater than %d, "
5240 "pid = %d", CRYPTO_MAX_FIND_COUNT
, curproc
->p_pid
);
5241 rv
= CRYPTO_ARGUMENTS_BAD
;
5244 len
= max_count
* sizeof (crypto_object_id_t
);
5245 session_id
= STRUCT_FGET(find_update
, fu_session
);
5247 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5250 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, len
, rctl_chk
)) !=
5255 buffer
= kmem_alloc(len
, KM_SLEEP
);
5257 if ((rv
= kcf_get_hardware_provider_nomech(
5258 CRYPTO_OPS_OFFSET(object_ops
),
5259 CRYPTO_OBJECT_OFFSET(object_find
), sp
->sd_provider
,
5260 &real_provider
)) != CRYPTO_SUCCESS
) {
5264 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_FIND
,
5265 sp
->sd_provider_session
->ps_session
, 0, NULL
, 0, buffer
, 0,
5266 NULL
, sp
->sd_find_init_cookie
, max_count
, &count
);
5268 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5269 KCF_PROV_REFRELE(real_provider
);
5271 if (rv
== CRYPTO_SUCCESS
) {
5272 if (count
> max_count
) {
5273 /* bad bad provider */
5278 /* copyout handles */
5280 STRUCT_FGETP(find_update
, fu_handles
),
5281 count
* sizeof (crypto_object_id_t
)) != 0) {
5285 STRUCT_FSET(find_update
, fu_count
, count
);
5289 CRYPTO_DECREMENT_RCTL_SESSION(sp
, rctl_bytes
, rctl_chk
);
5290 CRYPTO_SESSION_RELE(sp
);
5291 crypto_release_minor(cm
);
5294 kmem_free(buffer
, len
);
5299 STRUCT_FSET(find_update
, fu_return_value
, rv
);
5300 if (copyout(STRUCT_BUF(find_update
), arg
,
5301 STRUCT_SIZE(find_update
)) != 0) {
5309 * Free provider-allocated storage used for find object searches.
5312 crypto_free_find_ctx(crypto_session_data_t
*sp
)
5314 kcf_provider_desc_t
*real_provider
;
5315 kcf_req_params_t params
;
5318 if ((rv
= kcf_get_hardware_provider_nomech(
5319 CRYPTO_OPS_OFFSET(object_ops
),
5320 CRYPTO_OBJECT_OFFSET(object_find_final
),
5321 sp
->sd_provider
, &real_provider
)) != CRYPTO_SUCCESS
) {
5325 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_FIND_FINAL
,
5326 sp
->sd_provider_session
->ps_session
, 0, NULL
, 0, NULL
, 0,
5327 NULL
, sp
->sd_find_init_cookie
, 0, NULL
);
5329 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5330 KCF_PROV_REFRELE(real_provider
);
5336 object_find_final(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5338 STRUCT_DECL(crypto_object_find_final
, object_find_final
);
5339 crypto_session_id_t session_id
;
5341 crypto_session_data_t
*sp
;
5345 STRUCT_INIT(object_find_final
, mode
);
5347 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5348 cmn_err(CE_WARN
, "object_find_final: failed holding minor");
5352 if (copyin(arg
, STRUCT_BUF(object_find_final
),
5353 STRUCT_SIZE(object_find_final
)) != 0) {
5354 crypto_release_minor(cm
);
5358 session_id
= STRUCT_FGET(object_find_final
, ff_session
);
5360 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5364 if ((rv
= crypto_free_find_ctx(sp
)) == CRYPTO_SUCCESS
) {
5365 sp
->sd_find_init_cookie
= NULL
;
5368 CRYPTO_SESSION_RELE(sp
);
5371 crypto_release_minor(cm
);
5376 STRUCT_FSET(object_find_final
, ff_return_value
, rv
);
5378 if (copyout(STRUCT_BUF(object_find_final
), arg
,
5379 STRUCT_SIZE(object_find_final
)) != 0) {
5387 object_generate_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5389 STRUCT_DECL(crypto_object_generate_key
, generate_key
);
5390 kcf_provider_desc_t
*real_provider
= NULL
;
5391 kcf_req_params_t params
;
5392 crypto_mechanism_t mech
;
5393 crypto_object_attribute_t
*k_attrs
= NULL
;
5394 crypto_session_id_t session_id
;
5396 crypto_session_data_t
*sp
= NULL
;
5397 crypto_object_id_t key_handle
;
5399 size_t k_attrs_size
;
5400 size_t mech_rctl_bytes
= 0, key_rctl_bytes
= 0;
5401 boolean_t mech_rctl_chk
= B_FALSE
;
5402 boolean_t key_rctl_chk
= B_FALSE
;
5406 boolean_t allocated_by_crypto_module
= B_FALSE
;
5408 STRUCT_INIT(generate_key
, mode
);
5410 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5411 cmn_err(CE_WARN
, "object_generate_key: failed holding minor");
5415 if (copyin(arg
, STRUCT_BUF(generate_key
),
5416 STRUCT_SIZE(generate_key
)) != 0) {
5417 crypto_release_minor(cm
);
5421 session_id
= STRUCT_FGET(generate_key
, gk_session
);
5423 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5427 bcopy(STRUCT_FADDR(generate_key
, gk_mechanism
), &mech
.cm_type
,
5428 sizeof (crypto_mech_type_t
));
5430 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, NULL
,
5431 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
5432 &real_provider
, CRYPTO_FG_GENERATE
)) != CRYPTO_SUCCESS
) {
5436 rv
= crypto_provider_copyin_mech_param(real_provider
,
5437 STRUCT_FADDR(generate_key
, gk_mechanism
), &mech
, mode
, &error
);
5439 if (rv
== CRYPTO_NOT_SUPPORTED
) {
5440 allocated_by_crypto_module
= B_TRUE
;
5441 if (!copyin_mech(mode
, sp
,
5442 STRUCT_FADDR(generate_key
, gk_mechanism
),
5443 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
5447 if (rv
!= CRYPTO_SUCCESS
)
5451 count
= STRUCT_FGET(generate_key
, gk_count
);
5452 attributes
= STRUCT_FGETP(generate_key
, gk_attributes
);
5453 if (!copyin_attributes(mode
, sp
, count
, attributes
, &k_attrs
,
5454 &k_attrs_size
, NULL
, &rv
, &error
, &key_rctl_bytes
,
5455 &key_rctl_chk
, B_TRUE
)) {
5459 KCF_WRAP_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_GENERATE
,
5460 sp
->sd_provider_session
->ps_session
, &mech
, k_attrs
, count
,
5461 &key_handle
, NULL
, 0, NULL
, NULL
, NULL
, 0);
5463 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5465 if (rv
== CRYPTO_SUCCESS
)
5466 STRUCT_FSET(generate_key
, gk_handle
, key_handle
);
5469 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
5470 CRYPTO_DECREMENT_RCTL_SESSION(sp
, key_rctl_bytes
, key_rctl_chk
);
5472 if (k_attrs
!= NULL
)
5473 kmem_free(k_attrs
, k_attrs_size
);
5478 STRUCT_FSET(generate_key
, gk_return_value
, rv
);
5479 if (copyout(STRUCT_BUF(generate_key
), arg
,
5480 STRUCT_SIZE(generate_key
)) != 0) {
5481 if (rv
== CRYPTO_SUCCESS
) {
5482 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
,
5483 KCF_OP_OBJECT_DESTROY
,
5484 sp
->sd_provider_session
->ps_session
, key_handle
,
5485 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
5487 (void) kcf_submit_request(real_provider
, NULL
,
5488 NULL
, ¶ms
, B_FALSE
);
5494 CRYPTO_SESSION_RELE(sp
);
5495 crypto_release_minor(cm
);
5497 if (real_provider
!= NULL
) {
5498 crypto_free_mech(real_provider
,
5499 allocated_by_crypto_module
, &mech
);
5500 KCF_PROV_REFRELE(real_provider
);
5507 nostore_generate_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5509 STRUCT_DECL(crypto_nostore_generate_key
, generate_key
);
5511 STRUCT_DECL(crypto_object_attribute
, oa
);
5513 /* LINTED E_FUNC_SET_NOT_USED */
5514 STRUCT_DECL(crypto_object_attribute
, oa
);
5516 kcf_provider_desc_t
*real_provider
= NULL
;
5517 kcf_req_params_t params
;
5518 crypto_mechanism_t mech
;
5519 crypto_object_attribute_t
*k_in_attrs
= NULL
;
5520 crypto_object_attribute_t
*k_out_attrs
= NULL
;
5521 crypto_session_id_t session_id
;
5523 crypto_session_data_t
*sp
= NULL
;
5524 caddr_t in_attributes
;
5525 caddr_t out_attributes
;
5526 size_t k_in_attrs_size
;
5527 size_t k_out_attrs_size
;
5528 size_t mech_rctl_bytes
= 0;
5529 boolean_t mech_rctl_chk
= B_FALSE
;
5530 size_t in_key_rctl_bytes
= 0, out_key_rctl_bytes
= 0;
5531 boolean_t in_key_rctl_chk
= B_FALSE
;
5532 boolean_t out_key_rctl_chk
= B_FALSE
;
5537 boolean_t allocated_by_crypto_module
= B_FALSE
;
5538 caddr_t u_attrs
= NULL
;
5540 STRUCT_INIT(generate_key
, mode
);
5541 STRUCT_INIT(oa
, mode
);
5543 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5544 cmn_err(CE_WARN
, "nostore_generate_key: failed holding minor");
5548 if (copyin(arg
, STRUCT_BUF(generate_key
),
5549 STRUCT_SIZE(generate_key
)) != 0) {
5550 crypto_release_minor(cm
);
5554 session_id
= STRUCT_FGET(generate_key
, ngk_session
);
5556 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5560 bcopy(STRUCT_FADDR(generate_key
, ngk_mechanism
), &mech
.cm_type
,
5561 sizeof (crypto_mech_type_t
));
5563 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, NULL
,
5564 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
5565 &real_provider
, CRYPTO_FG_GENERATE
)) != CRYPTO_SUCCESS
) {
5569 rv
= crypto_provider_copyin_mech_param(real_provider
,
5570 STRUCT_FADDR(generate_key
, ngk_mechanism
), &mech
, mode
, &error
);
5572 if (rv
== CRYPTO_NOT_SUPPORTED
) {
5573 allocated_by_crypto_module
= B_TRUE
;
5574 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(generate_key
,
5575 ngk_mechanism
), &mech
, &mech_rctl_bytes
,
5576 &mech_rctl_chk
, &rv
, &error
)) {
5580 if (rv
!= CRYPTO_SUCCESS
)
5584 in_count
= STRUCT_FGET(generate_key
, ngk_in_count
);
5585 in_attributes
= STRUCT_FGETP(generate_key
, ngk_in_attributes
);
5586 if (!copyin_attributes(mode
, sp
, in_count
, in_attributes
, &k_in_attrs
,
5587 &k_in_attrs_size
, NULL
, &rv
, &error
, &in_key_rctl_bytes
,
5588 &in_key_rctl_chk
, B_TRUE
)) {
5592 out_count
= STRUCT_FGET(generate_key
, ngk_out_count
);
5593 out_attributes
= STRUCT_FGETP(generate_key
, ngk_out_attributes
);
5594 if (!copyin_attributes(mode
, sp
, out_count
, out_attributes
,
5596 &k_out_attrs_size
, &u_attrs
, &rv
, &error
, &out_key_rctl_bytes
,
5597 &out_key_rctl_chk
, B_FALSE
)) {
5601 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_GENERATE
,
5602 sp
->sd_provider_session
->ps_session
, &mech
, k_in_attrs
, in_count
,
5603 NULL
, 0, NULL
, k_out_attrs
, out_count
, NULL
, 0);
5605 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5607 if (rv
== CRYPTO_SUCCESS
) {
5608 error
= copyout_attributes(mode
, out_attributes
,
5609 out_count
, k_out_attrs
, u_attrs
);
5612 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
5613 CRYPTO_DECREMENT_RCTL_SESSION(sp
, in_key_rctl_bytes
, in_key_rctl_chk
);
5614 CRYPTO_DECREMENT_RCTL_SESSION(sp
, out_key_rctl_bytes
,
5617 if (k_in_attrs
!= NULL
)
5618 kmem_free(k_in_attrs
, k_in_attrs_size
);
5619 if (k_out_attrs
!= NULL
) {
5620 bzero(k_out_attrs
, k_out_attrs_size
);
5621 kmem_free(k_out_attrs
, k_out_attrs_size
);
5624 if (u_attrs
!= NULL
)
5625 kmem_free(u_attrs
, out_count
* STRUCT_SIZE(oa
));
5630 STRUCT_FSET(generate_key
, ngk_return_value
, rv
);
5631 if (copyout(STRUCT_BUF(generate_key
), arg
,
5632 STRUCT_SIZE(generate_key
)) != 0) {
5636 CRYPTO_SESSION_RELE(sp
);
5637 crypto_release_minor(cm
);
5639 if (real_provider
!= NULL
) {
5640 crypto_free_mech(real_provider
,
5641 allocated_by_crypto_module
, &mech
);
5642 KCF_PROV_REFRELE(real_provider
);
5649 object_generate_key_pair(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5651 STRUCT_DECL(crypto_object_generate_key_pair
, generate_key_pair
);
5652 kcf_provider_desc_t
*real_provider
= NULL
;
5653 kcf_req_params_t params
;
5654 crypto_mechanism_t mech
;
5655 crypto_object_attribute_t
*k_pub_attrs
= NULL
;
5656 crypto_object_attribute_t
*k_pri_attrs
= NULL
;
5657 crypto_session_id_t session_id
;
5659 crypto_session_data_t
*sp
= NULL
;
5660 crypto_object_id_t pub_handle
;
5661 crypto_object_id_t pri_handle
;
5662 caddr_t pri_attributes
;
5663 caddr_t pub_attributes
;
5664 size_t k_pub_attrs_size
, k_pri_attrs_size
;
5665 size_t mech_rctl_bytes
= 0;
5666 boolean_t mech_rctl_chk
= B_FALSE
;
5667 size_t pub_rctl_bytes
= 0;
5668 boolean_t pub_rctl_chk
= B_FALSE
;
5669 size_t pri_rctl_bytes
= 0;
5670 boolean_t pri_rctl_chk
= B_FALSE
;
5675 boolean_t allocated_by_crypto_module
= B_FALSE
;
5677 STRUCT_INIT(generate_key_pair
, mode
);
5679 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5681 "object_generate_key_pair: failed holding minor");
5685 if (copyin(arg
, STRUCT_BUF(generate_key_pair
),
5686 STRUCT_SIZE(generate_key_pair
)) != 0) {
5687 crypto_release_minor(cm
);
5691 session_id
= STRUCT_FGET(generate_key_pair
, kp_session
);
5693 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5697 bcopy(STRUCT_FADDR(generate_key_pair
, kp_mechanism
), &mech
.cm_type
,
5698 sizeof (crypto_mech_type_t
));
5700 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, NULL
,
5701 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
5702 &real_provider
, CRYPTO_FG_GENERATE_KEY_PAIR
)) != CRYPTO_SUCCESS
) {
5706 rv
= crypto_provider_copyin_mech_param(real_provider
,
5707 STRUCT_FADDR(generate_key_pair
, kp_mechanism
), &mech
, mode
, &error
);
5709 if (rv
== CRYPTO_NOT_SUPPORTED
) {
5710 allocated_by_crypto_module
= B_TRUE
;
5711 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(generate_key_pair
,
5712 kp_mechanism
), &mech
, &mech_rctl_bytes
,
5713 &mech_rctl_chk
, &rv
, &error
)) {
5717 if (rv
!= CRYPTO_SUCCESS
)
5721 pub_count
= STRUCT_FGET(generate_key_pair
, kp_public_count
);
5722 pri_count
= STRUCT_FGET(generate_key_pair
, kp_private_count
);
5724 pub_attributes
= STRUCT_FGETP(generate_key_pair
, kp_public_attributes
);
5725 if (!copyin_attributes(mode
, sp
, pub_count
, pub_attributes
,
5726 &k_pub_attrs
, &k_pub_attrs_size
, NULL
, &rv
, &error
, &pub_rctl_bytes
,
5727 &pub_rctl_chk
, B_TRUE
)) {
5731 pri_attributes
= STRUCT_FGETP(generate_key_pair
, kp_private_attributes
);
5732 if (!copyin_attributes(mode
, sp
, pri_count
, pri_attributes
,
5733 &k_pri_attrs
, &k_pri_attrs_size
, NULL
, &rv
, &error
,
5734 &pri_rctl_bytes
, &pri_rctl_chk
, B_TRUE
)) {
5738 KCF_WRAP_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_GENERATE_PAIR
,
5739 sp
->sd_provider_session
->ps_session
, &mech
, k_pub_attrs
,
5740 pub_count
, &pub_handle
, k_pri_attrs
, pri_count
, &pri_handle
,
5743 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5745 if (rv
== CRYPTO_SUCCESS
) {
5746 STRUCT_FSET(generate_key_pair
, kp_public_handle
, pub_handle
);
5747 STRUCT_FSET(generate_key_pair
, kp_private_handle
, pri_handle
);
5751 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
5752 CRYPTO_DECREMENT_RCTL_SESSION(sp
, pub_rctl_bytes
, pub_rctl_chk
);
5753 CRYPTO_DECREMENT_RCTL_SESSION(sp
, pri_rctl_bytes
, pri_rctl_chk
);
5755 if (k_pub_attrs
!= NULL
)
5756 kmem_free(k_pub_attrs
, k_pub_attrs_size
);
5758 if (k_pri_attrs
!= NULL
)
5759 kmem_free(k_pri_attrs
, k_pri_attrs_size
);
5764 STRUCT_FSET(generate_key_pair
, kp_return_value
, rv
);
5765 if (copyout(STRUCT_BUF(generate_key_pair
), arg
,
5766 STRUCT_SIZE(generate_key_pair
)) != 0) {
5767 if (rv
== CRYPTO_SUCCESS
) {
5768 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
,
5769 KCF_OP_OBJECT_DESTROY
,
5770 sp
->sd_provider_session
->ps_session
, pub_handle
,
5771 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
5773 (void) kcf_submit_request(real_provider
, NULL
,
5774 NULL
, ¶ms
, B_FALSE
);
5776 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
,
5777 KCF_OP_OBJECT_DESTROY
,
5778 sp
->sd_provider_session
->ps_session
, pri_handle
,
5779 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
5781 (void) kcf_submit_request(real_provider
, NULL
,
5782 NULL
, ¶ms
, B_FALSE
);
5788 CRYPTO_SESSION_RELE(sp
);
5789 crypto_release_minor(cm
);
5791 if (real_provider
!= NULL
) {
5792 crypto_free_mech(real_provider
,
5793 allocated_by_crypto_module
, &mech
);
5794 KCF_PROV_REFRELE(real_provider
);
5801 nostore_generate_key_pair(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5803 STRUCT_DECL(crypto_nostore_generate_key_pair
, generate_key_pair
);
5805 STRUCT_DECL(crypto_object_attribute
, oa
);
5807 /* LINTED E_FUNC_SET_NOT_USED */
5808 STRUCT_DECL(crypto_object_attribute
, oa
);
5810 kcf_provider_desc_t
*real_provider
= NULL
;
5811 kcf_req_params_t params
;
5812 crypto_mechanism_t mech
;
5813 crypto_object_attribute_t
*k_in_pub_attrs
= NULL
;
5814 crypto_object_attribute_t
*k_in_pri_attrs
= NULL
;
5815 crypto_object_attribute_t
*k_out_pub_attrs
= NULL
;
5816 crypto_object_attribute_t
*k_out_pri_attrs
= NULL
;
5817 crypto_session_id_t session_id
;
5819 crypto_session_data_t
*sp
= NULL
;
5820 caddr_t in_pri_attributes
;
5821 caddr_t in_pub_attributes
;
5822 caddr_t out_pri_attributes
;
5823 caddr_t out_pub_attributes
;
5824 size_t k_in_pub_attrs_size
, k_in_pri_attrs_size
;
5825 size_t k_out_pub_attrs_size
, k_out_pri_attrs_size
;
5826 size_t mech_rctl_bytes
= 0;
5827 boolean_t mech_rctl_chk
= B_FALSE
;
5828 size_t in_pub_rctl_bytes
= 0;
5829 boolean_t in_pub_rctl_chk
= B_FALSE
;
5830 size_t in_pri_rctl_bytes
= 0;
5831 boolean_t in_pri_rctl_chk
= B_FALSE
;
5832 size_t out_pub_rctl_bytes
= 0;
5833 boolean_t out_pub_rctl_chk
= B_FALSE
;
5834 size_t out_pri_rctl_bytes
= 0;
5835 boolean_t out_pri_rctl_chk
= B_FALSE
;
5836 uint_t in_pub_count
;
5837 uint_t in_pri_count
;
5838 uint_t out_pub_count
;
5839 uint_t out_pri_count
;
5842 boolean_t allocated_by_crypto_module
= B_FALSE
;
5843 caddr_t u_pub_attrs
= NULL
;
5844 caddr_t u_pri_attrs
= NULL
;
5846 STRUCT_INIT(generate_key_pair
, mode
);
5847 STRUCT_INIT(oa
, mode
);
5849 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
5851 "nostore_generate_key_pair: failed holding minor");
5855 if (copyin(arg
, STRUCT_BUF(generate_key_pair
),
5856 STRUCT_SIZE(generate_key_pair
)) != 0) {
5857 crypto_release_minor(cm
);
5861 session_id
= STRUCT_FGET(generate_key_pair
, nkp_session
);
5863 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
5867 bcopy(STRUCT_FADDR(generate_key_pair
, nkp_mechanism
), &mech
.cm_type
,
5868 sizeof (crypto_mech_type_t
));
5870 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, NULL
,
5871 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
5872 &real_provider
, CRYPTO_FG_GENERATE_KEY_PAIR
)) != CRYPTO_SUCCESS
) {
5876 rv
= crypto_provider_copyin_mech_param(real_provider
,
5877 STRUCT_FADDR(generate_key_pair
, nkp_mechanism
), &mech
, mode
,
5880 if (rv
== CRYPTO_NOT_SUPPORTED
) {
5881 allocated_by_crypto_module
= B_TRUE
;
5882 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(generate_key_pair
,
5883 nkp_mechanism
), &mech
, &mech_rctl_bytes
,
5884 &mech_rctl_chk
, &rv
, &error
)) {
5888 if (rv
!= CRYPTO_SUCCESS
)
5892 in_pub_count
= STRUCT_FGET(generate_key_pair
, nkp_in_public_count
);
5893 in_pri_count
= STRUCT_FGET(generate_key_pair
, nkp_in_private_count
);
5895 in_pub_attributes
= STRUCT_FGETP(generate_key_pair
,
5896 nkp_in_public_attributes
);
5897 if (!copyin_attributes(mode
, sp
, in_pub_count
, in_pub_attributes
,
5898 &k_in_pub_attrs
, &k_in_pub_attrs_size
, NULL
, &rv
, &error
,
5899 &in_pub_rctl_bytes
, &in_pub_rctl_chk
, B_TRUE
)) {
5903 in_pri_attributes
= STRUCT_FGETP(generate_key_pair
,
5904 nkp_in_private_attributes
);
5905 if (!copyin_attributes(mode
, sp
, in_pri_count
, in_pri_attributes
,
5906 &k_in_pri_attrs
, &k_in_pri_attrs_size
, NULL
, &rv
, &error
,
5907 &in_pri_rctl_bytes
, &in_pri_rctl_chk
, B_TRUE
)) {
5911 out_pub_count
= STRUCT_FGET(generate_key_pair
, nkp_out_public_count
);
5912 out_pri_count
= STRUCT_FGET(generate_key_pair
, nkp_out_private_count
);
5914 out_pub_attributes
= STRUCT_FGETP(generate_key_pair
,
5915 nkp_out_public_attributes
);
5916 if (!copyin_attributes(mode
, sp
, out_pub_count
, out_pub_attributes
,
5917 &k_out_pub_attrs
, &k_out_pub_attrs_size
, &u_pub_attrs
, &rv
, &error
,
5918 &out_pub_rctl_bytes
, &out_pub_rctl_chk
, B_FALSE
)) {
5922 out_pri_attributes
= STRUCT_FGETP(generate_key_pair
,
5923 nkp_out_private_attributes
);
5924 if (!copyin_attributes(mode
, sp
, out_pri_count
, out_pri_attributes
,
5925 &k_out_pri_attrs
, &k_out_pri_attrs_size
, &u_pri_attrs
, &rv
, &error
,
5926 &out_pri_rctl_bytes
, &out_pri_rctl_chk
, B_FALSE
)) {
5930 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_GENERATE_PAIR
,
5931 sp
->sd_provider_session
->ps_session
, &mech
, k_in_pub_attrs
,
5932 in_pub_count
, k_in_pri_attrs
, in_pri_count
, NULL
, k_out_pub_attrs
,
5933 out_pub_count
, k_out_pri_attrs
, out_pri_count
);
5935 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
5937 if (rv
== CRYPTO_SUCCESS
) {
5938 error
= copyout_attributes(mode
, out_pub_attributes
,
5939 out_pub_count
, k_out_pub_attrs
, u_pub_attrs
);
5940 if (error
!= CRYPTO_SUCCESS
)
5942 error
= copyout_attributes(mode
, out_pri_attributes
,
5943 out_pri_count
, k_out_pri_attrs
, u_pri_attrs
);
5947 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
5948 CRYPTO_DECREMENT_RCTL_SESSION(sp
, in_pub_rctl_bytes
, in_pub_rctl_chk
);
5949 CRYPTO_DECREMENT_RCTL_SESSION(sp
, in_pri_rctl_bytes
, in_pri_rctl_chk
);
5950 CRYPTO_DECREMENT_RCTL_SESSION(sp
, out_pub_rctl_bytes
,
5952 CRYPTO_DECREMENT_RCTL_SESSION(sp
, out_pri_rctl_bytes
,
5955 if (k_in_pub_attrs
!= NULL
)
5956 kmem_free(k_in_pub_attrs
, k_in_pub_attrs_size
);
5958 if (k_in_pri_attrs
!= NULL
)
5959 kmem_free(k_in_pri_attrs
, k_in_pri_attrs_size
);
5961 if (k_out_pub_attrs
!= NULL
)
5962 kmem_free(k_out_pub_attrs
, k_out_pub_attrs_size
);
5964 if (k_out_pri_attrs
!= NULL
) {
5965 bzero(k_out_pri_attrs
, k_out_pri_attrs_size
);
5966 kmem_free(k_out_pri_attrs
, k_out_pri_attrs_size
);
5969 if (u_pub_attrs
!= NULL
)
5970 kmem_free(u_pub_attrs
, out_pub_count
* STRUCT_SIZE(oa
));
5972 if (u_pri_attrs
!= NULL
)
5973 kmem_free(u_pri_attrs
, out_pri_count
* STRUCT_SIZE(oa
));
5978 STRUCT_FSET(generate_key_pair
, nkp_return_value
, rv
);
5979 if (copyout(STRUCT_BUF(generate_key_pair
), arg
,
5980 STRUCT_SIZE(generate_key_pair
)) != 0) {
5984 CRYPTO_SESSION_RELE(sp
);
5985 crypto_release_minor(cm
);
5987 if (real_provider
!= NULL
) {
5988 crypto_free_mech(real_provider
,
5989 allocated_by_crypto_module
, &mech
);
5990 KCF_PROV_REFRELE(real_provider
);
5997 object_wrap_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
5999 STRUCT_DECL(crypto_object_wrap_key
, wrap_key
);
6000 kcf_provider_desc_t
*real_provider
= NULL
;
6001 kcf_req_params_t params
;
6002 crypto_mechanism_t mech
;
6004 crypto_session_id_t session_id
;
6006 crypto_session_data_t
*sp
= NULL
;
6007 crypto_object_id_t handle
;
6008 size_t mech_rctl_bytes
= 0, key_rctl_bytes
= 0;
6009 boolean_t mech_rctl_chk
= B_FALSE
;
6010 boolean_t key_rctl_chk
= B_FALSE
;
6011 size_t wrapped_key_rctl_bytes
= 0;
6012 boolean_t wrapped_key_rctl_chk
= B_FALSE
;
6013 size_t wrapped_key_len
, new_wrapped_key_len
;
6014 uchar_t
*wrapped_key
= NULL
;
6015 char *wrapped_key_buffer
;
6018 boolean_t allocated_by_crypto_module
= B_FALSE
;
6020 STRUCT_INIT(wrap_key
, mode
);
6022 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
6023 cmn_err(CE_WARN
, "object_wrap_key: failed holding minor");
6027 if (copyin(arg
, STRUCT_BUF(wrap_key
), STRUCT_SIZE(wrap_key
)) != 0) {
6028 crypto_release_minor(cm
);
6032 bzero(&key
, sizeof (crypto_key_t
));
6034 session_id
= STRUCT_FGET(wrap_key
, wk_session
);
6036 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
6040 bcopy(STRUCT_FADDR(wrap_key
, wk_mechanism
), &mech
.cm_type
,
6041 sizeof (crypto_mech_type_t
));
6043 /* We need the key length for provider selection so copy it in now. */
6044 if (!copyin_key(mode
, sp
, STRUCT_FADDR(wrap_key
, wk_wrapping_key
), &key
,
6045 &key_rctl_bytes
, &key_rctl_chk
, &rv
, &error
)) {
6049 wrapped_key_len
= STRUCT_FGET(wrap_key
, wk_wrapped_key_len
);
6051 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, &key
,
6052 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
6053 &real_provider
, CRYPTO_FG_WRAP
)) != CRYPTO_SUCCESS
) {
6057 rv
= crypto_provider_copyin_mech_param(real_provider
,
6058 STRUCT_FADDR(wrap_key
, wk_mechanism
), &mech
, mode
, &error
);
6060 if (rv
== CRYPTO_NOT_SUPPORTED
) {
6061 allocated_by_crypto_module
= B_TRUE
;
6062 if (!copyin_mech(mode
, sp
, STRUCT_FADDR(wrap_key
, wk_mechanism
),
6063 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
6067 if (rv
!= CRYPTO_SUCCESS
)
6072 * Don't allocate output buffer unless both buffer pointer and
6073 * buffer length are not NULL or 0 (length).
6075 wrapped_key_buffer
= STRUCT_FGETP(wrap_key
, wk_wrapped_key
);
6076 if (wrapped_key_buffer
== NULL
|| wrapped_key_len
== 0) {
6077 wrapped_key_len
= 0;
6080 if (wrapped_key_len
> crypto_max_buffer_len
) {
6081 cmn_err(CE_NOTE
, "object_wrap_key: buffer greater than %ld "
6082 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
6083 rv
= CRYPTO_ARGUMENTS_BAD
;
6087 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, wrapped_key_len
,
6088 wrapped_key_rctl_chk
)) != CRYPTO_SUCCESS
) {
6092 /* new_wrapped_key_len can be modified by the provider */
6093 wrapped_key_rctl_bytes
= new_wrapped_key_len
= wrapped_key_len
;
6094 wrapped_key
= kmem_alloc(wrapped_key_len
, KM_SLEEP
);
6096 handle
= STRUCT_FGET(wrap_key
, wk_object_handle
);
6097 KCF_WRAP_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_WRAP
,
6098 sp
->sd_provider_session
->ps_session
, &mech
, NULL
, 0, &handle
,
6099 NULL
, 0, NULL
, &key
, wrapped_key
, &new_wrapped_key_len
);
6101 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
6103 if (rv
== CRYPTO_SUCCESS
) {
6104 if (wrapped_key_len
!= 0 && copyout(wrapped_key
,
6105 wrapped_key_buffer
, new_wrapped_key_len
) != 0) {
6108 STRUCT_FSET(wrap_key
, wk_wrapped_key_len
,
6109 (ulong_t
)new_wrapped_key_len
);
6112 if (rv
== CRYPTO_BUFFER_TOO_SMALL
) {
6114 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
6115 * of section 11.2 of the pkcs11 spec. We catch it here and
6116 * provide the correct pkcs11 return value.
6118 if (STRUCT_FGETP(wrap_key
, wk_wrapped_key
) == NULL
)
6119 rv
= CRYPTO_SUCCESS
;
6120 STRUCT_FSET(wrap_key
, wk_wrapped_key_len
,
6121 (ulong_t
)new_wrapped_key_len
);
6125 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
6126 CRYPTO_DECREMENT_RCTL_SESSION(sp
, key_rctl_bytes
, key_rctl_chk
);
6127 CRYPTO_DECREMENT_RCTL_SESSION(sp
, wrapped_key_rctl_bytes
,
6128 wrapped_key_rctl_chk
);
6129 CRYPTO_SESSION_RELE(sp
);
6131 crypto_release_minor(cm
);
6133 if (real_provider
!= NULL
) {
6134 crypto_free_mech(real_provider
,
6135 allocated_by_crypto_module
, &mech
);
6136 KCF_PROV_REFRELE(real_provider
);
6139 if (wrapped_key
!= NULL
)
6140 kmem_free(wrapped_key
, wrapped_key_len
);
6142 free_crypto_key(&key
);
6147 STRUCT_FSET(wrap_key
, wk_return_value
, rv
);
6148 if (copyout(STRUCT_BUF(wrap_key
), arg
, STRUCT_SIZE(wrap_key
)) != 0) {
6156 object_unwrap_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
6158 STRUCT_DECL(crypto_object_unwrap_key
, unwrap_key
);
6159 kcf_provider_desc_t
*real_provider
= NULL
;
6160 kcf_req_params_t params
;
6161 crypto_mechanism_t mech
;
6162 crypto_key_t unwrapping_key
;
6163 crypto_session_id_t session_id
;
6165 crypto_session_data_t
*sp
= NULL
;
6166 crypto_object_id_t handle
;
6167 crypto_object_attribute_t
*k_attrs
= NULL
;
6168 size_t k_attrs_size
;
6169 size_t mech_rctl_bytes
= 0, unwrapping_key_rctl_bytes
= 0;
6170 boolean_t mech_rctl_chk
= B_FALSE
;
6171 boolean_t unwrapping_key_rctl_chk
= B_FALSE
;
6172 size_t wrapped_key_rctl_bytes
= 0, k_attrs_rctl_bytes
= 0;
6173 boolean_t wrapped_key_rctl_chk
= B_FALSE
;
6174 boolean_t k_attrs_rctl_chk
= B_FALSE
;
6175 size_t wrapped_key_len
;
6176 uchar_t
*wrapped_key
= NULL
;
6180 caddr_t uk_attributes
;
6181 boolean_t allocated_by_crypto_module
= B_FALSE
;
6183 STRUCT_INIT(unwrap_key
, mode
);
6185 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
6186 cmn_err(CE_WARN
, "object_unwrap_key: failed holding minor");
6190 if (copyin(arg
, STRUCT_BUF(unwrap_key
), STRUCT_SIZE(unwrap_key
)) != 0) {
6191 crypto_release_minor(cm
);
6195 bzero(&unwrapping_key
, sizeof (unwrapping_key
));
6197 session_id
= STRUCT_FGET(unwrap_key
, uk_session
);
6199 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
6203 bcopy(STRUCT_FADDR(unwrap_key
, uk_mechanism
), &mech
.cm_type
,
6204 sizeof (crypto_mech_type_t
));
6206 /* We need the key length for provider selection so copy it in now. */
6207 if (!copyin_key(mode
, sp
, STRUCT_FADDR(unwrap_key
, uk_unwrapping_key
),
6208 &unwrapping_key
, &unwrapping_key_rctl_bytes
,
6209 &unwrapping_key_rctl_chk
, &rv
, &error
)) {
6213 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, &unwrapping_key
,
6214 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
6215 &real_provider
, CRYPTO_FG_UNWRAP
)) != CRYPTO_SUCCESS
) {
6219 rv
= crypto_provider_copyin_mech_param(real_provider
,
6220 STRUCT_FADDR(unwrap_key
, uk_mechanism
), &mech
, mode
, &error
);
6222 if (rv
== CRYPTO_NOT_SUPPORTED
) {
6223 allocated_by_crypto_module
= B_TRUE
;
6224 if (!copyin_mech(mode
, sp
,
6225 STRUCT_FADDR(unwrap_key
, uk_mechanism
),
6226 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
6230 if (rv
!= CRYPTO_SUCCESS
)
6234 count
= STRUCT_FGET(unwrap_key
, uk_count
);
6235 uk_attributes
= STRUCT_FGETP(unwrap_key
, uk_attributes
);
6236 if (!copyin_attributes(mode
, sp
, count
, uk_attributes
, &k_attrs
,
6237 &k_attrs_size
, NULL
, &rv
, &error
, &k_attrs_rctl_bytes
,
6238 &k_attrs_rctl_chk
, B_TRUE
)) {
6242 wrapped_key_len
= STRUCT_FGET(unwrap_key
, uk_wrapped_key_len
);
6243 if (wrapped_key_len
> crypto_max_buffer_len
) {
6244 cmn_err(CE_NOTE
, "object_unwrap_key: buffer greater than %ld "
6245 "bytes, pid = %d", crypto_max_buffer_len
, curproc
->p_pid
);
6246 rv
= CRYPTO_ARGUMENTS_BAD
;
6250 if ((rv
= CRYPTO_BUFFER_CHECK(sp
, wrapped_key_len
,
6251 wrapped_key_rctl_chk
)) != CRYPTO_SUCCESS
) {
6254 wrapped_key_rctl_bytes
= wrapped_key_len
;
6255 wrapped_key
= kmem_alloc(wrapped_key_len
, KM_SLEEP
);
6257 if (wrapped_key_len
!= 0 && copyin(STRUCT_FGETP(unwrap_key
,
6258 uk_wrapped_key
), wrapped_key
, wrapped_key_len
) != 0) {
6263 /* wrapped_key_len is not modified by the unwrap operation */
6264 KCF_WRAP_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_UNWRAP
,
6265 sp
->sd_provider_session
->ps_session
, &mech
, k_attrs
, count
, &handle
,
6266 NULL
, 0, NULL
, &unwrapping_key
, wrapped_key
, &wrapped_key_len
);
6268 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
6270 if (rv
== CRYPTO_SUCCESS
)
6271 STRUCT_FSET(unwrap_key
, uk_object_handle
, handle
);
6274 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
6275 CRYPTO_DECREMENT_RCTL_SESSION(sp
, unwrapping_key_rctl_bytes
,
6276 unwrapping_key_rctl_chk
);
6277 CRYPTO_DECREMENT_RCTL_SESSION(sp
, wrapped_key_rctl_bytes
,
6278 wrapped_key_rctl_chk
);
6279 CRYPTO_DECREMENT_RCTL_SESSION(sp
, k_attrs_rctl_bytes
,
6282 if (k_attrs
!= NULL
)
6283 kmem_free(k_attrs
, k_attrs_size
);
6285 if (wrapped_key
!= NULL
)
6286 kmem_free(wrapped_key
, wrapped_key_len
);
6288 free_crypto_key(&unwrapping_key
);
6293 STRUCT_FSET(unwrap_key
, uk_return_value
, rv
);
6294 if (copyout(STRUCT_BUF(unwrap_key
), arg
,
6295 STRUCT_SIZE(unwrap_key
)) != 0) {
6296 if (rv
== CRYPTO_SUCCESS
) {
6297 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
,
6298 KCF_OP_OBJECT_DESTROY
,
6299 sp
->sd_provider_session
->ps_session
, handle
,
6300 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
6302 (void) kcf_submit_request(real_provider
, NULL
,
6303 NULL
, ¶ms
, B_FALSE
);
6309 CRYPTO_SESSION_RELE(sp
);
6310 crypto_release_minor(cm
);
6312 if (real_provider
!= NULL
) {
6313 crypto_free_mech(real_provider
,
6314 allocated_by_crypto_module
, &mech
);
6315 KCF_PROV_REFRELE(real_provider
);
6323 object_derive_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
6325 STRUCT_DECL(crypto_derive_key
, derive_key
);
6326 kcf_provider_desc_t
*real_provider
= NULL
;
6327 kcf_req_params_t params
;
6328 crypto_object_attribute_t
*k_attrs
= NULL
;
6329 crypto_mechanism_t mech
;
6330 crypto_key_t base_key
;
6331 crypto_session_id_t session_id
;
6333 crypto_session_data_t
*sp
= NULL
;
6334 crypto_object_id_t handle
;
6335 size_t k_attrs_size
;
6336 size_t key_rctl_bytes
= 0, mech_rctl_bytes
= 0;
6337 boolean_t mech_rctl_chk
= B_FALSE
;
6338 boolean_t key_rctl_chk
= B_FALSE
;
6339 size_t attributes_rctl_bytes
= 0;
6340 boolean_t attributes_rctl_chk
= B_FALSE
;
6345 boolean_t allocated_by_crypto_module
= B_FALSE
;
6346 boolean_t please_destroy_object
= B_FALSE
;
6348 STRUCT_INIT(derive_key
, mode
);
6350 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
6351 cmn_err(CE_WARN
, "object_derive_key: failed holding minor");
6355 if (copyin(arg
, STRUCT_BUF(derive_key
), STRUCT_SIZE(derive_key
)) != 0) {
6356 crypto_release_minor(cm
);
6360 bzero(&base_key
, sizeof (base_key
));
6362 session_id
= STRUCT_FGET(derive_key
, dk_session
);
6364 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
6368 bcopy(STRUCT_FADDR(derive_key
, dk_mechanism
), &mech
.cm_type
,
6369 sizeof (crypto_mech_type_t
));
6371 /* We need the key length for provider selection so copy it in now. */
6372 if (!copyin_key(mode
, sp
, STRUCT_FADDR(derive_key
, dk_base_key
),
6373 &base_key
, &key_rctl_bytes
, &key_rctl_chk
, &rv
, &error
)) {
6377 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, &base_key
,
6378 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
6379 &real_provider
, CRYPTO_FG_DERIVE
)) != CRYPTO_SUCCESS
) {
6383 rv
= crypto_provider_copyin_mech_param(real_provider
,
6384 STRUCT_FADDR(derive_key
, dk_mechanism
), &mech
, mode
, &error
);
6386 if (rv
== CRYPTO_NOT_SUPPORTED
) {
6387 allocated_by_crypto_module
= B_TRUE
;
6388 if (!copyin_mech(mode
, sp
,
6389 STRUCT_FADDR(derive_key
, dk_mechanism
),
6390 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
6394 if (rv
!= CRYPTO_SUCCESS
)
6398 count
= STRUCT_FGET(derive_key
, dk_count
);
6400 attributes
= STRUCT_FGETP(derive_key
, dk_attributes
);
6401 if (!copyin_attributes(mode
, sp
, count
, attributes
, &k_attrs
,
6402 &k_attrs_size
, NULL
, &rv
, &error
,
6403 &attributes_rctl_bytes
, &attributes_rctl_chk
, B_TRUE
)) {
6407 KCF_WRAP_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_DERIVE
,
6408 sp
->sd_provider_session
->ps_session
, &mech
, k_attrs
, count
,
6409 &handle
, NULL
, 0, NULL
, &base_key
, NULL
, NULL
);
6411 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
6413 if (rv
== CRYPTO_SUCCESS
) {
6414 STRUCT_FSET(derive_key
, dk_object_handle
, handle
);
6416 rv
= crypto_provider_copyout_mech_param(real_provider
,
6417 &mech
, STRUCT_FADDR(derive_key
, dk_mechanism
),
6420 if (rv
== CRYPTO_NOT_SUPPORTED
) {
6421 rv
= CRYPTO_SUCCESS
;
6425 if (rv
!= CRYPTO_SUCCESS
)
6426 please_destroy_object
= B_TRUE
;
6430 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
6431 CRYPTO_DECREMENT_RCTL_SESSION(sp
, key_rctl_bytes
, key_rctl_chk
);
6432 CRYPTO_DECREMENT_RCTL_SESSION(sp
, attributes_rctl_bytes
,
6433 attributes_rctl_chk
);
6435 if (k_attrs
!= NULL
)
6436 kmem_free(k_attrs
, k_attrs_size
);
6438 free_crypto_key(&base_key
);
6443 STRUCT_FSET(derive_key
, dk_return_value
, rv
);
6444 if (copyout(STRUCT_BUF(derive_key
), arg
,
6445 STRUCT_SIZE(derive_key
)) != 0) {
6446 if (rv
== CRYPTO_SUCCESS
) {
6447 please_destroy_object
= B_TRUE
;
6452 if (please_destroy_object
) {
6453 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms
, KCF_OP_OBJECT_DESTROY
,
6454 sp
->sd_provider_session
->ps_session
, handle
,
6455 NULL
, 0, NULL
, 0, NULL
, NULL
, 0, NULL
);
6457 (void) kcf_submit_request(real_provider
, NULL
,
6458 NULL
, ¶ms
, B_FALSE
);
6461 CRYPTO_SESSION_RELE(sp
);
6462 crypto_release_minor(cm
);
6464 if (real_provider
!= NULL
) {
6465 crypto_free_mech(real_provider
,
6466 allocated_by_crypto_module
, &mech
);
6467 KCF_PROV_REFRELE(real_provider
);
6474 nostore_derive_key(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
6476 STRUCT_DECL(crypto_nostore_derive_key
, derive_key
);
6478 STRUCT_DECL(crypto_object_attribute
, oa
);
6480 /* LINTED E_FUNC_SET_NOT_USED */
6481 STRUCT_DECL(crypto_object_attribute
, oa
);
6483 kcf_provider_desc_t
*real_provider
= NULL
;
6484 kcf_req_params_t params
;
6485 crypto_object_attribute_t
*k_in_attrs
= NULL
;
6486 crypto_object_attribute_t
*k_out_attrs
= NULL
;
6487 crypto_mechanism_t mech
;
6488 crypto_key_t base_key
;
6489 crypto_session_id_t session_id
;
6491 crypto_session_data_t
*sp
= NULL
;
6492 size_t k_in_attrs_size
, k_out_attrs_size
;
6493 size_t key_rctl_bytes
= 0, mech_rctl_bytes
= 0;
6494 boolean_t mech_rctl_chk
= B_FALSE
;
6495 boolean_t key_rctl_chk
= B_FALSE
;
6496 size_t in_attributes_rctl_bytes
= 0;
6497 size_t out_attributes_rctl_bytes
= 0;
6498 boolean_t in_attributes_rctl_chk
= B_FALSE
;
6499 boolean_t out_attributes_rctl_chk
= B_FALSE
;
6500 caddr_t in_attributes
, out_attributes
;
6501 uint_t in_count
, out_count
;
6504 boolean_t allocated_by_crypto_module
= B_FALSE
;
6505 caddr_t u_attrs
= NULL
;
6507 STRUCT_INIT(derive_key
, mode
);
6508 STRUCT_INIT(oa
, mode
);
6510 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
6511 cmn_err(CE_WARN
, "nostore_derive_key: failed holding minor");
6515 if (copyin(arg
, STRUCT_BUF(derive_key
), STRUCT_SIZE(derive_key
)) != 0) {
6516 crypto_release_minor(cm
);
6520 bzero(&base_key
, sizeof (base_key
));
6522 session_id
= STRUCT_FGET(derive_key
, ndk_session
);
6524 if (!get_session_ptr(session_id
, cm
, &sp
, &error
, &rv
)) {
6528 bcopy(STRUCT_FADDR(derive_key
, ndk_mechanism
), &mech
.cm_type
,
6529 sizeof (crypto_mech_type_t
));
6531 /* We need the key length for provider selection so copy it in now. */
6532 if (!copyin_key(mode
, sp
, STRUCT_FADDR(derive_key
, ndk_base_key
),
6533 &base_key
, &key_rctl_bytes
, &key_rctl_chk
, &rv
, &error
)) {
6537 if ((rv
= kcf_get_hardware_provider(mech
.cm_type
, &base_key
,
6538 CRYPTO_MECH_INVALID
, NULL
, sp
->sd_provider
,
6539 &real_provider
, CRYPTO_FG_DERIVE
)) != CRYPTO_SUCCESS
) {
6543 rv
= crypto_provider_copyin_mech_param(real_provider
,
6544 STRUCT_FADDR(derive_key
, ndk_mechanism
), &mech
, mode
, &error
);
6546 if (rv
== CRYPTO_NOT_SUPPORTED
) {
6547 allocated_by_crypto_module
= B_TRUE
;
6548 if (!copyin_mech(mode
, sp
,
6549 STRUCT_FADDR(derive_key
, ndk_mechanism
),
6550 &mech
, &mech_rctl_bytes
, &mech_rctl_chk
, &rv
, &error
)) {
6554 if (rv
!= CRYPTO_SUCCESS
)
6558 in_count
= STRUCT_FGET(derive_key
, ndk_in_count
);
6559 out_count
= STRUCT_FGET(derive_key
, ndk_out_count
);
6561 in_attributes
= STRUCT_FGETP(derive_key
, ndk_in_attributes
);
6562 if (!copyin_attributes(mode
, sp
, in_count
, in_attributes
, &k_in_attrs
,
6563 &k_in_attrs_size
, NULL
, &rv
, &error
, &in_attributes_rctl_bytes
,
6564 &in_attributes_rctl_chk
, B_TRUE
)) {
6568 out_attributes
= STRUCT_FGETP(derive_key
, ndk_out_attributes
);
6569 if (!copyin_attributes(mode
, sp
, out_count
, out_attributes
,
6570 &k_out_attrs
, &k_out_attrs_size
, &u_attrs
, &rv
, &error
,
6571 &out_attributes_rctl_bytes
,
6572 &out_attributes_rctl_chk
, B_FALSE
)) {
6576 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms
, KCF_OP_KEY_DERIVE
,
6577 sp
->sd_provider_session
->ps_session
, &mech
, k_in_attrs
, in_count
,
6578 NULL
, 0, &base_key
, k_out_attrs
, out_count
, NULL
, 0);
6580 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
, B_FALSE
);
6582 if (rv
== CRYPTO_SUCCESS
) {
6583 rv
= crypto_provider_copyout_mech_param(real_provider
,
6584 &mech
, STRUCT_FADDR(derive_key
, ndk_mechanism
),
6587 if (rv
== CRYPTO_NOT_SUPPORTED
) {
6588 rv
= CRYPTO_SUCCESS
;
6590 /* copyout the derived secret */
6591 if (copyout_attributes(mode
, out_attributes
, out_count
,
6592 k_out_attrs
, u_attrs
) != 0)
6597 CRYPTO_DECREMENT_RCTL_SESSION(sp
, mech_rctl_bytes
, mech_rctl_chk
);
6598 CRYPTO_DECREMENT_RCTL_SESSION(sp
, key_rctl_bytes
, key_rctl_chk
);
6599 CRYPTO_DECREMENT_RCTL_SESSION(sp
, in_attributes_rctl_bytes
,
6600 in_attributes_rctl_chk
);
6601 CRYPTO_DECREMENT_RCTL_SESSION(sp
, out_attributes_rctl_bytes
,
6602 out_attributes_rctl_chk
);
6604 if (k_in_attrs
!= NULL
)
6605 kmem_free(k_in_attrs
, k_in_attrs_size
);
6606 if (k_out_attrs
!= NULL
) {
6607 bzero(k_out_attrs
, k_out_attrs_size
);
6608 kmem_free(k_out_attrs
, k_out_attrs_size
);
6611 if (u_attrs
!= NULL
)
6612 kmem_free(u_attrs
, out_count
* STRUCT_SIZE(oa
));
6614 free_crypto_key(&base_key
);
6619 STRUCT_FSET(derive_key
, ndk_return_value
, rv
);
6620 if (copyout(STRUCT_BUF(derive_key
), arg
,
6621 STRUCT_SIZE(derive_key
)) != 0) {
6625 CRYPTO_SESSION_RELE(sp
);
6626 crypto_release_minor(cm
);
6628 if (real_provider
!= NULL
) {
6629 crypto_free_mech(real_provider
,
6630 allocated_by_crypto_module
, &mech
);
6631 KCF_PROV_REFRELE(real_provider
);
6637 get_provider_by_mech(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
6639 _NOTE(ARGUNUSED(mode
, rval
))
6640 kcf_mech_entry_t
*me
;
6641 kcf_provider_desc_t
*pd
;
6643 crypto_by_mech_t mech
;
6644 crypto_provider_session_t
*ps
;
6648 if ((cm
= crypto_hold_minor(getminor(dev
))) == NULL
) {
6649 cmn_err(CE_WARN
, "get_provider_by_mech: failed holding minor");
6653 bzero(&key
, sizeof (key
));
6654 key
.ck_format
= CRYPTO_KEY_RAW
;
6656 if (copyin(arg
, &mech
, sizeof (mech
)) != 0) {
6657 crypto_release_minor(cm
);
6661 key
.ck_length
= mech
.mech_keylen
;
6662 /* pd is returned held */
6663 if ((pd
= kcf_get_mech_provider(mech
.mech_type
, &key
, &me
, &error
,
6664 NULL
, mech
.mech_fg
, 0)) == NULL
) {
6669 /* don't want to allow direct access to software providers */
6670 if (pd
->pd_prov_type
== CRYPTO_SW_PROVIDER
) {
6671 rv
= CRYPTO_MECHANISM_INVALID
;
6672 KCF_PROV_REFRELE(pd
);
6673 cmn_err(CE_WARN
, "software mech_type given");
6677 mutex_enter(&cm
->cm_lock
);
6678 if ((rv
= crypto_create_provider_session(cm
, pd
, pd
->pd_sid
, &ps
, NULL
))
6680 rv
= crypto_create_session_ptr(cm
, pd
, ps
, &mech
.session_id
);
6682 mutex_exit(&cm
->cm_lock
);
6684 crypto_release_minor(cm
);
6686 if (copyout(&mech
, arg
, sizeof (mech
)) != 0)
6694 crypto_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*c
,
6697 #define ARG ((caddr_t)arg)
6700 case CRYPTO_GET_FUNCTION_LIST
:
6701 return (get_function_list(dev
, ARG
, mode
, rval
));
6703 case CRYPTO_GET_MECHANISM_NUMBER
:
6704 return (get_mechanism_number(dev
, ARG
, mode
, rval
));
6706 case CRYPTO_GET_MECHANISM_LIST
:
6707 return (get_mechanism_list(dev
, ARG
, mode
, rval
));
6709 case CRYPTO_GET_ALL_MECHANISM_INFO
:
6710 return (get_all_mechanism_info(dev
, ARG
, mode
, rval
));
6712 case CRYPTO_GET_PROVIDER_LIST
:
6713 return (get_provider_list(dev
, ARG
, mode
, rval
));
6715 case CRYPTO_GET_PROVIDER_BY_MECH
:
6716 return (get_provider_by_mech(dev
, ARG
, mode
, rval
));
6718 case CRYPTO_GET_PROVIDER_INFO
:
6719 return (get_provider_info(dev
, ARG
, mode
, rval
));
6721 case CRYPTO_GET_PROVIDER_MECHANISMS
:
6722 return (get_provider_mechanisms(dev
, ARG
, mode
, rval
));
6724 case CRYPTO_GET_PROVIDER_MECHANISM_INFO
:
6725 return (get_provider_mechanism_info(dev
, ARG
, mode
, rval
));
6727 case CRYPTO_OPEN_SESSION
:
6728 return (open_session(dev
, ARG
, mode
, rval
));
6730 case CRYPTO_CLOSE_SESSION
:
6731 return (close_session(dev
, ARG
, mode
, rval
));
6733 case CRYPTO_ENCRYPT_INIT
:
6734 return (encrypt_init(dev
, ARG
, mode
, rval
));
6736 case CRYPTO_DECRYPT_INIT
:
6737 return (decrypt_init(dev
, ARG
, mode
, rval
));
6739 case CRYPTO_ENCRYPT
:
6740 return (encrypt(dev
, ARG
, mode
, rval
));
6742 case CRYPTO_DECRYPT
:
6743 return (decrypt(dev
, ARG
, mode
, rval
));
6745 case CRYPTO_ENCRYPT_UPDATE
:
6746 return (encrypt_update(dev
, ARG
, mode
, rval
));
6748 case CRYPTO_DECRYPT_UPDATE
:
6749 return (decrypt_update(dev
, ARG
, mode
, rval
));
6751 case CRYPTO_ENCRYPT_FINAL
:
6752 return (encrypt_final(dev
, ARG
, mode
, rval
));
6754 case CRYPTO_DECRYPT_FINAL
:
6755 return (decrypt_final(dev
, ARG
, mode
, rval
));
6757 case CRYPTO_DIGEST_INIT
:
6758 return (digest_init(dev
, ARG
, mode
, rval
));
6761 return (digest(dev
, ARG
, mode
, rval
));
6763 case CRYPTO_DIGEST_UPDATE
:
6764 return (digest_update(dev
, ARG
, mode
, rval
));
6766 case CRYPTO_DIGEST_KEY
:
6767 return (digest_key(dev
, ARG
, mode
, rval
));
6769 case CRYPTO_DIGEST_FINAL
:
6770 return (digest_final(dev
, ARG
, mode
, rval
));
6772 case CRYPTO_SIGN_INIT
:
6773 return (sign_init(dev
, ARG
, mode
, rval
));
6776 return (sign(dev
, ARG
, mode
, rval
));
6778 case CRYPTO_SIGN_UPDATE
:
6779 return (sign_update(dev
, ARG
, mode
, rval
));
6781 case CRYPTO_SIGN_FINAL
:
6782 return (sign_final(dev
, ARG
, mode
, rval
));
6784 case CRYPTO_SIGN_RECOVER_INIT
:
6785 return (sign_recover_init(dev
, ARG
, mode
, rval
));
6787 case CRYPTO_SIGN_RECOVER
:
6788 return (sign_recover(dev
, ARG
, mode
, rval
));
6790 case CRYPTO_VERIFY_INIT
:
6791 return (verify_init(dev
, ARG
, mode
, rval
));
6794 return (verify(dev
, ARG
, mode
, rval
));
6796 case CRYPTO_VERIFY_UPDATE
:
6797 return (verify_update(dev
, ARG
, mode
, rval
));
6799 case CRYPTO_VERIFY_FINAL
:
6800 return (verify_final(dev
, ARG
, mode
, rval
));
6802 case CRYPTO_VERIFY_RECOVER_INIT
:
6803 return (verify_recover_init(dev
, ARG
, mode
, rval
));
6805 case CRYPTO_VERIFY_RECOVER
:
6806 return (verify_recover(dev
, ARG
, mode
, rval
));
6808 case CRYPTO_MAC_INIT
:
6809 return (mac_init(dev
, ARG
, mode
, rval
));
6812 return (mac(dev
, ARG
, mode
, rval
));
6814 case CRYPTO_MAC_UPDATE
:
6815 return (mac_update(dev
, ARG
, mode
, rval
));
6817 case CRYPTO_MAC_FINAL
:
6818 return (mac_final(dev
, ARG
, mode
, rval
));
6820 case CRYPTO_SET_PIN
:
6821 return (set_pin(dev
, ARG
, mode
, rval
));
6824 return (login(dev
, ARG
, mode
, rval
));
6827 return (logout(dev
, ARG
, mode
, rval
));
6829 case CRYPTO_SEED_RANDOM
:
6830 return (seed_random(dev
, ARG
, mode
, rval
));
6832 case CRYPTO_GENERATE_RANDOM
:
6833 return (generate_random(dev
, ARG
, mode
, rval
));
6835 case CRYPTO_OBJECT_CREATE
:
6836 return (object_create(dev
, ARG
, mode
, rval
));
6838 case CRYPTO_OBJECT_COPY
:
6839 return (object_copy(dev
, ARG
, mode
, rval
));
6841 case CRYPTO_OBJECT_DESTROY
:
6842 return (object_destroy(dev
, ARG
, mode
, rval
));
6844 case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE
:
6845 return (object_get_attribute_value(dev
, ARG
, mode
, rval
));
6847 case CRYPTO_OBJECT_GET_SIZE
:
6848 return (object_get_size(dev
, ARG
, mode
, rval
));
6850 case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE
:
6851 return (object_set_attribute_value(dev
, ARG
, mode
, rval
));
6853 case CRYPTO_OBJECT_FIND_INIT
:
6854 return (object_find_init(dev
, ARG
, mode
, rval
));
6856 case CRYPTO_OBJECT_FIND_UPDATE
:
6857 return (object_find_update(dev
, ARG
, mode
, rval
));
6859 case CRYPTO_OBJECT_FIND_FINAL
:
6860 return (object_find_final(dev
, ARG
, mode
, rval
));
6862 case CRYPTO_GENERATE_KEY
:
6863 return (object_generate_key(dev
, ARG
, mode
, rval
));
6865 case CRYPTO_GENERATE_KEY_PAIR
:
6866 return (object_generate_key_pair(dev
, ARG
, mode
, rval
));
6868 case CRYPTO_WRAP_KEY
:
6869 return (object_wrap_key(dev
, ARG
, mode
, rval
));
6871 case CRYPTO_UNWRAP_KEY
:
6872 return (object_unwrap_key(dev
, ARG
, mode
, rval
));
6874 case CRYPTO_DERIVE_KEY
:
6875 return (object_derive_key(dev
, ARG
, mode
, rval
));
6877 case CRYPTO_NOSTORE_GENERATE_KEY
:
6878 return (nostore_generate_key(dev
, ARG
, mode
, rval
));
6880 case CRYPTO_NOSTORE_GENERATE_KEY_PAIR
:
6881 return (nostore_generate_key_pair(dev
, ARG
, mode
, rval
));
6883 case CRYPTO_NOSTORE_DERIVE_KEY
:
6884 return (nostore_derive_key(dev
, ARG
, mode
, rval
));
6890 * Check for the project.max-crypto-memory resource control.
6893 crypto_buffer_check(size_t need
)
6898 return (CRYPTO_SUCCESS
);
6900 mutex_enter(&curproc
->p_lock
);
6901 kpj
= curproc
->p_task
->tk_proj
;
6902 mutex_enter(&(kpj
->kpj_data
.kpd_crypto_lock
));
6904 if (kpj
->kpj_data
.kpd_crypto_mem
+ need
>
6905 kpj
->kpj_data
.kpd_crypto_mem_ctl
) {
6906 if (rctl_test(rc_project_crypto_mem
,
6907 kpj
->kpj_rctls
, curproc
, need
, 0) & RCT_DENY
) {
6908 mutex_exit(&(kpj
->kpj_data
.kpd_crypto_lock
));
6909 mutex_exit(&curproc
->p_lock
);
6910 return (CRYPTO_HOST_MEMORY
);
6914 kpj
->kpj_data
.kpd_crypto_mem
+= need
;
6915 mutex_exit(&(kpj
->kpj_data
.kpd_crypto_lock
));
6917 curproc
->p_crypto_mem
+= need
;
6918 mutex_exit(&curproc
->p_lock
);
6920 return (CRYPTO_SUCCESS
);