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