xref: /titanic_51/usr/src/uts/common/crypto/io/crypto.c (revision 7b93957c241820af312fd1aad1e23e305a8dabbf)
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);
4090 
4091 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4092 
4093 out:
4094 	CRYPTO_SESSION_RELE(sp);
4095 
4096 release_minor:
4097 	if (need != 0) {
4098 		mutex_enter(&crypto_rctl_lock);
4099 		CRYPTO_DECREMENT_RCTL(need, projp);
4100 		mutex_exit(&crypto_rctl_lock);
4101 	}
4102 	crypto_release_minor(cm);
4103 
4104 	if (real_provider != NULL)
4105 		KCF_PROV_REFRELE(real_provider);
4106 
4107 	if (seed_buffer != NULL)
4108 		kmem_free(seed_buffer, seed_len);
4109 
4110 	if (error != 0)
4111 		return (error);
4112 
4113 	STRUCT_FSET(seed_random, sr_return_value, rv);
4114 	if (copyout(STRUCT_BUF(seed_random), arg,
4115 	    STRUCT_SIZE(seed_random)) != 0) {
4116 		return (EFAULT);
4117 	}
4118 	return (0);
4119 }
4120 
4121 /* ARGSUSED */
4122 static int
4123 generate_random(dev_t dev, caddr_t arg, int mode, int *rval)
4124 {
4125 	STRUCT_DECL(crypto_generate_random, generate_random);
4126 	kproject_t *projp;
4127 	kcf_provider_desc_t *real_provider = NULL;
4128 	kcf_req_params_t params;
4129 	crypto_session_id_t session_id;
4130 	crypto_minor_t *cm;
4131 	crypto_session_data_t *sp;
4132 	uchar_t *buffer = NULL;
4133 	size_t len;
4134 	size_t need = 0;
4135 	int error = 0;
4136 	int rv;
4137 
4138 	STRUCT_INIT(generate_random, mode);
4139 
4140 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4141 		cmn_err(CE_WARN, "generate_random: failed holding minor");
4142 		return (ENXIO);
4143 	}
4144 
4145 	if (copyin(arg, STRUCT_BUF(generate_random),
4146 	    STRUCT_SIZE(generate_random)) != 0) {
4147 		crypto_release_minor(cm);
4148 		return (EFAULT);
4149 	}
4150 
4151 	len = STRUCT_FGET(generate_random, gr_buflen);
4152 	if (len > crypto_max_buffer_len) {
4153 		cmn_err(CE_NOTE, "generate_random: buffer greater than %ld "
4154 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4155 		rv = CRYPTO_ARGUMENTS_BAD;
4156 		goto release_minor;
4157 	}
4158 
4159 	if ((rv = crypto_buffer_check(len, &projp)) != CRYPTO_SUCCESS) {
4160 		goto release_minor;
4161 	}
4162 	need = len;
4163 	buffer = kmem_alloc(len, KM_SLEEP);
4164 
4165 	session_id = STRUCT_FGET(generate_random, gr_session);
4166 
4167 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4168 		goto release_minor;
4169 	}
4170 
4171 	if ((rv = kcf_get_hardware_provider_nomech(
4172 	    CRYPTO_OPS_OFFSET(random_ops),
4173 	    CRYPTO_RANDOM_OFFSET(generate_random), CHECK_RESTRICT_FALSE,
4174 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4175 		goto out;
4176 	}
4177 
4178 	KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_GENERATE,
4179 	    sp->sd_provider_session->ps_session, buffer, len);
4180 
4181 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4182 
4183 out:
4184 	CRYPTO_SESSION_RELE(sp);
4185 
4186 	if (rv == CRYPTO_SUCCESS) {
4187 		if (len != 0 && copyout(buffer,
4188 		    STRUCT_FGETP(generate_random, gr_buf), len) != 0) {
4189 			error = EFAULT;
4190 		}
4191 	}
4192 
4193 release_minor:
4194 	if (need != 0) {
4195 		mutex_enter(&crypto_rctl_lock);
4196 		CRYPTO_DECREMENT_RCTL(need, projp);
4197 		mutex_exit(&crypto_rctl_lock);
4198 	}
4199 	crypto_release_minor(cm);
4200 
4201 	if (real_provider != NULL)
4202 		KCF_PROV_REFRELE(real_provider);
4203 
4204 	if (buffer != NULL) {
4205 		/* random numbers are often used to create keys */
4206 		bzero(buffer, len);
4207 		kmem_free(buffer, len);
4208 	}
4209 
4210 	if (error != 0)
4211 		return (error);
4212 
4213 	STRUCT_FSET(generate_random, gr_return_value, rv);
4214 	if (copyout(STRUCT_BUF(generate_random), arg,
4215 	    STRUCT_SIZE(generate_random)) != 0) {
4216 		return (EFAULT);
4217 	}
4218 	return (0);
4219 }
4220 
4221 /*
4222  * Copyout a kernel array of attributes to user space.
4223  * u_attrs is the corresponding user space array containing
4224  * user space pointers necessary for the copyout.
4225  */
4226 /* ARGSUSED */
4227 static int
4228 copyout_attributes(int mode, caddr_t out, uint_t count,
4229     crypto_object_attribute_t *k_attrs, caddr_t u_attrs)
4230 {
4231 	STRUCT_DECL(crypto_object_attribute, oa);
4232 	caddr_t p, valuep;
4233 	size_t value_len;
4234 	size_t len;
4235 	int i;
4236 	int error = 0;
4237 
4238 	if (count == 0)
4239 		return (0);
4240 
4241 	STRUCT_INIT(oa, mode);
4242 
4243 	len = count * STRUCT_SIZE(oa);
4244 
4245 	ASSERT(u_attrs != NULL);
4246 	p = u_attrs;
4247 	for (i = 0; i < count; i++) {
4248 		/* can this bcopy be eliminated? */
4249 		bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa));
4250 		value_len = k_attrs[i].oa_value_len;
4251 		STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type);
4252 		STRUCT_FSET(oa, oa_value_len, value_len);
4253 		valuep = STRUCT_FGETP(oa, oa_value);
4254 		if (valuep != NULL && value_len != -1) {
4255 			if (copyout(k_attrs[i].oa_value,
4256 			    valuep, value_len) != 0) {
4257 				error = EFAULT;
4258 				goto out;
4259 			}
4260 		}
4261 		bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa));
4262 		p += STRUCT_SIZE(oa);
4263 	}
4264 	if (copyout(u_attrs, out, len)) {
4265 		error = EFAULT;
4266 	}
4267 out:
4268 	return (error);
4269 }
4270 
4271 
4272 /* ARGSUSED */
4273 static int
4274 object_create(dev_t dev, caddr_t arg, int mode, int *rval)
4275 {
4276 	STRUCT_DECL(crypto_object_create, object_create);
4277 	kproject_t *projp;
4278 	kcf_provider_desc_t *real_provider = NULL;
4279 	kcf_req_params_t params;
4280 	crypto_object_attribute_t *k_attrs = NULL;
4281 	crypto_session_id_t session_id;
4282 	crypto_minor_t *cm;
4283 	crypto_session_data_t *sp = NULL;
4284 	crypto_object_id_t object_handle;
4285 	caddr_t oc_attributes;
4286 	size_t k_attrs_size;
4287 	size_t rctl_bytes = 0;
4288 	int error = 0;
4289 	int rv;
4290 	uint_t count;
4291 
4292 	STRUCT_INIT(object_create, mode);
4293 
4294 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4295 		cmn_err(CE_WARN, "object_create: failed holding minor");
4296 		return (ENXIO);
4297 	}
4298 
4299 	if (copyin(arg, STRUCT_BUF(object_create),
4300 	    STRUCT_SIZE(object_create)) != 0) {
4301 		crypto_release_minor(cm);
4302 		return (EFAULT);
4303 	}
4304 
4305 	count = STRUCT_FGET(object_create, oc_count);
4306 	oc_attributes = STRUCT_FGETP(object_create, oc_attributes);
4307 	if (!copyin_attributes(mode, count, oc_attributes, &k_attrs,
4308 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4309 		goto release_minor;
4310 	}
4311 
4312 	session_id = STRUCT_FGET(object_create, oc_session);
4313 
4314 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4315 		goto release_minor;
4316 	}
4317 
4318 	if ((rv = kcf_get_hardware_provider_nomech(
4319 	    CRYPTO_OPS_OFFSET(object_ops),
4320 	    CRYPTO_OBJECT_OFFSET(object_create),
4321 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4322 	    != CRYPTO_SUCCESS) {
4323 		goto release_minor;
4324 	}
4325 
4326 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_CREATE,
4327 	    sp->sd_provider_session->ps_session, 0, k_attrs, count,
4328 	    &object_handle, 0, NULL, NULL, 0, NULL);
4329 
4330 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4331 
4332 	if (rv == CRYPTO_SUCCESS)
4333 		STRUCT_FSET(object_create, oc_handle, object_handle);
4334 
4335 release_minor:
4336 	if (rctl_bytes != 0) {
4337 		mutex_enter(&crypto_rctl_lock);
4338 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4339 		mutex_exit(&crypto_rctl_lock);
4340 	}
4341 
4342 	if (k_attrs != NULL)
4343 		kmem_free(k_attrs, k_attrs_size);
4344 
4345 	if (error != 0)
4346 		goto out;
4347 
4348 	STRUCT_FSET(object_create, oc_return_value, rv);
4349 	if (copyout(STRUCT_BUF(object_create), arg,
4350 	    STRUCT_SIZE(object_create)) != 0) {
4351 		if (rv == CRYPTO_SUCCESS) {
4352 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4353 			    KCF_OP_OBJECT_DESTROY,
4354 			    sp->sd_provider_session->ps_session, object_handle,
4355 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4356 
4357 			(void) kcf_submit_request(real_provider, NULL,
4358 			    NULL, &params, B_FALSE);
4359 
4360 			error = EFAULT;
4361 		}
4362 	}
4363 out:
4364 	if (sp != NULL)
4365 		CRYPTO_SESSION_RELE(sp);
4366 	crypto_release_minor(cm);
4367 	if (real_provider != NULL)
4368 		KCF_PROV_REFRELE(real_provider);
4369 	return (error);
4370 }
4371 
4372 /* ARGSUSED */
4373 static int
4374 object_copy(dev_t dev, caddr_t arg, int mode, int *rval)
4375 {
4376 	STRUCT_DECL(crypto_object_copy, object_copy);
4377 	kproject_t *projp;
4378 	kcf_provider_desc_t *real_provider = NULL;
4379 	kcf_req_params_t params;
4380 	crypto_object_attribute_t *k_attrs = NULL;
4381 	crypto_session_id_t session_id;
4382 	crypto_minor_t *cm;
4383 	crypto_session_data_t *sp = NULL;
4384 	crypto_object_id_t handle, new_handle;
4385 	caddr_t oc_new_attributes;
4386 	size_t k_attrs_size;
4387 	size_t rctl_bytes = 0;
4388 	int error = 0;
4389 	int rv;
4390 	uint_t count;
4391 
4392 	STRUCT_INIT(object_copy, mode);
4393 
4394 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4395 		cmn_err(CE_WARN, "object_copy: failed holding minor");
4396 		return (ENXIO);
4397 	}
4398 
4399 	if (copyin(arg, STRUCT_BUF(object_copy),
4400 	    STRUCT_SIZE(object_copy)) != 0) {
4401 		crypto_release_minor(cm);
4402 		return (EFAULT);
4403 	}
4404 
4405 	count = STRUCT_FGET(object_copy, oc_count);
4406 	oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes);
4407 	if (!copyin_attributes(mode, count, oc_new_attributes, &k_attrs,
4408 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4409 		goto release_minor;
4410 	}
4411 
4412 	session_id = STRUCT_FGET(object_copy, oc_session);
4413 
4414 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4415 		goto release_minor;
4416 	}
4417 
4418 	if ((rv = kcf_get_hardware_provider_nomech(
4419 	    CRYPTO_OPS_OFFSET(object_ops),
4420 	    CRYPTO_OBJECT_OFFSET(object_copy), CHECK_RESTRICT_FALSE,
4421 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4422 		goto release_minor;
4423 	}
4424 
4425 	handle = STRUCT_FGET(object_copy, oc_handle);
4426 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_COPY,
4427 	    sp->sd_provider_session->ps_session, handle, k_attrs, count,
4428 	    &new_handle, 0, NULL, NULL, 0, NULL);
4429 
4430 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4431 
4432 	if (rv == CRYPTO_SUCCESS)
4433 		STRUCT_FSET(object_copy, oc_new_handle, new_handle);
4434 
4435 release_minor:
4436 	if (rctl_bytes != 0) {
4437 		mutex_enter(&crypto_rctl_lock);
4438 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4439 		mutex_exit(&crypto_rctl_lock);
4440 	}
4441 
4442 	if (k_attrs != NULL)
4443 		kmem_free(k_attrs, k_attrs_size);
4444 
4445 	if (error != 0)
4446 		goto out;
4447 
4448 	STRUCT_FSET(object_copy, oc_return_value, rv);
4449 	if (copyout(STRUCT_BUF(object_copy), arg,
4450 	    STRUCT_SIZE(object_copy)) != 0) {
4451 		if (rv == CRYPTO_SUCCESS) {
4452 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4453 			    KCF_OP_OBJECT_DESTROY,
4454 			    sp->sd_provider_session->ps_session, new_handle,
4455 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4456 
4457 			(void) kcf_submit_request(real_provider, NULL,
4458 			    NULL, &params, B_FALSE);
4459 
4460 			error = EFAULT;
4461 		}
4462 	}
4463 out:
4464 	if (sp != NULL)
4465 		CRYPTO_SESSION_RELE(sp);
4466 	crypto_release_minor(cm);
4467 	if (real_provider != NULL)
4468 		KCF_PROV_REFRELE(real_provider);
4469 	return (error);
4470 }
4471 
4472 /* ARGSUSED */
4473 static int
4474 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval)
4475 {
4476 	STRUCT_DECL(crypto_object_destroy, object_destroy);
4477 	kcf_provider_desc_t *real_provider;
4478 	kcf_req_params_t params;
4479 	crypto_session_id_t session_id;
4480 	crypto_minor_t *cm;
4481 	crypto_session_data_t *sp;
4482 	crypto_object_id_t handle;
4483 	int error = 0;
4484 	int rv;
4485 
4486 	STRUCT_INIT(object_destroy, mode);
4487 
4488 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4489 		cmn_err(CE_WARN, "object_destroy: failed holding minor");
4490 		return (ENXIO);
4491 	}
4492 
4493 	if (copyin(arg, STRUCT_BUF(object_destroy),
4494 	    STRUCT_SIZE(object_destroy)) != 0) {
4495 		crypto_release_minor(cm);
4496 		return (EFAULT);
4497 	}
4498 
4499 	session_id = STRUCT_FGET(object_destroy, od_session);
4500 
4501 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4502 		goto release_minor;
4503 	}
4504 
4505 	if ((rv = kcf_get_hardware_provider_nomech(
4506 	    CRYPTO_OPS_OFFSET(object_ops),
4507 	    CRYPTO_OBJECT_OFFSET(object_destroy), CHECK_RESTRICT_FALSE,
4508 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4509 		goto out;
4510 	}
4511 
4512 	handle = STRUCT_FGET(object_destroy, od_handle);
4513 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
4514 	    sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0,
4515 	    NULL, NULL, 0, NULL);
4516 
4517 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4518 	KCF_PROV_REFRELE(real_provider);
4519 
4520 out:
4521 	CRYPTO_SESSION_RELE(sp);
4522 
4523 release_minor:
4524 	crypto_release_minor(cm);
4525 
4526 	if (error != 0)
4527 		return (error);
4528 
4529 	STRUCT_FSET(object_destroy, od_return_value, rv);
4530 
4531 	if (copyout(STRUCT_BUF(object_destroy), arg,
4532 	    STRUCT_SIZE(object_destroy)) != 0) {
4533 		return (EFAULT);
4534 	}
4535 	return (0);
4536 }
4537 
4538 /* ARGSUSED */
4539 static int
4540 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4541 {
4542 	STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value);
4543 	/* LINTED E_FUNC_SET_NOT_USED */
4544 	STRUCT_DECL(crypto_object_attribute, oa);
4545 	kproject_t *projp;
4546 	kcf_provider_desc_t *real_provider;
4547 	kcf_req_params_t params;
4548 	crypto_object_attribute_t *k_attrs = NULL;
4549 	crypto_session_id_t session_id;
4550 	crypto_minor_t *cm;
4551 	crypto_session_data_t *sp;
4552 	crypto_object_id_t handle;
4553 	caddr_t og_attributes;
4554 	caddr_t u_attrs;
4555 	size_t k_attrs_size;
4556 	size_t rctl_bytes = 0;
4557 	int error = 0;
4558 	int rv;
4559 	uint_t count;
4560 
4561 	STRUCT_INIT(get_attribute_value, mode);
4562 	STRUCT_INIT(oa, mode);
4563 
4564 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4565 		cmn_err(CE_WARN,
4566 		    "object_get_attribute_value: failed holding minor");
4567 		return (ENXIO);
4568 	}
4569 
4570 	if (copyin(arg, STRUCT_BUF(get_attribute_value),
4571 	    STRUCT_SIZE(get_attribute_value)) != 0) {
4572 		crypto_release_minor(cm);
4573 		return (EFAULT);
4574 	}
4575 
4576 	count = STRUCT_FGET(get_attribute_value, og_count);
4577 	og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes);
4578 	if (!copyin_attributes(mode, count, og_attributes, &k_attrs,
4579 	    &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes, 0, B_FALSE,
4580 	    &projp)) {
4581 		goto release_minor;
4582 	}
4583 
4584 	session_id = STRUCT_FGET(get_attribute_value, og_session);
4585 
4586 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4587 		goto release_minor;
4588 	}
4589 
4590 	if ((rv = kcf_get_hardware_provider_nomech(
4591 	    CRYPTO_OPS_OFFSET(object_ops),
4592 	    CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
4593 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4594 	    != CRYPTO_SUCCESS) {
4595 		goto out;
4596 	}
4597 
4598 	handle = STRUCT_FGET(get_attribute_value, og_handle);
4599 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE,
4600 	    sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL,
4601 	    0, NULL, NULL, 0, NULL);
4602 
4603 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4604 	KCF_PROV_REFRELE(real_provider);
4605 
4606 out:
4607 	CRYPTO_SESSION_RELE(sp);
4608 
4609 	if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE ||
4610 	    rv == CRYPTO_ATTRIBUTE_TYPE_INVALID ||
4611 	    rv == CRYPTO_BUFFER_TOO_SMALL) {
4612 		error = copyout_attributes(mode,
4613 		    STRUCT_FGETP(get_attribute_value, og_attributes),
4614 		    count, k_attrs, u_attrs);
4615 	}
4616 
4617 release_minor:
4618 	if (rctl_bytes != 0) {
4619 		mutex_enter(&crypto_rctl_lock);
4620 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4621 		mutex_exit(&crypto_rctl_lock);
4622 	}
4623 	crypto_release_minor(cm);
4624 
4625 	if (k_attrs != NULL)
4626 		kmem_free(k_attrs, k_attrs_size);
4627 
4628 	if (u_attrs != NULL)
4629 		kmem_free(u_attrs, count * STRUCT_SIZE(oa));
4630 
4631 	if (error != 0)
4632 		return (error);
4633 
4634 	STRUCT_FSET(get_attribute_value, og_return_value, rv);
4635 	if (copyout(STRUCT_BUF(get_attribute_value), arg,
4636 	    STRUCT_SIZE(get_attribute_value)) != 0) {
4637 		return (EFAULT);
4638 	}
4639 	return (0);
4640 }
4641 
4642 /* ARGSUSED */
4643 static int
4644 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval)
4645 {
4646 	STRUCT_DECL(crypto_object_get_size, object_get_size);
4647 	kcf_provider_desc_t *real_provider;
4648 	kcf_req_params_t params;
4649 	crypto_session_id_t session_id;
4650 	crypto_minor_t *cm;
4651 	crypto_session_data_t *sp;
4652 	crypto_object_id_t handle;
4653 	size_t size;
4654 	int error = 0;
4655 	int rv;
4656 
4657 	STRUCT_INIT(object_get_size, mode);
4658 
4659 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4660 		cmn_err(CE_WARN, "object_get_size: failed holding minor");
4661 		return (ENXIO);
4662 	}
4663 
4664 	if (copyin(arg, STRUCT_BUF(object_get_size),
4665 	    STRUCT_SIZE(object_get_size)) != 0) {
4666 		crypto_release_minor(cm);
4667 		return (EFAULT);
4668 	}
4669 
4670 	session_id = STRUCT_FGET(object_get_size, gs_session);
4671 
4672 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4673 		goto release_minor;
4674 	}
4675 
4676 	if ((rv = kcf_get_hardware_provider_nomech(
4677 	    CRYPTO_OPS_OFFSET(object_ops),
4678 	    CRYPTO_OBJECT_OFFSET(object_get_size), CHECK_RESTRICT_FALSE,
4679 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4680 		goto out;
4681 	}
4682 
4683 	handle = STRUCT_FGET(object_get_size, gs_handle);
4684 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_SIZE,
4685 	    sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size,
4686 	    NULL, NULL, 0, NULL);
4687 
4688 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4689 	KCF_PROV_REFRELE(real_provider);
4690 
4691 out:
4692 	CRYPTO_SESSION_RELE(sp);
4693 
4694 	if (rv == CRYPTO_SUCCESS) {
4695 		STRUCT_FSET(object_get_size, gs_size, size);
4696 	}
4697 release_minor:
4698 	crypto_release_minor(cm);
4699 
4700 	if (error != 0)
4701 		return (error);
4702 
4703 	STRUCT_FSET(object_get_size, gs_return_value, rv);
4704 	if (copyout(STRUCT_BUF(object_get_size), arg,
4705 	    STRUCT_SIZE(object_get_size)) != 0) {
4706 		return (EFAULT);
4707 	}
4708 	return (0);
4709 }
4710 
4711 /* ARGSUSED */
4712 static int
4713 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4714 {
4715 	STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value);
4716 	kproject_t *projp;
4717 	kcf_provider_desc_t *real_provider;
4718 	kcf_req_params_t params;
4719 	crypto_object_attribute_t *k_attrs = NULL;
4720 	crypto_session_id_t session_id;
4721 	crypto_minor_t *cm;
4722 	crypto_session_data_t *sp;
4723 	crypto_object_id_t object_handle;
4724 	caddr_t sa_attributes;
4725 	size_t k_attrs_size;
4726 	size_t rctl_bytes = 0;
4727 	int error = 0;
4728 	int rv;
4729 	uint_t count;
4730 
4731 	STRUCT_INIT(set_attribute_value, mode);
4732 
4733 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4734 		cmn_err(CE_WARN,
4735 		    "object_set_attribute_value: failed holding minor");
4736 		return (ENXIO);
4737 	}
4738 
4739 	if (copyin(arg, STRUCT_BUF(set_attribute_value),
4740 	    STRUCT_SIZE(set_attribute_value)) != 0) {
4741 		crypto_release_minor(cm);
4742 		return (EFAULT);
4743 	}
4744 
4745 	count = STRUCT_FGET(set_attribute_value, sa_count);
4746 	sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes);
4747 	if (!copyin_attributes(mode, count, sa_attributes, &k_attrs,
4748 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4749 		goto release_minor;
4750 	}
4751 
4752 	session_id = STRUCT_FGET(set_attribute_value, sa_session);
4753 
4754 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4755 		goto release_minor;
4756 	}
4757 
4758 	if ((rv = kcf_get_hardware_provider_nomech(
4759 	    CRYPTO_OPS_OFFSET(object_ops),
4760 	    CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
4761 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4762 	    != CRYPTO_SUCCESS) {
4763 		goto out;
4764 	}
4765 
4766 	object_handle = STRUCT_FGET(set_attribute_value, sa_handle);
4767 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE,
4768 	    sp->sd_provider_session->ps_session, object_handle, k_attrs, count,
4769 	    NULL, 0, NULL, NULL, 0, NULL);
4770 
4771 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4772 	KCF_PROV_REFRELE(real_provider);
4773 
4774 out:
4775 	CRYPTO_SESSION_RELE(sp);
4776 
4777 release_minor:
4778 	if (rctl_bytes != 0) {
4779 		mutex_enter(&crypto_rctl_lock);
4780 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4781 		mutex_exit(&crypto_rctl_lock);
4782 	}
4783 	crypto_release_minor(cm);
4784 
4785 	if (k_attrs != NULL)
4786 		kmem_free(k_attrs, k_attrs_size);
4787 
4788 	if (error != 0)
4789 		return (error);
4790 
4791 	STRUCT_FSET(set_attribute_value, sa_return_value, rv);
4792 	if (copyout(STRUCT_BUF(set_attribute_value), arg,
4793 	    STRUCT_SIZE(set_attribute_value)) != 0) {
4794 		return (EFAULT);
4795 	}
4796 	return (0);
4797 }
4798 
4799 /* ARGSUSED */
4800 static int
4801 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval)
4802 {
4803 	STRUCT_DECL(crypto_object_find_init, find_init);
4804 	kproject_t *projp;
4805 	kcf_provider_desc_t *real_provider = NULL;
4806 	kcf_req_params_t params;
4807 	crypto_object_attribute_t *k_attrs = NULL;
4808 	crypto_session_id_t session_id;
4809 	crypto_minor_t *cm;
4810 	crypto_session_data_t *sp;
4811 	caddr_t attributes;
4812 	size_t k_attrs_size;
4813 	size_t rctl_bytes = 0;
4814 	int error = 0;
4815 	int rv;
4816 	uint_t count;
4817 	void *cookie;
4818 
4819 	STRUCT_INIT(find_init, mode);
4820 
4821 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4822 		cmn_err(CE_WARN, "object_find_init: failed holding minor");
4823 		return (ENXIO);
4824 	}
4825 
4826 	if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) {
4827 		crypto_release_minor(cm);
4828 		return (EFAULT);
4829 	}
4830 
4831 	count = STRUCT_FGET(find_init, fi_count);
4832 	attributes = STRUCT_FGETP(find_init, fi_attributes);
4833 	if (!copyin_attributes(mode, count, attributes, &k_attrs,
4834 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4835 		goto release_minor;
4836 	}
4837 
4838 	session_id = STRUCT_FGET(find_init, fi_session);
4839 
4840 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4841 		goto release_minor;
4842 	}
4843 
4844 	if ((rv = kcf_get_hardware_provider_nomech(
4845 	    CRYPTO_OPS_OFFSET(object_ops),
4846 	    CRYPTO_OBJECT_OFFSET(object_find_init), CHECK_RESTRICT_FALSE,
4847 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4848 		goto out;
4849 	}
4850 
4851 	/* check for an active find */
4852 	if (sp->sd_find_init_cookie != NULL) {
4853 		rv = CRYPTO_OPERATION_IS_ACTIVE;
4854 		CRYPTO_SESSION_RELE(sp);
4855 		goto release_minor;
4856 	}
4857 
4858 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_INIT,
4859 	    sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0,
4860 	    &cookie, NULL, 0, NULL);
4861 
4862 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4863 
4864 	if (rv == CRYPTO_SUCCESS) {
4865 		/*
4866 		 * The cookie is allocated by a provider at the start of an
4867 		 * object search.  It is freed when the search is terminated
4868 		 * by a final operation, or when the session is closed.
4869 		 * It contains state information about which object handles
4870 		 * have been returned to the caller.
4871 		 */
4872 		sp->sd_find_init_cookie = cookie;
4873 	}
4874 
4875 out:
4876 	CRYPTO_SESSION_RELE(sp);
4877 
4878 release_minor:
4879 	if (rctl_bytes != 0) {
4880 		mutex_enter(&crypto_rctl_lock);
4881 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4882 		mutex_exit(&crypto_rctl_lock);
4883 	}
4884 	crypto_release_minor(cm);
4885 
4886 	if (real_provider != NULL)
4887 		KCF_PROV_REFRELE(real_provider);
4888 
4889 	if (k_attrs != NULL)
4890 		kmem_free(k_attrs, k_attrs_size);
4891 
4892 	if (error != 0)
4893 		return (error);
4894 
4895 	STRUCT_FSET(find_init, fi_return_value, rv);
4896 	if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) {
4897 		return (EFAULT);
4898 	}
4899 	return (0);
4900 }
4901 
4902 /* ARGSUSED */
4903 static int
4904 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval)
4905 {
4906 	STRUCT_DECL(crypto_object_find_update, find_update);
4907 	kproject_t *projp;
4908 	kcf_provider_desc_t *real_provider;
4909 	kcf_req_params_t params;
4910 	crypto_minor_t *cm;
4911 	crypto_session_data_t *sp;
4912 	crypto_object_id_t *buffer = NULL;
4913 	crypto_session_id_t session_id;
4914 	size_t len, rctl_bytes = 0;
4915 	uint_t count, max_count;
4916 	int rv, error = 0;
4917 
4918 	STRUCT_INIT(find_update, mode);
4919 
4920 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4921 		cmn_err(CE_WARN, "object_find_update: failed holding minor");
4922 		return (ENXIO);
4923 	}
4924 
4925 	if (copyin(arg, STRUCT_BUF(find_update),
4926 	    STRUCT_SIZE(find_update)) != 0) {
4927 		crypto_release_minor(cm);
4928 		return (EFAULT);
4929 	}
4930 
4931 	max_count = STRUCT_FGET(find_update, fu_max_count);
4932 	if (max_count > CRYPTO_MAX_FIND_COUNT) {
4933 		cmn_err(CE_NOTE, "object_find_update: count greater than %d, "
4934 		    "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid);
4935 		rv = CRYPTO_ARGUMENTS_BAD;
4936 		goto release_minor;
4937 	}
4938 	len = max_count * sizeof (crypto_object_id_t);
4939 	if ((rv = crypto_buffer_check(len, &projp)) != CRYPTO_SUCCESS) {
4940 		goto release_minor;
4941 	}
4942 	rctl_bytes = len;
4943 	buffer = kmem_alloc(len, KM_SLEEP);
4944 
4945 	session_id = STRUCT_FGET(find_update, fu_session);
4946 
4947 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4948 		goto release_minor;
4949 	}
4950 
4951 	if ((rv = kcf_get_hardware_provider_nomech(
4952 	    CRYPTO_OPS_OFFSET(object_ops),
4953 	    CRYPTO_OBJECT_OFFSET(object_find), CHECK_RESTRICT_FALSE,
4954 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4955 		goto out;
4956 	}
4957 
4958 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND,
4959 	    sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0,
4960 	    NULL, sp->sd_find_init_cookie, max_count, &count);
4961 
4962 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4963 	KCF_PROV_REFRELE(real_provider);
4964 
4965 out:
4966 	CRYPTO_SESSION_RELE(sp);
4967 	if (rv == CRYPTO_SUCCESS) {
4968 		if (count > max_count) {
4969 			/* bad bad provider */
4970 			rv = CRYPTO_FAILED;
4971 			goto release_minor;
4972 		}
4973 		if (count != 0) {
4974 			/* copyout handles */
4975 			if (copyout(buffer,
4976 			    STRUCT_FGETP(find_update, fu_handles),
4977 			    count * sizeof (crypto_object_id_t)) != 0) {
4978 				error = EFAULT;
4979 			}
4980 		}
4981 		STRUCT_FSET(find_update, fu_count, count);
4982 	}
4983 
4984 release_minor:
4985 	if (rctl_bytes != 0) {
4986 		mutex_enter(&crypto_rctl_lock);
4987 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4988 		mutex_exit(&crypto_rctl_lock);
4989 	}
4990 	crypto_release_minor(cm);
4991 
4992 	if (buffer != NULL)
4993 		kmem_free(buffer, len);
4994 
4995 	if (error != 0)
4996 		return (error);
4997 
4998 	STRUCT_FSET(find_update, fu_return_value, rv);
4999 	if (copyout(STRUCT_BUF(find_update), arg,
5000 	    STRUCT_SIZE(find_update)) != 0) {
5001 		return (EFAULT);
5002 	}
5003 
5004 	return (0);
5005 }
5006 
5007 /*
5008  * Free provider-allocated storage used for find object searches.
5009  */
5010 static int
5011 crypto_free_find_ctx(crypto_session_data_t *sp)
5012 {
5013 	kcf_provider_desc_t *real_provider;
5014 	kcf_req_params_t params;
5015 	int rv;
5016 
5017 	if ((rv = kcf_get_hardware_provider_nomech(
5018 	    CRYPTO_OPS_OFFSET(object_ops),
5019 	    CRYPTO_OBJECT_OFFSET(object_find_final), CHECK_RESTRICT_FALSE,
5020 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5021 		return (rv);
5022 	}
5023 
5024 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_FINAL,
5025 	    sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0,
5026 	    NULL, sp->sd_find_init_cookie, 0, NULL);
5027 
5028 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5029 	KCF_PROV_REFRELE(real_provider);
5030 	return (rv);
5031 }
5032 
5033 /* ARGSUSED */
5034 static int
5035 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval)
5036 {
5037 	STRUCT_DECL(crypto_object_find_final, object_find_final);
5038 	crypto_session_id_t session_id;
5039 	crypto_minor_t *cm;
5040 	crypto_session_data_t *sp;
5041 	int error = 0;
5042 	int rv;
5043 
5044 	STRUCT_INIT(object_find_final, mode);
5045 
5046 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5047 		cmn_err(CE_WARN, "object_find_final: failed holding minor");
5048 		return (ENXIO);
5049 	}
5050 
5051 	if (copyin(arg, STRUCT_BUF(object_find_final),
5052 	    STRUCT_SIZE(object_find_final)) != 0) {
5053 		crypto_release_minor(cm);
5054 		return (EFAULT);
5055 	}
5056 
5057 	session_id = STRUCT_FGET(object_find_final, ff_session);
5058 
5059 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5060 		goto release_minor;
5061 	}
5062 
5063 	if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) {
5064 		sp->sd_find_init_cookie = NULL;
5065 	}
5066 
5067 	CRYPTO_SESSION_RELE(sp);
5068 
5069 release_minor:
5070 	crypto_release_minor(cm);
5071 
5072 	if (error != 0)
5073 		return (error);
5074 
5075 	STRUCT_FSET(object_find_final, ff_return_value, rv);
5076 
5077 	if (copyout(STRUCT_BUF(object_find_final), arg,
5078 	    STRUCT_SIZE(object_find_final)) != 0) {
5079 		return (EFAULT);
5080 	}
5081 	return (0);
5082 }
5083 
5084 /* ARGSUSED */
5085 static int
5086 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5087 {
5088 	STRUCT_DECL(crypto_object_generate_key, generate_key);
5089 	kproject_t *mech_projp, *key_projp;
5090 	kcf_provider_desc_t *real_provider = NULL;
5091 	kcf_req_params_t params;
5092 	crypto_mechanism_t mech;
5093 	crypto_object_attribute_t *k_attrs = NULL;
5094 	crypto_session_id_t session_id;
5095 	crypto_minor_t *cm;
5096 	crypto_session_data_t *sp = NULL;
5097 	crypto_object_id_t key_handle;
5098 	caddr_t attributes;
5099 	size_t k_attrs_size;
5100 	size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5101 	size_t carry;
5102 	uint_t count;
5103 	int error = 0;
5104 	int rv;
5105 	boolean_t allocated_by_crypto_module = B_FALSE;
5106 
5107 	STRUCT_INIT(generate_key, mode);
5108 
5109 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5110 		cmn_err(CE_WARN, "object_generate_key: failed holding minor");
5111 		return (ENXIO);
5112 	}
5113 
5114 	if (copyin(arg, STRUCT_BUF(generate_key),
5115 	    STRUCT_SIZE(generate_key)) != 0) {
5116 		crypto_release_minor(cm);
5117 		return (EFAULT);
5118 	}
5119 
5120 	session_id = STRUCT_FGET(generate_key, gk_session);
5121 
5122 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5123 		goto release_minor;
5124 	}
5125 
5126 	bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type,
5127 	    sizeof (crypto_mech_type_t));
5128 
5129 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5130 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5131 	    CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5132 		goto release_minor;
5133 	}
5134 
5135 	carry = 0;
5136 	rv = crypto_provider_copyin_mech_param(real_provider,
5137 	    STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error);
5138 
5139 	if (rv == CRYPTO_NOT_SUPPORTED) {
5140 		allocated_by_crypto_module = B_TRUE;
5141 		if (!copyin_mech(mode, STRUCT_FADDR(generate_key, gk_mechanism),
5142 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5143 		    &mech_projp)) {
5144 			goto release_minor;
5145 		}
5146 	} else {
5147 		if (rv != CRYPTO_SUCCESS)
5148 			goto release_minor;
5149 	}
5150 
5151 	count = STRUCT_FGET(generate_key, gk_count);
5152 	attributes = STRUCT_FGETP(generate_key, gk_attributes);
5153 	if (!copyin_attributes(mode, count, attributes, &k_attrs,
5154 	    &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes, carry, B_TRUE,
5155 	    &key_projp)) {
5156 		goto release_minor;
5157 	}
5158 
5159 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE,
5160 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5161 	    &key_handle, NULL, 0, NULL, NULL, NULL, 0);
5162 
5163 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5164 
5165 	if (rv == CRYPTO_SUCCESS)
5166 		STRUCT_FSET(generate_key, gk_handle, key_handle);
5167 
5168 release_minor:
5169 	mutex_enter(&crypto_rctl_lock);
5170 	if (mech_rctl_bytes != 0)
5171 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5172 	if (key_rctl_bytes != 0)
5173 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
5174 	mutex_exit(&crypto_rctl_lock);
5175 
5176 	if (k_attrs != NULL)
5177 		kmem_free(k_attrs, k_attrs_size);
5178 
5179 	if (error != 0)
5180 		goto out;
5181 
5182 	STRUCT_FSET(generate_key, gk_return_value, rv);
5183 	if (copyout(STRUCT_BUF(generate_key), arg,
5184 	    STRUCT_SIZE(generate_key)) != 0) {
5185 		if (rv == CRYPTO_SUCCESS) {
5186 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5187 			    KCF_OP_OBJECT_DESTROY,
5188 			    sp->sd_provider_session->ps_session, key_handle,
5189 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5190 
5191 			(void) kcf_submit_request(real_provider, NULL,
5192 			    NULL, &params, B_FALSE);
5193 
5194 			error = EFAULT;
5195 		}
5196 	}
5197 out:
5198 	if (sp != NULL)
5199 		CRYPTO_SESSION_RELE(sp);
5200 	crypto_release_minor(cm);
5201 
5202 	if (real_provider != NULL) {
5203 		crypto_free_mech(real_provider,
5204 		    allocated_by_crypto_module, &mech);
5205 		KCF_PROV_REFRELE(real_provider);
5206 	}
5207 	return (error);
5208 }
5209 
5210 /* ARGSUSED */
5211 static int
5212 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5213 {
5214 	STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair);
5215 	kproject_t *pub_projp, *pri_projp, *mech_projp;
5216 	kcf_provider_desc_t *real_provider = NULL;
5217 	kcf_req_params_t params;
5218 	crypto_mechanism_t mech;
5219 	crypto_object_attribute_t *k_pub_attrs = NULL;
5220 	crypto_object_attribute_t *k_pri_attrs = NULL;
5221 	crypto_session_id_t session_id;
5222 	crypto_minor_t *cm;
5223 	crypto_session_data_t *sp = NULL;
5224 	crypto_object_id_t pub_handle;
5225 	crypto_object_id_t pri_handle;
5226 	caddr_t pri_attributes;
5227 	caddr_t pub_attributes;
5228 	size_t k_pub_attrs_size, k_pri_attrs_size;
5229 	size_t mech_rctl_bytes = 0;
5230 	size_t pub_rctl_bytes = 0;
5231 	size_t pri_rctl_bytes = 0;
5232 	size_t carry;
5233 	uint_t pub_count;
5234 	uint_t pri_count;
5235 	int error = 0;
5236 	int rv;
5237 	boolean_t allocated_by_crypto_module = B_FALSE;
5238 
5239 	STRUCT_INIT(generate_key_pair, mode);
5240 
5241 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5242 		cmn_err(CE_WARN,
5243 		    "object_generate_key_pair: failed holding minor");
5244 		return (ENXIO);
5245 	}
5246 
5247 	if (copyin(arg, STRUCT_BUF(generate_key_pair),
5248 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5249 		crypto_release_minor(cm);
5250 		return (EFAULT);
5251 	}
5252 
5253 	session_id = STRUCT_FGET(generate_key_pair, kp_session);
5254 
5255 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5256 		goto release_minor;
5257 	}
5258 
5259 	bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type,
5260 	    sizeof (crypto_mech_type_t));
5261 
5262 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5263 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5264 	    CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5265 		goto release_minor;
5266 	}
5267 
5268 	carry = 0;
5269 	rv = crypto_provider_copyin_mech_param(real_provider,
5270 	    STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error);
5271 
5272 	if (rv == CRYPTO_NOT_SUPPORTED) {
5273 		allocated_by_crypto_module = B_TRUE;
5274 		if (!copyin_mech(mode, STRUCT_FADDR(generate_key_pair,
5275 		    kp_mechanism), &mech, &mech_rctl_bytes, &carry, &rv,
5276 		    &error, &mech_projp)) {
5277 			goto release_minor;
5278 		}
5279 	} else {
5280 		if (rv != CRYPTO_SUCCESS)
5281 			goto release_minor;
5282 	}
5283 
5284 	pub_count = STRUCT_FGET(generate_key_pair, kp_public_count);
5285 	pri_count = STRUCT_FGET(generate_key_pair, kp_private_count);
5286 
5287 	pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes);
5288 	if (!copyin_attributes(mode, pub_count, pub_attributes, &k_pub_attrs,
5289 	    &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes, carry,
5290 	    B_TRUE, &pub_projp)) {
5291 		goto release_minor;
5292 	}
5293 
5294 	pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes);
5295 	if (!copyin_attributes(mode, pri_count, pri_attributes, &k_pri_attrs,
5296 	    &k_pri_attrs_size, NULL, &rv, &error, &pri_rctl_bytes, 0,
5297 	    B_TRUE, &pri_projp)) {
5298 		goto release_minor;
5299 	}
5300 
5301 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
5302 	    sp->sd_provider_session->ps_session, &mech, k_pub_attrs,
5303 	    pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle,
5304 	    NULL, NULL, 0);
5305 
5306 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5307 
5308 	if (rv == CRYPTO_SUCCESS) {
5309 		STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle);
5310 		STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle);
5311 	}
5312 
5313 release_minor:
5314 	mutex_enter(&crypto_rctl_lock);
5315 	if (mech_rctl_bytes != 0)
5316 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5317 	if (pub_rctl_bytes != 0)
5318 		CRYPTO_DECREMENT_RCTL(pub_rctl_bytes, pub_projp);
5319 	if (pri_rctl_bytes != 0)
5320 		CRYPTO_DECREMENT_RCTL(pri_rctl_bytes, pri_projp);
5321 	mutex_exit(&crypto_rctl_lock);
5322 
5323 	if (k_pub_attrs != NULL)
5324 		kmem_free(k_pub_attrs, k_pub_attrs_size);
5325 
5326 	if (k_pri_attrs != NULL)
5327 		kmem_free(k_pri_attrs, k_pri_attrs_size);
5328 
5329 	if (error != 0)
5330 		goto out;
5331 
5332 	STRUCT_FSET(generate_key_pair, kp_return_value, rv);
5333 	if (copyout(STRUCT_BUF(generate_key_pair), arg,
5334 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5335 		if (rv == CRYPTO_SUCCESS) {
5336 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5337 			    KCF_OP_OBJECT_DESTROY,
5338 			    sp->sd_provider_session->ps_session, pub_handle,
5339 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5340 
5341 			(void) kcf_submit_request(real_provider, NULL,
5342 			    NULL, &params, B_FALSE);
5343 
5344 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5345 			    KCF_OP_OBJECT_DESTROY,
5346 			    sp->sd_provider_session->ps_session, pri_handle,
5347 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5348 
5349 			(void) kcf_submit_request(real_provider, NULL,
5350 			    NULL, &params, B_FALSE);
5351 
5352 			error = EFAULT;
5353 		}
5354 	}
5355 out:
5356 	if (sp != NULL)
5357 		CRYPTO_SESSION_RELE(sp);
5358 	crypto_release_minor(cm);
5359 
5360 	if (real_provider != NULL) {
5361 		crypto_free_mech(real_provider,
5362 		    allocated_by_crypto_module, &mech);
5363 		KCF_PROV_REFRELE(real_provider);
5364 	}
5365 	return (error);
5366 }
5367 
5368 /* ARGSUSED */
5369 static int
5370 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
5371 {
5372 	STRUCT_DECL(crypto_object_wrap_key, wrap_key);
5373 	kproject_t *mech_projp, *key_projp, *wrapped_key_projp;
5374 	kcf_provider_desc_t *real_provider = NULL;
5375 	kcf_req_params_t params;
5376 	crypto_mechanism_t mech;
5377 	crypto_key_t key;
5378 	crypto_session_id_t session_id;
5379 	crypto_minor_t *cm;
5380 	crypto_session_data_t *sp;
5381 	crypto_object_id_t handle;
5382 	size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5383 	size_t wrapped_key_rctl_bytes = 0;
5384 	size_t carry;
5385 	size_t wrapped_key_len, new_wrapped_key_len;
5386 	uchar_t *wrapped_key = NULL;
5387 	char *wrapped_key_buffer;
5388 	int error = 0;
5389 	int rv;
5390 	boolean_t allocated_by_crypto_module = B_FALSE;
5391 
5392 	STRUCT_INIT(wrap_key, mode);
5393 
5394 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5395 		cmn_err(CE_WARN, "object_wrap_key: failed holding minor");
5396 		return (ENXIO);
5397 	}
5398 
5399 	if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) {
5400 		crypto_release_minor(cm);
5401 		return (EFAULT);
5402 	}
5403 
5404 	bzero(&key, sizeof (crypto_key_t));
5405 
5406 	session_id = STRUCT_FGET(wrap_key, wk_session);
5407 
5408 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5409 		goto release_minor;
5410 	}
5411 
5412 	bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type,
5413 	    sizeof (crypto_mech_type_t));
5414 
5415 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5416 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5417 	    CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) {
5418 		goto out;
5419 	}
5420 
5421 	carry = 0;
5422 	rv = crypto_provider_copyin_mech_param(real_provider,
5423 	    STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error);
5424 
5425 	if (rv == CRYPTO_NOT_SUPPORTED) {
5426 		allocated_by_crypto_module = B_TRUE;
5427 		if (!copyin_mech(mode, STRUCT_FADDR(wrap_key, wk_mechanism),
5428 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5429 		    &mech_projp)) {
5430 			goto out;
5431 		}
5432 	} else {
5433 		if (rv != CRYPTO_SUCCESS)
5434 			goto out;
5435 	}
5436 
5437 	if (!copyin_key(mode, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key,
5438 	    &key_rctl_bytes, &rv, &error, carry, &key_projp)) {
5439 		goto out;
5440 	}
5441 
5442 	wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len);
5443 
5444 	/*
5445 	 * Don't allocate output buffer unless both buffer pointer and
5446 	 * buffer length are not NULL or 0 (length).
5447 	 */
5448 	wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key);
5449 	if (wrapped_key_buffer == NULL || wrapped_key_len == 0) {
5450 		wrapped_key_len = 0;
5451 	}
5452 
5453 	if (wrapped_key_len > crypto_max_buffer_len) {
5454 		cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld "
5455 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
5456 		rv = CRYPTO_ARGUMENTS_BAD;
5457 		goto out;
5458 	}
5459 
5460 	if ((rv = crypto_buffer_check(wrapped_key_len,
5461 	    &wrapped_key_projp)) != CRYPTO_SUCCESS) {
5462 		goto out;
5463 	}
5464 
5465 	/* new_wrapped_key_len can be modified by the provider */
5466 	wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len;
5467 	wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
5468 
5469 	handle = STRUCT_FGET(wrap_key, wk_object_handle);
5470 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP,
5471 	    sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle,
5472 	    NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len);
5473 
5474 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5475 
5476 	if (rv == CRYPTO_SUCCESS) {
5477 		if (wrapped_key_len != 0 && copyout(wrapped_key,
5478 		    wrapped_key_buffer, new_wrapped_key_len) != 0) {
5479 			error = EFAULT;
5480 		}
5481 		STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len);
5482 	}
5483 
5484 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
5485 		/*
5486 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
5487 		 * of section 11.2 of the pkcs11 spec. We catch it here and
5488 		 * provide the correct pkcs11 return value.
5489 		 */
5490 		if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL)
5491 			rv = CRYPTO_SUCCESS;
5492 		STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len);
5493 	}
5494 out:
5495 	CRYPTO_SESSION_RELE(sp);
5496 
5497 release_minor:
5498 	mutex_enter(&crypto_rctl_lock);
5499 	if (mech_rctl_bytes != 0)
5500 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5501 	if (key_rctl_bytes != 0)
5502 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
5503 	if (wrapped_key_rctl_bytes != 0)
5504 		CRYPTO_DECREMENT_RCTL(wrapped_key_rctl_bytes,
5505 		    wrapped_key_projp);
5506 	mutex_exit(&crypto_rctl_lock);
5507 	crypto_release_minor(cm);
5508 
5509 	if (real_provider != NULL) {
5510 		crypto_free_mech(real_provider,
5511 		    allocated_by_crypto_module, &mech);
5512 		KCF_PROV_REFRELE(real_provider);
5513 	}
5514 
5515 	if (wrapped_key != NULL)
5516 		kmem_free(wrapped_key, wrapped_key_len);
5517 
5518 	free_crypto_key(&key);
5519 
5520 	if (error != 0)
5521 		return (error);
5522 
5523 	STRUCT_FSET(wrap_key, wk_return_value, rv);
5524 	if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) {
5525 		return (EFAULT);
5526 	}
5527 	return (0);
5528 }
5529 
5530 /* ARGSUSED */
5531 static int
5532 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
5533 {
5534 	STRUCT_DECL(crypto_object_unwrap_key, unwrap_key);
5535 	kproject_t *mech_projp, *unwrapping_key_projp, *wrapped_key_projp,
5536 	    *k_attrs_projp;
5537 	kcf_provider_desc_t *real_provider = NULL;
5538 	kcf_req_params_t params;
5539 	crypto_mechanism_t mech;
5540 	crypto_key_t unwrapping_key;
5541 	crypto_session_id_t session_id;
5542 	crypto_minor_t *cm;
5543 	crypto_session_data_t *sp = NULL;
5544 	crypto_object_id_t handle;
5545 	crypto_object_attribute_t *k_attrs = NULL;
5546 	size_t k_attrs_size;
5547 	size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0;
5548 	size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0;
5549 	size_t carry;
5550 	size_t wrapped_key_len;
5551 	uchar_t *wrapped_key = NULL;
5552 	int error = 0;
5553 	int rv;
5554 	uint_t count;
5555 	caddr_t uk_attributes;
5556 	boolean_t allocated_by_crypto_module = B_FALSE;
5557 
5558 	STRUCT_INIT(unwrap_key, mode);
5559 
5560 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5561 		cmn_err(CE_WARN, "object_unwrap_key: failed holding minor");
5562 		return (ENXIO);
5563 	}
5564 
5565 	if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) {
5566 		crypto_release_minor(cm);
5567 		return (EFAULT);
5568 	}
5569 
5570 	bzero(&unwrapping_key, sizeof (unwrapping_key));
5571 
5572 	session_id = STRUCT_FGET(unwrap_key, uk_session);
5573 
5574 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5575 		goto release_minor;
5576 	}
5577 
5578 	bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type,
5579 	    sizeof (crypto_mech_type_t));
5580 
5581 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5582 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5583 	    CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) {
5584 		goto release_minor;
5585 	}
5586 
5587 	carry = 0;
5588 	rv = crypto_provider_copyin_mech_param(real_provider,
5589 	    STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error);
5590 
5591 	if (rv == CRYPTO_NOT_SUPPORTED) {
5592 		allocated_by_crypto_module = B_TRUE;
5593 		if (!copyin_mech(mode, STRUCT_FADDR(unwrap_key, uk_mechanism),
5594 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5595 		    &mech_projp)) {
5596 			goto release_minor;
5597 		}
5598 	} else {
5599 		if (rv != CRYPTO_SUCCESS)
5600 			goto release_minor;
5601 	}
5602 
5603 	if (!copyin_key(mode, STRUCT_FADDR(unwrap_key, uk_unwrapping_key),
5604 	    &unwrapping_key, &unwrapping_key_rctl_bytes, &rv, &error, carry,
5605 	    &unwrapping_key_projp)) {
5606 		goto release_minor;
5607 	}
5608 
5609 	count = STRUCT_FGET(unwrap_key, uk_count);
5610 	uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes);
5611 	if (!copyin_attributes(mode, count, uk_attributes, &k_attrs,
5612 	    &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes, 0, B_TRUE,
5613 	    &k_attrs_projp)) {
5614 		goto release_minor;
5615 	}
5616 
5617 	wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len);
5618 	if (wrapped_key_len > crypto_max_buffer_len) {
5619 		cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld "
5620 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
5621 		rv = CRYPTO_ARGUMENTS_BAD;
5622 		goto release_minor;
5623 	}
5624 
5625 	if ((rv = crypto_buffer_check(wrapped_key_len, &wrapped_key_projp))
5626 	    != CRYPTO_SUCCESS) {
5627 		goto release_minor;
5628 	}
5629 	wrapped_key_rctl_bytes = wrapped_key_len;
5630 	wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
5631 
5632 	if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key,
5633 	    uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) {
5634 		error = EFAULT;
5635 		goto release_minor;
5636 	}
5637 
5638 	/* wrapped_key_len is not modified by the unwrap operation */
5639 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP,
5640 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle,
5641 	    NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len);
5642 
5643 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5644 
5645 	if (rv == CRYPTO_SUCCESS)
5646 		STRUCT_FSET(unwrap_key, uk_object_handle, handle);
5647 
5648 release_minor:
5649 	mutex_enter(&crypto_rctl_lock);
5650 	if (mech_rctl_bytes != 0)
5651 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5652 	if (unwrapping_key_rctl_bytes != 0)
5653 		CRYPTO_DECREMENT_RCTL(unwrapping_key_rctl_bytes,
5654 		    unwrapping_key_projp);
5655 	if (wrapped_key_rctl_bytes != 0)
5656 		CRYPTO_DECREMENT_RCTL(wrapped_key_rctl_bytes,
5657 		    wrapped_key_projp);
5658 	if (k_attrs_rctl_bytes != 0)
5659 		CRYPTO_DECREMENT_RCTL(k_attrs_rctl_bytes, k_attrs_projp);
5660 	mutex_exit(&crypto_rctl_lock);
5661 
5662 	if (k_attrs != NULL)
5663 		kmem_free(k_attrs, k_attrs_size);
5664 
5665 	if (wrapped_key != NULL)
5666 		kmem_free(wrapped_key, wrapped_key_len);
5667 
5668 	free_crypto_key(&unwrapping_key);
5669 
5670 	if (error != 0)
5671 		goto out;
5672 
5673 	STRUCT_FSET(unwrap_key, uk_return_value, rv);
5674 	if (copyout(STRUCT_BUF(unwrap_key), arg,
5675 	    STRUCT_SIZE(unwrap_key)) != 0) {
5676 		if (rv == CRYPTO_SUCCESS) {
5677 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5678 			    KCF_OP_OBJECT_DESTROY,
5679 			    sp->sd_provider_session->ps_session, handle,
5680 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5681 
5682 			(void) kcf_submit_request(real_provider, NULL,
5683 			    NULL, &params, B_FALSE);
5684 
5685 			error = EFAULT;
5686 		}
5687 	}
5688 out:
5689 	if (sp != NULL)
5690 		CRYPTO_SESSION_RELE(sp);
5691 	crypto_release_minor(cm);
5692 
5693 	if (real_provider != NULL) {
5694 		crypto_free_mech(real_provider,
5695 		    allocated_by_crypto_module, &mech);
5696 		KCF_PROV_REFRELE(real_provider);
5697 	}
5698 
5699 	return (error);
5700 }
5701 
5702 /* ARGSUSED */
5703 static int
5704 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
5705 {
5706 	STRUCT_DECL(crypto_derive_key, derive_key);
5707 	kproject_t *key_projp, *mech_projp, *attributes_projp;
5708 	kcf_provider_desc_t *real_provider = NULL;
5709 	kcf_req_params_t params;
5710 	crypto_object_attribute_t *k_attrs = NULL;
5711 	crypto_mechanism_t mech;
5712 	crypto_key_t base_key;
5713 	crypto_session_id_t session_id;
5714 	crypto_minor_t *cm;
5715 	crypto_session_data_t *sp = NULL;
5716 	crypto_object_id_t handle;
5717 	size_t k_attrs_size;
5718 	size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
5719 	size_t attributes_rctl_bytes = 0;
5720 	size_t carry;
5721 	caddr_t attributes;
5722 	uint_t count;
5723 	int error = 0;
5724 	int rv;
5725 	boolean_t allocated_by_crypto_module = B_FALSE;
5726 	boolean_t please_destroy_object = B_FALSE;
5727 
5728 	STRUCT_INIT(derive_key, mode);
5729 
5730 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5731 		cmn_err(CE_WARN, "object_derive_key: failed holding minor");
5732 		return (ENXIO);
5733 	}
5734 
5735 	if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
5736 		crypto_release_minor(cm);
5737 		return (EFAULT);
5738 	}
5739 
5740 	bzero(&base_key, sizeof (base_key));
5741 
5742 	session_id = STRUCT_FGET(derive_key, dk_session);
5743 
5744 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5745 		goto release_minor;
5746 	}
5747 
5748 	bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type,
5749 	    sizeof (crypto_mech_type_t));
5750 
5751 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5752 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5753 	    CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
5754 		goto release_minor;
5755 	}
5756 
5757 	carry = 0;
5758 	rv = crypto_provider_copyin_mech_param(real_provider,
5759 	    STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error);
5760 
5761 	if (rv == CRYPTO_NOT_SUPPORTED) {
5762 		allocated_by_crypto_module = B_TRUE;
5763 		if (!copyin_mech(mode, STRUCT_FADDR(derive_key, dk_mechanism),
5764 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5765 		    &mech_projp)) {
5766 			goto release_minor;
5767 		}
5768 	} else {
5769 		if (rv != CRYPTO_SUCCESS)
5770 			goto release_minor;
5771 	}
5772 
5773 	if (!copyin_key(mode, STRUCT_FADDR(derive_key, dk_base_key),
5774 	    &base_key, &key_rctl_bytes, &rv, &error, carry, &key_projp)) {
5775 		goto release_minor;
5776 	}
5777 
5778 	count = STRUCT_FGET(derive_key, dk_count);
5779 
5780 	attributes = STRUCT_FGETP(derive_key, dk_attributes);
5781 	if (!copyin_attributes(mode, count, attributes, &k_attrs,
5782 	    &k_attrs_size, NULL, &rv, &error, &attributes_rctl_bytes, 0, B_TRUE,
5783 	    &attributes_projp)) {
5784 		goto release_minor;
5785 	}
5786 
5787 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE,
5788 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5789 	    &handle, NULL, 0, NULL, &base_key, NULL, NULL);
5790 
5791 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5792 
5793 	if (rv == CRYPTO_SUCCESS) {
5794 		STRUCT_FSET(derive_key, dk_object_handle, handle);
5795 
5796 		rv = crypto_provider_copyout_mech_param(real_provider,
5797 		    &mech, STRUCT_FADDR(derive_key, dk_mechanism),
5798 		    mode, &error);
5799 
5800 		if (rv == CRYPTO_NOT_SUPPORTED) {
5801 			rv = CRYPTO_SUCCESS;
5802 			goto release_minor;
5803 		}
5804 
5805 		if (rv != CRYPTO_SUCCESS)
5806 			please_destroy_object = B_TRUE;
5807 	}
5808 
5809 release_minor:
5810 	mutex_enter(&crypto_rctl_lock);
5811 	if (mech_rctl_bytes != 0)
5812 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5813 	if (key_rctl_bytes != 0)
5814 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
5815 	if (attributes_rctl_bytes != 0)
5816 		CRYPTO_DECREMENT_RCTL(attributes_rctl_bytes, attributes_projp);
5817 	mutex_exit(&crypto_rctl_lock);
5818 
5819 	if (k_attrs != NULL)
5820 		kmem_free(k_attrs, k_attrs_size);
5821 
5822 	free_crypto_key(&base_key);
5823 
5824 	if (error != 0)
5825 		goto out;
5826 
5827 	STRUCT_FSET(derive_key, dk_return_value, rv);
5828 	if (copyout(STRUCT_BUF(derive_key), arg,
5829 	    STRUCT_SIZE(derive_key)) != 0) {
5830 		if (rv == CRYPTO_SUCCESS) {
5831 			please_destroy_object = B_TRUE;
5832 			error = EFAULT;
5833 		}
5834 	}
5835 out:
5836 	if (please_destroy_object) {
5837 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
5838 		    sp->sd_provider_session->ps_session, handle,
5839 		    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5840 
5841 		(void) kcf_submit_request(real_provider, NULL,
5842 		    NULL, &params, B_FALSE);
5843 	}
5844 
5845 	if (sp != NULL)
5846 		CRYPTO_SESSION_RELE(sp);
5847 	crypto_release_minor(cm);
5848 
5849 	if (real_provider != NULL) {
5850 		crypto_free_mech(real_provider,
5851 		    allocated_by_crypto_module, &mech);
5852 		KCF_PROV_REFRELE(real_provider);
5853 	}
5854 	return (error);
5855 }
5856 
5857 /* ARGSUSED */
5858 static int
5859 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
5860     int *rval)
5861 {
5862 #define	ARG	((caddr_t)arg)
5863 
5864 	switch (cmd) {
5865 	case CRYPTO_GET_FUNCTION_LIST:
5866 		return (get_function_list(dev, ARG, mode, rval));
5867 
5868 	case CRYPTO_GET_MECHANISM_NUMBER:
5869 		return (get_mechanism_number(dev, ARG, mode, rval));
5870 
5871 	case CRYPTO_GET_PROVIDER_LIST:
5872 		return (get_provider_list(dev, ARG, mode, rval));
5873 
5874 	case CRYPTO_GET_PROVIDER_INFO:
5875 		return (get_provider_info(dev, ARG, mode, rval));
5876 
5877 	case CRYPTO_GET_PROVIDER_MECHANISMS:
5878 		return (get_provider_mechanisms(dev, ARG, mode, rval));
5879 
5880 	case CRYPTO_GET_PROVIDER_MECHANISM_INFO:
5881 		return (get_provider_mechanism_info(dev, ARG, mode, rval));
5882 
5883 	case CRYPTO_OPEN_SESSION:
5884 		return (open_session(dev, ARG, mode, rval));
5885 
5886 	case CRYPTO_CLOSE_SESSION:
5887 		return (close_session(dev, ARG, mode, rval));
5888 
5889 	case CRYPTO_ENCRYPT_INIT:
5890 		return (encrypt_init(dev, ARG, mode, rval));
5891 
5892 	case CRYPTO_DECRYPT_INIT:
5893 		return (decrypt_init(dev, ARG, mode, rval));
5894 
5895 	case CRYPTO_ENCRYPT:
5896 		return (encrypt(dev, ARG, mode, rval));
5897 
5898 	case CRYPTO_DECRYPT:
5899 		return (decrypt(dev, ARG, mode, rval));
5900 
5901 	case CRYPTO_ENCRYPT_UPDATE:
5902 		return (encrypt_update(dev, ARG, mode, rval));
5903 
5904 	case CRYPTO_DECRYPT_UPDATE:
5905 		return (decrypt_update(dev, ARG, mode, rval));
5906 
5907 	case CRYPTO_ENCRYPT_FINAL:
5908 		return (encrypt_final(dev, ARG, mode, rval));
5909 
5910 	case CRYPTO_DECRYPT_FINAL:
5911 		return (decrypt_final(dev, ARG, mode, rval));
5912 
5913 	case CRYPTO_DIGEST_INIT:
5914 		return (digest_init(dev, ARG, mode, rval));
5915 
5916 	case CRYPTO_DIGEST:
5917 		return (digest(dev, ARG, mode, rval));
5918 
5919 	case CRYPTO_DIGEST_UPDATE:
5920 		return (digest_update(dev, ARG, mode, rval));
5921 
5922 	case CRYPTO_DIGEST_KEY:
5923 		return (digest_key(dev, ARG, mode, rval));
5924 
5925 	case CRYPTO_DIGEST_FINAL:
5926 		return (digest_final(dev, ARG, mode, rval));
5927 
5928 	case CRYPTO_SIGN_INIT:
5929 		return (sign_init(dev, ARG, mode, rval));
5930 
5931 	case CRYPTO_SIGN:
5932 		return (sign(dev, ARG, mode, rval));
5933 
5934 	case CRYPTO_SIGN_UPDATE:
5935 		return (sign_update(dev, ARG, mode, rval));
5936 
5937 	case CRYPTO_SIGN_FINAL:
5938 		return (sign_final(dev, ARG, mode, rval));
5939 
5940 	case CRYPTO_SIGN_RECOVER_INIT:
5941 		return (sign_recover_init(dev, ARG, mode, rval));
5942 
5943 	case CRYPTO_SIGN_RECOVER:
5944 		return (sign_recover(dev, ARG, mode, rval));
5945 
5946 	case CRYPTO_VERIFY_INIT:
5947 		return (verify_init(dev, ARG, mode, rval));
5948 
5949 	case CRYPTO_VERIFY:
5950 		return (verify(dev, ARG, mode, rval));
5951 
5952 	case CRYPTO_VERIFY_UPDATE:
5953 		return (verify_update(dev, ARG, mode, rval));
5954 
5955 	case CRYPTO_VERIFY_FINAL:
5956 		return (verify_final(dev, ARG, mode, rval));
5957 
5958 	case CRYPTO_VERIFY_RECOVER_INIT:
5959 		return (verify_recover_init(dev, ARG, mode, rval));
5960 
5961 	case CRYPTO_VERIFY_RECOVER:
5962 		return (verify_recover(dev, ARG, mode, rval));
5963 
5964 	case CRYPTO_SET_PIN:
5965 		return (set_pin(dev, ARG, mode, rval));
5966 
5967 	case CRYPTO_LOGIN:
5968 		return (login(dev, ARG, mode, rval));
5969 
5970 	case CRYPTO_LOGOUT:
5971 		return (logout(dev, ARG, mode, rval));
5972 
5973 	case CRYPTO_SEED_RANDOM:
5974 		return (seed_random(dev, ARG, mode, rval));
5975 
5976 	case CRYPTO_GENERATE_RANDOM:
5977 		return (generate_random(dev, ARG, mode, rval));
5978 
5979 	case CRYPTO_OBJECT_CREATE:
5980 		return (object_create(dev, ARG, mode, rval));
5981 
5982 	case CRYPTO_OBJECT_COPY:
5983 		return (object_copy(dev, ARG, mode, rval));
5984 
5985 	case CRYPTO_OBJECT_DESTROY:
5986 		return (object_destroy(dev, ARG, mode, rval));
5987 
5988 	case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE:
5989 		return (object_get_attribute_value(dev, ARG, mode, rval));
5990 
5991 	case CRYPTO_OBJECT_GET_SIZE:
5992 		return (object_get_size(dev, ARG, mode, rval));
5993 
5994 	case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE:
5995 		return (object_set_attribute_value(dev, ARG, mode, rval));
5996 
5997 	case CRYPTO_OBJECT_FIND_INIT:
5998 		return (object_find_init(dev, ARG, mode, rval));
5999 
6000 	case CRYPTO_OBJECT_FIND_UPDATE:
6001 		return (object_find_update(dev, ARG, mode, rval));
6002 
6003 	case CRYPTO_OBJECT_FIND_FINAL:
6004 		return (object_find_final(dev, ARG, mode, rval));
6005 
6006 	case CRYPTO_GENERATE_KEY:
6007 		return (object_generate_key(dev, ARG, mode, rval));
6008 
6009 	case CRYPTO_GENERATE_KEY_PAIR:
6010 		return (object_generate_key_pair(dev, ARG, mode, rval));
6011 
6012 	case CRYPTO_WRAP_KEY:
6013 		return (object_wrap_key(dev, ARG, mode, rval));
6014 
6015 	case CRYPTO_UNWRAP_KEY:
6016 		return (object_unwrap_key(dev, ARG, mode, rval));
6017 
6018 	case CRYPTO_DERIVE_KEY:
6019 		return (object_derive_key(dev, ARG, mode, rval));
6020 	}
6021 	return (EINVAL);
6022 }
6023 
6024 /*
6025  * Check for the project.max-crypto-memory resource control.
6026  */
6027 static int
6028 crypto_buffer_check(size_t need, kproject_t **projp)
6029 {
6030 	ASSERT(projp != NULL);
6031 
6032 	if (need == 0)
6033 		return (CRYPTO_SUCCESS);
6034 
6035 	mutex_enter(&curproc->p_lock);
6036 	mutex_enter(&crypto_rctl_lock);
6037 	if (rctl_test(rc_project_crypto_mem,
6038 	    curproc->p_task->tk_proj->kpj_rctls, curproc, need, 0) & RCT_DENY) {
6039 		mutex_exit(&crypto_rctl_lock);
6040 		mutex_exit(&curproc->p_lock);
6041 		return (CRYPTO_HOST_MEMORY);
6042 	}
6043 
6044 	curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem += need;
6045 	mutex_exit(&crypto_rctl_lock);
6046 
6047 	(void) project_hold(curproc->p_task->tk_proj);
6048 	*projp = curproc->p_task->tk_proj;
6049 	mutex_exit(&curproc->p_lock);
6050 	return (CRYPTO_SUCCESS);
6051 }
6052