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