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