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