xref: /illumos-gate/usr/src/uts/common/crypto/io/crypto.c (revision a92282e44f968185a6bba094d1e5fece2da819cf)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
24  * Copyright 2018, Joyent, Inc.
25  */
26 
27 
28 /*
29  * The ioctl interface for cryptographic commands.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/modctl.h>
34 #include <sys/conf.h>
35 #include <sys/stat.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/kmem.h>
39 #include <sys/errno.h>
40 #include <sys/ksynch.h>
41 #include <sys/file.h>
42 #include <sys/open.h>
43 #include <sys/cred.h>
44 #include <sys/proc.h>
45 #include <sys/task.h>
46 #include <sys/mkdev.h>
47 #include <sys/model.h>
48 #include <sys/sysmacros.h>
49 #include <sys/crypto/common.h>
50 #include <sys/crypto/api.h>
51 #include <sys/crypto/impl.h>
52 #include <sys/crypto/sched_impl.h>
53 #include <sys/crypto/ioctl.h>
54 
55 extern int kcf_des3_threshold;
56 extern int kcf_aes_threshold;
57 extern int kcf_rc4_threshold;
58 extern int kcf_md5_threshold;
59 extern int kcf_sha1_threshold;
60 
61 /*
62  * Locking notes:
63  *
64  * crypto_locks protects the global array of minor structures.
65  * crypto_locks is an array of locks indexed by the cpuid. A reader needs
66  * to hold a single lock while a writer needs to hold all locks.
67  * krwlock_t is not an option here because the hold time
68  * is very small for these locks.
69  *
70  * The fields in the minor structure are protected by the cm_lock member
71  * of the minor structure. The cm_cv is used to signal decrements
72  * in the cm_refcnt, and is used with the cm_lock.
73  *
74  * The locking order is crypto_locks followed by cm_lock.
75  */
76 
77 /*
78  * DDI entry points.
79  */
80 static int crypto_attach(dev_info_t *, ddi_attach_cmd_t);
81 static int crypto_detach(dev_info_t *, ddi_detach_cmd_t);
82 static int crypto_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
83 static int crypto_open(dev_t *, int, int, cred_t *);
84 static int crypto_close(dev_t, int, int, cred_t *);
85 static int crypto_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
86 
87 static int cipher_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
88     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
89     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
90 
91 static int common_digest(dev_t, caddr_t, int, int (*)(crypto_context_t,
92     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
93 
94 static int cipher(dev_t, caddr_t, int, int (*)(crypto_context_t,
95     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
96 
97 static int cipher_update(dev_t, caddr_t, int, int (*)(crypto_context_t,
98     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
99 
100 static int common_final(dev_t, caddr_t, int, int (*)(crypto_context_t,
101     crypto_data_t *, crypto_call_req_t *));
102 
103 static int sign_verify_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
104     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
105     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
106 
107 static int sign_verify_update(dev_t dev, caddr_t arg, int mode,
108     int (*)(crypto_context_t, crypto_data_t *, crypto_call_req_t *));
109 
110 static void crypto_release_provider_session(crypto_minor_t *,
111     crypto_provider_session_t *);
112 static int crypto_buffer_check(size_t);
113 static int crypto_free_find_ctx(crypto_session_data_t *);
114 static int crypto_get_provider_list(crypto_minor_t *, uint_t *,
115     crypto_provider_entry_t **, boolean_t);
116 
117 static int crypto_create_provider_session(crypto_minor_t *,
118     kcf_provider_desc_t *, crypto_session_id_t, crypto_provider_session_t **,
119     kcf_provider_desc_t *);
120 static int crypto_create_session_ptr(crypto_minor_t *, kcf_provider_desc_t *,
121     crypto_provider_session_t *, crypto_session_id_t *);
122 
123 /* number of minor numbers to allocate at a time */
124 #define	CRYPTO_MINOR_CHUNK	16
125 
126 /*
127  * There are two limits associated with kernel memory. The first,
128  * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be
129  * allocated for a single copyin/copyout buffer. The second limit is
130  * the total number of bytes that can be allocated by a process
131  * for copyin/copyout buffers. The latter is enforced by the
132  * project.max-crypto-memory resource control.
133  */
134 
135 #define	CRYPTO_MAX_BUFFER_LEN	(2 * 1024 * 1024)
136 #define	CRYPTO_MAX_FIND_COUNT	512
137 
138 /*
139  * We preapprove some bytes for each session to avoid making the costly
140  * crypto_buffer_check() calls. The preapproval is done when a new session
141  * is created and that cost is amortized over later crypto calls.
142  * Most applications create a session and then do a bunch of crypto calls
143  * in that session. So, they benefit from this optimization.
144  *
145  * Note that we may hit the project.max-crypto-memory limit a bit sooner
146  * because of this preapproval. But it is acceptable since the preapproved
147  * amount is insignificant compared to the default max-crypto-memory limit
148  * which is quarter of the machine's memory. The preapproved amount is
149  * roughly 2 * 16K(maximum SSL record size).
150  */
151 #define	CRYPTO_PRE_APPROVED_LIMIT	(32 * 1024)
152 
153 /* The session table grows by CRYPTO_SESSION_CHUNK increments */
154 #define	CRYPTO_SESSION_CHUNK	100
155 
156 size_t crypto_max_buffer_len = CRYPTO_MAX_BUFFER_LEN;
157 size_t crypto_pre_approved_limit = CRYPTO_PRE_APPROVED_LIMIT;
158 
159 #define	INIT_RAW_CRYPTO_DATA(data, len)				\
160 	(data).cd_format = CRYPTO_DATA_RAW;			\
161 	(data).cd_raw.iov_base = (len > 0) ? kmem_alloc(len, KM_SLEEP) : NULL; \
162 	(data).cd_raw.iov_len = len;				\
163 	(data).cd_offset = 0;					\
164 	(data).cd_length = len;
165 
166 static struct kmem_cache *crypto_session_cache;
167 static crypto_minor_t **crypto_minors = NULL;
168 static dev_info_t *crypto_dip = NULL;
169 static minor_t crypto_minor_chunk = CRYPTO_MINOR_CHUNK;
170 static minor_t crypto_minors_table_count = 0;
171 
172 /*
173  * Minors are started from 1 because vmem_alloc()
174  * returns 0 in case of failure.
175  */
176 static vmem_t *crypto_arena = NULL;	/* Arena for device minors */
177 static minor_t crypto_minors_count = 0;
178 static kcf_lock_withpad_t *crypto_locks;
179 
180 #define	CRYPTO_ENTER_ALL_LOCKS()		\
181 	for (i = 0; i < max_ncpus; i++)		\
182 		mutex_enter(&crypto_locks[i].kl_lock);
183 
184 #define	CRYPTO_EXIT_ALL_LOCKS()			\
185 	for (i = 0; i < max_ncpus; i++)		\
186 		mutex_exit(&crypto_locks[i].kl_lock);
187 
188 #define	RETURN_LIST			B_TRUE
189 #define	DONT_RETURN_LIST		B_FALSE
190 
191 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
192 #define	CRYPTO_RANDOM_OFFSET(f)		offsetof(crypto_random_number_ops_t, f)
193 #define	CRYPTO_SESSION_OFFSET(f)	offsetof(crypto_session_ops_t, f)
194 #define	CRYPTO_OBJECT_OFFSET(f)		offsetof(crypto_object_ops_t, f)
195 #define	CRYPTO_PROVIDER_OFFSET(f)	\
196 	offsetof(crypto_provider_management_ops_t, f)
197 
198 #define	CRYPTO_CANCEL_CTX(spp) {	\
199 	crypto_cancel_ctx(*(spp));	\
200 	*(spp) = NULL;			\
201 }
202 
203 #define	CRYPTO_CANCEL_ALL_CTX(sp) {				\
204 	if ((sp)->sd_digest_ctx != NULL) {			\
205 		crypto_cancel_ctx((sp)->sd_digest_ctx);		\
206 		(sp)->sd_digest_ctx = NULL;			\
207 	}							\
208 	if ((sp)->sd_encr_ctx != NULL) {			\
209 		crypto_cancel_ctx((sp)->sd_encr_ctx);		\
210 		(sp)->sd_encr_ctx = NULL;			\
211 	}							\
212 	if ((sp)->sd_decr_ctx != NULL) {			\
213 		crypto_cancel_ctx((sp)->sd_decr_ctx);		\
214 		(sp)->sd_decr_ctx = NULL;			\
215 	}							\
216 	if ((sp)->sd_sign_ctx != NULL) {			\
217 		crypto_cancel_ctx((sp)->sd_sign_ctx);		\
218 		(sp)->sd_sign_ctx = NULL;			\
219 	}							\
220 	if ((sp)->sd_verify_ctx != NULL) {			\
221 		crypto_cancel_ctx((sp)->sd_verify_ctx);		\
222 		(sp)->sd_verify_ctx = NULL;			\
223 	}							\
224 	if ((sp)->sd_sign_recover_ctx != NULL) {		\
225 		crypto_cancel_ctx((sp)->sd_sign_recover_ctx);	\
226 		(sp)->sd_sign_recover_ctx = NULL;		\
227 	}							\
228 	if ((sp)->sd_verify_recover_ctx != NULL) {		\
229 		crypto_cancel_ctx((sp)->sd_verify_recover_ctx);	\
230 		(sp)->sd_verify_recover_ctx = NULL;		\
231 	}							\
232 	if ((sp)->sd_mac_ctx != NULL) {		\
233 		crypto_cancel_ctx((sp)->sd_mac_ctx);	\
234 		(sp)->sd_mac_ctx = NULL;		\
235 	}							\
236 }
237 
238 #define	CRYPTO_DECREMENT_RCTL(val)	if ((val) != 0) {	\
239 	kproject_t *projp;					\
240 	mutex_enter(&curproc->p_lock);				\
241 	projp = curproc->p_task->tk_proj;			\
242 	ASSERT(projp != NULL);					\
243 	mutex_enter(&(projp->kpj_data.kpd_crypto_lock));	\
244 	projp->kpj_data.kpd_crypto_mem -= (val);		\
245 	mutex_exit(&(projp->kpj_data.kpd_crypto_lock));		\
246 	curproc->p_crypto_mem -= (val);				\
247 	mutex_exit(&curproc->p_lock);				\
248 }
249 
250 /*
251  * We do not need to hold sd_lock in the macros below
252  * as they are called after doing a get_session_ptr() which
253  * sets the CRYPTO_SESSION_IS_BUSY flag.
254  */
255 #define	CRYPTO_DECREMENT_RCTL_SESSION(sp, val, rctl_chk)	\
256 	if (((val) != 0) && ((sp) != NULL)) {			\
257 		ASSERT(((sp)->sd_flags & CRYPTO_SESSION_IS_BUSY) != 0);	\
258 		if (rctl_chk) {				\
259 			CRYPTO_DECREMENT_RCTL(val);		\
260 		} else {					\
261 			(sp)->sd_pre_approved_amount += (val);	\
262 		}						\
263 	}
264 
265 #define	CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)		\
266 	((sp->sd_pre_approved_amount >= need) ?			\
267 	(sp->sd_pre_approved_amount -= need,			\
268 	    rctl_chk = B_FALSE, CRYPTO_SUCCESS) :		\
269 	    (rctl_chk = B_TRUE, crypto_buffer_check(need)))
270 
271 /*
272  * Module linkage.
273  */
274 static struct cb_ops cbops = {
275 	crypto_open,		/* cb_open */
276 	crypto_close,		/* cb_close */
277 	nodev,			/* cb_strategy */
278 	nodev,			/* cb_print */
279 	nodev,			/* cb_dump */
280 	nodev,			/* cb_read */
281 	nodev,			/* cb_write */
282 	crypto_ioctl,		/* cb_ioctl */
283 	nodev,			/* cb_devmap */
284 	nodev,			/* cb_mmap */
285 	nodev,			/* cb_segmap */
286 	nochpoll,		/* cb_chpoll */
287 	ddi_prop_op,		/* cb_prop_op */
288 	NULL,			/* cb_streamtab */
289 	D_MP,			/* cb_flag */
290 	CB_REV,			/* cb_rev */
291 	nodev,			/* cb_aread */
292 	nodev,			/* cb_awrite */
293 };
294 
295 static struct dev_ops devops = {
296 	DEVO_REV,		/* devo_rev */
297 	0,			/* devo_refcnt */
298 	crypto_getinfo,		/* devo_getinfo */
299 	nulldev,		/* devo_identify */
300 	nulldev,		/* devo_probe */
301 	crypto_attach,		/* devo_attach */
302 	crypto_detach,		/* devo_detach */
303 	nodev,			/* devo_reset */
304 	&cbops,			/* devo_cb_ops */
305 	NULL,			/* devo_bus_ops */
306 	NULL,			/* devo_power */
307 	ddi_quiesce_not_needed,		/* devo_quiesce */
308 };
309 
310 static struct modldrv modldrv = {
311 	&mod_driverops,					/* drv_modops */
312 	"Cryptographic Library Interface",	/* drv_linkinfo */
313 	&devops,
314 };
315 
316 static struct modlinkage modlinkage = {
317 	MODREV_1,		/* ml_rev */
318 	&modldrv,		/* ml_linkage */
319 	NULL
320 };
321 
322 /*
323  * DDI entry points.
324  */
325 int
326 _init(void)
327 {
328 	return (mod_install(&modlinkage));
329 }
330 
331 int
332 _fini(void)
333 {
334 	return (mod_remove(&modlinkage));
335 }
336 
337 int
338 _info(struct modinfo *modinfop)
339 {
340 	return (mod_info(&modlinkage, modinfop));
341 }
342 
343 /* ARGSUSED */
344 static int
345 crypto_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
346 {
347 	switch (cmd) {
348 	case DDI_INFO_DEVT2DEVINFO:
349 		*result = crypto_dip;
350 		return (DDI_SUCCESS);
351 
352 	case DDI_INFO_DEVT2INSTANCE:
353 		*result = (void *)0;
354 		return (DDI_SUCCESS);
355 	}
356 	return (DDI_FAILURE);
357 }
358 
359 static int
360 crypto_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
361 {
362 	int i;
363 
364 	if (cmd != DDI_ATTACH) {
365 		return (DDI_FAILURE);
366 	}
367 
368 	if (ddi_get_instance(dip) != 0) {
369 		/* we only allow instance 0 to attach */
370 		return (DDI_FAILURE);
371 	}
372 
373 	crypto_session_cache = kmem_cache_create("crypto_session_cache",
374 	    sizeof (crypto_session_data_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
375 
376 	if (crypto_session_cache == NULL)
377 		return (DDI_FAILURE);
378 
379 	/* create the minor node */
380 	if (ddi_create_minor_node(dip, "crypto", S_IFCHR, 0,
381 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
382 		kmem_cache_destroy(crypto_session_cache);
383 		crypto_session_cache = NULL;
384 		cmn_err(CE_WARN, "crypto_attach: failed creating minor node");
385 		ddi_remove_minor_node(dip, NULL);
386 		return (DDI_FAILURE);
387 	}
388 
389 	crypto_locks = kmem_zalloc(max_ncpus * sizeof (kcf_lock_withpad_t),
390 	    KM_SLEEP);
391 	for (i = 0; i < max_ncpus; i++)
392 		mutex_init(&crypto_locks[i].kl_lock, NULL, MUTEX_DRIVER, NULL);
393 
394 	crypto_dip = dip;
395 
396 	/* allocate integer space for minor numbers */
397 	crypto_arena = vmem_create("crypto", (void *)1,
398 	    CRYPTO_MINOR_CHUNK, 1, NULL, NULL, NULL, 0,
399 	    VM_SLEEP | VMC_IDENTIFIER);
400 
401 	return (DDI_SUCCESS);
402 }
403 
404 static int
405 crypto_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
406 {
407 	minor_t i;
408 	kcf_lock_withpad_t *mp;
409 
410 	if (cmd != DDI_DETACH)
411 		return (DDI_FAILURE);
412 
413 	mp = &crypto_locks[CPU_SEQID];
414 	mutex_enter(&mp->kl_lock);
415 
416 	/* check if device is open */
417 	for (i = 0; i < crypto_minors_table_count; i++) {
418 		if (crypto_minors[i] != NULL) {
419 			mutex_exit(&mp->kl_lock);
420 			return (DDI_FAILURE);
421 		}
422 	}
423 	mutex_exit(&mp->kl_lock);
424 
425 	crypto_dip = NULL;
426 	ddi_remove_minor_node(dip, NULL);
427 
428 	kmem_cache_destroy(crypto_session_cache);
429 	crypto_session_cache = NULL;
430 
431 	kmem_free(crypto_minors,
432 	    sizeof (crypto_minor_t *) * crypto_minors_table_count);
433 	crypto_minors = NULL;
434 	crypto_minors_table_count = 0;
435 	for (i = 0; i < max_ncpus; i++)
436 		mutex_destroy(&crypto_locks[i].kl_lock);
437 	kmem_free(crypto_locks, max_ncpus * sizeof (kcf_lock_withpad_t));
438 	crypto_locks = NULL;
439 
440 	vmem_destroy(crypto_arena);
441 	crypto_arena = NULL;
442 
443 	return (DDI_SUCCESS);
444 }
445 
446 /* ARGSUSED3 */
447 static int
448 crypto_open(dev_t *devp, int flag, int otyp, cred_t *credp)
449 {
450 	crypto_minor_t *cm = NULL;
451 	minor_t mn;
452 	kcf_lock_withpad_t *mp;
453 	int i;
454 
455 	if (otyp != OTYP_CHR)
456 		return (ENXIO);
457 
458 	if (crypto_dip == NULL)
459 		return (ENXIO);
460 
461 	/* exclusive opens are not supported */
462 	if (flag & FEXCL)
463 		return (ENOTSUP);
464 
465 again:
466 	mp = &crypto_locks[CPU_SEQID];
467 	mutex_enter(&mp->kl_lock);
468 
469 	/* grow the minors table if needed */
470 	if (crypto_minors_count >= crypto_minors_table_count) {
471 		crypto_minor_t **newtable;
472 		minor_t chunk = crypto_minor_chunk;
473 		minor_t saved_count;
474 		size_t new_size;
475 		ulong_t big_count;
476 
477 		big_count = crypto_minors_count + chunk;
478 		if (big_count > MAXMIN) {
479 			mutex_exit(&mp->kl_lock);
480 			return (ENOMEM);
481 		}
482 
483 		saved_count = crypto_minors_table_count;
484 		new_size = sizeof (crypto_minor_t *) *
485 		    (crypto_minors_table_count + chunk);
486 
487 		mutex_exit(&mp->kl_lock);
488 
489 		newtable = kmem_zalloc(new_size, KM_SLEEP);
490 		CRYPTO_ENTER_ALL_LOCKS();
491 		/*
492 		 * Check if table grew while we were sleeping.
493 		 * The minors table never shrinks.
494 		 */
495 		if (crypto_minors_table_count > saved_count) {
496 			CRYPTO_EXIT_ALL_LOCKS();
497 			kmem_free(newtable, new_size);
498 			goto again;
499 		}
500 
501 		/* we assume that bcopy() will return if count is 0 */
502 		bcopy(crypto_minors, newtable,
503 		    sizeof (crypto_minor_t *) * crypto_minors_table_count);
504 
505 		kmem_free(crypto_minors,
506 		    sizeof (crypto_minor_t *) * crypto_minors_table_count);
507 
508 		/* grow the minors number space */
509 		if (crypto_minors_table_count != 0) {
510 			(void) vmem_add(crypto_arena,
511 			    (void *)(uintptr_t)(crypto_minors_table_count + 1),
512 			    crypto_minor_chunk, VM_SLEEP);
513 		}
514 
515 		crypto_minors = newtable;
516 		crypto_minors_table_count += chunk;
517 		CRYPTO_EXIT_ALL_LOCKS();
518 	} else {
519 		mutex_exit(&mp->kl_lock);
520 	}
521 
522 	/* allocate a new minor number starting with 1 */
523 	mn = (minor_t)(uintptr_t)vmem_alloc(crypto_arena, 1, VM_SLEEP);
524 
525 	cm = kmem_zalloc(sizeof (crypto_minor_t), KM_SLEEP);
526 	mutex_init(&cm->cm_lock, NULL, MUTEX_DRIVER, NULL);
527 	cv_init(&cm->cm_cv, NULL, CV_DRIVER, NULL);
528 
529 	CRYPTO_ENTER_ALL_LOCKS();
530 	cm->cm_refcnt = 1;
531 	crypto_minors[mn - 1] = cm;
532 	crypto_minors_count++;
533 	CRYPTO_EXIT_ALL_LOCKS();
534 
535 	*devp = makedevice(getmajor(*devp), mn);
536 
537 	return (0);
538 }
539 
540 /* ARGSUSED1 */
541 static int
542 crypto_close(dev_t dev, int flag, int otyp, cred_t *credp)
543 {
544 	crypto_minor_t *cm = NULL;
545 	crypto_session_data_t *sp;
546 	minor_t mn = getminor(dev);
547 	uint_t i;
548 	size_t total = 0;
549 	kcf_lock_withpad_t *mp;
550 
551 	mp = &crypto_locks[CPU_SEQID];
552 	mutex_enter(&mp->kl_lock);
553 
554 	if (mn > crypto_minors_table_count) {
555 		mutex_exit(&mp->kl_lock);
556 		cmn_err(CE_WARN, "crypto_close: bad minor (too big) %d", mn);
557 		return (ENODEV);
558 	}
559 
560 	cm = crypto_minors[mn - 1];
561 	if (cm == NULL) {
562 		mutex_exit(&mp->kl_lock);
563 		cmn_err(CE_WARN, "crypto_close: duplicate close of minor %d",
564 		    getminor(dev));
565 		return (ENODEV);
566 	}
567 
568 	mutex_exit(&mp->kl_lock);
569 
570 	CRYPTO_ENTER_ALL_LOCKS();
571 	/*
572 	 * We free the minor number, mn, from the crypto_arena
573 	 * only later. This ensures that we won't race with another
574 	 * thread in crypto_open with the same minor number.
575 	 */
576 	crypto_minors[mn - 1] = NULL;
577 	crypto_minors_count--;
578 	CRYPTO_EXIT_ALL_LOCKS();
579 
580 	mutex_enter(&cm->cm_lock);
581 	cm->cm_refcnt --;		/* decrement refcnt held in open */
582 	while (cm->cm_refcnt > 0) {
583 		cv_wait(&cm->cm_cv, &cm->cm_lock);
584 	}
585 
586 	vmem_free(crypto_arena, (void *)(uintptr_t)mn, 1);
587 
588 	/* free all session table entries starting with 1 */
589 	for (i = 1; i < cm->cm_session_table_count; i++) {
590 		if (cm->cm_session_table[i] == NULL)
591 			continue;
592 
593 		sp = cm->cm_session_table[i];
594 		ASSERT((sp->sd_flags & CRYPTO_SESSION_IS_BUSY) == 0);
595 		ASSERT(sp->sd_pre_approved_amount == 0 ||
596 		    sp->sd_pre_approved_amount == crypto_pre_approved_limit);
597 		total += sp->sd_pre_approved_amount;
598 		if (sp->sd_find_init_cookie != NULL) {
599 			(void) crypto_free_find_ctx(sp);
600 		}
601 		crypto_release_provider_session(cm, sp->sd_provider_session);
602 		KCF_PROV_REFRELE(sp->sd_provider);
603 		CRYPTO_CANCEL_ALL_CTX(sp);
604 		mutex_destroy(&sp->sd_lock);
605 		cv_destroy(&sp->sd_cv);
606 		kmem_cache_free(crypto_session_cache, sp);
607 		cm->cm_session_table[i] = NULL;
608 	}
609 
610 	/* free the session table */
611 	if (cm->cm_session_table != NULL && cm->cm_session_table_count > 0)
612 		kmem_free(cm->cm_session_table, cm->cm_session_table_count *
613 		    sizeof (void *));
614 
615 	total += (cm->cm_session_table_count * sizeof (void *));
616 	CRYPTO_DECREMENT_RCTL(total);
617 
618 	kcf_free_provider_tab(cm->cm_provider_count,
619 	    cm->cm_provider_array);
620 
621 	mutex_exit(&cm->cm_lock);
622 	mutex_destroy(&cm->cm_lock);
623 	cv_destroy(&cm->cm_cv);
624 	kmem_free(cm, sizeof (crypto_minor_t));
625 
626 	return (0);
627 }
628 
629 static crypto_minor_t *
630 crypto_hold_minor(minor_t minor)
631 {
632 	crypto_minor_t *cm;
633 	kcf_lock_withpad_t *mp;
634 
635 	if (minor > crypto_minors_table_count)
636 		return (NULL);
637 
638 	mp = &crypto_locks[CPU_SEQID];
639 	mutex_enter(&mp->kl_lock);
640 
641 	if ((cm = crypto_minors[minor - 1]) != NULL) {
642 		atomic_inc_32(&cm->cm_refcnt);
643 	}
644 	mutex_exit(&mp->kl_lock);
645 	return (cm);
646 }
647 
648 static void
649 crypto_release_minor(crypto_minor_t *cm)
650 {
651 	if (atomic_dec_32_nv(&cm->cm_refcnt) == 0) {
652 		cv_signal(&cm->cm_cv);
653 	}
654 }
655 
656 /*
657  * Build a list of functions and other information for the provider, pd.
658  */
659 static void
660 crypto_build_function_list(crypto_function_list_t *fl, kcf_provider_desc_t *pd)
661 {
662 	crypto_ops_t *ops;
663 	crypto_digest_ops_t *digest_ops;
664 	crypto_cipher_ops_t *cipher_ops;
665 	crypto_mac_ops_t *mac_ops;
666 	crypto_sign_ops_t *sign_ops;
667 	crypto_verify_ops_t *verify_ops;
668 	crypto_dual_ops_t *dual_ops;
669 	crypto_random_number_ops_t *random_number_ops;
670 	crypto_session_ops_t *session_ops;
671 	crypto_object_ops_t *object_ops;
672 	crypto_key_ops_t *key_ops;
673 	crypto_provider_management_ops_t *provider_ops;
674 
675 	if ((ops = pd->pd_ops_vector) == NULL)
676 		return;
677 
678 	if ((digest_ops = ops->co_digest_ops) != NULL) {
679 		if (digest_ops->digest_init != NULL)
680 			fl->fl_digest_init = B_TRUE;
681 		if (digest_ops->digest != NULL)
682 			fl->fl_digest = B_TRUE;
683 		if (digest_ops->digest_update != NULL)
684 			fl->fl_digest_update = B_TRUE;
685 		if (digest_ops->digest_key != NULL)
686 			fl->fl_digest_key = B_TRUE;
687 		if (digest_ops->digest_final != NULL)
688 			fl->fl_digest_final = B_TRUE;
689 	}
690 	if ((cipher_ops = ops->co_cipher_ops) != NULL) {
691 		if (cipher_ops->encrypt_init != NULL)
692 			fl->fl_encrypt_init = B_TRUE;
693 		if (cipher_ops->encrypt != NULL)
694 			fl->fl_encrypt = B_TRUE;
695 		if (cipher_ops->encrypt_update != NULL)
696 			fl->fl_encrypt_update = B_TRUE;
697 		if (cipher_ops->encrypt_final != NULL)
698 			fl->fl_encrypt_final = B_TRUE;
699 		if (cipher_ops->decrypt_init != NULL)
700 			fl->fl_decrypt_init = B_TRUE;
701 		if (cipher_ops->decrypt != NULL)
702 			fl->fl_decrypt = B_TRUE;
703 		if (cipher_ops->decrypt_update != NULL)
704 			fl->fl_decrypt_update = B_TRUE;
705 		if (cipher_ops->decrypt_final != NULL)
706 			fl->fl_decrypt_final = B_TRUE;
707 	}
708 	if ((mac_ops = ops->co_mac_ops) != NULL) {
709 		if (mac_ops->mac_init != NULL)
710 			fl->fl_mac_init = B_TRUE;
711 		if (mac_ops->mac != NULL)
712 			fl->fl_mac = B_TRUE;
713 		if (mac_ops->mac_update != NULL)
714 			fl->fl_mac_update = B_TRUE;
715 		if (mac_ops->mac_final != NULL)
716 			fl->fl_mac_final = B_TRUE;
717 	}
718 	if ((sign_ops = ops->co_sign_ops) != NULL) {
719 		if (sign_ops->sign_init != NULL)
720 			fl->fl_sign_init = B_TRUE;
721 		if (sign_ops->sign != NULL)
722 			fl->fl_sign = B_TRUE;
723 		if (sign_ops->sign_update != NULL)
724 			fl->fl_sign_update = B_TRUE;
725 		if (sign_ops->sign_final != NULL)
726 			fl->fl_sign_final = B_TRUE;
727 		if (sign_ops->sign_recover_init != NULL)
728 			fl->fl_sign_recover_init = B_TRUE;
729 		if (sign_ops->sign_recover != NULL)
730 			fl->fl_sign_recover = B_TRUE;
731 	}
732 	if ((verify_ops = ops->co_verify_ops) != NULL) {
733 		if (verify_ops->verify_init != NULL)
734 			fl->fl_verify_init = B_TRUE;
735 		if (verify_ops->verify != NULL)
736 			fl->fl_verify = B_TRUE;
737 		if (verify_ops->verify_update != NULL)
738 			fl->fl_verify_update = B_TRUE;
739 		if (verify_ops->verify_final != NULL)
740 			fl->fl_verify_final = B_TRUE;
741 		if (verify_ops->verify_recover_init != NULL)
742 			fl->fl_verify_recover_init = B_TRUE;
743 		if (verify_ops->verify_recover != NULL)
744 			fl->fl_verify_recover = B_TRUE;
745 	}
746 	if ((dual_ops = ops->co_dual_ops) != NULL) {
747 		if (dual_ops->digest_encrypt_update != NULL)
748 			fl->fl_digest_encrypt_update = B_TRUE;
749 		if (dual_ops->decrypt_digest_update != NULL)
750 			fl->fl_decrypt_digest_update = B_TRUE;
751 		if (dual_ops->sign_encrypt_update != NULL)
752 			fl->fl_sign_encrypt_update = B_TRUE;
753 		if (dual_ops->decrypt_verify_update != NULL)
754 			fl->fl_decrypt_verify_update = B_TRUE;
755 	}
756 	if ((random_number_ops = ops->co_random_ops) != NULL) {
757 		if (random_number_ops->seed_random != NULL)
758 			fl->fl_seed_random = B_TRUE;
759 		if (random_number_ops->generate_random != NULL)
760 			fl->fl_generate_random = B_TRUE;
761 	}
762 	if ((session_ops = ops->co_session_ops) != NULL) {
763 		if (session_ops->session_open != NULL)
764 			fl->fl_session_open = B_TRUE;
765 		if (session_ops->session_close != NULL)
766 			fl->fl_session_close = B_TRUE;
767 		if (session_ops->session_login != NULL)
768 			fl->fl_session_login = B_TRUE;
769 		if (session_ops->session_logout != NULL)
770 			fl->fl_session_logout = B_TRUE;
771 	}
772 	if ((object_ops = ops->co_object_ops) != NULL) {
773 		if (object_ops->object_create != NULL)
774 			fl->fl_object_create = B_TRUE;
775 		if (object_ops->object_copy != NULL)
776 			fl->fl_object_copy = B_TRUE;
777 		if (object_ops->object_destroy != NULL)
778 			fl->fl_object_destroy = B_TRUE;
779 		if (object_ops->object_get_size != NULL)
780 			fl->fl_object_get_size = B_TRUE;
781 		if (object_ops->object_get_attribute_value != NULL)
782 			fl->fl_object_get_attribute_value = B_TRUE;
783 		if (object_ops->object_set_attribute_value != NULL)
784 			fl->fl_object_set_attribute_value = B_TRUE;
785 		if (object_ops->object_find_init != NULL)
786 			fl->fl_object_find_init = B_TRUE;
787 		if (object_ops->object_find != NULL)
788 			fl->fl_object_find = B_TRUE;
789 		if (object_ops->object_find_final != NULL)
790 			fl->fl_object_find_final = B_TRUE;
791 	}
792 	if ((key_ops = ops->co_key_ops) != NULL) {
793 		if (key_ops->key_generate != NULL)
794 			fl->fl_key_generate = B_TRUE;
795 		if (key_ops->key_generate_pair != NULL)
796 			fl->fl_key_generate_pair = B_TRUE;
797 		if (key_ops->key_wrap != NULL)
798 			fl->fl_key_wrap = B_TRUE;
799 		if (key_ops->key_unwrap != NULL)
800 			fl->fl_key_unwrap = B_TRUE;
801 		if (key_ops->key_derive != NULL)
802 			fl->fl_key_derive = B_TRUE;
803 	}
804 	if ((provider_ops = ops->co_provider_ops) != NULL) {
805 		if (provider_ops->init_token != NULL)
806 			fl->fl_init_token = B_TRUE;
807 		if (provider_ops->init_pin != NULL)
808 			fl->fl_init_pin = B_TRUE;
809 		if (provider_ops->set_pin != NULL)
810 			fl->fl_set_pin = B_TRUE;
811 	}
812 
813 	fl->prov_is_hash_limited = pd->pd_flags & CRYPTO_HASH_NO_UPDATE;
814 	if (fl->prov_is_hash_limited) {
815 		fl->prov_hash_limit = min(pd->pd_hash_limit,
816 		    min(CRYPTO_MAX_BUFFER_LEN,
817 		    curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl));
818 	}
819 
820 	fl->prov_is_hmac_limited = pd->pd_flags & CRYPTO_HMAC_NO_UPDATE;
821 	if (fl->prov_is_hmac_limited) {
822 		fl->prov_hmac_limit = min(pd->pd_hmac_limit,
823 		    min(CRYPTO_MAX_BUFFER_LEN,
824 		    curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl));
825 	}
826 
827 	if (fl->prov_is_hash_limited || fl->prov_is_hmac_limited) {
828 		/*
829 		 * XXX - The threshold should ideally be per hash/HMAC
830 		 * mechanism. For now, we use the same value for all
831 		 * hash/HMAC mechanisms. Empirical evidence suggests this
832 		 * is fine.
833 		 */
834 		fl->prov_hash_threshold = kcf_md5_threshold;
835 	}
836 
837 	fl->total_threshold_count = MAX_NUM_THRESHOLD;
838 	fl->fl_threshold[0].mech_type = CKM_DES3_CBC;
839 	fl->fl_threshold[0].mech_threshold = kcf_des3_threshold;
840 	fl->fl_threshold[1].mech_type = CKM_DES3_ECB;
841 	fl->fl_threshold[1].mech_threshold = kcf_des3_threshold;
842 	fl->fl_threshold[2].mech_type = CKM_AES_CBC;
843 	fl->fl_threshold[2].mech_threshold = kcf_aes_threshold;
844 	fl->fl_threshold[3].mech_type = CKM_AES_ECB;
845 	fl->fl_threshold[3].mech_threshold = kcf_aes_threshold;
846 	fl->fl_threshold[4].mech_type = CKM_RC4;
847 	fl->fl_threshold[4].mech_threshold = kcf_rc4_threshold;
848 	fl->fl_threshold[5].mech_type = CKM_MD5;
849 	fl->fl_threshold[5].mech_threshold = kcf_md5_threshold;
850 	fl->fl_threshold[6].mech_type = CKM_SHA_1;
851 	fl->fl_threshold[6].mech_threshold = kcf_sha1_threshold;
852 }
853 
854 /* ARGSUSED */
855 static int
856 get_function_list(dev_t dev, caddr_t arg, int mode, int *rval)
857 {
858 	crypto_get_function_list_t get_function_list;
859 	crypto_minor_t *cm;
860 	crypto_provider_id_t provider_id;
861 	crypto_function_list_t *fl;
862 	kcf_provider_desc_t *provider;
863 	int rv;
864 
865 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
866 		cmn_err(CE_WARN, "get_function_list: failed holding minor");
867 		return (ENXIO);
868 	}
869 
870 	if (copyin(arg, &get_function_list, sizeof (get_function_list)) != 0) {
871 		crypto_release_minor(cm);
872 		return (EFAULT);
873 	}
874 
875 	/* initialize provider_array */
876 	if (cm->cm_provider_array == NULL) {
877 		rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
878 		if (rv != CRYPTO_SUCCESS) {
879 			goto release_minor;
880 		}
881 	}
882 
883 	provider_id = get_function_list.fl_provider_id;
884 	mutex_enter(&cm->cm_lock);
885 	/* index must be less than count of providers */
886 	if (provider_id >= cm->cm_provider_count) {
887 		mutex_exit(&cm->cm_lock);
888 		rv = CRYPTO_ARGUMENTS_BAD;
889 		goto release_minor;
890 	}
891 
892 	ASSERT(cm->cm_provider_array != NULL);
893 	provider = cm->cm_provider_array[provider_id];
894 	mutex_exit(&cm->cm_lock);
895 
896 	fl = &get_function_list.fl_list;
897 	bzero(fl, sizeof (crypto_function_list_t));
898 
899 	if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
900 		crypto_build_function_list(fl, provider);
901 	} else {
902 		kcf_provider_desc_t *prev = NULL, *pd;
903 
904 		mutex_enter(&provider->pd_lock);
905 		while (kcf_get_next_logical_provider_member(provider,
906 		    prev, &pd)) {
907 			prev = pd;
908 			crypto_build_function_list(fl, pd);
909 			KCF_PROV_REFRELE(pd);
910 		}
911 		mutex_exit(&provider->pd_lock);
912 	}
913 
914 	rv = CRYPTO_SUCCESS;
915 
916 release_minor:
917 	crypto_release_minor(cm);
918 
919 	get_function_list.fl_return_value = rv;
920 
921 	if (copyout(&get_function_list, arg, sizeof (get_function_list)) != 0) {
922 		return (EFAULT);
923 	}
924 	return (0);
925 }
926 
927 /*
928  * This ioctl maps a PKCS#11 mechanism string into an internal number
929  * that is used by the kernel.  pn_internal_number is set to the
930  * internal number.
931  */
932 /* ARGSUSED */
933 static int
934 get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval)
935 {
936 	STRUCT_DECL(crypto_get_mechanism_number, get_number);
937 	crypto_mech_type_t number;
938 	size_t len;
939 	char *mechanism_name;
940 	int rv;
941 
942 	STRUCT_INIT(get_number, mode);
943 
944 	if (copyin(arg, STRUCT_BUF(get_number), STRUCT_SIZE(get_number)) != 0)
945 		return (EFAULT);
946 
947 	len = STRUCT_FGET(get_number, pn_mechanism_len);
948 	if (len == 0 || len > CRYPTO_MAX_MECH_NAME) {
949 		rv = CRYPTO_ARGUMENTS_BAD;
950 		goto out;
951 	}
952 	mechanism_name = kmem_alloc(len, KM_SLEEP);
953 
954 	if (copyin(STRUCT_FGETP(get_number, pn_mechanism_string),
955 	    mechanism_name, len) != 0) {
956 		kmem_free(mechanism_name, len);
957 		return (EFAULT);
958 	}
959 
960 	/*
961 	 * Get mechanism number from kcf. We set the load_module
962 	 * flag to false since we use only hardware providers.
963 	 */
964 	number = crypto_mech2id_common(mechanism_name, B_FALSE);
965 	kmem_free(mechanism_name, len);
966 	if (number == CRYPTO_MECH_INVALID) {
967 		rv = CRYPTO_ARGUMENTS_BAD;
968 		goto out;
969 	}
970 
971 	bcopy((char *)&number, (char *)STRUCT_FADDR(get_number,
972 	    pn_internal_number), sizeof (number));
973 
974 	rv = CRYPTO_SUCCESS;
975 out:
976 	STRUCT_FSET(get_number, pn_return_value, rv);
977 
978 	if (copyout(STRUCT_BUF(get_number), arg,
979 	    STRUCT_SIZE(get_number)) != 0) {
980 		return (EFAULT);
981 	}
982 	return (0);
983 }
984 
985 /*
986  * This ioctl returns an array of crypto_mech_name_t entries.
987  * It lists all the PKCS#11 mechanisms available in the kernel.
988  */
989 /* ARGSUSED */
990 static int
991 get_mechanism_list(dev_t dev, caddr_t arg, int mode, int *rval)
992 {
993 	STRUCT_DECL(crypto_get_mechanism_list, get_list);
994 	crypto_mech_name_t *entries;
995 	size_t copyout_size;
996 	uint_t req_count;
997 	uint_t count;
998 	ulong_t offset;
999 	int error = 0;
1000 
1001 	STRUCT_INIT(get_list, mode);
1002 
1003 	if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) {
1004 		return (EFAULT);
1005 	}
1006 
1007 	entries = crypto_get_mech_list(&count, KM_SLEEP);
1008 
1009 	/* Number of entries caller thinks we have */
1010 	req_count = STRUCT_FGET(get_list, ml_count);
1011 
1012 	STRUCT_FSET(get_list, ml_count, count);
1013 	STRUCT_FSET(get_list, ml_return_value, CRYPTO_SUCCESS);
1014 
1015 	/* check if buffer is too small */
1016 	if (count > req_count) {
1017 		STRUCT_FSET(get_list, ml_return_value, CRYPTO_BUFFER_TOO_SMALL);
1018 	}
1019 
1020 	/* copyout the first stuff */
1021 	if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) {
1022 		error = EFAULT;
1023 	}
1024 
1025 	/*
1026 	 * If only requesting number of entries or buffer too small or an
1027 	 * error occurred, stop here
1028 	 */
1029 	if (req_count == 0 || count > req_count || error != 0) {
1030 		goto out;
1031 	}
1032 
1033 	copyout_size = count * sizeof (crypto_mech_name_t);
1034 
1035 	/* copyout entries */
1036 	offset = (ulong_t)STRUCT_FADDR(get_list, ml_list);
1037 	offset -= (ulong_t)STRUCT_BUF(get_list);
1038 	if (copyout(entries, arg + offset, copyout_size) != 0) {
1039 		error = EFAULT;
1040 	}
1041 
1042 out:
1043 	crypto_free_mech_list(entries, count);
1044 	return (error);
1045 }
1046 
1047 /*
1048  * Copyout kernel array of mech_infos to user space.
1049  */
1050 /* ARGSUSED */
1051 static int
1052 copyout_mechinfos(int mode, caddr_t out, uint_t count,
1053     crypto_mechanism_info_t *k_minfos, caddr_t u_minfos)
1054 {
1055 	STRUCT_DECL(crypto_mechanism_info, mi);
1056 	caddr_t p;
1057 	size_t len;
1058 	int i;
1059 
1060 	if (count == 0)
1061 		return (0);
1062 
1063 	STRUCT_INIT(mi, mode);
1064 
1065 	len = count * STRUCT_SIZE(mi);
1066 
1067 	ASSERT(u_minfos != NULL);
1068 	p = u_minfos;
1069 	for (i = 0; i < count; i++) {
1070 		STRUCT_FSET(mi, mi_min_key_size, k_minfos[i].mi_min_key_size);
1071 		STRUCT_FSET(mi, mi_max_key_size, k_minfos[i].mi_max_key_size);
1072 		STRUCT_FSET(mi, mi_keysize_unit, k_minfos[i].mi_keysize_unit);
1073 		STRUCT_FSET(mi, mi_usage, k_minfos[i].mi_usage);
1074 		bcopy(STRUCT_BUF(mi), p, STRUCT_SIZE(mi));
1075 		p += STRUCT_SIZE(mi);
1076 	}
1077 
1078 	if (copyout(u_minfos, out, len) != 0)
1079 		return (EFAULT);
1080 
1081 	return (0);
1082 }
1083 
1084 /*
1085  * This ioctl returns information for the specified mechanism.
1086  */
1087 /* ARGSUSED */
1088 static int
1089 get_all_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval)
1090 {
1091 	STRUCT_DECL(crypto_get_all_mechanism_info, get_all_mech);
1092 #ifdef _LP64
1093 	STRUCT_DECL(crypto_mechanism_info, mi);
1094 #else
1095 	/* LINTED E_FUNC_SET_NOT_USED */
1096 	STRUCT_DECL(crypto_mechanism_info, mi);
1097 #endif
1098 	crypto_mech_name_t mech_name;
1099 	crypto_mech_type_t mech_type;
1100 	crypto_mechanism_info_t *mech_infos = NULL;
1101 	uint_t num_mech_infos = 0;
1102 	uint_t req_count;
1103 	caddr_t u_minfos;
1104 	ulong_t offset;
1105 	int error = 0;
1106 	int rv;
1107 
1108 	req_count = 0;
1109 	STRUCT_INIT(get_all_mech, mode);
1110 	STRUCT_INIT(mi, mode);
1111 
1112 	if (copyin(arg, STRUCT_BUF(get_all_mech),
1113 	    STRUCT_SIZE(get_all_mech)) != 0) {
1114 		return (EFAULT);
1115 	}
1116 
1117 	(void) strncpy(mech_name, STRUCT_FGET(get_all_mech, mi_mechanism_name),
1118 	    CRYPTO_MAX_MECH_NAME);
1119 	mech_type = crypto_mech2id(mech_name);
1120 
1121 	if (mech_type == CRYPTO_MECH_INVALID) {
1122 		rv = CRYPTO_ARGUMENTS_BAD;
1123 		goto out1;
1124 	}
1125 
1126 	rv = crypto_get_all_mech_info(mech_type, &mech_infos, &num_mech_infos,
1127 	    KM_SLEEP);
1128 	if (rv != CRYPTO_SUCCESS) {
1129 		goto out1;
1130 	}
1131 	/* rv is CRYPTO_SUCCESS at this point */
1132 
1133 	/* Number of entries caller thinks we have */
1134 	req_count = STRUCT_FGET(get_all_mech, mi_count);
1135 
1136 	STRUCT_FSET(get_all_mech, mi_count, num_mech_infos);
1137 
1138 	/* check if buffer is too small */
1139 	if (num_mech_infos > req_count) {
1140 		rv = CRYPTO_BUFFER_TOO_SMALL;
1141 	}
1142 
1143 out1:
1144 	STRUCT_FSET(get_all_mech, mi_return_value, rv);
1145 
1146 	/* copy the first part */
1147 	if (copyout(STRUCT_BUF(get_all_mech), arg,
1148 	    STRUCT_SIZE(get_all_mech)) != 0) {
1149 		error = EFAULT;
1150 	}
1151 
1152 	/*
1153 	 * If only requesting number of entries, or there are no entries,
1154 	 * or rv is not CRYPTO_SUCCESS due to buffer too small or some other
1155 	 * crypto error, or an error occurred with copyout, stop here
1156 	 */
1157 	if (req_count == 0 || num_mech_infos == 0 || rv != CRYPTO_SUCCESS ||
1158 	    error != 0) {
1159 		goto out2;
1160 	}
1161 
1162 	/* copyout mech_infos */
1163 	offset = (ulong_t)STRUCT_FADDR(get_all_mech, mi_list);
1164 	offset -= (ulong_t)STRUCT_BUF(get_all_mech);
1165 
1166 	u_minfos = kmem_alloc(num_mech_infos * STRUCT_SIZE(mi), KM_SLEEP);
1167 	error = copyout_mechinfos(mode, arg + offset, num_mech_infos,
1168 	    mech_infos, u_minfos);
1169 	kmem_free(u_minfos, num_mech_infos * STRUCT_SIZE(mi));
1170 out2:
1171 	if (mech_infos != NULL)
1172 		crypto_free_all_mech_info(mech_infos, num_mech_infos);
1173 	return (error);
1174 }
1175 
1176 /*
1177  * Side-effects:
1178  *  1. This routine stores provider descriptor pointers in an array
1179  *     and increments each descriptor's reference count.  The array
1180  *     is stored in per-minor number storage.
1181  *  2. Destroys the old array and creates a new one every time
1182  *     this routine is called.
1183  */
1184 int
1185 crypto_get_provider_list(crypto_minor_t *cm, uint_t *count,
1186     crypto_provider_entry_t **array, boolean_t return_slot_list)
1187 {
1188 	kcf_provider_desc_t **provider_array;
1189 	crypto_provider_entry_t *p = NULL;
1190 	uint_t provider_count;
1191 	int rval;
1192 	int i;
1193 
1194 	/*
1195 	 * Take snapshot of provider table returning only HW entries
1196 	 * that are in a usable state. Also returns logical provider entries.
1197 	 */
1198 	rval =  kcf_get_slot_list(&provider_count, &provider_array, B_FALSE);
1199 	if (rval != CRYPTO_SUCCESS)
1200 		return (rval);
1201 
1202 	/* allocate memory before taking cm->cm_lock */
1203 	if (return_slot_list) {
1204 		if (provider_count != 0) {
1205 			p = kmem_alloc(provider_count *
1206 			    sizeof (crypto_provider_entry_t), KM_SLEEP);
1207 			for (i = 0; i < provider_count; i++) {
1208 				p[i].pe_provider_id = i;
1209 				p[i].pe_mechanism_count =
1210 				    provider_array[i]->pd_mech_list_count;
1211 			}
1212 		}
1213 		*array = p;
1214 		*count = provider_count;
1215 	}
1216 
1217 	/*
1218 	 * Free existing array of providers and replace with new list.
1219 	 */
1220 	mutex_enter(&cm->cm_lock);
1221 	if (cm->cm_provider_array != NULL) {
1222 		ASSERT(cm->cm_provider_count > 0);
1223 		kcf_free_provider_tab(cm->cm_provider_count,
1224 		    cm->cm_provider_array);
1225 	}
1226 
1227 	cm->cm_provider_array = provider_array;
1228 	cm->cm_provider_count = provider_count;
1229 	mutex_exit(&cm->cm_lock);
1230 
1231 	return (CRYPTO_SUCCESS);
1232 }
1233 
1234 /*
1235  * This ioctl returns an array of crypto_provider_entry_t entries.
1236  * This is how consumers learn which hardware providers are available.
1237  */
1238 /* ARGSUSED */
1239 static int
1240 get_provider_list(dev_t dev, caddr_t arg, int mode, int *rval)
1241 {
1242 	STRUCT_DECL(crypto_get_provider_list, get_list);
1243 	crypto_provider_entry_t *entries;
1244 	crypto_minor_t *cm;
1245 	size_t copyout_size;
1246 	uint_t req_count;
1247 	uint_t count;
1248 	ulong_t offset;
1249 	int rv;
1250 
1251 	STRUCT_INIT(get_list, mode);
1252 
1253 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1254 		cmn_err(CE_WARN, "get_provider_list: failed holding minor");
1255 		return (ENXIO);
1256 	}
1257 
1258 	if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) {
1259 		crypto_release_minor(cm);
1260 		return (EFAULT);
1261 	}
1262 
1263 	rv = crypto_get_provider_list(cm, &count, &entries, RETURN_LIST);
1264 	if (rv != CRYPTO_SUCCESS) {
1265 		crypto_release_minor(cm);
1266 		STRUCT_FSET(get_list, pl_return_value, rv);
1267 		if (copyout(STRUCT_BUF(get_list), arg,
1268 		    STRUCT_SIZE(get_list)) != 0) {
1269 			return (EFAULT);
1270 		}
1271 		return (0);
1272 	}
1273 	crypto_release_minor(cm);
1274 
1275 	/* Number of slots caller thinks we have */
1276 	req_count = STRUCT_FGET(get_list, pl_count);
1277 
1278 	/* Check if only requesting number of slots */
1279 	if (req_count == 0) {
1280 
1281 		STRUCT_FSET(get_list, pl_count, count);
1282 		STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS);
1283 
1284 		crypto_free_provider_list(entries, count);
1285 		if (copyout(STRUCT_BUF(get_list), arg,
1286 		    STRUCT_SIZE(get_list)) != 0) {
1287 			return (EFAULT);
1288 		}
1289 		return (0);
1290 	}
1291 
1292 	/* check if buffer is too small */
1293 	req_count = STRUCT_FGET(get_list, pl_count);
1294 	if (count > req_count) {
1295 		STRUCT_FSET(get_list, pl_count, count);
1296 		STRUCT_FSET(get_list, pl_return_value, CRYPTO_BUFFER_TOO_SMALL);
1297 		crypto_free_provider_list(entries, count);
1298 		if (copyout(STRUCT_BUF(get_list), arg,
1299 		    STRUCT_SIZE(get_list)) != 0) {
1300 			return (EFAULT);
1301 		}
1302 		return (0);
1303 	}
1304 
1305 	STRUCT_FSET(get_list, pl_count, count);
1306 	STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS);
1307 
1308 	copyout_size = count * sizeof (crypto_provider_entry_t);
1309 
1310 	/* copyout the first stuff */
1311 	if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) {
1312 		crypto_free_provider_list(entries, count);
1313 		return (EFAULT);
1314 	}
1315 
1316 	if (count == 0) {
1317 		crypto_free_provider_list(entries, count);
1318 		return (0);
1319 	}
1320 
1321 	/* copyout entries */
1322 	offset = (ulong_t)STRUCT_FADDR(get_list, pl_list);
1323 	offset -= (ulong_t)STRUCT_BUF(get_list);
1324 	if (copyout(entries, arg + offset, copyout_size) != 0) {
1325 		crypto_free_provider_list(entries, count);
1326 		return (EFAULT);
1327 	}
1328 
1329 	crypto_free_provider_list(entries, count);
1330 	return (0);
1331 }
1332 
1333 static void
1334 ext_to_provider_data(int mode, kcf_provider_desc_t *provider,
1335     crypto_provider_ext_info_t *ei, void *out)
1336 {
1337 	STRUCT_DECL(crypto_provider_data, pd);
1338 	STRUCT_DECL(crypto_version, version);
1339 
1340 	STRUCT_INIT(pd, mode);
1341 	STRUCT_INIT(version, mode);
1342 
1343 	bcopy(provider->pd_description, STRUCT_FGET(pd, pd_prov_desc),
1344 	    CRYPTO_PROVIDER_DESCR_MAX_LEN);
1345 
1346 	bcopy(ei->ei_label, STRUCT_FGET(pd, pd_label), CRYPTO_EXT_SIZE_LABEL);
1347 	bcopy(ei->ei_manufacturerID, STRUCT_FGET(pd, pd_manufacturerID),
1348 	    CRYPTO_EXT_SIZE_MANUF);
1349 	bcopy(ei->ei_model, STRUCT_FGET(pd, pd_model), CRYPTO_EXT_SIZE_MODEL);
1350 	bcopy(ei->ei_serial_number, STRUCT_FGET(pd, pd_serial_number),
1351 	    CRYPTO_EXT_SIZE_SERIAL);
1352 	/*
1353 	 * We do not support ioctls for dual-function crypto operations yet.
1354 	 * So, we clear this flag as it might have been set by a provider.
1355 	 */
1356 	ei->ei_flags &= ~CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
1357 
1358 	STRUCT_FSET(pd, pd_flags, ei->ei_flags);
1359 	STRUCT_FSET(pd, pd_max_session_count, ei->ei_max_session_count);
1360 	STRUCT_FSET(pd, pd_session_count, (int)CRYPTO_UNAVAILABLE_INFO);
1361 	STRUCT_FSET(pd, pd_max_rw_session_count, ei->ei_max_session_count);
1362 	STRUCT_FSET(pd, pd_rw_session_count, (int)CRYPTO_UNAVAILABLE_INFO);
1363 	STRUCT_FSET(pd, pd_max_pin_len, ei->ei_max_pin_len);
1364 	STRUCT_FSET(pd, pd_min_pin_len, ei->ei_min_pin_len);
1365 	STRUCT_FSET(pd, pd_total_public_memory, ei->ei_total_public_memory);
1366 	STRUCT_FSET(pd, pd_free_public_memory, ei->ei_free_public_memory);
1367 	STRUCT_FSET(pd, pd_total_private_memory, ei->ei_total_private_memory);
1368 	STRUCT_FSET(pd, pd_free_private_memory, ei->ei_free_private_memory);
1369 	STRUCT_FSET(version, cv_major, ei->ei_hardware_version.cv_major);
1370 	STRUCT_FSET(version, cv_minor, ei->ei_hardware_version.cv_minor);
1371 	bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_hardware_version),
1372 	    STRUCT_SIZE(version));
1373 	STRUCT_FSET(version, cv_major, ei->ei_firmware_version.cv_major);
1374 	STRUCT_FSET(version, cv_minor, ei->ei_firmware_version.cv_minor);
1375 	bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_firmware_version),
1376 	    STRUCT_SIZE(version));
1377 	bcopy(ei->ei_time, STRUCT_FGET(pd, pd_time), CRYPTO_EXT_SIZE_TIME);
1378 	bcopy(STRUCT_BUF(pd), out, STRUCT_SIZE(pd));
1379 }
1380 
1381 /*
1382  * Utility routine to construct a crypto_provider_ext_info structure. Some
1383  * of the fields are constructed from information in the provider structure.
1384  * The rest of the fields have default values. We need to do this for
1385  * providers which do not support crypto_provider_management_ops routines.
1386  */
1387 static void
1388 fabricate_ext_info(kcf_provider_desc_t *provider,
1389     crypto_provider_ext_info_t *ei)
1390 {
1391 	/* empty label */
1392 	(void) memset(ei->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
1393 
1394 	(void) memset(ei->ei_manufacturerID, ' ', CRYPTO_EXT_SIZE_MANUF);
1395 	(void) strncpy((char *)ei->ei_manufacturerID, "Unknown", 7);
1396 
1397 	(void) memset(ei->ei_model, ' ', CRYPTO_EXT_SIZE_MODEL);
1398 	(void) strncpy((char *)ei->ei_model, "Unknown", 7);
1399 
1400 	(void) memset(ei->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL);
1401 	(void) strncpy((char *)ei->ei_serial_number, "Unknown", 7);
1402 
1403 	if (KCF_PROV_RANDOM_OPS(provider) != NULL)
1404 		ei->ei_flags |= CRYPTO_EXTF_RNG;
1405 	if (KCF_PROV_DUAL_OPS(provider) != NULL)
1406 		ei->ei_flags |= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
1407 
1408 	ei->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO;
1409 	ei->ei_max_pin_len = 0;
1410 	ei->ei_min_pin_len = 0;
1411 	ei->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO;
1412 	ei->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
1413 	ei->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO;
1414 	ei->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO;
1415 	ei->ei_hardware_version.cv_major = 1;
1416 	ei->ei_hardware_version.cv_minor = 0;
1417 	ei->ei_firmware_version.cv_major = 1;
1418 	ei->ei_firmware_version.cv_minor = 0;
1419 }
1420 
1421 /* ARGSUSED */
1422 static int
1423 get_provider_info(dev_t dev, caddr_t arg, int mode, int *rval)
1424 {
1425 	STRUCT_DECL(crypto_get_provider_info, get_info);
1426 	crypto_minor_t *cm;
1427 	crypto_provider_id_t provider_id;
1428 	kcf_provider_desc_t *provider, *real_provider;
1429 	crypto_provider_ext_info_t *ext_info = NULL;
1430 	size_t need;
1431 	int error = 0;
1432 	int rv;
1433 	kcf_req_params_t params;
1434 
1435 	STRUCT_INIT(get_info, mode);
1436 
1437 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1438 		cmn_err(CE_WARN, "get_provider_info: failed holding minor");
1439 		return (ENXIO);
1440 	}
1441 
1442 	if (copyin(arg, STRUCT_BUF(get_info), STRUCT_SIZE(get_info)) != 0) {
1443 		crypto_release_minor(cm);
1444 		return (EFAULT);
1445 	}
1446 
1447 	need = sizeof (crypto_provider_ext_info_t);
1448 	if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) {
1449 		need = 0;
1450 		goto release_minor;
1451 	}
1452 
1453 	/* initialize provider_array */
1454 	if (cm->cm_provider_array == NULL) {
1455 		rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1456 		if (rv != CRYPTO_SUCCESS) {
1457 			goto release_minor;
1458 		}
1459 	}
1460 
1461 	ext_info = kmem_zalloc(need, KM_SLEEP);
1462 
1463 	provider_id = STRUCT_FGET(get_info, gi_provider_id);
1464 	mutex_enter(&cm->cm_lock);
1465 	/* index must be less than count of providers */
1466 	if (provider_id >= cm->cm_provider_count) {
1467 		mutex_exit(&cm->cm_lock);
1468 		rv = CRYPTO_ARGUMENTS_BAD;
1469 		goto release_minor;
1470 	}
1471 
1472 	ASSERT(cm->cm_provider_array != NULL);
1473 	provider = cm->cm_provider_array[provider_id];
1474 	KCF_PROV_REFHOLD(provider);
1475 	mutex_exit(&cm->cm_lock);
1476 
1477 	(void) kcf_get_hardware_provider_nomech(
1478 	    CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
1479 	    provider, &real_provider);
1480 
1481 	if (real_provider != NULL) {
1482 		ASSERT(real_provider == provider ||
1483 		    provider->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
1484 		KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_EXTINFO,
1485 		    0, NULL, 0, NULL, 0, NULL, ext_info, provider);
1486 		rv = kcf_submit_request(real_provider, NULL, NULL, &params,
1487 		    B_FALSE);
1488 		ASSERT(rv != CRYPTO_NOT_SUPPORTED);
1489 		KCF_PROV_REFRELE(real_provider);
1490 	} else {
1491 		/* do the best we can */
1492 		fabricate_ext_info(provider, ext_info);
1493 		rv = CRYPTO_SUCCESS;
1494 	}
1495 	KCF_PROV_REFRELE(provider);
1496 
1497 	if (rv == CRYPTO_SUCCESS) {
1498 		ext_to_provider_data(mode, provider, ext_info,
1499 		    STRUCT_FADDR(get_info, gi_provider_data));
1500 	}
1501 
1502 release_minor:
1503 	CRYPTO_DECREMENT_RCTL(need);
1504 	crypto_release_minor(cm);
1505 
1506 	if (ext_info != NULL)
1507 		kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
1508 
1509 	if (error != 0)
1510 		return (error);
1511 
1512 	STRUCT_FSET(get_info, gi_return_value, rv);
1513 	if (copyout(STRUCT_BUF(get_info), arg, STRUCT_SIZE(get_info)) != 0) {
1514 		return (EFAULT);
1515 	}
1516 	return (0);
1517 }
1518 
1519 /*
1520  * This ioctl returns an array of crypto_mech_name_t entries.
1521  * This is how consumers learn which mechanisms are permitted
1522  * by a provider.
1523  */
1524 /* ARGSUSED */
1525 static int
1526 get_provider_mechanisms(dev_t dev, caddr_t arg, int mode, int *rval)
1527 {
1528 	STRUCT_DECL(crypto_get_provider_mechanisms, get_mechanisms);
1529 	crypto_mech_name_t *entries;
1530 	crypto_minor_t *cm;
1531 	size_t copyout_size;
1532 	uint_t req_count;
1533 	uint_t count;
1534 	ulong_t offset;
1535 	int err;
1536 
1537 	STRUCT_INIT(get_mechanisms, mode);
1538 
1539 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1540 		cmn_err(CE_WARN,
1541 		    "get_provider_mechanisms: failed holding minor");
1542 		return (ENXIO);
1543 	}
1544 
1545 	if (copyin(arg, STRUCT_BUF(get_mechanisms),
1546 	    STRUCT_SIZE(get_mechanisms)) != 0) {
1547 		crypto_release_minor(cm);
1548 		return (EFAULT);
1549 	}
1550 
1551 	/* get array of mechanisms from the core module */
1552 	if ((err = crypto_get_provider_mechanisms(cm,
1553 	    STRUCT_FGET(get_mechanisms, pm_provider_id),
1554 	    &count, &entries)) != 0) {
1555 		crypto_release_minor(cm);
1556 		STRUCT_FSET(get_mechanisms, pm_return_value, err);
1557 		if (copyout(STRUCT_BUF(get_mechanisms), arg,
1558 		    STRUCT_SIZE(get_mechanisms)) != 0) {
1559 			return (EFAULT);
1560 		}
1561 		return (0);
1562 	}
1563 	crypto_release_minor(cm);
1564 	/* Number of mechs caller thinks we have */
1565 	req_count = STRUCT_FGET(get_mechanisms, pm_count);
1566 
1567 	/* Check if caller is just requesting a count of mechanisms */
1568 	if (req_count == 0) {
1569 		STRUCT_FSET(get_mechanisms, pm_count, count);
1570 		STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS);
1571 
1572 		crypto_free_mech_list(entries, count);
1573 		if (copyout(STRUCT_BUF(get_mechanisms), arg,
1574 		    STRUCT_SIZE(get_mechanisms)) != 0) {
1575 			return (EFAULT);
1576 		}
1577 		return (0);
1578 	}
1579 
1580 	/* check if buffer is too small */
1581 	if (count > req_count) {
1582 		STRUCT_FSET(get_mechanisms, pm_count, count);
1583 		STRUCT_FSET(get_mechanisms, pm_return_value,
1584 		    CRYPTO_BUFFER_TOO_SMALL);
1585 		crypto_free_mech_list(entries, count);
1586 		if (copyout(STRUCT_BUF(get_mechanisms), arg,
1587 		    STRUCT_SIZE(get_mechanisms)) != 0) {
1588 			return (EFAULT);
1589 		}
1590 		return (0);
1591 	}
1592 
1593 	STRUCT_FSET(get_mechanisms, pm_count, count);
1594 	STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS);
1595 
1596 	copyout_size = count * sizeof (crypto_mech_name_t);
1597 
1598 	/* copyout the first stuff */
1599 	if (copyout(STRUCT_BUF(get_mechanisms), arg,
1600 	    STRUCT_SIZE(get_mechanisms)) != 0) {
1601 		crypto_free_mech_list(entries, count);
1602 		return (EFAULT);
1603 	}
1604 
1605 	if (count == 0) {
1606 		return (0);
1607 	}
1608 
1609 	/* copyout entries */
1610 	offset = (ulong_t)STRUCT_FADDR(get_mechanisms, pm_list);
1611 	offset -= (ulong_t)STRUCT_BUF(get_mechanisms);
1612 	if (copyout(entries, arg + offset, copyout_size) != 0) {
1613 		crypto_free_mech_list(entries, count);
1614 		return (EFAULT);
1615 	}
1616 
1617 	crypto_free_mech_list(entries, count);
1618 	return (0);
1619 }
1620 
1621 /*
1622  * This ioctl returns information about a provider's mechanism.
1623  */
1624 /* ARGSUSED */
1625 static int
1626 get_provider_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval)
1627 {
1628 	crypto_get_provider_mechanism_info_t mechanism_info;
1629 	crypto_minor_t *cm;
1630 	kcf_provider_desc_t *pd;
1631 	crypto_mech_info_t *mi = NULL;
1632 	int rv = CRYPTO_SUCCESS;
1633 	int i;
1634 
1635 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1636 		cmn_err(CE_WARN,
1637 		    "get_provider_mechanism_info: failed holding minor");
1638 		return (ENXIO);
1639 	}
1640 
1641 	if (copyin(arg, &mechanism_info, sizeof (mechanism_info)) != 0) {
1642 		crypto_release_minor(cm);
1643 		return (EFAULT);
1644 	}
1645 
1646 	/* initialize provider table */
1647 	if (cm->cm_provider_array == NULL) {
1648 		rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1649 		if (rv != CRYPTO_SUCCESS) {
1650 			mutex_enter(&cm->cm_lock);
1651 			goto fail;
1652 		}
1653 	}
1654 
1655 	/*
1656 	 * Provider ID must be less than the count of providers
1657 	 * obtained by calling get_provider_list().
1658 	 */
1659 	mutex_enter(&cm->cm_lock);
1660 	if (mechanism_info.mi_provider_id >= cm->cm_provider_count) {
1661 		rv = CRYPTO_ARGUMENTS_BAD;
1662 		goto fail;
1663 	}
1664 
1665 	pd = cm->cm_provider_array[mechanism_info.mi_provider_id];
1666 
1667 	/* First check if the provider supports the mechanism. */
1668 	for (i = 0; i < pd->pd_mech_list_count; i++) {
1669 		if (strncmp(pd->pd_mechanisms[i].cm_mech_name,
1670 		    mechanism_info.mi_mechanism_name,
1671 		    CRYPTO_MAX_MECH_NAME) == 0) {
1672 			mi = &pd->pd_mechanisms[i];
1673 			break;
1674 		}
1675 	}
1676 
1677 	if (mi == NULL) {
1678 		rv = CRYPTO_ARGUMENTS_BAD;
1679 		goto fail;
1680 	}
1681 
1682 	/* Now check if the mechanism is enabled for the provider. */
1683 	if (is_mech_disabled(pd, mechanism_info.mi_mechanism_name)) {
1684 		rv = CRYPTO_MECHANISM_INVALID;
1685 		goto fail;
1686 	}
1687 
1688 	mechanism_info.mi_min_key_size = mi->cm_min_key_length;
1689 	mechanism_info.mi_max_key_size = mi->cm_max_key_length;
1690 	mechanism_info.mi_flags = mi->cm_func_group_mask;
1691 
1692 fail:
1693 	mutex_exit(&cm->cm_lock);
1694 	crypto_release_minor(cm);
1695 	mechanism_info.mi_return_value = rv;
1696 	if (copyout(&mechanism_info, arg, sizeof (mechanism_info)) != 0) {
1697 		return (EFAULT);
1698 	}
1699 
1700 	return (0);
1701 }
1702 
1703 /*
1704  * Every open of /dev/crypto multiplexes all PKCS#11 sessions across
1705  * a single session to each provider. Calls to open and close session
1706  * are not made to providers that do not support sessions. For these
1707  * providers, a session number of 0 is passed during subsequent operations,
1708  * and it is ignored by the provider.
1709  */
1710 static int
1711 crypto_get_provider_session(crypto_minor_t *cm,
1712     crypto_provider_id_t provider_index, crypto_provider_session_t **output_ps)
1713 {
1714 	kcf_provider_desc_t *pd, *real_provider;
1715 	kcf_req_params_t params;
1716 	crypto_provider_session_t *ps;
1717 	crypto_session_id_t provider_session_id = 0;
1718 	int rv;
1719 
1720 	ASSERT(MUTEX_HELD(&cm->cm_lock));
1721 
1722 	/* pd may be a logical provider */
1723 	pd = cm->cm_provider_array[provider_index];
1724 
1725 again:
1726 	/*
1727 	 * Check if there is already a session to the provider.
1728 	 * Sessions may be to a logical provider or a real provider.
1729 	 */
1730 	for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
1731 		if (ps->ps_provider == pd)
1732 			break;
1733 	}
1734 
1735 	/* found existing session */
1736 	if (ps != NULL) {
1737 		ps->ps_refcnt++;
1738 		*output_ps = ps;
1739 		return (CRYPTO_SUCCESS);
1740 	}
1741 	mutex_exit(&cm->cm_lock);
1742 
1743 	/* find a hardware provider that supports session ops */
1744 	(void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
1745 	    CRYPTO_SESSION_OFFSET(session_open), pd, &real_provider);
1746 
1747 	if (real_provider != NULL) {
1748 		ASSERT(real_provider == pd ||
1749 		    pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
1750 		/* open session to provider */
1751 		KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_OPEN,
1752 		    &provider_session_id, 0, CRYPTO_USER, NULL, 0, pd);
1753 		rv = kcf_submit_request(real_provider, NULL, NULL, &params,
1754 		    B_FALSE);
1755 		if (rv != CRYPTO_SUCCESS) {
1756 			mutex_enter(&cm->cm_lock);
1757 			KCF_PROV_REFRELE(real_provider);
1758 			return (rv);
1759 		}
1760 	}
1761 
1762 	/*
1763 	 * Check if someone opened a session to the provider
1764 	 * while we dropped the lock.
1765 	 */
1766 	mutex_enter(&cm->cm_lock);
1767 	for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
1768 		if (ps->ps_provider == pd) {
1769 			mutex_exit(&cm->cm_lock);
1770 			if (real_provider != NULL) {
1771 				KCF_WRAP_SESSION_OPS_PARAMS(&params,
1772 				    KCF_OP_SESSION_CLOSE, NULL,
1773 				    provider_session_id, CRYPTO_USER, NULL, 0,
1774 				    pd);
1775 				(void) kcf_submit_request(real_provider, NULL,
1776 				    NULL, &params, B_FALSE);
1777 				KCF_PROV_REFRELE(real_provider);
1778 			}
1779 			mutex_enter(&cm->cm_lock);
1780 			goto again;
1781 
1782 		}
1783 	}
1784 
1785 	return (crypto_create_provider_session(cm, pd, provider_session_id,
1786 	    output_ps, real_provider));
1787 }
1788 
1789 static int
1790 crypto_create_provider_session(crypto_minor_t *cm, kcf_provider_desc_t *pd,
1791     crypto_session_id_t sid, crypto_provider_session_t **out_ps,
1792     kcf_provider_desc_t *real)
1793 {
1794 	crypto_provider_session_t *ps;
1795 
1796 	/* allocate crypto_provider_session structure */
1797 	ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP);
1798 
1799 	/* increment refcnt and attach to crypto_minor structure */
1800 	ps->ps_session = sid;
1801 	ps->ps_refcnt = 1;
1802 	KCF_PROV_REFHOLD(pd);
1803 	ps->ps_provider = pd;
1804 	if (real != NULL) {
1805 		ps->ps_real_provider = real;
1806 	}
1807 	ps->ps_next = cm->cm_provider_session;
1808 	cm->cm_provider_session = ps;
1809 
1810 	*out_ps = ps;
1811 	return (CRYPTO_SUCCESS);
1812 }
1813 
1814 /*
1815  * Release a provider session.
1816  * If the reference count goes to zero, then close the session
1817  * to the provider.
1818  */
1819 static void
1820 crypto_release_provider_session(crypto_minor_t *cm,
1821     crypto_provider_session_t *provider_session)
1822 {
1823 	kcf_req_params_t params;
1824 	crypto_provider_session_t *ps = NULL, **prev;
1825 
1826 	ASSERT(MUTEX_HELD(&cm->cm_lock));
1827 
1828 	/* verify that provider_session is valid */
1829 	for (ps = cm->cm_provider_session, prev = &cm->cm_provider_session;
1830 	    ps != NULL; prev = &ps->ps_next, ps = ps->ps_next) {
1831 		if (ps == provider_session) {
1832 			break;
1833 		}
1834 	}
1835 
1836 	if (ps == NULL)
1837 		return;
1838 
1839 	ps->ps_refcnt--;
1840 
1841 	if (ps->ps_refcnt > 0)
1842 		return;
1843 
1844 	if (ps->ps_real_provider != NULL) {
1845 		/* close session with provider */
1846 		KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_CLOSE, NULL,
1847 		    ps->ps_session, CRYPTO_USER, NULL, 0, ps->ps_provider);
1848 		(void) kcf_submit_request(ps->ps_real_provider,
1849 		    NULL, NULL, &params, B_FALSE);
1850 		KCF_PROV_REFRELE(ps->ps_real_provider);
1851 	}
1852 	KCF_PROV_REFRELE(ps->ps_provider);
1853 	*prev = ps->ps_next;
1854 	kmem_free(ps, sizeof (*ps));
1855 }
1856 
1857 static int
1858 grow_session_table(crypto_minor_t *cm)
1859 {
1860 	crypto_session_data_t **session_table;
1861 	crypto_session_data_t **new;
1862 	uint_t session_table_count;
1863 	uint_t need;
1864 	size_t current_allocation;
1865 	size_t new_allocation;
1866 	int rv;
1867 
1868 	ASSERT(MUTEX_HELD(&cm->cm_lock));
1869 
1870 	session_table_count = cm->cm_session_table_count;
1871 	session_table = cm->cm_session_table;
1872 	need = session_table_count + CRYPTO_SESSION_CHUNK;
1873 
1874 	current_allocation = session_table_count * sizeof (void *);
1875 	new_allocation = need * sizeof (void *);
1876 
1877 	/*
1878 	 * Memory needed to grow the session table is checked
1879 	 * against the project.max-crypto-memory resource control.
1880 	 */
1881 	if ((rv = crypto_buffer_check(new_allocation - current_allocation)) !=
1882 	    CRYPTO_SUCCESS) {
1883 		return (rv);
1884 	}
1885 
1886 	/* drop lock while we allocate memory */
1887 	mutex_exit(&cm->cm_lock);
1888 	new = kmem_zalloc(new_allocation, KM_SLEEP);
1889 	mutex_enter(&cm->cm_lock);
1890 
1891 	/* check if another thread increased the table size */
1892 	if (session_table_count != cm->cm_session_table_count) {
1893 		kmem_free(new, new_allocation);
1894 		return (CRYPTO_SUCCESS);
1895 	}
1896 
1897 	bcopy(session_table, new, current_allocation);
1898 	kmem_free(session_table, current_allocation);
1899 	cm->cm_session_table = new;
1900 	cm->cm_session_table_count += CRYPTO_SESSION_CHUNK;
1901 
1902 	return (CRYPTO_SUCCESS);
1903 }
1904 
1905 /*
1906  * Find unused entry in session table and return its index.
1907  * Initialize session table entry.
1908  */
1909 /* ARGSUSED */
1910 static int
1911 crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index,
1912     crypto_provider_id_t provider_id)
1913 {
1914 	crypto_minor_t *cm;
1915 	int rv;
1916 	crypto_provider_session_t *ps;
1917 	kcf_provider_desc_t *provider;
1918 
1919 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1920 		cmn_err(CE_WARN, "crypto_open_session: failed holding minor");
1921 		return (CRYPTO_FAILED);
1922 	}
1923 
1924 	/* initialize provider_array */
1925 	if (cm->cm_provider_array == NULL) {
1926 		rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1927 		if (rv != 0) {
1928 			crypto_release_minor(cm);
1929 			return (rv);
1930 		}
1931 	}
1932 
1933 	mutex_enter(&cm->cm_lock);
1934 	/* index must be less than count of providers */
1935 	if (provider_id >= cm->cm_provider_count) {
1936 		mutex_exit(&cm->cm_lock);
1937 		crypto_release_minor(cm);
1938 		return (CRYPTO_INVALID_PROVIDER_ID);
1939 	}
1940 	ASSERT(cm->cm_provider_array != NULL);
1941 
1942 	rv = crypto_get_provider_session(cm, provider_id, &ps);
1943 	if (rv != CRYPTO_SUCCESS) {
1944 		mutex_exit(&cm->cm_lock);
1945 		crypto_release_minor(cm);
1946 		return (rv);
1947 	}
1948 	provider = cm->cm_provider_array[provider_id];
1949 
1950 	rv = crypto_create_session_ptr(cm, provider, ps, session_index);
1951 	mutex_exit(&cm->cm_lock);
1952 	crypto_release_minor(cm);
1953 	return (rv);
1954 
1955 }
1956 
1957 static int
1958 crypto_create_session_ptr(crypto_minor_t *cm, kcf_provider_desc_t *provider,
1959     crypto_provider_session_t *ps,  crypto_session_id_t *session_index)
1960 {
1961 	crypto_session_data_t **session_table;
1962 	crypto_session_data_t *sp;
1963 	uint_t session_table_count;
1964 	uint_t i;
1965 	int rv;
1966 
1967 	ASSERT(MUTEX_HELD(&cm->cm_lock));
1968 
1969 again:
1970 	session_table_count = cm->cm_session_table_count;
1971 	session_table = cm->cm_session_table;
1972 
1973 	/* session handles start with 1 */
1974 	for (i = 1; i < session_table_count; i++) {
1975 		if (session_table[i] == NULL)
1976 			break;
1977 	}
1978 
1979 	if (i == session_table_count || session_table_count == 0) {
1980 		if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) {
1981 			crypto_release_provider_session(cm, ps);
1982 			return (rv);
1983 		}
1984 		goto again;
1985 	}
1986 
1987 	sp = kmem_cache_alloc(crypto_session_cache, KM_SLEEP);
1988 	sp->sd_flags = 0;
1989 	sp->sd_find_init_cookie = NULL;
1990 	sp->sd_digest_ctx = NULL;
1991 	sp->sd_encr_ctx = NULL;
1992 	sp->sd_decr_ctx = NULL;
1993 	sp->sd_sign_ctx = NULL;
1994 	sp->sd_verify_ctx = NULL;
1995 	sp->sd_mac_ctx = NULL;
1996 	sp->sd_sign_recover_ctx = NULL;
1997 	sp->sd_verify_recover_ctx = NULL;
1998 	mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL);
1999 	cv_init(&sp->sd_cv, NULL, CV_DRIVER, NULL);
2000 	KCF_PROV_REFHOLD(provider);
2001 	sp->sd_provider = provider;
2002 	sp->sd_provider_session = ps;
2003 
2004 	/* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */
2005 	if ((rv = crypto_buffer_check(crypto_pre_approved_limit)) !=
2006 	    CRYPTO_SUCCESS) {
2007 		sp->sd_pre_approved_amount = 0;
2008 	} else {
2009 		sp->sd_pre_approved_amount = (int)crypto_pre_approved_limit;
2010 	}
2011 
2012 	cm->cm_session_table[i] = sp;
2013 	if (session_index != NULL)
2014 		*session_index = i;
2015 
2016 	return (CRYPTO_SUCCESS);
2017 }
2018 
2019 /*
2020  * Close a session.
2021  */
2022 static int
2023 crypto_close_session(dev_t dev, crypto_session_id_t session_index)
2024 {
2025 	crypto_session_data_t **session_table;
2026 	crypto_session_data_t *sp;
2027 	crypto_minor_t *cm;
2028 
2029 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2030 		cmn_err(CE_WARN, "crypto_close_session: failed holding minor");
2031 		return (CRYPTO_FAILED);
2032 	}
2033 
2034 	mutex_enter(&cm->cm_lock);
2035 	session_table = cm->cm_session_table;
2036 
2037 	if ((session_index) == 0 ||
2038 	    (session_index >= cm->cm_session_table_count)) {
2039 		mutex_exit(&cm->cm_lock);
2040 		crypto_release_minor(cm);
2041 		return (CRYPTO_SESSION_HANDLE_INVALID);
2042 	}
2043 
2044 	sp = session_table[session_index];
2045 	if (sp == NULL) {
2046 		mutex_exit(&cm->cm_lock);
2047 		crypto_release_minor(cm);
2048 		return (CRYPTO_SESSION_HANDLE_INVALID);
2049 	}
2050 	/*
2051 	 * If session is in use, free it when the thread
2052 	 * finishes with the session.
2053 	 */
2054 	mutex_enter(&sp->sd_lock);
2055 	if (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) {
2056 		sp->sd_flags |= CRYPTO_SESSION_IS_CLOSED;
2057 		mutex_exit(&sp->sd_lock);
2058 	} else {
2059 		ASSERT(sp->sd_pre_approved_amount == 0 ||
2060 		    sp->sd_pre_approved_amount == crypto_pre_approved_limit);
2061 		CRYPTO_DECREMENT_RCTL(sp->sd_pre_approved_amount);
2062 
2063 		if (sp->sd_find_init_cookie != NULL) {
2064 			(void) crypto_free_find_ctx(sp);
2065 		}
2066 
2067 		crypto_release_provider_session(cm, sp->sd_provider_session);
2068 		KCF_PROV_REFRELE(sp->sd_provider);
2069 		CRYPTO_CANCEL_ALL_CTX(sp);
2070 		mutex_destroy(&sp->sd_lock);
2071 		cv_destroy(&sp->sd_cv);
2072 		kmem_cache_free(crypto_session_cache, sp);
2073 		session_table[session_index] = NULL;
2074 	}
2075 
2076 	mutex_exit(&cm->cm_lock);
2077 	crypto_release_minor(cm);
2078 
2079 	return (CRYPTO_SUCCESS);
2080 }
2081 
2082 /*
2083  * This ioctl opens a session and returns the session ID in os_session.
2084  */
2085 /* ARGSUSED */
2086 static int
2087 open_session(dev_t dev, caddr_t arg, int mode, int *rval)
2088 {
2089 	crypto_open_session_t open_session;
2090 	crypto_session_id_t session;
2091 	int rv;
2092 
2093 	if (copyin(arg, &open_session, sizeof (open_session)) != 0)
2094 		return (EFAULT);
2095 
2096 	rv = crypto_open_session(dev, open_session.os_flags,
2097 	    &session, open_session.os_provider_id);
2098 	if (rv != CRYPTO_SUCCESS) {
2099 		open_session.os_return_value = rv;
2100 		if (copyout(&open_session, arg, sizeof (open_session)) != 0) {
2101 			return (EFAULT);
2102 		}
2103 		return (0);
2104 	}
2105 
2106 	open_session.os_session = session;
2107 	open_session.os_return_value = CRYPTO_SUCCESS;
2108 
2109 	if (copyout(&open_session, arg, sizeof (open_session)) != 0) {
2110 		return (EFAULT);
2111 	}
2112 	return (0);
2113 }
2114 
2115 /*
2116  * This ioctl closes a session.
2117  */
2118 /* ARGSUSED */
2119 static int
2120 close_session(dev_t dev, caddr_t arg, int mode, int *rval)
2121 {
2122 	crypto_close_session_t close_session;
2123 	int rv;
2124 
2125 	if (copyin(arg, &close_session, sizeof (close_session)) != 0)
2126 		return (EFAULT);
2127 
2128 	rv = crypto_close_session(dev, close_session.cs_session);
2129 	close_session.cs_return_value = rv;
2130 	if (copyout(&close_session, arg, sizeof (close_session)) != 0) {
2131 		return (EFAULT);
2132 	}
2133 	return (0);
2134 }
2135 
2136 /*
2137  * Copy data model dependent mechanism structure into a kernel mechanism
2138  * structure.  Allocate param storage if necessary.
2139  */
2140 static boolean_t
2141 copyin_mech(int mode, crypto_session_data_t *sp, crypto_mechanism_t *in_mech,
2142     crypto_mechanism_t *out_mech, size_t *out_rctl_bytes,
2143     boolean_t *out_rctl_chk, int *out_rv, int *out_error)
2144 {
2145 	STRUCT_DECL(crypto_mechanism, mech);
2146 	caddr_t param;
2147 	size_t param_len;
2148 	size_t rctl_bytes = 0;
2149 	int error = 0;
2150 	int rv = 0;
2151 
2152 	STRUCT_INIT(mech, mode);
2153 	bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
2154 	param = STRUCT_FGETP(mech, cm_param);
2155 	param_len = STRUCT_FGET(mech, cm_param_len);
2156 	out_mech->cm_type = STRUCT_FGET(mech, cm_type);
2157 	out_mech->cm_param = NULL;
2158 	out_mech->cm_param_len = 0;
2159 	if (param != NULL && param_len != 0) {
2160 		if (param_len > crypto_max_buffer_len) {
2161 			cmn_err(CE_NOTE, "copyin_mech: buffer greater than "
2162 			    "%ld bytes, pid = %d", crypto_max_buffer_len,
2163 			    curproc->p_pid);
2164 			rv = CRYPTO_ARGUMENTS_BAD;
2165 			goto out;
2166 		}
2167 
2168 		rv = CRYPTO_BUFFER_CHECK(sp, param_len, *out_rctl_chk);
2169 		if (rv != CRYPTO_SUCCESS) {
2170 			goto out;
2171 		}
2172 		rctl_bytes = param_len;
2173 
2174 		out_mech->cm_param = kmem_alloc(param_len, KM_SLEEP);
2175 		if (copyin((char *)param, out_mech->cm_param, param_len) != 0) {
2176 			kmem_free(out_mech->cm_param, param_len);
2177 			out_mech->cm_param = NULL;
2178 			error = EFAULT;
2179 			goto out;
2180 		}
2181 		out_mech->cm_param_len = param_len;
2182 	}
2183 out:
2184 	*out_rctl_bytes = rctl_bytes;
2185 	*out_rv = rv;
2186 	*out_error = error;
2187 	return ((rv | error) ? B_FALSE : B_TRUE);
2188 }
2189 
2190 /*
2191  * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST.
2192  * The crypto_key structure is not freed.
2193  */
2194 static void
2195 crypto_free_key_attributes(crypto_key_t *key)
2196 {
2197 	crypto_object_attribute_t *attrs;
2198 	size_t len = 0;
2199 	int i;
2200 
2201 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
2202 	if (key->ck_count == 0 || key->ck_attrs == NULL)
2203 		return;
2204 
2205 	/* compute the size of the container */
2206 	len = key->ck_count * sizeof (crypto_object_attribute_t);
2207 
2208 	/* total up the size of all attributes in the container */
2209 	for (i = 0; i < key->ck_count; i++) {
2210 		attrs = &key->ck_attrs[i];
2211 		if (attrs->oa_value_len != 0 &&
2212 		    attrs->oa_value != NULL) {
2213 			len += roundup(attrs->oa_value_len, sizeof (caddr_t));
2214 		}
2215 	}
2216 
2217 	bzero(key->ck_attrs, len);
2218 	kmem_free(key->ck_attrs, len);
2219 }
2220 
2221 /*
2222  * Frees allocated storage in the key structure, but doesn't free
2223  * the key structure.
2224  */
2225 static void
2226 free_crypto_key(crypto_key_t *key)
2227 {
2228 	switch (key->ck_format) {
2229 	case CRYPTO_KEY_RAW: {
2230 		size_t len;
2231 
2232 		if (key->ck_length == 0 || key->ck_data == NULL)
2233 			break;
2234 
2235 		len = CRYPTO_BITS2BYTES(key->ck_length);
2236 		bzero(key->ck_data, len);
2237 		kmem_free(key->ck_data, len);
2238 		break;
2239 	}
2240 
2241 	case CRYPTO_KEY_ATTR_LIST:
2242 		crypto_free_key_attributes(key);
2243 		break;
2244 
2245 	default:
2246 		break;
2247 	}
2248 }
2249 
2250 /*
2251  * Copy in an array of crypto_object_attribute structures from user-space.
2252  * Kernel memory is allocated for the array and the value of each attribute
2253  * in the array.  Since unprivileged users can specify the size of attributes,
2254  * the amount of memory needed is charged against the
2255  * project.max-crypto-memory resource control.
2256  *
2257  * Attribute values are copied in from user-space if copyin_value is set to
2258  * B_TRUE.  This routine returns B_TRUE if the copyin was successful.
2259  */
2260 static boolean_t
2261 copyin_attributes(int mode, crypto_session_data_t *sp,
2262     uint_t count, caddr_t oc_attributes,
2263     crypto_object_attribute_t **k_attrs_out, size_t *k_attrs_size_out,
2264     caddr_t *u_attrs_out, int *out_rv, int *out_error, size_t *out_rctl_bytes,
2265     boolean_t *out_rctl_chk, boolean_t copyin_value)
2266 {
2267 	STRUCT_DECL(crypto_object_attribute, oa);
2268 	crypto_object_attribute_t *k_attrs = NULL;
2269 	caddr_t attrs = NULL, ap, p, value;
2270 	caddr_t k_attrs_buf;
2271 	size_t k_attrs_len;
2272 	size_t k_attrs_buf_len = 0;
2273 	size_t k_attrs_total_len = 0;
2274 	size_t tmp_len;
2275 	size_t rctl_bytes = 0;
2276 	size_t len = 0;
2277 	size_t value_len;
2278 	int error = 0;
2279 	int rv = 0;
2280 	int i;
2281 
2282 	STRUCT_INIT(oa, mode);
2283 
2284 	if (count == 0) {
2285 		rv = CRYPTO_SUCCESS;
2286 		goto out;
2287 	}
2288 
2289 	if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) {
2290 		rv = CRYPTO_ARGUMENTS_BAD;
2291 		goto out;
2292 	}
2293 
2294 	/* compute size of crypto_object_attribute array */
2295 	len = count * STRUCT_SIZE(oa);
2296 
2297 	/* this allocation is not charged against the user's resource limit */
2298 	attrs = kmem_alloc(len, KM_SLEEP);
2299 	if (copyin(oc_attributes, attrs, len) != 0) {
2300 		error = EFAULT;
2301 		goto out;
2302 	}
2303 
2304 	/* figure out how much memory to allocate for all of the attributes */
2305 	ap = attrs;
2306 	for (i = 0; i < count; i++) {
2307 		bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa));
2308 		tmp_len = roundup(STRUCT_FGET(oa, oa_value_len),
2309 		    sizeof (caddr_t));
2310 		if (tmp_len > crypto_max_buffer_len) {
2311 			cmn_err(CE_NOTE, "copyin_attributes: buffer greater "
2312 			    "than %ld bytes, pid = %d", crypto_max_buffer_len,
2313 			    curproc->p_pid);
2314 			rv = CRYPTO_ARGUMENTS_BAD;
2315 			goto out;
2316 		}
2317 		if (STRUCT_FGETP(oa, oa_value) != NULL)
2318 			k_attrs_buf_len += tmp_len;
2319 		ap += STRUCT_SIZE(oa);
2320 	}
2321 
2322 	k_attrs_len = count * sizeof (crypto_object_attribute_t);
2323 	k_attrs_total_len = k_attrs_buf_len + k_attrs_len;
2324 
2325 	rv = CRYPTO_BUFFER_CHECK(sp, k_attrs_total_len, *out_rctl_chk);
2326 	if (rv != CRYPTO_SUCCESS) {
2327 		goto out;
2328 	}
2329 	rctl_bytes = k_attrs_total_len;
2330 
2331 	/* one big allocation for everything */
2332 	k_attrs = kmem_alloc(k_attrs_total_len, KM_SLEEP);
2333 	k_attrs_buf = (char *)k_attrs + k_attrs_len;
2334 
2335 	ap = attrs;
2336 	p = k_attrs_buf;
2337 	for (i = 0; i < count; i++) {
2338 		bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa));
2339 		k_attrs[i].oa_type = STRUCT_FGET(oa, oa_type);
2340 		value = STRUCT_FGETP(oa, oa_value);
2341 		value_len = STRUCT_FGET(oa, oa_value_len);
2342 		if (value != NULL && value_len != 0 && copyin_value) {
2343 			if (copyin(value, p, value_len) != 0) {
2344 				kmem_free(k_attrs, k_attrs_total_len);
2345 				k_attrs = NULL;
2346 				error = EFAULT;
2347 				goto out;
2348 			}
2349 		}
2350 
2351 		if (value != NULL) {
2352 			k_attrs[i].oa_value = p;
2353 			p += roundup(value_len, sizeof (caddr_t));
2354 		} else {
2355 			k_attrs[i].oa_value = NULL;
2356 		}
2357 		k_attrs[i].oa_value_len = value_len;
2358 		ap += STRUCT_SIZE(oa);
2359 	}
2360 out:
2361 	if (attrs != NULL) {
2362 		/*
2363 		 * Free the array if there is a failure or the caller
2364 		 * doesn't want the array to be returned.
2365 		 */
2366 		if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) {
2367 			kmem_free(attrs, len);
2368 			attrs = NULL;
2369 		}
2370 	}
2371 
2372 	if (u_attrs_out != NULL)
2373 		*u_attrs_out = attrs;
2374 	if (k_attrs_size_out != NULL)
2375 		*k_attrs_size_out = k_attrs_total_len;
2376 	*k_attrs_out = k_attrs;
2377 	*out_rctl_bytes = rctl_bytes;
2378 	*out_rv = rv;
2379 	*out_error = error;
2380 	return ((rv | error) ? B_FALSE : B_TRUE);
2381 }
2382 
2383 /*
2384  * Copy data model dependent raw key into a kernel key
2385  * structure.  Checks key length or attribute lengths against
2386  * resource controls before allocating memory.  Returns B_TRUE
2387  * if both error and rv are set to 0.
2388  */
2389 static boolean_t
2390 copyin_key(int mode, crypto_session_data_t *sp, crypto_key_t *in_key,
2391     crypto_key_t *out_key, size_t *out_rctl_bytes,
2392     boolean_t *out_rctl_chk, int *out_rv, int *out_error)
2393 {
2394 	STRUCT_DECL(crypto_key, key);
2395 	crypto_object_attribute_t *k_attrs = NULL;
2396 	size_t key_bits;
2397 	size_t key_bytes = 0;
2398 	size_t rctl_bytes = 0;
2399 	int count;
2400 	int error = 0;
2401 	int rv = CRYPTO_SUCCESS;
2402 
2403 	STRUCT_INIT(key, mode);
2404 	bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key));
2405 	out_key->ck_format = STRUCT_FGET(key, ck_format);
2406 	switch (out_key->ck_format) {
2407 	case CRYPTO_KEY_RAW:
2408 		key_bits = STRUCT_FGET(key, ck_length);
2409 		if (key_bits != 0) {
2410 			if (key_bits >
2411 			    (CRYPTO_BYTES2BITS(crypto_max_buffer_len))) {
2412 				cmn_err(CE_NOTE, "copyin_key: buffer greater "
2413 				    "than %ld bytes, pid = %d",
2414 				    crypto_max_buffer_len, curproc->p_pid);
2415 				rv = CRYPTO_ARGUMENTS_BAD;
2416 				goto out;
2417 			}
2418 			key_bytes = CRYPTO_BITS2BYTES(key_bits);
2419 
2420 			rv = CRYPTO_BUFFER_CHECK(sp, key_bytes,
2421 			    *out_rctl_chk);
2422 			if (rv != CRYPTO_SUCCESS) {
2423 				goto out;
2424 			}
2425 			rctl_bytes = key_bytes;
2426 
2427 			out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP);
2428 
2429 			if (copyin((char *)STRUCT_FGETP(key, ck_data),
2430 			    out_key->ck_data, key_bytes) != 0) {
2431 				kmem_free(out_key->ck_data, key_bytes);
2432 				out_key->ck_data = NULL;
2433 				out_key->ck_length = 0;
2434 				error = EFAULT;
2435 				goto out;
2436 			}
2437 		}
2438 		out_key->ck_length = (ulong_t)key_bits;
2439 		break;
2440 
2441 	case CRYPTO_KEY_ATTR_LIST:
2442 		count = STRUCT_FGET(key, ck_count);
2443 
2444 		if (copyin_attributes(mode, sp, count,
2445 		    (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL,
2446 		    &rv, &error, &rctl_bytes, out_rctl_chk, B_TRUE)) {
2447 			out_key->ck_count = count;
2448 			out_key->ck_attrs = k_attrs;
2449 			k_attrs = NULL;
2450 		} else {
2451 			out_key->ck_count = 0;
2452 			out_key->ck_attrs = NULL;
2453 		}
2454 		break;
2455 
2456 	case CRYPTO_KEY_REFERENCE:
2457 		out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id);
2458 		break;
2459 
2460 	default:
2461 		rv = CRYPTO_ARGUMENTS_BAD;
2462 	}
2463 
2464 out:
2465 	*out_rctl_bytes = rctl_bytes;
2466 	*out_rv = rv;
2467 	*out_error = error;
2468 	return ((rv | error) ? B_FALSE : B_TRUE);
2469 }
2470 
2471 /*
2472  * This routine does two things:
2473  * 1. Given a crypto_minor structure and a session ID, it returns
2474  *    a valid session pointer.
2475  * 2. It checks that the provider, to which the session has been opened,
2476  *    has not been removed.
2477  */
2478 static boolean_t
2479 get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm,
2480     crypto_session_data_t **session_ptr, int *out_error, int *out_rv)
2481 {
2482 	crypto_session_data_t *sp = NULL;
2483 	int rv = CRYPTO_SESSION_HANDLE_INVALID;
2484 	int error = 0;
2485 
2486 	mutex_enter(&cm->cm_lock);
2487 	if ((i < cm->cm_session_table_count) &&
2488 	    (cm->cm_session_table[i] != NULL)) {
2489 		sp = cm->cm_session_table[i];
2490 		mutex_enter(&sp->sd_lock);
2491 		mutex_exit(&cm->cm_lock);
2492 		while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) {
2493 			if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) {
2494 				mutex_exit(&sp->sd_lock);
2495 				sp = NULL;
2496 				error = EINTR;
2497 				goto out;
2498 			}
2499 		}
2500 
2501 		if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) {
2502 			mutex_exit(&sp->sd_lock);
2503 			sp = NULL;
2504 			goto out;
2505 		}
2506 
2507 		if (KCF_IS_PROV_REMOVED(sp->sd_provider)) {
2508 			mutex_exit(&sp->sd_lock);
2509 			sp = NULL;
2510 			rv = CRYPTO_DEVICE_ERROR;
2511 			goto out;
2512 		}
2513 
2514 		rv = CRYPTO_SUCCESS;
2515 		sp->sd_flags |= CRYPTO_SESSION_IS_BUSY;
2516 		mutex_exit(&sp->sd_lock);
2517 	} else {
2518 		mutex_exit(&cm->cm_lock);
2519 	}
2520 out:
2521 	*session_ptr = sp;
2522 	*out_error = error;
2523 	*out_rv = rv;
2524 	return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE);
2525 }
2526 
2527 #define	CRYPTO_SESSION_RELE(s)	if ((s) != NULL) {	\
2528 	mutex_enter(&((s)->sd_lock));			\
2529 	(s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY;	\
2530 	cv_broadcast(&(s)->sd_cv);			\
2531 	mutex_exit(&((s)->sd_lock));			\
2532 }
2533 
2534 /* ARGSUSED */
2535 static int
2536 encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval)
2537 {
2538 	return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov));
2539 }
2540 
2541 /* ARGSUSED */
2542 static int
2543 decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval)
2544 {
2545 	return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov));
2546 }
2547 
2548 /*
2549  * umech is a mechanism structure that has been copied from user address
2550  * space into kernel address space. Only one copyin has been done.
2551  * The mechanism parameter, if non-null, still points to user address space.
2552  * If the mechanism parameter contains pointers, they are pointers into
2553  * user address space.
2554  *
2555  * kmech is a umech with all pointers and structures in kernel address space.
2556  *
2557  * This routine calls the provider's entry point to copy a umech parameter
2558  * into kernel address space. Kernel memory is allocated by the provider.
2559  */
2560 static int
2561 crypto_provider_copyin_mech_param(kcf_provider_desc_t *pd,
2562     crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error)
2563 {
2564 	crypto_mech_type_t provider_mech_type;
2565 	int rv;
2566 
2567 	/* get the provider's mech number */
2568 	provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
2569 
2570 	kmech->cm_param = NULL;
2571 	kmech->cm_param_len = 0;
2572 	kmech->cm_type = provider_mech_type;
2573 	rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode);
2574 	kmech->cm_type = umech->cm_type;
2575 
2576 	return (rv);
2577 }
2578 
2579 /*
2580  * umech is a mechanism structure that has been copied from user address
2581  * space into kernel address space. Only one copyin has been done.
2582  * The mechanism parameter, if non-null, still points to user address space.
2583  * If the mechanism parameter contains pointers, they are pointers into
2584  * user address space.
2585  *
2586  * kmech is a umech with all pointers and structures in kernel address space.
2587  *
2588  * This routine calls the provider's entry point to copy a kmech parameter
2589  * into user address space using umech as a template containing
2590  * user address pointers.
2591  */
2592 static int
2593 crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd,
2594     crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error)
2595 {
2596 	crypto_mech_type_t provider_mech_type;
2597 	int rv;
2598 
2599 	/* get the provider's mech number */
2600 	provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
2601 
2602 	kmech->cm_type = provider_mech_type;
2603 	rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode);
2604 	kmech->cm_type = umech->cm_type;
2605 
2606 	return (rv);
2607 }
2608 
2609 /*
2610  * Call the provider's entry point to free kernel memory that has been
2611  * allocated for the mechanism's parameter.
2612  */
2613 static void
2614 crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module,
2615     crypto_mechanism_t *mech)
2616 {
2617 	crypto_mech_type_t provider_mech_type;
2618 
2619 	if (allocated_by_crypto_module) {
2620 		if (mech->cm_param != NULL)
2621 			kmem_free(mech->cm_param, mech->cm_param_len);
2622 	} else {
2623 		/* get the provider's mech number */
2624 		provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type);
2625 
2626 		if (mech->cm_param != NULL && mech->cm_param_len != 0) {
2627 			mech->cm_type = provider_mech_type;
2628 			(void) KCF_PROV_FREE_MECH(pd, mech);
2629 		}
2630 	}
2631 }
2632 
2633 /*
2634  * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init
2635  * structures are identical except for field names.
2636  */
2637 static int
2638 cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t,
2639     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2640     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *))
2641 {
2642 	STRUCT_DECL(crypto_encrypt_init, encrypt_init);
2643 	kcf_provider_desc_t *real_provider = NULL;
2644 	crypto_session_id_t session_id;
2645 	crypto_mechanism_t mech;
2646 	crypto_key_t key;
2647 	crypto_minor_t *cm;
2648 	crypto_session_data_t *sp = NULL;
2649 	crypto_context_t cc;
2650 	crypto_ctx_t **ctxpp;
2651 	size_t mech_rctl_bytes = 0;
2652 	boolean_t mech_rctl_chk = B_FALSE;
2653 	size_t key_rctl_bytes = 0;
2654 	boolean_t key_rctl_chk = B_FALSE;
2655 	int error = 0;
2656 	int rv;
2657 	boolean_t allocated_by_crypto_module = B_FALSE;
2658 	crypto_func_group_t fg;
2659 
2660 	STRUCT_INIT(encrypt_init, mode);
2661 
2662 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2663 		cmn_err(CE_WARN, "cipher_init: failed holding minor");
2664 		return (ENXIO);
2665 	}
2666 
2667 	if (copyin(arg, STRUCT_BUF(encrypt_init),
2668 	    STRUCT_SIZE(encrypt_init)) != 0) {
2669 		crypto_release_minor(cm);
2670 		return (EFAULT);
2671 	}
2672 
2673 	mech.cm_param = NULL;
2674 	bzero(&key, sizeof (crypto_key_t));
2675 
2676 	session_id = STRUCT_FGET(encrypt_init, ei_session);
2677 
2678 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2679 		goto out;
2680 	}
2681 
2682 	bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type,
2683 	    sizeof (crypto_mech_type_t));
2684 
2685 	if (init == crypto_encrypt_init_prov) {
2686 		fg = CRYPTO_FG_ENCRYPT;
2687 	} else {
2688 		fg = CRYPTO_FG_DECRYPT;
2689 	}
2690 
2691 	/* We need the key length for provider selection so copy it in now. */
2692 	if (!copyin_key(mode, sp, STRUCT_FADDR(encrypt_init, ei_key), &key,
2693 	    &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
2694 		goto out;
2695 	}
2696 
2697 	if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
2698 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider, fg))
2699 	    != CRYPTO_SUCCESS) {
2700 		goto out;
2701 	}
2702 
2703 	rv = crypto_provider_copyin_mech_param(real_provider,
2704 	    STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error);
2705 
2706 	if (rv == CRYPTO_NOT_SUPPORTED) {
2707 		allocated_by_crypto_module = B_TRUE;
2708 		if (!copyin_mech(mode, sp, STRUCT_FADDR(encrypt_init, ei_mech),
2709 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
2710 			goto out;
2711 		}
2712 	} else {
2713 		if (rv != CRYPTO_SUCCESS)
2714 			goto out;
2715 	}
2716 
2717 	rv = (init)(real_provider, sp->sd_provider_session->ps_session,
2718 	    &mech, &key, NULL, &cc, NULL);
2719 
2720 	/*
2721 	 * Check if a context already exists. If so, it means it is being
2722 	 * abandoned. So, cancel it to avoid leaking it.
2723 	 */
2724 	ctxpp = (init == crypto_encrypt_init_prov) ?
2725 	    &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2726 
2727 	if (*ctxpp != NULL)
2728 		CRYPTO_CANCEL_CTX(ctxpp);
2729 	*ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
2730 
2731 out:
2732 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
2733 	CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
2734 	CRYPTO_SESSION_RELE(sp);
2735 	crypto_release_minor(cm);
2736 
2737 	if (real_provider != NULL) {
2738 		crypto_free_mech(real_provider,
2739 		    allocated_by_crypto_module, &mech);
2740 		KCF_PROV_REFRELE(real_provider);
2741 	}
2742 
2743 	free_crypto_key(&key);
2744 
2745 	if (error != 0)
2746 		/* XXX free context */
2747 		return (error);
2748 
2749 	STRUCT_FSET(encrypt_init, ei_return_value, rv);
2750 	if (copyout(STRUCT_BUF(encrypt_init), arg,
2751 	    STRUCT_SIZE(encrypt_init)) != 0) {
2752 		/* XXX free context */
2753 		return (EFAULT);
2754 	}
2755 	return (0);
2756 }
2757 
2758 /* ARGSUSED */
2759 static int
2760 encrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2761 {
2762 	return (cipher(dev, arg, mode, crypto_encrypt_single));
2763 }
2764 
2765 /* ARGSUSED */
2766 static int
2767 decrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2768 {
2769 	return (cipher(dev, arg, mode, crypto_decrypt_single));
2770 }
2771 
2772 /*
2773  * ASSUMPTION: crypto_encrypt and crypto_decrypt structures
2774  * are identical except for field names.
2775  */
2776 static int
2777 cipher(dev_t dev, caddr_t arg, int mode,
2778     int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2779     crypto_call_req_t *))
2780 {
2781 	STRUCT_DECL(crypto_encrypt, encrypt);
2782 	crypto_session_id_t session_id;
2783 	crypto_minor_t *cm;
2784 	crypto_session_data_t *sp = NULL;
2785 	crypto_ctx_t **ctxpp;
2786 	crypto_data_t data, encr;
2787 	size_t datalen, encrlen, need = 0;
2788 	boolean_t do_inplace;
2789 	char *encrbuf;
2790 	int error = 0;
2791 	int rv;
2792 	boolean_t rctl_chk = B_FALSE;
2793 
2794 	do_inplace = B_FALSE;
2795 	STRUCT_INIT(encrypt, mode);
2796 
2797 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2798 		cmn_err(CE_WARN, "cipher: failed holding minor");
2799 		return (ENXIO);
2800 	}
2801 
2802 	if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) {
2803 		crypto_release_minor(cm);
2804 		return (EFAULT);
2805 	}
2806 
2807 	data.cd_raw.iov_base = NULL;
2808 	encr.cd_raw.iov_base = NULL;
2809 
2810 	datalen = STRUCT_FGET(encrypt, ce_datalen);
2811 	encrlen = STRUCT_FGET(encrypt, ce_encrlen);
2812 
2813 	/*
2814 	 * Don't allocate output buffer unless both buffer pointer and
2815 	 * buffer length are not NULL or 0 (length).
2816 	 */
2817 	encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf);
2818 	if (encrbuf == NULL || encrlen == 0) {
2819 		encrlen = 0;
2820 	}
2821 
2822 	if (datalen > crypto_max_buffer_len ||
2823 	    encrlen > crypto_max_buffer_len) {
2824 		cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, "
2825 		    "pid = %d", crypto_max_buffer_len, curproc->p_pid);
2826 		rv = CRYPTO_ARGUMENTS_BAD;
2827 		goto release_minor;
2828 	}
2829 
2830 	session_id = STRUCT_FGET(encrypt, ce_session);
2831 
2832 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2833 		goto release_minor;
2834 	}
2835 
2836 	do_inplace = (STRUCT_FGET(encrypt, ce_flags) &
2837 	    CRYPTO_INPLACE_OPERATION) != 0;
2838 	need = do_inplace ? datalen : datalen + encrlen;
2839 
2840 	if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
2841 	    CRYPTO_SUCCESS) {
2842 		need = 0;
2843 		goto release_minor;
2844 	}
2845 
2846 	INIT_RAW_CRYPTO_DATA(data, datalen);
2847 	data.cd_miscdata = NULL;
2848 
2849 	if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf),
2850 	    data.cd_raw.iov_base, datalen) != 0) {
2851 		error = EFAULT;
2852 		goto release_minor;
2853 	}
2854 
2855 	if (do_inplace) {
2856 		/* set out = in for in-place */
2857 		encr = data;
2858 	} else {
2859 		INIT_RAW_CRYPTO_DATA(encr, encrlen);
2860 	}
2861 
2862 	ctxpp = (single == crypto_encrypt_single) ?
2863 	    &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2864 
2865 	if (do_inplace)
2866 		/* specify in-place buffers with output = NULL */
2867 		rv = (single)(*ctxpp, &encr, NULL, NULL);
2868 	else
2869 		rv = (single)(*ctxpp, &data, &encr, NULL);
2870 
2871 	if (KCF_CONTEXT_DONE(rv))
2872 		*ctxpp = NULL;
2873 
2874 	if (rv == CRYPTO_SUCCESS) {
2875 		ASSERT(encr.cd_length <= encrlen);
2876 		if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2877 		    encrbuf, encr.cd_length) != 0) {
2878 			error = EFAULT;
2879 			goto release_minor;
2880 		}
2881 		STRUCT_FSET(encrypt, ce_encrlen,
2882 		    (ulong_t)encr.cd_length);
2883 	}
2884 
2885 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
2886 		/*
2887 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
2888 		 * of section 11.2 of the pkcs11 spec. We catch it here and
2889 		 * provide the correct pkcs11 return value.
2890 		 */
2891 		if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL)
2892 			rv = CRYPTO_SUCCESS;
2893 		STRUCT_FSET(encrypt, ce_encrlen,
2894 		    (ulong_t)encr.cd_length);
2895 	}
2896 
2897 release_minor:
2898 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
2899 	CRYPTO_SESSION_RELE(sp);
2900 	crypto_release_minor(cm);
2901 
2902 	if (data.cd_raw.iov_base != NULL)
2903 		kmem_free(data.cd_raw.iov_base, datalen);
2904 
2905 	if (!do_inplace && encr.cd_raw.iov_base != NULL)
2906 		kmem_free(encr.cd_raw.iov_base, encrlen);
2907 
2908 	if (error != 0)
2909 		return (error);
2910 
2911 	STRUCT_FSET(encrypt, ce_return_value, rv);
2912 	if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) {
2913 		return (EFAULT);
2914 	}
2915 	return (0);
2916 }
2917 
2918 /* ARGSUSED */
2919 static int
2920 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2921 {
2922 	return (cipher_update(dev, arg, mode, crypto_encrypt_update));
2923 }
2924 
2925 /* ARGSUSED */
2926 static int
2927 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2928 {
2929 	return (cipher_update(dev, arg, mode, crypto_decrypt_update));
2930 }
2931 
2932 /*
2933  * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update
2934  * structures are identical except for field names.
2935  */
2936 static int
2937 cipher_update(dev_t dev, caddr_t arg, int mode,
2938     int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2939     crypto_call_req_t *))
2940 {
2941 	STRUCT_DECL(crypto_encrypt_update, encrypt_update);
2942 	crypto_session_id_t session_id;
2943 	crypto_minor_t *cm;
2944 	crypto_session_data_t *sp = NULL;
2945 	crypto_ctx_t **ctxpp;
2946 	crypto_data_t data, encr;
2947 	size_t datalen, encrlen, need = 0;
2948 	boolean_t do_inplace;
2949 	char *encrbuf;
2950 	int error = 0;
2951 	int rv;
2952 	boolean_t rctl_chk = B_FALSE;
2953 
2954 	do_inplace = B_FALSE;
2955 	STRUCT_INIT(encrypt_update, mode);
2956 
2957 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2958 		cmn_err(CE_WARN, "cipher_update: failed holding minor");
2959 		return (ENXIO);
2960 	}
2961 
2962 	if (copyin(arg, STRUCT_BUF(encrypt_update),
2963 	    STRUCT_SIZE(encrypt_update)) != 0) {
2964 		crypto_release_minor(cm);
2965 		return (EFAULT);
2966 	}
2967 
2968 	data.cd_raw.iov_base = NULL;
2969 	encr.cd_raw.iov_base = NULL;
2970 
2971 	datalen = STRUCT_FGET(encrypt_update, eu_datalen);
2972 	encrlen = STRUCT_FGET(encrypt_update, eu_encrlen);
2973 
2974 	/*
2975 	 * Don't allocate output buffer unless both buffer pointer and
2976 	 * buffer length are not NULL or 0 (length).
2977 	 */
2978 	encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf);
2979 	if (encrbuf == NULL || encrlen == 0) {
2980 		encrlen = 0;
2981 	}
2982 
2983 	if (datalen > crypto_max_buffer_len ||
2984 	    encrlen > crypto_max_buffer_len) {
2985 		cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld "
2986 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
2987 		rv = CRYPTO_ARGUMENTS_BAD;
2988 		goto out;
2989 	}
2990 
2991 	session_id = STRUCT_FGET(encrypt_update, eu_session);
2992 
2993 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2994 		goto out;
2995 	}
2996 
2997 	do_inplace = (STRUCT_FGET(encrypt_update, eu_flags) &
2998 	    CRYPTO_INPLACE_OPERATION) != 0;
2999 	need = do_inplace ? datalen : datalen + encrlen;
3000 
3001 	if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
3002 	    CRYPTO_SUCCESS) {
3003 		need = 0;
3004 		goto out;
3005 	}
3006 
3007 	INIT_RAW_CRYPTO_DATA(data, datalen);
3008 	data.cd_miscdata = NULL;
3009 
3010 	if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf),
3011 	    data.cd_raw.iov_base, datalen) != 0) {
3012 		error = EFAULT;
3013 		goto out;
3014 	}
3015 
3016 	if (do_inplace) {
3017 		/* specify in-place buffers with output = input */
3018 		encr = data;
3019 	} else {
3020 		INIT_RAW_CRYPTO_DATA(encr, encrlen);
3021 	}
3022 
3023 	ctxpp = (update == crypto_encrypt_update) ?
3024 	    &sp->sd_encr_ctx : &sp->sd_decr_ctx;
3025 
3026 	if (do_inplace)
3027 		/* specify in-place buffers with output = NULL */
3028 		rv = (update)(*ctxpp, &encr, NULL, NULL);
3029 	else
3030 		rv = (update)(*ctxpp, &data, &encr, NULL);
3031 
3032 	if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) {
3033 		if (rv == CRYPTO_SUCCESS) {
3034 			ASSERT(encr.cd_length <= encrlen);
3035 			if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
3036 			    encrbuf, encr.cd_length) != 0) {
3037 				error = EFAULT;
3038 				goto out;
3039 			}
3040 		} else {
3041 			/*
3042 			 * The providers return CRYPTO_BUFFER_TOO_SMALL even
3043 			 * for case 1 of section 11.2 of the pkcs11 spec.
3044 			 * We catch it here and provide the correct pkcs11
3045 			 * return value.
3046 			 */
3047 			if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL)
3048 				rv = CRYPTO_SUCCESS;
3049 		}
3050 		STRUCT_FSET(encrypt_update, eu_encrlen,
3051 		    (ulong_t)encr.cd_length);
3052 	} else {
3053 		CRYPTO_CANCEL_CTX(ctxpp);
3054 	}
3055 out:
3056 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3057 	CRYPTO_SESSION_RELE(sp);
3058 	crypto_release_minor(cm);
3059 
3060 	if (data.cd_raw.iov_base != NULL)
3061 		kmem_free(data.cd_raw.iov_base, datalen);
3062 
3063 	if (!do_inplace && (encr.cd_raw.iov_base != NULL))
3064 		kmem_free(encr.cd_raw.iov_base, encrlen);
3065 
3066 	if (error != 0)
3067 		return (error);
3068 
3069 	STRUCT_FSET(encrypt_update, eu_return_value, rv);
3070 	if (copyout(STRUCT_BUF(encrypt_update), arg,
3071 	    STRUCT_SIZE(encrypt_update)) != 0) {
3072 		return (EFAULT);
3073 	}
3074 	return (0);
3075 }
3076 
3077 /* ARGSUSED */
3078 static int
3079 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
3080 {
3081 	return (common_final(dev, arg, mode, crypto_encrypt_final));
3082 }
3083 
3084 /* ARGSUSED */
3085 static int
3086 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
3087 {
3088 	return (common_final(dev, arg, mode, crypto_decrypt_final));
3089 }
3090 
3091 /*
3092  * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final,
3093  * and crypto_digest_final structures are identical except for field names.
3094  */
3095 static int
3096 common_final(dev_t dev, caddr_t arg, int mode,
3097     int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
3098 {
3099 	STRUCT_DECL(crypto_encrypt_final, encrypt_final);
3100 	crypto_session_id_t session_id;
3101 	crypto_minor_t *cm;
3102 	crypto_session_data_t *sp = NULL;
3103 	crypto_ctx_t **ctxpp;
3104 	crypto_data_t encr;
3105 	size_t encrlen, need = 0;
3106 	char *encrbuf;
3107 	int error = 0;
3108 	int rv;
3109 	boolean_t rctl_chk = B_FALSE;
3110 
3111 	STRUCT_INIT(encrypt_final, mode);
3112 
3113 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3114 		cmn_err(CE_WARN, "common_final: failed holding minor");
3115 		return (ENXIO);
3116 	}
3117 
3118 	if (copyin(arg, STRUCT_BUF(encrypt_final),
3119 	    STRUCT_SIZE(encrypt_final)) != 0) {
3120 		crypto_release_minor(cm);
3121 		return (EFAULT);
3122 	}
3123 
3124 	encr.cd_format = CRYPTO_DATA_RAW;
3125 	encr.cd_raw.iov_base = NULL;
3126 
3127 	encrlen = STRUCT_FGET(encrypt_final, ef_encrlen);
3128 
3129 	/*
3130 	 * Don't allocate output buffer unless both buffer pointer and
3131 	 * buffer length are not NULL or 0 (length).
3132 	 */
3133 	encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf);
3134 	if (encrbuf == NULL || encrlen == 0) {
3135 		encrlen = 0;
3136 	}
3137 
3138 	if (encrlen > crypto_max_buffer_len) {
3139 		cmn_err(CE_NOTE, "common_final: buffer greater than %ld "
3140 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3141 		rv = CRYPTO_ARGUMENTS_BAD;
3142 		goto release_minor;
3143 	}
3144 
3145 	session_id = STRUCT_FGET(encrypt_final, ef_session);
3146 
3147 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3148 		goto release_minor;
3149 	}
3150 
3151 	if ((rv = CRYPTO_BUFFER_CHECK(sp, encrlen, rctl_chk)) !=
3152 	    CRYPTO_SUCCESS) {
3153 		goto release_minor;
3154 	}
3155 	need = encrlen;
3156 	encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP);
3157 	encr.cd_raw.iov_len = encrlen;
3158 
3159 	encr.cd_offset = 0;
3160 	encr.cd_length = encrlen;
3161 
3162 	ASSERT(final == crypto_encrypt_final ||
3163 	    final == crypto_decrypt_final || final == crypto_sign_final ||
3164 	    final == crypto_digest_final || final == crypto_mac_final);
3165 
3166 	if (final == crypto_encrypt_final) {
3167 		ctxpp = &sp->sd_encr_ctx;
3168 	} else if (final == crypto_decrypt_final) {
3169 		ctxpp = &sp->sd_decr_ctx;
3170 	} else if (final == crypto_sign_final) {
3171 		ctxpp = &sp->sd_sign_ctx;
3172 	} else if (final == crypto_mac_final) {
3173 		ctxpp = &sp->sd_mac_ctx;
3174 	} else {
3175 		ctxpp = &sp->sd_digest_ctx;
3176 	}
3177 
3178 	rv = (final)(*ctxpp, &encr, NULL);
3179 	if (KCF_CONTEXT_DONE(rv))
3180 		*ctxpp = NULL;
3181 
3182 	if (rv == CRYPTO_SUCCESS) {
3183 		ASSERT(encr.cd_length <= encrlen);
3184 		if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
3185 		    encrbuf, encr.cd_length) != 0) {
3186 			error = EFAULT;
3187 			goto release_minor;
3188 		}
3189 		STRUCT_FSET(encrypt_final, ef_encrlen,
3190 		    (ulong_t)encr.cd_length);
3191 	}
3192 
3193 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3194 		/*
3195 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3196 		 * of section 11.2 of the pkcs11 spec. We catch it here and
3197 		 * provide the correct pkcs11 return value.
3198 		 */
3199 		if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL)
3200 			rv = CRYPTO_SUCCESS;
3201 		STRUCT_FSET(encrypt_final, ef_encrlen,
3202 		    (ulong_t)encr.cd_length);
3203 	}
3204 
3205 release_minor:
3206 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3207 	CRYPTO_SESSION_RELE(sp);
3208 	crypto_release_minor(cm);
3209 
3210 	if (encr.cd_raw.iov_base != NULL)
3211 		kmem_free(encr.cd_raw.iov_base, encrlen);
3212 
3213 	if (error != 0)
3214 		return (error);
3215 
3216 	STRUCT_FSET(encrypt_final, ef_return_value, rv);
3217 	if (copyout(STRUCT_BUF(encrypt_final), arg,
3218 	    STRUCT_SIZE(encrypt_final)) != 0) {
3219 		return (EFAULT);
3220 	}
3221 	return (0);
3222 }
3223 
3224 /* ARGSUSED */
3225 static int
3226 digest_init(dev_t dev, caddr_t arg, int mode, int *rval)
3227 {
3228 	STRUCT_DECL(crypto_digest_init, digest_init);
3229 	kcf_provider_desc_t *real_provider = NULL;
3230 	crypto_session_id_t session_id;
3231 	crypto_mechanism_t mech;
3232 	crypto_minor_t *cm;
3233 	crypto_session_data_t *sp = NULL;
3234 	crypto_context_t cc;
3235 	size_t rctl_bytes = 0;
3236 	boolean_t rctl_chk = B_FALSE;
3237 	int error = 0;
3238 	int rv;
3239 
3240 	STRUCT_INIT(digest_init, mode);
3241 
3242 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3243 		cmn_err(CE_WARN, "digest_init: failed holding minor");
3244 		return (ENXIO);
3245 	}
3246 
3247 	if (copyin(arg, STRUCT_BUF(digest_init),
3248 	    STRUCT_SIZE(digest_init)) != 0) {
3249 		crypto_release_minor(cm);
3250 		return (EFAULT);
3251 	}
3252 
3253 	mech.cm_param = NULL;
3254 
3255 	session_id = STRUCT_FGET(digest_init, di_session);
3256 
3257 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3258 		goto out;
3259 	}
3260 
3261 	if (!copyin_mech(mode, sp, STRUCT_FADDR(digest_init, di_mech), &mech,
3262 	    &rctl_bytes, &rctl_chk, &rv, &error)) {
3263 		goto out;
3264 	}
3265 
3266 	if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
3267 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider,
3268 	    CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) {
3269 		goto out;
3270 	}
3271 
3272 	rv = crypto_digest_init_prov(real_provider,
3273 	    sp->sd_provider_session->ps_session, &mech, &cc, NULL);
3274 
3275 	/*
3276 	 * Check if a context already exists. If so, it means it is being
3277 	 * abandoned. So, cancel it to avoid leaking it.
3278 	 */
3279 	if (sp->sd_digest_ctx != NULL)
3280 		CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3281 	sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL;
3282 out:
3283 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
3284 	CRYPTO_SESSION_RELE(sp);
3285 	crypto_release_minor(cm);
3286 
3287 	if (real_provider != NULL)
3288 		KCF_PROV_REFRELE(real_provider);
3289 
3290 	if (mech.cm_param != NULL)
3291 		kmem_free(mech.cm_param, mech.cm_param_len);
3292 
3293 	if (error != 0)
3294 		return (error);
3295 
3296 	STRUCT_FSET(digest_init, di_return_value, rv);
3297 	if (copyout(STRUCT_BUF(digest_init), arg,
3298 	    STRUCT_SIZE(digest_init)) != 0) {
3299 		return (EFAULT);
3300 	}
3301 	return (0);
3302 }
3303 
3304 /* ARGSUSED */
3305 static int
3306 digest_update(dev_t dev, caddr_t arg, int mode, int *rval)
3307 {
3308 	STRUCT_DECL(crypto_digest_update, digest_update);
3309 	crypto_session_id_t session_id;
3310 	crypto_minor_t *cm;
3311 	crypto_session_data_t *sp = NULL;
3312 	crypto_data_t data;
3313 	size_t datalen, need = 0;
3314 	int error = 0;
3315 	int rv;
3316 	boolean_t rctl_chk = B_FALSE;
3317 
3318 	STRUCT_INIT(digest_update, mode);
3319 
3320 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3321 		cmn_err(CE_WARN, "digest_update: failed holding minor");
3322 		return (ENXIO);
3323 	}
3324 
3325 	if (copyin(arg, STRUCT_BUF(digest_update),
3326 	    STRUCT_SIZE(digest_update)) != 0) {
3327 		crypto_release_minor(cm);
3328 		return (EFAULT);
3329 	}
3330 
3331 	data.cd_format = CRYPTO_DATA_RAW;
3332 	data.cd_raw.iov_base = NULL;
3333 
3334 	datalen = STRUCT_FGET(digest_update, du_datalen);
3335 	if (datalen > crypto_max_buffer_len) {
3336 		cmn_err(CE_NOTE, "digest_update: buffer greater than %ld "
3337 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3338 		rv = CRYPTO_ARGUMENTS_BAD;
3339 		goto release_minor;
3340 	}
3341 
3342 	session_id = STRUCT_FGET(digest_update, du_session);
3343 
3344 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3345 		goto release_minor;
3346 	}
3347 
3348 	if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) !=
3349 	    CRYPTO_SUCCESS) {
3350 		goto release_minor;
3351 	}
3352 
3353 	need = datalen;
3354 	data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP);
3355 	data.cd_raw.iov_len = datalen;
3356 
3357 	if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf),
3358 	    data.cd_raw.iov_base, datalen) != 0) {
3359 		error = EFAULT;
3360 		goto release_minor;
3361 	}
3362 
3363 	data.cd_offset = 0;
3364 	data.cd_length = datalen;
3365 
3366 	rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL);
3367 	if (rv != CRYPTO_SUCCESS)
3368 		CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3369 
3370 release_minor:
3371 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3372 	CRYPTO_SESSION_RELE(sp);
3373 	crypto_release_minor(cm);
3374 
3375 	if (data.cd_raw.iov_base != NULL)
3376 		kmem_free(data.cd_raw.iov_base, datalen);
3377 
3378 	if (error != 0)
3379 		return (error);
3380 
3381 	STRUCT_FSET(digest_update, du_return_value, rv);
3382 	if (copyout(STRUCT_BUF(digest_update), arg,
3383 	    STRUCT_SIZE(digest_update)) != 0) {
3384 		return (EFAULT);
3385 	}
3386 	return (0);
3387 }
3388 
3389 /* ARGSUSED */
3390 static int
3391 digest_key(dev_t dev, caddr_t arg, int mode, int *rval)
3392 {
3393 	STRUCT_DECL(crypto_digest_key, digest_key);
3394 	crypto_session_id_t session_id;
3395 	crypto_key_t key;
3396 	crypto_minor_t *cm;
3397 	crypto_session_data_t *sp = NULL;
3398 	size_t rctl_bytes = 0;
3399 	boolean_t key_rctl_chk = B_FALSE;
3400 	int error = 0;
3401 	int rv;
3402 
3403 	STRUCT_INIT(digest_key, mode);
3404 
3405 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3406 		cmn_err(CE_WARN, "digest_key: failed holding minor");
3407 		return (ENXIO);
3408 	}
3409 
3410 	if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) {
3411 		crypto_release_minor(cm);
3412 		return (EFAULT);
3413 	}
3414 
3415 	bzero(&key, sizeof (crypto_key_t));
3416 
3417 	session_id = STRUCT_FGET(digest_key, dk_session);
3418 
3419 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3420 		goto out;
3421 	}
3422 
3423 	if (!copyin_key(mode, sp, STRUCT_FADDR(digest_key, dk_key), &key,
3424 	    &rctl_bytes, &key_rctl_chk, &rv, &error)) {
3425 		goto out;
3426 	}
3427 
3428 	rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL);
3429 	if (rv != CRYPTO_SUCCESS)
3430 		CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3431 out:
3432 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, key_rctl_chk);
3433 	CRYPTO_SESSION_RELE(sp);
3434 	crypto_release_minor(cm);
3435 
3436 	free_crypto_key(&key);
3437 
3438 	if (error != 0)
3439 		return (error);
3440 
3441 	STRUCT_FSET(digest_key, dk_return_value, rv);
3442 	if (copyout(STRUCT_BUF(digest_key), arg,
3443 	    STRUCT_SIZE(digest_key)) != 0) {
3444 		return (EFAULT);
3445 	}
3446 	return (0);
3447 }
3448 
3449 /* ARGSUSED */
3450 static int
3451 digest_final(dev_t dev, caddr_t arg, int mode, int *rval)
3452 {
3453 	return (common_final(dev, arg, mode, crypto_digest_final));
3454 }
3455 
3456 /* ARGSUSED */
3457 static int
3458 digest(dev_t dev, caddr_t arg, int mode, int *rval)
3459 {
3460 	return (common_digest(dev, arg, mode, crypto_digest_single));
3461 }
3462 
3463 static int
3464 mac_init(dev_t dev, caddr_t arg, int mode, int *rval)
3465 {
3466 	_NOTE(ARGUNUSED(rval))
3467 	return (sign_verify_init(dev, arg, mode, crypto_mac_init_prov));
3468 }
3469 
3470 static int
3471 mac_update(dev_t dev, caddr_t arg, int mode, int *rval)
3472 {
3473 	_NOTE(ARGUNUSED(rval))
3474 	return (sign_verify_update(dev, arg, mode, crypto_mac_update));
3475 }
3476 
3477 static int
3478 mac_final(dev_t dev, caddr_t arg, int mode, int *rval)
3479 {
3480 	_NOTE(ARGUNUSED(rval))
3481 	return (common_final(dev, arg, mode, crypto_mac_final));
3482 }
3483 
3484 /* ARGSUSED */
3485 static int
3486 mac(dev_t dev, caddr_t arg, int mode, int *rval)
3487 {
3488 	_NOTE(ARGUNUSED(rval))
3489 	return (common_digest(dev, arg, mode, crypto_mac_single));
3490 }
3491 
3492 /*
3493  * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
3494  * and crypto_verify_recover are identical except for field names.
3495  */
3496 static int
3497 common_digest(dev_t dev, caddr_t arg, int mode,
3498     int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
3499     crypto_call_req_t *))
3500 {
3501 	STRUCT_DECL(crypto_digest, crypto_digest);
3502 	crypto_session_id_t session_id;
3503 	crypto_minor_t *cm;
3504 	crypto_session_data_t *sp = NULL;
3505 	crypto_data_t data, digest;
3506 	crypto_ctx_t **ctxpp;
3507 	size_t datalen, digestlen, need = 0;
3508 	char *digestbuf;
3509 	int error = 0;
3510 	int rv;
3511 	boolean_t rctl_chk = B_FALSE;
3512 
3513 	STRUCT_INIT(crypto_digest, mode);
3514 
3515 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3516 		cmn_err(CE_WARN, "common_digest: failed holding minor");
3517 		return (ENXIO);
3518 	}
3519 
3520 	if (copyin(arg, STRUCT_BUF(crypto_digest),
3521 	    STRUCT_SIZE(crypto_digest)) != 0) {
3522 		crypto_release_minor(cm);
3523 		return (EFAULT);
3524 	}
3525 
3526 	data.cd_raw.iov_base = NULL;
3527 	digest.cd_raw.iov_base = NULL;
3528 	data.cd_miscdata = NULL;
3529 	digest.cd_miscdata = NULL;
3530 
3531 	datalen = STRUCT_FGET(crypto_digest, cd_datalen);
3532 	digestlen = STRUCT_FGET(crypto_digest, cd_digestlen);
3533 
3534 	/*
3535 	 * Don't allocate output buffer unless both buffer pointer and
3536 	 * buffer length are not NULL or 0 (length).
3537 	 */
3538 	digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf);
3539 	if (digestbuf == NULL || digestlen == 0) {
3540 		digestlen = 0;
3541 	}
3542 
3543 	if (datalen > crypto_max_buffer_len ||
3544 	    digestlen > crypto_max_buffer_len) {
3545 		cmn_err(CE_NOTE, "common_digest: buffer greater than %ld "
3546 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3547 		rv = CRYPTO_ARGUMENTS_BAD;
3548 		goto release_minor;
3549 	}
3550 
3551 	session_id = STRUCT_FGET(crypto_digest, cd_session);
3552 
3553 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3554 		goto release_minor;
3555 	}
3556 
3557 	need = datalen + digestlen;
3558 	if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
3559 	    CRYPTO_SUCCESS) {
3560 		need = 0;
3561 		goto release_minor;
3562 	}
3563 
3564 	INIT_RAW_CRYPTO_DATA(data, datalen);
3565 
3566 	if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf),
3567 	    data.cd_raw.iov_base, datalen) != 0) {
3568 		error = EFAULT;
3569 		goto release_minor;
3570 	}
3571 
3572 	INIT_RAW_CRYPTO_DATA(digest, digestlen);
3573 
3574 	ASSERT(single == crypto_digest_single ||
3575 	    single == crypto_sign_single ||
3576 	    single == crypto_verify_recover_single ||
3577 	    single == crypto_sign_recover_single ||
3578 	    single == crypto_mac_single);
3579 
3580 	if (single == crypto_digest_single) {
3581 		ctxpp = &sp->sd_digest_ctx;
3582 	} else if (single == crypto_sign_single) {
3583 		ctxpp = &sp->sd_sign_ctx;
3584 	} else if (single == crypto_verify_recover_single) {
3585 		ctxpp = &sp->sd_verify_recover_ctx;
3586 	} else if (single == crypto_mac_single) {
3587 		ctxpp = &sp->sd_mac_ctx;
3588 	} else {
3589 		ctxpp = &sp->sd_sign_recover_ctx;
3590 	}
3591 	rv = (single)(*ctxpp, &data, &digest, NULL);
3592 	if (KCF_CONTEXT_DONE(rv))
3593 		*ctxpp = NULL;
3594 
3595 	if (rv == CRYPTO_SUCCESS) {
3596 		ASSERT(digest.cd_length <= digestlen);
3597 		if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base,
3598 		    digestbuf, digest.cd_length) != 0) {
3599 			error = EFAULT;
3600 			goto release_minor;
3601 		}
3602 		STRUCT_FSET(crypto_digest, cd_digestlen,
3603 		    (ulong_t)digest.cd_length);
3604 	}
3605 
3606 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3607 		/*
3608 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3609 		 * of section 11.2 of the pkcs11 spec. We catch it here and
3610 		 * provide the correct pkcs11 return value.
3611 		 */
3612 		if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL)
3613 			rv = CRYPTO_SUCCESS;
3614 		STRUCT_FSET(crypto_digest, cd_digestlen,
3615 		    (ulong_t)digest.cd_length);
3616 	}
3617 
3618 release_minor:
3619 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3620 	CRYPTO_SESSION_RELE(sp);
3621 	crypto_release_minor(cm);
3622 
3623 	if (data.cd_raw.iov_base != NULL)
3624 		kmem_free(data.cd_raw.iov_base, datalen);
3625 
3626 	if (digest.cd_raw.iov_base != NULL)
3627 		kmem_free(digest.cd_raw.iov_base, digestlen);
3628 
3629 	if (error != 0)
3630 		return (error);
3631 
3632 	STRUCT_FSET(crypto_digest, cd_return_value, rv);
3633 	if (copyout(STRUCT_BUF(crypto_digest), arg,
3634 	    STRUCT_SIZE(crypto_digest)) != 0) {
3635 		return (EFAULT);
3636 	}
3637 	return (0);
3638 }
3639 
3640 /*
3641  * A helper function that does what the name suggests.
3642  * Returns 0 on success and non-zero otherwise.
3643  * On failure, out_pin is set to 0.
3644  */
3645 int
3646 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len,
3647     crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp,
3648     int *rv, int *error)
3649 {
3650 	char *tmp_pin = NULL;
3651 	int tmp_error = 0, tmp_rv = 0;
3652 
3653 	if (pin_len > KCF_MAX_PIN_LEN) {
3654 		tmp_rv = CRYPTO_PIN_LEN_RANGE;
3655 		goto out;
3656 	}
3657 	tmp_pin = kmem_alloc(pin_len, KM_SLEEP);
3658 
3659 	if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) {
3660 		tmp_error = EFAULT;
3661 		goto out;
3662 	}
3663 
3664 	(void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv);
3665 out:
3666 	*out_pin = tmp_pin;
3667 	*rv = tmp_rv;
3668 	*error = tmp_error;
3669 	return (tmp_rv | tmp_error);
3670 }
3671 
3672 /* ARGSUSED */
3673 static int
3674 set_pin(dev_t dev, caddr_t arg, int mode, int *rval)
3675 {
3676 	STRUCT_DECL(crypto_set_pin, set_pin);
3677 	kcf_provider_desc_t *real_provider;
3678 	kcf_req_params_t params;
3679 	crypto_minor_t *cm;
3680 	crypto_session_data_t *sp;
3681 	char *old_pin = NULL;
3682 	char *new_pin = NULL;
3683 	size_t old_pin_len;
3684 	size_t new_pin_len;
3685 	int error = 0;
3686 	int rv;
3687 
3688 	STRUCT_INIT(set_pin, mode);
3689 
3690 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3691 		cmn_err(CE_WARN, "set_pin: failed holding minor");
3692 		return (ENXIO);
3693 	}
3694 
3695 	if (copyin(arg, STRUCT_BUF(set_pin),
3696 	    STRUCT_SIZE(set_pin)) != 0) {
3697 		crypto_release_minor(cm);
3698 		return (EFAULT);
3699 	}
3700 
3701 	old_pin_len = STRUCT_FGET(set_pin, sp_old_len);
3702 
3703 	if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin),
3704 	    &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session),
3705 	    &sp, &rv, &error) != 0)
3706 		goto release_minor;
3707 
3708 	new_pin_len = STRUCT_FGET(set_pin, sp_new_len);
3709 	if (new_pin_len > KCF_MAX_PIN_LEN) {
3710 		rv = CRYPTO_PIN_LEN_RANGE;
3711 		goto out;
3712 	}
3713 	new_pin = kmem_alloc(new_pin_len, KM_SLEEP);
3714 
3715 	if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin),
3716 	    new_pin, new_pin_len) != 0) {
3717 		error = EFAULT;
3718 		goto out;
3719 	}
3720 
3721 	if ((rv = kcf_get_hardware_provider_nomech(
3722 	    CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin),
3723 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
3724 		goto out;
3725 	}
3726 
3727 	KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_SETPIN,
3728 	    sp->sd_provider_session->ps_session, old_pin, old_pin_len,
3729 	    new_pin, new_pin_len, NULL, NULL, real_provider);
3730 
3731 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3732 	KCF_PROV_REFRELE(real_provider);
3733 
3734 out:
3735 	CRYPTO_SESSION_RELE(sp);
3736 
3737 release_minor:
3738 	crypto_release_minor(cm);
3739 
3740 	if (old_pin != NULL) {
3741 		bzero(old_pin, old_pin_len);
3742 		kmem_free(old_pin, old_pin_len);
3743 	}
3744 
3745 	if (new_pin != NULL) {
3746 		bzero(new_pin, new_pin_len);
3747 		kmem_free(new_pin, new_pin_len);
3748 	}
3749 
3750 	if (error != 0)
3751 		return (error);
3752 
3753 	STRUCT_FSET(set_pin, sp_return_value, rv);
3754 	if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) {
3755 		return (EFAULT);
3756 	}
3757 	return (0);
3758 }
3759 
3760 /* ARGSUSED */
3761 static int
3762 login(dev_t dev, caddr_t arg, int mode, int *rval)
3763 {
3764 	STRUCT_DECL(crypto_login, login);
3765 	kcf_provider_desc_t *real_provider;
3766 	kcf_req_params_t params;
3767 	crypto_minor_t *cm;
3768 	crypto_session_data_t *sp;
3769 	size_t pin_len;
3770 	char *pin;
3771 	uint_t user_type;
3772 	int error = 0;
3773 	int rv;
3774 
3775 	STRUCT_INIT(login, mode);
3776 
3777 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3778 		cmn_err(CE_WARN, "login: failed holding minor");
3779 		return (ENXIO);
3780 	}
3781 
3782 	if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) {
3783 		crypto_release_minor(cm);
3784 		return (EFAULT);
3785 	}
3786 
3787 	user_type = STRUCT_FGET(login, co_user_type);
3788 
3789 	pin_len = STRUCT_FGET(login, co_pin_len);
3790 
3791 	if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin),
3792 	    &pin, pin_len, cm, STRUCT_FGET(login, co_session),
3793 	    &sp, &rv, &error) != 0) {
3794 		if (rv == CRYPTO_PIN_LEN_RANGE)
3795 			rv = CRYPTO_PIN_INCORRECT;
3796 		goto release_minor;
3797 	}
3798 
3799 	if ((rv = kcf_get_hardware_provider_nomech(
3800 	    CRYPTO_OPS_OFFSET(session_ops),
3801 	    CRYPTO_SESSION_OFFSET(session_login), sp->sd_provider,
3802 	    &real_provider)) != CRYPTO_SUCCESS) {
3803 		goto out;
3804 	}
3805 
3806 	KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGIN, NULL,
3807 	    sp->sd_provider_session->ps_session, user_type, pin, pin_len,
3808 	    real_provider);
3809 
3810 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3811 	KCF_PROV_REFRELE(real_provider);
3812 
3813 out:
3814 	CRYPTO_SESSION_RELE(sp);
3815 
3816 release_minor:
3817 	crypto_release_minor(cm);
3818 
3819 	if (pin != NULL) {
3820 		bzero(pin, pin_len);
3821 		kmem_free(pin, pin_len);
3822 	}
3823 
3824 	if (error != 0)
3825 		return (error);
3826 
3827 	STRUCT_FSET(login, co_return_value, rv);
3828 	if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) {
3829 		return (EFAULT);
3830 	}
3831 	return (0);
3832 }
3833 
3834 /* ARGSUSED */
3835 static int
3836 logout(dev_t dev, caddr_t arg, int mode, int *rval)
3837 {
3838 	crypto_logout_t logout;
3839 	kcf_provider_desc_t *real_provider;
3840 	kcf_req_params_t params;
3841 	crypto_minor_t *cm;
3842 	crypto_session_data_t *sp;
3843 	int error = 0;
3844 	int rv;
3845 
3846 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3847 		cmn_err(CE_WARN, "logout: failed holding minor");
3848 		return (ENXIO);
3849 	}
3850 
3851 	if (copyin(arg, &logout, sizeof (logout)) != 0) {
3852 		crypto_release_minor(cm);
3853 		return (EFAULT);
3854 	}
3855 
3856 	if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv))  {
3857 		goto release_minor;
3858 	}
3859 
3860 	if ((rv = kcf_get_hardware_provider_nomech(
3861 	    CRYPTO_OPS_OFFSET(session_ops),
3862 	    CRYPTO_SESSION_OFFSET(session_logout), sp->sd_provider,
3863 	    &real_provider)) != CRYPTO_SUCCESS) {
3864 		goto out;
3865 	}
3866 
3867 	KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGOUT, NULL,
3868 	    sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider);
3869 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3870 	KCF_PROV_REFRELE(real_provider);
3871 
3872 out:
3873 	CRYPTO_SESSION_RELE(sp);
3874 
3875 release_minor:
3876 	crypto_release_minor(cm);
3877 
3878 	if (error != 0)
3879 		return (error);
3880 
3881 	logout.cl_return_value = rv;
3882 	if (copyout(&logout, arg, sizeof (logout)) != 0) {
3883 		return (EFAULT);
3884 	}
3885 	return (0);
3886 }
3887 
3888 /* ARGSUSED */
3889 static int
3890 sign_init(dev_t dev, caddr_t arg, int mode, int *rval)
3891 {
3892 	return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov));
3893 }
3894 
3895 /* ARGSUSED */
3896 static int
3897 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3898 {
3899 	return (sign_verify_init(dev, arg, mode,
3900 	    crypto_sign_recover_init_prov));
3901 }
3902 
3903 /* ARGSUSED */
3904 static int
3905 verify_init(dev_t dev, caddr_t arg, int mode, int *rval)
3906 {
3907 	return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov));
3908 }
3909 
3910 /* ARGSUSED */
3911 static int
3912 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3913 {
3914 	return (sign_verify_init(dev, arg, mode,
3915 	    crypto_verify_recover_init_prov));
3916 }
3917 
3918 /*
3919  * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init,
3920  * and crypto_verify_recover_init structures are identical
3921  * except for field names.
3922  */
3923 static int
3924 sign_verify_init(dev_t dev, caddr_t arg, int mode,
3925     int (*init)(crypto_provider_t, crypto_session_id_t,
3926     crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t,
3927     crypto_context_t *, crypto_call_req_t *))
3928 {
3929 	STRUCT_DECL(crypto_sign_init, sign_init);
3930 	kcf_provider_desc_t *real_provider = NULL;
3931 	crypto_session_id_t session_id;
3932 	crypto_mechanism_t mech;
3933 	crypto_key_t key;
3934 	crypto_minor_t *cm;
3935 	crypto_session_data_t *sp = NULL;
3936 	crypto_context_t cc;
3937 	crypto_ctx_t **ctxpp;
3938 	size_t mech_rctl_bytes = 0;
3939 	boolean_t mech_rctl_chk = B_FALSE;
3940 	size_t key_rctl_bytes = 0;
3941 	boolean_t key_rctl_chk = B_FALSE;
3942 	int error = 0;
3943 	int rv;
3944 	boolean_t allocated_by_crypto_module = B_FALSE;
3945 	crypto_func_group_t fg;
3946 
3947 	STRUCT_INIT(sign_init, mode);
3948 
3949 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3950 		cmn_err(CE_WARN, "sign_verify_init: failed holding minor");
3951 		return (ENXIO);
3952 	}
3953 
3954 	if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) {
3955 		crypto_release_minor(cm);
3956 		return (EFAULT);
3957 	}
3958 
3959 	mech.cm_param = NULL;
3960 	bzero(&key, sizeof (key));
3961 
3962 	session_id = STRUCT_FGET(sign_init, si_session);
3963 
3964 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3965 		goto out;
3966 	}
3967 
3968 	bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type,
3969 	    sizeof (crypto_mech_type_t));
3970 
3971 	ASSERT(init == crypto_sign_init_prov ||
3972 	    init == crypto_verify_init_prov ||
3973 	    init == crypto_sign_recover_init_prov ||
3974 	    init == crypto_verify_recover_init_prov ||
3975 	    init == crypto_mac_init_prov);
3976 
3977 	if (init == crypto_sign_init_prov) {
3978 		fg =  CRYPTO_FG_SIGN;
3979 		ctxpp = &sp->sd_sign_ctx;
3980 	} else if (init == crypto_verify_init_prov) {
3981 		fg =  CRYPTO_FG_VERIFY;
3982 		ctxpp = &sp->sd_verify_ctx;
3983 	} else if (init == crypto_sign_recover_init_prov) {
3984 		fg =  CRYPTO_FG_SIGN_RECOVER;
3985 		ctxpp = &sp->sd_sign_recover_ctx;
3986 	} else if (init == crypto_mac_init_prov) {
3987 		fg =  CRYPTO_FG_MAC;
3988 		ctxpp = &sp->sd_mac_ctx;
3989 	} else {
3990 		fg =  CRYPTO_FG_VERIFY_RECOVER;
3991 		ctxpp = &sp->sd_verify_recover_ctx;
3992 	}
3993 
3994 	/* We need the key length for provider selection so copy it in now. */
3995 	if (!copyin_key(mode, sp, STRUCT_FADDR(sign_init, si_key), &key,
3996 	    &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
3997 		goto out;
3998 	}
3999 
4000 	if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
4001 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider,
4002 	    fg)) != CRYPTO_SUCCESS) {
4003 		goto out;
4004 	}
4005 
4006 	rv = crypto_provider_copyin_mech_param(real_provider,
4007 	    STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error);
4008 
4009 	if (rv == CRYPTO_NOT_SUPPORTED) {
4010 		allocated_by_crypto_module = B_TRUE;
4011 		if (!copyin_mech(mode, sp, STRUCT_FADDR(sign_init, si_mech),
4012 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
4013 			goto out;
4014 		}
4015 	} else {
4016 		if (rv != CRYPTO_SUCCESS)
4017 			goto out;
4018 	}
4019 
4020 	rv = (init)(real_provider, sp->sd_provider_session->ps_session,
4021 	    &mech, &key, NULL, &cc, NULL);
4022 
4023 	/*
4024 	 * Check if a context already exists. If so, it means it is being
4025 	 * abandoned. So, cancel it to avoid leaking it.
4026 	 */
4027 	if (*ctxpp != NULL)
4028 		CRYPTO_CANCEL_CTX(ctxpp);
4029 	*ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
4030 
4031 out:
4032 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
4033 	CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
4034 	CRYPTO_SESSION_RELE(sp);
4035 	crypto_release_minor(cm);
4036 
4037 	if (real_provider != NULL) {
4038 		crypto_free_mech(real_provider,
4039 		    allocated_by_crypto_module, &mech);
4040 		KCF_PROV_REFRELE(real_provider);
4041 	}
4042 
4043 	free_crypto_key(&key);
4044 
4045 	if (error != 0)
4046 		return (error);
4047 
4048 	STRUCT_FSET(sign_init, si_return_value, rv);
4049 	if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) {
4050 		return (EFAULT);
4051 	}
4052 	return (0);
4053 }
4054 
4055 /* ARGSUSED */
4056 static int
4057 sign(dev_t dev, caddr_t arg, int mode, int *rval)
4058 {
4059 	return (common_digest(dev, arg, mode, crypto_sign_single));
4060 }
4061 
4062 /* ARGSUSED */
4063 static int
4064 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval)
4065 {
4066 	return (common_digest(dev, arg, mode, crypto_sign_recover_single));
4067 }
4068 
4069 /* ARGSUSED */
4070 static int
4071 verify(dev_t dev, caddr_t arg, int mode, int *rval)
4072 {
4073 	STRUCT_DECL(crypto_verify, verify);
4074 	crypto_session_id_t session_id;
4075 	crypto_minor_t *cm;
4076 	crypto_session_data_t *sp = NULL;
4077 	crypto_data_t data, sign;
4078 	size_t datalen, signlen, need = 0;
4079 	int error = 0;
4080 	int rv;
4081 	boolean_t rctl_chk = B_FALSE;
4082 
4083 	STRUCT_INIT(verify, mode);
4084 
4085 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4086 		cmn_err(CE_WARN, "verify: failed holding minor");
4087 		return (ENXIO);
4088 	}
4089 
4090 	if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) {
4091 		crypto_release_minor(cm);
4092 		return (EFAULT);
4093 	}
4094 
4095 	data.cd_raw.iov_base = NULL;
4096 	sign.cd_raw.iov_base = NULL;
4097 
4098 	datalen = STRUCT_FGET(verify, cv_datalen);
4099 	signlen = STRUCT_FGET(verify, cv_signlen);
4100 	if (datalen > crypto_max_buffer_len ||
4101 	    signlen > crypto_max_buffer_len) {
4102 		cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, "
4103 		"pid = %d", crypto_max_buffer_len, curproc->p_pid);
4104 		rv = CRYPTO_ARGUMENTS_BAD;
4105 		goto release_minor;
4106 	}
4107 
4108 	session_id = STRUCT_FGET(verify, cv_session);
4109 
4110 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4111 		goto release_minor;
4112 	}
4113 
4114 	need = datalen + signlen;
4115 	if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
4116 	    CRYPTO_SUCCESS) {
4117 		need = 0;
4118 		goto release_minor;
4119 	}
4120 
4121 	INIT_RAW_CRYPTO_DATA(data, datalen);
4122 	INIT_RAW_CRYPTO_DATA(sign, signlen);
4123 
4124 	if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf),
4125 	    data.cd_raw.iov_base, datalen) != 0) {
4126 		error = EFAULT;
4127 		goto release_minor;
4128 	}
4129 
4130 	if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf),
4131 	    sign.cd_raw.iov_base, signlen) != 0) {
4132 		error = EFAULT;
4133 		goto release_minor;
4134 	}
4135 
4136 	rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL);
4137 	if (KCF_CONTEXT_DONE(rv))
4138 		sp->sd_verify_ctx = NULL;
4139 
4140 release_minor:
4141 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4142 	CRYPTO_SESSION_RELE(sp);
4143 	crypto_release_minor(cm);
4144 
4145 	if (data.cd_raw.iov_base != NULL)
4146 		kmem_free(data.cd_raw.iov_base, datalen);
4147 
4148 	if (sign.cd_raw.iov_base != NULL)
4149 		kmem_free(sign.cd_raw.iov_base, signlen);
4150 
4151 	if (error != 0)
4152 		return (error);
4153 
4154 	STRUCT_FSET(verify, cv_return_value, rv);
4155 	if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) {
4156 		return (EFAULT);
4157 	}
4158 	return (0);
4159 }
4160 
4161 /* ARGSUSED */
4162 static int
4163 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval)
4164 {
4165 	return (common_digest(dev, arg, mode, crypto_verify_recover_single));
4166 }
4167 
4168 /* ARGSUSED */
4169 static int
4170 sign_update(dev_t dev, caddr_t arg, int mode, int *rval)
4171 {
4172 	return (sign_verify_update(dev, arg, mode, crypto_sign_update));
4173 }
4174 
4175 /* ARGSUSED */
4176 static int
4177 verify_update(dev_t dev, caddr_t arg, int mode, int *rval)
4178 {
4179 	return (sign_verify_update(dev, arg, mode, crypto_verify_update));
4180 }
4181 
4182 /*
4183  * ASSUMPTION: crypto_sign_update and crypto_verify_update structures
4184  * are identical except for field names.
4185  */
4186 static int
4187 sign_verify_update(dev_t dev, caddr_t arg, int mode,
4188     int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
4189 {
4190 	STRUCT_DECL(crypto_sign_update, sign_update);
4191 	crypto_session_id_t session_id;
4192 	crypto_minor_t *cm;
4193 	crypto_session_data_t *sp = NULL;
4194 	crypto_ctx_t **ctxpp;
4195 	crypto_data_t data;
4196 	size_t datalen, need = 0;
4197 	int error = 0;
4198 	int rv;
4199 	boolean_t rctl_chk = B_FALSE;
4200 
4201 	STRUCT_INIT(sign_update, mode);
4202 
4203 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4204 		cmn_err(CE_WARN, "sign_verify_update: failed holding minor");
4205 		return (ENXIO);
4206 	}
4207 
4208 	if (copyin(arg, STRUCT_BUF(sign_update),
4209 	    STRUCT_SIZE(sign_update)) != 0) {
4210 		crypto_release_minor(cm);
4211 		return (EFAULT);
4212 	}
4213 
4214 	data.cd_raw.iov_base = NULL;
4215 	data.cd_miscdata = NULL;
4216 
4217 	datalen = STRUCT_FGET(sign_update, su_datalen);
4218 	if (datalen > crypto_max_buffer_len) {
4219 		cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld "
4220 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4221 		rv = CRYPTO_ARGUMENTS_BAD;
4222 		goto release_minor;
4223 	}
4224 
4225 	session_id = STRUCT_FGET(sign_update, su_session);
4226 
4227 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4228 		goto release_minor;
4229 	}
4230 
4231 	if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) !=
4232 	    CRYPTO_SUCCESS) {
4233 		goto release_minor;
4234 	}
4235 	need = datalen;
4236 
4237 	INIT_RAW_CRYPTO_DATA(data, datalen);
4238 
4239 	if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf),
4240 	    data.cd_raw.iov_base, datalen) != 0) {
4241 		error = EFAULT;
4242 		goto release_minor;
4243 	}
4244 
4245 	ASSERT(update == crypto_sign_update ||
4246 	    update == crypto_verify_update ||
4247 	    update == crypto_mac_update);
4248 
4249 	if (update == crypto_sign_update)
4250 		ctxpp = &sp->sd_sign_ctx;
4251 	else if (update == crypto_verify_update)
4252 		ctxpp = &sp->sd_verify_ctx;
4253 	else
4254 		ctxpp = &sp->sd_mac_ctx;
4255 
4256 	rv = (update)(*ctxpp, &data, NULL);
4257 	if (rv != CRYPTO_SUCCESS)
4258 		CRYPTO_CANCEL_CTX(ctxpp);
4259 
4260 release_minor:
4261 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4262 	CRYPTO_SESSION_RELE(sp);
4263 	crypto_release_minor(cm);
4264 
4265 	if (data.cd_raw.iov_base != NULL)
4266 		kmem_free(data.cd_raw.iov_base, datalen);
4267 
4268 	if (error != 0)
4269 		return (error);
4270 
4271 	STRUCT_FSET(sign_update, su_return_value, rv);
4272 	if (copyout(STRUCT_BUF(sign_update), arg,
4273 	    STRUCT_SIZE(sign_update)) != 0) {
4274 		return (EFAULT);
4275 	}
4276 	return (0);
4277 }
4278 
4279 /* ARGSUSED */
4280 static int
4281 sign_final(dev_t dev, caddr_t arg, int mode, int *rval)
4282 {
4283 	return (common_final(dev, arg, mode, crypto_sign_final));
4284 }
4285 
4286 /*
4287  * Can't use the common final because it does a copyout of
4288  * the final part.
4289  */
4290 /* ARGSUSED */
4291 static int
4292 verify_final(dev_t dev, caddr_t arg, int mode, int *rval)
4293 {
4294 	STRUCT_DECL(crypto_verify_final, verify_final);
4295 	crypto_session_id_t session_id;
4296 	crypto_minor_t *cm;
4297 	crypto_session_data_t *sp = NULL;
4298 	crypto_data_t sign;
4299 	size_t signlen, need = 0;
4300 	int error = 0;
4301 	int rv;
4302 	boolean_t rctl_chk = B_FALSE;
4303 
4304 	STRUCT_INIT(verify_final, mode);
4305 
4306 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4307 		cmn_err(CE_WARN, "verify_final: failed holding minor");
4308 		return (ENXIO);
4309 	}
4310 
4311 	if (copyin(arg, STRUCT_BUF(verify_final),
4312 	    STRUCT_SIZE(verify_final)) != 0) {
4313 		crypto_release_minor(cm);
4314 		return (EFAULT);
4315 	}
4316 
4317 	sign.cd_raw.iov_base = NULL;
4318 
4319 	signlen = STRUCT_FGET(verify_final, vf_signlen);
4320 	if (signlen > crypto_max_buffer_len) {
4321 		cmn_err(CE_NOTE, "verify_final: buffer greater than %ld "
4322 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4323 		rv = CRYPTO_ARGUMENTS_BAD;
4324 		goto release_minor;
4325 	}
4326 
4327 	session_id = STRUCT_FGET(verify_final, vf_session);
4328 
4329 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4330 		goto release_minor;
4331 	}
4332 
4333 	if ((rv = CRYPTO_BUFFER_CHECK(sp, signlen, rctl_chk)) !=
4334 	    CRYPTO_SUCCESS) {
4335 		goto release_minor;
4336 	}
4337 	need = signlen;
4338 
4339 	INIT_RAW_CRYPTO_DATA(sign, signlen);
4340 
4341 	if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf),
4342 	    sign.cd_raw.iov_base, signlen) != 0) {
4343 		error = EFAULT;
4344 		goto release_minor;
4345 	}
4346 
4347 	rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL);
4348 	if (KCF_CONTEXT_DONE(rv))
4349 		sp->sd_verify_ctx = NULL;
4350 
4351 release_minor:
4352 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4353 	CRYPTO_SESSION_RELE(sp);
4354 	crypto_release_minor(cm);
4355 
4356 	if (sign.cd_raw.iov_base != NULL)
4357 		kmem_free(sign.cd_raw.iov_base, signlen);
4358 
4359 	if (error != 0)
4360 		return (error);
4361 
4362 	STRUCT_FSET(verify_final, vf_return_value, rv);
4363 	if (copyout(STRUCT_BUF(verify_final), arg,
4364 	    STRUCT_SIZE(verify_final)) != 0) {
4365 		return (EFAULT);
4366 	}
4367 	return (0);
4368 }
4369 
4370 /* ARGSUSED */
4371 static int
4372 seed_random(dev_t dev, caddr_t arg, int mode, int *rval)
4373 {
4374 	STRUCT_DECL(crypto_seed_random, seed_random);
4375 	kcf_provider_desc_t *real_provider = NULL;
4376 	kcf_req_params_t params;
4377 	crypto_session_id_t session_id;
4378 	crypto_minor_t *cm;
4379 	crypto_session_data_t *sp = NULL;
4380 	uchar_t *seed_buffer = NULL;
4381 	size_t seed_len;
4382 	size_t need = 0;
4383 	int error = 0;
4384 	int rv;
4385 	boolean_t rctl_chk = B_FALSE;
4386 
4387 	STRUCT_INIT(seed_random, mode);
4388 
4389 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4390 		cmn_err(CE_WARN, "seed_random: failed holding minor");
4391 		return (ENXIO);
4392 	}
4393 
4394 	if (copyin(arg, STRUCT_BUF(seed_random),
4395 	    STRUCT_SIZE(seed_random)) != 0) {
4396 		crypto_release_minor(cm);
4397 		return (EFAULT);
4398 	}
4399 
4400 	seed_len = STRUCT_FGET(seed_random, sr_seedlen);
4401 	if (seed_len > crypto_max_buffer_len) {
4402 		cmn_err(CE_NOTE, "seed_random: buffer greater than %ld "
4403 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4404 		rv = CRYPTO_ARGUMENTS_BAD;
4405 		goto release_minor;
4406 	}
4407 
4408 	session_id = STRUCT_FGET(seed_random, sr_session);
4409 
4410 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4411 		goto release_minor;
4412 	}
4413 
4414 	if ((rv = CRYPTO_BUFFER_CHECK(sp, seed_len, rctl_chk)) !=
4415 	    CRYPTO_SUCCESS) {
4416 		goto release_minor;
4417 	}
4418 	need = seed_len;
4419 	seed_buffer = kmem_alloc(seed_len, KM_SLEEP);
4420 
4421 	if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf),
4422 	    seed_buffer, seed_len) != 0) {
4423 		error = EFAULT;
4424 		goto release_minor;
4425 	}
4426 
4427 	if ((rv = kcf_get_hardware_provider_nomech(
4428 	    CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random),
4429 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4430 		goto release_minor;
4431 	}
4432 
4433 	KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_SEED,
4434 	    sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0,
4435 	    CRYPTO_SEED_NOW);
4436 
4437 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4438 
4439 release_minor:
4440 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4441 	CRYPTO_SESSION_RELE(sp);
4442 	crypto_release_minor(cm);
4443 
4444 	if (real_provider != NULL)
4445 		KCF_PROV_REFRELE(real_provider);
4446 
4447 	if (seed_buffer != NULL)
4448 		kmem_free(seed_buffer, seed_len);
4449 
4450 	if (error != 0)
4451 		return (error);
4452 
4453 	STRUCT_FSET(seed_random, sr_return_value, rv);
4454 	if (copyout(STRUCT_BUF(seed_random), arg,
4455 	    STRUCT_SIZE(seed_random)) != 0) {
4456 		return (EFAULT);
4457 	}
4458 	return (0);
4459 }
4460 
4461 /* ARGSUSED */
4462 static int
4463 generate_random(dev_t dev, caddr_t arg, int mode, int *rval)
4464 {
4465 	STRUCT_DECL(crypto_generate_random, generate_random);
4466 	kcf_provider_desc_t *real_provider = NULL;
4467 	kcf_req_params_t params;
4468 	crypto_session_id_t session_id;
4469 	crypto_minor_t *cm;
4470 	crypto_session_data_t *sp = NULL;
4471 	uchar_t *buffer = NULL;
4472 	size_t len;
4473 	size_t need = 0;
4474 	int error = 0;
4475 	int rv;
4476 	boolean_t rctl_chk = B_FALSE;
4477 
4478 	STRUCT_INIT(generate_random, mode);
4479 
4480 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4481 		cmn_err(CE_WARN, "generate_random: failed holding minor");
4482 		return (ENXIO);
4483 	}
4484 
4485 	if (copyin(arg, STRUCT_BUF(generate_random),
4486 	    STRUCT_SIZE(generate_random)) != 0) {
4487 		crypto_release_minor(cm);
4488 		return (EFAULT);
4489 	}
4490 
4491 	len = STRUCT_FGET(generate_random, gr_buflen);
4492 	if (len > crypto_max_buffer_len) {
4493 		cmn_err(CE_NOTE, "generate_random: buffer greater than %ld "
4494 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4495 		rv = CRYPTO_ARGUMENTS_BAD;
4496 		goto release_minor;
4497 	}
4498 
4499 	session_id = STRUCT_FGET(generate_random, gr_session);
4500 
4501 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4502 		goto release_minor;
4503 	}
4504 
4505 	if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) !=
4506 	    CRYPTO_SUCCESS) {
4507 		goto release_minor;
4508 	}
4509 	need = len;
4510 	buffer = kmem_alloc(len, KM_SLEEP);
4511 
4512 	if ((rv = kcf_get_hardware_provider_nomech(
4513 	    CRYPTO_OPS_OFFSET(random_ops),
4514 	    CRYPTO_RANDOM_OFFSET(generate_random), sp->sd_provider,
4515 	    &real_provider)) != CRYPTO_SUCCESS) {
4516 		goto release_minor;
4517 	}
4518 
4519 	KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_GENERATE,
4520 	    sp->sd_provider_session->ps_session, buffer, len, 0, 0);
4521 
4522 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4523 
4524 	if (rv == CRYPTO_SUCCESS) {
4525 		if (len != 0 && copyout(buffer,
4526 		    STRUCT_FGETP(generate_random, gr_buf), len) != 0) {
4527 			error = EFAULT;
4528 		}
4529 	}
4530 
4531 release_minor:
4532 	CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4533 	CRYPTO_SESSION_RELE(sp);
4534 	crypto_release_minor(cm);
4535 
4536 	if (real_provider != NULL)
4537 		KCF_PROV_REFRELE(real_provider);
4538 
4539 	if (buffer != NULL) {
4540 		/* random numbers are often used to create keys */
4541 		bzero(buffer, len);
4542 		kmem_free(buffer, len);
4543 	}
4544 
4545 	if (error != 0)
4546 		return (error);
4547 
4548 	STRUCT_FSET(generate_random, gr_return_value, rv);
4549 	if (copyout(STRUCT_BUF(generate_random), arg,
4550 	    STRUCT_SIZE(generate_random)) != 0) {
4551 		return (EFAULT);
4552 	}
4553 	return (0);
4554 }
4555 
4556 /*
4557  * Copyout a kernel array of attributes to user space.
4558  * u_attrs is the corresponding user space array containing
4559  * user space pointers necessary for the copyout.
4560  */
4561 /* ARGSUSED */
4562 static int
4563 copyout_attributes(int mode, caddr_t out, uint_t count,
4564     crypto_object_attribute_t *k_attrs, caddr_t u_attrs)
4565 {
4566 	STRUCT_DECL(crypto_object_attribute, oa);
4567 	caddr_t p, valuep;
4568 	size_t value_len;
4569 	size_t len;
4570 	int i;
4571 	int error = 0;
4572 
4573 	if (count == 0)
4574 		return (0);
4575 
4576 	STRUCT_INIT(oa, mode);
4577 
4578 	len = count * STRUCT_SIZE(oa);
4579 
4580 	ASSERT(u_attrs != NULL);
4581 	p = u_attrs;
4582 	for (i = 0; i < count; i++) {
4583 		/* can this bcopy be eliminated? */
4584 		bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa));
4585 		value_len = k_attrs[i].oa_value_len;
4586 		STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type);
4587 		STRUCT_FSET(oa, oa_value_len, (ssize_t)value_len);
4588 		valuep = STRUCT_FGETP(oa, oa_value);
4589 		if ((valuep != NULL) && (value_len != (size_t)-1)) {
4590 			if (copyout(k_attrs[i].oa_value,
4591 			    valuep, value_len) != 0) {
4592 				error = EFAULT;
4593 				goto out;
4594 			}
4595 		}
4596 		bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa));
4597 		p += STRUCT_SIZE(oa);
4598 	}
4599 	if (copyout(u_attrs, out, len)) {
4600 		error = EFAULT;
4601 	}
4602 out:
4603 	return (error);
4604 }
4605 
4606 
4607 /* ARGSUSED */
4608 static int
4609 object_create(dev_t dev, caddr_t arg, int mode, int *rval)
4610 {
4611 	STRUCT_DECL(crypto_object_create, object_create);
4612 	kcf_provider_desc_t *real_provider = NULL;
4613 	kcf_req_params_t params;
4614 	crypto_object_attribute_t *k_attrs = NULL;
4615 	crypto_session_id_t session_id;
4616 	crypto_minor_t *cm;
4617 	crypto_session_data_t *sp = NULL;
4618 	crypto_object_id_t object_handle;
4619 	caddr_t oc_attributes;
4620 	size_t k_attrs_size;
4621 	size_t rctl_bytes = 0;
4622 	boolean_t rctl_chk = B_FALSE;
4623 	int error = 0;
4624 	int rv;
4625 	uint_t count;
4626 
4627 	STRUCT_INIT(object_create, mode);
4628 
4629 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4630 		cmn_err(CE_WARN, "object_create: failed holding minor");
4631 		return (ENXIO);
4632 	}
4633 
4634 	if (copyin(arg, STRUCT_BUF(object_create),
4635 	    STRUCT_SIZE(object_create)) != 0) {
4636 		crypto_release_minor(cm);
4637 		return (EFAULT);
4638 	}
4639 
4640 	count = STRUCT_FGET(object_create, oc_count);
4641 	oc_attributes = STRUCT_FGETP(object_create, oc_attributes);
4642 
4643 	session_id = STRUCT_FGET(object_create, oc_session);
4644 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4645 		goto release_minor;
4646 	}
4647 	if (!copyin_attributes(mode, sp, count, oc_attributes, &k_attrs,
4648 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4649 	    &rctl_chk, B_TRUE)) {
4650 		goto release_minor;
4651 	}
4652 
4653 	if ((rv = kcf_get_hardware_provider_nomech(
4654 	    CRYPTO_OPS_OFFSET(object_ops),
4655 	    CRYPTO_OBJECT_OFFSET(object_create), sp->sd_provider,
4656 	    &real_provider)) != CRYPTO_SUCCESS) {
4657 		goto release_minor;
4658 	}
4659 
4660 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_CREATE,
4661 	    sp->sd_provider_session->ps_session, 0, k_attrs, count,
4662 	    &object_handle, 0, NULL, NULL, 0, NULL);
4663 
4664 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4665 
4666 	if (rv == CRYPTO_SUCCESS)
4667 		STRUCT_FSET(object_create, oc_handle, object_handle);
4668 
4669 release_minor:
4670 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4671 
4672 	if (k_attrs != NULL)
4673 		kmem_free(k_attrs, k_attrs_size);
4674 
4675 	if (error != 0)
4676 		goto out;
4677 
4678 	STRUCT_FSET(object_create, oc_return_value, rv);
4679 	if (copyout(STRUCT_BUF(object_create), arg,
4680 	    STRUCT_SIZE(object_create)) != 0) {
4681 		if (rv == CRYPTO_SUCCESS) {
4682 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4683 			    KCF_OP_OBJECT_DESTROY,
4684 			    sp->sd_provider_session->ps_session, object_handle,
4685 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4686 
4687 			(void) kcf_submit_request(real_provider, NULL,
4688 			    NULL, &params, B_FALSE);
4689 
4690 			error = EFAULT;
4691 		}
4692 	}
4693 out:
4694 	CRYPTO_SESSION_RELE(sp);
4695 	crypto_release_minor(cm);
4696 	if (real_provider != NULL)
4697 		KCF_PROV_REFRELE(real_provider);
4698 	return (error);
4699 }
4700 
4701 /* ARGSUSED */
4702 static int
4703 object_copy(dev_t dev, caddr_t arg, int mode, int *rval)
4704 {
4705 	STRUCT_DECL(crypto_object_copy, object_copy);
4706 	kcf_provider_desc_t *real_provider = NULL;
4707 	kcf_req_params_t params;
4708 	crypto_object_attribute_t *k_attrs = NULL;
4709 	crypto_session_id_t session_id;
4710 	crypto_minor_t *cm;
4711 	crypto_session_data_t *sp = NULL;
4712 	crypto_object_id_t handle, new_handle;
4713 	caddr_t oc_new_attributes;
4714 	size_t k_attrs_size;
4715 	size_t rctl_bytes = 0;
4716 	boolean_t rctl_chk = B_FALSE;
4717 	int error = 0;
4718 	int rv;
4719 	uint_t count;
4720 
4721 	STRUCT_INIT(object_copy, mode);
4722 
4723 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4724 		cmn_err(CE_WARN, "object_copy: failed holding minor");
4725 		return (ENXIO);
4726 	}
4727 
4728 	if (copyin(arg, STRUCT_BUF(object_copy),
4729 	    STRUCT_SIZE(object_copy)) != 0) {
4730 		crypto_release_minor(cm);
4731 		return (EFAULT);
4732 	}
4733 
4734 	count = STRUCT_FGET(object_copy, oc_count);
4735 	oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes);
4736 
4737 	session_id = STRUCT_FGET(object_copy, oc_session);
4738 
4739 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4740 		goto release_minor;
4741 	}
4742 	if (!copyin_attributes(mode, sp, count, oc_new_attributes, &k_attrs,
4743 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4744 	    &rctl_chk, B_TRUE)) {
4745 		goto release_minor;
4746 	}
4747 
4748 	if ((rv = kcf_get_hardware_provider_nomech(
4749 	    CRYPTO_OPS_OFFSET(object_ops),
4750 	    CRYPTO_OBJECT_OFFSET(object_copy), sp->sd_provider,
4751 	    &real_provider)) != CRYPTO_SUCCESS) {
4752 		goto release_minor;
4753 	}
4754 
4755 	handle = STRUCT_FGET(object_copy, oc_handle);
4756 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_COPY,
4757 	    sp->sd_provider_session->ps_session, handle, k_attrs, count,
4758 	    &new_handle, 0, NULL, NULL, 0, NULL);
4759 
4760 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4761 
4762 	if (rv == CRYPTO_SUCCESS)
4763 		STRUCT_FSET(object_copy, oc_new_handle, new_handle);
4764 
4765 release_minor:
4766 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4767 
4768 	if (k_attrs != NULL)
4769 		kmem_free(k_attrs, k_attrs_size);
4770 
4771 	if (error != 0)
4772 		goto out;
4773 
4774 	STRUCT_FSET(object_copy, oc_return_value, rv);
4775 	if (copyout(STRUCT_BUF(object_copy), arg,
4776 	    STRUCT_SIZE(object_copy)) != 0) {
4777 		if (rv == CRYPTO_SUCCESS) {
4778 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4779 			    KCF_OP_OBJECT_DESTROY,
4780 			    sp->sd_provider_session->ps_session, new_handle,
4781 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4782 
4783 			(void) kcf_submit_request(real_provider, NULL,
4784 			    NULL, &params, B_FALSE);
4785 
4786 			error = EFAULT;
4787 		}
4788 	}
4789 out:
4790 	CRYPTO_SESSION_RELE(sp);
4791 	crypto_release_minor(cm);
4792 	if (real_provider != NULL)
4793 		KCF_PROV_REFRELE(real_provider);
4794 	return (error);
4795 }
4796 
4797 /* ARGSUSED */
4798 static int
4799 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval)
4800 {
4801 	STRUCT_DECL(crypto_object_destroy, object_destroy);
4802 	kcf_provider_desc_t *real_provider;
4803 	kcf_req_params_t params;
4804 	crypto_session_id_t session_id;
4805 	crypto_minor_t *cm;
4806 	crypto_session_data_t *sp;
4807 	crypto_object_id_t handle;
4808 	int error = 0;
4809 	int rv;
4810 
4811 	STRUCT_INIT(object_destroy, mode);
4812 
4813 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4814 		cmn_err(CE_WARN, "object_destroy: failed holding minor");
4815 		return (ENXIO);
4816 	}
4817 
4818 	if (copyin(arg, STRUCT_BUF(object_destroy),
4819 	    STRUCT_SIZE(object_destroy)) != 0) {
4820 		crypto_release_minor(cm);
4821 		return (EFAULT);
4822 	}
4823 
4824 	session_id = STRUCT_FGET(object_destroy, od_session);
4825 
4826 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4827 		goto release_minor;
4828 	}
4829 
4830 	if ((rv = kcf_get_hardware_provider_nomech(
4831 	    CRYPTO_OPS_OFFSET(object_ops),
4832 	    CRYPTO_OBJECT_OFFSET(object_destroy), sp->sd_provider,
4833 	    &real_provider)) != CRYPTO_SUCCESS) {
4834 		goto out;
4835 	}
4836 
4837 	handle = STRUCT_FGET(object_destroy, od_handle);
4838 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
4839 	    sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0,
4840 	    NULL, NULL, 0, NULL);
4841 
4842 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4843 	KCF_PROV_REFRELE(real_provider);
4844 
4845 out:
4846 	CRYPTO_SESSION_RELE(sp);
4847 
4848 release_minor:
4849 	crypto_release_minor(cm);
4850 
4851 	if (error != 0)
4852 		return (error);
4853 
4854 	STRUCT_FSET(object_destroy, od_return_value, rv);
4855 
4856 	if (copyout(STRUCT_BUF(object_destroy), arg,
4857 	    STRUCT_SIZE(object_destroy)) != 0) {
4858 		return (EFAULT);
4859 	}
4860 	return (0);
4861 }
4862 
4863 /* ARGSUSED */
4864 static int
4865 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4866 {
4867 	STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value);
4868 #ifdef _LP64
4869 	STRUCT_DECL(crypto_object_attribute, oa);
4870 #else
4871 	/* LINTED E_FUNC_SET_NOT_USED */
4872 	STRUCT_DECL(crypto_object_attribute, oa);
4873 #endif
4874 	kcf_provider_desc_t *real_provider;
4875 	kcf_req_params_t params;
4876 	crypto_object_attribute_t *k_attrs = NULL;
4877 	crypto_session_id_t session_id;
4878 	crypto_minor_t *cm;
4879 	crypto_session_data_t *sp = NULL;
4880 	crypto_object_id_t handle;
4881 	caddr_t og_attributes;
4882 	caddr_t u_attrs = NULL;
4883 	size_t k_attrs_size;
4884 	size_t rctl_bytes = 0;
4885 	boolean_t rctl_chk = B_FALSE;
4886 	int error = 0;
4887 	int rv;
4888 	uint_t count;
4889 
4890 	STRUCT_INIT(get_attribute_value, mode);
4891 	STRUCT_INIT(oa, mode);
4892 
4893 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4894 		cmn_err(CE_WARN,
4895 		    "object_get_attribute_value: failed holding minor");
4896 		return (ENXIO);
4897 	}
4898 
4899 	if (copyin(arg, STRUCT_BUF(get_attribute_value),
4900 	    STRUCT_SIZE(get_attribute_value)) != 0) {
4901 		crypto_release_minor(cm);
4902 		return (EFAULT);
4903 	}
4904 
4905 	count = STRUCT_FGET(get_attribute_value, og_count);
4906 	og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes);
4907 
4908 	session_id = STRUCT_FGET(get_attribute_value, og_session);
4909 
4910 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4911 		goto release_minor;
4912 	}
4913 	if (!copyin_attributes(mode, sp, count, og_attributes, &k_attrs,
4914 	    &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes,
4915 	    &rctl_chk, B_FALSE)) {
4916 		goto release_minor;
4917 	}
4918 
4919 	if ((rv = kcf_get_hardware_provider_nomech(
4920 	    CRYPTO_OPS_OFFSET(object_ops),
4921 	    CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
4922 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4923 		goto out;
4924 	}
4925 
4926 	handle = STRUCT_FGET(get_attribute_value, og_handle);
4927 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE,
4928 	    sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL,
4929 	    0, NULL, NULL, 0, NULL);
4930 
4931 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4932 	KCF_PROV_REFRELE(real_provider);
4933 
4934 out:
4935 	if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE ||
4936 	    rv == CRYPTO_ATTRIBUTE_TYPE_INVALID ||
4937 	    rv == CRYPTO_BUFFER_TOO_SMALL) {
4938 		error = copyout_attributes(mode,
4939 		    STRUCT_FGETP(get_attribute_value, og_attributes),
4940 		    count, k_attrs, u_attrs);
4941 	}
4942 
4943 release_minor:
4944 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4945 	CRYPTO_SESSION_RELE(sp);
4946 	crypto_release_minor(cm);
4947 
4948 	if (k_attrs != NULL)
4949 		kmem_free(k_attrs, k_attrs_size);
4950 
4951 	if (u_attrs != NULL)
4952 		kmem_free(u_attrs, count * STRUCT_SIZE(oa));
4953 
4954 	if (error != 0)
4955 		return (error);
4956 
4957 	STRUCT_FSET(get_attribute_value, og_return_value, rv);
4958 	if (copyout(STRUCT_BUF(get_attribute_value), arg,
4959 	    STRUCT_SIZE(get_attribute_value)) != 0) {
4960 		return (EFAULT);
4961 	}
4962 	return (0);
4963 }
4964 
4965 /* ARGSUSED */
4966 static int
4967 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval)
4968 {
4969 	STRUCT_DECL(crypto_object_get_size, object_get_size);
4970 	kcf_provider_desc_t *real_provider;
4971 	kcf_req_params_t params;
4972 	crypto_session_id_t session_id;
4973 	crypto_minor_t *cm;
4974 	crypto_session_data_t *sp = NULL;
4975 	crypto_object_id_t handle;
4976 	size_t size;
4977 	int error = 0;
4978 	int rv;
4979 
4980 	STRUCT_INIT(object_get_size, mode);
4981 
4982 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4983 		cmn_err(CE_WARN, "object_get_size: failed holding minor");
4984 		return (ENXIO);
4985 	}
4986 
4987 	if (copyin(arg, STRUCT_BUF(object_get_size),
4988 	    STRUCT_SIZE(object_get_size)) != 0) {
4989 		crypto_release_minor(cm);
4990 		return (EFAULT);
4991 	}
4992 
4993 	session_id = STRUCT_FGET(object_get_size, gs_session);
4994 
4995 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4996 		goto release_minor;
4997 	}
4998 
4999 	if ((rv = kcf_get_hardware_provider_nomech(
5000 	    CRYPTO_OPS_OFFSET(object_ops),
5001 	    CRYPTO_OBJECT_OFFSET(object_get_size),
5002 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5003 		goto release_minor;
5004 	}
5005 
5006 	handle = STRUCT_FGET(object_get_size, gs_handle);
5007 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_SIZE,
5008 	    sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size,
5009 	    NULL, NULL, 0, NULL);
5010 
5011 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5012 	KCF_PROV_REFRELE(real_provider);
5013 
5014 	if (rv == CRYPTO_SUCCESS) {
5015 		STRUCT_FSET(object_get_size, gs_size, (ulong_t)size);
5016 	}
5017 
5018 release_minor:
5019 	crypto_release_minor(cm);
5020 	CRYPTO_SESSION_RELE(sp);
5021 
5022 	if (error != 0)
5023 		return (error);
5024 
5025 	STRUCT_FSET(object_get_size, gs_return_value, rv);
5026 	if (copyout(STRUCT_BUF(object_get_size), arg,
5027 	    STRUCT_SIZE(object_get_size)) != 0) {
5028 		return (EFAULT);
5029 	}
5030 	return (0);
5031 }
5032 
5033 /* ARGSUSED */
5034 static int
5035 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
5036 {
5037 	STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value);
5038 	kcf_provider_desc_t *real_provider;
5039 	kcf_req_params_t params;
5040 	crypto_object_attribute_t *k_attrs = NULL;
5041 	crypto_session_id_t session_id;
5042 	crypto_minor_t *cm;
5043 	crypto_session_data_t *sp = NULL;
5044 	crypto_object_id_t object_handle;
5045 	caddr_t sa_attributes;
5046 	size_t k_attrs_size;
5047 	size_t rctl_bytes = 0;
5048 	boolean_t rctl_chk = B_FALSE;
5049 	int error = 0;
5050 	int rv;
5051 	uint_t count;
5052 
5053 	STRUCT_INIT(set_attribute_value, mode);
5054 
5055 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5056 		cmn_err(CE_WARN,
5057 		    "object_set_attribute_value: failed holding minor");
5058 		return (ENXIO);
5059 	}
5060 
5061 	if (copyin(arg, STRUCT_BUF(set_attribute_value),
5062 	    STRUCT_SIZE(set_attribute_value)) != 0) {
5063 		crypto_release_minor(cm);
5064 		return (EFAULT);
5065 	}
5066 
5067 	count = STRUCT_FGET(set_attribute_value, sa_count);
5068 	sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes);
5069 
5070 	session_id = STRUCT_FGET(set_attribute_value, sa_session);
5071 
5072 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5073 		goto release_minor;
5074 	}
5075 	if (!copyin_attributes(mode, sp, count, sa_attributes, &k_attrs,
5076 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
5077 	    &rctl_chk, B_TRUE)) {
5078 		goto release_minor;
5079 	}
5080 
5081 	if ((rv = kcf_get_hardware_provider_nomech(
5082 	    CRYPTO_OPS_OFFSET(object_ops),
5083 	    CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
5084 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5085 		goto release_minor;
5086 	}
5087 
5088 	object_handle = STRUCT_FGET(set_attribute_value, sa_handle);
5089 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE,
5090 	    sp->sd_provider_session->ps_session, object_handle, k_attrs, count,
5091 	    NULL, 0, NULL, NULL, 0, NULL);
5092 
5093 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5094 	KCF_PROV_REFRELE(real_provider);
5095 
5096 release_minor:
5097 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5098 	CRYPTO_SESSION_RELE(sp);
5099 	crypto_release_minor(cm);
5100 
5101 	if (k_attrs != NULL)
5102 		kmem_free(k_attrs, k_attrs_size);
5103 
5104 	if (error != 0)
5105 		return (error);
5106 
5107 	STRUCT_FSET(set_attribute_value, sa_return_value, rv);
5108 	if (copyout(STRUCT_BUF(set_attribute_value), arg,
5109 	    STRUCT_SIZE(set_attribute_value)) != 0) {
5110 		return (EFAULT);
5111 	}
5112 	return (0);
5113 }
5114 
5115 /* ARGSUSED */
5116 static int
5117 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval)
5118 {
5119 	STRUCT_DECL(crypto_object_find_init, find_init);
5120 	kcf_provider_desc_t *real_provider = NULL;
5121 	kcf_req_params_t params;
5122 	crypto_object_attribute_t *k_attrs = NULL;
5123 	crypto_session_id_t session_id;
5124 	crypto_minor_t *cm;
5125 	crypto_session_data_t *sp = NULL;
5126 	caddr_t attributes;
5127 	size_t k_attrs_size;
5128 	size_t rctl_bytes = 0;
5129 	boolean_t rctl_chk = B_FALSE;
5130 	int error = 0;
5131 	int rv;
5132 	uint_t count;
5133 	void *cookie;
5134 
5135 	STRUCT_INIT(find_init, mode);
5136 
5137 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5138 		cmn_err(CE_WARN, "object_find_init: failed holding minor");
5139 		return (ENXIO);
5140 	}
5141 
5142 	if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) {
5143 		crypto_release_minor(cm);
5144 		return (EFAULT);
5145 	}
5146 
5147 	count = STRUCT_FGET(find_init, fi_count);
5148 	attributes = STRUCT_FGETP(find_init, fi_attributes);
5149 
5150 	session_id = STRUCT_FGET(find_init, fi_session);
5151 
5152 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5153 		goto release_minor;
5154 	}
5155 	if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
5156 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
5157 	    &rctl_chk, B_TRUE)) {
5158 		goto release_minor;
5159 	}
5160 
5161 	if ((rv = kcf_get_hardware_provider_nomech(
5162 	    CRYPTO_OPS_OFFSET(object_ops),
5163 	    CRYPTO_OBJECT_OFFSET(object_find_init),
5164 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5165 		goto release_minor;
5166 	}
5167 
5168 	/* check for an active find */
5169 	if (sp->sd_find_init_cookie != NULL) {
5170 		rv = CRYPTO_OPERATION_IS_ACTIVE;
5171 		goto release_minor;
5172 	}
5173 
5174 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_INIT,
5175 	    sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0,
5176 	    &cookie, NULL, 0, NULL);
5177 
5178 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5179 
5180 	if (rv == CRYPTO_SUCCESS) {
5181 		/*
5182 		 * The cookie is allocated by a provider at the start of an
5183 		 * object search.  It is freed when the search is terminated
5184 		 * by a final operation, or when the session is closed.
5185 		 * It contains state information about which object handles
5186 		 * have been returned to the caller.
5187 		 */
5188 		sp->sd_find_init_cookie = cookie;
5189 	}
5190 
5191 release_minor:
5192 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5193 	CRYPTO_SESSION_RELE(sp);
5194 	crypto_release_minor(cm);
5195 
5196 	if (real_provider != NULL)
5197 		KCF_PROV_REFRELE(real_provider);
5198 
5199 	if (k_attrs != NULL)
5200 		kmem_free(k_attrs, k_attrs_size);
5201 
5202 	if (error != 0)
5203 		return (error);
5204 
5205 	STRUCT_FSET(find_init, fi_return_value, rv);
5206 	if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) {
5207 		return (EFAULT);
5208 	}
5209 	return (0);
5210 }
5211 
5212 /* ARGSUSED */
5213 static int
5214 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval)
5215 {
5216 	STRUCT_DECL(crypto_object_find_update, find_update);
5217 	kcf_provider_desc_t *real_provider;
5218 	kcf_req_params_t params;
5219 	crypto_minor_t *cm;
5220 	crypto_session_data_t *sp = NULL;
5221 	crypto_object_id_t *buffer = NULL;
5222 	crypto_session_id_t session_id;
5223 	size_t len, rctl_bytes = 0;
5224 	uint_t count, max_count;
5225 	int rv, error = 0;
5226 	boolean_t rctl_chk = B_FALSE;
5227 
5228 	STRUCT_INIT(find_update, mode);
5229 
5230 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5231 		cmn_err(CE_WARN, "object_find_update: failed holding minor");
5232 		return (ENXIO);
5233 	}
5234 
5235 	if (copyin(arg, STRUCT_BUF(find_update),
5236 	    STRUCT_SIZE(find_update)) != 0) {
5237 		crypto_release_minor(cm);
5238 		return (EFAULT);
5239 	}
5240 
5241 	max_count = STRUCT_FGET(find_update, fu_max_count);
5242 	if (max_count > CRYPTO_MAX_FIND_COUNT) {
5243 		cmn_err(CE_NOTE, "object_find_update: count greater than %d, "
5244 		    "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid);
5245 		rv = CRYPTO_ARGUMENTS_BAD;
5246 		goto release_minor;
5247 	}
5248 	len = max_count * sizeof (crypto_object_id_t);
5249 	session_id = STRUCT_FGET(find_update, fu_session);
5250 
5251 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5252 		goto release_minor;
5253 	}
5254 	if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) !=
5255 	    CRYPTO_SUCCESS) {
5256 		goto release_minor;
5257 	}
5258 	rctl_bytes = len;
5259 	buffer = kmem_alloc(len, KM_SLEEP);
5260 
5261 	if ((rv = kcf_get_hardware_provider_nomech(
5262 	    CRYPTO_OPS_OFFSET(object_ops),
5263 	    CRYPTO_OBJECT_OFFSET(object_find), sp->sd_provider,
5264 	    &real_provider)) != CRYPTO_SUCCESS) {
5265 		goto release_minor;
5266 	}
5267 
5268 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND,
5269 	    sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0,
5270 	    NULL, sp->sd_find_init_cookie, max_count, &count);
5271 
5272 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5273 	KCF_PROV_REFRELE(real_provider);
5274 
5275 	if (rv == CRYPTO_SUCCESS) {
5276 		if (count > max_count) {
5277 			/* bad bad provider */
5278 			rv = CRYPTO_FAILED;
5279 			goto release_minor;
5280 		}
5281 		if (count != 0) {
5282 			/* copyout handles */
5283 			if (copyout(buffer,
5284 			    STRUCT_FGETP(find_update, fu_handles),
5285 			    count * sizeof (crypto_object_id_t)) != 0) {
5286 				error = EFAULT;
5287 			}
5288 		}
5289 		STRUCT_FSET(find_update, fu_count, count);
5290 	}
5291 
5292 release_minor:
5293 	CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5294 	CRYPTO_SESSION_RELE(sp);
5295 	crypto_release_minor(cm);
5296 
5297 	if (buffer != NULL)
5298 		kmem_free(buffer, len);
5299 
5300 	if (error != 0)
5301 		return (error);
5302 
5303 	STRUCT_FSET(find_update, fu_return_value, rv);
5304 	if (copyout(STRUCT_BUF(find_update), arg,
5305 	    STRUCT_SIZE(find_update)) != 0) {
5306 		return (EFAULT);
5307 	}
5308 
5309 	return (0);
5310 }
5311 
5312 /*
5313  * Free provider-allocated storage used for find object searches.
5314  */
5315 static int
5316 crypto_free_find_ctx(crypto_session_data_t *sp)
5317 {
5318 	kcf_provider_desc_t *real_provider;
5319 	kcf_req_params_t params;
5320 	int rv;
5321 
5322 	if ((rv = kcf_get_hardware_provider_nomech(
5323 	    CRYPTO_OPS_OFFSET(object_ops),
5324 	    CRYPTO_OBJECT_OFFSET(object_find_final),
5325 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5326 		return (rv);
5327 	}
5328 
5329 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_FINAL,
5330 	    sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0,
5331 	    NULL, sp->sd_find_init_cookie, 0, NULL);
5332 
5333 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5334 	KCF_PROV_REFRELE(real_provider);
5335 	return (rv);
5336 }
5337 
5338 /* ARGSUSED */
5339 static int
5340 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval)
5341 {
5342 	STRUCT_DECL(crypto_object_find_final, object_find_final);
5343 	crypto_session_id_t session_id;
5344 	crypto_minor_t *cm;
5345 	crypto_session_data_t *sp;
5346 	int error = 0;
5347 	int rv;
5348 
5349 	STRUCT_INIT(object_find_final, mode);
5350 
5351 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5352 		cmn_err(CE_WARN, "object_find_final: failed holding minor");
5353 		return (ENXIO);
5354 	}
5355 
5356 	if (copyin(arg, STRUCT_BUF(object_find_final),
5357 	    STRUCT_SIZE(object_find_final)) != 0) {
5358 		crypto_release_minor(cm);
5359 		return (EFAULT);
5360 	}
5361 
5362 	session_id = STRUCT_FGET(object_find_final, ff_session);
5363 
5364 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5365 		goto release_minor;
5366 	}
5367 
5368 	if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) {
5369 		sp->sd_find_init_cookie = NULL;
5370 	}
5371 
5372 	CRYPTO_SESSION_RELE(sp);
5373 
5374 release_minor:
5375 	crypto_release_minor(cm);
5376 
5377 	if (error != 0)
5378 		return (error);
5379 
5380 	STRUCT_FSET(object_find_final, ff_return_value, rv);
5381 
5382 	if (copyout(STRUCT_BUF(object_find_final), arg,
5383 	    STRUCT_SIZE(object_find_final)) != 0) {
5384 		return (EFAULT);
5385 	}
5386 	return (0);
5387 }
5388 
5389 /* ARGSUSED */
5390 static int
5391 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5392 {
5393 	STRUCT_DECL(crypto_object_generate_key, generate_key);
5394 	kcf_provider_desc_t *real_provider = NULL;
5395 	kcf_req_params_t params;
5396 	crypto_mechanism_t mech;
5397 	crypto_object_attribute_t *k_attrs = NULL;
5398 	crypto_session_id_t session_id;
5399 	crypto_minor_t *cm;
5400 	crypto_session_data_t *sp = NULL;
5401 	crypto_object_id_t key_handle;
5402 	caddr_t attributes;
5403 	size_t k_attrs_size;
5404 	size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5405 	boolean_t mech_rctl_chk = B_FALSE;
5406 	boolean_t key_rctl_chk = B_FALSE;
5407 	uint_t count;
5408 	int error = 0;
5409 	int rv;
5410 	boolean_t allocated_by_crypto_module = B_FALSE;
5411 
5412 	STRUCT_INIT(generate_key, mode);
5413 
5414 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5415 		cmn_err(CE_WARN, "object_generate_key: failed holding minor");
5416 		return (ENXIO);
5417 	}
5418 
5419 	if (copyin(arg, STRUCT_BUF(generate_key),
5420 	    STRUCT_SIZE(generate_key)) != 0) {
5421 		crypto_release_minor(cm);
5422 		return (EFAULT);
5423 	}
5424 
5425 	session_id = STRUCT_FGET(generate_key, gk_session);
5426 
5427 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5428 		goto release_minor;
5429 	}
5430 
5431 	bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type,
5432 	    sizeof (crypto_mech_type_t));
5433 
5434 	if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5435 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5436 	    &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5437 		goto release_minor;
5438 	}
5439 
5440 	rv = crypto_provider_copyin_mech_param(real_provider,
5441 	    STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error);
5442 
5443 	if (rv == CRYPTO_NOT_SUPPORTED) {
5444 		allocated_by_crypto_module = B_TRUE;
5445 		if (!copyin_mech(mode, sp,
5446 		    STRUCT_FADDR(generate_key, gk_mechanism),
5447 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
5448 			goto release_minor;
5449 		}
5450 	} else {
5451 		if (rv != CRYPTO_SUCCESS)
5452 			goto release_minor;
5453 	}
5454 
5455 	count = STRUCT_FGET(generate_key, gk_count);
5456 	attributes = STRUCT_FGETP(generate_key, gk_attributes);
5457 	if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
5458 	    &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes,
5459 	    &key_rctl_chk, B_TRUE)) {
5460 		goto release_minor;
5461 	}
5462 
5463 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE,
5464 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5465 	    &key_handle, NULL, 0, NULL, NULL, NULL, 0);
5466 
5467 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5468 
5469 	if (rv == CRYPTO_SUCCESS)
5470 		STRUCT_FSET(generate_key, gk_handle, key_handle);
5471 
5472 release_minor:
5473 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5474 	CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
5475 
5476 	if (k_attrs != NULL)
5477 		kmem_free(k_attrs, k_attrs_size);
5478 
5479 	if (error != 0)
5480 		goto out;
5481 
5482 	STRUCT_FSET(generate_key, gk_return_value, rv);
5483 	if (copyout(STRUCT_BUF(generate_key), arg,
5484 	    STRUCT_SIZE(generate_key)) != 0) {
5485 		if (rv == CRYPTO_SUCCESS) {
5486 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5487 			    KCF_OP_OBJECT_DESTROY,
5488 			    sp->sd_provider_session->ps_session, key_handle,
5489 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5490 
5491 			(void) kcf_submit_request(real_provider, NULL,
5492 			    NULL, &params, B_FALSE);
5493 
5494 			error = EFAULT;
5495 		}
5496 	}
5497 out:
5498 	CRYPTO_SESSION_RELE(sp);
5499 	crypto_release_minor(cm);
5500 
5501 	if (real_provider != NULL) {
5502 		crypto_free_mech(real_provider,
5503 		    allocated_by_crypto_module, &mech);
5504 		KCF_PROV_REFRELE(real_provider);
5505 	}
5506 	return (error);
5507 }
5508 
5509 /* ARGSUSED */
5510 static int
5511 nostore_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5512 {
5513 	STRUCT_DECL(crypto_nostore_generate_key, generate_key);
5514 #ifdef _LP64
5515 	STRUCT_DECL(crypto_object_attribute, oa);
5516 #else
5517 	/* LINTED E_FUNC_SET_NOT_USED */
5518 	STRUCT_DECL(crypto_object_attribute, oa);
5519 #endif
5520 	kcf_provider_desc_t *real_provider = NULL;
5521 	kcf_req_params_t params;
5522 	crypto_mechanism_t mech;
5523 	crypto_object_attribute_t *k_in_attrs = NULL;
5524 	crypto_object_attribute_t *k_out_attrs = NULL;
5525 	crypto_session_id_t session_id;
5526 	crypto_minor_t *cm;
5527 	crypto_session_data_t *sp = NULL;
5528 	caddr_t in_attributes;
5529 	caddr_t out_attributes;
5530 	size_t k_in_attrs_size;
5531 	size_t k_out_attrs_size;
5532 	size_t mech_rctl_bytes = 0;
5533 	boolean_t mech_rctl_chk = B_FALSE;
5534 	size_t in_key_rctl_bytes = 0, out_key_rctl_bytes = 0;
5535 	boolean_t in_key_rctl_chk = B_FALSE;
5536 	boolean_t out_key_rctl_chk = B_FALSE;
5537 	uint_t in_count;
5538 	uint_t out_count;
5539 	int error = 0;
5540 	int rv;
5541 	boolean_t allocated_by_crypto_module = B_FALSE;
5542 	caddr_t u_attrs = NULL;
5543 
5544 	out_count = 0;
5545 	STRUCT_INIT(generate_key, mode);
5546 	STRUCT_INIT(oa, mode);
5547 
5548 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5549 		cmn_err(CE_WARN, "nostore_generate_key: failed holding minor");
5550 		return (ENXIO);
5551 	}
5552 
5553 	if (copyin(arg, STRUCT_BUF(generate_key),
5554 	    STRUCT_SIZE(generate_key)) != 0) {
5555 		crypto_release_minor(cm);
5556 		return (EFAULT);
5557 	}
5558 
5559 	session_id = STRUCT_FGET(generate_key, ngk_session);
5560 
5561 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5562 		goto release_minor;
5563 	}
5564 
5565 	bcopy(STRUCT_FADDR(generate_key, ngk_mechanism), &mech.cm_type,
5566 	    sizeof (crypto_mech_type_t));
5567 
5568 	if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5569 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5570 	    &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5571 		goto release_minor;
5572 	}
5573 
5574 	rv = crypto_provider_copyin_mech_param(real_provider,
5575 	    STRUCT_FADDR(generate_key, ngk_mechanism), &mech, mode, &error);
5576 
5577 	if (rv == CRYPTO_NOT_SUPPORTED) {
5578 		allocated_by_crypto_module = B_TRUE;
5579 		if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key,
5580 		    ngk_mechanism), &mech, &mech_rctl_bytes,
5581 		    &mech_rctl_chk, &rv, &error)) {
5582 			goto release_minor;
5583 		}
5584 	} else {
5585 		if (rv != CRYPTO_SUCCESS)
5586 			goto release_minor;
5587 	}
5588 
5589 	in_count = STRUCT_FGET(generate_key, ngk_in_count);
5590 	in_attributes = STRUCT_FGETP(generate_key, ngk_in_attributes);
5591 	if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs,
5592 	    &k_in_attrs_size, NULL, &rv, &error, &in_key_rctl_bytes,
5593 	    &in_key_rctl_chk, B_TRUE)) {
5594 		goto release_minor;
5595 	}
5596 
5597 	out_count = STRUCT_FGET(generate_key, ngk_out_count);
5598 	out_attributes = STRUCT_FGETP(generate_key, ngk_out_attributes);
5599 	if (!copyin_attributes(mode, sp, out_count, out_attributes,
5600 	    &k_out_attrs,
5601 	    &k_out_attrs_size, &u_attrs, &rv, &error, &out_key_rctl_bytes,
5602 	    &out_key_rctl_chk, B_FALSE)) {
5603 		goto release_minor;
5604 	}
5605 
5606 	KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE,
5607 	    sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count,
5608 	    NULL, 0, NULL, k_out_attrs, out_count, NULL, 0);
5609 
5610 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5611 
5612 	if (rv == CRYPTO_SUCCESS) {
5613 		error = copyout_attributes(mode, out_attributes,
5614 		    out_count, k_out_attrs, u_attrs);
5615 	}
5616 release_minor:
5617 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5618 	CRYPTO_DECREMENT_RCTL_SESSION(sp, in_key_rctl_bytes, in_key_rctl_chk);
5619 	CRYPTO_DECREMENT_RCTL_SESSION(sp, out_key_rctl_bytes,
5620 	    out_key_rctl_chk);
5621 
5622 	if (k_in_attrs != NULL)
5623 		kmem_free(k_in_attrs, k_in_attrs_size);
5624 	if (k_out_attrs != NULL) {
5625 		bzero(k_out_attrs, k_out_attrs_size);
5626 		kmem_free(k_out_attrs, k_out_attrs_size);
5627 	}
5628 
5629 	if (u_attrs != NULL)
5630 		kmem_free(u_attrs, out_count * STRUCT_SIZE(oa));
5631 
5632 	if (error != 0)
5633 		goto out;
5634 
5635 	STRUCT_FSET(generate_key, ngk_return_value, rv);
5636 	if (copyout(STRUCT_BUF(generate_key), arg,
5637 	    STRUCT_SIZE(generate_key)) != 0) {
5638 		error = EFAULT;
5639 	}
5640 out:
5641 	CRYPTO_SESSION_RELE(sp);
5642 	crypto_release_minor(cm);
5643 
5644 	if (real_provider != NULL) {
5645 		crypto_free_mech(real_provider,
5646 		    allocated_by_crypto_module, &mech);
5647 		KCF_PROV_REFRELE(real_provider);
5648 	}
5649 	return (error);
5650 }
5651 
5652 /* ARGSUSED */
5653 static int
5654 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5655 {
5656 	STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair);
5657 	kcf_provider_desc_t *real_provider = NULL;
5658 	kcf_req_params_t params;
5659 	crypto_mechanism_t mech;
5660 	crypto_object_attribute_t *k_pub_attrs = NULL;
5661 	crypto_object_attribute_t *k_pri_attrs = NULL;
5662 	crypto_session_id_t session_id;
5663 	crypto_minor_t *cm;
5664 	crypto_session_data_t *sp = NULL;
5665 	crypto_object_id_t pub_handle;
5666 	crypto_object_id_t pri_handle;
5667 	caddr_t pri_attributes;
5668 	caddr_t pub_attributes;
5669 	size_t k_pub_attrs_size, k_pri_attrs_size;
5670 	size_t mech_rctl_bytes = 0;
5671 	boolean_t mech_rctl_chk = B_FALSE;
5672 	size_t pub_rctl_bytes = 0;
5673 	boolean_t pub_rctl_chk = B_FALSE;
5674 	size_t pri_rctl_bytes = 0;
5675 	boolean_t pri_rctl_chk = B_FALSE;
5676 	uint_t pub_count;
5677 	uint_t pri_count;
5678 	int error = 0;
5679 	int rv;
5680 	boolean_t allocated_by_crypto_module = B_FALSE;
5681 
5682 	STRUCT_INIT(generate_key_pair, mode);
5683 
5684 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5685 		cmn_err(CE_WARN,
5686 		    "object_generate_key_pair: failed holding minor");
5687 		return (ENXIO);
5688 	}
5689 
5690 	if (copyin(arg, STRUCT_BUF(generate_key_pair),
5691 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5692 		crypto_release_minor(cm);
5693 		return (EFAULT);
5694 	}
5695 
5696 	session_id = STRUCT_FGET(generate_key_pair, kp_session);
5697 
5698 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5699 		goto release_minor;
5700 	}
5701 
5702 	bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type,
5703 	    sizeof (crypto_mech_type_t));
5704 
5705 	if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5706 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5707 	    &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5708 		goto release_minor;
5709 	}
5710 
5711 	rv = crypto_provider_copyin_mech_param(real_provider,
5712 	    STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error);
5713 
5714 	if (rv == CRYPTO_NOT_SUPPORTED) {
5715 		allocated_by_crypto_module = B_TRUE;
5716 		if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair,
5717 		    kp_mechanism), &mech, &mech_rctl_bytes,
5718 		    &mech_rctl_chk, &rv, &error)) {
5719 			goto release_minor;
5720 		}
5721 	} else {
5722 		if (rv != CRYPTO_SUCCESS)
5723 			goto release_minor;
5724 	}
5725 
5726 	pub_count = STRUCT_FGET(generate_key_pair, kp_public_count);
5727 	pri_count = STRUCT_FGET(generate_key_pair, kp_private_count);
5728 
5729 	pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes);
5730 	if (!copyin_attributes(mode, sp, pub_count, pub_attributes,
5731 	    &k_pub_attrs, &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes,
5732 	    &pub_rctl_chk, B_TRUE)) {
5733 		goto release_minor;
5734 	}
5735 
5736 	pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes);
5737 	if (!copyin_attributes(mode, sp, pri_count, pri_attributes,
5738 	    &k_pri_attrs, &k_pri_attrs_size, NULL, &rv, &error,
5739 	    &pri_rctl_bytes, &pri_rctl_chk, B_TRUE)) {
5740 		goto release_minor;
5741 	}
5742 
5743 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
5744 	    sp->sd_provider_session->ps_session, &mech, k_pub_attrs,
5745 	    pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle,
5746 	    NULL, NULL, 0);
5747 
5748 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5749 
5750 	if (rv == CRYPTO_SUCCESS) {
5751 		STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle);
5752 		STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle);
5753 	}
5754 
5755 release_minor:
5756 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5757 	CRYPTO_DECREMENT_RCTL_SESSION(sp, pub_rctl_bytes, pub_rctl_chk);
5758 	CRYPTO_DECREMENT_RCTL_SESSION(sp, pri_rctl_bytes, pri_rctl_chk);
5759 
5760 	if (k_pub_attrs != NULL)
5761 		kmem_free(k_pub_attrs, k_pub_attrs_size);
5762 
5763 	if (k_pri_attrs != NULL)
5764 		kmem_free(k_pri_attrs, k_pri_attrs_size);
5765 
5766 	if (error != 0)
5767 		goto out;
5768 
5769 	STRUCT_FSET(generate_key_pair, kp_return_value, rv);
5770 	if (copyout(STRUCT_BUF(generate_key_pair), arg,
5771 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5772 		if (rv == CRYPTO_SUCCESS) {
5773 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5774 			    KCF_OP_OBJECT_DESTROY,
5775 			    sp->sd_provider_session->ps_session, pub_handle,
5776 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5777 
5778 			(void) kcf_submit_request(real_provider, NULL,
5779 			    NULL, &params, B_FALSE);
5780 
5781 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5782 			    KCF_OP_OBJECT_DESTROY,
5783 			    sp->sd_provider_session->ps_session, pri_handle,
5784 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5785 
5786 			(void) kcf_submit_request(real_provider, NULL,
5787 			    NULL, &params, B_FALSE);
5788 
5789 			error = EFAULT;
5790 		}
5791 	}
5792 out:
5793 	CRYPTO_SESSION_RELE(sp);
5794 	crypto_release_minor(cm);
5795 
5796 	if (real_provider != NULL) {
5797 		crypto_free_mech(real_provider,
5798 		    allocated_by_crypto_module, &mech);
5799 		KCF_PROV_REFRELE(real_provider);
5800 	}
5801 	return (error);
5802 }
5803 
5804 /* ARGSUSED */
5805 static int
5806 nostore_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5807 {
5808 	STRUCT_DECL(crypto_nostore_generate_key_pair, generate_key_pair);
5809 #ifdef _LP64
5810 	STRUCT_DECL(crypto_object_attribute, oa);
5811 #else
5812 	/* LINTED E_FUNC_SET_NOT_USED */
5813 	STRUCT_DECL(crypto_object_attribute, oa);
5814 #endif
5815 	kcf_provider_desc_t *real_provider = NULL;
5816 	kcf_req_params_t params;
5817 	crypto_mechanism_t mech;
5818 	crypto_object_attribute_t *k_in_pub_attrs = NULL;
5819 	crypto_object_attribute_t *k_in_pri_attrs = NULL;
5820 	crypto_object_attribute_t *k_out_pub_attrs = NULL;
5821 	crypto_object_attribute_t *k_out_pri_attrs = NULL;
5822 	crypto_session_id_t session_id;
5823 	crypto_minor_t *cm;
5824 	crypto_session_data_t *sp = NULL;
5825 	caddr_t in_pri_attributes;
5826 	caddr_t in_pub_attributes;
5827 	caddr_t out_pri_attributes;
5828 	caddr_t out_pub_attributes;
5829 	size_t k_in_pub_attrs_size, k_in_pri_attrs_size;
5830 	size_t k_out_pub_attrs_size, k_out_pri_attrs_size;
5831 	size_t mech_rctl_bytes = 0;
5832 	boolean_t mech_rctl_chk = B_FALSE;
5833 	size_t in_pub_rctl_bytes = 0;
5834 	boolean_t in_pub_rctl_chk = B_FALSE;
5835 	size_t in_pri_rctl_bytes = 0;
5836 	boolean_t in_pri_rctl_chk = B_FALSE;
5837 	size_t out_pub_rctl_bytes = 0;
5838 	boolean_t out_pub_rctl_chk = B_FALSE;
5839 	size_t out_pri_rctl_bytes = 0;
5840 	boolean_t out_pri_rctl_chk = B_FALSE;
5841 	uint_t in_pub_count;
5842 	uint_t in_pri_count;
5843 	uint_t out_pub_count;
5844 	uint_t out_pri_count;
5845 	int error = 0;
5846 	int rv;
5847 	boolean_t allocated_by_crypto_module = B_FALSE;
5848 	caddr_t u_pub_attrs = NULL;
5849 	caddr_t u_pri_attrs = NULL;
5850 
5851 	out_pub_count = 0;
5852 	out_pri_count = 0;
5853 	STRUCT_INIT(generate_key_pair, mode);
5854 	STRUCT_INIT(oa, mode);
5855 
5856 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5857 		cmn_err(CE_WARN,
5858 		    "nostore_generate_key_pair: failed holding minor");
5859 		return (ENXIO);
5860 	}
5861 
5862 	if (copyin(arg, STRUCT_BUF(generate_key_pair),
5863 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5864 		crypto_release_minor(cm);
5865 		return (EFAULT);
5866 	}
5867 
5868 	session_id = STRUCT_FGET(generate_key_pair, nkp_session);
5869 
5870 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5871 		goto release_minor;
5872 	}
5873 
5874 	bcopy(STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech.cm_type,
5875 	    sizeof (crypto_mech_type_t));
5876 
5877 	if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5878 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5879 	    &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5880 		goto release_minor;
5881 	}
5882 
5883 	rv = crypto_provider_copyin_mech_param(real_provider,
5884 	    STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech, mode,
5885 	    &error);
5886 
5887 	if (rv == CRYPTO_NOT_SUPPORTED) {
5888 		allocated_by_crypto_module = B_TRUE;
5889 		if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair,
5890 		    nkp_mechanism), &mech, &mech_rctl_bytes,
5891 		    &mech_rctl_chk, &rv, &error)) {
5892 			goto release_minor;
5893 		}
5894 	} else {
5895 		if (rv != CRYPTO_SUCCESS)
5896 			goto release_minor;
5897 	}
5898 
5899 	in_pub_count = STRUCT_FGET(generate_key_pair, nkp_in_public_count);
5900 	in_pri_count = STRUCT_FGET(generate_key_pair, nkp_in_private_count);
5901 
5902 	in_pub_attributes = STRUCT_FGETP(generate_key_pair,
5903 	    nkp_in_public_attributes);
5904 	if (!copyin_attributes(mode, sp, in_pub_count, in_pub_attributes,
5905 	    &k_in_pub_attrs, &k_in_pub_attrs_size, NULL, &rv, &error,
5906 	    &in_pub_rctl_bytes, &in_pub_rctl_chk, B_TRUE)) {
5907 		goto release_minor;
5908 	}
5909 
5910 	in_pri_attributes = STRUCT_FGETP(generate_key_pair,
5911 	    nkp_in_private_attributes);
5912 	if (!copyin_attributes(mode, sp, in_pri_count, in_pri_attributes,
5913 	    &k_in_pri_attrs, &k_in_pri_attrs_size, NULL, &rv, &error,
5914 	    &in_pri_rctl_bytes, &in_pri_rctl_chk, B_TRUE)) {
5915 		goto release_minor;
5916 	}
5917 
5918 	out_pub_count = STRUCT_FGET(generate_key_pair, nkp_out_public_count);
5919 	out_pri_count = STRUCT_FGET(generate_key_pair, nkp_out_private_count);
5920 
5921 	out_pub_attributes = STRUCT_FGETP(generate_key_pair,
5922 	    nkp_out_public_attributes);
5923 	if (!copyin_attributes(mode, sp, out_pub_count, out_pub_attributes,
5924 	    &k_out_pub_attrs, &k_out_pub_attrs_size, &u_pub_attrs, &rv, &error,
5925 	    &out_pub_rctl_bytes, &out_pub_rctl_chk, B_FALSE)) {
5926 		goto release_minor;
5927 	}
5928 
5929 	out_pri_attributes = STRUCT_FGETP(generate_key_pair,
5930 	    nkp_out_private_attributes);
5931 	if (!copyin_attributes(mode, sp, out_pri_count, out_pri_attributes,
5932 	    &k_out_pri_attrs, &k_out_pri_attrs_size, &u_pri_attrs, &rv, &error,
5933 	    &out_pri_rctl_bytes, &out_pri_rctl_chk, B_FALSE)) {
5934 		goto release_minor;
5935 	}
5936 
5937 	KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
5938 	    sp->sd_provider_session->ps_session, &mech, k_in_pub_attrs,
5939 	    in_pub_count, k_in_pri_attrs, in_pri_count, NULL, k_out_pub_attrs,
5940 	    out_pub_count, k_out_pri_attrs, out_pri_count);
5941 
5942 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5943 
5944 	if (rv == CRYPTO_SUCCESS) {
5945 		error = copyout_attributes(mode, out_pub_attributes,
5946 		    out_pub_count, k_out_pub_attrs, u_pub_attrs);
5947 		if (error != CRYPTO_SUCCESS)
5948 			goto release_minor;
5949 		error = copyout_attributes(mode, out_pri_attributes,
5950 		    out_pri_count, k_out_pri_attrs, u_pri_attrs);
5951 	}
5952 
5953 release_minor:
5954 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5955 	CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pub_rctl_bytes, in_pub_rctl_chk);
5956 	CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pri_rctl_bytes, in_pri_rctl_chk);
5957 	CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pub_rctl_bytes,
5958 	    out_pub_rctl_chk);
5959 	CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pri_rctl_bytes,
5960 	    out_pri_rctl_chk);
5961 
5962 	if (k_in_pub_attrs != NULL)
5963 		kmem_free(k_in_pub_attrs, k_in_pub_attrs_size);
5964 
5965 	if (k_in_pri_attrs != NULL)
5966 		kmem_free(k_in_pri_attrs, k_in_pri_attrs_size);
5967 
5968 	if (k_out_pub_attrs != NULL)
5969 		kmem_free(k_out_pub_attrs, k_out_pub_attrs_size);
5970 
5971 	if (k_out_pri_attrs != NULL) {
5972 		bzero(k_out_pri_attrs, k_out_pri_attrs_size);
5973 		kmem_free(k_out_pri_attrs, k_out_pri_attrs_size);
5974 	}
5975 
5976 	if (u_pub_attrs != NULL)
5977 		kmem_free(u_pub_attrs, out_pub_count * STRUCT_SIZE(oa));
5978 
5979 	if (u_pri_attrs != NULL)
5980 		kmem_free(u_pri_attrs, out_pri_count * STRUCT_SIZE(oa));
5981 
5982 	if (error != 0)
5983 		goto out;
5984 
5985 	STRUCT_FSET(generate_key_pair, nkp_return_value, rv);
5986 	if (copyout(STRUCT_BUF(generate_key_pair), arg,
5987 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5988 		error = EFAULT;
5989 	}
5990 out:
5991 	CRYPTO_SESSION_RELE(sp);
5992 	crypto_release_minor(cm);
5993 
5994 	if (real_provider != NULL) {
5995 		crypto_free_mech(real_provider,
5996 		    allocated_by_crypto_module, &mech);
5997 		KCF_PROV_REFRELE(real_provider);
5998 	}
5999 	return (error);
6000 }
6001 
6002 /* ARGSUSED */
6003 static int
6004 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
6005 {
6006 	STRUCT_DECL(crypto_object_wrap_key, wrap_key);
6007 	kcf_provider_desc_t *real_provider = NULL;
6008 	kcf_req_params_t params;
6009 	crypto_mechanism_t mech;
6010 	crypto_key_t key;
6011 	crypto_session_id_t session_id;
6012 	crypto_minor_t *cm;
6013 	crypto_session_data_t *sp = NULL;
6014 	crypto_object_id_t handle;
6015 	size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
6016 	boolean_t mech_rctl_chk = B_FALSE;
6017 	boolean_t key_rctl_chk = B_FALSE;
6018 	size_t wrapped_key_rctl_bytes = 0;
6019 	boolean_t wrapped_key_rctl_chk = B_FALSE;
6020 	size_t wrapped_key_len, new_wrapped_key_len;
6021 	uchar_t *wrapped_key = NULL;
6022 	char *wrapped_key_buffer;
6023 	int error = 0;
6024 	int rv;
6025 	boolean_t allocated_by_crypto_module = B_FALSE;
6026 
6027 	STRUCT_INIT(wrap_key, mode);
6028 
6029 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6030 		cmn_err(CE_WARN, "object_wrap_key: failed holding minor");
6031 		return (ENXIO);
6032 	}
6033 
6034 	if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) {
6035 		crypto_release_minor(cm);
6036 		return (EFAULT);
6037 	}
6038 
6039 	bzero(&key, sizeof (crypto_key_t));
6040 
6041 	session_id = STRUCT_FGET(wrap_key, wk_session);
6042 
6043 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6044 		goto out;
6045 	}
6046 
6047 	bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type,
6048 	    sizeof (crypto_mech_type_t));
6049 
6050 	/* We need the key length for provider selection so copy it in now. */
6051 	if (!copyin_key(mode, sp, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key,
6052 	    &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6053 		goto out;
6054 	}
6055 
6056 	wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len);
6057 
6058 	if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
6059 	    CRYPTO_MECH_INVALID, NULL,  sp->sd_provider,
6060 	    &real_provider, CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) {
6061 		goto out;
6062 	}
6063 
6064 	rv = crypto_provider_copyin_mech_param(real_provider,
6065 	    STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error);
6066 
6067 	if (rv == CRYPTO_NOT_SUPPORTED) {
6068 		allocated_by_crypto_module = B_TRUE;
6069 		if (!copyin_mech(mode, sp, STRUCT_FADDR(wrap_key, wk_mechanism),
6070 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6071 			goto out;
6072 		}
6073 	} else {
6074 		if (rv != CRYPTO_SUCCESS)
6075 			goto out;
6076 	}
6077 
6078 	/*
6079 	 * Don't allocate output buffer unless both buffer pointer and
6080 	 * buffer length are not NULL or 0 (length).
6081 	 */
6082 	wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key);
6083 	if (wrapped_key_buffer == NULL || wrapped_key_len == 0) {
6084 		wrapped_key_len = 0;
6085 	}
6086 
6087 	if (wrapped_key_len > crypto_max_buffer_len) {
6088 		cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld "
6089 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
6090 		rv = CRYPTO_ARGUMENTS_BAD;
6091 		goto out;
6092 	}
6093 
6094 	if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len,
6095 	    wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
6096 		goto out;
6097 	}
6098 
6099 	/* new_wrapped_key_len can be modified by the provider */
6100 	wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len;
6101 	wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
6102 
6103 	handle = STRUCT_FGET(wrap_key, wk_object_handle);
6104 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP,
6105 	    sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle,
6106 	    NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len);
6107 
6108 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6109 
6110 	if (rv == CRYPTO_SUCCESS) {
6111 		if (wrapped_key_len != 0 && copyout(wrapped_key,
6112 		    wrapped_key_buffer, new_wrapped_key_len) != 0) {
6113 			error = EFAULT;
6114 		}
6115 		STRUCT_FSET(wrap_key, wk_wrapped_key_len,
6116 		    (ulong_t)new_wrapped_key_len);
6117 	}
6118 
6119 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
6120 		/*
6121 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
6122 		 * of section 11.2 of the pkcs11 spec. We catch it here and
6123 		 * provide the correct pkcs11 return value.
6124 		 */
6125 		if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL)
6126 			rv = CRYPTO_SUCCESS;
6127 		STRUCT_FSET(wrap_key, wk_wrapped_key_len,
6128 		    (ulong_t)new_wrapped_key_len);
6129 	}
6130 
6131 out:
6132 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6133 	CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6134 	CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes,
6135 	    wrapped_key_rctl_chk);
6136 	CRYPTO_SESSION_RELE(sp);
6137 
6138 	crypto_release_minor(cm);
6139 
6140 	if (real_provider != NULL) {
6141 		crypto_free_mech(real_provider,
6142 		    allocated_by_crypto_module, &mech);
6143 		KCF_PROV_REFRELE(real_provider);
6144 	}
6145 
6146 	if (wrapped_key != NULL)
6147 		kmem_free(wrapped_key, wrapped_key_len);
6148 
6149 	free_crypto_key(&key);
6150 
6151 	if (error != 0)
6152 		return (error);
6153 
6154 	STRUCT_FSET(wrap_key, wk_return_value, rv);
6155 	if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) {
6156 		return (EFAULT);
6157 	}
6158 	return (0);
6159 }
6160 
6161 /* ARGSUSED */
6162 static int
6163 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
6164 {
6165 	STRUCT_DECL(crypto_object_unwrap_key, unwrap_key);
6166 	kcf_provider_desc_t *real_provider = NULL;
6167 	kcf_req_params_t params;
6168 	crypto_mechanism_t mech;
6169 	crypto_key_t unwrapping_key;
6170 	crypto_session_id_t session_id;
6171 	crypto_minor_t *cm;
6172 	crypto_session_data_t *sp = NULL;
6173 	crypto_object_id_t handle;
6174 	crypto_object_attribute_t *k_attrs = NULL;
6175 	size_t k_attrs_size;
6176 	size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0;
6177 	boolean_t mech_rctl_chk = B_FALSE;
6178 	boolean_t unwrapping_key_rctl_chk = B_FALSE;
6179 	size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0;
6180 	boolean_t wrapped_key_rctl_chk = B_FALSE;
6181 	boolean_t k_attrs_rctl_chk = B_FALSE;
6182 	size_t wrapped_key_len;
6183 	uchar_t *wrapped_key = NULL;
6184 	int error = 0;
6185 	int rv;
6186 	uint_t count;
6187 	caddr_t uk_attributes;
6188 	boolean_t allocated_by_crypto_module = B_FALSE;
6189 
6190 	STRUCT_INIT(unwrap_key, mode);
6191 
6192 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6193 		cmn_err(CE_WARN, "object_unwrap_key: failed holding minor");
6194 		return (ENXIO);
6195 	}
6196 
6197 	if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) {
6198 		crypto_release_minor(cm);
6199 		return (EFAULT);
6200 	}
6201 
6202 	bzero(&unwrapping_key, sizeof (unwrapping_key));
6203 
6204 	session_id = STRUCT_FGET(unwrap_key, uk_session);
6205 
6206 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6207 		goto release_minor;
6208 	}
6209 
6210 	bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type,
6211 	    sizeof (crypto_mech_type_t));
6212 
6213 	/* We need the key length for provider selection so copy it in now. */
6214 	if (!copyin_key(mode, sp, STRUCT_FADDR(unwrap_key, uk_unwrapping_key),
6215 	    &unwrapping_key, &unwrapping_key_rctl_bytes,
6216 	    &unwrapping_key_rctl_chk, &rv, &error)) {
6217 		goto release_minor;
6218 	}
6219 
6220 	if ((rv = kcf_get_hardware_provider(mech.cm_type, &unwrapping_key,
6221 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6222 	    &real_provider, CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) {
6223 		goto release_minor;
6224 	}
6225 
6226 	rv = crypto_provider_copyin_mech_param(real_provider,
6227 	    STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error);
6228 
6229 	if (rv == CRYPTO_NOT_SUPPORTED) {
6230 		allocated_by_crypto_module = B_TRUE;
6231 		if (!copyin_mech(mode, sp,
6232 		    STRUCT_FADDR(unwrap_key, uk_mechanism),
6233 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6234 			goto release_minor;
6235 		}
6236 	} else {
6237 		if (rv != CRYPTO_SUCCESS)
6238 			goto release_minor;
6239 	}
6240 
6241 	count = STRUCT_FGET(unwrap_key, uk_count);
6242 	uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes);
6243 	if (!copyin_attributes(mode, sp, count, uk_attributes, &k_attrs,
6244 	    &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes,
6245 	    &k_attrs_rctl_chk, B_TRUE)) {
6246 		goto release_minor;
6247 	}
6248 
6249 	wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len);
6250 	if (wrapped_key_len > crypto_max_buffer_len) {
6251 		cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld "
6252 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
6253 		rv = CRYPTO_ARGUMENTS_BAD;
6254 		goto release_minor;
6255 	}
6256 
6257 	if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len,
6258 	    wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
6259 		goto release_minor;
6260 	}
6261 	wrapped_key_rctl_bytes = wrapped_key_len;
6262 	wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
6263 
6264 	if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key,
6265 	    uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) {
6266 		error = EFAULT;
6267 		goto release_minor;
6268 	}
6269 
6270 	/* wrapped_key_len is not modified by the unwrap operation */
6271 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP,
6272 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle,
6273 	    NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len);
6274 
6275 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6276 
6277 	if (rv == CRYPTO_SUCCESS)
6278 		STRUCT_FSET(unwrap_key, uk_object_handle, handle);
6279 
6280 release_minor:
6281 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6282 	CRYPTO_DECREMENT_RCTL_SESSION(sp, unwrapping_key_rctl_bytes,
6283 	    unwrapping_key_rctl_chk);
6284 	CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes,
6285 	    wrapped_key_rctl_chk);
6286 	CRYPTO_DECREMENT_RCTL_SESSION(sp, k_attrs_rctl_bytes,
6287 	    k_attrs_rctl_chk);
6288 
6289 	if (k_attrs != NULL)
6290 		kmem_free(k_attrs, k_attrs_size);
6291 
6292 	if (wrapped_key != NULL)
6293 		kmem_free(wrapped_key, wrapped_key_len);
6294 
6295 	free_crypto_key(&unwrapping_key);
6296 
6297 	if (error != 0)
6298 		goto out;
6299 
6300 	STRUCT_FSET(unwrap_key, uk_return_value, rv);
6301 	if (copyout(STRUCT_BUF(unwrap_key), arg,
6302 	    STRUCT_SIZE(unwrap_key)) != 0) {
6303 		if (rv == CRYPTO_SUCCESS) {
6304 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
6305 			    KCF_OP_OBJECT_DESTROY,
6306 			    sp->sd_provider_session->ps_session, handle,
6307 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
6308 
6309 			(void) kcf_submit_request(real_provider, NULL,
6310 			    NULL, &params, B_FALSE);
6311 
6312 			error = EFAULT;
6313 		}
6314 	}
6315 out:
6316 	CRYPTO_SESSION_RELE(sp);
6317 	crypto_release_minor(cm);
6318 
6319 	if (real_provider != NULL) {
6320 		crypto_free_mech(real_provider,
6321 		    allocated_by_crypto_module, &mech);
6322 		KCF_PROV_REFRELE(real_provider);
6323 	}
6324 
6325 	return (error);
6326 }
6327 
6328 /* ARGSUSED */
6329 static int
6330 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
6331 {
6332 	STRUCT_DECL(crypto_derive_key, derive_key);
6333 	kcf_provider_desc_t *real_provider = NULL;
6334 	kcf_req_params_t params;
6335 	crypto_object_attribute_t *k_attrs = NULL;
6336 	crypto_mechanism_t mech;
6337 	crypto_key_t base_key;
6338 	crypto_session_id_t session_id;
6339 	crypto_minor_t *cm;
6340 	crypto_session_data_t *sp = NULL;
6341 	crypto_object_id_t handle;
6342 	size_t k_attrs_size;
6343 	size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
6344 	boolean_t mech_rctl_chk = B_FALSE;
6345 	boolean_t key_rctl_chk = B_FALSE;
6346 	size_t attributes_rctl_bytes = 0;
6347 	boolean_t attributes_rctl_chk = B_FALSE;
6348 	caddr_t attributes;
6349 	uint_t count;
6350 	int error = 0;
6351 	int rv;
6352 	boolean_t allocated_by_crypto_module = B_FALSE;
6353 	boolean_t please_destroy_object = B_FALSE;
6354 
6355 	STRUCT_INIT(derive_key, mode);
6356 
6357 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6358 		cmn_err(CE_WARN, "object_derive_key: failed holding minor");
6359 		return (ENXIO);
6360 	}
6361 
6362 	if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
6363 		crypto_release_minor(cm);
6364 		return (EFAULT);
6365 	}
6366 
6367 	bzero(&base_key, sizeof (base_key));
6368 
6369 	session_id = STRUCT_FGET(derive_key, dk_session);
6370 
6371 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6372 		goto release_minor;
6373 	}
6374 
6375 	bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type,
6376 	    sizeof (crypto_mech_type_t));
6377 
6378 	/* We need the key length for provider selection so copy it in now. */
6379 	if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, dk_base_key),
6380 	    &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6381 		goto release_minor;
6382 	}
6383 
6384 	if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key,
6385 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6386 	    &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
6387 		goto release_minor;
6388 	}
6389 
6390 	rv = crypto_provider_copyin_mech_param(real_provider,
6391 	    STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error);
6392 
6393 	if (rv == CRYPTO_NOT_SUPPORTED) {
6394 		allocated_by_crypto_module = B_TRUE;
6395 		if (!copyin_mech(mode, sp,
6396 		    STRUCT_FADDR(derive_key, dk_mechanism),
6397 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6398 			goto release_minor;
6399 		}
6400 	} else {
6401 		if (rv != CRYPTO_SUCCESS)
6402 			goto release_minor;
6403 	}
6404 
6405 	count = STRUCT_FGET(derive_key, dk_count);
6406 
6407 	attributes = STRUCT_FGETP(derive_key, dk_attributes);
6408 	if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
6409 	    &k_attrs_size, NULL, &rv, &error,
6410 	    &attributes_rctl_bytes, &attributes_rctl_chk, B_TRUE)) {
6411 		goto release_minor;
6412 	}
6413 
6414 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE,
6415 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count,
6416 	    &handle, NULL, 0, NULL, &base_key, NULL, NULL);
6417 
6418 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6419 
6420 	if (rv == CRYPTO_SUCCESS) {
6421 		STRUCT_FSET(derive_key, dk_object_handle, handle);
6422 
6423 		rv = crypto_provider_copyout_mech_param(real_provider,
6424 		    &mech, STRUCT_FADDR(derive_key, dk_mechanism),
6425 		    mode, &error);
6426 
6427 		if (rv == CRYPTO_NOT_SUPPORTED) {
6428 			rv = CRYPTO_SUCCESS;
6429 			goto release_minor;
6430 		}
6431 
6432 		if (rv != CRYPTO_SUCCESS)
6433 			please_destroy_object = B_TRUE;
6434 	}
6435 
6436 release_minor:
6437 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6438 	CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6439 	CRYPTO_DECREMENT_RCTL_SESSION(sp, attributes_rctl_bytes,
6440 	    attributes_rctl_chk);
6441 
6442 	if (k_attrs != NULL)
6443 		kmem_free(k_attrs, k_attrs_size);
6444 
6445 	free_crypto_key(&base_key);
6446 
6447 	if (error != 0)
6448 		goto out;
6449 
6450 	STRUCT_FSET(derive_key, dk_return_value, rv);
6451 	if (copyout(STRUCT_BUF(derive_key), arg,
6452 	    STRUCT_SIZE(derive_key)) != 0) {
6453 		if (rv == CRYPTO_SUCCESS) {
6454 			please_destroy_object = B_TRUE;
6455 			error = EFAULT;
6456 		}
6457 	}
6458 out:
6459 	if (please_destroy_object) {
6460 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
6461 		    sp->sd_provider_session->ps_session, handle,
6462 		    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
6463 
6464 		(void) kcf_submit_request(real_provider, NULL,
6465 		    NULL, &params, B_FALSE);
6466 	}
6467 
6468 	CRYPTO_SESSION_RELE(sp);
6469 	crypto_release_minor(cm);
6470 
6471 	if (real_provider != NULL) {
6472 		crypto_free_mech(real_provider,
6473 		    allocated_by_crypto_module, &mech);
6474 		KCF_PROV_REFRELE(real_provider);
6475 	}
6476 	return (error);
6477 }
6478 
6479 /* ARGSUSED */
6480 static int
6481 nostore_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
6482 {
6483 	STRUCT_DECL(crypto_nostore_derive_key, derive_key);
6484 #ifdef _LP64
6485 	STRUCT_DECL(crypto_object_attribute, oa);
6486 #else
6487 	/* LINTED E_FUNC_SET_NOT_USED */
6488 	STRUCT_DECL(crypto_object_attribute, oa);
6489 #endif
6490 	kcf_provider_desc_t *real_provider = NULL;
6491 	kcf_req_params_t params;
6492 	crypto_object_attribute_t *k_in_attrs = NULL;
6493 	crypto_object_attribute_t *k_out_attrs = NULL;
6494 	crypto_mechanism_t mech;
6495 	crypto_key_t base_key;
6496 	crypto_session_id_t session_id;
6497 	crypto_minor_t *cm;
6498 	crypto_session_data_t *sp = NULL;
6499 	size_t k_in_attrs_size, k_out_attrs_size;
6500 	size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
6501 	boolean_t mech_rctl_chk = B_FALSE;
6502 	boolean_t key_rctl_chk = B_FALSE;
6503 	size_t in_attributes_rctl_bytes = 0;
6504 	size_t out_attributes_rctl_bytes = 0;
6505 	boolean_t in_attributes_rctl_chk = B_FALSE;
6506 	boolean_t out_attributes_rctl_chk = B_FALSE;
6507 	caddr_t in_attributes, out_attributes;
6508 	uint_t in_count, out_count;
6509 	int error = 0;
6510 	int rv;
6511 	boolean_t allocated_by_crypto_module = B_FALSE;
6512 	caddr_t u_attrs = NULL;
6513 
6514 	out_count = 0;
6515 	STRUCT_INIT(derive_key, mode);
6516 	STRUCT_INIT(oa, mode);
6517 
6518 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6519 		cmn_err(CE_WARN, "nostore_derive_key: failed holding minor");
6520 		return (ENXIO);
6521 	}
6522 
6523 	if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
6524 		crypto_release_minor(cm);
6525 		return (EFAULT);
6526 	}
6527 
6528 	bzero(&base_key, sizeof (base_key));
6529 
6530 	session_id = STRUCT_FGET(derive_key, ndk_session);
6531 
6532 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6533 		goto release_minor;
6534 	}
6535 
6536 	bcopy(STRUCT_FADDR(derive_key, ndk_mechanism), &mech.cm_type,
6537 	    sizeof (crypto_mech_type_t));
6538 
6539 	/* We need the key length for provider selection so copy it in now. */
6540 	if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, ndk_base_key),
6541 	    &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6542 		goto release_minor;
6543 	}
6544 
6545 	if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key,
6546 	    CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6547 	    &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
6548 		goto release_minor;
6549 	}
6550 
6551 	rv = crypto_provider_copyin_mech_param(real_provider,
6552 	    STRUCT_FADDR(derive_key, ndk_mechanism), &mech, mode, &error);
6553 
6554 	if (rv == CRYPTO_NOT_SUPPORTED) {
6555 		allocated_by_crypto_module = B_TRUE;
6556 		if (!copyin_mech(mode, sp,
6557 		    STRUCT_FADDR(derive_key, ndk_mechanism),
6558 		    &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6559 			goto release_minor;
6560 		}
6561 	} else {
6562 		if (rv != CRYPTO_SUCCESS)
6563 			goto release_minor;
6564 	}
6565 
6566 	in_count = STRUCT_FGET(derive_key, ndk_in_count);
6567 	out_count = STRUCT_FGET(derive_key, ndk_out_count);
6568 
6569 	in_attributes = STRUCT_FGETP(derive_key, ndk_in_attributes);
6570 	if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs,
6571 	    &k_in_attrs_size, NULL, &rv, &error, &in_attributes_rctl_bytes,
6572 	    &in_attributes_rctl_chk, B_TRUE)) {
6573 		goto release_minor;
6574 	}
6575 
6576 	out_attributes = STRUCT_FGETP(derive_key, ndk_out_attributes);
6577 	if (!copyin_attributes(mode, sp, out_count, out_attributes,
6578 	    &k_out_attrs, &k_out_attrs_size, &u_attrs, &rv, &error,
6579 	    &out_attributes_rctl_bytes,
6580 	    &out_attributes_rctl_chk, B_FALSE)) {
6581 		goto release_minor;
6582 	}
6583 
6584 	KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE,
6585 	    sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count,
6586 	    NULL, 0, &base_key, k_out_attrs, out_count, NULL, 0);
6587 
6588 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6589 
6590 	if (rv == CRYPTO_SUCCESS) {
6591 		rv = crypto_provider_copyout_mech_param(real_provider,
6592 		    &mech, STRUCT_FADDR(derive_key, ndk_mechanism),
6593 		    mode, &error);
6594 
6595 		if (rv == CRYPTO_NOT_SUPPORTED) {
6596 			rv = CRYPTO_SUCCESS;
6597 		}
6598 		/* copyout the derived secret */
6599 		if (copyout_attributes(mode, out_attributes, out_count,
6600 		    k_out_attrs, u_attrs) != 0)
6601 			error = EFAULT;
6602 	}
6603 
6604 release_minor:
6605 	CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6606 	CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6607 	CRYPTO_DECREMENT_RCTL_SESSION(sp, in_attributes_rctl_bytes,
6608 	    in_attributes_rctl_chk);
6609 	CRYPTO_DECREMENT_RCTL_SESSION(sp, out_attributes_rctl_bytes,
6610 	    out_attributes_rctl_chk);
6611 
6612 	if (k_in_attrs != NULL)
6613 		kmem_free(k_in_attrs, k_in_attrs_size);
6614 	if (k_out_attrs != NULL) {
6615 		bzero(k_out_attrs, k_out_attrs_size);
6616 		kmem_free(k_out_attrs, k_out_attrs_size);
6617 	}
6618 
6619 	if (u_attrs != NULL)
6620 		kmem_free(u_attrs, out_count * STRUCT_SIZE(oa));
6621 
6622 	free_crypto_key(&base_key);
6623 
6624 	if (error != 0)
6625 		goto out;
6626 
6627 	STRUCT_FSET(derive_key, ndk_return_value, rv);
6628 	if (copyout(STRUCT_BUF(derive_key), arg,
6629 	    STRUCT_SIZE(derive_key)) != 0) {
6630 		error = EFAULT;
6631 	}
6632 out:
6633 	CRYPTO_SESSION_RELE(sp);
6634 	crypto_release_minor(cm);
6635 
6636 	if (real_provider != NULL) {
6637 		crypto_free_mech(real_provider,
6638 		    allocated_by_crypto_module, &mech);
6639 		KCF_PROV_REFRELE(real_provider);
6640 	}
6641 	return (error);
6642 }
6643 
6644 static int
6645 get_provider_by_mech(dev_t dev, caddr_t arg, int mode, int *rval)
6646 {
6647 	_NOTE(ARGUNUSED(mode, rval))
6648 	kcf_mech_entry_t *me;
6649 	kcf_provider_desc_t *pd;
6650 	crypto_key_t key;
6651 	crypto_by_mech_t mech;
6652 	crypto_provider_session_t *ps;
6653 	crypto_minor_t *cm;
6654 	int rv, error;
6655 
6656 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6657 		cmn_err(CE_WARN, "get_provider_by_mech: failed holding minor");
6658 		return (ENXIO);
6659 	}
6660 
6661 	bzero(&key, sizeof (key));
6662 	key.ck_format = CRYPTO_KEY_RAW;
6663 
6664 	if (copyin(arg, &mech, sizeof (mech)) != 0) {
6665 		crypto_release_minor(cm);
6666 		return (EFAULT);
6667 	}
6668 
6669 	key.ck_length = mech.mech_keylen;
6670 	/* pd is returned held */
6671 	if ((pd = kcf_get_mech_provider(mech.mech_type, &key, &me, &error,
6672 	    NULL, mech.mech_fg, 0)) == NULL) {
6673 		rv = error;
6674 		goto release_minor;
6675 	}
6676 
6677 	/* don't want to allow direct access to software providers */
6678 	if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
6679 		rv = CRYPTO_MECHANISM_INVALID;
6680 		KCF_PROV_REFRELE(pd);
6681 		cmn_err(CE_WARN, "software mech_type given");
6682 		goto release_minor;
6683 	}
6684 
6685 	mutex_enter(&cm->cm_lock);
6686 	if ((rv = crypto_create_provider_session(cm, pd, pd->pd_sid, &ps, NULL))
6687 	    == CRYPTO_SUCCESS)
6688 		rv = crypto_create_session_ptr(cm, pd, ps, &mech.session_id);
6689 
6690 	mutex_exit(&cm->cm_lock);
6691 release_minor:
6692 	crypto_release_minor(cm);
6693 	mech.rv = rv;
6694 	if (copyout(&mech, arg, sizeof (mech)) != 0)
6695 		return (EFAULT);
6696 
6697 	return (rv);
6698 }
6699 
6700 /* ARGSUSED */
6701 static int
6702 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
6703     int *rval)
6704 {
6705 #define	ARG	((caddr_t)arg)
6706 
6707 	switch (cmd) {
6708 	case CRYPTO_GET_FUNCTION_LIST:
6709 		return (get_function_list(dev, ARG, mode, rval));
6710 
6711 	case CRYPTO_GET_MECHANISM_NUMBER:
6712 		return (get_mechanism_number(dev, ARG, mode, rval));
6713 
6714 	case CRYPTO_GET_MECHANISM_LIST:
6715 		return (get_mechanism_list(dev, ARG, mode, rval));
6716 
6717 	case CRYPTO_GET_ALL_MECHANISM_INFO:
6718 		return (get_all_mechanism_info(dev, ARG, mode, rval));
6719 
6720 	case CRYPTO_GET_PROVIDER_LIST:
6721 		return (get_provider_list(dev, ARG, mode, rval));
6722 
6723 	case CRYPTO_GET_PROVIDER_BY_MECH:
6724 		return (get_provider_by_mech(dev, ARG, mode, rval));
6725 
6726 	case CRYPTO_GET_PROVIDER_INFO:
6727 		return (get_provider_info(dev, ARG, mode, rval));
6728 
6729 	case CRYPTO_GET_PROVIDER_MECHANISMS:
6730 		return (get_provider_mechanisms(dev, ARG, mode, rval));
6731 
6732 	case CRYPTO_GET_PROVIDER_MECHANISM_INFO:
6733 		return (get_provider_mechanism_info(dev, ARG, mode, rval));
6734 
6735 	case CRYPTO_OPEN_SESSION:
6736 		return (open_session(dev, ARG, mode, rval));
6737 
6738 	case CRYPTO_CLOSE_SESSION:
6739 		return (close_session(dev, ARG, mode, rval));
6740 
6741 	case CRYPTO_ENCRYPT_INIT:
6742 		return (encrypt_init(dev, ARG, mode, rval));
6743 
6744 	case CRYPTO_DECRYPT_INIT:
6745 		return (decrypt_init(dev, ARG, mode, rval));
6746 
6747 	case CRYPTO_ENCRYPT:
6748 		return (encrypt(dev, ARG, mode, rval));
6749 
6750 	case CRYPTO_DECRYPT:
6751 		return (decrypt(dev, ARG, mode, rval));
6752 
6753 	case CRYPTO_ENCRYPT_UPDATE:
6754 		return (encrypt_update(dev, ARG, mode, rval));
6755 
6756 	case CRYPTO_DECRYPT_UPDATE:
6757 		return (decrypt_update(dev, ARG, mode, rval));
6758 
6759 	case CRYPTO_ENCRYPT_FINAL:
6760 		return (encrypt_final(dev, ARG, mode, rval));
6761 
6762 	case CRYPTO_DECRYPT_FINAL:
6763 		return (decrypt_final(dev, ARG, mode, rval));
6764 
6765 	case CRYPTO_DIGEST_INIT:
6766 		return (digest_init(dev, ARG, mode, rval));
6767 
6768 	case CRYPTO_DIGEST:
6769 		return (digest(dev, ARG, mode, rval));
6770 
6771 	case CRYPTO_DIGEST_UPDATE:
6772 		return (digest_update(dev, ARG, mode, rval));
6773 
6774 	case CRYPTO_DIGEST_KEY:
6775 		return (digest_key(dev, ARG, mode, rval));
6776 
6777 	case CRYPTO_DIGEST_FINAL:
6778 		return (digest_final(dev, ARG, mode, rval));
6779 
6780 	case CRYPTO_SIGN_INIT:
6781 		return (sign_init(dev, ARG, mode, rval));
6782 
6783 	case CRYPTO_SIGN:
6784 		return (sign(dev, ARG, mode, rval));
6785 
6786 	case CRYPTO_SIGN_UPDATE:
6787 		return (sign_update(dev, ARG, mode, rval));
6788 
6789 	case CRYPTO_SIGN_FINAL:
6790 		return (sign_final(dev, ARG, mode, rval));
6791 
6792 	case CRYPTO_SIGN_RECOVER_INIT:
6793 		return (sign_recover_init(dev, ARG, mode, rval));
6794 
6795 	case CRYPTO_SIGN_RECOVER:
6796 		return (sign_recover(dev, ARG, mode, rval));
6797 
6798 	case CRYPTO_VERIFY_INIT:
6799 		return (verify_init(dev, ARG, mode, rval));
6800 
6801 	case CRYPTO_VERIFY:
6802 		return (verify(dev, ARG, mode, rval));
6803 
6804 	case CRYPTO_VERIFY_UPDATE:
6805 		return (verify_update(dev, ARG, mode, rval));
6806 
6807 	case CRYPTO_VERIFY_FINAL:
6808 		return (verify_final(dev, ARG, mode, rval));
6809 
6810 	case CRYPTO_VERIFY_RECOVER_INIT:
6811 		return (verify_recover_init(dev, ARG, mode, rval));
6812 
6813 	case CRYPTO_VERIFY_RECOVER:
6814 		return (verify_recover(dev, ARG, mode, rval));
6815 
6816 	case CRYPTO_MAC_INIT:
6817 		return (mac_init(dev, ARG, mode, rval));
6818 
6819 	case CRYPTO_MAC:
6820 		return (mac(dev, ARG, mode, rval));
6821 
6822 	case CRYPTO_MAC_UPDATE:
6823 		return (mac_update(dev, ARG, mode, rval));
6824 
6825 	case CRYPTO_MAC_FINAL:
6826 		return (mac_final(dev, ARG, mode, rval));
6827 
6828 	case CRYPTO_SET_PIN:
6829 		return (set_pin(dev, ARG, mode, rval));
6830 
6831 	case CRYPTO_LOGIN:
6832 		return (login(dev, ARG, mode, rval));
6833 
6834 	case CRYPTO_LOGOUT:
6835 		return (logout(dev, ARG, mode, rval));
6836 
6837 	case CRYPTO_SEED_RANDOM:
6838 		return (seed_random(dev, ARG, mode, rval));
6839 
6840 	case CRYPTO_GENERATE_RANDOM:
6841 		return (generate_random(dev, ARG, mode, rval));
6842 
6843 	case CRYPTO_OBJECT_CREATE:
6844 		return (object_create(dev, ARG, mode, rval));
6845 
6846 	case CRYPTO_OBJECT_COPY:
6847 		return (object_copy(dev, ARG, mode, rval));
6848 
6849 	case CRYPTO_OBJECT_DESTROY:
6850 		return (object_destroy(dev, ARG, mode, rval));
6851 
6852 	case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE:
6853 		return (object_get_attribute_value(dev, ARG, mode, rval));
6854 
6855 	case CRYPTO_OBJECT_GET_SIZE:
6856 		return (object_get_size(dev, ARG, mode, rval));
6857 
6858 	case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE:
6859 		return (object_set_attribute_value(dev, ARG, mode, rval));
6860 
6861 	case CRYPTO_OBJECT_FIND_INIT:
6862 		return (object_find_init(dev, ARG, mode, rval));
6863 
6864 	case CRYPTO_OBJECT_FIND_UPDATE:
6865 		return (object_find_update(dev, ARG, mode, rval));
6866 
6867 	case CRYPTO_OBJECT_FIND_FINAL:
6868 		return (object_find_final(dev, ARG, mode, rval));
6869 
6870 	case CRYPTO_GENERATE_KEY:
6871 		return (object_generate_key(dev, ARG, mode, rval));
6872 
6873 	case CRYPTO_GENERATE_KEY_PAIR:
6874 		return (object_generate_key_pair(dev, ARG, mode, rval));
6875 
6876 	case CRYPTO_WRAP_KEY:
6877 		return (object_wrap_key(dev, ARG, mode, rval));
6878 
6879 	case CRYPTO_UNWRAP_KEY:
6880 		return (object_unwrap_key(dev, ARG, mode, rval));
6881 
6882 	case CRYPTO_DERIVE_KEY:
6883 		return (object_derive_key(dev, ARG, mode, rval));
6884 
6885 	case CRYPTO_NOSTORE_GENERATE_KEY:
6886 		return (nostore_generate_key(dev, ARG, mode, rval));
6887 
6888 	case CRYPTO_NOSTORE_GENERATE_KEY_PAIR:
6889 		return (nostore_generate_key_pair(dev, ARG, mode, rval));
6890 
6891 	case CRYPTO_NOSTORE_DERIVE_KEY:
6892 		return (nostore_derive_key(dev, ARG, mode, rval));
6893 	}
6894 	return (EINVAL);
6895 }
6896 
6897 /*
6898  * Check for the project.max-crypto-memory resource control.
6899  */
6900 static int
6901 crypto_buffer_check(size_t need)
6902 {
6903 	kproject_t *kpj;
6904 
6905 	if (need == 0)
6906 		return (CRYPTO_SUCCESS);
6907 
6908 	mutex_enter(&curproc->p_lock);
6909 	kpj = curproc->p_task->tk_proj;
6910 	mutex_enter(&(kpj->kpj_data.kpd_crypto_lock));
6911 
6912 	if (kpj->kpj_data.kpd_crypto_mem + need >
6913 	    kpj->kpj_data.kpd_crypto_mem_ctl) {
6914 		if (rctl_test(rc_project_crypto_mem,
6915 		    kpj->kpj_rctls, curproc, need, 0) & RCT_DENY) {
6916 			mutex_exit(&(kpj->kpj_data.kpd_crypto_lock));
6917 			mutex_exit(&curproc->p_lock);
6918 			return (CRYPTO_HOST_MEMORY);
6919 		}
6920 	}
6921 
6922 	kpj->kpj_data.kpd_crypto_mem += need;
6923 	mutex_exit(&(kpj->kpj_data.kpd_crypto_lock));
6924 
6925 	curproc->p_crypto_mem += need;
6926 	mutex_exit(&curproc->p_lock);
6927 
6928 	return (CRYPTO_SUCCESS);
6929 }
6930