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