xref: /titanic_52/usr/src/uts/common/crypto/io/crypto.c (revision 6185db853e024a486ff8837e6784dd290d866112)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * The ioctl interface for cryptographic commands.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/modctl.h>
34 #include <sys/conf.h>
35 #include <sys/stat.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/kmem.h>
39 #include <sys/errno.h>
40 #include <sys/ksynch.h>
41 #include <sys/file.h>
42 #include <sys/open.h>
43 #include <sys/cred.h>
44 #include <sys/proc.h>
45 #include <sys/task.h>
46 #include <sys/mkdev.h>
47 #include <sys/model.h>
48 #include <sys/sysmacros.h>
49 #include <sys/crypto/common.h>
50 #include <sys/crypto/api.h>
51 #include <sys/crypto/impl.h>
52 #include <sys/crypto/sched_impl.h>
53 #include <sys/crypto/ioctl.h>
54 
55 /*
56  * Locking notes:
57  *
58  * crypto_lock protects the global array of minor structures.  It
59  * also protects the cm_refcnt member of each of these structures.
60  * The crypto_cv is used to signal decrements in the cm_refcnt,
61  * and is used with the global crypto_lock.
62  *
63  * Other fields in the minor structure are protected by the
64  * cm_lock member of the minor structure.
65  */
66 
67 /*
68  * DDI entry points.
69  */
70 static int crypto_attach(dev_info_t *, ddi_attach_cmd_t);
71 static int crypto_detach(dev_info_t *, ddi_detach_cmd_t);
72 static int crypto_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
73 static int crypto_open(dev_t *, int, int, cred_t *);
74 static int crypto_close(dev_t, int, int, cred_t *);
75 static int crypto_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
76 
77 static int cipher_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
78     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
79     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
80 
81 static int common_digest(dev_t, caddr_t, int, int (*)(crypto_context_t,
82     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
83 
84 static int cipher(dev_t, caddr_t, int, int (*)(crypto_context_t,
85     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
86 
87 static int cipher_update(dev_t, caddr_t, int, int (*)(crypto_context_t,
88     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
89 
90 static int common_final(dev_t, caddr_t, int, int (*)(crypto_context_t,
91     crypto_data_t *, crypto_call_req_t *));
92 
93 static int sign_verify_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
94     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
95     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
96 
97 static int sign_verify_update(dev_t dev, caddr_t arg, int mode,
98     int (*)(crypto_context_t, crypto_data_t *, crypto_call_req_t *));
99 
100 static void crypto_initialize_rctl(void);
101 static void crypto_release_provider_session(crypto_minor_t *,
102     crypto_provider_session_t *);
103 static int crypto_buffer_check(size_t, kproject_t **);
104 static int crypto_free_find_ctx(crypto_session_data_t *);
105 static int crypto_get_provider_list(crypto_minor_t *, uint_t *,
106     crypto_provider_entry_t **, boolean_t);
107 
108 /* number of minor numbers to allocate at a time */
109 #define	CRYPTO_MINOR_CHUNK	16
110 
111 /*
112  * There are two limits associated with kernel memory. The first,
113  * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be
114  * allocated for a single copyin/copyout buffer. The second limit is
115  * the total number of bytes that can be allocated by a process
116  * for copyin/copyout buffers. The latter is enforced by the
117  * project.max-crypto-memory resource control.
118  */
119 
120 #define	CRYPTO_MAX_BUFFER_LEN	(2 * 1024 * 1024)
121 #define	CRYPTO_MAX_FIND_COUNT	512
122 
123 /*
124  * When a mechanism parameter length is less than CRYPTO_DEFERRED_LIMIT
125  * bytes, then the length is added to the next resource control check.
126  */
127 #define	CRYPTO_DEFERRED_LIMIT	100
128 
129 /* The session table grows by CRYPTO_SESSION_CHUNK increments */
130 #define	CRYPTO_SESSION_CHUNK	100
131 
132 size_t crypto_max_buffer_len = CRYPTO_MAX_BUFFER_LEN;
133 
134 #define	INIT_RAW_CRYPTO_DATA(data, len)				\
135 	(data).cd_format = CRYPTO_DATA_RAW;			\
136 	(data).cd_raw.iov_base = kmem_alloc(len, KM_SLEEP);	\
137 	(data).cd_raw.iov_len = len;				\
138 	(data).cd_offset = 0;					\
139 	(data).cd_length = len;
140 
141 static struct kmem_cache *crypto_session_cache;
142 static crypto_minor_t **crypto_minors = NULL;
143 static dev_info_t *crypto_dip = NULL;
144 static minor_t crypto_minor_chunk = CRYPTO_MINOR_CHUNK;
145 static minor_t crypto_minors_table_count = 0;
146 
147 /*
148  * Minors are started from 1 because vmem_alloc()
149  * returns 0 in case of failure.
150  */
151 static vmem_t *crypto_arena = NULL;	/* Arena for device minors */
152 static minor_t crypto_minors_count = 0;
153 static kmutex_t crypto_lock;
154 static kmutex_t crypto_rctl_lock;
155 static kcondvar_t crypto_cv;
156 
157 #define	RETURN_LIST			B_TRUE
158 #define	DONT_RETURN_LIST		B_FALSE
159 
160 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
161 #define	CRYPTO_RANDOM_OFFSET(f)		offsetof(crypto_random_number_ops_t, f)
162 #define	CRYPTO_SESSION_OFFSET(f)	offsetof(crypto_session_ops_t, f)
163 #define	CRYPTO_OBJECT_OFFSET(f)		offsetof(crypto_object_ops_t, f)
164 #define	CRYPTO_PROVIDER_OFFSET(f)	\
165 	offsetof(crypto_provider_management_ops_t, f)
166 
167 #define	CRYPTO_CANCEL_CTX(spp) {	\
168 	crypto_cancel_ctx(*(spp));	\
169 	*(spp) = NULL;			\
170 }
171 
172 #define	CRYPTO_CANCEL_ALL_CTX(sp) {				\
173 	if ((sp)->sd_digest_ctx != NULL) {			\
174 		crypto_cancel_ctx((sp)->sd_digest_ctx);		\
175 		(sp)->sd_digest_ctx = NULL;			\
176 	}							\
177 	if ((sp)->sd_encr_ctx != NULL) {			\
178 		crypto_cancel_ctx((sp)->sd_encr_ctx);		\
179 		(sp)->sd_encr_ctx = NULL;			\
180 	}							\
181 	if ((sp)->sd_decr_ctx != NULL) {			\
182 		crypto_cancel_ctx((sp)->sd_decr_ctx);		\
183 		(sp)->sd_decr_ctx = NULL;			\
184 	}							\
185 	if ((sp)->sd_sign_ctx != NULL) {			\
186 		crypto_cancel_ctx((sp)->sd_sign_ctx);		\
187 		(sp)->sd_sign_ctx = NULL;			\
188 	}							\
189 	if ((sp)->sd_verify_ctx != NULL) {			\
190 		crypto_cancel_ctx((sp)->sd_verify_ctx);		\
191 		(sp)->sd_verify_ctx = NULL;			\
192 	}							\
193 	if ((sp)->sd_sign_recover_ctx != NULL) {		\
194 		crypto_cancel_ctx((sp)->sd_sign_recover_ctx);	\
195 		(sp)->sd_sign_recover_ctx = NULL;		\
196 	}							\
197 	if ((sp)->sd_verify_recover_ctx != NULL) {		\
198 		crypto_cancel_ctx((sp)->sd_verify_recover_ctx);	\
199 		(sp)->sd_verify_recover_ctx = NULL;		\
200 	}							\
201 }
202 
203 #define	CRYPTO_DECREMENT_RCTL(val, projp) {				\
204 	ASSERT(projp != NULL);						\
205 	(projp)->kpj_data.kpd_crypto_mem -= (val);			\
206 	project_rele(projp);						\
207 }
208 
209 /*
210  * Module linkage.
211  */
212 static struct cb_ops cbops = {
213 	crypto_open,		/* cb_open */
214 	crypto_close,		/* cb_close */
215 	nodev,			/* cb_strategy */
216 	nodev,			/* cb_print */
217 	nodev,			/* cb_dump */
218 	nodev,			/* cb_read */
219 	nodev,			/* cb_write */
220 	crypto_ioctl,		/* cb_ioctl */
221 	nodev,			/* cb_devmap */
222 	nodev,			/* cb_mmap */
223 	nodev,			/* cb_segmap */
224 	nochpoll,		/* cb_chpoll */
225 	ddi_prop_op,		/* cb_prop_op */
226 	NULL,			/* cb_streamtab */
227 	D_MP,			/* cb_flag */
228 	CB_REV,			/* cb_rev */
229 	nodev,			/* cb_aread */
230 	nodev,			/* cb_awrite */
231 };
232 
233 static struct dev_ops devops = {
234 	DEVO_REV,		/* devo_rev */
235 	0,			/* devo_refcnt */
236 	crypto_getinfo,		/* devo_getinfo */
237 	nulldev,		/* devo_identify */
238 	nulldev,		/* devo_probe */
239 	crypto_attach,		/* devo_attach */
240 	crypto_detach,		/* devo_detach */
241 	nodev,			/* devo_reset */
242 	&cbops,			/* devo_cb_ops */
243 	NULL,			/* devo_bus_ops */
244 	NULL,			/* devo_power */
245 };
246 
247 static struct modldrv modldrv = {
248 	&mod_driverops,					/* drv_modops */
249 	"Cryptographic Library Interface v%I%",	/* drv_linkinfo */
250 	&devops,
251 };
252 
253 static struct modlinkage modlinkage = {
254 	MODREV_1,		/* ml_rev */
255 	&modldrv,		/* ml_linkage */
256 	NULL
257 };
258 
259 /*
260  * DDI entry points.
261  */
262 int
263 _init(void)
264 {
265 	return (mod_install(&modlinkage));
266 }
267 
268 int
269 _fini(void)
270 {
271 	return (mod_remove(&modlinkage));
272 }
273 
274 int
275 _info(struct modinfo *modinfop)
276 {
277 	return (mod_info(&modlinkage, modinfop));
278 }
279 
280 /* ARGSUSED */
281 static int
282 crypto_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
283 {
284 	switch (cmd) {
285 	case DDI_INFO_DEVT2DEVINFO:
286 		*result = crypto_dip;
287 		return (DDI_SUCCESS);
288 
289 	case DDI_INFO_DEVT2INSTANCE:
290 		*result = (void *)0;
291 		return (DDI_SUCCESS);
292 	}
293 	return (DDI_FAILURE);
294 }
295 
296 static int
297 crypto_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
298 {
299 	if (cmd != DDI_ATTACH) {
300 		return (DDI_FAILURE);
301 	}
302 
303 	if (ddi_get_instance(dip) != 0) {
304 		/* we only allow instance 0 to attach */
305 		return (DDI_FAILURE);
306 	}
307 
308 	crypto_session_cache = kmem_cache_create("crypto_session_cache",
309 	    sizeof (crypto_session_data_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
310 
311 	if (crypto_session_cache == NULL)
312 		return (DDI_FAILURE);
313 
314 	/* create the minor node */
315 	if (ddi_create_minor_node(dip, "crypto", S_IFCHR, 0,
316 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
317 		kmem_cache_destroy(crypto_session_cache);
318 		crypto_session_cache = NULL;
319 		cmn_err(CE_WARN, "crypto_attach: failed creating minor node");
320 		ddi_remove_minor_node(dip, NULL);
321 		return (DDI_FAILURE);
322 	}
323 
324 	mutex_init(&crypto_lock, NULL, MUTEX_DRIVER, NULL);
325 	mutex_init(&crypto_rctl_lock, NULL, MUTEX_DRIVER, NULL);
326 	cv_init(&crypto_cv, NULL, CV_DRIVER, NULL);
327 	crypto_dip = dip;
328 
329 	/* allocate integer space for minor numbers */
330 	crypto_arena = vmem_create("crypto", (void *)1,
331 	    CRYPTO_MINOR_CHUNK, 1, NULL, NULL, NULL, 0,
332 	    VM_SLEEP | VMC_IDENTIFIER);
333 
334 	return (DDI_SUCCESS);
335 }
336 
337 static int
338 crypto_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
339 {
340 	minor_t i;
341 
342 	if (cmd != DDI_DETACH)
343 		return (DDI_FAILURE);
344 
345 	/* check if device is open */
346 	mutex_enter(&crypto_lock);
347 	for (i = 0; i < crypto_minors_table_count; i++) {
348 		if (crypto_minors[i] != NULL) {
349 			mutex_exit(&crypto_lock);
350 			return (DDI_FAILURE);
351 		}
352 	}
353 	mutex_exit(&crypto_lock);
354 
355 	crypto_dip = NULL;
356 	ddi_remove_minor_node(dip, NULL);
357 
358 	kmem_cache_destroy(crypto_session_cache);
359 	crypto_session_cache = NULL;
360 
361 	kmem_free(crypto_minors,
362 	    sizeof (crypto_minor_t *) * crypto_minors_table_count);
363 	crypto_minors = NULL;
364 	crypto_minors_table_count = 0;
365 	mutex_destroy(&crypto_lock);
366 	mutex_destroy(&crypto_rctl_lock);
367 	cv_destroy(&crypto_cv);
368 	vmem_destroy(crypto_arena);
369 	crypto_arena = NULL;
370 
371 	return (DDI_SUCCESS);
372 }
373 
374 /* ARGSUSED */
375 static int
376 crypto_open(dev_t *devp, int flag, int otyp, cred_t *credp)
377 {
378 	crypto_minor_t *cm = NULL;
379 	minor_t mn;
380 
381 	if (otyp != OTYP_CHR)
382 		return (ENXIO);
383 
384 	if (crypto_dip == NULL)
385 		return (ENXIO);
386 
387 	/* exclusive opens are not supported */
388 	if (flag & FEXCL)
389 		return (ENOTSUP);
390 
391 	mutex_enter(&crypto_lock);
392 again:
393 	/* grow the minors table if needed */
394 	if (crypto_minors_count >= crypto_minors_table_count) {
395 		crypto_minor_t **newtable;
396 		minor_t chunk = crypto_minor_chunk;
397 		minor_t saved_count;
398 		size_t new_size;
399 		ulong_t big_count;
400 
401 		big_count = crypto_minors_count + chunk;
402 		if (big_count > MAXMIN) {
403 			mutex_exit(&crypto_lock);
404 			return (ENOMEM);
405 		}
406 
407 		saved_count = crypto_minors_table_count;
408 		new_size = sizeof (crypto_minor_t *) *
409 		    (crypto_minors_table_count + chunk);
410 
411 		mutex_exit(&crypto_lock);
412 		newtable = kmem_zalloc(new_size, KM_SLEEP);
413 		mutex_enter(&crypto_lock);
414 
415 		/*
416 		 * Check if table grew while we were sleeping.
417 		 * The minors table never shrinks.
418 		 */
419 		if (crypto_minors_table_count > saved_count) {
420 			kmem_free(newtable, new_size);
421 			goto again;
422 		}
423 
424 		/* we assume that bcopy() will return if count is 0 */
425 		bcopy(crypto_minors, newtable,
426 		    sizeof (crypto_minor_t *) * crypto_minors_table_count);
427 
428 		kmem_free(crypto_minors,
429 		    sizeof (crypto_minor_t *) * crypto_minors_table_count);
430 
431 		/* grow the minors number space */
432 		if (crypto_minors_table_count != 0) {
433 			(void) vmem_add(crypto_arena,
434 			    (void *)(uintptr_t)(crypto_minors_table_count + 1),
435 			    crypto_minor_chunk, VM_SLEEP);
436 		}
437 
438 		crypto_minors = newtable;
439 		crypto_minors_table_count += chunk;
440 	}
441 	mutex_exit(&crypto_lock);
442 
443 	/* allocate a new minor number starting with 1 */
444 	mn = (minor_t)(uintptr_t)vmem_alloc(crypto_arena, 1, VM_SLEEP);
445 
446 	cm = kmem_zalloc(sizeof (crypto_minor_t), KM_SLEEP);
447 	mutex_init(&cm->cm_lock, NULL, MUTEX_DRIVER, NULL);
448 	cv_init(&cm->cm_cv, NULL, CV_DRIVER, NULL);
449 
450 	mutex_enter(&crypto_lock);
451 	crypto_minors[mn - 1] = cm;
452 	crypto_minors_count++;
453 	mutex_exit(&crypto_lock);
454 
455 	*devp = makedevice(getmajor(*devp), mn);
456 
457 	return (0);
458 }
459 
460 /* ARGSUSED */
461 static int
462 crypto_close(dev_t dev, int flag, int otyp, cred_t *credp)
463 {
464 	crypto_minor_t *cm = NULL;
465 	crypto_session_data_t *sp;
466 	minor_t mn = getminor(dev);
467 	uint_t i;
468 
469 	mutex_enter(&crypto_lock);
470 	if (mn > crypto_minors_table_count) {
471 		mutex_exit(&crypto_lock);
472 		cmn_err(CE_WARN, "crypto_close: bad minor (too big) %d", mn);
473 		return (ENODEV);
474 	}
475 
476 	while (((cm = crypto_minors[mn - 1]) != NULL) && (cm->cm_refcnt > 0)) {
477 		cv_wait(&crypto_cv, &crypto_lock);
478 	}
479 
480 	if (cm == NULL) {
481 		mutex_exit(&crypto_lock);
482 		cmn_err(CE_WARN, "crypto_close: duplicate close of minor %d",
483 		    getminor(dev));
484 		return (ENODEV);
485 	}
486 
487 	/* take it out of the global table */
488 	crypto_minors[mn - 1] = NULL;
489 	crypto_minors_count--;
490 
491 	vmem_free(crypto_arena, (void *)(uintptr_t)mn, 1);
492 
493 	mutex_enter(&cm->cm_lock);
494 	mutex_exit(&crypto_lock);
495 
496 	/* free all session table entries starting with 1 */
497 	for (i = 1; i < cm->cm_session_table_count; i++) {
498 		if (cm->cm_session_table[i] == NULL)
499 			continue;
500 
501 		sp = cm->cm_session_table[i];
502 		ASSERT((sp->sd_flags & CRYPTO_SESSION_IS_BUSY) == 0);
503 		if (sp->sd_find_init_cookie != NULL) {
504 			(void) crypto_free_find_ctx(sp);
505 		}
506 		crypto_release_provider_session(cm, sp->sd_provider_session);
507 		KCF_PROV_REFRELE(sp->sd_provider);
508 		CRYPTO_CANCEL_ALL_CTX(sp);
509 		mutex_destroy(&sp->sd_lock);
510 		cv_destroy(&sp->sd_cv);
511 		kmem_cache_free(crypto_session_cache, sp);
512 		cm->cm_session_table[i] = NULL;
513 	}
514 
515 	/* free the session table */
516 	if (cm->cm_session_table != NULL && cm->cm_session_table_count > 0)
517 		kmem_free(cm->cm_session_table, cm->cm_session_table_count *
518 		    sizeof (void *));
519 
520 	if (cm->cm_session_table_count != 0) {
521 		mutex_enter(&crypto_rctl_lock);
522 		CRYPTO_DECREMENT_RCTL(cm->cm_session_table_count *
523 		    sizeof (void *), cm->cm_projp);
524 		mutex_exit(&crypto_rctl_lock);
525 	}
526 
527 	kcf_free_provider_tab(cm->cm_provider_count,
528 	    cm->cm_provider_array);
529 
530 	mutex_destroy(&cm->cm_lock);
531 	cv_destroy(&cm->cm_cv);
532 	kmem_free(cm, sizeof (crypto_minor_t));
533 
534 	return (0);
535 }
536 
537 static crypto_minor_t *
538 crypto_hold_minor(minor_t minor)
539 {
540 	crypto_minor_t *cm = NULL;
541 
542 	mutex_enter(&crypto_lock);
543 	if ((minor <= crypto_minors_table_count) &&
544 	    ((cm = crypto_minors[minor - 1]) != NULL)) {
545 		cm->cm_refcnt++;
546 	}
547 	mutex_exit(&crypto_lock);
548 	return (cm);
549 }
550 
551 static void
552 crypto_release_minor(crypto_minor_t *cm)
553 {
554 	mutex_enter(&crypto_lock);
555 	cm->cm_refcnt--;
556 	if (cm->cm_refcnt == 0) {
557 		cv_broadcast(&crypto_cv);
558 	}
559 	mutex_exit(&crypto_lock);
560 }
561 
562 /*
563  *
564  */
565 static void
566 crypto_build_function_list(crypto_function_list_t *fl, kcf_provider_desc_t *pd)
567 {
568 	crypto_ops_t *ops;
569 	crypto_digest_ops_t *digest_ops;
570 	crypto_cipher_ops_t *cipher_ops;
571 	crypto_mac_ops_t *mac_ops;
572 	crypto_sign_ops_t *sign_ops;
573 	crypto_verify_ops_t *verify_ops;
574 	crypto_dual_ops_t *dual_ops;
575 	crypto_random_number_ops_t *random_number_ops;
576 	crypto_session_ops_t *session_ops;
577 	crypto_object_ops_t *object_ops;
578 	crypto_key_ops_t *key_ops;
579 	crypto_provider_management_ops_t *provider_ops;
580 
581 	if ((ops = pd->pd_ops_vector) == NULL)
582 		return;
583 
584 	if ((digest_ops = ops->co_digest_ops) != NULL) {
585 		if (digest_ops->digest_init != NULL)
586 			fl->fl_digest_init = B_TRUE;
587 		if (digest_ops->digest != NULL)
588 			fl->fl_digest = B_TRUE;
589 		if (digest_ops->digest_update != NULL)
590 			fl->fl_digest_update = B_TRUE;
591 		if (digest_ops->digest_key != NULL)
592 			fl->fl_digest_key = B_TRUE;
593 		if (digest_ops->digest_final != NULL)
594 			fl->fl_digest_final = B_TRUE;
595 	}
596 	if ((cipher_ops = ops->co_cipher_ops) != NULL) {
597 		if (cipher_ops->encrypt_init != NULL)
598 			fl->fl_encrypt_init = B_TRUE;
599 		if (cipher_ops->encrypt != NULL)
600 			fl->fl_encrypt = B_TRUE;
601 		if (cipher_ops->encrypt_update != NULL)
602 			fl->fl_encrypt_update = B_TRUE;
603 		if (cipher_ops->encrypt_final != NULL)
604 			fl->fl_encrypt_final = B_TRUE;
605 		if (cipher_ops->decrypt_init != NULL)
606 			fl->fl_decrypt_init = B_TRUE;
607 		if (cipher_ops->decrypt != NULL)
608 			fl->fl_decrypt = B_TRUE;
609 		if (cipher_ops->decrypt_update != NULL)
610 			fl->fl_decrypt_update = B_TRUE;
611 		if (cipher_ops->decrypt_final != NULL)
612 			fl->fl_decrypt_final = B_TRUE;
613 	}
614 	if ((mac_ops = ops->co_mac_ops) != NULL) {
615 		if (mac_ops->mac_init != NULL)
616 			fl->fl_mac_init = B_TRUE;
617 		if (mac_ops->mac != NULL)
618 			fl->fl_mac = B_TRUE;
619 		if (mac_ops->mac_update != NULL)
620 			fl->fl_mac_update = B_TRUE;
621 		if (mac_ops->mac_final != NULL)
622 			fl->fl_mac_final = B_TRUE;
623 	}
624 	if ((sign_ops = ops->co_sign_ops) != NULL) {
625 		if (sign_ops->sign_init != NULL)
626 			fl->fl_sign_init = B_TRUE;
627 		if (sign_ops->sign != NULL)
628 			fl->fl_sign = B_TRUE;
629 		if (sign_ops->sign_update != NULL)
630 			fl->fl_sign_update = B_TRUE;
631 		if (sign_ops->sign_final != NULL)
632 			fl->fl_sign_final = B_TRUE;
633 		if (sign_ops->sign_recover_init != NULL)
634 			fl->fl_sign_recover_init = B_TRUE;
635 		if (sign_ops->sign_recover != NULL)
636 			fl->fl_sign_recover = B_TRUE;
637 	}
638 	if ((verify_ops = ops->co_verify_ops) != NULL) {
639 		if (verify_ops->verify_init != NULL)
640 			fl->fl_verify_init = B_TRUE;
641 		if (verify_ops->verify != NULL)
642 			fl->fl_verify = B_TRUE;
643 		if (verify_ops->verify_update != NULL)
644 			fl->fl_verify_update = B_TRUE;
645 		if (verify_ops->verify_final != NULL)
646 			fl->fl_verify_final = B_TRUE;
647 		if (verify_ops->verify_recover_init != NULL)
648 			fl->fl_verify_recover_init = B_TRUE;
649 		if (verify_ops->verify_recover != NULL)
650 			fl->fl_verify_recover = B_TRUE;
651 	}
652 	if ((dual_ops = ops->co_dual_ops) != NULL) {
653 		if (dual_ops->digest_encrypt_update != NULL)
654 			fl->fl_digest_encrypt_update = B_TRUE;
655 		if (dual_ops->decrypt_digest_update != NULL)
656 			fl->fl_decrypt_digest_update = B_TRUE;
657 		if (dual_ops->sign_encrypt_update != NULL)
658 			fl->fl_sign_encrypt_update = B_TRUE;
659 		if (dual_ops->decrypt_verify_update != NULL)
660 			fl->fl_decrypt_verify_update = B_TRUE;
661 	}
662 	if ((random_number_ops = ops->co_random_ops) != NULL) {
663 		if (random_number_ops->seed_random != NULL)
664 			fl->fl_seed_random = B_TRUE;
665 		if (random_number_ops->generate_random != NULL)
666 			fl->fl_generate_random = B_TRUE;
667 	}
668 	if ((session_ops = ops->co_session_ops) != NULL) {
669 		if (session_ops->session_open != NULL)
670 			fl->fl_session_open = B_TRUE;
671 		if (session_ops->session_close != NULL)
672 			fl->fl_session_close = B_TRUE;
673 		if (session_ops->session_login != NULL)
674 			fl->fl_session_login = B_TRUE;
675 		if (session_ops->session_logout != NULL)
676 			fl->fl_session_logout = B_TRUE;
677 	}
678 	if ((object_ops = ops->co_object_ops) != NULL) {
679 		if (object_ops->object_create != NULL)
680 			fl->fl_object_create = B_TRUE;
681 		if (object_ops->object_copy != NULL)
682 			fl->fl_object_copy = B_TRUE;
683 		if (object_ops->object_destroy != NULL)
684 			fl->fl_object_destroy = B_TRUE;
685 		if (object_ops->object_get_size != NULL)
686 			fl->fl_object_get_size = B_TRUE;
687 		if (object_ops->object_get_attribute_value != NULL)
688 			fl->fl_object_get_attribute_value = B_TRUE;
689 		if (object_ops->object_set_attribute_value != NULL)
690 			fl->fl_object_set_attribute_value = B_TRUE;
691 		if (object_ops->object_find_init != NULL)
692 			fl->fl_object_find_init = B_TRUE;
693 		if (object_ops->object_find != NULL)
694 			fl->fl_object_find = B_TRUE;
695 		if (object_ops->object_find_final != NULL)
696 			fl->fl_object_find_final = B_TRUE;
697 	}
698 	if ((key_ops = ops->co_key_ops) != NULL) {
699 		if (key_ops->key_generate != NULL)
700 			fl->fl_key_generate = B_TRUE;
701 		if (key_ops->key_generate_pair != NULL)
702 			fl->fl_key_generate_pair = B_TRUE;
703 		if (key_ops->key_wrap != NULL)
704 			fl->fl_key_wrap = B_TRUE;
705 		if (key_ops->key_unwrap != NULL)
706 			fl->fl_key_unwrap = B_TRUE;
707 		if (key_ops->key_derive != NULL)
708 			fl->fl_key_derive = B_TRUE;
709 	}
710 	if ((provider_ops = ops->co_provider_ops) != NULL) {
711 		if (provider_ops->init_token != NULL)
712 			fl->fl_init_token = B_TRUE;
713 		if (provider_ops->init_pin != NULL)
714 			fl->fl_init_pin = B_TRUE;
715 		if (provider_ops->set_pin != NULL)
716 			fl->fl_set_pin = B_TRUE;
717 	}
718 }
719 
720 /* ARGSUSED */
721 static int
722 get_function_list(dev_t dev, caddr_t arg, int mode, int *rval)
723 {
724 	crypto_get_function_list_t get_function_list;
725 	crypto_minor_t *cm;
726 	crypto_provider_id_t provider_id;
727 	crypto_function_list_t *fl;
728 	kcf_provider_desc_t *provider;
729 	int rv;
730 
731 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
732 		cmn_err(CE_WARN, "get_function_list: failed holding minor");
733 		return (ENXIO);
734 	}
735 
736 	if (copyin(arg, &get_function_list, sizeof (get_function_list)) != 0) {
737 		crypto_release_minor(cm);
738 		return (EFAULT);
739 	}
740 
741 	/* initialize provider_array */
742 	if (cm->cm_provider_array == NULL) {
743 		rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
744 		if (rv != CRYPTO_SUCCESS) {
745 			goto release_minor;
746 		}
747 	}
748 
749 	provider_id = get_function_list.fl_provider_id;
750 	mutex_enter(&cm->cm_lock);
751 	/* index must be less than count of providers */
752 	if (provider_id >= cm->cm_provider_count) {
753 		mutex_exit(&cm->cm_lock);
754 		rv = CRYPTO_ARGUMENTS_BAD;
755 		goto release_minor;
756 	}
757 
758 	ASSERT(cm->cm_provider_array != NULL);
759 	provider = cm->cm_provider_array[provider_id];
760 	mutex_exit(&cm->cm_lock);
761 
762 	fl = &get_function_list.fl_list;
763 	bzero(fl, sizeof (crypto_function_list_t));
764 
765 	if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
766 		crypto_build_function_list(fl, provider);
767 	} else {
768 		kcf_provider_desc_t *prev = NULL, *pd;
769 
770 		mutex_enter(&provider->pd_lock);
771 		while (kcf_get_next_logical_provider_member(provider,
772 		    prev, &pd)) {
773 			prev = pd;
774 			crypto_build_function_list(fl, pd);
775 			KCF_PROV_REFRELE(pd);
776 		}
777 		mutex_exit(&provider->pd_lock);
778 	}
779 
780 	rv = CRYPTO_SUCCESS;
781 
782 release_minor:
783 	crypto_release_minor(cm);
784 
785 	get_function_list.fl_return_value = rv;
786 
787 	if (copyout(&get_function_list, arg, sizeof (get_function_list)) != 0) {
788 		return (EFAULT);
789 	}
790 	return (0);
791 }
792 
793 /*
794  * This ioctl maps a PKCS#11 mechanism string into an internal number
795  * that is used by the kernel.  pn_internal_number is set to the
796  * internal number.
797  */
798 /* ARGSUSED */
799 static int
800 get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval)
801 {
802 	STRUCT_DECL(crypto_get_mechanism_number, get_number);
803 	crypto_mech_type_t number;
804 	size_t len;
805 	char *mechanism_name;
806 	int rv;
807 
808 	STRUCT_INIT(get_number, mode);
809 
810 	if (copyin(arg, STRUCT_BUF(get_number), STRUCT_SIZE(get_number)) != 0)
811 		return (EFAULT);
812 
813 	len = STRUCT_FGET(get_number, pn_mechanism_len);
814 	if (len == 0 || len > CRYPTO_MAX_MECH_NAME) {
815 		rv = CRYPTO_ARGUMENTS_BAD;
816 		goto out;
817 	}
818 	mechanism_name = kmem_alloc(len, KM_SLEEP);
819 
820 	if (copyin(STRUCT_FGETP(get_number, pn_mechanism_string),
821 	    mechanism_name, len) != 0) {
822 		kmem_free(mechanism_name, len);
823 		return (EFAULT);
824 	}
825 
826 	/*
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 	kcf_ops_class_t class;
2240 	int index;
2241 	int rv;
2242 
2243 	/* get the provider's mech number */
2244 	class = KCF_MECH2CLASS(umech->cm_type);
2245 	index = KCF_MECH2INDEX(umech->cm_type);
2246 	provider_mech_type = pd->pd_map_mechnums[class][index];
2247 
2248 	kmech->cm_param = NULL;
2249 	kmech->cm_param_len = 0;
2250 	kmech->cm_type = provider_mech_type;
2251 	rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode);
2252 	kmech->cm_type = umech->cm_type;
2253 
2254 	return (rv);
2255 }
2256 
2257 /*
2258  * umech is a mechanism structure that has been copied from user address
2259  * space into kernel address space. Only one copyin has been done.
2260  * The mechanism parameter, if non-null, still points to user address space.
2261  * If the mechanism parameter contains pointers, they are pointers into
2262  * user address space.
2263  *
2264  * kmech is a umech with all pointers and structures in kernel address space.
2265  *
2266  * This routine calls the provider's entry point to copy a kmech parameter
2267  * into user address space using umech as a template containing
2268  * user address pointers.
2269  */
2270 static int
2271 crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd,
2272     crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error)
2273 {
2274 	crypto_mech_type_t provider_mech_type;
2275 	kcf_ops_class_t class;
2276 	int index;
2277 	int rv;
2278 
2279 	/* get the provider's mech number */
2280 	class = KCF_MECH2CLASS(umech->cm_type);
2281 	index = KCF_MECH2INDEX(umech->cm_type);
2282 	provider_mech_type = pd->pd_map_mechnums[class][index];
2283 
2284 	kmech->cm_type = provider_mech_type;
2285 	rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode);
2286 	kmech->cm_type = umech->cm_type;
2287 
2288 	return (rv);
2289 }
2290 
2291 /*
2292  * Call the provider's entry point to free kernel memory that has been
2293  * allocated for the mechanism's parameter.
2294  */
2295 static void
2296 crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module,
2297     crypto_mechanism_t *mech)
2298 {
2299 	crypto_mech_type_t provider_mech_type;
2300 	kcf_ops_class_t class;
2301 	int index;
2302 
2303 	if (allocated_by_crypto_module) {
2304 		if (mech->cm_param != NULL)
2305 			kmem_free(mech->cm_param, mech->cm_param_len);
2306 	} else {
2307 		/* get the provider's mech number */
2308 		class = KCF_MECH2CLASS(mech->cm_type);
2309 		index = KCF_MECH2INDEX(mech->cm_type);
2310 		provider_mech_type = pd->pd_map_mechnums[class][index];
2311 
2312 		if (mech->cm_param != NULL && mech->cm_param_len != 0) {
2313 			mech->cm_type = provider_mech_type;
2314 			(void) KCF_PROV_FREE_MECH(pd, mech);
2315 		}
2316 	}
2317 }
2318 
2319 /*
2320  * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init
2321  * structures are identical except for field names.
2322  */
2323 static int
2324 cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t,
2325     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2326     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *))
2327 {
2328 	STRUCT_DECL(crypto_encrypt_init, encrypt_init);
2329 	kproject_t *mech_projp, *key_projp;
2330 	kcf_provider_desc_t *real_provider = NULL;
2331 	crypto_session_id_t session_id;
2332 	crypto_mechanism_t mech;
2333 	crypto_key_t key;
2334 	crypto_minor_t *cm;
2335 	crypto_session_data_t *sp;
2336 	crypto_context_t cc;
2337 	crypto_ctx_t **ctxpp;
2338 	size_t mech_rctl_bytes = 0;
2339 	size_t key_rctl_bytes = 0;
2340 	size_t carry;
2341 	int error = 0;
2342 	int rv;
2343 	boolean_t allocated_by_crypto_module = B_FALSE;
2344 	crypto_func_group_t fg;
2345 
2346 	STRUCT_INIT(encrypt_init, mode);
2347 
2348 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2349 		cmn_err(CE_WARN, "cipher_init: failed holding minor");
2350 		return (ENXIO);
2351 	}
2352 
2353 	if (copyin(arg, STRUCT_BUF(encrypt_init),
2354 	    STRUCT_SIZE(encrypt_init)) != 0) {
2355 		crypto_release_minor(cm);
2356 		return (EFAULT);
2357 	}
2358 
2359 	mech.cm_param = NULL;
2360 	bzero(&key, sizeof (crypto_key_t));
2361 
2362 	session_id = STRUCT_FGET(encrypt_init, ei_session);
2363 
2364 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2365 		goto release_minor;
2366 	}
2367 
2368 	bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type,
2369 	    sizeof (crypto_mech_type_t));
2370 
2371 	if (init == crypto_encrypt_init_prov) {
2372 		fg = CRYPTO_FG_ENCRYPT;
2373 	} else {
2374 		fg = CRYPTO_FG_DECRYPT;
2375 	}
2376 
2377 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
2378 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, fg))
2379 	    != CRYPTO_SUCCESS) {
2380 		goto out;
2381 	}
2382 
2383 	carry = 0;
2384 	rv = crypto_provider_copyin_mech_param(real_provider,
2385 	    STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error);
2386 
2387 	if (rv == CRYPTO_NOT_SUPPORTED) {
2388 		allocated_by_crypto_module = B_TRUE;
2389 		if (!copyin_mech(mode, STRUCT_FADDR(encrypt_init, ei_mech),
2390 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
2391 		    &mech_projp)) {
2392 			goto out;
2393 		}
2394 	} else {
2395 		if (rv != CRYPTO_SUCCESS)
2396 			goto out;
2397 	}
2398 
2399 	if (!copyin_key(mode, STRUCT_FADDR(encrypt_init, ei_key), &key,
2400 	    &key_rctl_bytes, &rv, &error, carry, &key_projp)) {
2401 		goto out;
2402 	}
2403 
2404 	rv = (init)(real_provider, sp->sd_provider_session->ps_session,
2405 	    &mech, &key, NULL, &cc, NULL);
2406 
2407 	/*
2408 	 * Check if a context already exists. If so, it means it is being
2409 	 * abandoned. So, cancel it to avoid leaking it.
2410 	 */
2411 	ctxpp = (init == crypto_encrypt_init_prov) ?
2412 	    &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2413 
2414 	if (*ctxpp != NULL)
2415 		CRYPTO_CANCEL_CTX(ctxpp);
2416 	*ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
2417 
2418 out:
2419 	CRYPTO_SESSION_RELE(sp);
2420 
2421 release_minor:
2422 	mutex_enter(&crypto_rctl_lock);
2423 	if (mech_rctl_bytes != 0)
2424 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
2425 	if (key_rctl_bytes != 0)
2426 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
2427 	mutex_exit(&crypto_rctl_lock);
2428 	crypto_release_minor(cm);
2429 
2430 	if (real_provider != NULL) {
2431 		crypto_free_mech(real_provider,
2432 		    allocated_by_crypto_module, &mech);
2433 		KCF_PROV_REFRELE(real_provider);
2434 	}
2435 
2436 	free_crypto_key(&key);
2437 
2438 	if (error != 0)
2439 		/* XXX free context */
2440 		return (error);
2441 
2442 	STRUCT_FSET(encrypt_init, ei_return_value, rv);
2443 	if (copyout(STRUCT_BUF(encrypt_init), arg,
2444 	    STRUCT_SIZE(encrypt_init)) != 0) {
2445 		/* XXX free context */
2446 		return (EFAULT);
2447 	}
2448 	return (0);
2449 }
2450 
2451 /* ARGSUSED */
2452 static int
2453 encrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2454 {
2455 	return (cipher(dev, arg, mode, crypto_encrypt_single));
2456 }
2457 
2458 /* ARGSUSED */
2459 static int
2460 decrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2461 {
2462 	return (cipher(dev, arg, mode, crypto_decrypt_single));
2463 }
2464 
2465 /*
2466  * ASSUMPTION: crypto_encrypt and crypto_decrypt structures
2467  * are identical except for field names.
2468  */
2469 static int
2470 cipher(dev_t dev, caddr_t arg, int mode,
2471     int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2472     crypto_call_req_t *))
2473 {
2474 	STRUCT_DECL(crypto_encrypt, encrypt);
2475 	kproject_t *projp;
2476 	crypto_session_id_t session_id;
2477 	crypto_minor_t *cm;
2478 	crypto_session_data_t *sp;
2479 	crypto_ctx_t **ctxpp;
2480 	crypto_data_t data, encr;
2481 	size_t datalen, encrlen, need = 0;
2482 	char *encrbuf;
2483 	int error = 0;
2484 	int rv;
2485 
2486 	STRUCT_INIT(encrypt, mode);
2487 
2488 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2489 		cmn_err(CE_WARN, "cipher: failed holding minor");
2490 		return (ENXIO);
2491 	}
2492 
2493 	if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) {
2494 		crypto_release_minor(cm);
2495 		return (EFAULT);
2496 	}
2497 
2498 	data.cd_raw.iov_base = NULL;
2499 	encr.cd_raw.iov_base = NULL;
2500 
2501 	datalen = STRUCT_FGET(encrypt, ce_datalen);
2502 	encrlen = STRUCT_FGET(encrypt, ce_encrlen);
2503 
2504 	/*
2505 	 * Don't allocate output buffer unless both buffer pointer and
2506 	 * buffer length are not NULL or 0 (length).
2507 	 */
2508 	encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf);
2509 	if (encrbuf == NULL || encrlen == 0) {
2510 		encrlen = 0;
2511 	}
2512 
2513 	if (datalen > crypto_max_buffer_len ||
2514 	    encrlen > crypto_max_buffer_len) {
2515 		cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, "
2516 		    "pid = %d", crypto_max_buffer_len, curproc->p_pid);
2517 		rv = CRYPTO_ARGUMENTS_BAD;
2518 		goto release_minor;
2519 	}
2520 
2521 	need = datalen + encrlen;
2522 	if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) {
2523 		need = 0;
2524 		goto release_minor;
2525 	}
2526 
2527 	INIT_RAW_CRYPTO_DATA(data, datalen);
2528 	data.cd_miscdata = NULL;
2529 
2530 	if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf),
2531 	    data.cd_raw.iov_base, datalen) != 0) {
2532 		error = EFAULT;
2533 		goto release_minor;
2534 	}
2535 
2536 	INIT_RAW_CRYPTO_DATA(encr, encrlen);
2537 
2538 	session_id = STRUCT_FGET(encrypt, ce_session);
2539 
2540 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2541 		goto release_minor;
2542 	}
2543 
2544 	ctxpp = (single == crypto_encrypt_single) ?
2545 	    &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2546 
2547 	rv = (single)(*ctxpp, &data, &encr, NULL);
2548 	if (KCF_CONTEXT_DONE(rv))
2549 		*ctxpp = NULL;
2550 
2551 	CRYPTO_SESSION_RELE(sp);
2552 
2553 	if (rv == CRYPTO_SUCCESS) {
2554 		ASSERT(encr.cd_length <= encrlen);
2555 		if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2556 		    encrbuf, encr.cd_length) != 0) {
2557 			error = EFAULT;
2558 			goto release_minor;
2559 		}
2560 		STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length);
2561 	}
2562 
2563 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
2564 		/*
2565 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
2566 		 * of section 11.2 of the pkcs11 spec. We catch it here and
2567 		 * provide the correct pkcs11 return value.
2568 		 */
2569 		if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL)
2570 			rv = CRYPTO_SUCCESS;
2571 		STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length);
2572 	}
2573 
2574 release_minor:
2575 	if (need != 0) {
2576 		mutex_enter(&crypto_rctl_lock);
2577 		CRYPTO_DECREMENT_RCTL(need, projp);
2578 		mutex_exit(&crypto_rctl_lock);
2579 	}
2580 	crypto_release_minor(cm);
2581 
2582 	if (data.cd_raw.iov_base != NULL)
2583 		kmem_free(data.cd_raw.iov_base, datalen);
2584 
2585 	if (encr.cd_raw.iov_base != NULL)
2586 		kmem_free(encr.cd_raw.iov_base, encrlen);
2587 
2588 	if (error != 0)
2589 		return (error);
2590 
2591 	STRUCT_FSET(encrypt, ce_return_value, rv);
2592 	if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) {
2593 		return (EFAULT);
2594 	}
2595 	return (0);
2596 }
2597 
2598 /* ARGSUSED */
2599 static int
2600 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2601 {
2602 	return (cipher_update(dev, arg, mode, crypto_encrypt_update));
2603 }
2604 
2605 /* ARGSUSED */
2606 static int
2607 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2608 {
2609 	return (cipher_update(dev, arg, mode, crypto_decrypt_update));
2610 }
2611 
2612 /*
2613  * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update
2614  * structures are identical except for field names.
2615  */
2616 static int
2617 cipher_update(dev_t dev, caddr_t arg, int mode,
2618     int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2619     crypto_call_req_t *))
2620 {
2621 	STRUCT_DECL(crypto_encrypt_update, encrypt_update);
2622 	kproject_t *projp;
2623 	crypto_session_id_t session_id;
2624 	crypto_minor_t *cm;
2625 	crypto_session_data_t *sp;
2626 	crypto_ctx_t **ctxpp;
2627 	crypto_data_t data, encr;
2628 	size_t datalen, encrlen, need = 0;
2629 	char *encrbuf;
2630 	int error = 0;
2631 	int rv;
2632 
2633 	STRUCT_INIT(encrypt_update, mode);
2634 
2635 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2636 		cmn_err(CE_WARN, "cipher_update: failed holding minor");
2637 		return (ENXIO);
2638 	}
2639 
2640 	if (copyin(arg, STRUCT_BUF(encrypt_update),
2641 	    STRUCT_SIZE(encrypt_update)) != 0) {
2642 		crypto_release_minor(cm);
2643 		return (EFAULT);
2644 	}
2645 
2646 	data.cd_raw.iov_base = NULL;
2647 	encr.cd_raw.iov_base = NULL;
2648 
2649 	datalen = STRUCT_FGET(encrypt_update, eu_datalen);
2650 	encrlen = STRUCT_FGET(encrypt_update, eu_encrlen);
2651 
2652 	/*
2653 	 * Don't allocate output buffer unless both buffer pointer and
2654 	 * buffer length are not NULL or 0 (length).
2655 	 */
2656 	encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf);
2657 	if (encrbuf == NULL || encrlen == 0) {
2658 		encrlen = 0;
2659 	}
2660 
2661 	if (datalen > crypto_max_buffer_len ||
2662 	    encrlen > crypto_max_buffer_len) {
2663 		cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld "
2664 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
2665 		rv = CRYPTO_ARGUMENTS_BAD;
2666 		goto release_minor;
2667 	}
2668 
2669 	need = datalen + encrlen;
2670 	if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) {
2671 		need = 0;
2672 		goto release_minor;
2673 	}
2674 
2675 	INIT_RAW_CRYPTO_DATA(data, datalen);
2676 	data.cd_miscdata = NULL;
2677 
2678 	if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf),
2679 	    data.cd_raw.iov_base, datalen) != 0) {
2680 		error = EFAULT;
2681 		goto release_minor;
2682 	}
2683 
2684 	INIT_RAW_CRYPTO_DATA(encr, encrlen);
2685 
2686 	session_id = STRUCT_FGET(encrypt_update, eu_session);
2687 
2688 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2689 		goto release_minor;
2690 	}
2691 
2692 	ctxpp = (update == crypto_encrypt_update) ?
2693 	    &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2694 
2695 	rv = (update)(*ctxpp, &data, &encr, NULL);
2696 
2697 	if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) {
2698 		if (rv == CRYPTO_SUCCESS) {
2699 			ASSERT(encr.cd_length <= encrlen);
2700 			if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2701 			    encrbuf, encr.cd_length) != 0) {
2702 				error = EFAULT;
2703 				goto out;
2704 			}
2705 		} else {
2706 			/*
2707 			 * The providers return CRYPTO_BUFFER_TOO_SMALL even
2708 			 * for case 1 of section 11.2 of the pkcs11 spec.
2709 			 * We catch it here and provide the correct pkcs11
2710 			 * return value.
2711 			 */
2712 			if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL)
2713 				rv = CRYPTO_SUCCESS;
2714 		}
2715 		STRUCT_FSET(encrypt_update, eu_encrlen, encr.cd_length);
2716 	} else {
2717 		CRYPTO_CANCEL_CTX(ctxpp);
2718 	}
2719 out:
2720 	CRYPTO_SESSION_RELE(sp);
2721 
2722 release_minor:
2723 	if (need != 0) {
2724 		mutex_enter(&crypto_rctl_lock);
2725 		CRYPTO_DECREMENT_RCTL(need, projp);
2726 		mutex_exit(&crypto_rctl_lock);
2727 	}
2728 	crypto_release_minor(cm);
2729 
2730 	if (data.cd_raw.iov_base != NULL)
2731 		kmem_free(data.cd_raw.iov_base, datalen);
2732 
2733 	if (encr.cd_raw.iov_base != NULL)
2734 		kmem_free(encr.cd_raw.iov_base, encrlen);
2735 
2736 	if (error != 0)
2737 		return (error);
2738 
2739 	STRUCT_FSET(encrypt_update, eu_return_value, rv);
2740 	if (copyout(STRUCT_BUF(encrypt_update), arg,
2741 	    STRUCT_SIZE(encrypt_update)) != 0) {
2742 		return (EFAULT);
2743 	}
2744 	return (0);
2745 }
2746 
2747 /* ARGSUSED */
2748 static int
2749 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
2750 {
2751 	return (common_final(dev, arg, mode, crypto_encrypt_final));
2752 }
2753 
2754 /* ARGSUSED */
2755 static int
2756 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
2757 {
2758 	return (common_final(dev, arg, mode, crypto_decrypt_final));
2759 }
2760 
2761 /*
2762  * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final,
2763  * and crypto_digest_final structures are identical except for field names.
2764  */
2765 static int
2766 common_final(dev_t dev, caddr_t arg, int mode,
2767     int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
2768 {
2769 	STRUCT_DECL(crypto_encrypt_final, encrypt_final);
2770 	kproject_t *projp;
2771 	crypto_session_id_t session_id;
2772 	crypto_minor_t *cm;
2773 	crypto_session_data_t *sp;
2774 	crypto_ctx_t **ctxpp;
2775 	crypto_data_t encr;
2776 	size_t encrlen, need = 0;
2777 	char *encrbuf;
2778 	int error = 0;
2779 	int rv;
2780 
2781 	STRUCT_INIT(encrypt_final, mode);
2782 
2783 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2784 		cmn_err(CE_WARN, "common_final: failed holding minor");
2785 		return (ENXIO);
2786 	}
2787 
2788 	if (copyin(arg, STRUCT_BUF(encrypt_final),
2789 	    STRUCT_SIZE(encrypt_final)) != 0) {
2790 		crypto_release_minor(cm);
2791 		return (EFAULT);
2792 	}
2793 
2794 	encr.cd_format = CRYPTO_DATA_RAW;
2795 	encr.cd_raw.iov_base = NULL;
2796 
2797 	encrlen = STRUCT_FGET(encrypt_final, ef_encrlen);
2798 
2799 	/*
2800 	 * Don't allocate output buffer unless both buffer pointer and
2801 	 * buffer length are not NULL or 0 (length).
2802 	 */
2803 	encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf);
2804 	if (encrbuf == NULL || encrlen == 0) {
2805 		encrlen = 0;
2806 	}
2807 
2808 	if (encrlen > crypto_max_buffer_len) {
2809 		cmn_err(CE_NOTE, "common_final: buffer greater than %ld "
2810 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
2811 		rv = CRYPTO_ARGUMENTS_BAD;
2812 		goto release_minor;
2813 	}
2814 
2815 	if ((rv = crypto_buffer_check(encrlen, &projp)) != CRYPTO_SUCCESS) {
2816 		goto release_minor;
2817 	}
2818 	need = encrlen;
2819 	encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP);
2820 	encr.cd_raw.iov_len = encrlen;
2821 
2822 	encr.cd_offset = 0;
2823 	encr.cd_length = encrlen;
2824 
2825 	session_id = STRUCT_FGET(encrypt_final, ef_session);
2826 
2827 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2828 		goto release_minor;
2829 	}
2830 
2831 	ASSERT(final == crypto_encrypt_final ||
2832 	    final == crypto_decrypt_final || final == crypto_sign_final ||
2833 	    final == crypto_digest_final);
2834 
2835 	if (final == crypto_encrypt_final) {
2836 		ctxpp = &sp->sd_encr_ctx;
2837 	} else if (final == crypto_decrypt_final) {
2838 		ctxpp = &sp->sd_decr_ctx;
2839 	} else if (final == crypto_sign_final) {
2840 		ctxpp = &sp->sd_sign_ctx;
2841 	} else {
2842 		ctxpp = &sp->sd_digest_ctx;
2843 	}
2844 
2845 	rv = (final)(*ctxpp, &encr, NULL);
2846 	if (KCF_CONTEXT_DONE(rv))
2847 		*ctxpp = NULL;
2848 
2849 	CRYPTO_SESSION_RELE(sp);
2850 
2851 	if (rv == CRYPTO_SUCCESS) {
2852 		ASSERT(encr.cd_length <= encrlen);
2853 		if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2854 		    encrbuf, encr.cd_length) != 0) {
2855 			error = EFAULT;
2856 			goto release_minor;
2857 		}
2858 		STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length);
2859 	}
2860 
2861 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
2862 		/*
2863 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
2864 		 * of section 11.2 of the pkcs11 spec. We catch it here and
2865 		 * provide the correct pkcs11 return value.
2866 		 */
2867 		if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL)
2868 			rv = CRYPTO_SUCCESS;
2869 		STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length);
2870 	}
2871 
2872 release_minor:
2873 	if (need != 0) {
2874 		mutex_enter(&crypto_rctl_lock);
2875 		CRYPTO_DECREMENT_RCTL(need, projp);
2876 		mutex_exit(&crypto_rctl_lock);
2877 	}
2878 	crypto_release_minor(cm);
2879 
2880 	if (encr.cd_raw.iov_base != NULL)
2881 		kmem_free(encr.cd_raw.iov_base, encrlen);
2882 
2883 	if (error != 0)
2884 		return (error);
2885 
2886 	STRUCT_FSET(encrypt_final, ef_return_value, rv);
2887 	if (copyout(STRUCT_BUF(encrypt_final), arg,
2888 	    STRUCT_SIZE(encrypt_final)) != 0) {
2889 		return (EFAULT);
2890 	}
2891 	return (0);
2892 }
2893 
2894 /* ARGSUSED */
2895 static int
2896 digest_init(dev_t dev, caddr_t arg, int mode, int *rval)
2897 {
2898 	STRUCT_DECL(crypto_digest_init, digest_init);
2899 	kproject_t *mech_projp;
2900 	kcf_provider_desc_t *real_provider = NULL;
2901 	crypto_session_id_t session_id;
2902 	crypto_mechanism_t mech;
2903 	crypto_minor_t *cm;
2904 	crypto_session_data_t *sp;
2905 	crypto_context_t cc;
2906 	size_t rctl_bytes = 0;
2907 	int error = 0;
2908 	int rv;
2909 
2910 	STRUCT_INIT(digest_init, mode);
2911 
2912 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2913 		cmn_err(CE_WARN, "digest_init: failed holding minor");
2914 		return (ENXIO);
2915 	}
2916 
2917 	if (copyin(arg, STRUCT_BUF(digest_init),
2918 	    STRUCT_SIZE(digest_init)) != 0) {
2919 		crypto_release_minor(cm);
2920 		return (EFAULT);
2921 	}
2922 
2923 	mech.cm_param = NULL;
2924 
2925 	session_id = STRUCT_FGET(digest_init, di_session);
2926 
2927 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2928 		goto release_minor;
2929 	}
2930 
2931 	if (!copyin_mech(mode, STRUCT_FADDR(digest_init, di_mech), &mech,
2932 	    &rctl_bytes, NULL, &rv, &error, &mech_projp)) {
2933 		goto out;
2934 	}
2935 
2936 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
2937 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
2938 	    CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) {
2939 		goto out;
2940 	}
2941 
2942 	rv = crypto_digest_init_prov(real_provider,
2943 	    sp->sd_provider_session->ps_session, &mech, &cc, NULL);
2944 
2945 	/*
2946 	 * Check if a context already exists. If so, it means it is being
2947 	 * abandoned. So, cancel it to avoid leaking it.
2948 	 */
2949 	if (sp->sd_digest_ctx != NULL)
2950 		CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
2951 	sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL;
2952 out:
2953 	CRYPTO_SESSION_RELE(sp);
2954 
2955 release_minor:
2956 	if (rctl_bytes != 0) {
2957 		mutex_enter(&crypto_rctl_lock);
2958 		CRYPTO_DECREMENT_RCTL(rctl_bytes, mech_projp);
2959 		mutex_exit(&crypto_rctl_lock);
2960 	}
2961 	crypto_release_minor(cm);
2962 
2963 	if (real_provider != NULL)
2964 		KCF_PROV_REFRELE(real_provider);
2965 
2966 	if (mech.cm_param != NULL)
2967 		kmem_free(mech.cm_param, mech.cm_param_len);
2968 
2969 	if (error != 0)
2970 		return (error);
2971 
2972 	STRUCT_FSET(digest_init, di_return_value, rv);
2973 	if (copyout(STRUCT_BUF(digest_init), arg,
2974 	    STRUCT_SIZE(digest_init)) != 0) {
2975 		return (EFAULT);
2976 	}
2977 	return (0);
2978 }
2979 
2980 /* ARGSUSED */
2981 static int
2982 digest_update(dev_t dev, caddr_t arg, int mode, int *rval)
2983 {
2984 	STRUCT_DECL(crypto_digest_update, digest_update);
2985 	kproject_t *projp;
2986 	crypto_session_id_t session_id;
2987 	crypto_minor_t *cm;
2988 	crypto_session_data_t *sp;
2989 	crypto_data_t data;
2990 	size_t datalen, need = 0;
2991 	int error = 0;
2992 	int rv;
2993 
2994 	STRUCT_INIT(digest_update, mode);
2995 
2996 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2997 		cmn_err(CE_WARN, "digest_update: failed holding minor");
2998 		return (ENXIO);
2999 	}
3000 
3001 	if (copyin(arg, STRUCT_BUF(digest_update),
3002 	    STRUCT_SIZE(digest_update)) != 0) {
3003 		crypto_release_minor(cm);
3004 		return (EFAULT);
3005 	}
3006 
3007 	data.cd_format = CRYPTO_DATA_RAW;
3008 	data.cd_raw.iov_base = NULL;
3009 
3010 	datalen = STRUCT_FGET(digest_update, du_datalen);
3011 	if (datalen > crypto_max_buffer_len) {
3012 		cmn_err(CE_NOTE, "digest_update: buffer greater than %ld "
3013 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3014 		rv = CRYPTO_ARGUMENTS_BAD;
3015 		goto release_minor;
3016 	}
3017 
3018 	if ((rv = crypto_buffer_check(datalen, &projp)) != CRYPTO_SUCCESS) {
3019 		goto release_minor;
3020 	}
3021 	need = datalen;
3022 	data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP);
3023 	data.cd_raw.iov_len = datalen;
3024 
3025 	if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf),
3026 	    data.cd_raw.iov_base, datalen) != 0) {
3027 		error = EFAULT;
3028 		goto release_minor;
3029 	}
3030 
3031 	data.cd_offset = 0;
3032 	data.cd_length = datalen;
3033 
3034 	session_id = STRUCT_FGET(digest_update, du_session);
3035 
3036 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3037 		goto release_minor;
3038 	}
3039 
3040 	rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL);
3041 	if (rv != CRYPTO_SUCCESS)
3042 		CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3043 	CRYPTO_SESSION_RELE(sp);
3044 
3045 release_minor:
3046 	if (need != 0) {
3047 		mutex_enter(&crypto_rctl_lock);
3048 		CRYPTO_DECREMENT_RCTL(need, projp);
3049 		mutex_exit(&crypto_rctl_lock);
3050 	}
3051 	crypto_release_minor(cm);
3052 
3053 	if (data.cd_raw.iov_base != NULL)
3054 		kmem_free(data.cd_raw.iov_base, datalen);
3055 
3056 	if (error != 0)
3057 		return (error);
3058 
3059 	STRUCT_FSET(digest_update, du_return_value, rv);
3060 	if (copyout(STRUCT_BUF(digest_update), arg,
3061 	    STRUCT_SIZE(digest_update)) != 0) {
3062 		return (EFAULT);
3063 	}
3064 	return (0);
3065 }
3066 
3067 /* ARGSUSED */
3068 static int
3069 digest_key(dev_t dev, caddr_t arg, int mode, int *rval)
3070 {
3071 	STRUCT_DECL(crypto_digest_key, digest_key);
3072 	kproject_t *projp;
3073 	crypto_session_id_t session_id;
3074 	crypto_key_t key;
3075 	crypto_minor_t *cm;
3076 	crypto_session_data_t *sp;
3077 	size_t rctl_bytes = 0;
3078 	int error = 0;
3079 	int rv;
3080 
3081 	STRUCT_INIT(digest_key, mode);
3082 
3083 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3084 		cmn_err(CE_WARN, "digest_key: failed holding minor");
3085 		return (ENXIO);
3086 	}
3087 
3088 	if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) {
3089 		crypto_release_minor(cm);
3090 		return (EFAULT);
3091 	}
3092 
3093 	bzero(&key, sizeof (crypto_key_t));
3094 
3095 	session_id = STRUCT_FGET(digest_key, dk_session);
3096 
3097 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3098 		goto release_minor;
3099 	}
3100 
3101 	if (!copyin_key(mode, STRUCT_FADDR(digest_key, dk_key), &key,
3102 	    &rctl_bytes, &rv, &error, 0, &projp)) {
3103 		goto out;
3104 	}
3105 
3106 	rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL);
3107 	if (rv != CRYPTO_SUCCESS)
3108 		CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3109 out:
3110 	CRYPTO_SESSION_RELE(sp);
3111 
3112 release_minor:
3113 	if (rctl_bytes != 0) {
3114 		mutex_enter(&crypto_rctl_lock);
3115 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
3116 		mutex_exit(&crypto_rctl_lock);
3117 	}
3118 	crypto_release_minor(cm);
3119 
3120 	free_crypto_key(&key);
3121 
3122 	if (error != 0)
3123 		return (error);
3124 
3125 	STRUCT_FSET(digest_key, dk_return_value, rv);
3126 	if (copyout(STRUCT_BUF(digest_key), arg,
3127 	    STRUCT_SIZE(digest_key)) != 0) {
3128 		return (EFAULT);
3129 	}
3130 	return (0);
3131 }
3132 
3133 /* ARGSUSED */
3134 static int
3135 digest_final(dev_t dev, caddr_t arg, int mode, int *rval)
3136 {
3137 	return (common_final(dev, arg, mode, crypto_digest_final));
3138 }
3139 
3140 /* ARGSUSED */
3141 static int
3142 digest(dev_t dev, caddr_t arg, int mode, int *rval)
3143 {
3144 	return (common_digest(dev, arg, mode, crypto_digest_single));
3145 }
3146 
3147 /*
3148  * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
3149  * and crypto_verify_recover are identical except for field names.
3150  */
3151 static int
3152 common_digest(dev_t dev, caddr_t arg, int mode,
3153     int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
3154     crypto_call_req_t *))
3155 {
3156 	STRUCT_DECL(crypto_digest, crypto_digest);
3157 	kproject_t *projp;
3158 	crypto_session_id_t session_id;
3159 	crypto_minor_t *cm;
3160 	crypto_session_data_t *sp;
3161 	crypto_data_t data, digest;
3162 	crypto_ctx_t **ctxpp;
3163 	size_t datalen, digestlen, need = 0;
3164 	char *digestbuf;
3165 	int error = 0;
3166 	int rv;
3167 
3168 	STRUCT_INIT(crypto_digest, mode);
3169 
3170 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3171 		cmn_err(CE_WARN, "common_digest: failed holding minor");
3172 		return (ENXIO);
3173 	}
3174 
3175 	if (copyin(arg, STRUCT_BUF(crypto_digest),
3176 	    STRUCT_SIZE(crypto_digest)) != 0) {
3177 		crypto_release_minor(cm);
3178 		return (EFAULT);
3179 	}
3180 
3181 	data.cd_raw.iov_base = NULL;
3182 	digest.cd_raw.iov_base = NULL;
3183 
3184 	datalen = STRUCT_FGET(crypto_digest, cd_datalen);
3185 	digestlen = STRUCT_FGET(crypto_digest, cd_digestlen);
3186 
3187 	/*
3188 	 * Don't allocate output buffer unless both buffer pointer and
3189 	 * buffer length are not NULL or 0 (length).
3190 	 */
3191 	digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf);
3192 	if (digestbuf == NULL || digestlen == 0) {
3193 		digestlen = 0;
3194 	}
3195 
3196 	if (datalen > crypto_max_buffer_len ||
3197 	    digestlen > crypto_max_buffer_len) {
3198 		cmn_err(CE_NOTE, "common_digest: buffer greater than %ld "
3199 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3200 		rv = CRYPTO_ARGUMENTS_BAD;
3201 		goto release_minor;
3202 	}
3203 
3204 	need = datalen + digestlen;
3205 	if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) {
3206 		need = 0;
3207 		goto release_minor;
3208 	}
3209 
3210 	INIT_RAW_CRYPTO_DATA(data, datalen);
3211 
3212 	if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf),
3213 	    data.cd_raw.iov_base, datalen) != 0) {
3214 		error = EFAULT;
3215 		goto release_minor;
3216 	}
3217 
3218 	INIT_RAW_CRYPTO_DATA(digest, digestlen);
3219 
3220 	session_id = STRUCT_FGET(crypto_digest, cd_session);
3221 
3222 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3223 		goto release_minor;
3224 	}
3225 
3226 	ASSERT(single == crypto_digest_single ||
3227 	    single == crypto_sign_single ||
3228 	    single == crypto_verify_recover_single ||
3229 	    single == crypto_sign_recover_single);
3230 
3231 	if (single == crypto_digest_single) {
3232 		ctxpp = &sp->sd_digest_ctx;
3233 	} else if (single == crypto_sign_single) {
3234 		ctxpp = &sp->sd_sign_ctx;
3235 	} else if (single == crypto_verify_recover_single) {
3236 		ctxpp = &sp->sd_verify_recover_ctx;
3237 	} else {
3238 		ctxpp = &sp->sd_sign_recover_ctx;
3239 	}
3240 	rv = (single)(*ctxpp, &data, &digest, NULL);
3241 	if (KCF_CONTEXT_DONE(rv))
3242 		*ctxpp = NULL;
3243 
3244 	CRYPTO_SESSION_RELE(sp);
3245 
3246 	if (rv == CRYPTO_SUCCESS) {
3247 		ASSERT(digest.cd_length <= digestlen);
3248 		if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base,
3249 		    digestbuf, digest.cd_length) != 0) {
3250 			error = EFAULT;
3251 			goto release_minor;
3252 		}
3253 		STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length);
3254 	}
3255 
3256 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3257 		/*
3258 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3259 		 * of section 11.2 of the pkcs11 spec. We catch it here and
3260 		 * provide the correct pkcs11 return value.
3261 		 */
3262 		if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL)
3263 			rv = CRYPTO_SUCCESS;
3264 		STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length);
3265 	}
3266 
3267 release_minor:
3268 	if (need != 0) {
3269 		mutex_enter(&crypto_rctl_lock);
3270 		CRYPTO_DECREMENT_RCTL(need, projp);
3271 		mutex_exit(&crypto_rctl_lock);
3272 	}
3273 	crypto_release_minor(cm);
3274 
3275 	if (data.cd_raw.iov_base != NULL)
3276 		kmem_free(data.cd_raw.iov_base, datalen);
3277 
3278 	if (digest.cd_raw.iov_base != NULL)
3279 		kmem_free(digest.cd_raw.iov_base, digestlen);
3280 
3281 	if (error != 0)
3282 		return (error);
3283 
3284 	STRUCT_FSET(crypto_digest, cd_return_value, rv);
3285 	if (copyout(STRUCT_BUF(crypto_digest), arg,
3286 	    STRUCT_SIZE(crypto_digest)) != 0) {
3287 		return (EFAULT);
3288 	}
3289 	return (0);
3290 }
3291 
3292 /*
3293  * A helper function that does what the name suggests.
3294  * Returns 0 on success and non-zero otherwise.
3295  * On failure, out_pin is set to 0.
3296  */
3297 int
3298 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len,
3299     crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp,
3300     int *rv, int *error)
3301 {
3302 	char *tmp_pin = NULL;
3303 	int tmp_error = 0, tmp_rv = 0;
3304 
3305 	if (pin_len > KCF_MAX_PIN_LEN) {
3306 		tmp_rv = CRYPTO_PIN_LEN_RANGE;
3307 		goto out;
3308 	}
3309 	tmp_pin = kmem_alloc(pin_len, KM_SLEEP);
3310 
3311 	if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) {
3312 		tmp_error = EFAULT;
3313 		goto out;
3314 	}
3315 
3316 	(void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv);
3317 out:
3318 	*out_pin = tmp_pin;
3319 	*rv = tmp_rv;
3320 	*error = tmp_error;
3321 	return (tmp_rv | tmp_error);
3322 }
3323 
3324 /* ARGSUSED */
3325 static int
3326 set_pin(dev_t dev, caddr_t arg, int mode, int *rval)
3327 {
3328 	STRUCT_DECL(crypto_set_pin, set_pin);
3329 	kcf_provider_desc_t *real_provider;
3330 	kcf_req_params_t params;
3331 	crypto_minor_t *cm;
3332 	crypto_session_data_t *sp;
3333 	char *old_pin = NULL;
3334 	char *new_pin = NULL;
3335 	size_t old_pin_len;
3336 	size_t new_pin_len;
3337 	int error = 0;
3338 	int rv;
3339 
3340 	STRUCT_INIT(set_pin, mode);
3341 
3342 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3343 		cmn_err(CE_WARN, "set_pin: failed holding minor");
3344 		return (ENXIO);
3345 	}
3346 
3347 	if (copyin(arg, STRUCT_BUF(set_pin),
3348 	    STRUCT_SIZE(set_pin)) != 0) {
3349 		crypto_release_minor(cm);
3350 		return (EFAULT);
3351 	}
3352 
3353 	old_pin_len = STRUCT_FGET(set_pin, sp_old_len);
3354 
3355 	if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin),
3356 	    &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session),
3357 	    &sp, &rv, &error) != 0)
3358 		goto release_minor;
3359 
3360 	new_pin_len = STRUCT_FGET(set_pin, sp_new_len);
3361 	if (new_pin_len > KCF_MAX_PIN_LEN) {
3362 		rv = CRYPTO_PIN_LEN_RANGE;
3363 		goto out;
3364 	}
3365 	new_pin = kmem_alloc(new_pin_len, KM_SLEEP);
3366 
3367 	if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin),
3368 	    new_pin, new_pin_len) != 0) {
3369 		error = EFAULT;
3370 		goto out;
3371 	}
3372 
3373 	if ((rv = kcf_get_hardware_provider_nomech(
3374 	    CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin),
3375 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
3376 	    != CRYPTO_SUCCESS) {
3377 		goto out;
3378 	}
3379 
3380 	KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_SETPIN,
3381 	    sp->sd_provider_session->ps_session, old_pin, old_pin_len,
3382 	    new_pin, new_pin_len, NULL, NULL, real_provider);
3383 
3384 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3385 	KCF_PROV_REFRELE(real_provider);
3386 
3387 out:
3388 	CRYPTO_SESSION_RELE(sp);
3389 
3390 release_minor:
3391 	crypto_release_minor(cm);
3392 
3393 	if (old_pin != NULL) {
3394 		bzero(old_pin, old_pin_len);
3395 		kmem_free(old_pin, old_pin_len);
3396 	}
3397 
3398 	if (new_pin != NULL) {
3399 		bzero(new_pin, new_pin_len);
3400 		kmem_free(new_pin, new_pin_len);
3401 	}
3402 
3403 	if (error != 0)
3404 		return (error);
3405 
3406 	STRUCT_FSET(set_pin, sp_return_value, rv);
3407 	if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) {
3408 		return (EFAULT);
3409 	}
3410 	return (0);
3411 }
3412 
3413 /* ARGSUSED */
3414 static int
3415 login(dev_t dev, caddr_t arg, int mode, int *rval)
3416 {
3417 	STRUCT_DECL(crypto_login, login);
3418 	kcf_provider_desc_t *real_provider;
3419 	kcf_req_params_t params;
3420 	crypto_minor_t *cm;
3421 	crypto_session_data_t *sp;
3422 	size_t pin_len;
3423 	char *pin;
3424 	uint_t user_type;
3425 	int error = 0;
3426 	int rv;
3427 
3428 	STRUCT_INIT(login, mode);
3429 
3430 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3431 		cmn_err(CE_WARN, "login: failed holding minor");
3432 		return (ENXIO);
3433 	}
3434 
3435 	if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) {
3436 		crypto_release_minor(cm);
3437 		return (EFAULT);
3438 	}
3439 
3440 	user_type = STRUCT_FGET(login, co_user_type);
3441 
3442 	pin_len = STRUCT_FGET(login, co_pin_len);
3443 
3444 	if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin),
3445 	    &pin, pin_len, cm, STRUCT_FGET(login, co_session),
3446 	    &sp, &rv, &error) != 0) {
3447 		if (rv == CRYPTO_PIN_LEN_RANGE)
3448 			rv = CRYPTO_PIN_INCORRECT;
3449 		goto release_minor;
3450 	}
3451 
3452 	if ((rv = kcf_get_hardware_provider_nomech(
3453 	    CRYPTO_OPS_OFFSET(session_ops),
3454 	    CRYPTO_SESSION_OFFSET(session_login),
3455 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
3456 	    != CRYPTO_SUCCESS) {
3457 		goto out;
3458 	}
3459 
3460 	KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGIN, NULL,
3461 	    sp->sd_provider_session->ps_session, user_type, pin, pin_len,
3462 	    real_provider);
3463 
3464 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3465 	KCF_PROV_REFRELE(real_provider);
3466 
3467 out:
3468 	CRYPTO_SESSION_RELE(sp);
3469 
3470 release_minor:
3471 	crypto_release_minor(cm);
3472 
3473 	if (pin != NULL) {
3474 		bzero(pin, pin_len);
3475 		kmem_free(pin, pin_len);
3476 	}
3477 
3478 	if (error != 0)
3479 		return (error);
3480 
3481 	STRUCT_FSET(login, co_return_value, rv);
3482 	if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) {
3483 		return (EFAULT);
3484 	}
3485 	return (0);
3486 }
3487 
3488 /* ARGSUSED */
3489 static int
3490 logout(dev_t dev, caddr_t arg, int mode, int *rval)
3491 {
3492 	crypto_logout_t logout;
3493 	kcf_provider_desc_t *real_provider;
3494 	kcf_req_params_t params;
3495 	crypto_minor_t *cm;
3496 	crypto_session_data_t *sp;
3497 	int error = 0;
3498 	int rv;
3499 
3500 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3501 		cmn_err(CE_WARN, "logout: failed holding minor");
3502 		return (ENXIO);
3503 	}
3504 
3505 	if (copyin(arg, &logout, sizeof (logout)) != 0) {
3506 		crypto_release_minor(cm);
3507 		return (EFAULT);
3508 	}
3509 
3510 	if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv))  {
3511 		goto release_minor;
3512 	}
3513 
3514 	if ((rv = kcf_get_hardware_provider_nomech(
3515 	    CRYPTO_OPS_OFFSET(session_ops),
3516 	    CRYPTO_SESSION_OFFSET(session_logout), CHECK_RESTRICT_FALSE,
3517 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
3518 		goto out;
3519 	}
3520 
3521 	KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGOUT, NULL,
3522 	    sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider);
3523 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3524 	KCF_PROV_REFRELE(real_provider);
3525 
3526 out:
3527 	CRYPTO_SESSION_RELE(sp);
3528 
3529 release_minor:
3530 	crypto_release_minor(cm);
3531 
3532 	if (error != 0)
3533 		return (error);
3534 
3535 	logout.cl_return_value = rv;
3536 	if (copyout(&logout, arg, sizeof (logout)) != 0) {
3537 		return (EFAULT);
3538 	}
3539 	return (0);
3540 }
3541 
3542 /* ARGSUSED */
3543 static int
3544 sign_init(dev_t dev, caddr_t arg, int mode, int *rval)
3545 {
3546 	return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov));
3547 }
3548 
3549 /* ARGSUSED */
3550 static int
3551 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3552 {
3553 	return (sign_verify_init(dev, arg, mode,
3554 	    crypto_sign_recover_init_prov));
3555 }
3556 
3557 /* ARGSUSED */
3558 static int
3559 verify_init(dev_t dev, caddr_t arg, int mode, int *rval)
3560 {
3561 	return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov));
3562 }
3563 
3564 /* ARGSUSED */
3565 static int
3566 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3567 {
3568 	return (sign_verify_init(dev, arg, mode,
3569 	    crypto_verify_recover_init_prov));
3570 }
3571 
3572 /*
3573  * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init,
3574  * and crypto_verify_recover_init structures are identical
3575  * except for field names.
3576  */
3577 static int
3578 sign_verify_init(dev_t dev, caddr_t arg, int mode,
3579     int (*init)(crypto_provider_t, crypto_session_id_t,
3580     crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t,
3581     crypto_context_t *, crypto_call_req_t *))
3582 {
3583 	STRUCT_DECL(crypto_sign_init, sign_init);
3584 	kproject_t *mech_projp, *key_projp;
3585 	kcf_provider_desc_t *real_provider = NULL;
3586 	crypto_session_id_t session_id;
3587 	crypto_mechanism_t mech;
3588 	crypto_key_t key;
3589 	crypto_minor_t *cm;
3590 	crypto_session_data_t *sp;
3591 	crypto_context_t cc;
3592 	crypto_ctx_t **ctxpp;
3593 	size_t mech_rctl_bytes = 0;
3594 	size_t key_rctl_bytes = 0;
3595 	size_t carry;
3596 	int error = 0;
3597 	int rv;
3598 	boolean_t allocated_by_crypto_module = B_FALSE;
3599 	crypto_func_group_t fg;
3600 
3601 	STRUCT_INIT(sign_init, mode);
3602 
3603 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3604 		cmn_err(CE_WARN, "sign_verify_init: failed holding minor");
3605 		return (ENXIO);
3606 	}
3607 
3608 	if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) {
3609 		crypto_release_minor(cm);
3610 		return (EFAULT);
3611 	}
3612 
3613 	mech.cm_param = NULL;
3614 	bzero(&key, sizeof (key));
3615 
3616 	session_id = STRUCT_FGET(sign_init, si_session);
3617 
3618 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3619 		goto release_minor;
3620 	}
3621 
3622 	bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type,
3623 	    sizeof (crypto_mech_type_t));
3624 
3625 	ASSERT(init == crypto_sign_init_prov ||
3626 	    init == crypto_verify_init_prov ||
3627 	    init == crypto_sign_recover_init_prov ||
3628 	    init == crypto_verify_recover_init_prov);
3629 
3630 	if (init == crypto_sign_init_prov) {
3631 		fg =  CRYPTO_FG_SIGN;
3632 		ctxpp = &sp->sd_sign_ctx;
3633 	} else if (init == crypto_verify_init_prov) {
3634 		fg =  CRYPTO_FG_VERIFY;
3635 		ctxpp = &sp->sd_verify_ctx;
3636 	} else if (init == crypto_sign_recover_init_prov) {
3637 		fg =  CRYPTO_FG_SIGN_RECOVER;
3638 		ctxpp = &sp->sd_sign_recover_ctx;
3639 	} else {
3640 		fg =  CRYPTO_FG_VERIFY_RECOVER;
3641 		ctxpp = &sp->sd_verify_recover_ctx;
3642 	}
3643 
3644 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
3645 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, fg))
3646 	    != CRYPTO_SUCCESS) {
3647 		goto out;
3648 	}
3649 
3650 	carry = 0;
3651 	rv = crypto_provider_copyin_mech_param(real_provider,
3652 	    STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error);
3653 
3654 	if (rv == CRYPTO_NOT_SUPPORTED) {
3655 		allocated_by_crypto_module = B_TRUE;
3656 		if (!copyin_mech(mode, STRUCT_FADDR(sign_init, si_mech),
3657 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
3658 		    &mech_projp)) {
3659 			goto out;
3660 		}
3661 	} else {
3662 		if (rv != CRYPTO_SUCCESS)
3663 			goto out;
3664 	}
3665 
3666 	if (!copyin_key(mode, STRUCT_FADDR(sign_init, si_key), &key,
3667 	    &key_rctl_bytes, &rv, &error, carry, &key_projp)) {
3668 		goto out;
3669 	}
3670 
3671 	rv = (init)(real_provider, sp->sd_provider_session->ps_session,
3672 	    &mech, &key, NULL, &cc, NULL);
3673 
3674 	/*
3675 	 * Check if a context already exists. If so, it means it is being
3676 	 * abandoned. So, cancel it to avoid leaking it.
3677 	 */
3678 	if (*ctxpp != NULL)
3679 		CRYPTO_CANCEL_CTX(ctxpp);
3680 	*ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
3681 
3682 out:
3683 	CRYPTO_SESSION_RELE(sp);
3684 
3685 release_minor:
3686 	mutex_enter(&crypto_rctl_lock);
3687 	if (mech_rctl_bytes != 0)
3688 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
3689 	if (key_rctl_bytes != 0)
3690 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
3691 	mutex_exit(&crypto_rctl_lock);
3692 	crypto_release_minor(cm);
3693 
3694 	if (real_provider != NULL) {
3695 		crypto_free_mech(real_provider,
3696 		    allocated_by_crypto_module, &mech);
3697 		KCF_PROV_REFRELE(real_provider);
3698 	}
3699 
3700 	free_crypto_key(&key);
3701 
3702 	if (error != 0)
3703 		return (error);
3704 
3705 	STRUCT_FSET(sign_init, si_return_value, rv);
3706 	if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) {
3707 		return (EFAULT);
3708 	}
3709 	return (0);
3710 }
3711 
3712 /* ARGSUSED */
3713 static int
3714 sign(dev_t dev, caddr_t arg, int mode, int *rval)
3715 {
3716 	return (common_digest(dev, arg, mode, crypto_sign_single));
3717 }
3718 
3719 /* ARGSUSED */
3720 static int
3721 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval)
3722 {
3723 	return (common_digest(dev, arg, mode, crypto_sign_recover_single));
3724 }
3725 
3726 /* ARGSUSED */
3727 static int
3728 verify(dev_t dev, caddr_t arg, int mode, int *rval)
3729 {
3730 	STRUCT_DECL(crypto_verify, verify);
3731 	kproject_t *projp;
3732 	crypto_session_id_t session_id;
3733 	crypto_minor_t *cm;
3734 	crypto_session_data_t *sp;
3735 	crypto_data_t data, sign;
3736 	size_t datalen, signlen, need = 0;
3737 	int error = 0;
3738 	int rv;
3739 
3740 	STRUCT_INIT(verify, mode);
3741 
3742 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3743 		cmn_err(CE_WARN, "verify: failed holding minor");
3744 		return (ENXIO);
3745 	}
3746 
3747 	if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) {
3748 		crypto_release_minor(cm);
3749 		return (EFAULT);
3750 	}
3751 
3752 	data.cd_raw.iov_base = NULL;
3753 	sign.cd_raw.iov_base = NULL;
3754 
3755 	datalen = STRUCT_FGET(verify, cv_datalen);
3756 	signlen = STRUCT_FGET(verify, cv_signlen);
3757 	if (datalen > crypto_max_buffer_len ||
3758 	    signlen > crypto_max_buffer_len) {
3759 		cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, "
3760 		"pid = %d", crypto_max_buffer_len, curproc->p_pid);
3761 		rv = CRYPTO_ARGUMENTS_BAD;
3762 		goto release_minor;
3763 	}
3764 
3765 	need = datalen + signlen;
3766 	if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) {
3767 		need = 0;
3768 		goto release_minor;
3769 	}
3770 
3771 	INIT_RAW_CRYPTO_DATA(data, datalen);
3772 	INIT_RAW_CRYPTO_DATA(sign, signlen);
3773 
3774 	if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf),
3775 	    data.cd_raw.iov_base, datalen) != 0) {
3776 		error = EFAULT;
3777 		goto release_minor;
3778 	}
3779 
3780 	if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf),
3781 	    sign.cd_raw.iov_base, signlen) != 0) {
3782 		error = EFAULT;
3783 		goto release_minor;
3784 	}
3785 	session_id = STRUCT_FGET(verify, cv_session);
3786 
3787 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3788 		goto release_minor;
3789 	}
3790 
3791 	rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL);
3792 	if (KCF_CONTEXT_DONE(rv))
3793 		sp->sd_verify_ctx = NULL;
3794 
3795 	CRYPTO_SESSION_RELE(sp);
3796 
3797 release_minor:
3798 	if (need != 0) {
3799 		mutex_enter(&crypto_rctl_lock);
3800 		CRYPTO_DECREMENT_RCTL(need, projp);
3801 		mutex_exit(&crypto_rctl_lock);
3802 	}
3803 	crypto_release_minor(cm);
3804 
3805 	if (data.cd_raw.iov_base != NULL)
3806 		kmem_free(data.cd_raw.iov_base, datalen);
3807 
3808 	if (sign.cd_raw.iov_base != NULL)
3809 		kmem_free(sign.cd_raw.iov_base, signlen);
3810 
3811 	if (error != 0)
3812 		return (error);
3813 
3814 	STRUCT_FSET(verify, cv_return_value, rv);
3815 	if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) {
3816 		return (EFAULT);
3817 	}
3818 	return (0);
3819 }
3820 
3821 /* ARGSUSED */
3822 static int
3823 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval)
3824 {
3825 	return (common_digest(dev, arg, mode, crypto_verify_recover_single));
3826 }
3827 
3828 /* ARGSUSED */
3829 static int
3830 sign_update(dev_t dev, caddr_t arg, int mode, int *rval)
3831 {
3832 	return (sign_verify_update(dev, arg, mode, crypto_sign_update));
3833 }
3834 
3835 /* ARGSUSED */
3836 static int
3837 verify_update(dev_t dev, caddr_t arg, int mode, int *rval)
3838 {
3839 	return (sign_verify_update(dev, arg, mode, crypto_verify_update));
3840 }
3841 
3842 /*
3843  * ASSUMPTION: crypto_sign_update and crypto_verify_update structures
3844  * are identical except for field names.
3845  */
3846 static int
3847 sign_verify_update(dev_t dev, caddr_t arg, int mode,
3848     int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
3849 {
3850 	STRUCT_DECL(crypto_sign_update, sign_update);
3851 	kproject_t *projp;
3852 	crypto_session_id_t session_id;
3853 	crypto_minor_t *cm;
3854 	crypto_session_data_t *sp;
3855 	crypto_ctx_t **ctxpp;
3856 	crypto_data_t data;
3857 	size_t datalen, need = 0;
3858 	int error = 0;
3859 	int rv;
3860 
3861 	STRUCT_INIT(sign_update, mode);
3862 
3863 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3864 		cmn_err(CE_WARN, "sign_verify_update: failed holding minor");
3865 		return (ENXIO);
3866 	}
3867 
3868 	if (copyin(arg, STRUCT_BUF(sign_update),
3869 	    STRUCT_SIZE(sign_update)) != 0) {
3870 		crypto_release_minor(cm);
3871 		return (EFAULT);
3872 	}
3873 
3874 	data.cd_raw.iov_base = NULL;
3875 
3876 	datalen = STRUCT_FGET(sign_update, su_datalen);
3877 	if (datalen > crypto_max_buffer_len) {
3878 		cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld "
3879 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3880 		rv = CRYPTO_ARGUMENTS_BAD;
3881 		goto release_minor;
3882 	}
3883 
3884 	if ((rv = crypto_buffer_check(datalen, &projp)) != CRYPTO_SUCCESS) {
3885 		goto release_minor;
3886 	}
3887 	need = datalen;
3888 
3889 	INIT_RAW_CRYPTO_DATA(data, datalen);
3890 
3891 	if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf),
3892 	    data.cd_raw.iov_base, datalen) != 0) {
3893 		error = EFAULT;
3894 		goto release_minor;
3895 	}
3896 
3897 	session_id = STRUCT_FGET(sign_update, su_session);
3898 
3899 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3900 		goto release_minor;
3901 	}
3902 
3903 	ctxpp = (update == crypto_sign_update) ?
3904 	    &sp->sd_sign_ctx : &sp->sd_verify_ctx;
3905 
3906 	rv = (update)(*ctxpp, &data, NULL);
3907 	if (rv != CRYPTO_SUCCESS)
3908 		CRYPTO_CANCEL_CTX(ctxpp);
3909 	CRYPTO_SESSION_RELE(sp);
3910 
3911 release_minor:
3912 	if (need != 0) {
3913 		mutex_enter(&crypto_rctl_lock);
3914 		CRYPTO_DECREMENT_RCTL(need, projp);
3915 		mutex_exit(&crypto_rctl_lock);
3916 	}
3917 	crypto_release_minor(cm);
3918 
3919 	if (data.cd_raw.iov_base != NULL)
3920 		kmem_free(data.cd_raw.iov_base, datalen);
3921 
3922 	if (error != 0)
3923 		return (error);
3924 
3925 	STRUCT_FSET(sign_update, su_return_value, rv);
3926 	if (copyout(STRUCT_BUF(sign_update), arg,
3927 	    STRUCT_SIZE(sign_update)) != 0) {
3928 		return (EFAULT);
3929 	}
3930 	return (0);
3931 }
3932 
3933 /* ARGSUSED */
3934 static int
3935 sign_final(dev_t dev, caddr_t arg, int mode, int *rval)
3936 {
3937 	return (common_final(dev, arg, mode, crypto_sign_final));
3938 }
3939 
3940 /*
3941  * Can't use the common final because it does a copyout of
3942  * the final part.
3943  */
3944 /* ARGSUSED */
3945 static int
3946 verify_final(dev_t dev, caddr_t arg, int mode, int *rval)
3947 {
3948 	STRUCT_DECL(crypto_verify_final, verify_final);
3949 	kproject_t *projp;
3950 	crypto_session_id_t session_id;
3951 	crypto_minor_t *cm;
3952 	crypto_session_data_t *sp;
3953 	crypto_data_t sign;
3954 	size_t signlen, need = 0;
3955 	int error = 0;
3956 	int rv;
3957 
3958 	STRUCT_INIT(verify_final, mode);
3959 
3960 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3961 		cmn_err(CE_WARN, "verify_final: failed holding minor");
3962 		return (ENXIO);
3963 	}
3964 
3965 	if (copyin(arg, STRUCT_BUF(verify_final),
3966 	    STRUCT_SIZE(verify_final)) != 0) {
3967 		crypto_release_minor(cm);
3968 		return (EFAULT);
3969 	}
3970 
3971 	sign.cd_raw.iov_base = NULL;
3972 
3973 	signlen = STRUCT_FGET(verify_final, vf_signlen);
3974 	if (signlen > crypto_max_buffer_len) {
3975 		cmn_err(CE_NOTE, "verify_final: buffer greater than %ld "
3976 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3977 		rv = CRYPTO_ARGUMENTS_BAD;
3978 		goto release_minor;
3979 	}
3980 
3981 	if ((rv = crypto_buffer_check(signlen, &projp)) != CRYPTO_SUCCESS) {
3982 		goto release_minor;
3983 	}
3984 	need = signlen;
3985 
3986 	INIT_RAW_CRYPTO_DATA(sign, signlen);
3987 
3988 	if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf),
3989 	    sign.cd_raw.iov_base, signlen) != 0) {
3990 		error = EFAULT;
3991 		goto release_minor;
3992 	}
3993 
3994 	session_id = STRUCT_FGET(verify_final, vf_session);
3995 
3996 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3997 		goto release_minor;
3998 	}
3999 
4000 	rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL);
4001 	if (KCF_CONTEXT_DONE(rv))
4002 		sp->sd_verify_ctx = NULL;
4003 
4004 	CRYPTO_SESSION_RELE(sp);
4005 
4006 release_minor:
4007 	if (need != 0) {
4008 		mutex_enter(&crypto_rctl_lock);
4009 		CRYPTO_DECREMENT_RCTL(need, projp);
4010 		mutex_exit(&crypto_rctl_lock);
4011 	}
4012 	crypto_release_minor(cm);
4013 
4014 	if (sign.cd_raw.iov_base != NULL)
4015 		kmem_free(sign.cd_raw.iov_base, signlen);
4016 
4017 	if (error != 0)
4018 		return (error);
4019 
4020 	STRUCT_FSET(verify_final, vf_return_value, rv);
4021 	if (copyout(STRUCT_BUF(verify_final), arg,
4022 	    STRUCT_SIZE(verify_final)) != 0) {
4023 		return (EFAULT);
4024 	}
4025 	return (0);
4026 }
4027 
4028 /* ARGSUSED */
4029 static int
4030 seed_random(dev_t dev, caddr_t arg, int mode, int *rval)
4031 {
4032 	STRUCT_DECL(crypto_seed_random, seed_random);
4033 	kproject_t *projp;
4034 	kcf_provider_desc_t *real_provider = NULL;
4035 	kcf_req_params_t params;
4036 	crypto_session_id_t session_id;
4037 	crypto_minor_t *cm;
4038 	crypto_session_data_t *sp;
4039 	uchar_t *seed_buffer = NULL;
4040 	size_t seed_len;
4041 	size_t need = 0;
4042 	int error = 0;
4043 	int rv;
4044 
4045 	STRUCT_INIT(seed_random, mode);
4046 
4047 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4048 		cmn_err(CE_WARN, "seed_random: failed holding minor");
4049 		return (ENXIO);
4050 	}
4051 
4052 	if (copyin(arg, STRUCT_BUF(seed_random),
4053 	    STRUCT_SIZE(seed_random)) != 0) {
4054 		crypto_release_minor(cm);
4055 		return (EFAULT);
4056 	}
4057 
4058 	seed_len = STRUCT_FGET(seed_random, sr_seedlen);
4059 	if (seed_len > crypto_max_buffer_len) {
4060 		cmn_err(CE_NOTE, "seed_random: buffer greater than %ld "
4061 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4062 		rv = CRYPTO_ARGUMENTS_BAD;
4063 		goto release_minor;
4064 	}
4065 
4066 	if ((rv = crypto_buffer_check(seed_len, &projp)) != CRYPTO_SUCCESS) {
4067 		goto release_minor;
4068 	}
4069 	need = seed_len;
4070 	seed_buffer = kmem_alloc(seed_len, KM_SLEEP);
4071 
4072 	if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf),
4073 	    seed_buffer, seed_len) != 0) {
4074 		error = EFAULT;
4075 		goto release_minor;
4076 	}
4077 
4078 	session_id = STRUCT_FGET(seed_random, sr_session);
4079 
4080 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4081 		goto release_minor;
4082 	}
4083 
4084 	if ((rv = kcf_get_hardware_provider_nomech(
4085 	    CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random),
4086 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4087 	    != CRYPTO_SUCCESS) {
4088 		goto out;
4089 	}
4090 
4091 	KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_SEED,
4092 	    sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0,
4093 	    CRYPTO_SEED_NOW);
4094 
4095 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4096 
4097 out:
4098 	CRYPTO_SESSION_RELE(sp);
4099 
4100 release_minor:
4101 	if (need != 0) {
4102 		mutex_enter(&crypto_rctl_lock);
4103 		CRYPTO_DECREMENT_RCTL(need, projp);
4104 		mutex_exit(&crypto_rctl_lock);
4105 	}
4106 	crypto_release_minor(cm);
4107 
4108 	if (real_provider != NULL)
4109 		KCF_PROV_REFRELE(real_provider);
4110 
4111 	if (seed_buffer != NULL)
4112 		kmem_free(seed_buffer, seed_len);
4113 
4114 	if (error != 0)
4115 		return (error);
4116 
4117 	STRUCT_FSET(seed_random, sr_return_value, rv);
4118 	if (copyout(STRUCT_BUF(seed_random), arg,
4119 	    STRUCT_SIZE(seed_random)) != 0) {
4120 		return (EFAULT);
4121 	}
4122 	return (0);
4123 }
4124 
4125 /* ARGSUSED */
4126 static int
4127 generate_random(dev_t dev, caddr_t arg, int mode, int *rval)
4128 {
4129 	STRUCT_DECL(crypto_generate_random, generate_random);
4130 	kproject_t *projp;
4131 	kcf_provider_desc_t *real_provider = NULL;
4132 	kcf_req_params_t params;
4133 	crypto_session_id_t session_id;
4134 	crypto_minor_t *cm;
4135 	crypto_session_data_t *sp;
4136 	uchar_t *buffer = NULL;
4137 	size_t len;
4138 	size_t need = 0;
4139 	int error = 0;
4140 	int rv;
4141 
4142 	STRUCT_INIT(generate_random, mode);
4143 
4144 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4145 		cmn_err(CE_WARN, "generate_random: failed holding minor");
4146 		return (ENXIO);
4147 	}
4148 
4149 	if (copyin(arg, STRUCT_BUF(generate_random),
4150 	    STRUCT_SIZE(generate_random)) != 0) {
4151 		crypto_release_minor(cm);
4152 		return (EFAULT);
4153 	}
4154 
4155 	len = STRUCT_FGET(generate_random, gr_buflen);
4156 	if (len > crypto_max_buffer_len) {
4157 		cmn_err(CE_NOTE, "generate_random: buffer greater than %ld "
4158 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4159 		rv = CRYPTO_ARGUMENTS_BAD;
4160 		goto release_minor;
4161 	}
4162 
4163 	if ((rv = crypto_buffer_check(len, &projp)) != CRYPTO_SUCCESS) {
4164 		goto release_minor;
4165 	}
4166 	need = len;
4167 	buffer = kmem_alloc(len, KM_SLEEP);
4168 
4169 	session_id = STRUCT_FGET(generate_random, gr_session);
4170 
4171 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4172 		goto release_minor;
4173 	}
4174 
4175 	if ((rv = kcf_get_hardware_provider_nomech(
4176 	    CRYPTO_OPS_OFFSET(random_ops),
4177 	    CRYPTO_RANDOM_OFFSET(generate_random), CHECK_RESTRICT_FALSE,
4178 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4179 		goto out;
4180 	}
4181 
4182 	KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_GENERATE,
4183 	    sp->sd_provider_session->ps_session, buffer, len, 0, 0);
4184 
4185 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4186 
4187 out:
4188 	CRYPTO_SESSION_RELE(sp);
4189 
4190 	if (rv == CRYPTO_SUCCESS) {
4191 		if (len != 0 && copyout(buffer,
4192 		    STRUCT_FGETP(generate_random, gr_buf), len) != 0) {
4193 			error = EFAULT;
4194 		}
4195 	}
4196 
4197 release_minor:
4198 	if (need != 0) {
4199 		mutex_enter(&crypto_rctl_lock);
4200 		CRYPTO_DECREMENT_RCTL(need, projp);
4201 		mutex_exit(&crypto_rctl_lock);
4202 	}
4203 	crypto_release_minor(cm);
4204 
4205 	if (real_provider != NULL)
4206 		KCF_PROV_REFRELE(real_provider);
4207 
4208 	if (buffer != NULL) {
4209 		/* random numbers are often used to create keys */
4210 		bzero(buffer, len);
4211 		kmem_free(buffer, len);
4212 	}
4213 
4214 	if (error != 0)
4215 		return (error);
4216 
4217 	STRUCT_FSET(generate_random, gr_return_value, rv);
4218 	if (copyout(STRUCT_BUF(generate_random), arg,
4219 	    STRUCT_SIZE(generate_random)) != 0) {
4220 		return (EFAULT);
4221 	}
4222 	return (0);
4223 }
4224 
4225 /*
4226  * Copyout a kernel array of attributes to user space.
4227  * u_attrs is the corresponding user space array containing
4228  * user space pointers necessary for the copyout.
4229  */
4230 /* ARGSUSED */
4231 static int
4232 copyout_attributes(int mode, caddr_t out, uint_t count,
4233     crypto_object_attribute_t *k_attrs, caddr_t u_attrs)
4234 {
4235 	STRUCT_DECL(crypto_object_attribute, oa);
4236 	caddr_t p, valuep;
4237 	size_t value_len;
4238 	size_t len;
4239 	int i;
4240 	int error = 0;
4241 
4242 	if (count == 0)
4243 		return (0);
4244 
4245 	STRUCT_INIT(oa, mode);
4246 
4247 	len = count * STRUCT_SIZE(oa);
4248 
4249 	ASSERT(u_attrs != NULL);
4250 	p = u_attrs;
4251 	for (i = 0; i < count; i++) {
4252 		/* can this bcopy be eliminated? */
4253 		bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa));
4254 		value_len = k_attrs[i].oa_value_len;
4255 		STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type);
4256 		STRUCT_FSET(oa, oa_value_len, value_len);
4257 		valuep = STRUCT_FGETP(oa, oa_value);
4258 		if (valuep != NULL && value_len != -1) {
4259 			if (copyout(k_attrs[i].oa_value,
4260 			    valuep, value_len) != 0) {
4261 				error = EFAULT;
4262 				goto out;
4263 			}
4264 		}
4265 		bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa));
4266 		p += STRUCT_SIZE(oa);
4267 	}
4268 	if (copyout(u_attrs, out, len)) {
4269 		error = EFAULT;
4270 	}
4271 out:
4272 	return (error);
4273 }
4274 
4275 
4276 /* ARGSUSED */
4277 static int
4278 object_create(dev_t dev, caddr_t arg, int mode, int *rval)
4279 {
4280 	STRUCT_DECL(crypto_object_create, object_create);
4281 	kproject_t *projp;
4282 	kcf_provider_desc_t *real_provider = NULL;
4283 	kcf_req_params_t params;
4284 	crypto_object_attribute_t *k_attrs = NULL;
4285 	crypto_session_id_t session_id;
4286 	crypto_minor_t *cm;
4287 	crypto_session_data_t *sp = NULL;
4288 	crypto_object_id_t object_handle;
4289 	caddr_t oc_attributes;
4290 	size_t k_attrs_size;
4291 	size_t rctl_bytes = 0;
4292 	int error = 0;
4293 	int rv;
4294 	uint_t count;
4295 
4296 	STRUCT_INIT(object_create, mode);
4297 
4298 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4299 		cmn_err(CE_WARN, "object_create: failed holding minor");
4300 		return (ENXIO);
4301 	}
4302 
4303 	if (copyin(arg, STRUCT_BUF(object_create),
4304 	    STRUCT_SIZE(object_create)) != 0) {
4305 		crypto_release_minor(cm);
4306 		return (EFAULT);
4307 	}
4308 
4309 	count = STRUCT_FGET(object_create, oc_count);
4310 	oc_attributes = STRUCT_FGETP(object_create, oc_attributes);
4311 	if (!copyin_attributes(mode, count, oc_attributes, &k_attrs,
4312 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4313 		goto release_minor;
4314 	}
4315 
4316 	session_id = STRUCT_FGET(object_create, oc_session);
4317 
4318 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4319 		goto release_minor;
4320 	}
4321 
4322 	if ((rv = kcf_get_hardware_provider_nomech(
4323 	    CRYPTO_OPS_OFFSET(object_ops),
4324 	    CRYPTO_OBJECT_OFFSET(object_create),
4325 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4326 	    != CRYPTO_SUCCESS) {
4327 		goto release_minor;
4328 	}
4329 
4330 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_CREATE,
4331 	    sp->sd_provider_session->ps_session, 0, k_attrs, count,
4332 	    &object_handle, 0, NULL, NULL, 0, NULL);
4333 
4334 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4335 
4336 	if (rv == CRYPTO_SUCCESS)
4337 		STRUCT_FSET(object_create, oc_handle, object_handle);
4338 
4339 release_minor:
4340 	if (rctl_bytes != 0) {
4341 		mutex_enter(&crypto_rctl_lock);
4342 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4343 		mutex_exit(&crypto_rctl_lock);
4344 	}
4345 
4346 	if (k_attrs != NULL)
4347 		kmem_free(k_attrs, k_attrs_size);
4348 
4349 	if (error != 0)
4350 		goto out;
4351 
4352 	STRUCT_FSET(object_create, oc_return_value, rv);
4353 	if (copyout(STRUCT_BUF(object_create), arg,
4354 	    STRUCT_SIZE(object_create)) != 0) {
4355 		if (rv == CRYPTO_SUCCESS) {
4356 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4357 			    KCF_OP_OBJECT_DESTROY,
4358 			    sp->sd_provider_session->ps_session, object_handle,
4359 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4360 
4361 			(void) kcf_submit_request(real_provider, NULL,
4362 			    NULL, &params, B_FALSE);
4363 
4364 			error = EFAULT;
4365 		}
4366 	}
4367 out:
4368 	if (sp != NULL)
4369 		CRYPTO_SESSION_RELE(sp);
4370 	crypto_release_minor(cm);
4371 	if (real_provider != NULL)
4372 		KCF_PROV_REFRELE(real_provider);
4373 	return (error);
4374 }
4375 
4376 /* ARGSUSED */
4377 static int
4378 object_copy(dev_t dev, caddr_t arg, int mode, int *rval)
4379 {
4380 	STRUCT_DECL(crypto_object_copy, object_copy);
4381 	kproject_t *projp;
4382 	kcf_provider_desc_t *real_provider = NULL;
4383 	kcf_req_params_t params;
4384 	crypto_object_attribute_t *k_attrs = NULL;
4385 	crypto_session_id_t session_id;
4386 	crypto_minor_t *cm;
4387 	crypto_session_data_t *sp = NULL;
4388 	crypto_object_id_t handle, new_handle;
4389 	caddr_t oc_new_attributes;
4390 	size_t k_attrs_size;
4391 	size_t rctl_bytes = 0;
4392 	int error = 0;
4393 	int rv;
4394 	uint_t count;
4395 
4396 	STRUCT_INIT(object_copy, mode);
4397 
4398 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4399 		cmn_err(CE_WARN, "object_copy: failed holding minor");
4400 		return (ENXIO);
4401 	}
4402 
4403 	if (copyin(arg, STRUCT_BUF(object_copy),
4404 	    STRUCT_SIZE(object_copy)) != 0) {
4405 		crypto_release_minor(cm);
4406 		return (EFAULT);
4407 	}
4408 
4409 	count = STRUCT_FGET(object_copy, oc_count);
4410 	oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes);
4411 	if (!copyin_attributes(mode, count, oc_new_attributes, &k_attrs,
4412 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4413 		goto release_minor;
4414 	}
4415 
4416 	session_id = STRUCT_FGET(object_copy, oc_session);
4417 
4418 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4419 		goto release_minor;
4420 	}
4421 
4422 	if ((rv = kcf_get_hardware_provider_nomech(
4423 	    CRYPTO_OPS_OFFSET(object_ops),
4424 	    CRYPTO_OBJECT_OFFSET(object_copy), CHECK_RESTRICT_FALSE,
4425 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4426 		goto release_minor;
4427 	}
4428 
4429 	handle = STRUCT_FGET(object_copy, oc_handle);
4430 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_COPY,
4431 	    sp->sd_provider_session->ps_session, handle, k_attrs, count,
4432 	    &new_handle, 0, NULL, NULL, 0, NULL);
4433 
4434 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4435 
4436 	if (rv == CRYPTO_SUCCESS)
4437 		STRUCT_FSET(object_copy, oc_new_handle, new_handle);
4438 
4439 release_minor:
4440 	if (rctl_bytes != 0) {
4441 		mutex_enter(&crypto_rctl_lock);
4442 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4443 		mutex_exit(&crypto_rctl_lock);
4444 	}
4445 
4446 	if (k_attrs != NULL)
4447 		kmem_free(k_attrs, k_attrs_size);
4448 
4449 	if (error != 0)
4450 		goto out;
4451 
4452 	STRUCT_FSET(object_copy, oc_return_value, rv);
4453 	if (copyout(STRUCT_BUF(object_copy), arg,
4454 	    STRUCT_SIZE(object_copy)) != 0) {
4455 		if (rv == CRYPTO_SUCCESS) {
4456 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4457 			    KCF_OP_OBJECT_DESTROY,
4458 			    sp->sd_provider_session->ps_session, new_handle,
4459 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4460 
4461 			(void) kcf_submit_request(real_provider, NULL,
4462 			    NULL, &params, B_FALSE);
4463 
4464 			error = EFAULT;
4465 		}
4466 	}
4467 out:
4468 	if (sp != NULL)
4469 		CRYPTO_SESSION_RELE(sp);
4470 	crypto_release_minor(cm);
4471 	if (real_provider != NULL)
4472 		KCF_PROV_REFRELE(real_provider);
4473 	return (error);
4474 }
4475 
4476 /* ARGSUSED */
4477 static int
4478 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval)
4479 {
4480 	STRUCT_DECL(crypto_object_destroy, object_destroy);
4481 	kcf_provider_desc_t *real_provider;
4482 	kcf_req_params_t params;
4483 	crypto_session_id_t session_id;
4484 	crypto_minor_t *cm;
4485 	crypto_session_data_t *sp;
4486 	crypto_object_id_t handle;
4487 	int error = 0;
4488 	int rv;
4489 
4490 	STRUCT_INIT(object_destroy, mode);
4491 
4492 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4493 		cmn_err(CE_WARN, "object_destroy: failed holding minor");
4494 		return (ENXIO);
4495 	}
4496 
4497 	if (copyin(arg, STRUCT_BUF(object_destroy),
4498 	    STRUCT_SIZE(object_destroy)) != 0) {
4499 		crypto_release_minor(cm);
4500 		return (EFAULT);
4501 	}
4502 
4503 	session_id = STRUCT_FGET(object_destroy, od_session);
4504 
4505 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4506 		goto release_minor;
4507 	}
4508 
4509 	if ((rv = kcf_get_hardware_provider_nomech(
4510 	    CRYPTO_OPS_OFFSET(object_ops),
4511 	    CRYPTO_OBJECT_OFFSET(object_destroy), CHECK_RESTRICT_FALSE,
4512 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4513 		goto out;
4514 	}
4515 
4516 	handle = STRUCT_FGET(object_destroy, od_handle);
4517 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
4518 	    sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0,
4519 	    NULL, NULL, 0, NULL);
4520 
4521 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4522 	KCF_PROV_REFRELE(real_provider);
4523 
4524 out:
4525 	CRYPTO_SESSION_RELE(sp);
4526 
4527 release_minor:
4528 	crypto_release_minor(cm);
4529 
4530 	if (error != 0)
4531 		return (error);
4532 
4533 	STRUCT_FSET(object_destroy, od_return_value, rv);
4534 
4535 	if (copyout(STRUCT_BUF(object_destroy), arg,
4536 	    STRUCT_SIZE(object_destroy)) != 0) {
4537 		return (EFAULT);
4538 	}
4539 	return (0);
4540 }
4541 
4542 /* ARGSUSED */
4543 static int
4544 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4545 {
4546 	STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value);
4547 	/* LINTED E_FUNC_SET_NOT_USED */
4548 	STRUCT_DECL(crypto_object_attribute, oa);
4549 	kproject_t *projp;
4550 	kcf_provider_desc_t *real_provider;
4551 	kcf_req_params_t params;
4552 	crypto_object_attribute_t *k_attrs = NULL;
4553 	crypto_session_id_t session_id;
4554 	crypto_minor_t *cm;
4555 	crypto_session_data_t *sp;
4556 	crypto_object_id_t handle;
4557 	caddr_t og_attributes;
4558 	caddr_t u_attrs;
4559 	size_t k_attrs_size;
4560 	size_t rctl_bytes = 0;
4561 	int error = 0;
4562 	int rv;
4563 	uint_t count;
4564 
4565 	STRUCT_INIT(get_attribute_value, mode);
4566 	STRUCT_INIT(oa, mode);
4567 
4568 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4569 		cmn_err(CE_WARN,
4570 		    "object_get_attribute_value: failed holding minor");
4571 		return (ENXIO);
4572 	}
4573 
4574 	if (copyin(arg, STRUCT_BUF(get_attribute_value),
4575 	    STRUCT_SIZE(get_attribute_value)) != 0) {
4576 		crypto_release_minor(cm);
4577 		return (EFAULT);
4578 	}
4579 
4580 	count = STRUCT_FGET(get_attribute_value, og_count);
4581 	og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes);
4582 	if (!copyin_attributes(mode, count, og_attributes, &k_attrs,
4583 	    &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes, 0, B_FALSE,
4584 	    &projp)) {
4585 		goto release_minor;
4586 	}
4587 
4588 	session_id = STRUCT_FGET(get_attribute_value, og_session);
4589 
4590 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4591 		goto release_minor;
4592 	}
4593 
4594 	if ((rv = kcf_get_hardware_provider_nomech(
4595 	    CRYPTO_OPS_OFFSET(object_ops),
4596 	    CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
4597 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4598 	    != CRYPTO_SUCCESS) {
4599 		goto out;
4600 	}
4601 
4602 	handle = STRUCT_FGET(get_attribute_value, og_handle);
4603 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE,
4604 	    sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL,
4605 	    0, NULL, NULL, 0, NULL);
4606 
4607 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4608 	KCF_PROV_REFRELE(real_provider);
4609 
4610 out:
4611 	CRYPTO_SESSION_RELE(sp);
4612 
4613 	if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE ||
4614 	    rv == CRYPTO_ATTRIBUTE_TYPE_INVALID ||
4615 	    rv == CRYPTO_BUFFER_TOO_SMALL) {
4616 		error = copyout_attributes(mode,
4617 		    STRUCT_FGETP(get_attribute_value, og_attributes),
4618 		    count, k_attrs, u_attrs);
4619 	}
4620 
4621 release_minor:
4622 	if (rctl_bytes != 0) {
4623 		mutex_enter(&crypto_rctl_lock);
4624 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4625 		mutex_exit(&crypto_rctl_lock);
4626 	}
4627 	crypto_release_minor(cm);
4628 
4629 	if (k_attrs != NULL)
4630 		kmem_free(k_attrs, k_attrs_size);
4631 
4632 	if (u_attrs != NULL)
4633 		kmem_free(u_attrs, count * STRUCT_SIZE(oa));
4634 
4635 	if (error != 0)
4636 		return (error);
4637 
4638 	STRUCT_FSET(get_attribute_value, og_return_value, rv);
4639 	if (copyout(STRUCT_BUF(get_attribute_value), arg,
4640 	    STRUCT_SIZE(get_attribute_value)) != 0) {
4641 		return (EFAULT);
4642 	}
4643 	return (0);
4644 }
4645 
4646 /* ARGSUSED */
4647 static int
4648 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval)
4649 {
4650 	STRUCT_DECL(crypto_object_get_size, object_get_size);
4651 	kcf_provider_desc_t *real_provider;
4652 	kcf_req_params_t params;
4653 	crypto_session_id_t session_id;
4654 	crypto_minor_t *cm;
4655 	crypto_session_data_t *sp;
4656 	crypto_object_id_t handle;
4657 	size_t size;
4658 	int error = 0;
4659 	int rv;
4660 
4661 	STRUCT_INIT(object_get_size, mode);
4662 
4663 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4664 		cmn_err(CE_WARN, "object_get_size: failed holding minor");
4665 		return (ENXIO);
4666 	}
4667 
4668 	if (copyin(arg, STRUCT_BUF(object_get_size),
4669 	    STRUCT_SIZE(object_get_size)) != 0) {
4670 		crypto_release_minor(cm);
4671 		return (EFAULT);
4672 	}
4673 
4674 	session_id = STRUCT_FGET(object_get_size, gs_session);
4675 
4676 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4677 		goto release_minor;
4678 	}
4679 
4680 	if ((rv = kcf_get_hardware_provider_nomech(
4681 	    CRYPTO_OPS_OFFSET(object_ops),
4682 	    CRYPTO_OBJECT_OFFSET(object_get_size), CHECK_RESTRICT_FALSE,
4683 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4684 		goto out;
4685 	}
4686 
4687 	handle = STRUCT_FGET(object_get_size, gs_handle);
4688 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_SIZE,
4689 	    sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size,
4690 	    NULL, NULL, 0, NULL);
4691 
4692 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4693 	KCF_PROV_REFRELE(real_provider);
4694 
4695 out:
4696 	CRYPTO_SESSION_RELE(sp);
4697 
4698 	if (rv == CRYPTO_SUCCESS) {
4699 		STRUCT_FSET(object_get_size, gs_size, size);
4700 	}
4701 release_minor:
4702 	crypto_release_minor(cm);
4703 
4704 	if (error != 0)
4705 		return (error);
4706 
4707 	STRUCT_FSET(object_get_size, gs_return_value, rv);
4708 	if (copyout(STRUCT_BUF(object_get_size), arg,
4709 	    STRUCT_SIZE(object_get_size)) != 0) {
4710 		return (EFAULT);
4711 	}
4712 	return (0);
4713 }
4714 
4715 /* ARGSUSED */
4716 static int
4717 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4718 {
4719 	STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value);
4720 	kproject_t *projp;
4721 	kcf_provider_desc_t *real_provider;
4722 	kcf_req_params_t params;
4723 	crypto_object_attribute_t *k_attrs = NULL;
4724 	crypto_session_id_t session_id;
4725 	crypto_minor_t *cm;
4726 	crypto_session_data_t *sp;
4727 	crypto_object_id_t object_handle;
4728 	caddr_t sa_attributes;
4729 	size_t k_attrs_size;
4730 	size_t rctl_bytes = 0;
4731 	int error = 0;
4732 	int rv;
4733 	uint_t count;
4734 
4735 	STRUCT_INIT(set_attribute_value, mode);
4736 
4737 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4738 		cmn_err(CE_WARN,
4739 		    "object_set_attribute_value: failed holding minor");
4740 		return (ENXIO);
4741 	}
4742 
4743 	if (copyin(arg, STRUCT_BUF(set_attribute_value),
4744 	    STRUCT_SIZE(set_attribute_value)) != 0) {
4745 		crypto_release_minor(cm);
4746 		return (EFAULT);
4747 	}
4748 
4749 	count = STRUCT_FGET(set_attribute_value, sa_count);
4750 	sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes);
4751 	if (!copyin_attributes(mode, count, sa_attributes, &k_attrs,
4752 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4753 		goto release_minor;
4754 	}
4755 
4756 	session_id = STRUCT_FGET(set_attribute_value, sa_session);
4757 
4758 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4759 		goto release_minor;
4760 	}
4761 
4762 	if ((rv = kcf_get_hardware_provider_nomech(
4763 	    CRYPTO_OPS_OFFSET(object_ops),
4764 	    CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
4765 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider))
4766 	    != CRYPTO_SUCCESS) {
4767 		goto out;
4768 	}
4769 
4770 	object_handle = STRUCT_FGET(set_attribute_value, sa_handle);
4771 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE,
4772 	    sp->sd_provider_session->ps_session, object_handle, k_attrs, count,
4773 	    NULL, 0, NULL, NULL, 0, NULL);
4774 
4775 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4776 	KCF_PROV_REFRELE(real_provider);
4777 
4778 out:
4779 	CRYPTO_SESSION_RELE(sp);
4780 
4781 release_minor:
4782 	if (rctl_bytes != 0) {
4783 		mutex_enter(&crypto_rctl_lock);
4784 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4785 		mutex_exit(&crypto_rctl_lock);
4786 	}
4787 	crypto_release_minor(cm);
4788 
4789 	if (k_attrs != NULL)
4790 		kmem_free(k_attrs, k_attrs_size);
4791 
4792 	if (error != 0)
4793 		return (error);
4794 
4795 	STRUCT_FSET(set_attribute_value, sa_return_value, rv);
4796 	if (copyout(STRUCT_BUF(set_attribute_value), arg,
4797 	    STRUCT_SIZE(set_attribute_value)) != 0) {
4798 		return (EFAULT);
4799 	}
4800 	return (0);
4801 }
4802 
4803 /* ARGSUSED */
4804 static int
4805 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval)
4806 {
4807 	STRUCT_DECL(crypto_object_find_init, find_init);
4808 	kproject_t *projp;
4809 	kcf_provider_desc_t *real_provider = NULL;
4810 	kcf_req_params_t params;
4811 	crypto_object_attribute_t *k_attrs = NULL;
4812 	crypto_session_id_t session_id;
4813 	crypto_minor_t *cm;
4814 	crypto_session_data_t *sp;
4815 	caddr_t attributes;
4816 	size_t k_attrs_size;
4817 	size_t rctl_bytes = 0;
4818 	int error = 0;
4819 	int rv;
4820 	uint_t count;
4821 	void *cookie;
4822 
4823 	STRUCT_INIT(find_init, mode);
4824 
4825 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4826 		cmn_err(CE_WARN, "object_find_init: failed holding minor");
4827 		return (ENXIO);
4828 	}
4829 
4830 	if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) {
4831 		crypto_release_minor(cm);
4832 		return (EFAULT);
4833 	}
4834 
4835 	count = STRUCT_FGET(find_init, fi_count);
4836 	attributes = STRUCT_FGETP(find_init, fi_attributes);
4837 	if (!copyin_attributes(mode, count, attributes, &k_attrs,
4838 	    &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) {
4839 		goto release_minor;
4840 	}
4841 
4842 	session_id = STRUCT_FGET(find_init, fi_session);
4843 
4844 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4845 		goto release_minor;
4846 	}
4847 
4848 	if ((rv = kcf_get_hardware_provider_nomech(
4849 	    CRYPTO_OPS_OFFSET(object_ops),
4850 	    CRYPTO_OBJECT_OFFSET(object_find_init), CHECK_RESTRICT_FALSE,
4851 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4852 		goto out;
4853 	}
4854 
4855 	/* check for an active find */
4856 	if (sp->sd_find_init_cookie != NULL) {
4857 		rv = CRYPTO_OPERATION_IS_ACTIVE;
4858 		CRYPTO_SESSION_RELE(sp);
4859 		goto release_minor;
4860 	}
4861 
4862 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_INIT,
4863 	    sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0,
4864 	    &cookie, NULL, 0, NULL);
4865 
4866 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4867 
4868 	if (rv == CRYPTO_SUCCESS) {
4869 		/*
4870 		 * The cookie is allocated by a provider at the start of an
4871 		 * object search.  It is freed when the search is terminated
4872 		 * by a final operation, or when the session is closed.
4873 		 * It contains state information about which object handles
4874 		 * have been returned to the caller.
4875 		 */
4876 		sp->sd_find_init_cookie = cookie;
4877 	}
4878 
4879 out:
4880 	CRYPTO_SESSION_RELE(sp);
4881 
4882 release_minor:
4883 	if (rctl_bytes != 0) {
4884 		mutex_enter(&crypto_rctl_lock);
4885 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4886 		mutex_exit(&crypto_rctl_lock);
4887 	}
4888 	crypto_release_minor(cm);
4889 
4890 	if (real_provider != NULL)
4891 		KCF_PROV_REFRELE(real_provider);
4892 
4893 	if (k_attrs != NULL)
4894 		kmem_free(k_attrs, k_attrs_size);
4895 
4896 	if (error != 0)
4897 		return (error);
4898 
4899 	STRUCT_FSET(find_init, fi_return_value, rv);
4900 	if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) {
4901 		return (EFAULT);
4902 	}
4903 	return (0);
4904 }
4905 
4906 /* ARGSUSED */
4907 static int
4908 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval)
4909 {
4910 	STRUCT_DECL(crypto_object_find_update, find_update);
4911 	kproject_t *projp;
4912 	kcf_provider_desc_t *real_provider;
4913 	kcf_req_params_t params;
4914 	crypto_minor_t *cm;
4915 	crypto_session_data_t *sp;
4916 	crypto_object_id_t *buffer = NULL;
4917 	crypto_session_id_t session_id;
4918 	size_t len, rctl_bytes = 0;
4919 	uint_t count, max_count;
4920 	int rv, error = 0;
4921 
4922 	STRUCT_INIT(find_update, mode);
4923 
4924 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4925 		cmn_err(CE_WARN, "object_find_update: failed holding minor");
4926 		return (ENXIO);
4927 	}
4928 
4929 	if (copyin(arg, STRUCT_BUF(find_update),
4930 	    STRUCT_SIZE(find_update)) != 0) {
4931 		crypto_release_minor(cm);
4932 		return (EFAULT);
4933 	}
4934 
4935 	max_count = STRUCT_FGET(find_update, fu_max_count);
4936 	if (max_count > CRYPTO_MAX_FIND_COUNT) {
4937 		cmn_err(CE_NOTE, "object_find_update: count greater than %d, "
4938 		    "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid);
4939 		rv = CRYPTO_ARGUMENTS_BAD;
4940 		goto release_minor;
4941 	}
4942 	len = max_count * sizeof (crypto_object_id_t);
4943 	if ((rv = crypto_buffer_check(len, &projp)) != CRYPTO_SUCCESS) {
4944 		goto release_minor;
4945 	}
4946 	rctl_bytes = len;
4947 	buffer = kmem_alloc(len, KM_SLEEP);
4948 
4949 	session_id = STRUCT_FGET(find_update, fu_session);
4950 
4951 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4952 		goto release_minor;
4953 	}
4954 
4955 	if ((rv = kcf_get_hardware_provider_nomech(
4956 	    CRYPTO_OPS_OFFSET(object_ops),
4957 	    CRYPTO_OBJECT_OFFSET(object_find), CHECK_RESTRICT_FALSE,
4958 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4959 		goto out;
4960 	}
4961 
4962 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND,
4963 	    sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0,
4964 	    NULL, sp->sd_find_init_cookie, max_count, &count);
4965 
4966 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4967 	KCF_PROV_REFRELE(real_provider);
4968 
4969 out:
4970 	CRYPTO_SESSION_RELE(sp);
4971 	if (rv == CRYPTO_SUCCESS) {
4972 		if (count > max_count) {
4973 			/* bad bad provider */
4974 			rv = CRYPTO_FAILED;
4975 			goto release_minor;
4976 		}
4977 		if (count != 0) {
4978 			/* copyout handles */
4979 			if (copyout(buffer,
4980 			    STRUCT_FGETP(find_update, fu_handles),
4981 			    count * sizeof (crypto_object_id_t)) != 0) {
4982 				error = EFAULT;
4983 			}
4984 		}
4985 		STRUCT_FSET(find_update, fu_count, count);
4986 	}
4987 
4988 release_minor:
4989 	if (rctl_bytes != 0) {
4990 		mutex_enter(&crypto_rctl_lock);
4991 		CRYPTO_DECREMENT_RCTL(rctl_bytes, projp);
4992 		mutex_exit(&crypto_rctl_lock);
4993 	}
4994 	crypto_release_minor(cm);
4995 
4996 	if (buffer != NULL)
4997 		kmem_free(buffer, len);
4998 
4999 	if (error != 0)
5000 		return (error);
5001 
5002 	STRUCT_FSET(find_update, fu_return_value, rv);
5003 	if (copyout(STRUCT_BUF(find_update), arg,
5004 	    STRUCT_SIZE(find_update)) != 0) {
5005 		return (EFAULT);
5006 	}
5007 
5008 	return (0);
5009 }
5010 
5011 /*
5012  * Free provider-allocated storage used for find object searches.
5013  */
5014 static int
5015 crypto_free_find_ctx(crypto_session_data_t *sp)
5016 {
5017 	kcf_provider_desc_t *real_provider;
5018 	kcf_req_params_t params;
5019 	int rv;
5020 
5021 	if ((rv = kcf_get_hardware_provider_nomech(
5022 	    CRYPTO_OPS_OFFSET(object_ops),
5023 	    CRYPTO_OBJECT_OFFSET(object_find_final), CHECK_RESTRICT_FALSE,
5024 	    sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5025 		return (rv);
5026 	}
5027 
5028 	KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_FINAL,
5029 	    sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0,
5030 	    NULL, sp->sd_find_init_cookie, 0, NULL);
5031 
5032 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5033 	KCF_PROV_REFRELE(real_provider);
5034 	return (rv);
5035 }
5036 
5037 /* ARGSUSED */
5038 static int
5039 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval)
5040 {
5041 	STRUCT_DECL(crypto_object_find_final, object_find_final);
5042 	crypto_session_id_t session_id;
5043 	crypto_minor_t *cm;
5044 	crypto_session_data_t *sp;
5045 	int error = 0;
5046 	int rv;
5047 
5048 	STRUCT_INIT(object_find_final, mode);
5049 
5050 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5051 		cmn_err(CE_WARN, "object_find_final: failed holding minor");
5052 		return (ENXIO);
5053 	}
5054 
5055 	if (copyin(arg, STRUCT_BUF(object_find_final),
5056 	    STRUCT_SIZE(object_find_final)) != 0) {
5057 		crypto_release_minor(cm);
5058 		return (EFAULT);
5059 	}
5060 
5061 	session_id = STRUCT_FGET(object_find_final, ff_session);
5062 
5063 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5064 		goto release_minor;
5065 	}
5066 
5067 	if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) {
5068 		sp->sd_find_init_cookie = NULL;
5069 	}
5070 
5071 	CRYPTO_SESSION_RELE(sp);
5072 
5073 release_minor:
5074 	crypto_release_minor(cm);
5075 
5076 	if (error != 0)
5077 		return (error);
5078 
5079 	STRUCT_FSET(object_find_final, ff_return_value, rv);
5080 
5081 	if (copyout(STRUCT_BUF(object_find_final), arg,
5082 	    STRUCT_SIZE(object_find_final)) != 0) {
5083 		return (EFAULT);
5084 	}
5085 	return (0);
5086 }
5087 
5088 /* ARGSUSED */
5089 static int
5090 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5091 {
5092 	STRUCT_DECL(crypto_object_generate_key, generate_key);
5093 	kproject_t *mech_projp, *key_projp;
5094 	kcf_provider_desc_t *real_provider = NULL;
5095 	kcf_req_params_t params;
5096 	crypto_mechanism_t mech;
5097 	crypto_object_attribute_t *k_attrs = NULL;
5098 	crypto_session_id_t session_id;
5099 	crypto_minor_t *cm;
5100 	crypto_session_data_t *sp = NULL;
5101 	crypto_object_id_t key_handle;
5102 	caddr_t attributes;
5103 	size_t k_attrs_size;
5104 	size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5105 	size_t carry;
5106 	uint_t count;
5107 	int error = 0;
5108 	int rv;
5109 	boolean_t allocated_by_crypto_module = B_FALSE;
5110 
5111 	STRUCT_INIT(generate_key, mode);
5112 
5113 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5114 		cmn_err(CE_WARN, "object_generate_key: failed holding minor");
5115 		return (ENXIO);
5116 	}
5117 
5118 	if (copyin(arg, STRUCT_BUF(generate_key),
5119 	    STRUCT_SIZE(generate_key)) != 0) {
5120 		crypto_release_minor(cm);
5121 		return (EFAULT);
5122 	}
5123 
5124 	session_id = STRUCT_FGET(generate_key, gk_session);
5125 
5126 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5127 		goto release_minor;
5128 	}
5129 
5130 	bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type,
5131 	    sizeof (crypto_mech_type_t));
5132 
5133 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5134 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5135 	    CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5136 		goto release_minor;
5137 	}
5138 
5139 	carry = 0;
5140 	rv = crypto_provider_copyin_mech_param(real_provider,
5141 	    STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error);
5142 
5143 	if (rv == CRYPTO_NOT_SUPPORTED) {
5144 		allocated_by_crypto_module = B_TRUE;
5145 		if (!copyin_mech(mode, STRUCT_FADDR(generate_key, gk_mechanism),
5146 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5147 		    &mech_projp)) {
5148 			goto release_minor;
5149 		}
5150 	} else {
5151 		if (rv != CRYPTO_SUCCESS)
5152 			goto release_minor;
5153 	}
5154 
5155 	count = STRUCT_FGET(generate_key, gk_count);
5156 	attributes = STRUCT_FGETP(generate_key, gk_attributes);
5157 	if (!copyin_attributes(mode, count, attributes, &k_attrs,
5158 	    &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes, carry, B_TRUE,
5159 	    &key_projp)) {
5160 		goto release_minor;
5161 	}
5162 
5163 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE,
5164 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5165 	    &key_handle, NULL, 0, NULL, NULL, NULL, 0);
5166 
5167 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5168 
5169 	if (rv == CRYPTO_SUCCESS)
5170 		STRUCT_FSET(generate_key, gk_handle, key_handle);
5171 
5172 release_minor:
5173 	mutex_enter(&crypto_rctl_lock);
5174 	if (mech_rctl_bytes != 0)
5175 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5176 	if (key_rctl_bytes != 0)
5177 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
5178 	mutex_exit(&crypto_rctl_lock);
5179 
5180 	if (k_attrs != NULL)
5181 		kmem_free(k_attrs, k_attrs_size);
5182 
5183 	if (error != 0)
5184 		goto out;
5185 
5186 	STRUCT_FSET(generate_key, gk_return_value, rv);
5187 	if (copyout(STRUCT_BUF(generate_key), arg,
5188 	    STRUCT_SIZE(generate_key)) != 0) {
5189 		if (rv == CRYPTO_SUCCESS) {
5190 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5191 			    KCF_OP_OBJECT_DESTROY,
5192 			    sp->sd_provider_session->ps_session, key_handle,
5193 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5194 
5195 			(void) kcf_submit_request(real_provider, NULL,
5196 			    NULL, &params, B_FALSE);
5197 
5198 			error = EFAULT;
5199 		}
5200 	}
5201 out:
5202 	if (sp != NULL)
5203 		CRYPTO_SESSION_RELE(sp);
5204 	crypto_release_minor(cm);
5205 
5206 	if (real_provider != NULL) {
5207 		crypto_free_mech(real_provider,
5208 		    allocated_by_crypto_module, &mech);
5209 		KCF_PROV_REFRELE(real_provider);
5210 	}
5211 	return (error);
5212 }
5213 
5214 /* ARGSUSED */
5215 static int
5216 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5217 {
5218 	STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair);
5219 	kproject_t *pub_projp, *pri_projp, *mech_projp;
5220 	kcf_provider_desc_t *real_provider = NULL;
5221 	kcf_req_params_t params;
5222 	crypto_mechanism_t mech;
5223 	crypto_object_attribute_t *k_pub_attrs = NULL;
5224 	crypto_object_attribute_t *k_pri_attrs = NULL;
5225 	crypto_session_id_t session_id;
5226 	crypto_minor_t *cm;
5227 	crypto_session_data_t *sp = NULL;
5228 	crypto_object_id_t pub_handle;
5229 	crypto_object_id_t pri_handle;
5230 	caddr_t pri_attributes;
5231 	caddr_t pub_attributes;
5232 	size_t k_pub_attrs_size, k_pri_attrs_size;
5233 	size_t mech_rctl_bytes = 0;
5234 	size_t pub_rctl_bytes = 0;
5235 	size_t pri_rctl_bytes = 0;
5236 	size_t carry;
5237 	uint_t pub_count;
5238 	uint_t pri_count;
5239 	int error = 0;
5240 	int rv;
5241 	boolean_t allocated_by_crypto_module = B_FALSE;
5242 
5243 	STRUCT_INIT(generate_key_pair, mode);
5244 
5245 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5246 		cmn_err(CE_WARN,
5247 		    "object_generate_key_pair: failed holding minor");
5248 		return (ENXIO);
5249 	}
5250 
5251 	if (copyin(arg, STRUCT_BUF(generate_key_pair),
5252 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5253 		crypto_release_minor(cm);
5254 		return (EFAULT);
5255 	}
5256 
5257 	session_id = STRUCT_FGET(generate_key_pair, kp_session);
5258 
5259 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5260 		goto release_minor;
5261 	}
5262 
5263 	bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type,
5264 	    sizeof (crypto_mech_type_t));
5265 
5266 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5267 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5268 	    CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5269 		goto release_minor;
5270 	}
5271 
5272 	carry = 0;
5273 	rv = crypto_provider_copyin_mech_param(real_provider,
5274 	    STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error);
5275 
5276 	if (rv == CRYPTO_NOT_SUPPORTED) {
5277 		allocated_by_crypto_module = B_TRUE;
5278 		if (!copyin_mech(mode, STRUCT_FADDR(generate_key_pair,
5279 		    kp_mechanism), &mech, &mech_rctl_bytes, &carry, &rv,
5280 		    &error, &mech_projp)) {
5281 			goto release_minor;
5282 		}
5283 	} else {
5284 		if (rv != CRYPTO_SUCCESS)
5285 			goto release_minor;
5286 	}
5287 
5288 	pub_count = STRUCT_FGET(generate_key_pair, kp_public_count);
5289 	pri_count = STRUCT_FGET(generate_key_pair, kp_private_count);
5290 
5291 	pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes);
5292 	if (!copyin_attributes(mode, pub_count, pub_attributes, &k_pub_attrs,
5293 	    &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes, carry,
5294 	    B_TRUE, &pub_projp)) {
5295 		goto release_minor;
5296 	}
5297 
5298 	pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes);
5299 	if (!copyin_attributes(mode, pri_count, pri_attributes, &k_pri_attrs,
5300 	    &k_pri_attrs_size, NULL, &rv, &error, &pri_rctl_bytes, 0,
5301 	    B_TRUE, &pri_projp)) {
5302 		goto release_minor;
5303 	}
5304 
5305 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
5306 	    sp->sd_provider_session->ps_session, &mech, k_pub_attrs,
5307 	    pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle,
5308 	    NULL, NULL, 0);
5309 
5310 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5311 
5312 	if (rv == CRYPTO_SUCCESS) {
5313 		STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle);
5314 		STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle);
5315 	}
5316 
5317 release_minor:
5318 	mutex_enter(&crypto_rctl_lock);
5319 	if (mech_rctl_bytes != 0)
5320 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5321 	if (pub_rctl_bytes != 0)
5322 		CRYPTO_DECREMENT_RCTL(pub_rctl_bytes, pub_projp);
5323 	if (pri_rctl_bytes != 0)
5324 		CRYPTO_DECREMENT_RCTL(pri_rctl_bytes, pri_projp);
5325 	mutex_exit(&crypto_rctl_lock);
5326 
5327 	if (k_pub_attrs != NULL)
5328 		kmem_free(k_pub_attrs, k_pub_attrs_size);
5329 
5330 	if (k_pri_attrs != NULL)
5331 		kmem_free(k_pri_attrs, k_pri_attrs_size);
5332 
5333 	if (error != 0)
5334 		goto out;
5335 
5336 	STRUCT_FSET(generate_key_pair, kp_return_value, rv);
5337 	if (copyout(STRUCT_BUF(generate_key_pair), arg,
5338 	    STRUCT_SIZE(generate_key_pair)) != 0) {
5339 		if (rv == CRYPTO_SUCCESS) {
5340 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5341 			    KCF_OP_OBJECT_DESTROY,
5342 			    sp->sd_provider_session->ps_session, pub_handle,
5343 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5344 
5345 			(void) kcf_submit_request(real_provider, NULL,
5346 			    NULL, &params, B_FALSE);
5347 
5348 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5349 			    KCF_OP_OBJECT_DESTROY,
5350 			    sp->sd_provider_session->ps_session, pri_handle,
5351 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5352 
5353 			(void) kcf_submit_request(real_provider, NULL,
5354 			    NULL, &params, B_FALSE);
5355 
5356 			error = EFAULT;
5357 		}
5358 	}
5359 out:
5360 	if (sp != NULL)
5361 		CRYPTO_SESSION_RELE(sp);
5362 	crypto_release_minor(cm);
5363 
5364 	if (real_provider != NULL) {
5365 		crypto_free_mech(real_provider,
5366 		    allocated_by_crypto_module, &mech);
5367 		KCF_PROV_REFRELE(real_provider);
5368 	}
5369 	return (error);
5370 }
5371 
5372 /* ARGSUSED */
5373 static int
5374 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
5375 {
5376 	STRUCT_DECL(crypto_object_wrap_key, wrap_key);
5377 	kproject_t *mech_projp, *key_projp, *wrapped_key_projp;
5378 	kcf_provider_desc_t *real_provider = NULL;
5379 	kcf_req_params_t params;
5380 	crypto_mechanism_t mech;
5381 	crypto_key_t key;
5382 	crypto_session_id_t session_id;
5383 	crypto_minor_t *cm;
5384 	crypto_session_data_t *sp;
5385 	crypto_object_id_t handle;
5386 	size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5387 	size_t wrapped_key_rctl_bytes = 0;
5388 	size_t carry;
5389 	size_t wrapped_key_len, new_wrapped_key_len;
5390 	uchar_t *wrapped_key = NULL;
5391 	char *wrapped_key_buffer;
5392 	int error = 0;
5393 	int rv;
5394 	boolean_t allocated_by_crypto_module = B_FALSE;
5395 
5396 	STRUCT_INIT(wrap_key, mode);
5397 
5398 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5399 		cmn_err(CE_WARN, "object_wrap_key: failed holding minor");
5400 		return (ENXIO);
5401 	}
5402 
5403 	if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) {
5404 		crypto_release_minor(cm);
5405 		return (EFAULT);
5406 	}
5407 
5408 	bzero(&key, sizeof (crypto_key_t));
5409 
5410 	session_id = STRUCT_FGET(wrap_key, wk_session);
5411 
5412 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5413 		goto release_minor;
5414 	}
5415 
5416 	bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type,
5417 	    sizeof (crypto_mech_type_t));
5418 
5419 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5420 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5421 	    CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) {
5422 		goto out;
5423 	}
5424 
5425 	carry = 0;
5426 	rv = crypto_provider_copyin_mech_param(real_provider,
5427 	    STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error);
5428 
5429 	if (rv == CRYPTO_NOT_SUPPORTED) {
5430 		allocated_by_crypto_module = B_TRUE;
5431 		if (!copyin_mech(mode, STRUCT_FADDR(wrap_key, wk_mechanism),
5432 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5433 		    &mech_projp)) {
5434 			goto out;
5435 		}
5436 	} else {
5437 		if (rv != CRYPTO_SUCCESS)
5438 			goto out;
5439 	}
5440 
5441 	if (!copyin_key(mode, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key,
5442 	    &key_rctl_bytes, &rv, &error, carry, &key_projp)) {
5443 		goto out;
5444 	}
5445 
5446 	wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len);
5447 
5448 	/*
5449 	 * Don't allocate output buffer unless both buffer pointer and
5450 	 * buffer length are not NULL or 0 (length).
5451 	 */
5452 	wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key);
5453 	if (wrapped_key_buffer == NULL || wrapped_key_len == 0) {
5454 		wrapped_key_len = 0;
5455 	}
5456 
5457 	if (wrapped_key_len > crypto_max_buffer_len) {
5458 		cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld "
5459 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
5460 		rv = CRYPTO_ARGUMENTS_BAD;
5461 		goto out;
5462 	}
5463 
5464 	if ((rv = crypto_buffer_check(wrapped_key_len,
5465 	    &wrapped_key_projp)) != CRYPTO_SUCCESS) {
5466 		goto out;
5467 	}
5468 
5469 	/* new_wrapped_key_len can be modified by the provider */
5470 	wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len;
5471 	wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
5472 
5473 	handle = STRUCT_FGET(wrap_key, wk_object_handle);
5474 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP,
5475 	    sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle,
5476 	    NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len);
5477 
5478 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5479 
5480 	if (rv == CRYPTO_SUCCESS) {
5481 		if (wrapped_key_len != 0 && copyout(wrapped_key,
5482 		    wrapped_key_buffer, new_wrapped_key_len) != 0) {
5483 			error = EFAULT;
5484 		}
5485 		STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len);
5486 	}
5487 
5488 	if (rv == CRYPTO_BUFFER_TOO_SMALL) {
5489 		/*
5490 		 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
5491 		 * of section 11.2 of the pkcs11 spec. We catch it here and
5492 		 * provide the correct pkcs11 return value.
5493 		 */
5494 		if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL)
5495 			rv = CRYPTO_SUCCESS;
5496 		STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len);
5497 	}
5498 out:
5499 	CRYPTO_SESSION_RELE(sp);
5500 
5501 release_minor:
5502 	mutex_enter(&crypto_rctl_lock);
5503 	if (mech_rctl_bytes != 0)
5504 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5505 	if (key_rctl_bytes != 0)
5506 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
5507 	if (wrapped_key_rctl_bytes != 0)
5508 		CRYPTO_DECREMENT_RCTL(wrapped_key_rctl_bytes,
5509 		    wrapped_key_projp);
5510 	mutex_exit(&crypto_rctl_lock);
5511 	crypto_release_minor(cm);
5512 
5513 	if (real_provider != NULL) {
5514 		crypto_free_mech(real_provider,
5515 		    allocated_by_crypto_module, &mech);
5516 		KCF_PROV_REFRELE(real_provider);
5517 	}
5518 
5519 	if (wrapped_key != NULL)
5520 		kmem_free(wrapped_key, wrapped_key_len);
5521 
5522 	free_crypto_key(&key);
5523 
5524 	if (error != 0)
5525 		return (error);
5526 
5527 	STRUCT_FSET(wrap_key, wk_return_value, rv);
5528 	if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) {
5529 		return (EFAULT);
5530 	}
5531 	return (0);
5532 }
5533 
5534 /* ARGSUSED */
5535 static int
5536 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
5537 {
5538 	STRUCT_DECL(crypto_object_unwrap_key, unwrap_key);
5539 	kproject_t *mech_projp, *unwrapping_key_projp, *wrapped_key_projp,
5540 	    *k_attrs_projp;
5541 	kcf_provider_desc_t *real_provider = NULL;
5542 	kcf_req_params_t params;
5543 	crypto_mechanism_t mech;
5544 	crypto_key_t unwrapping_key;
5545 	crypto_session_id_t session_id;
5546 	crypto_minor_t *cm;
5547 	crypto_session_data_t *sp = NULL;
5548 	crypto_object_id_t handle;
5549 	crypto_object_attribute_t *k_attrs = NULL;
5550 	size_t k_attrs_size;
5551 	size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0;
5552 	size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0;
5553 	size_t carry;
5554 	size_t wrapped_key_len;
5555 	uchar_t *wrapped_key = NULL;
5556 	int error = 0;
5557 	int rv;
5558 	uint_t count;
5559 	caddr_t uk_attributes;
5560 	boolean_t allocated_by_crypto_module = B_FALSE;
5561 
5562 	STRUCT_INIT(unwrap_key, mode);
5563 
5564 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5565 		cmn_err(CE_WARN, "object_unwrap_key: failed holding minor");
5566 		return (ENXIO);
5567 	}
5568 
5569 	if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) {
5570 		crypto_release_minor(cm);
5571 		return (EFAULT);
5572 	}
5573 
5574 	bzero(&unwrapping_key, sizeof (unwrapping_key));
5575 
5576 	session_id = STRUCT_FGET(unwrap_key, uk_session);
5577 
5578 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5579 		goto release_minor;
5580 	}
5581 
5582 	bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type,
5583 	    sizeof (crypto_mech_type_t));
5584 
5585 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5586 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5587 	    CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) {
5588 		goto release_minor;
5589 	}
5590 
5591 	carry = 0;
5592 	rv = crypto_provider_copyin_mech_param(real_provider,
5593 	    STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error);
5594 
5595 	if (rv == CRYPTO_NOT_SUPPORTED) {
5596 		allocated_by_crypto_module = B_TRUE;
5597 		if (!copyin_mech(mode, STRUCT_FADDR(unwrap_key, uk_mechanism),
5598 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5599 		    &mech_projp)) {
5600 			goto release_minor;
5601 		}
5602 	} else {
5603 		if (rv != CRYPTO_SUCCESS)
5604 			goto release_minor;
5605 	}
5606 
5607 	if (!copyin_key(mode, STRUCT_FADDR(unwrap_key, uk_unwrapping_key),
5608 	    &unwrapping_key, &unwrapping_key_rctl_bytes, &rv, &error, carry,
5609 	    &unwrapping_key_projp)) {
5610 		goto release_minor;
5611 	}
5612 
5613 	count = STRUCT_FGET(unwrap_key, uk_count);
5614 	uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes);
5615 	if (!copyin_attributes(mode, count, uk_attributes, &k_attrs,
5616 	    &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes, 0, B_TRUE,
5617 	    &k_attrs_projp)) {
5618 		goto release_minor;
5619 	}
5620 
5621 	wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len);
5622 	if (wrapped_key_len > crypto_max_buffer_len) {
5623 		cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld "
5624 		    "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
5625 		rv = CRYPTO_ARGUMENTS_BAD;
5626 		goto release_minor;
5627 	}
5628 
5629 	if ((rv = crypto_buffer_check(wrapped_key_len, &wrapped_key_projp))
5630 	    != CRYPTO_SUCCESS) {
5631 		goto release_minor;
5632 	}
5633 	wrapped_key_rctl_bytes = wrapped_key_len;
5634 	wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
5635 
5636 	if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key,
5637 	    uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) {
5638 		error = EFAULT;
5639 		goto release_minor;
5640 	}
5641 
5642 	/* wrapped_key_len is not modified by the unwrap operation */
5643 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP,
5644 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle,
5645 	    NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len);
5646 
5647 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5648 
5649 	if (rv == CRYPTO_SUCCESS)
5650 		STRUCT_FSET(unwrap_key, uk_object_handle, handle);
5651 
5652 release_minor:
5653 	mutex_enter(&crypto_rctl_lock);
5654 	if (mech_rctl_bytes != 0)
5655 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5656 	if (unwrapping_key_rctl_bytes != 0)
5657 		CRYPTO_DECREMENT_RCTL(unwrapping_key_rctl_bytes,
5658 		    unwrapping_key_projp);
5659 	if (wrapped_key_rctl_bytes != 0)
5660 		CRYPTO_DECREMENT_RCTL(wrapped_key_rctl_bytes,
5661 		    wrapped_key_projp);
5662 	if (k_attrs_rctl_bytes != 0)
5663 		CRYPTO_DECREMENT_RCTL(k_attrs_rctl_bytes, k_attrs_projp);
5664 	mutex_exit(&crypto_rctl_lock);
5665 
5666 	if (k_attrs != NULL)
5667 		kmem_free(k_attrs, k_attrs_size);
5668 
5669 	if (wrapped_key != NULL)
5670 		kmem_free(wrapped_key, wrapped_key_len);
5671 
5672 	free_crypto_key(&unwrapping_key);
5673 
5674 	if (error != 0)
5675 		goto out;
5676 
5677 	STRUCT_FSET(unwrap_key, uk_return_value, rv);
5678 	if (copyout(STRUCT_BUF(unwrap_key), arg,
5679 	    STRUCT_SIZE(unwrap_key)) != 0) {
5680 		if (rv == CRYPTO_SUCCESS) {
5681 			KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5682 			    KCF_OP_OBJECT_DESTROY,
5683 			    sp->sd_provider_session->ps_session, handle,
5684 			    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5685 
5686 			(void) kcf_submit_request(real_provider, NULL,
5687 			    NULL, &params, B_FALSE);
5688 
5689 			error = EFAULT;
5690 		}
5691 	}
5692 out:
5693 	if (sp != NULL)
5694 		CRYPTO_SESSION_RELE(sp);
5695 	crypto_release_minor(cm);
5696 
5697 	if (real_provider != NULL) {
5698 		crypto_free_mech(real_provider,
5699 		    allocated_by_crypto_module, &mech);
5700 		KCF_PROV_REFRELE(real_provider);
5701 	}
5702 
5703 	return (error);
5704 }
5705 
5706 /* ARGSUSED */
5707 static int
5708 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
5709 {
5710 	STRUCT_DECL(crypto_derive_key, derive_key);
5711 	kproject_t *key_projp, *mech_projp, *attributes_projp;
5712 	kcf_provider_desc_t *real_provider = NULL;
5713 	kcf_req_params_t params;
5714 	crypto_object_attribute_t *k_attrs = NULL;
5715 	crypto_mechanism_t mech;
5716 	crypto_key_t base_key;
5717 	crypto_session_id_t session_id;
5718 	crypto_minor_t *cm;
5719 	crypto_session_data_t *sp = NULL;
5720 	crypto_object_id_t handle;
5721 	size_t k_attrs_size;
5722 	size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
5723 	size_t attributes_rctl_bytes = 0;
5724 	size_t carry;
5725 	caddr_t attributes;
5726 	uint_t count;
5727 	int error = 0;
5728 	int rv;
5729 	boolean_t allocated_by_crypto_module = B_FALSE;
5730 	boolean_t please_destroy_object = B_FALSE;
5731 
5732 	STRUCT_INIT(derive_key, mode);
5733 
5734 	if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5735 		cmn_err(CE_WARN, "object_derive_key: failed holding minor");
5736 		return (ENXIO);
5737 	}
5738 
5739 	if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
5740 		crypto_release_minor(cm);
5741 		return (EFAULT);
5742 	}
5743 
5744 	bzero(&base_key, sizeof (base_key));
5745 
5746 	session_id = STRUCT_FGET(derive_key, dk_session);
5747 
5748 	if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5749 		goto release_minor;
5750 	}
5751 
5752 	bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type,
5753 	    sizeof (crypto_mech_type_t));
5754 
5755 	if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID,
5756 	    CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider,
5757 	    CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
5758 		goto release_minor;
5759 	}
5760 
5761 	carry = 0;
5762 	rv = crypto_provider_copyin_mech_param(real_provider,
5763 	    STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error);
5764 
5765 	if (rv == CRYPTO_NOT_SUPPORTED) {
5766 		allocated_by_crypto_module = B_TRUE;
5767 		if (!copyin_mech(mode, STRUCT_FADDR(derive_key, dk_mechanism),
5768 		    &mech, &mech_rctl_bytes, &carry, &rv, &error,
5769 		    &mech_projp)) {
5770 			goto release_minor;
5771 		}
5772 	} else {
5773 		if (rv != CRYPTO_SUCCESS)
5774 			goto release_minor;
5775 	}
5776 
5777 	if (!copyin_key(mode, STRUCT_FADDR(derive_key, dk_base_key),
5778 	    &base_key, &key_rctl_bytes, &rv, &error, carry, &key_projp)) {
5779 		goto release_minor;
5780 	}
5781 
5782 	count = STRUCT_FGET(derive_key, dk_count);
5783 
5784 	attributes = STRUCT_FGETP(derive_key, dk_attributes);
5785 	if (!copyin_attributes(mode, count, attributes, &k_attrs,
5786 	    &k_attrs_size, NULL, &rv, &error, &attributes_rctl_bytes, 0, B_TRUE,
5787 	    &attributes_projp)) {
5788 		goto release_minor;
5789 	}
5790 
5791 	KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE,
5792 	    sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5793 	    &handle, NULL, 0, NULL, &base_key, NULL, NULL);
5794 
5795 	rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5796 
5797 	if (rv == CRYPTO_SUCCESS) {
5798 		STRUCT_FSET(derive_key, dk_object_handle, handle);
5799 
5800 		rv = crypto_provider_copyout_mech_param(real_provider,
5801 		    &mech, STRUCT_FADDR(derive_key, dk_mechanism),
5802 		    mode, &error);
5803 
5804 		if (rv == CRYPTO_NOT_SUPPORTED) {
5805 			rv = CRYPTO_SUCCESS;
5806 			goto release_minor;
5807 		}
5808 
5809 		if (rv != CRYPTO_SUCCESS)
5810 			please_destroy_object = B_TRUE;
5811 	}
5812 
5813 release_minor:
5814 	mutex_enter(&crypto_rctl_lock);
5815 	if (mech_rctl_bytes != 0)
5816 		CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp);
5817 	if (key_rctl_bytes != 0)
5818 		CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp);
5819 	if (attributes_rctl_bytes != 0)
5820 		CRYPTO_DECREMENT_RCTL(attributes_rctl_bytes, attributes_projp);
5821 	mutex_exit(&crypto_rctl_lock);
5822 
5823 	if (k_attrs != NULL)
5824 		kmem_free(k_attrs, k_attrs_size);
5825 
5826 	free_crypto_key(&base_key);
5827 
5828 	if (error != 0)
5829 		goto out;
5830 
5831 	STRUCT_FSET(derive_key, dk_return_value, rv);
5832 	if (copyout(STRUCT_BUF(derive_key), arg,
5833 	    STRUCT_SIZE(derive_key)) != 0) {
5834 		if (rv == CRYPTO_SUCCESS) {
5835 			please_destroy_object = B_TRUE;
5836 			error = EFAULT;
5837 		}
5838 	}
5839 out:
5840 	if (please_destroy_object) {
5841 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
5842 		    sp->sd_provider_session->ps_session, handle,
5843 		    NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5844 
5845 		(void) kcf_submit_request(real_provider, NULL,
5846 		    NULL, &params, B_FALSE);
5847 	}
5848 
5849 	if (sp != NULL)
5850 		CRYPTO_SESSION_RELE(sp);
5851 	crypto_release_minor(cm);
5852 
5853 	if (real_provider != NULL) {
5854 		crypto_free_mech(real_provider,
5855 		    allocated_by_crypto_module, &mech);
5856 		KCF_PROV_REFRELE(real_provider);
5857 	}
5858 	return (error);
5859 }
5860 
5861 /* ARGSUSED */
5862 static int
5863 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
5864     int *rval)
5865 {
5866 #define	ARG	((caddr_t)arg)
5867 
5868 	switch (cmd) {
5869 	case CRYPTO_GET_FUNCTION_LIST:
5870 		return (get_function_list(dev, ARG, mode, rval));
5871 
5872 	case CRYPTO_GET_MECHANISM_NUMBER:
5873 		return (get_mechanism_number(dev, ARG, mode, rval));
5874 
5875 	case CRYPTO_GET_PROVIDER_LIST:
5876 		return (get_provider_list(dev, ARG, mode, rval));
5877 
5878 	case CRYPTO_GET_PROVIDER_INFO:
5879 		return (get_provider_info(dev, ARG, mode, rval));
5880 
5881 	case CRYPTO_GET_PROVIDER_MECHANISMS:
5882 		return (get_provider_mechanisms(dev, ARG, mode, rval));
5883 
5884 	case CRYPTO_GET_PROVIDER_MECHANISM_INFO:
5885 		return (get_provider_mechanism_info(dev, ARG, mode, rval));
5886 
5887 	case CRYPTO_OPEN_SESSION:
5888 		return (open_session(dev, ARG, mode, rval));
5889 
5890 	case CRYPTO_CLOSE_SESSION:
5891 		return (close_session(dev, ARG, mode, rval));
5892 
5893 	case CRYPTO_ENCRYPT_INIT:
5894 		return (encrypt_init(dev, ARG, mode, rval));
5895 
5896 	case CRYPTO_DECRYPT_INIT:
5897 		return (decrypt_init(dev, ARG, mode, rval));
5898 
5899 	case CRYPTO_ENCRYPT:
5900 		return (encrypt(dev, ARG, mode, rval));
5901 
5902 	case CRYPTO_DECRYPT:
5903 		return (decrypt(dev, ARG, mode, rval));
5904 
5905 	case CRYPTO_ENCRYPT_UPDATE:
5906 		return (encrypt_update(dev, ARG, mode, rval));
5907 
5908 	case CRYPTO_DECRYPT_UPDATE:
5909 		return (decrypt_update(dev, ARG, mode, rval));
5910 
5911 	case CRYPTO_ENCRYPT_FINAL:
5912 		return (encrypt_final(dev, ARG, mode, rval));
5913 
5914 	case CRYPTO_DECRYPT_FINAL:
5915 		return (decrypt_final(dev, ARG, mode, rval));
5916 
5917 	case CRYPTO_DIGEST_INIT:
5918 		return (digest_init(dev, ARG, mode, rval));
5919 
5920 	case CRYPTO_DIGEST:
5921 		return (digest(dev, ARG, mode, rval));
5922 
5923 	case CRYPTO_DIGEST_UPDATE:
5924 		return (digest_update(dev, ARG, mode, rval));
5925 
5926 	case CRYPTO_DIGEST_KEY:
5927 		return (digest_key(dev, ARG, mode, rval));
5928 
5929 	case CRYPTO_DIGEST_FINAL:
5930 		return (digest_final(dev, ARG, mode, rval));
5931 
5932 	case CRYPTO_SIGN_INIT:
5933 		return (sign_init(dev, ARG, mode, rval));
5934 
5935 	case CRYPTO_SIGN:
5936 		return (sign(dev, ARG, mode, rval));
5937 
5938 	case CRYPTO_SIGN_UPDATE:
5939 		return (sign_update(dev, ARG, mode, rval));
5940 
5941 	case CRYPTO_SIGN_FINAL:
5942 		return (sign_final(dev, ARG, mode, rval));
5943 
5944 	case CRYPTO_SIGN_RECOVER_INIT:
5945 		return (sign_recover_init(dev, ARG, mode, rval));
5946 
5947 	case CRYPTO_SIGN_RECOVER:
5948 		return (sign_recover(dev, ARG, mode, rval));
5949 
5950 	case CRYPTO_VERIFY_INIT:
5951 		return (verify_init(dev, ARG, mode, rval));
5952 
5953 	case CRYPTO_VERIFY:
5954 		return (verify(dev, ARG, mode, rval));
5955 
5956 	case CRYPTO_VERIFY_UPDATE:
5957 		return (verify_update(dev, ARG, mode, rval));
5958 
5959 	case CRYPTO_VERIFY_FINAL:
5960 		return (verify_final(dev, ARG, mode, rval));
5961 
5962 	case CRYPTO_VERIFY_RECOVER_INIT:
5963 		return (verify_recover_init(dev, ARG, mode, rval));
5964 
5965 	case CRYPTO_VERIFY_RECOVER:
5966 		return (verify_recover(dev, ARG, mode, rval));
5967 
5968 	case CRYPTO_SET_PIN:
5969 		return (set_pin(dev, ARG, mode, rval));
5970 
5971 	case CRYPTO_LOGIN:
5972 		return (login(dev, ARG, mode, rval));
5973 
5974 	case CRYPTO_LOGOUT:
5975 		return (logout(dev, ARG, mode, rval));
5976 
5977 	case CRYPTO_SEED_RANDOM:
5978 		return (seed_random(dev, ARG, mode, rval));
5979 
5980 	case CRYPTO_GENERATE_RANDOM:
5981 		return (generate_random(dev, ARG, mode, rval));
5982 
5983 	case CRYPTO_OBJECT_CREATE:
5984 		return (object_create(dev, ARG, mode, rval));
5985 
5986 	case CRYPTO_OBJECT_COPY:
5987 		return (object_copy(dev, ARG, mode, rval));
5988 
5989 	case CRYPTO_OBJECT_DESTROY:
5990 		return (object_destroy(dev, ARG, mode, rval));
5991 
5992 	case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE:
5993 		return (object_get_attribute_value(dev, ARG, mode, rval));
5994 
5995 	case CRYPTO_OBJECT_GET_SIZE:
5996 		return (object_get_size(dev, ARG, mode, rval));
5997 
5998 	case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE:
5999 		return (object_set_attribute_value(dev, ARG, mode, rval));
6000 
6001 	case CRYPTO_OBJECT_FIND_INIT:
6002 		return (object_find_init(dev, ARG, mode, rval));
6003 
6004 	case CRYPTO_OBJECT_FIND_UPDATE:
6005 		return (object_find_update(dev, ARG, mode, rval));
6006 
6007 	case CRYPTO_OBJECT_FIND_FINAL:
6008 		return (object_find_final(dev, ARG, mode, rval));
6009 
6010 	case CRYPTO_GENERATE_KEY:
6011 		return (object_generate_key(dev, ARG, mode, rval));
6012 
6013 	case CRYPTO_GENERATE_KEY_PAIR:
6014 		return (object_generate_key_pair(dev, ARG, mode, rval));
6015 
6016 	case CRYPTO_WRAP_KEY:
6017 		return (object_wrap_key(dev, ARG, mode, rval));
6018 
6019 	case CRYPTO_UNWRAP_KEY:
6020 		return (object_unwrap_key(dev, ARG, mode, rval));
6021 
6022 	case CRYPTO_DERIVE_KEY:
6023 		return (object_derive_key(dev, ARG, mode, rval));
6024 	}
6025 	return (EINVAL);
6026 }
6027 
6028 /*
6029  * Check for the project.max-crypto-memory resource control.
6030  */
6031 static int
6032 crypto_buffer_check(size_t need, kproject_t **projp)
6033 {
6034 	ASSERT(projp != NULL);
6035 
6036 	if (need == 0)
6037 		return (CRYPTO_SUCCESS);
6038 
6039 	mutex_enter(&curproc->p_lock);
6040 	mutex_enter(&crypto_rctl_lock);
6041 	if (rctl_test(rc_project_crypto_mem,
6042 	    curproc->p_task->tk_proj->kpj_rctls, curproc, need, 0) & RCT_DENY) {
6043 		mutex_exit(&crypto_rctl_lock);
6044 		mutex_exit(&curproc->p_lock);
6045 		return (CRYPTO_HOST_MEMORY);
6046 	}
6047 
6048 	curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem += need;
6049 	mutex_exit(&crypto_rctl_lock);
6050 
6051 	(void) project_hold(curproc->p_task->tk_proj);
6052 	*projp = curproc->p_task->tk_proj;
6053 	mutex_exit(&curproc->p_lock);
6054 	return (CRYPTO_SUCCESS);
6055 }
6056