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