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