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