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