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