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