xref: /illumos-gate/usr/src/uts/common/crypto/io/dprov.c (revision 7c478bd9)
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  * Dummy Cryptographic Provider:
31  *
32  * This file implements a "dummy" cryptographic provider. It is implemented
33  * as a pseudo device driver.
34  *
35  */
36 
37 /*
38  * This driver implements a KEF provider with the following capabilities:
39  *
40  * - registration/unregistration with KEF
41  * - digest entry points
42  * - mac entry points
43  * - ctx management
44  * - support for async requests
45  * - cipher entry points
46  * - dual entry points
47  * - sign entry points
48  * - verify entry points
49  * - dual operations entry points
50  * - dual cipher/mac operation entry points
51  * - session management
52  * - object management
53  * - key management
54  * - provider management
55  *
56  * In order to avoid duplicating the implementation of algorithms
57  * provided by software providers, this pseudo driver acts as
58  * a consumer of the framework. When invoking one of the framework's
59  * entry points, the driver specifies the software provider to
60  * be used for the operation.
61  *
62  * User management: we implement a PKCS#11 style provider which supports:
63  * - one normal user with a PIN, and
64  * - one SO user with a PIN.
65  * These values are kept in the per-instance structure, and are initialized
66  * with the provider management entry points.
67  *
68  */
69 
70 
71 #include <sys/types.h>
72 #include <sys/modctl.h>
73 #include <sys/conf.h>
74 #include <sys/stat.h>
75 #include <sys/ddi.h>
76 #include <sys/sunddi.h>
77 #include <sys/kmem.h>
78 #include <sys/errno.h>
79 #include <sys/ksynch.h>
80 #include <sys/file.h>
81 #include <sys/open.h>
82 #include <sys/cred.h>
83 #include <sys/model.h>
84 #include <sys/note.h>
85 #include <sys/random.h>
86 #include <sys/byteorder.h>
87 #include <sys/crypto/common.h>
88 #include <sys/crypto/spi.h>
89 
90 #include <sys/taskq.h>
91 #include <sys/disp.h>
92 #include <sys/sysmacros.h>
93 #include <sys/crypto/impl.h>
94 #include <sys/crypto/sched_impl.h>
95 
96 /*
97  * Debugging macros.
98  */
99 #ifdef DEBUG
100 #define	D_INIT		0x00000001	/* _init/_fini/_info */
101 #define	D_ATTACH	0x00000002	/* attach/detach */
102 #define	D_DIGEST	0x00000010	/* digest entry points */
103 #define	D_MAC		0x00000020	/* mac entry points */
104 #define	D_CONTEXT	0x00000040	/* context entry points */
105 #define	D_CIPHER	0x00000080	/* cipher entry points */
106 #define	D_SIGN		0x00000100	/* sign entry points */
107 #define	D_VERIFY	0x00000200	/* verify entry points */
108 #define	D_SESSION	0x00000400	/* session management entry points */
109 #define	D_MGMT		0x00000800	/* provider management entry points */
110 #define	D_DUAL		0x00001000	/* dual ops */
111 #define	D_CIPHER_MAC	0x00002000	/* cipher/mac dual ops */
112 #define	D_OBJECT	0x00004000	/* object management */
113 #define	D_RANDOM	0x00008000	/* random number generation */
114 #define	D_KEY		0x00010000	/* key management */
115 
116 static uint32_t dprov_debug = 0;
117 
118 #define	DPROV_DEBUG(f, x)	if (dprov_debug & (f)) { (void) printf x; }
119 #define	DPROV_CALL(f, r, x)	if (dprov_debug & (f)) { (void) r x; }
120 #else /* DEBUG */
121 #define	DPROV_DEBUG(f, x)
122 #define	DPROV_CALL(f, r, x)
123 #endif /* DEBUG */
124 
125 /*
126  * DDI entry points.
127  */
128 static int dprov_attach(dev_info_t *, ddi_attach_cmd_t);
129 static int dprov_detach(dev_info_t *, ddi_detach_cmd_t);
130 static int dprov_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
131 
132 /*
133  * Module linkage.
134  */
135 static struct cb_ops cbops = {
136 	nodev,			/* cb_open */
137 	nodev,			/* cb_close */
138 	nodev,			/* cb_strategy */
139 	nodev,			/* cb_print */
140 	nodev,			/* cb_dump */
141 	nodev,			/* cb_read */
142 	nodev,			/* cb_write */
143 	nodev,			/* cb_ioctl */
144 	nodev,			/* cb_devmap */
145 	nodev,			/* cb_mmap */
146 	nodev,			/* cb_segmap */
147 	nochpoll,		/* cb_chpoll */
148 	ddi_prop_op,		/* cb_prop_op */
149 	NULL,			/* cb_streamtab */
150 	D_MP,			/* cb_flag */
151 	CB_REV,			/* cb_rev */
152 	nodev,			/* cb_aread */
153 	nodev,			/* cb_awrite */
154 };
155 
156 static struct dev_ops devops = {
157 	DEVO_REV,		/* devo_rev */
158 	0,			/* devo_refcnt */
159 	dprov_getinfo,		/* devo_getinfo */
160 	nulldev,		/* devo_identify */
161 	nulldev,		/* devo_probe */
162 	dprov_attach,		/* devo_attach */
163 	dprov_detach,		/* devo_detach */
164 	nodev,			/* devo_reset */
165 	&cbops,			/* devo_cb_ops */
166 	NULL,			/* devo_bus_ops */
167 	NULL,			/* devo_power */
168 };
169 
170 static struct modldrv modldrv = {
171 	&mod_driverops,
172 	"Pseudo KCF Prov (drv) %I%",
173 	&devops
174 };
175 
176 static struct modlcrypto modlcrypto = {
177 	&mod_cryptoops,
178 	"Pseudo KCF Prov (crypto) %I%"
179 };
180 
181 static struct modlinkage modlinkage = {
182 	MODREV_1,
183 	&modldrv,
184 	&modlcrypto,
185 	NULL
186 };
187 
188 /*
189  * CSPI information (entry points, provider info, etc.)
190  */
191 
192 typedef enum dprov_mech_type {
193 	MD5_MECH_INFO_TYPE,		/* SUN_CKM_MD5 */
194 	MD5_HMAC_MECH_INFO_TYPE,	/* SUN_CKM_MD5_HMAC */
195 	MD5_HMAC_GEN_MECH_INFO_TYPE,	/* SUN_CKM_MD5_HMAC_GENERAL */
196 
197 	SHA1_HMAC_MECH_INFO_TYPE,	/* SUN_CKM_SHA1_HMAC */
198 	SHA1_HMAC_GEN_MECH_INFO_TYPE,	/* SUN_CKM_SHA1_HMAC_GENERAL */
199 	SHA1_MECH_INFO_TYPE,		/* SUN_CKM_SHA1 */
200 
201 	SHA256_HMAC_MECH_INFO_TYPE,	/* SUN_CKM_SHA256_HMAC */
202 	SHA256_HMAC_GEN_MECH_INFO_TYPE,	/* SUN_CKM_SHA256_HMAC_GENERAL */
203 	SHA256_MECH_INFO_TYPE,		/* SUN_CKM_SHA256 */
204 	SHA384_HMAC_MECH_INFO_TYPE,	/* SUN_CKM_SHA384_HMAC */
205 	SHA384_HMAC_GEN_MECH_INFO_TYPE,	/* SUN_CKM_SHA384_HMAC_GENERAL */
206 	SHA384_MECH_INFO_TYPE,		/* SUN_CKM_SHA384 */
207 	SHA512_HMAC_MECH_INFO_TYPE,	/* SUN_CKM_SHA512_HMAC */
208 	SHA512_HMAC_GEN_MECH_INFO_TYPE,	/* SUN_CKM_SHA512_HMAC_GENERAL */
209 	SHA512_MECH_INFO_TYPE,		/* SUN_CKM_SHA512 */
210 
211 	DES_CBC_MECH_INFO_TYPE,		/* SUN_CKM_DES_CBC */
212 	DES3_CBC_MECH_INFO_TYPE,	/* SUN_CKM_DES3_CBC */
213 	DES_ECB_MECH_INFO_TYPE,		/* SUN_CKM_DES_ECB */
214 	DES3_ECB_MECH_INFO_TYPE,	/* SUN_CKM_DES3_ECB */
215 
216 	BF_CBC_MECH_INFO_TYPE,		/* SUN_CKM_BF_CBC */
217 	BF_ECB_MECH_INFO_TYPE,		/* SUN_CKM_BF_ECB */
218 	AES_CBC_MECH_INFO_TYPE,		/* SUN_CKM_AES_CBC */
219 	AES_ECB_MECH_INFO_TYPE,		/* SUN_CKM_AES_ECB */
220 	RC4_MECH_INFO_TYPE,		/* SUN_CKM_RC4 */
221 	RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_RSA_PKCS */
222 	RSA_X_509_MECH_INFO_TYPE,	/* SUN_CKM_RSA_X_509 */
223 	MD5_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_MD5_RSA_PKCS */
224 	SHA1_RSA_PKCS_MECH_INFO_TYPE,	/* SUN_CKM_SHA1_RSA_PKCS */
225 	MD5_KEY_DERIVATION_MECH_INFO_TYPE, /* SUN_CKM_MD5_KEY_DERIVATION */
226 	SHA1_KEY_DERIVATION_MECH_INFO_TYPE, /* SUN_CKM_SHA1_KEY_DERIVATION */
227 	DES_KEY_GEN_MECH_INFO_TYPE,	/* SUN_CKM_DES_KEY_GEN */
228 	DES3_KEY_GEN_MECH_INFO_TYPE,	/* SUN_CKM_DES3_KEY_GEN */
229 	AES_KEY_GEN_MECH_INFO_TYPE,	/* SUN_CKM_AES_KEY_GEN */
230 	RC4_KEY_GEN_MECH_INFO_TYPE,	/* SUN_CKM_RC4_KEY_GEN */
231 	RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE /* SUN_CKM_RSA_PKCS_KEY_PAIR_GEN */
232 } dprov_mech_type_t;
233 
234 /*
235  * Mechanism info structure passed to KCF during registration.
236  */
237 #define	MD5_DIGEST_LEN		16	/* MD5 digest size */
238 #define	MD5_HMAC_BLOCK_SIZE	64	/* MD5-HMAC block size */
239 #define	MD5_HMAC_MIN_KEY_LEN	8	/* MD5-HMAC min key length in bits */
240 #define	MD5_HMAC_MAX_KEY_LEN	INT_MAX	/* MD5-HMAC max key length in bits */
241 
242 #define	SHA1_DIGEST_LEN		20	/* SHA1 digest size */
243 #define	SHA1_HMAC_BLOCK_SIZE	64	/* SHA1-HMAC block size */
244 #define	SHA1_HMAC_MIN_KEY_LEN	8	/* SHA1-HMAC min key length in bits */
245 #define	SHA1_HMAC_MAX_KEY_LEN	INT_MAX /* SHA1-HMAC max key length in bits */
246 
247 #define	SHA256_DIGEST_LENGTH	32	/* SHA256 digest length in bytes */
248 #define	SHA384_DIGEST_LENGTH	48	/* SHA384 digest length in bytes */
249 #define	SHA512_DIGEST_LENGTH	64	/* SHA512 digest length in bytes */
250 #define	SHA256_HMAC_BLOCK_SIZE	64	/* SHA256-HMAC block size */
251 #define	SHA512_HMAC_BLOCK_SIZE	128	/* SHA512-HMAC block size */
252 #define	SHA2_HMAC_MIN_KEY_LEN	8	/* SHA2-HMAC min key length in bits */
253 #define	SHA2_HMAC_MAX_KEY_LEN	INT_MAX /* SHA2-HMAC max key length in bits */
254 
255 #define	DES_KEY_LEN		8	/* DES key length in bytes */
256 #define	DES3_KEY_LEN		24	/* DES3 key length in bytes */
257 
258 #define	BF_MIN_KEY_LEN		32	/* Blowfish min key length in bits */
259 #define	BF_MAX_KEY_LEN		448	/* Blowfish max key length in bits */
260 
261 #define	AES_MIN_KEY_LEN		16	/* AES min key length in bytes */
262 #define	AES_MAX_KEY_LEN		32	/* AES max key length in bytes */
263 
264 #define	ARCFOUR_MIN_KEY_BITS	40	/* RC4 min supported key size */
265 #define	ARCFOUR_MAX_KEY_BITS	2048	/* RC4 max supported key size */
266 
267 #define	RSA_MIN_KEY_LEN		256	/* RSA min key length in bits */
268 #define	RSA_MAX_KEY_LEN		4096	/* RSA max key length in bits */
269 
270 #define	DPROV_CKM_MD5_KEY_DERIVATION	"CKM_MD5_KEY_DERIVATION"
271 #define	DPROV_CKM_SHA1_KEY_DERIVATION	"CKM_SHA1_KEY_DERIVATION"
272 #define	DPROV_CKM_DES_KEY_GEN		"CKM_DES_KEY_GEN"
273 #define	DPROV_CKM_DES3_KEY_GEN		"CKM_DES3_KEY_GEN"
274 #define	DPROV_CKM_AES_KEY_GEN		"CKM_AES_KEY_GEN"
275 #define	DPROV_CKM_RC4_KEY_GEN		"CKM_RC4_KEY_GEN"
276 #define	DPROV_CKM_RSA_PKCS_KEY_PAIR_GEN	"CKM_RSA_PKCS_KEY_PAIR_GEN"
277 
278 static crypto_mech_info_t dprov_mech_info_tab[] = {
279 	/* MD5 */
280 	{SUN_CKM_MD5, MD5_MECH_INFO_TYPE,
281 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
282 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
283 	/* MD5-HMAC */
284 	{SUN_CKM_MD5_HMAC, MD5_HMAC_MECH_INFO_TYPE,
285 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
286 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
287 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
288 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
289 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
290 	    MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN,
291 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
292 	/* MD5-HMAC GENERAL */
293 	{SUN_CKM_MD5_HMAC_GENERAL, MD5_HMAC_GEN_MECH_INFO_TYPE,
294 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
295 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
296 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
297 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
298 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
299 	    MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN,
300 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
301 	/* SHA1 */
302 	{SUN_CKM_SHA1, SHA1_MECH_INFO_TYPE,
303 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
304 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
305 	/* SHA1-HMAC */
306 	{SUN_CKM_SHA1_HMAC, SHA1_HMAC_MECH_INFO_TYPE,
307 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
308 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
309 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
310 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
311 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
312 	    SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
313 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
314 	/* SHA1-HMAC GENERAL */
315 	{SUN_CKM_SHA1_HMAC_GENERAL, SHA1_HMAC_GEN_MECH_INFO_TYPE,
316 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
317 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
318 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
319 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
320 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
321 	    SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
322 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
323 	/* SHA256 */
324 	{SUN_CKM_SHA256, SHA256_MECH_INFO_TYPE,
325 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
326 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
327 	/* SHA256-HMAC */
328 	{SUN_CKM_SHA256_HMAC, SHA256_HMAC_MECH_INFO_TYPE,
329 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
330 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
331 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
332 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
333 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
334 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
335 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
336 	/* SHA256-HMAC GENERAL */
337 	{SUN_CKM_SHA256_HMAC_GENERAL, SHA256_HMAC_GEN_MECH_INFO_TYPE,
338 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
339 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
340 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
341 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
342 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
343 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
344 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
345 	/* SHA384 */
346 	{SUN_CKM_SHA384, SHA384_MECH_INFO_TYPE,
347 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
348 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
349 	/* SHA384-HMAC */
350 	{SUN_CKM_SHA384_HMAC, SHA384_HMAC_MECH_INFO_TYPE,
351 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
352 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
353 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
354 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
355 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
356 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
357 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
358 	/* SHA384-HMAC GENERAL */
359 	{SUN_CKM_SHA384_HMAC_GENERAL, SHA384_HMAC_GEN_MECH_INFO_TYPE,
360 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
361 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
362 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
363 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
364 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
365 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
366 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
367 	/* SHA512 */
368 	{SUN_CKM_SHA512, SHA512_MECH_INFO_TYPE,
369 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
370 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
371 	/* SHA512-HMAC */
372 	{SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE,
373 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
374 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
375 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
376 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
377 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
378 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
379 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
380 	/* SHA512-HMAC GENERAL */
381 	{SUN_CKM_SHA512_HMAC_GENERAL, SHA512_HMAC_GEN_MECH_INFO_TYPE,
382 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
383 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
384 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
385 	    CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
386 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
387 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
388 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
389 	/* DES-CBC */
390 	{SUN_CKM_DES_CBC, DES_CBC_MECH_INFO_TYPE,
391 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
392 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
393 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
394 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
395 	    DES_KEY_LEN, DES_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
396 	/* DES3-CBC */
397 	{SUN_CKM_DES3_CBC, DES3_CBC_MECH_INFO_TYPE,
398 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
399 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
400 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
401 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
402 	    DES3_KEY_LEN, DES3_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
403 	/* DES-ECB */
404 	{SUN_CKM_DES_ECB, DES_ECB_MECH_INFO_TYPE,
405 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
406 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
407 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
408 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
409 	    DES_KEY_LEN, DES_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
410 	/* DES3-ECB */
411 	{SUN_CKM_DES3_ECB, DES3_ECB_MECH_INFO_TYPE,
412 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
413 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
414 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
415 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
416 	    DES3_KEY_LEN, DES3_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
417 	/* BF-CBC */
418 	{SUN_CKM_BF_CBC, BF_CBC_MECH_INFO_TYPE,
419 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
420 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
421 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
422 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC, BF_MIN_KEY_LEN, BF_MAX_KEY_LEN,
423 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
424 	/* BF-ECB */
425 	{SUN_CKM_BF_ECB, BF_ECB_MECH_INFO_TYPE,
426 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
427 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
428 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
429 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
430 	    BF_MIN_KEY_LEN, BF_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
431 	/* AES-CBC */
432 	{SUN_CKM_AES_CBC, AES_CBC_MECH_INFO_TYPE,
433 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
434 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
435 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
436 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
437 	    AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
438 	/* AES-ECB */
439 	{SUN_CKM_AES_ECB, AES_ECB_MECH_INFO_TYPE,
440 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
441 	    CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
442 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
443 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC,
444 	    AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
445 	/* RC4 */
446 	{SUN_CKM_RC4, RC4_MECH_INFO_TYPE,
447 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
448 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
449 	    ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
450 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
451 	/* RSA_PKCS */
452 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
453 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
454 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
455 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
456 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
457 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
458 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
459 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
460 	/* RSA_X_509 */
461 	{SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
462 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
463 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
464 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
465 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
466 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
467 	    CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
468 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
469 	/* MD5_RSA_PKCS */
470 	{SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE,
471 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
472 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
473 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
474 	/* SHA1_RSA_PKCS */
475 	{SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE,
476 	    CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
477 	    CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
478 	    RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
479 	/* MD5_KEY_DERIVATION */
480 	{DPROV_CKM_MD5_KEY_DERIVATION, MD5_KEY_DERIVATION_MECH_INFO_TYPE,
481 	    CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
482 	/* SHA1_KEY_DERIVATION */
483 	{DPROV_CKM_SHA1_KEY_DERIVATION, SHA1_KEY_DERIVATION_MECH_INFO_TYPE,
484 	    CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
485 	/* DES_KEY_GENERATION */
486 	{DPROV_CKM_DES_KEY_GEN, DES_KEY_GEN_MECH_INFO_TYPE,
487 	    CRYPTO_FG_GENERATE, DES_KEY_LEN, DES_KEY_LEN,
488 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
489 	/* DES3_KEY_GENERATION */
490 	{DPROV_CKM_DES3_KEY_GEN, DES3_KEY_GEN_MECH_INFO_TYPE,
491 	    CRYPTO_FG_GENERATE, DES3_KEY_LEN, DES3_KEY_LEN,
492 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
493 	/* AES_KEY_GENERATION */
494 	{DPROV_CKM_AES_KEY_GEN, AES_KEY_GEN_MECH_INFO_TYPE,
495 	    CRYPTO_FG_GENERATE, AES_MIN_KEY_LEN, AES_MAX_KEY_LEN,
496 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
497 	/* RC4_KEY_GENERATION */
498 	{DPROV_CKM_RC4_KEY_GEN, RC4_KEY_GEN_MECH_INFO_TYPE,
499 	    CRYPTO_FG_GENERATE, ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
500 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
501 	/* RSA_PKCS_KEY_PAIR_GEN */
502 	{DPROV_CKM_RSA_PKCS_KEY_PAIR_GEN, RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE,
503 	    CRYPTO_FG_GENERATE_KEY_PAIR, RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN,
504 	    CRYPTO_KEYSIZE_UNIT_IN_BITS}
505 };
506 
507 static void dprov_provider_status(crypto_provider_handle_t, uint_t *);
508 
509 static crypto_control_ops_t dprov_control_ops = {
510 	dprov_provider_status
511 };
512 
513 #define	DPROV_MANUFACTURER	"SUNW                            "
514 #define	DPROV_MODEL		"dprov           "
515 #define	DPROV_ALLSPACES		"                "
516 
517 static int dprov_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
518     crypto_req_handle_t);
519 static int dprov_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
520     crypto_req_handle_t);
521 static int dprov_digest_update(crypto_ctx_t *, crypto_data_t *,
522     crypto_req_handle_t);
523 static int dprov_digest_key(crypto_ctx_t *, crypto_key_t *,
524     crypto_req_handle_t);
525 static int dprov_digest_final(crypto_ctx_t *, crypto_data_t *,
526     crypto_req_handle_t);
527 static int dprov_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
528     crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
529     crypto_req_handle_t);
530 
531 static crypto_digest_ops_t dprov_digest_ops = {
532 	dprov_digest_init,
533 	dprov_digest,
534 	dprov_digest_update,
535 	dprov_digest_key,
536 	dprov_digest_final,
537 	dprov_digest_atomic
538 };
539 
540 static int dprov_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
541     crypto_spi_ctx_template_t, crypto_req_handle_t);
542 static int dprov_mac(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
543     crypto_req_handle_t);
544 static int dprov_mac_update(crypto_ctx_t *, crypto_data_t *,
545     crypto_req_handle_t);
546 static int dprov_mac_final(crypto_ctx_t *, crypto_data_t *,
547     crypto_req_handle_t);
548 static int dprov_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
549     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
550     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
551 static int dprov_mac_verify_atomic(crypto_provider_handle_t,
552     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
553     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
554 
555 static crypto_mac_ops_t dprov_mac_ops = {
556 	dprov_mac_init,
557 	dprov_mac,
558 	dprov_mac_update,
559 	dprov_mac_final,
560 	dprov_mac_atomic,
561 	dprov_mac_verify_atomic
562 };
563 
564 static int dprov_encrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
565     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
566 static int dprov_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
567     crypto_req_handle_t);
568 static int dprov_encrypt_update(crypto_ctx_t *, crypto_data_t *,
569     crypto_data_t *, crypto_req_handle_t);
570 static int dprov_encrypt_final(crypto_ctx_t *, crypto_data_t *,
571     crypto_req_handle_t);
572 static int dprov_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
573     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
574     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
575 
576 static int dprov_decrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
577     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
578 static int dprov_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
579     crypto_req_handle_t);
580 static int dprov_decrypt_update(crypto_ctx_t *, crypto_data_t *,
581     crypto_data_t *, crypto_req_handle_t);
582 static int dprov_decrypt_final(crypto_ctx_t *, crypto_data_t *,
583     crypto_req_handle_t);
584 static int dprov_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
585     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
586     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
587 
588 static crypto_cipher_ops_t dprov_cipher_ops = {
589 	dprov_encrypt_init,
590 	dprov_encrypt,
591 	dprov_encrypt_update,
592 	dprov_encrypt_final,
593 	dprov_encrypt_atomic,
594 	dprov_decrypt_init,
595 	dprov_decrypt,
596 	dprov_decrypt_update,
597 	dprov_decrypt_final,
598 	dprov_decrypt_atomic
599 };
600 
601 static int dprov_sign_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
602     crypto_spi_ctx_template_t, crypto_req_handle_t);
603 static int dprov_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
604     crypto_req_handle_t);
605 static int dprov_sign_update(crypto_ctx_t *, crypto_data_t *,
606     crypto_req_handle_t);
607 static int dprov_sign_final(crypto_ctx_t *, crypto_data_t *,
608     crypto_req_handle_t);
609 static int dprov_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
610     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
611     crypto_spi_ctx_template_t, crypto_req_handle_t);
612 static int dprov_sign_recover_init(crypto_ctx_t *, crypto_mechanism_t *,
613     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
614 static int dprov_sign_recover(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
615     crypto_req_handle_t);
616 static int dprov_sign_recover_atomic(crypto_provider_handle_t,
617     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
618     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
619     crypto_req_handle_t);
620 
621 static crypto_sign_ops_t dprov_sign_ops = {
622 	dprov_sign_init,
623 	dprov_sign,
624 	dprov_sign_update,
625 	dprov_sign_final,
626 	dprov_sign_atomic,
627 	dprov_sign_recover_init,
628 	dprov_sign_recover,
629 	dprov_sign_recover_atomic
630 };
631 
632 static int dprov_verify_init(crypto_ctx_t *, crypto_mechanism_t *,
633     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
634 static int dprov_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
635     crypto_req_handle_t);
636 static int dprov_verify_update(crypto_ctx_t *, crypto_data_t *,
637     crypto_req_handle_t);
638 static int dprov_verify_final(crypto_ctx_t *, crypto_data_t *,
639     crypto_req_handle_t);
640 static int dprov_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
641     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
642     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
643 static int dprov_verify_recover_init(crypto_ctx_t *, crypto_mechanism_t *,
644     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
645 static int dprov_verify_recover(crypto_ctx_t *, crypto_data_t *,
646     crypto_data_t *, crypto_req_handle_t);
647 static int dprov_verify_recover_atomic(crypto_provider_handle_t,
648     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
649     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
650     crypto_req_handle_t);
651 
652 static crypto_verify_ops_t dprov_verify_ops = {
653 	dprov_verify_init,
654 	dprov_verify,
655 	dprov_verify_update,
656 	dprov_verify_final,
657 	dprov_verify_atomic,
658 	dprov_verify_recover_init,
659 	dprov_verify_recover,
660 	dprov_verify_recover_atomic
661 };
662 
663 static int dprov_digest_encrypt_update(crypto_ctx_t *, crypto_ctx_t *,
664     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
665 static int dprov_decrypt_digest_update(crypto_ctx_t *, crypto_ctx_t *,
666     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
667 static int dprov_sign_encrypt_update(crypto_ctx_t *, crypto_ctx_t *,
668     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
669 static int dprov_decrypt_verify_update(crypto_ctx_t *, crypto_ctx_t *,
670     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
671 
672 static crypto_dual_ops_t dprov_dual_ops = {
673 	dprov_digest_encrypt_update,
674 	dprov_decrypt_digest_update,
675 	dprov_sign_encrypt_update,
676 	dprov_decrypt_verify_update
677 };
678 
679 static int dprov_encrypt_mac_init(crypto_ctx_t *,
680     crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
681     crypto_key_t *, crypto_spi_ctx_template_t,
682     crypto_spi_ctx_template_t, crypto_req_handle_t);
683 static int dprov_encrypt_mac(crypto_ctx_t *,
684     crypto_data_t *, crypto_dual_data_t *, crypto_data_t *,
685     crypto_req_handle_t);
686 static int dprov_encrypt_mac_update(crypto_ctx_t *,
687     crypto_data_t *, crypto_dual_data_t *, crypto_req_handle_t);
688 static int dprov_encrypt_mac_final(crypto_ctx_t *,
689     crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
690 static int dprov_encrypt_mac_atomic(crypto_provider_handle_t,
691     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
692     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
693     crypto_dual_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
694     crypto_spi_ctx_template_t, crypto_req_handle_t);
695 
696 static int dprov_mac_decrypt_init(crypto_ctx_t *,
697     crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
698     crypto_key_t *, crypto_spi_ctx_template_t,
699     crypto_spi_ctx_template_t, crypto_req_handle_t);
700 static int dprov_mac_decrypt(crypto_ctx_t *,
701     crypto_dual_data_t *, crypto_data_t *, crypto_data_t *,
702     crypto_req_handle_t);
703 static int dprov_mac_decrypt_update(crypto_ctx_t *,
704     crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
705 static int dprov_mac_decrypt_final(crypto_ctx_t *,
706     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
707 static int dprov_mac_decrypt_atomic(crypto_provider_handle_t,
708     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
709     crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
710     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
711     crypto_spi_ctx_template_t, crypto_req_handle_t);
712 static int dprov_mac_verify_decrypt_atomic(crypto_provider_handle_t,
713     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
714     crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
715     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
716     crypto_spi_ctx_template_t, crypto_req_handle_t);
717 
718 static crypto_dual_cipher_mac_ops_t dprov_cipher_mac_ops = {
719 	dprov_encrypt_mac_init,
720 	dprov_encrypt_mac,
721 	dprov_encrypt_mac_update,
722 	dprov_encrypt_mac_final,
723 	dprov_encrypt_mac_atomic,
724 	dprov_mac_decrypt_init,
725 	dprov_mac_decrypt,
726 	dprov_mac_decrypt_update,
727 	dprov_mac_decrypt_final,
728 	dprov_mac_decrypt_atomic,
729 	dprov_mac_verify_decrypt_atomic
730 };
731 
732 static int dprov_seed_random(crypto_provider_handle_t, crypto_session_id_t,
733     uchar_t *, size_t, crypto_req_handle_t);
734 static int dprov_generate_random(crypto_provider_handle_t, crypto_session_id_t,
735     uchar_t *, size_t, crypto_req_handle_t);
736 
737 static crypto_random_number_ops_t dprov_random_number_ops = {
738 	dprov_seed_random,
739 	dprov_generate_random
740 };
741 
742 static int dprov_session_open(crypto_provider_handle_t, crypto_session_id_t *,
743     crypto_req_handle_t);
744 static int dprov_session_close(crypto_provider_handle_t, crypto_session_id_t,
745     crypto_req_handle_t);
746 static int dprov_session_login(crypto_provider_handle_t, crypto_session_id_t,
747     crypto_user_type_t, char *, size_t, crypto_req_handle_t);
748 static int dprov_session_logout(crypto_provider_handle_t, crypto_session_id_t,
749     crypto_req_handle_t);
750 
751 static crypto_session_ops_t dprov_session_ops = {
752 	dprov_session_open,
753 	dprov_session_close,
754 	dprov_session_login,
755 	dprov_session_logout
756 };
757 
758 static int dprov_object_create(crypto_provider_handle_t, crypto_session_id_t,
759     crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
760     crypto_req_handle_t);
761 static int dprov_object_copy(crypto_provider_handle_t, crypto_session_id_t,
762     crypto_object_id_t, crypto_object_attribute_t *, uint_t,
763     crypto_object_id_t *, crypto_req_handle_t);
764 static int dprov_object_destroy(crypto_provider_handle_t, crypto_session_id_t,
765     crypto_object_id_t, crypto_req_handle_t);
766 static int dprov_object_get_size(crypto_provider_handle_t, crypto_session_id_t,
767     crypto_object_id_t, size_t *, crypto_req_handle_t);
768 static int dprov_object_get_attribute_value(crypto_provider_handle_t,
769     crypto_session_id_t, crypto_object_id_t,
770     crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
771 static int dprov_object_set_attribute_value(crypto_provider_handle_t,
772     crypto_session_id_t, crypto_object_id_t,
773     crypto_object_attribute_t *,  uint_t, crypto_req_handle_t);
774 static int dprov_object_find_init(crypto_provider_handle_t, crypto_session_id_t,
775     crypto_object_attribute_t *, uint_t, void **,
776     crypto_req_handle_t);
777 static int dprov_object_find(crypto_provider_handle_t, void *,
778     crypto_object_id_t *, uint_t, uint_t *, crypto_req_handle_t);
779 static int dprov_object_find_final(crypto_provider_handle_t, void *,
780     crypto_req_handle_t);
781 
782 static crypto_object_ops_t dprov_object_ops = {
783 	dprov_object_create,
784 	dprov_object_copy,
785 	dprov_object_destroy,
786 	dprov_object_get_size,
787 	dprov_object_get_attribute_value,
788 	dprov_object_set_attribute_value,
789 	dprov_object_find_init,
790 	dprov_object_find,
791 	dprov_object_find_final
792 };
793 
794 static int dprov_key_generate(crypto_provider_handle_t, crypto_session_id_t,
795     crypto_mechanism_t *, crypto_object_attribute_t *, uint_t,
796     crypto_object_id_t *, crypto_req_handle_t);
797 static int dprov_key_generate_pair(crypto_provider_handle_t,
798     crypto_session_id_t, crypto_mechanism_t *, crypto_object_attribute_t *,
799     uint_t, crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
800     crypto_object_id_t *, crypto_req_handle_t);
801 static int dprov_key_wrap(crypto_provider_handle_t, crypto_session_id_t,
802     crypto_mechanism_t *, crypto_key_t *, crypto_object_id_t *,
803     uchar_t *, size_t *, crypto_req_handle_t);
804 static int dprov_key_unwrap(crypto_provider_handle_t, crypto_session_id_t,
805     crypto_mechanism_t *, crypto_key_t *, uchar_t *, size_t *,
806     crypto_object_attribute_t *, uint_t,
807     crypto_object_id_t *, crypto_req_handle_t);
808 static int dprov_key_derive(crypto_provider_handle_t, crypto_session_id_t,
809     crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *,
810     uint_t, crypto_object_id_t *, crypto_req_handle_t);
811 
812 static crypto_key_ops_t dprov_key_ops = {
813 	dprov_key_generate,
814 	dprov_key_generate_pair,
815 	dprov_key_wrap,
816 	dprov_key_unwrap,
817 	dprov_key_derive
818 };
819 
820 static int dprov_ext_info(crypto_provider_handle_t,
821     crypto_provider_ext_info_t *, crypto_req_handle_t);
822 static int dprov_init_token(crypto_provider_handle_t, char *, size_t,
823     char *, crypto_req_handle_t);
824 static int dprov_init_pin(crypto_provider_handle_t, crypto_session_id_t,
825     char *, size_t, crypto_req_handle_t);
826 static int dprov_set_pin(crypto_provider_handle_t, crypto_session_id_t,
827     char *, size_t, char *, size_t, crypto_req_handle_t);
828 
829 static crypto_provider_management_ops_t dprov_management_ops = {
830 	dprov_ext_info,
831 	dprov_init_token,
832 	dprov_init_pin,
833 	dprov_set_pin
834 };
835 
836 static int dprov_free_context(crypto_ctx_t *);
837 
838 static crypto_ctx_ops_t dprov_ctx_ops = {
839 	NULL,
840 	dprov_free_context
841 };
842 
843 static crypto_ops_t dprov_crypto_ops = {
844 	&dprov_control_ops,
845 	&dprov_digest_ops,
846 	&dprov_cipher_ops,
847 	&dprov_mac_ops,
848 	&dprov_sign_ops,
849 	&dprov_verify_ops,
850 	&dprov_dual_ops,
851 	&dprov_cipher_mac_ops,
852 	&dprov_random_number_ops,
853 	&dprov_session_ops,
854 	&dprov_object_ops,
855 	&dprov_key_ops,
856 	&dprov_management_ops,
857 	&dprov_ctx_ops
858 };
859 
860 
861 /* maximum SO and user PIN lengths */
862 #define	DPROV_MAX_PIN_LEN	128
863 
864 /*
865  * Objects: each session is associated with an array of objects.
866  * Unlike PKCS#11, the objects cannot be shared between sessions.
867  * The ioctl driver multiplexes PKCS#11 sessions to providers
868  * sessions in order to support this semantic. This simplifies
869  * the CSPI greatly since the provider does not have to associate
870  * sessions with a user space process.
871  * There is also a per-instance array of objects, which correspond
872  * to PKCS#11 token objects. These objects can be shared by multiple
873  * sesions.
874  *
875  * Token objects are identified by having a CKA_TOKEN attribute B_TRUE.
876  * Private objects are identified by having a CKA_PRIVATE attribute
877  * set to B_TRUE.
878  */
879 
880 #define	DPROV_MAX_OBJECTS	128	/* max # of objects */
881 #define	DPROV_MAX_ATTR		64	/* max # of attributes per object */
882 
883 /* object description */
884 typedef struct dprov_object {
885 	crypto_object_attribute_t do_attr[DPROV_MAX_ATTR]; /* attributes */
886 	uint_t do_token_idx;		/* index in per-instance table */
887 					/* for token objects. */
888 	boolean_t do_destroyed;		/* object has been destroyed. */
889 					/* keep object around until all */
890 					/* sessions that refer to it */
891 					/* are closed, but mark it */
892 					/* destroyed so that references */
893 					/* to the object fail. */
894 					/* used for token objects only */
895 	uint_t do_refcnt;
896 } dprov_object_t;
897 
898 /*
899  * If a session has a reference to a dprov_object_t,
900  * it REFHOLD()s.
901  */
902 #define	DPROV_OBJECT_REFHOLD(object) {		\
903 	atomic_add_32(&(object)->do_refcnt, 1);	\
904 	ASSERT((object)->do_refcnt != 0);		\
905 }
906 
907 /*
908  * Releases a reference to an object. When the last
909  * reference is released, the object is freed.
910  */
911 #define	DPROV_OBJECT_REFRELE(object) {				\
912 	ASSERT((object)->do_refcnt != 0);			\
913 	membar_exit();						\
914 	if (atomic_add_32_nv(&(object)->do_refcnt, -1) == 0)	\
915 		dprov_free_object(object);			\
916 }
917 
918 /*
919  * Object attributes are passed to the provider using crypto_object_attribute
920  * structures, which contain the type of the attribute, a pointer to
921  * it's value, and the length of its value. The attribute types values
922  * are defined by the PKCS#11 specification. This provider only cares
923  * about a subset of these attributes. In order to avoid having to
924  * include the PKCS#11 header files, we define here the attributes values
925  * which are used by the provider.
926  */
927 
928 #define	DPROV_CKA_CLASS			0x00000000
929 #define	DPROV_CKA_TOKEN			0x00000001
930 #define	DPROV_CKA_PRIVATE		0x00000002
931 #define	DPROV_CKA_VALUE			0x00000011
932 #define	DPROV_CKA_KEY_TYPE		0x00000100
933 #define	DPROV_CKA_ENCRYPT		0x00000104
934 #define	DPROV_CKA_DECRYPT		0x00000105
935 #define	DPROV_CKA_WRAP			0x00000106
936 #define	DPROV_CKA_UNWRAP		0x00000107
937 #define	DPROV_CKA_SIGN			0x00000108
938 #define	DPROV_CKA_SIGN_RECOVER		0x00000109
939 #define	DPROV_CKA_VERIFY		0x0000010A
940 #define	DPROV_CKA_VERIFY_RECOVER	0x0000010B
941 #define	DPROV_CKA_DERIVE		0x0000010C
942 #define	DPROV_CKA_MODULUS		0x00000120
943 #define	DPROV_CKA_MODULUS_BITS		0x00000121
944 #define	DPROV_CKA_PUBLIC_EXPONENT	0x00000122
945 #define	DPROV_CKA_PRIVATE_EXPONENT	0x00000123
946 #define	DPROV_CKA_VALUE_BITS		0x00000160
947 #define	DPROV_CKA_VALUE_LEN		0x00000161
948 #define	DPROV_CKA_EXTRACTABLE		0x00000162
949 
950 /*
951  * Object classes from PKCS#11
952  */
953 #define	DPROV_CKO_DATA			0x00000000
954 #define	DPROV_CKO_CERTIFICATE		0x00000001
955 #define	DPROV_CKO_PUBLIC_KEY		0x00000002
956 #define	DPROV_CKO_PRIVATE_KEY		0x00000003
957 #define	DPROV_CKO_SECRET_KEY		0x00000004
958 #define	DPROV_CKO_HW_FEATURE		0x00000005
959 #define	DPROV_CKO_DOMAIN_PARAMETERS	0x00000006
960 #define	DPROV_CKO_VENDOR_DEFINED	0x80000000
961 
962 /*
963  * A few key types from PKCS#11
964  */
965 #define	DPROV_CKK_RSA			0x00000000
966 #define	DPROV_CKK_GENERIC_SECRET	0x00000010
967 #define	DPROV_CKK_RC4			0x00000012
968 #define	DPROV_CKK_DES			0x00000013
969 #define	DPROV_CKK_DES3			0x00000015
970 #define	DPROV_CKK_AES			0x0000001F
971 
972 /*
973  * Find object context. Allows the find object init/find/final
974  * to store data persistent across calls.
975  */
976 typedef struct dprov_find_ctx {
977 	crypto_object_id_t fc_ids[DPROV_MAX_OBJECTS];	/* object ids */
978 	uint_t fc_nids;			/* number of ids in fc_ids */
979 	uint_t fc_next;			/* next id to return */
980 } dprov_find_ctx_t;
981 
982 /*
983  * Session management: each instance is associated with an array
984  * of sessions. KEF providers sessions are always R/W the library and
985  * the ioctl maintain the PKCS#11 R/W attributes for the session.
986  */
987 
988 #define	DPROV_MIN_SESSIONS	32	/* # of sessions to start with */
989 
990 typedef enum dprov_session_state {
991 	DPROV_SESSION_STATE_PUBLIC,	/* public (default) */
992 	DPROV_SESSION_STATE_SO,		/* SO logged in */
993 	DPROV_SESSION_STATE_USER	/* user logged in */
994 } dprov_session_state_t;
995 
996 /* session description */
997 typedef struct dprov_session {
998 	dprov_session_state_t ds_state;	/* session state */
999 	dprov_object_t *ds_objects[DPROV_MAX_OBJECTS];	/* session objects */
1000 } dprov_session_t;
1001 
1002 
1003 static crypto_provider_info_t dprov_prov_info = {
1004 	CRYPTO_SPI_VERSION_1,
1005 	"Dummy Pseudo HW Provider",
1006 	CRYPTO_HW_PROVIDER,
1007 	NULL,				/* pi_provider_dev */
1008 	NULL,				/* pi_provider_handle */
1009 	&dprov_crypto_ops,
1010 	sizeof (dprov_mech_info_tab)/sizeof (crypto_mech_info_t),
1011 	dprov_mech_info_tab,
1012 	0,				/* pi_logical_provider_count */
1013 	NULL				/* pi_logical_providers */
1014 };
1015 
1016 /*
1017  * Per-instance info.
1018  */
1019 typedef struct dprov_state {
1020 	kmutex_t ds_lock;		/* per-instance lock */
1021 	dev_info_t *ds_dip;		/* device info */
1022 	crypto_kcf_provider_handle_t ds_prov_handle;	/* framework handle */
1023 	taskq_t *ds_taskq;		/* taskq for async behavior */
1024 	char ds_user_pin[DPROV_MAX_PIN_LEN];	/* normal user PIN */
1025 	uint_t ds_user_pin_len;
1026 	char ds_so_pin[DPROV_MAX_PIN_LEN];	/* SO PIN */
1027 	uint_t ds_so_pin_len;
1028 	dprov_session_t **ds_sessions;	/* sessions for this instance */
1029 	uint_t ds_sessions_slots;	/* number of session slots */
1030 	uint_t ds_sessions_count;	/* number of open sessions */
1031 	boolean_t ds_token_initialized;	/* provider initialized? */
1032 	boolean_t ds_user_pin_set;	/* user pin set? */
1033 	char ds_label[CRYPTO_EXT_SIZE_LABEL];		/* "token" label */
1034 	dprov_object_t *ds_objects[DPROV_MAX_OBJECTS];	/* "token" objects */
1035 } dprov_state_t;
1036 
1037 
1038 /*
1039  * A taskq is associated with each instance of the pseudo driver in order
1040  * to simulate the asynchronous execution of requests.
1041  * The following defines the taskq request structures.
1042  */
1043 
1044 /* request types */
1045 typedef enum dprov_req_type {
1046 	/* digest requests */
1047 	DPROV_REQ_DIGEST_INIT = 1,
1048 	DPROV_REQ_DIGEST,
1049 	DPROV_REQ_DIGEST_UPDATE,
1050 	DPROV_REQ_DIGEST_KEY,
1051 	DPROV_REQ_DIGEST_FINAL,
1052 	DPROV_REQ_DIGEST_ATOMIC,
1053 	/* cipher requests */
1054 	DPROV_REQ_ENCRYPT_INIT,
1055 	DPROV_REQ_ENCRYPT,
1056 	DPROV_REQ_ENCRYPT_UPDATE,
1057 	DPROV_REQ_ENCRYPT_FINAL,
1058 	DPROV_REQ_ENCRYPT_ATOMIC,
1059 	DPROV_REQ_DECRYPT_INIT,
1060 	DPROV_REQ_DECRYPT,
1061 	DPROV_REQ_DECRYPT_UPDATE,
1062 	DPROV_REQ_DECRYPT_FINAL,
1063 	DPROV_REQ_DECRYPT_ATOMIC,
1064 	/* mac requests */
1065 	DPROV_REQ_MAC_INIT,
1066 	DPROV_REQ_MAC,
1067 	DPROV_REQ_MAC_UPDATE,
1068 	DPROV_REQ_MAC_FINAL,
1069 	DPROV_REQ_MAC_ATOMIC,
1070 	DPROV_REQ_MAC_VERIFY_ATOMIC,
1071 	/* sign requests */
1072 	DPROV_REQ_SIGN_INIT,
1073 	DPROV_REQ_SIGN,
1074 	DPROV_REQ_SIGN_UPDATE,
1075 	DPROV_REQ_SIGN_FINAL,
1076 	DPROV_REQ_SIGN_ATOMIC,
1077 	DPROV_REQ_SIGN_RECOVER_INIT,
1078 	DPROV_REQ_SIGN_RECOVER,
1079 	DPROV_REQ_SIGN_RECOVER_ATOMIC,
1080 	/* verify requests */
1081 	DPROV_REQ_VERIFY_INIT,
1082 	DPROV_REQ_VERIFY,
1083 	DPROV_REQ_VERIFY_UPDATE,
1084 	DPROV_REQ_VERIFY_FINAL,
1085 	DPROV_REQ_VERIFY_ATOMIC,
1086 	DPROV_REQ_VERIFY_RECOVER_INIT,
1087 	DPROV_REQ_VERIFY_RECOVER,
1088 	DPROV_REQ_VERIFY_RECOVER_ATOMIC,
1089 	/* dual ops requests */
1090 	DPROV_REQ_DIGEST_ENCRYPT_UPDATE,
1091 	DPROV_REQ_DECRYPT_DIGEST_UPDATE,
1092 	DPROV_REQ_SIGN_ENCRYPT_UPDATE,
1093 	DPROV_REQ_DECRYPT_VERIFY_UPDATE,
1094 	/* dual cipher/mac requests */
1095 	DPROV_REQ_ENCRYPT_MAC_INIT,
1096 	DPROV_REQ_ENCRYPT_MAC,
1097 	DPROV_REQ_ENCRYPT_MAC_UPDATE,
1098 	DPROV_REQ_ENCRYPT_MAC_FINAL,
1099 	DPROV_REQ_ENCRYPT_MAC_ATOMIC,
1100 	DPROV_REQ_MAC_DECRYPT_INIT,
1101 	DPROV_REQ_MAC_DECRYPT,
1102 	DPROV_REQ_MAC_DECRYPT_UPDATE,
1103 	DPROV_REQ_MAC_DECRYPT_FINAL,
1104 	DPROV_REQ_MAC_DECRYPT_ATOMIC,
1105 	DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC,
1106 	/* random number ops */
1107 	DPROV_REQ_RANDOM_SEED,
1108 	DPROV_REQ_RANDOM_GENERATE,
1109 	/* session management requests */
1110 	DPROV_REQ_SESSION_OPEN,
1111 	DPROV_REQ_SESSION_CLOSE,
1112 	DPROV_REQ_SESSION_LOGIN,
1113 	DPROV_REQ_SESSION_LOGOUT,
1114 	/* object management requests */
1115 	DPROV_REQ_OBJECT_CREATE,
1116 	DPROV_REQ_OBJECT_COPY,
1117 	DPROV_REQ_OBJECT_DESTROY,
1118 	DPROV_REQ_OBJECT_GET_SIZE,
1119 	DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE,
1120 	DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE,
1121 	DPROV_REQ_OBJECT_FIND_INIT,
1122 	DPROV_REQ_OBJECT_FIND,
1123 	DPROV_REQ_OBJECT_FIND_FINAL,
1124 	/* key management requests */
1125 	DPROV_REQ_KEY_GENERATE,
1126 	DPROV_REQ_KEY_GENERATE_PAIR,
1127 	DPROV_REQ_KEY_WRAP,
1128 	DPROV_REQ_KEY_UNWRAP,
1129 	DPROV_REQ_KEY_DERIVE,
1130 	/* provider management requests */
1131 	DPROV_REQ_MGMT_EXTINFO,
1132 	DPROV_REQ_MGMT_INITTOKEN,
1133 	DPROV_REQ_MGMT_INITPIN,
1134 	DPROV_REQ_MGMT_SETPIN
1135 } dprov_req_type_t;
1136 
1137 /* for DPROV_REQ_DIGEST requests */
1138 typedef struct dprov_digest_req {
1139 	crypto_mechanism_t *dr_mechanism;
1140 	crypto_ctx_t *dr_ctx;
1141 	crypto_data_t *dr_data;
1142 	crypto_key_t *dr_key;
1143 	crypto_data_t *dr_digest;
1144 } dprov_digest_req_t;
1145 
1146 /* for DPROV_REQ_MAC requests */
1147 typedef struct dprov_mac_req {
1148 	crypto_mechanism_t *dr_mechanism;
1149 	crypto_ctx_t *dr_ctx;
1150 	crypto_data_t *dr_data;
1151 	crypto_key_t *dr_key;
1152 	crypto_data_t *dr_mac;
1153 	crypto_session_id_t dr_session_id;
1154 } dprov_mac_req_t;
1155 
1156 /* for DPROV_REQ_ENCRYPT and DPROV_REQ_DECRYPT requests */
1157 typedef struct dprov_cipher_req {
1158 	crypto_mechanism_t *dr_mechanism;
1159 	crypto_ctx_t *dr_ctx;
1160 	crypto_key_t *dr_key;
1161 	crypto_data_t *dr_plaintext;
1162 	crypto_data_t *dr_ciphertext;
1163 	crypto_session_id_t dr_session_id;
1164 } dprov_cipher_req_t;
1165 
1166 /* for DPROV_REQ_SIGN requests */
1167 typedef struct dprov_sign_req {
1168 	crypto_mechanism_t *sr_mechanism;
1169 	crypto_ctx_t *sr_ctx;
1170 	crypto_key_t *sr_key;
1171 	crypto_data_t *sr_data;
1172 	crypto_data_t *sr_signature;
1173 	crypto_session_id_t sr_session_id;
1174 } dprov_sign_req_t;
1175 
1176 /* for DPROV_REQ_VERIFY requests */
1177 typedef struct dprov_verify_req {
1178 	crypto_mechanism_t *vr_mechanism;
1179 	crypto_ctx_t *vr_ctx;
1180 	crypto_key_t *vr_key;
1181 	crypto_data_t *vr_data;
1182 	crypto_data_t *vr_signature;
1183 	crypto_session_id_t vr_session_id;
1184 } dprov_verify_req_t;
1185 
1186 /* for dual ops requests */
1187 typedef struct dprov_dual_req {
1188 	crypto_ctx_t *dr_signverify_ctx;
1189 	crypto_ctx_t *dr_cipher_ctx;
1190 	crypto_data_t *dr_plaintext;
1191 	crypto_data_t *dr_ciphertext;
1192 } dprov_dual_req_t;
1193 
1194 /* for cipher/mac dual ops requests */
1195 typedef struct dprov_cipher_mac_req {
1196 	crypto_session_id_t mr_session_id;
1197 	crypto_ctx_t *mr_ctx;
1198 	crypto_mechanism_t *mr_cipher_mech;
1199 	crypto_key_t *mr_cipher_key;
1200 	crypto_mechanism_t *mr_mac_mech;
1201 	crypto_key_t *mr_mac_key;
1202 	crypto_dual_data_t *mr_dual_data;
1203 	crypto_data_t *mr_data;
1204 	crypto_data_t *mr_mac;
1205 } dprov_cipher_mac_req_t;
1206 
1207 /* for DPROV_REQ_RANDOM requests */
1208 typedef struct dprov_random_req {
1209 	uchar_t *rr_buf;
1210 	size_t rr_len;
1211 	crypto_session_id_t rr_session_id;
1212 } dprov_random_req_t;
1213 
1214 /* for DPROV_REQ_SESSION requests */
1215 typedef struct dprov_session_req {
1216 	crypto_session_id_t *sr_session_id_ptr;
1217 	crypto_session_id_t sr_session_id;
1218 	crypto_user_type_t sr_user_type;
1219 	char *sr_pin;
1220 	size_t sr_pin_len;
1221 } dprov_session_req_t;
1222 
1223 /* for DPROV_REQ_OBJECT requests */
1224 typedef struct dprov_object_req {
1225 	crypto_session_id_t or_session_id;
1226 	crypto_object_id_t or_object_id;
1227 	crypto_object_attribute_t *or_template;
1228 	uint_t or_attribute_count;
1229 	crypto_object_id_t *or_object_id_ptr;
1230 	size_t *or_object_size;
1231 	void **or_find_pp;
1232 	void *or_find_p;
1233 	uint_t or_max_object_count;
1234 	uint_t *or_object_count_ptr;
1235 } dprov_object_req_t;
1236 
1237 /* for DPROV_REQ_KEY requests */
1238 typedef struct dprov_key_req {
1239 	crypto_session_id_t kr_session_id;
1240 	crypto_mechanism_t *kr_mechanism;
1241 	crypto_object_attribute_t *kr_template;
1242 	uint_t kr_attribute_count;
1243 	crypto_object_id_t *kr_object_id_ptr;
1244 	crypto_object_attribute_t *kr_private_key_template;
1245 	uint_t kr_private_key_attribute_count;
1246 	crypto_object_id_t *kr_private_key_object_id_ptr;
1247 	crypto_key_t *kr_key;
1248 	uchar_t *kr_wrapped_key;
1249 	size_t *kr_wrapped_key_len_ptr;
1250 } dprov_key_req_t;
1251 
1252 /* for DPROV_REQ_MGMT requests */
1253 typedef struct dprov_mgmt_req {
1254 	crypto_session_id_t mr_session_id;
1255 	char *mr_pin;
1256 	size_t mr_pin_len;
1257 	char *mr_old_pin;
1258 	size_t mr_old_pin_len;
1259 	char *mr_label;
1260 	crypto_provider_ext_info_t *mr_ext_info;
1261 } dprov_mgmt_req_t;
1262 
1263 /* request, as queued on taskq */
1264 typedef struct dprov_req {
1265 	dprov_req_type_t dr_type;
1266 	dprov_state_t *dr_softc;
1267 	crypto_req_handle_t dr_kcf_req;
1268 	union {
1269 		dprov_digest_req_t dru_digest_req;
1270 		dprov_mac_req_t dru_mac_req;
1271 		dprov_cipher_req_t dru_cipher_req;
1272 		dprov_sign_req_t dru_sign_req;
1273 		dprov_verify_req_t dru_verify_req;
1274 		dprov_dual_req_t dru_dual_req;
1275 		dprov_cipher_mac_req_t dru_cipher_mac_req;
1276 		dprov_random_req_t dru_random_req;
1277 		dprov_session_req_t dru_session_req;
1278 		dprov_object_req_t dru_object_req;
1279 		dprov_key_req_t dru_key_req;
1280 		dprov_mgmt_req_t dru_mgmt_req;
1281 	} dr_req;
1282 } dprov_req_t;
1283 
1284 /* shortcuts for union fields */
1285 #define	dr_digest_req		dr_req.dru_digest_req
1286 #define	dr_mac_req		dr_req.dru_mac_req
1287 #define	dr_cipher_req		dr_req.dru_cipher_req
1288 #define	dr_sign_req		dr_req.dru_sign_req
1289 #define	dr_verify_req		dr_req.dru_verify_req
1290 #define	dr_dual_req		dr_req.dru_dual_req
1291 #define	dr_cipher_mac_req	dr_req.dru_cipher_mac_req
1292 #define	dr_random_req		dr_req.dru_random_req
1293 #define	dr_session_req		dr_req.dru_session_req
1294 #define	dr_object_req		dr_req.dru_object_req
1295 #define	dr_key_req		dr_req.dru_key_req
1296 #define	dr_mgmt_req		dr_req.dru_mgmt_req
1297 
1298 /* prototypes for the tasq dispatcher functions */
1299 static void dprov_digest_task(dprov_req_t *);
1300 static void dprov_mac_task(dprov_req_t *);
1301 static void dprov_sign_task(dprov_req_t *);
1302 static void dprov_verify_task(dprov_req_t *);
1303 static void dprov_dual_task(dprov_req_t *);
1304 static void dprov_cipher_task(dprov_req_t *);
1305 static void dprov_cipher_mac_task(dprov_req_t *);
1306 static void dprov_random_task(dprov_req_t *);
1307 static void dprov_session_task(dprov_req_t *);
1308 static void dprov_object_task(dprov_req_t *);
1309 static void dprov_key_task(dprov_req_t *);
1310 static void dprov_mgmt_task(dprov_req_t *);
1311 
1312 /* helper functions */
1313 static int dprov_digest_submit_req(dprov_req_type_t, dprov_state_t *,
1314     crypto_req_handle_t, crypto_mechanism_t *, crypto_data_t *, crypto_key_t *,
1315     crypto_data_t *, crypto_ctx_t *, int);
1316 static int dprov_cipher_submit_req(dprov_req_type_t, dprov_state_t *,
1317     crypto_req_handle_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1318     crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1319 static int dprov_mac_submit_req(dprov_req_type_t, dprov_state_t *,
1320     crypto_req_handle_t, crypto_mechanism_t *, crypto_data_t *,
1321     crypto_key_t *, crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1322 static int dprov_sign_submit_req(dprov_req_type_t, dprov_state_t *,
1323     crypto_req_handle_t, crypto_mechanism_t *, crypto_key_t *,
1324     crypto_data_t *, crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1325 static int dprov_verify_submit_req(dprov_req_type_t, dprov_state_t *,
1326     crypto_req_handle_t, crypto_mechanism_t *, crypto_key_t *,
1327     crypto_data_t *, crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1328 static int dprov_dual_submit_req(dprov_req_type_t, dprov_state_t *,
1329     crypto_req_handle_t, crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
1330     crypto_data_t *);
1331 static int dprov_cipher_mac_submit_req(dprov_req_type_t, dprov_state_t *,
1332     crypto_req_handle_t, crypto_ctx_t *, crypto_session_id_t,
1333     crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *, crypto_key_t *,
1334     crypto_dual_data_t *, crypto_data_t *, crypto_data_t *, int);
1335 static int dprov_random_submit_req(dprov_req_type_t, dprov_state_t *,
1336     crypto_req_handle_t, uchar_t *, size_t, crypto_session_id_t);
1337 static int dprov_session_submit_req(dprov_req_type_t, dprov_state_t *,
1338     crypto_req_handle_t, crypto_session_id_t *, crypto_session_id_t,
1339     crypto_user_type_t, char *, size_t);
1340 static int dprov_object_submit_req(dprov_req_type_t, dprov_state_t *,
1341     crypto_req_handle_t, crypto_session_id_t, crypto_object_id_t,
1342     crypto_object_attribute_t *, uint_t, crypto_object_id_t *, size_t *,
1343     void **, void *, uint_t, uint_t *, int);
1344 static int dprov_key_submit_req(dprov_req_type_t, dprov_state_t *,
1345     crypto_req_handle_t, crypto_session_id_t, crypto_mechanism_t *,
1346     crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
1347     crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
1348     crypto_key_t *, uchar_t *, size_t *);
1349 static int dprov_mgmt_submit_req(dprov_req_type_t, dprov_state_t *,
1350     crypto_req_handle_t, crypto_session_id_t, char *, size_t, char *, size_t,
1351     char *, crypto_provider_ext_info_t *);
1352 static int dprov_get_sw_prov(crypto_mechanism_t *, kcf_provider_desc_t **,
1353     crypto_mech_type_t *);
1354 
1355 /* object management helper functions */
1356 static void dprov_free_object(dprov_object_t *);
1357 static void dprov_release_session_objects(dprov_session_t *);
1358 static boolean_t dprov_object_is_private(dprov_object_t *);
1359 static boolean_t dprov_object_is_token(dprov_object_t *);
1360 static int dprov_key_value_secret(dprov_state_t *, crypto_session_id_t,
1361     dprov_req_type_t, crypto_key_t *, crypto_key_t *);
1362 static int dprov_key_attr_asymmetric(dprov_state_t *, crypto_session_id_t,
1363     dprov_req_type_t, crypto_key_t *, crypto_key_t *);
1364 static int dprov_get_object_attr_boolean(dprov_object_t *, uint64_t,
1365 	boolean_t *);
1366 static int dprov_get_object_attr_ulong(dprov_object_t *, uint64_t, ulong_t *);
1367 static int dprov_get_object_attr_array(dprov_object_t *, uint64_t, void **,
1368     size_t *);
1369 static int dprov_get_key_attr_ulong(crypto_key_t *, uint64_t, ulong_t *);
1370 static int dprov_get_key_attr_array(crypto_key_t *, uint64_t, void **,
1371     size_t *);
1372 static int dprov_create_object_from_template(dprov_state_t *, dprov_session_t *,
1373     crypto_object_attribute_t *, uint_t, crypto_object_id_t *, boolean_t,
1374     boolean_t);
1375 static int dprov_get_template_attr_scalar_common(crypto_object_attribute_t *,
1376     uint_t, uint64_t, void *, size_t);
1377 static int dprov_get_template_attr_boolean(crypto_object_attribute_t *,
1378     uint_t, uint64_t, boolean_t *);
1379 static int dprov_get_template_attr_ulong(crypto_object_attribute_t *, uint_t,
1380     uint64_t, ulong_t *);
1381 static int dprov_template_attr_present(crypto_object_attribute_t *, uint_t,
1382     uint64_t);
1383 static int dprov_get_template_attr_array(crypto_object_attribute_t *, uint_t,
1384     uint64_t, void **, size_t *);
1385 static int dprov_destroy_object(dprov_state_t *, dprov_session_t *,
1386     crypto_object_id_t);
1387 static int dprov_object_set_attr(dprov_session_t *, crypto_object_id_t,
1388     crypto_object_attribute_t *, uint_t, boolean_t);
1389 static int dprov_find_attr(crypto_object_attribute_t *, uint_t, uint64_t);
1390 static boolean_t dprov_attributes_match(dprov_object_t *,
1391     crypto_object_attribute_t *, uint_t);
1392 
1393 /* retrieve the softc and instance number from a SPI crypto context */
1394 #define	DPROV_SOFTC_FROM_CTX(ctx, softc, instance) {	\
1395 	(softc) = (dprov_state_t *)(ctx)->cc_provider;	\
1396 	(instance) = ddi_get_instance((softc)->ds_dip);	\
1397 }
1398 
1399 /* retrieve the softc and instance number from a taskq request */
1400 #define	DPROV_SOFTC_FROM_REQ(req, softc, instance) {	\
1401 	(softc) = (req)->dr_softc;			\
1402 	(instance) = ddi_get_instance((softc)->ds_dip);	\
1403 }
1404 
1405 /*
1406  * The dprov private context most of the time contains a pointer to the
1407  * crypto_context_t that was allocated when calling a KCF function.
1408  * Dual cipher/mac operations however require the dprov driver
1409  * to maintain the contexts associated with the separate cipher
1410  * and mac operations. These two types of dprov contexts are
1411  * defined below.
1412  */
1413 typedef enum dprov_ctx_type {
1414 	DPROV_CTX_SINGLE,
1415 	DPROV_CTX_DUAL
1416 } dprov_ctx_type_t;
1417 
1418 /*
1419  * When the context refers to a single KCF context, the
1420  * cc_provider field of a crypto_ctx_t points to a structure of
1421  * type dprov_ctx_single.
1422  */
1423 typedef struct dprov_ctx_single {
1424 	dprov_ctx_type_t dc_type;
1425 	crypto_context_t dc_ctx;
1426 } dprov_ctx_single_t;
1427 
1428 /*
1429  * When the context is used for cipher/mac operations, it contains
1430  * pointers to to KCF contexts, one for the cipher operation, the
1431  * other for the mac operation.
1432  */
1433 typedef struct dprov_ctx_dual {
1434 	dprov_ctx_type_t cd_type;
1435 	crypto_context_t cd_cipher_ctx;
1436 	crypto_context_t cd_mac_ctx;
1437 } dprov_ctx_dual_t;
1438 
1439 /*
1440  * Helper macros for context accessors. These macros return the
1441  * k-API context corresponding to the given SPI context for
1442  * single and dual cipher/mac operations.
1443  */
1444 
1445 #define	DPROV_CTX_SINGLE(_ctx) \
1446 	(((dprov_ctx_single_t *)(_ctx)->cc_provider_private)->dc_ctx)
1447 
1448 #define	DPROV_CTX_DUAL_CIPHER(_ctx) \
1449 	(((dprov_ctx_dual_t *)(_ctx)->cc_provider_private)->cd_cipher_ctx)
1450 
1451 #define	DPROV_CTX_DUAL_MAC(_ctx) \
1452 	(((dprov_ctx_dual_t *)(_ctx)->cc_provider_private)->cd_mac_ctx)
1453 
1454 static int dprov_alloc_context(dprov_req_type_t, crypto_ctx_t *);
1455 
1456 
1457 
1458 static void *statep;	/* state pointer */
1459 
1460 /*
1461  * DDI entry points.
1462  */
1463 int
1464 _init(void)
1465 {
1466 	int error;
1467 
1468 	DPROV_DEBUG(D_INIT, ("dprov: in _init\n"));
1469 
1470 	if ((error = ddi_soft_state_init(&statep, sizeof (dprov_state_t),
1471 	    0)) != 0)
1472 		return (error);
1473 
1474 	return (mod_install(&modlinkage));
1475 }
1476 
1477 int
1478 _fini(void)
1479 {
1480 	int error;
1481 
1482 	DPROV_DEBUG(D_INIT, ("dprov: in _fini\n"));
1483 
1484 	if ((error = mod_remove(&modlinkage)) != 0)
1485 		return (error);
1486 
1487 	ddi_soft_state_fini(&statep);
1488 
1489 	return (0);
1490 }
1491 
1492 int
1493 _info(struct modinfo *modinfop)
1494 {
1495 	DPROV_DEBUG(D_INIT, ("dprov: in _info\n"));
1496 
1497 	return (mod_info(&modlinkage, modinfop));
1498 }
1499 
1500 /* ARGSUSED */
1501 static int
1502 dprov_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1503 {
1504 	int instance = getminor((dev_t)arg);
1505 	dprov_state_t *softc;
1506 
1507 	DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_getinfo() for %d\n",
1508 	    instance));
1509 
1510 	switch (cmd) {
1511 	case DDI_INFO_DEVT2DEVINFO:
1512 		softc = ddi_get_soft_state(statep, instance);
1513 		*result = softc->ds_dip;
1514 		return (DDI_SUCCESS);
1515 
1516 	case DDI_INFO_DEVT2INSTANCE:
1517 		*result = (void *)(uintptr_t)instance;
1518 		return (DDI_SUCCESS);
1519 	}
1520 	return (DDI_FAILURE);
1521 }
1522 
1523 static int
1524 dprov_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1525 {
1526 	int instance = ddi_get_instance(dip);
1527 	dprov_state_t *softc;
1528 	char devname[256];
1529 	int ret;
1530 
1531 	DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_attach() for %d\n",
1532 	    instance));
1533 
1534 	if (cmd != DDI_ATTACH) {
1535 		return (DDI_FAILURE);
1536 	}
1537 
1538 	/* get new softc and initialize it */
1539 	if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS)
1540 		return (DDI_FAILURE);
1541 
1542 	softc = ddi_get_soft_state(statep, instance);
1543 	mutex_init(&softc->ds_lock, NULL, MUTEX_DRIVER, NULL);
1544 	softc->ds_dip = dip;
1545 	softc->ds_prov_handle = NULL;
1546 
1547 	/* create minor node */
1548 	(void) sprintf(devname, "dprov%d", instance);
1549 	if (ddi_create_minor_node(dip, devname, S_IFCHR, instance,
1550 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
1551 		cmn_err(CE_WARN, "attach: failed creating minor node");
1552 		mutex_destroy(&softc->ds_lock);
1553 		ddi_soft_state_free(statep, instance);
1554 		return (DDI_FAILURE);
1555 	}
1556 
1557 	/* create taskq */
1558 	softc->ds_taskq = taskq_create(devname, 1, minclsyspri,
1559 	    crypto_taskq_minalloc, crypto_taskq_maxalloc, TASKQ_PREPOPULATE);
1560 
1561 	/* initialize table of sessions */
1562 	softc->ds_sessions = kmem_zalloc(DPROV_MIN_SESSIONS *
1563 	    sizeof (dprov_session_t *), KM_SLEEP);
1564 	softc->ds_sessions_slots = DPROV_MIN_SESSIONS;
1565 	softc->ds_sessions_count = 0;
1566 
1567 	/* initialized done by init_token entry point */
1568 	softc->ds_token_initialized = B_TRUE;
1569 
1570 	bcopy("changeme", softc->ds_user_pin, 8);
1571 	softc->ds_user_pin_len = 8;
1572 	softc->ds_user_pin_set = B_TRUE;
1573 
1574 	/* register with the crypto framework */
1575 	dprov_prov_info.pi_provider_dev.pd_hw = dip;
1576 	dprov_prov_info.pi_provider_handle = softc;
1577 	if ((ret = crypto_register_provider(&dprov_prov_info,
1578 	    &softc->ds_prov_handle)) != CRYPTO_SUCCESS) {
1579 		cmn_err(CE_WARN,
1580 		    "dprov crypto_register_provider() failed (0x%x)", ret);
1581 		taskq_destroy(softc->ds_taskq);
1582 		kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
1583 		    sizeof (dprov_session_t *));
1584 		mutex_destroy(&softc->ds_lock);
1585 		ddi_soft_state_free(statep, instance);
1586 		ddi_remove_minor_node(dip, NULL);
1587 		return (DDI_FAILURE);
1588 	}
1589 
1590 	/*
1591 	 * This call is for testing only; it is not required by the SPI.
1592 	 */
1593 	crypto_provider_notification(softc->ds_prov_handle,
1594 	    CRYPTO_PROVIDER_READY);
1595 
1596 	return (DDI_SUCCESS);
1597 }
1598 
1599 static int
1600 dprov_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1601 {
1602 	int instance = ddi_get_instance(dip);
1603 	dprov_state_t *softc = ddi_get_soft_state(statep, instance);
1604 	dprov_session_t *session;
1605 	int i, ret;
1606 
1607 	DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_detach() for %d\n",
1608 	    instance));
1609 
1610 	if (cmd != DDI_DETACH)
1611 		return (DDI_FAILURE);
1612 
1613 	/* unregister from the crypto framework */
1614 	if (softc->ds_prov_handle != NULL)
1615 		if ((ret = crypto_unregister_provider(
1616 		    softc->ds_prov_handle)) != CRYPTO_SUCCESS) {
1617 			cmn_err(CE_WARN, "dprov_detach: "
1618 			    "crypto_unregister_provider() "
1619 			    "failed (0x%x)", ret);
1620 			return (DDI_FAILURE);
1621 		}
1622 
1623 
1624 	taskq_destroy(softc->ds_taskq);
1625 
1626 	for (i = 0; i < softc->ds_sessions_slots; i++) {
1627 		if ((session = softc->ds_sessions[i]) == NULL)
1628 			continue;
1629 
1630 		dprov_release_session_objects(session);
1631 
1632 		kmem_free(session, sizeof (dprov_session_t));
1633 		softc->ds_sessions_count--;
1634 
1635 	}
1636 
1637 	kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
1638 	    sizeof (dprov_session_t *));
1639 	/* free token objects */
1640 	for (i = 0; i < DPROV_MAX_OBJECTS; i++)
1641 		if (softc->ds_objects[i] != NULL)
1642 			dprov_free_object(softc->ds_objects[i]);
1643 
1644 	mutex_destroy(&softc->ds_lock);
1645 	ddi_soft_state_free(statep, instance);
1646 
1647 	ddi_remove_minor_node(dip, NULL);
1648 
1649 	return (DDI_SUCCESS);
1650 }
1651 
1652 /*
1653  * Control entry points.
1654  */
1655 static void
1656 dprov_provider_status(crypto_provider_handle_t provider, uint_t *status)
1657 {
1658 	_NOTE(ARGUNUSED(provider))
1659 
1660 	*status = CRYPTO_PROVIDER_READY;
1661 }
1662 
1663 /*
1664  * Digest entry points.
1665  */
1666 
1667 static int
1668 dprov_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
1669     crypto_req_handle_t req)
1670 {
1671 	int error = CRYPTO_FAILED;
1672 	dprov_state_t *softc;
1673 	/* LINTED E_FUNC_SET_NOT_USED */
1674 	int instance;
1675 
1676 	/* extract softc and instance number from context */
1677 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1678 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_init: started\n", instance));
1679 
1680 	/* check mechanism */
1681 	if (mechanism->cm_type != MD5_MECH_INFO_TYPE &&
1682 	    mechanism->cm_type != SHA1_MECH_INFO_TYPE &&
1683 	    mechanism->cm_type != SHA256_MECH_INFO_TYPE &&
1684 	    mechanism->cm_type != SHA384_MECH_INFO_TYPE &&
1685 	    mechanism->cm_type != SHA512_MECH_INFO_TYPE) {
1686 		cmn_err(CE_WARN, "dprov_digest_init: unexpected mech type "
1687 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
1688 		return (CRYPTO_MECHANISM_INVALID);
1689 	}
1690 
1691 	/* submit request to the taskq */
1692 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_INIT, softc, req,
1693 	    mechanism, NULL, NULL, NULL, ctx, KM_SLEEP);
1694 
1695 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_init: done err = 0x%x\n",
1696 	    instance, error));
1697 
1698 	return (error);
1699 }
1700 
1701 static int
1702 dprov_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
1703     crypto_req_handle_t req)
1704 {
1705 	int error = CRYPTO_FAILED;
1706 	dprov_state_t *softc;
1707 	/* LINTED E_FUNC_SET_NOT_USED */
1708 	int instance;
1709 
1710 	/* extract softc and instance number from context */
1711 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1712 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest: started\n", instance));
1713 
1714 	/* submit request to the taskq */
1715 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST, softc, req,
1716 	    NULL, data, NULL, digest, ctx, KM_NOSLEEP);
1717 
1718 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest: done, err = 0x%x\n",
1719 	    instance, error));
1720 
1721 	return (error);
1722 }
1723 
1724 static int
1725 dprov_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
1726     crypto_req_handle_t req)
1727 {
1728 	int error = CRYPTO_FAILED;
1729 	dprov_state_t *softc;
1730 	/* LINTED E_FUNC_SET_NOT_USED */
1731 	int instance;
1732 
1733 	/* extract softc and instance number from context */
1734 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1735 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_update: started\n",
1736 	    instance));
1737 
1738 	/* submit request to the taskq */
1739 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_UPDATE, softc,
1740 	    req, NULL, data, NULL, NULL, ctx, KM_NOSLEEP);
1741 
1742 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_update: done err = 0x0%x\n",
1743 	    instance, error));
1744 
1745 	return (error);
1746 }
1747 
1748 static int
1749 dprov_digest_key(crypto_ctx_t *ctx, crypto_key_t *key, crypto_req_handle_t req)
1750 {
1751 	int error = CRYPTO_FAILED;
1752 	dprov_state_t *softc;
1753 	/* LINTED E_FUNC_SET_NOT_USED */
1754 	int instance;
1755 
1756 	/* extract softc and instance number from context */
1757 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1758 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_key: started\n", instance));
1759 
1760 	/* submit request to the taskq */
1761 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_KEY, softc, req, NULL,
1762 	    NULL, key, NULL, ctx, KM_NOSLEEP);
1763 
1764 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_key: done err = 0x0%x\n",
1765 	    instance, error));
1766 
1767 	return (error);
1768 }
1769 
1770 static int
1771 dprov_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
1772     crypto_req_handle_t req)
1773 {
1774 	int error = CRYPTO_FAILED;
1775 	dprov_state_t *softc;
1776 	/* LINTED E_FUNC_SET_NOT_USED */
1777 	int instance;
1778 
1779 	/* extract softc and instance number from context */
1780 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1781 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_final: started\n", instance));
1782 
1783 	/* submit request to the taskq */
1784 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_FINAL, softc, req,
1785 	    NULL, NULL, NULL, digest, ctx, KM_NOSLEEP);
1786 
1787 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_final: done err = 0x0%x\n",
1788 	    instance, error));
1789 
1790 	return (error);
1791 }
1792 
1793 /* ARGSUSED */
1794 static int
1795 dprov_digest_atomic(crypto_provider_handle_t provider,
1796     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1797     crypto_data_t *data, crypto_data_t *digest,
1798     crypto_req_handle_t req)
1799 {
1800 	int error = CRYPTO_FAILED;
1801 	dprov_state_t *softc = (dprov_state_t *)provider;
1802 	/* LINTED E_FUNC_SET_NOT_USED */
1803 	int instance;
1804 
1805 	instance = ddi_get_instance(softc->ds_dip);
1806 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_atomic: started\n",
1807 	    instance));
1808 
1809 	/* check mechanism */
1810 	if (mechanism->cm_type != MD5_MECH_INFO_TYPE &&
1811 	    mechanism->cm_type != SHA1_MECH_INFO_TYPE &&
1812 	    mechanism->cm_type != SHA256_MECH_INFO_TYPE &&
1813 	    mechanism->cm_type != SHA384_MECH_INFO_TYPE &&
1814 	    mechanism->cm_type != SHA512_MECH_INFO_TYPE) {
1815 		cmn_err(CE_WARN, "dprov_digest_atomic: unexpected mech type "
1816 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
1817 		return (CRYPTO_MECHANISM_INVALID);
1818 	}
1819 
1820 	/* submit request to the taskq */
1821 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_ATOMIC, softc, req,
1822 	    mechanism, data, NULL, digest, NULL, KM_SLEEP);
1823 
1824 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_atomic: done err = 0x0%x\n",
1825 	    instance, error));
1826 
1827 	return (error);
1828 }
1829 
1830 /*
1831  * MAC entry points.
1832  */
1833 
1834 /*
1835  * Checks whether the specified mech_type is supported by mac
1836  * entry points.
1837  */
1838 static boolean_t
1839 dprov_valid_mac_mech(crypto_mech_type_t mech_type)
1840 {
1841 	return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
1842 	    mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE ||
1843 	    mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
1844 	    mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE ||
1845 	    mech_type == SHA256_HMAC_MECH_INFO_TYPE ||
1846 	    mech_type == SHA256_HMAC_GEN_MECH_INFO_TYPE ||
1847 	    mech_type == SHA384_HMAC_MECH_INFO_TYPE ||
1848 	    mech_type == SHA384_HMAC_GEN_MECH_INFO_TYPE ||
1849 	    mech_type == SHA512_HMAC_MECH_INFO_TYPE ||
1850 	    mech_type == SHA512_HMAC_GEN_MECH_INFO_TYPE);
1851 }
1852 
1853 static int
1854 dprov_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
1855     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
1856     crypto_req_handle_t req)
1857 {
1858 	int error = CRYPTO_FAILED;
1859 	dprov_state_t *softc;
1860 	/* LINTED E_FUNC_SET_NOT_USED */
1861 	int instance;
1862 
1863 	/* extract softc and instance number from context */
1864 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1865 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_init: started\n", instance));
1866 
1867 	/* check mechanism */
1868 	if (!dprov_valid_mac_mech(mechanism->cm_type)) {
1869 		cmn_err(CE_WARN, "dprov_mac_init: unexpected mech type "
1870 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
1871 		return (CRYPTO_MECHANISM_INVALID);
1872 	}
1873 
1874 	if (ctx_template != NULL)
1875 		return (CRYPTO_ARGUMENTS_BAD);
1876 
1877 	/* submit request to the taskq */
1878 	error = dprov_mac_submit_req(DPROV_REQ_MAC_INIT, softc, req,
1879 	    mechanism, NULL, key, NULL, ctx, 0, KM_SLEEP);
1880 
1881 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_init: done err = 0x%x\n",
1882 	    instance, error));
1883 
1884 	return (error);
1885 }
1886 
1887 static int
1888 dprov_mac(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *mac,
1889     crypto_req_handle_t req)
1890 {
1891 	int error = CRYPTO_FAILED;
1892 	dprov_state_t *softc;
1893 	/* LINTED E_FUNC_SET_NOT_USED */
1894 	int instance;
1895 
1896 	/* extract softc and instance number from context */
1897 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1898 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac: started\n", instance));
1899 
1900 	/* submit request to the taskq */
1901 	error = dprov_mac_submit_req(DPROV_REQ_MAC, softc, req,
1902 	    NULL, data, NULL, mac, ctx, 0, KM_NOSLEEP);
1903 
1904 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac: done, err = 0x%x\n", instance,
1905 	    error));
1906 
1907 	return (error);
1908 }
1909 
1910 static int
1911 dprov_mac_update(crypto_ctx_t *ctx, crypto_data_t *data,
1912     crypto_req_handle_t req)
1913 {
1914 	int error = CRYPTO_FAILED;
1915 	dprov_state_t *softc;
1916 	/* LINTED E_FUNC_SET_NOT_USED */
1917 	int instance;
1918 
1919 	/* extract softc and instance number from context */
1920 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1921 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_update: started\n", instance));
1922 
1923 	/* submit request to the taskq */
1924 	error = dprov_mac_submit_req(DPROV_REQ_MAC_UPDATE, softc,
1925 	    req, NULL, data, NULL, NULL, ctx, 0, KM_NOSLEEP);
1926 
1927 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_update: done err = 0x0%x\n",
1928 	    instance, error));
1929 
1930 	return (error);
1931 }
1932 
1933 static int
1934 dprov_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
1935 {
1936 	int error = CRYPTO_FAILED;
1937 	dprov_state_t *softc;
1938 	/* LINTED E_FUNC_SET_NOT_USED */
1939 	int instance;
1940 
1941 	/* extract softc and instance number from context */
1942 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1943 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_final: started\n", instance));
1944 
1945 	/* submit request to the taskq */
1946 	error = dprov_mac_submit_req(DPROV_REQ_MAC_FINAL, softc, req,
1947 	    NULL, NULL, NULL, mac, ctx, 0, KM_NOSLEEP);
1948 
1949 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_final: done err = 0x0%x\n",
1950 	    instance, error));
1951 
1952 	return (error);
1953 }
1954 
1955 static int
1956 dprov_mac_atomic(crypto_provider_handle_t provider,
1957     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1958     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1959     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1960 {
1961 	int error = CRYPTO_FAILED;
1962 	dprov_state_t *softc = (dprov_state_t *)provider;
1963 	/* LINTED E_FUNC_SET_NOT_USED */
1964 	int instance;
1965 
1966 	instance = ddi_get_instance(softc->ds_dip);
1967 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_atomic: started\n", instance));
1968 
1969 	if (ctx_template != NULL)
1970 		return (CRYPTO_ARGUMENTS_BAD);
1971 
1972 	/* check mechanism */
1973 	if (!dprov_valid_mac_mech(mechanism->cm_type)) {
1974 		cmn_err(CE_WARN, "dprov_mac_atomic: unexpected mech type "
1975 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
1976 		return (CRYPTO_MECHANISM_INVALID);
1977 	}
1978 
1979 	/* submit request to the taskq */
1980 	error = dprov_mac_submit_req(DPROV_REQ_MAC_ATOMIC, softc, req,
1981 	    mechanism, data, key, mac, NULL, session_id, KM_SLEEP);
1982 
1983 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_atomic: done err = 0x0%x\n",
1984 	    instance, error));
1985 
1986 	return (error);
1987 }
1988 
1989 static int
1990 dprov_mac_verify_atomic(crypto_provider_handle_t provider,
1991     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1992     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1993     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1994 {
1995 	int error = CRYPTO_FAILED;
1996 	dprov_state_t *softc = (dprov_state_t *)provider;
1997 	/* LINTED E_FUNC_SET_NOT_USED */
1998 	int instance;
1999 
2000 	instance = ddi_get_instance(softc->ds_dip);
2001 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_verify_atomic: started\n",
2002 	    instance));
2003 
2004 	if (ctx_template != NULL)
2005 		return (CRYPTO_ARGUMENTS_BAD);
2006 
2007 	/* check mechanism */
2008 	if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2009 		cmn_err(CE_WARN, "dprov_mac_verify_atomic: unexpected mech "
2010 		    "type 0x%llx\n", (unsigned long long)mechanism->cm_type);
2011 		return (CRYPTO_MECHANISM_INVALID);
2012 	}
2013 
2014 	/* submit request to the taskq */
2015 	error = dprov_mac_submit_req(DPROV_REQ_MAC_VERIFY_ATOMIC, softc, req,
2016 	    mechanism, data, key, mac, NULL, session_id, KM_SLEEP);
2017 
2018 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_verify_atomic: done err = 0x0%x\n",
2019 	    instance, error));
2020 
2021 	return (error);
2022 }
2023 
2024 /*
2025  * Cipher (encrypt/decrypt) entry points.
2026  */
2027 
2028 /*
2029  * Checks whether the specified mech_type is supported by cipher entry
2030  * points.
2031  */
2032 static boolean_t
2033 dprov_valid_cipher_mech(crypto_mech_type_t mech_type)
2034 {
2035 	return (mech_type == DES_CBC_MECH_INFO_TYPE ||
2036 		mech_type == DES3_CBC_MECH_INFO_TYPE ||
2037 		mech_type == DES_ECB_MECH_INFO_TYPE ||
2038 		mech_type == DES3_ECB_MECH_INFO_TYPE ||
2039 		mech_type == BF_CBC_MECH_INFO_TYPE ||
2040 		mech_type == BF_ECB_MECH_INFO_TYPE ||
2041 		mech_type == AES_CBC_MECH_INFO_TYPE ||
2042 		mech_type == AES_ECB_MECH_INFO_TYPE ||
2043 		mech_type == RC4_MECH_INFO_TYPE ||
2044 		mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2045 		mech_type == RSA_X_509_MECH_INFO_TYPE ||
2046 		mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2047 		mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE);
2048 }
2049 
2050 static boolean_t
2051 is_publickey_mech(crypto_mech_type_t mech_type)
2052 {
2053 	return (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2054 		mech_type == RSA_X_509_MECH_INFO_TYPE ||
2055 		mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2056 		mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE);
2057 }
2058 
2059 
2060 /* ARGSUSED */
2061 static int
2062 dprov_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2063     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2064     crypto_req_handle_t req)
2065 {
2066 	int error = CRYPTO_FAILED;
2067 	dprov_state_t *softc;
2068 	/* LINTED E_FUNC_SET_NOT_USED */
2069 	int instance;
2070 
2071 	/* extract softc and instance number from context */
2072 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2073 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_init: started\n",
2074 	    instance));
2075 
2076 	/* check mechanism */
2077 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2078 		cmn_err(CE_WARN, "dprov_encrypt_init: unexpected mech type "
2079 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2080 		return (CRYPTO_MECHANISM_INVALID);
2081 	}
2082 
2083 	/* submit request to the taskq */
2084 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_INIT, softc,
2085 	    req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2086 
2087 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_init: done err = 0x0%x\n",
2088 	    instance, error));
2089 
2090 	return (error);
2091 }
2092 
2093 /* ARGSUSED */
2094 static int
2095 dprov_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2096     crypto_data_t *ciphertext, crypto_req_handle_t req)
2097 {
2098 	int error = CRYPTO_FAILED;
2099 	dprov_state_t *softc;
2100 	/* LINTED E_FUNC_SET_NOT_USED */
2101 	int instance;
2102 
2103 	/* extract softc and instance number from context */
2104 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2105 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt: started\n", instance));
2106 
2107 	/* submit request to the taskq */
2108 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT, softc,
2109 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2110 
2111 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt: done err = 0x0%x\n",
2112 	    instance, error));
2113 
2114 	return (error);
2115 }
2116 
2117 /* ARGSUSED */
2118 static int
2119 dprov_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2120     crypto_data_t *ciphertext, crypto_req_handle_t req)
2121 {
2122 	int error = CRYPTO_FAILED;
2123 	dprov_state_t *softc;
2124 	/* LINTED E_FUNC_SET_NOT_USED */
2125 	int instance;
2126 
2127 	/* extract softc and instance number from context */
2128 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2129 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_update: started\n",
2130 	    instance));
2131 
2132 	/* submit request to the taskq */
2133 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_UPDATE, softc,
2134 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2135 
2136 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_update: done err = 0x0%x\n",
2137 	    instance, error));
2138 
2139 	return (error);
2140 }
2141 
2142 /* ARGSUSED */
2143 static int
2144 dprov_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2145     crypto_req_handle_t req)
2146 {
2147 	int error = CRYPTO_FAILED;
2148 	dprov_state_t *softc;
2149 	/* LINTED E_FUNC_SET_NOT_USED */
2150 	int instance;
2151 
2152 	/* extract softc and instance number from context */
2153 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2154 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_final: started\n",
2155 	    instance));
2156 
2157 	/* submit request to the taskq */
2158 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_FINAL, softc,
2159 	    req, NULL, NULL, NULL, ciphertext, ctx, 0, KM_NOSLEEP);
2160 
2161 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_final: done err = 0x0%x\n",
2162 	    instance, error));
2163 
2164 	return (error);
2165 }
2166 
2167 static int
2168 dprov_encrypt_atomic(crypto_provider_handle_t provider,
2169     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2170     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
2171     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2172 {
2173 	int error = CRYPTO_FAILED;
2174 	dprov_state_t *softc = (dprov_state_t *)provider;
2175 	/* LINTED E_FUNC_SET_NOT_USED */
2176 	int instance;
2177 
2178 	instance = ddi_get_instance(softc->ds_dip);
2179 	DPROV_DEBUG(D_MAC, ("(%d) dprov_encrypt_atomic: started\n", instance));
2180 
2181 	if (ctx_template != NULL)
2182 		return (CRYPTO_ARGUMENTS_BAD);
2183 
2184 	/* check mechanism */
2185 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2186 		cmn_err(CE_WARN, "dprov_encrypt_atomic: unexpected mech type "
2187 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2188 		return (CRYPTO_MECHANISM_INVALID);
2189 	}
2190 
2191 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_ATOMIC, softc,
2192 	    req, mechanism, key, plaintext, ciphertext, NULL, session_id,
2193 	    KM_SLEEP);
2194 
2195 	DPROV_DEBUG(D_MAC, ("(%d) dprov_encrypt_atomic: done err = 0x0%x\n",
2196 	    instance, error));
2197 
2198 	return (error);
2199 }
2200 
2201 /* ARGSUSED */
2202 static int
2203 dprov_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2204     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2205     crypto_req_handle_t req)
2206 {
2207 	int error = CRYPTO_FAILED;
2208 	dprov_state_t *softc;
2209 	/* LINTED E_FUNC_SET_NOT_USED */
2210 	int instance;
2211 
2212 	/* extract softc and instance number from context */
2213 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2214 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_init: started\n",
2215 	    instance));
2216 
2217 	/* check mechanism */
2218 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2219 		cmn_err(CE_WARN, "dprov_decrypt_init: unexpected mech type "
2220 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2221 		return (CRYPTO_MECHANISM_INVALID);
2222 	}
2223 
2224 	/* submit request to the taskq */
2225 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_INIT, softc,
2226 	    req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2227 
2228 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_init: done err = 0x0%x\n",
2229 	    instance, error));
2230 
2231 	return (error);
2232 }
2233 
2234 /* ARGSUSED */
2235 static int
2236 dprov_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2237     crypto_data_t *plaintext, crypto_req_handle_t req)
2238 {
2239 	int error = CRYPTO_FAILED;
2240 
2241 	dprov_state_t *softc;
2242 	/* LINTED E_FUNC_SET_NOT_USED */
2243 	int instance;
2244 
2245 	/* extract softc and instance number from context */
2246 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2247 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt: started\n", instance));
2248 
2249 	/* submit request to the taskq */
2250 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT, softc,
2251 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2252 
2253 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt: done err = 0x0%x\n",
2254 	    instance, error));
2255 
2256 	return (error);
2257 }
2258 
2259 /* ARGSUSED */
2260 static int
2261 dprov_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2262     crypto_data_t *plaintext, crypto_req_handle_t req)
2263 {
2264 	int error = CRYPTO_FAILED;
2265 	dprov_state_t *softc;
2266 	/* LINTED E_FUNC_SET_NOT_USED */
2267 	int instance;
2268 
2269 	/* extract softc and instance number from context */
2270 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2271 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_update: started\n",
2272 	    instance));
2273 
2274 	/* submit request to the taskq */
2275 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_UPDATE, softc,
2276 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2277 
2278 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_update: done err = 0x0%x\n",
2279 	    instance, error));
2280 
2281 	return (error);
2282 }
2283 
2284 /* ARGSUSED */
2285 static int
2286 dprov_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2287     crypto_req_handle_t req)
2288 {
2289 	int error = CRYPTO_FAILED;
2290 	dprov_state_t *softc;
2291 	/* LINTED E_FUNC_SET_NOT_USED */
2292 	int instance;
2293 
2294 	/* extract softc and instance number from context */
2295 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2296 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_final: started\n",
2297 	    instance));
2298 
2299 	/* submit request to the taskq */
2300 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_FINAL, softc,
2301 	    req, NULL, NULL, plaintext, NULL, ctx, 0, KM_NOSLEEP);
2302 
2303 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_final: done err = 0x0%x\n",
2304 	    instance, error));
2305 
2306 	return (error);
2307 }
2308 
2309 static int
2310 dprov_decrypt_atomic(crypto_provider_handle_t provider,
2311     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2312     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
2313     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2314 {
2315 	int error = CRYPTO_FAILED;
2316 	dprov_state_t *softc = (dprov_state_t *)provider;
2317 	/* LINTED E_FUNC_SET_NOT_USED */
2318 	int instance;
2319 
2320 	instance = ddi_get_instance(softc->ds_dip);
2321 	DPROV_DEBUG(D_MAC, ("(%d) dprov_decrypt_atomic: started\n", instance));
2322 
2323 	if (ctx_template != NULL)
2324 		return (CRYPTO_ARGUMENTS_BAD);
2325 
2326 	/* check mechanism */
2327 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2328 		cmn_err(CE_WARN, "dprov_atomic_init: unexpected mech type "
2329 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2330 		return (CRYPTO_MECHANISM_INVALID);
2331 	}
2332 
2333 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_ATOMIC, softc,
2334 	    req, mechanism, key, plaintext, ciphertext, NULL, session_id,
2335 	    KM_SLEEP);
2336 
2337 	DPROV_DEBUG(D_MAC, ("(%d) dprov_decrypt_atomic: done err = 0x0%x\n",
2338 	    instance, error));
2339 
2340 	return (error);
2341 }
2342 
2343 /*
2344  * Sign entry points.
2345  */
2346 
2347 /*
2348  * Checks whether the specified mech_type is supported by sign/verify
2349  * entry points.
2350  */
2351 static boolean_t
2352 dprov_valid_sign_verif_mech(crypto_mech_type_t mech_type)
2353 {
2354 	return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
2355 		mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE ||
2356 		mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2357 		mech_type == RSA_X_509_MECH_INFO_TYPE ||
2358 		mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2359 		mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE);
2360 }
2361 
2362 static int
2363 dprov_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2364     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2365     crypto_req_handle_t req)
2366 {
2367 	int error = CRYPTO_FAILED;
2368 	dprov_state_t *softc;
2369 	/* LINTED E_FUNC_SET_NOT_USED */
2370 	int instance;
2371 
2372 	/* extract softc and instance number from context */
2373 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2374 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_init: started\n", instance));
2375 
2376 	/* check mechanism */
2377 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2378 		cmn_err(CE_WARN, "dprov_sign_init: unexpected mech type "
2379 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2380 		return (CRYPTO_MECHANISM_INVALID);
2381 	}
2382 
2383 	if (ctx_template != NULL)
2384 		return (CRYPTO_ARGUMENTS_BAD);
2385 
2386 	/* submit request to the taskq */
2387 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_INIT, softc, req,
2388 	    mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2389 
2390 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_init: done err = 0x%x\n",
2391 	    instance, error));
2392 
2393 	return (error);
2394 }
2395 
2396 static int
2397 dprov_sign(crypto_ctx_t *ctx, crypto_data_t *data,
2398     crypto_data_t *signature, crypto_req_handle_t req)
2399 {
2400 	int error = CRYPTO_FAILED;
2401 	dprov_state_t *softc;
2402 	/* LINTED E_FUNC_SET_NOT_USED */
2403 	int instance;
2404 
2405 	/* extract softc and instance number from context */
2406 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2407 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign: started\n", instance));
2408 
2409 	/* submit request to the taskq */
2410 	error = dprov_sign_submit_req(DPROV_REQ_SIGN, softc, req,
2411 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2412 
2413 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign: done err = 0x%x\n",
2414 	    instance, error));
2415 
2416 	return (error);
2417 }
2418 
2419 static int
2420 dprov_sign_update(crypto_ctx_t *ctx, crypto_data_t *data,
2421     crypto_req_handle_t req)
2422 {
2423 	int error = CRYPTO_FAILED;
2424 	dprov_state_t *softc;
2425 	/* LINTED E_FUNC_SET_NOT_USED */
2426 	int instance;
2427 
2428 	/* extract softc and instance number from context */
2429 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2430 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_update: started\n", instance));
2431 
2432 	/* submit request to the taskq */
2433 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_UPDATE, softc, req,
2434 	    NULL, NULL, data, NULL, ctx, 0, KM_NOSLEEP);
2435 
2436 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_update: done err = 0x%x\n",
2437 	    instance, error));
2438 
2439 	return (error);
2440 }
2441 
2442 static int
2443 dprov_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
2444     crypto_req_handle_t req)
2445 {
2446 	int error = CRYPTO_FAILED;
2447 	dprov_state_t *softc;
2448 	/* LINTED E_FUNC_SET_NOT_USED */
2449 	int instance;
2450 
2451 	/* extract softc and instance number from context */
2452 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2453 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_final: started\n", instance));
2454 
2455 	/* submit request to the taskq */
2456 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_FINAL, softc, req,
2457 	    NULL, NULL, NULL, signature, ctx, 0, KM_NOSLEEP);
2458 
2459 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_final: done err = 0x%x\n",
2460 	    instance, error));
2461 
2462 	return (error);
2463 }
2464 
2465 static int
2466 dprov_sign_atomic(crypto_provider_handle_t provider,
2467     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2468     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2469     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2470 {
2471 	int error = CRYPTO_FAILED;
2472 	dprov_state_t *softc = (dprov_state_t *)provider;
2473 	/* LINTED E_FUNC_SET_NOT_USED */
2474 	int instance;
2475 
2476 	instance = ddi_get_instance(softc->ds_dip);
2477 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_atomic: started\n", instance));
2478 
2479 	/* check mechanism */
2480 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2481 		cmn_err(CE_WARN, "dprov_sign_atomic: unexpected mech type "
2482 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2483 		return (CRYPTO_MECHANISM_INVALID);
2484 	}
2485 
2486 	if (ctx_template != NULL)
2487 		return (CRYPTO_ARGUMENTS_BAD);
2488 
2489 	/* submit request to the taskq */
2490 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_ATOMIC, softc, req,
2491 	    mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2492 
2493 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_atomic: done err = 0x%x\n",
2494 	    instance, error));
2495 
2496 	return (error);
2497 }
2498 
2499 static int
2500 dprov_sign_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2501     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2502     crypto_req_handle_t req)
2503 {
2504 	int error = CRYPTO_FAILED;
2505 	dprov_state_t *softc;
2506 	/* LINTED E_FUNC_SET_NOT_USED */
2507 	int instance;
2508 
2509 	/* extract softc and instance number from context */
2510 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2511 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_init: started\n",
2512 	    instance));
2513 
2514 	if (ctx_template != NULL)
2515 		return (CRYPTO_ARGUMENTS_BAD);
2516 
2517 	/* submit request to the taskq */
2518 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER_INIT, softc, req,
2519 	    mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2520 
2521 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_init: done err = 0x%x\n",
2522 	    instance, error));
2523 
2524 	return (error);
2525 }
2526 
2527 static int
2528 dprov_sign_recover(crypto_ctx_t *ctx, crypto_data_t *data,
2529     crypto_data_t *signature, crypto_req_handle_t req)
2530 {
2531 	int error = CRYPTO_FAILED;
2532 	dprov_state_t *softc;
2533 	/* LINTED E_FUNC_SET_NOT_USED */
2534 	int instance;
2535 
2536 	/* extract softc and instance number from context */
2537 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2538 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover: started\n", instance));
2539 
2540 	/* submit request to the taskq */
2541 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER, softc, req,
2542 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2543 
2544 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover: done err = 0x%x\n",
2545 	    instance, error));
2546 
2547 	return (error);
2548 }
2549 
2550 static int
2551 dprov_sign_recover_atomic(crypto_provider_handle_t provider,
2552     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2553     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2554     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2555 {
2556 	int error = CRYPTO_FAILED;
2557 	dprov_state_t *softc = (dprov_state_t *)provider;
2558 	/* LINTED E_FUNC_SET_NOT_USED */
2559 	int instance;
2560 
2561 	instance = ddi_get_instance(softc->ds_dip);
2562 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_atomic: started\n",
2563 	    instance));
2564 
2565 	if (ctx_template != NULL)
2566 		return (CRYPTO_ARGUMENTS_BAD);
2567 
2568 	/* submit request to the taskq */
2569 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER_ATOMIC, softc, req,
2570 	    mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2571 
2572 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_atomic: done "
2573 	    "err = 0x%x\n", instance, error));
2574 
2575 	return (error);
2576 }
2577 
2578 /*
2579  * Verify entry points.
2580  */
2581 
2582 static int
2583 dprov_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2584     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2585     crypto_req_handle_t req)
2586 {
2587 	int error = CRYPTO_FAILED;
2588 	dprov_state_t *softc;
2589 	/* LINTED E_FUNC_SET_NOT_USED */
2590 	int instance;
2591 
2592 	/* extract softc and instance number from context */
2593 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2594 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_init: started\n", instance));
2595 
2596 	/* check mechanism */
2597 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2598 		cmn_err(CE_WARN, "dprov_verify_init: unexpected mech type "
2599 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2600 		return (CRYPTO_MECHANISM_INVALID);
2601 	}
2602 
2603 	if (ctx_template != NULL)
2604 		return (CRYPTO_ARGUMENTS_BAD);
2605 
2606 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_INIT, softc, req,
2607 	    mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2608 
2609 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_init: done err = 0x%x\n",
2610 	    instance, error));
2611 
2612 	return (error);
2613 }
2614 
2615 static int
2616 dprov_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
2617     crypto_req_handle_t req)
2618 {
2619 	int error = CRYPTO_FAILED;
2620 	dprov_state_t *softc;
2621 	/* LINTED E_FUNC_SET_NOT_USED */
2622 	int instance;
2623 
2624 	/* extract softc and instance number from context */
2625 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2626 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify: started\n", instance));
2627 
2628 	/* submit request to the taskq */
2629 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY, softc, req,
2630 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2631 
2632 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify: done err = 0x%x\n",
2633 	    instance, error));
2634 
2635 	return (error);
2636 }
2637 
2638 static int
2639 dprov_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
2640     crypto_req_handle_t req)
2641 {
2642 	int error = CRYPTO_FAILED;
2643 	dprov_state_t *softc;
2644 	/* LINTED E_FUNC_SET_NOT_USED */
2645 	int instance;
2646 
2647 	/* extract softc and instance number from context */
2648 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2649 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_update: started\n",
2650 	    instance));
2651 
2652 	/* submit request to the taskq */
2653 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_UPDATE, softc, req,
2654 	    NULL, NULL, data, NULL, ctx, 0, KM_NOSLEEP);
2655 
2656 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_update: done err = 0x%x\n",
2657 	    instance, error));
2658 
2659 	return (error);
2660 }
2661 
2662 static int
2663 dprov_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
2664     crypto_req_handle_t req)
2665 {
2666 	int error = CRYPTO_FAILED;
2667 	dprov_state_t *softc;
2668 	/* LINTED E_FUNC_SET_NOT_USED */
2669 	int instance;
2670 
2671 	/* extract softc and instance number from context */
2672 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2673 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_final: started\n", instance));
2674 
2675 	/* submit request to the taskq */
2676 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_FINAL, softc, req,
2677 	    NULL, NULL, NULL, signature, ctx, 0, KM_NOSLEEP);
2678 
2679 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_final: done err = 0x%x\n",
2680 	    instance, error));
2681 
2682 	return (error);
2683 }
2684 
2685 static int
2686 dprov_verify_atomic(crypto_provider_handle_t provider,
2687     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2688     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2689     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2690 {
2691 	int error = CRYPTO_FAILED;
2692 	dprov_state_t *softc = (dprov_state_t *)provider;
2693 	/* LINTED E_FUNC_SET_NOT_USED */
2694 	int instance;
2695 
2696 	instance = ddi_get_instance(softc->ds_dip);
2697 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_atomic: started\n",
2698 	    instance));
2699 
2700 	/* check mechanism */
2701 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2702 		cmn_err(CE_WARN, "dprov_verify_atomic: unexpected mech type "
2703 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2704 		return (CRYPTO_MECHANISM_INVALID);
2705 	}
2706 
2707 	if (ctx_template != NULL)
2708 		return (CRYPTO_ARGUMENTS_BAD);
2709 
2710 	/* submit request to the taskq */
2711 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_ATOMIC, softc, req,
2712 	    mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2713 
2714 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_atomic: done err = 0x%x\n",
2715 	    instance, error));
2716 
2717 	return (error);
2718 }
2719 
2720 static int
2721 dprov_verify_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2722     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2723     crypto_req_handle_t req)
2724 {
2725 	int error = CRYPTO_FAILED;
2726 	dprov_state_t *softc;
2727 	/* LINTED E_FUNC_SET_NOT_USED */
2728 	int instance;
2729 
2730 	/* extract softc and instance number from context */
2731 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2732 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_init: started\n",
2733 	    instance));
2734 
2735 	if (ctx_template != NULL)
2736 		return (CRYPTO_ARGUMENTS_BAD);
2737 
2738 	/* submit request to the taskq */
2739 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER_INIT, softc,
2740 	    req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2741 
2742 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_init: done "
2743 	    "err = 0x%x\n", instance, error));
2744 
2745 	return (error);
2746 }
2747 
2748 static int
2749 dprov_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
2750     crypto_data_t *data, crypto_req_handle_t req)
2751 {
2752 	int error = CRYPTO_FAILED;
2753 	dprov_state_t *softc;
2754 	/* LINTED E_FUNC_SET_NOT_USED */
2755 	int instance;
2756 
2757 	/* extract softc and instance number from context */
2758 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2759 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover: started\n",
2760 	    instance));
2761 
2762 	/* submit request to the taskq */
2763 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER, softc, req,
2764 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2765 
2766 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover: done err = 0x%x\n",
2767 	    instance, error));
2768 
2769 	return (error);
2770 }
2771 
2772 static int
2773 dprov_verify_recover_atomic(crypto_provider_handle_t provider,
2774     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2775     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
2776     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2777 {
2778 	int error = CRYPTO_FAILED;
2779 	dprov_state_t *softc = (dprov_state_t *)provider;
2780 	/* LINTED E_FUNC_SET_NOT_USED */
2781 	int instance;
2782 
2783 	instance = ddi_get_instance(softc->ds_dip);
2784 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_atomic: started\n",
2785 	    instance));
2786 
2787 	if (ctx_template != NULL)
2788 		return (CRYPTO_ARGUMENTS_BAD);
2789 
2790 	/* submit request to the taskq */
2791 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER_ATOMIC, softc,
2792 	    req, mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2793 
2794 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_atomic: done "
2795 	    "err = 0x%x\n", instance, error));
2796 
2797 	return (error);
2798 }
2799 
2800 /*
2801  * Dual operations entry points.
2802  */
2803 
2804 static int
2805 dprov_digest_encrypt_update(crypto_ctx_t *digest_ctx,
2806     crypto_ctx_t *encrypt_ctx, crypto_data_t *plaintext,
2807     crypto_data_t *ciphertext, crypto_req_handle_t req)
2808 {
2809 	int error = CRYPTO_FAILED;
2810 	dprov_state_t *softc;
2811 	/* LINTED E_FUNC_SET_NOT_USED */
2812 	int instance;
2813 
2814 	/* extract softc and instance number from context */
2815 	DPROV_SOFTC_FROM_CTX(digest_ctx, softc, instance);
2816 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_digest_encrypt_update: started\n",
2817 	    instance));
2818 
2819 	if (digest_ctx->cc_provider != encrypt_ctx->cc_provider)
2820 		return (CRYPTO_INVALID_CONTEXT);
2821 
2822 	/* submit request to the taskq */
2823 	error = dprov_dual_submit_req(DPROV_REQ_DIGEST_ENCRYPT_UPDATE,
2824 	    softc, req, digest_ctx, encrypt_ctx, plaintext, ciphertext);
2825 
2826 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_digest_encrypt_update: done "
2827 	    "err = 0x%x\n", instance, error));
2828 
2829 	return (error);
2830 }
2831 
2832 static int
2833 dprov_decrypt_digest_update(crypto_ctx_t *decrypt_ctx, crypto_ctx_t *digest_ctx,
2834     crypto_data_t *ciphertext, crypto_data_t *plaintext,
2835     crypto_req_handle_t req)
2836 {
2837 	int error = CRYPTO_FAILED;
2838 	dprov_state_t *softc;
2839 	/* LINTED E_FUNC_SET_NOT_USED */
2840 	int instance;
2841 
2842 	/* extract softc and instance number from context */
2843 	DPROV_SOFTC_FROM_CTX(decrypt_ctx, softc, instance);
2844 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_digest_update: started\n",
2845 	    instance));
2846 
2847 	if (decrypt_ctx->cc_provider != digest_ctx->cc_provider)
2848 		return (CRYPTO_INVALID_CONTEXT);
2849 
2850 	/* submit request to the taskq */
2851 	error = dprov_dual_submit_req(DPROV_REQ_DECRYPT_DIGEST_UPDATE,
2852 	    softc, req, digest_ctx, decrypt_ctx, plaintext, ciphertext);
2853 
2854 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_digest_update: done "
2855 	    "err = 0x%x\n", instance, error));
2856 
2857 	return (error);
2858 }
2859 
2860 static int
2861 dprov_sign_encrypt_update(crypto_ctx_t *sign_ctx, crypto_ctx_t *encrypt_ctx,
2862     crypto_data_t *plaintext, crypto_data_t *ciphertext,
2863     crypto_req_handle_t req)
2864 {
2865 	int error = CRYPTO_FAILED;
2866 	dprov_state_t *softc;
2867 	/* LINTED E_FUNC_SET_NOT_USED */
2868 	int instance;
2869 
2870 	/* extract softc and instance number from context */
2871 	DPROV_SOFTC_FROM_CTX(sign_ctx, softc, instance);
2872 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_sign_encrypt_update: started\n",
2873 	    instance));
2874 
2875 	if (sign_ctx->cc_provider != encrypt_ctx->cc_provider)
2876 		return (CRYPTO_INVALID_CONTEXT);
2877 
2878 	/* submit request to the taskq */
2879 	error = dprov_dual_submit_req(DPROV_REQ_SIGN_ENCRYPT_UPDATE,
2880 	    softc, req, sign_ctx, encrypt_ctx, plaintext, ciphertext);
2881 
2882 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_sign_encrypt_update: done "
2883 	    "err = 0x%x\n", instance, error));
2884 
2885 	return (error);
2886 }
2887 
2888 static int
2889 dprov_decrypt_verify_update(crypto_ctx_t *decrypt_ctx, crypto_ctx_t *verify_ctx,
2890     crypto_data_t *ciphertext, crypto_data_t *plaintext,
2891     crypto_req_handle_t req)
2892 {
2893 	int error = CRYPTO_FAILED;
2894 	dprov_state_t *softc;
2895 	/* LINTED E_FUNC_SET_NOT_USED */
2896 	int instance;
2897 
2898 	/* extract softc and instance number from context */
2899 	DPROV_SOFTC_FROM_CTX(decrypt_ctx, softc, instance);
2900 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_verify_update: started\n",
2901 	    instance));
2902 
2903 	if (decrypt_ctx->cc_provider != verify_ctx->cc_provider)
2904 		return (CRYPTO_INVALID_CONTEXT);
2905 
2906 	/* submit request to the taskq */
2907 	error = dprov_dual_submit_req(DPROV_REQ_DECRYPT_VERIFY_UPDATE,
2908 	    softc, req, verify_ctx, decrypt_ctx, plaintext, ciphertext);
2909 
2910 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_verify_update: done "
2911 	    "err = 0x%x\n", instance, error));
2912 
2913 	return (error);
2914 }
2915 
2916 /*
2917  * Dual cipher-mac entry points.
2918  */
2919 
2920 static int
2921 dprov_encrypt_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *encrypt_mech,
2922     crypto_key_t *encrypt_key, crypto_mechanism_t *mac_mech,
2923     crypto_key_t *mac_key, crypto_spi_ctx_template_t encr_ctx_template,
2924     crypto_spi_ctx_template_t mac_ctx_template,
2925     crypto_req_handle_t req)
2926 {
2927 	int error = CRYPTO_FAILED;
2928 	dprov_state_t *softc;
2929 	/* LINTED E_FUNC_SET_NOT_USED */
2930 	int instance;
2931 
2932 	/* extract softc and instance number from context */
2933 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2934 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_init: started\n",
2935 	    instance));
2936 
2937 	/* check mechanisms */
2938 	if (!dprov_valid_cipher_mech(encrypt_mech->cm_type)) {
2939 		cmn_err(CE_WARN, "dprov_encrypt_mac_init: unexpected encrypt "
2940 		    "mech type 0x%llx\n",
2941 		    (unsigned long long)encrypt_mech->cm_type);
2942 		return (CRYPTO_MECHANISM_INVALID);
2943 	}
2944 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
2945 		cmn_err(CE_WARN, "dprov_encrypt_mac_init: unexpected mac "
2946 		    "mech type 0x%llx\n",
2947 		    (unsigned long long)mac_mech->cm_type);
2948 		return (CRYPTO_MECHANISM_INVALID);
2949 	}
2950 
2951 	if (encr_ctx_template != NULL || mac_ctx_template != NULL)
2952 		return (CRYPTO_ARGUMENTS_BAD);
2953 
2954 	/* submit request to the taskq */
2955 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_INIT,
2956 	    softc, req, ctx, 0, encrypt_mech, encrypt_key, mac_mech, mac_key,
2957 	    NULL, NULL, NULL, KM_SLEEP);
2958 
2959 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_init: done "
2960 	    "err = 0x%x\n", instance, error));
2961 
2962 	return (error);
2963 }
2964 
2965 static int
2966 dprov_encrypt_mac(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2967     crypto_dual_data_t *ciphertext, crypto_data_t *mac, crypto_req_handle_t req)
2968 {
2969 	int error = CRYPTO_FAILED;
2970 	dprov_state_t *softc;
2971 	/* LINTED E_FUNC_SET_NOT_USED */
2972 	int instance;
2973 
2974 	/* extract softc and instance number from context */
2975 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2976 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac: started\n",
2977 	    instance));
2978 
2979 	/*
2980 	 * submit request to the taskq
2981 	 * Careful! cihertext/plaintext order inversion
2982 	 */
2983 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC,
2984 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
2985 	    ciphertext, plaintext, mac, KM_NOSLEEP);
2986 
2987 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac: done "
2988 	    "err = 0x%x\n", instance, error));
2989 
2990 	return (error);
2991 }
2992 
2993 static int
2994 dprov_encrypt_mac_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2995     crypto_dual_data_t *ciphertext, crypto_req_handle_t req)
2996 {
2997 	int error = CRYPTO_FAILED;
2998 	dprov_state_t *softc;
2999 	/* LINTED E_FUNC_SET_NOT_USED */
3000 	int instance;
3001 
3002 	/* extract softc and instance number from context */
3003 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3004 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_update: started\n",
3005 	    instance));
3006 
3007 	/* submit request to the taskq */
3008 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_UPDATE,
3009 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3010 	    ciphertext, plaintext, NULL, KM_NOSLEEP);
3011 
3012 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_update: done "
3013 	    "err = 0x%x\n", instance, error));
3014 
3015 	return (error);
3016 }
3017 
3018 static int
3019 dprov_encrypt_mac_final(crypto_ctx_t *ctx,
3020     crypto_dual_data_t *ciphertext, crypto_data_t *mac,
3021     crypto_req_handle_t req)
3022 {
3023 	int error = CRYPTO_FAILED;
3024 	dprov_state_t *softc;
3025 	/* LINTED E_FUNC_SET_NOT_USED */
3026 	int instance;
3027 
3028 	/* extract softc and instance number from context */
3029 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3030 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_final: started\n",
3031 	    instance));
3032 
3033 	/* submit request to the taskq */
3034 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_FINAL,
3035 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3036 	    ciphertext, NULL, mac, KM_NOSLEEP);
3037 
3038 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_final: done "
3039 	    "err = 0x%x\n", instance, error));
3040 
3041 	return (error);
3042 }
3043 
3044 static int
3045 dprov_encrypt_mac_atomic(crypto_provider_handle_t provider,
3046     crypto_session_id_t session_id, crypto_mechanism_t *encrypt_mech,
3047     crypto_key_t *encrypt_key, crypto_mechanism_t *mac_mech,
3048     crypto_key_t *mac_key, crypto_data_t *plaintext,
3049     crypto_dual_data_t *ciphertext, crypto_data_t *mac,
3050     crypto_spi_ctx_template_t encr_ctx_template,
3051     crypto_spi_ctx_template_t mac_ctx_template,
3052     crypto_req_handle_t req)
3053 {
3054 	int error = CRYPTO_FAILED;
3055 	dprov_state_t *softc = (dprov_state_t *)provider;
3056 	/* LINTED E_FUNC_SET_NOT_USED */
3057 	int instance;
3058 
3059 	instance = ddi_get_instance(softc->ds_dip);
3060 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_atomic: started\n",
3061 	    instance));
3062 
3063 	/* check mechanisms */
3064 	if (!dprov_valid_cipher_mech(encrypt_mech->cm_type)) {
3065 		cmn_err(CE_WARN, "dprov_encrypt_mac_atomic: unexpected encrypt "
3066 		    "mech type 0x%llx\n",
3067 		    (unsigned long long)encrypt_mech->cm_type);
3068 		return (CRYPTO_MECHANISM_INVALID);
3069 	}
3070 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3071 		cmn_err(CE_WARN, "dprov_encrypt_mac_atomic: unexpected mac "
3072 		    "mech type 0x%llx\n",
3073 		    (unsigned long long)mac_mech->cm_type);
3074 		return (CRYPTO_MECHANISM_INVALID);
3075 	}
3076 
3077 	if (encr_ctx_template != NULL || mac_ctx_template != NULL)
3078 		return (CRYPTO_ARGUMENTS_BAD);
3079 
3080 	/* submit request to the taskq */
3081 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_ATOMIC,
3082 	    softc, req, NULL, session_id, encrypt_mech, encrypt_key, mac_mech,
3083 	    mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3084 
3085 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_atomic: done "
3086 	    "err = 0x%x\n", instance, error));
3087 
3088 	return (error);
3089 }
3090 
3091 static int
3092 dprov_mac_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mac_mech,
3093     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3094     crypto_key_t *decrypt_key, crypto_spi_ctx_template_t mac_ctx_template,
3095     crypto_spi_ctx_template_t decr_ctx_template,
3096     crypto_req_handle_t req)
3097 {
3098 	int error = CRYPTO_FAILED;
3099 	dprov_state_t *softc;
3100 	/* LINTED E_FUNC_SET_NOT_USED */
3101 	int instance;
3102 
3103 	/* extract softc and instance number from context */
3104 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3105 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_init: started\n",
3106 	    instance));
3107 
3108 	/* check mechanisms */
3109 	if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3110 		cmn_err(CE_WARN, "dprov_mac_decrypt_init: unexpected decrypt "
3111 		    "mech type 0x%llx\n",
3112 		    (unsigned long long)decrypt_mech->cm_type);
3113 		return (CRYPTO_MECHANISM_INVALID);
3114 	}
3115 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3116 		cmn_err(CE_WARN, "dprov_mac_decrypt_init: unexpected mac "
3117 		    "mech type 0x%llx\n",
3118 		    (unsigned long long)mac_mech->cm_type);
3119 		return (CRYPTO_MECHANISM_INVALID);
3120 	}
3121 
3122 	if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3123 		return (CRYPTO_ARGUMENTS_BAD);
3124 
3125 	/* submit request to the taskq */
3126 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_INIT,
3127 	    softc, req, ctx, 0, decrypt_mech, decrypt_key, mac_mech, mac_key,
3128 	    NULL, NULL, NULL, KM_SLEEP);
3129 
3130 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_init: done "
3131 	    "err = 0x%x\n", instance, error));
3132 
3133 	return (error);
3134 }
3135 
3136 static int
3137 dprov_mac_decrypt(crypto_ctx_t *ctx, crypto_dual_data_t *ciphertext,
3138     crypto_data_t *mac, crypto_data_t *plaintext, crypto_req_handle_t req)
3139 {
3140 	int error = CRYPTO_FAILED;
3141 	dprov_state_t *softc;
3142 	/* LINTED E_FUNC_SET_NOT_USED */
3143 	int instance;
3144 
3145 	/* extract softc and instance number from context */
3146 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3147 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt: started\n",
3148 	    instance));
3149 
3150 	/* submit request to the taskq */
3151 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT,
3152 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3153 	    ciphertext, plaintext, mac, KM_NOSLEEP);
3154 
3155 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt: done "
3156 	    "err = 0x%x\n", instance, error));
3157 
3158 	return (error);
3159 }
3160 
3161 static int
3162 dprov_mac_decrypt_update(crypto_ctx_t *ctx, crypto_dual_data_t *ciphertext,
3163     crypto_data_t *plaintext, crypto_req_handle_t req)
3164 {
3165 	int error = CRYPTO_FAILED;
3166 	dprov_state_t *softc;
3167 	/* LINTED E_FUNC_SET_NOT_USED */
3168 	int instance;
3169 
3170 	/* extract softc and instance number from context */
3171 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3172 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_update: started\n",
3173 	    instance));
3174 
3175 	/* submit request to the taskq */
3176 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_UPDATE,
3177 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3178 	    ciphertext, plaintext, NULL, KM_NOSLEEP);
3179 
3180 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_update: done "
3181 	    "err = 0x%x\n", instance, error));
3182 
3183 	return (error);
3184 }
3185 
3186 static int
3187 dprov_mac_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *mac,
3188     crypto_data_t *plaintext, crypto_req_handle_t req)
3189 {
3190 	int error = CRYPTO_FAILED;
3191 	dprov_state_t *softc;
3192 	/* LINTED E_FUNC_SET_NOT_USED */
3193 	int instance;
3194 
3195 	/* extract softc and instance number from context */
3196 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3197 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_final: started\n",
3198 	    instance));
3199 
3200 	/* submit request to the taskq */
3201 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_FINAL,
3202 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3203 	    NULL, plaintext, mac, KM_NOSLEEP);
3204 
3205 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_final: done "
3206 	    "err = 0x%x\n", instance, error));
3207 
3208 	return (error);
3209 }
3210 
3211 static int
3212 dprov_mac_decrypt_atomic(crypto_provider_handle_t provider,
3213     crypto_session_id_t session_id, crypto_mechanism_t *mac_mech,
3214     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3215     crypto_key_t *decrypt_key, crypto_dual_data_t *ciphertext,
3216     crypto_data_t *mac, crypto_data_t *plaintext,
3217     crypto_spi_ctx_template_t mac_ctx_template,
3218     crypto_spi_ctx_template_t decr_ctx_template,
3219     crypto_req_handle_t req)
3220 {
3221 	int error = CRYPTO_FAILED;
3222 	dprov_state_t *softc = (dprov_state_t *)provider;
3223 	/* LINTED E_FUNC_SET_NOT_USED */
3224 	int instance;
3225 
3226 	instance = ddi_get_instance(softc->ds_dip);
3227 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_atomic: started\n",
3228 	    instance));
3229 
3230 	/* check mechanisms */
3231 	if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3232 		cmn_err(CE_WARN, "dprov_mac_decrypt_atomic: unexpected encrypt "
3233 		    "mech type 0x%llx\n",
3234 		    (unsigned long long)decrypt_mech->cm_type);
3235 		return (CRYPTO_MECHANISM_INVALID);
3236 	}
3237 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3238 		cmn_err(CE_WARN, "dprov_mac_decrypt_atomic: unexpected mac "
3239 		    "mech type 0x%llx\n",
3240 		    (unsigned long long)mac_mech->cm_type);
3241 		return (CRYPTO_MECHANISM_INVALID);
3242 	}
3243 
3244 	if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3245 		return (CRYPTO_ARGUMENTS_BAD);
3246 
3247 	/* submit request to the taskq */
3248 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_ATOMIC,
3249 	    softc, req, NULL, session_id, decrypt_mech, decrypt_key, mac_mech,
3250 	    mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3251 
3252 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_atomic: done "
3253 	    "err = 0x%x\n", instance, error));
3254 
3255 	return (error);
3256 }
3257 
3258 static int
3259 dprov_mac_verify_decrypt_atomic(crypto_provider_handle_t provider,
3260     crypto_session_id_t session_id, crypto_mechanism_t *mac_mech,
3261     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3262     crypto_key_t *decrypt_key, crypto_dual_data_t *ciphertext,
3263     crypto_data_t *mac, crypto_data_t *plaintext,
3264     crypto_spi_ctx_template_t mac_ctx_template,
3265     crypto_spi_ctx_template_t decr_ctx_template,
3266     crypto_req_handle_t req)
3267 {
3268 	int error = CRYPTO_FAILED;
3269 	dprov_state_t *softc = (dprov_state_t *)provider;
3270 	/* LINTED E_FUNC_SET_NOT_USED */
3271 	int instance;
3272 
3273 	instance = ddi_get_instance(softc->ds_dip);
3274 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_verify_decrypt_atomic:"
3275 	    "started\n", instance));
3276 
3277 	/* check mechanisms */
3278 	if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3279 		cmn_err(CE_WARN, "dprov_mac_verify_decrypt_atomic: "
3280 		    "unexpected encrypt mech type 0x%llx\n",
3281 		    (unsigned long long)decrypt_mech->cm_type);
3282 		return (CRYPTO_MECHANISM_INVALID);
3283 	}
3284 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3285 		cmn_err(CE_WARN, "dprov_mac_verify_decrypt_atomic: "
3286 		    "unexpected mac mech type 0x%llx\n",
3287 		    (unsigned long long)mac_mech->cm_type);
3288 		return (CRYPTO_MECHANISM_INVALID);
3289 	}
3290 
3291 	if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3292 		return (CRYPTO_ARGUMENTS_BAD);
3293 
3294 	/* submit request to the taskq */
3295 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC,
3296 	    softc, req, NULL, session_id, decrypt_mech, decrypt_key, mac_mech,
3297 	    mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3298 
3299 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_verify_decrypt_atomic: done "
3300 	    "err = 0x%x\n", instance, error));
3301 
3302 	return (error);
3303 }
3304 
3305 /*
3306  * Random number entry points.
3307  */
3308 
3309 static int
3310 dprov_seed_random(crypto_provider_handle_t provider,  crypto_session_id_t sid,
3311     uchar_t *buf, size_t len, crypto_req_handle_t req)
3312 {
3313 	int error = CRYPTO_FAILED;
3314 	dprov_state_t *softc = (dprov_state_t *)provider;
3315 	/* LINTED E_FUNC_SET_NOT_USED */
3316 	int instance;
3317 
3318 	instance = ddi_get_instance(softc->ds_dip);
3319 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: started\n",
3320 	    instance));
3321 
3322 	error = dprov_random_submit_req(DPROV_REQ_RANDOM_SEED, softc,
3323 	    req, buf, len, sid);
3324 
3325 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: done err = 0x0%x\n",
3326 	    instance, error));
3327 
3328 	return (error);
3329 }
3330 
3331 static int
3332 dprov_generate_random(crypto_provider_handle_t provider,
3333     crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req)
3334 {
3335 	int error = CRYPTO_FAILED;
3336 	dprov_state_t *softc = (dprov_state_t *)provider;
3337 	/* LINTED E_FUNC_SET_NOT_USED */
3338 	int instance;
3339 
3340 	instance = ddi_get_instance(softc->ds_dip);
3341 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: started\n",
3342 	    instance));
3343 
3344 	error = dprov_random_submit_req(DPROV_REQ_RANDOM_GENERATE, softc,
3345 	    req, buf, len, sid);
3346 
3347 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: done "
3348 	    "err = 0x0%x\n", instance, error));
3349 
3350 	return (error);
3351 }
3352 
3353 /*
3354  * Session Management entry points.
3355  */
3356 
3357 static int
3358 dprov_session_open(crypto_provider_handle_t provider,
3359     crypto_session_id_t *session_id, crypto_req_handle_t req)
3360 {
3361 	int error = CRYPTO_FAILED;
3362 	dprov_state_t *softc = (dprov_state_t *)provider;
3363 	/* LINTED E_FUNC_SET_NOT_USED */
3364 	int instance;
3365 
3366 	instance = ddi_get_instance(softc->ds_dip);
3367 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_open: started\n",
3368 	    instance));
3369 
3370 	error = dprov_session_submit_req(DPROV_REQ_SESSION_OPEN, softc,
3371 	    req, session_id, 0, 0, NULL, 0);
3372 
3373 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_open: done err = 0x0%x\n",
3374 	    instance, error));
3375 
3376 	return (error);
3377 }
3378 
3379 static int
3380 dprov_session_close(crypto_provider_handle_t provider,
3381     crypto_session_id_t session_id, crypto_req_handle_t req)
3382 {
3383 	int error = CRYPTO_FAILED;
3384 	dprov_state_t *softc = (dprov_state_t *)provider;
3385 	/* LINTED E_FUNC_SET_NOT_USED */
3386 	int instance;
3387 
3388 	instance = ddi_get_instance(softc->ds_dip);
3389 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_close: started\n",
3390 	    instance));
3391 
3392 	error = dprov_session_submit_req(DPROV_REQ_SESSION_CLOSE, softc,
3393 	    req, 0, session_id, 0, NULL, 0);
3394 
3395 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_close: done err = 0x0%x\n",
3396 	    instance, error));
3397 
3398 	return (error);
3399 }
3400 
3401 static int
3402 dprov_session_login(crypto_provider_handle_t provider,
3403     crypto_session_id_t session_id, crypto_user_type_t user_type,
3404     char *pin, size_t pin_len, crypto_req_handle_t req)
3405 {
3406 	int error = CRYPTO_FAILED;
3407 	dprov_state_t *softc = (dprov_state_t *)provider;
3408 	/* LINTED E_FUNC_SET_NOT_USED */
3409 	int instance;
3410 
3411 	instance = ddi_get_instance(softc->ds_dip);
3412 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_login: started\n",
3413 	    instance));
3414 
3415 	error = dprov_session_submit_req(DPROV_REQ_SESSION_LOGIN, softc,
3416 	    req, 0, session_id, user_type, pin, pin_len);
3417 
3418 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_login: done err = 0x0%x\n",
3419 	    instance, error));
3420 
3421 	return (error);
3422 }
3423 
3424 static int
3425 dprov_session_logout(crypto_provider_handle_t provider,
3426     crypto_session_id_t session_id, crypto_req_handle_t req)
3427 {
3428 	int error = CRYPTO_FAILED;
3429 	dprov_state_t *softc = (dprov_state_t *)provider;
3430 	/* LINTED E_FUNC_SET_NOT_USED */
3431 	int instance;
3432 
3433 	instance = ddi_get_instance(softc->ds_dip);
3434 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_logout: started\n",
3435 	    instance));
3436 
3437 	error = dprov_session_submit_req(DPROV_REQ_SESSION_LOGOUT, softc,
3438 	    req, 0, session_id, 0, NULL, 0);
3439 
3440 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_logout: done err = 0x0%x\n",
3441 	    instance, error));
3442 
3443 	return (error);
3444 }
3445 
3446 /*
3447  * Object management entry points.
3448  */
3449 
3450 static int
3451 dprov_object_create(crypto_provider_handle_t provider,
3452     crypto_session_id_t session_id, crypto_object_attribute_t *template,
3453     uint_t attribute_count, crypto_object_id_t *object,
3454     crypto_req_handle_t req)
3455 {
3456 	int error = CRYPTO_FAILED;
3457 	dprov_state_t *softc = (dprov_state_t *)provider;
3458 	/* LINTED E_FUNC_SET_NOT_USED */
3459 	int instance;
3460 
3461 	instance = ddi_get_instance(softc->ds_dip);
3462 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_create: started\n",
3463 	    instance));
3464 
3465 	/* submit request to the taskq */
3466 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_CREATE, softc, req,
3467 	    session_id, 0, template, attribute_count, object, NULL, NULL,
3468 	    NULL, 0, NULL, KM_NOSLEEP);
3469 
3470 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_create: done err = 0x0%x\n",
3471 	    instance, error));
3472 
3473 	return (error);
3474 }
3475 
3476 static int
3477 dprov_object_copy(crypto_provider_handle_t provider,
3478     crypto_session_id_t session_id, crypto_object_id_t object,
3479     crypto_object_attribute_t *template, uint_t attribute_count,
3480     crypto_object_id_t *new_object, crypto_req_handle_t req)
3481 {
3482 	int error = CRYPTO_FAILED;
3483 	dprov_state_t *softc = (dprov_state_t *)provider;
3484 	/* LINTED E_FUNC_SET_NOT_USED */
3485 	int instance;
3486 
3487 	instance = ddi_get_instance(softc->ds_dip);
3488 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_copy: started\n",
3489 	    instance));
3490 
3491 	/* submit request to the taskq */
3492 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_COPY, softc, req,
3493 	    session_id, object, template, attribute_count, new_object,
3494 	    NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3495 
3496 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_copy: done err = 0x0%x\n",
3497 	    instance, error));
3498 
3499 	return (error);
3500 }
3501 
3502 static int
3503 dprov_object_destroy(crypto_provider_handle_t provider,
3504     crypto_session_id_t session_id, crypto_object_id_t object,
3505     crypto_req_handle_t req)
3506 {
3507 	int error = CRYPTO_FAILED;
3508 	dprov_state_t *softc = (dprov_state_t *)provider;
3509 	/* LINTED E_FUNC_SET_NOT_USED */
3510 	int instance;
3511 
3512 	instance = ddi_get_instance(softc->ds_dip);
3513 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_destroy: started\n",
3514 	    instance));
3515 
3516 	/* submit request to the taskq */
3517 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_DESTROY, softc, req,
3518 	    session_id, object, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL,
3519 	    KM_NOSLEEP);
3520 
3521 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_destroy: done err = 0x0%x\n",
3522 	    instance, error));
3523 
3524 	return (error);
3525 }
3526 
3527 static int
3528 dprov_object_get_size(crypto_provider_handle_t provider,
3529     crypto_session_id_t session_id, crypto_object_id_t object,
3530     size_t *size, crypto_req_handle_t req)
3531 {
3532 	int error = CRYPTO_FAILED;
3533 	dprov_state_t *softc = (dprov_state_t *)provider;
3534 	/* LINTED E_FUNC_SET_NOT_USED */
3535 	int instance;
3536 
3537 	instance = ddi_get_instance(softc->ds_dip);
3538 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_size: started\n",
3539 	    instance));
3540 
3541 	/* submit request to the taskq */
3542 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_GET_SIZE, softc, req,
3543 	    session_id, object, NULL, 0, NULL, size, NULL, NULL, 0, NULL,
3544 	    KM_NOSLEEP);
3545 
3546 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_size: done err = 0x0%x\n",
3547 	    instance, error));
3548 
3549 	return (error);
3550 }
3551 
3552 static int
3553 dprov_object_get_attribute_value(crypto_provider_handle_t provider,
3554     crypto_session_id_t session_id, crypto_object_id_t object,
3555     crypto_object_attribute_t *template, uint_t attribute_count,
3556     crypto_req_handle_t req)
3557 {
3558 	int error = CRYPTO_FAILED;
3559 	dprov_state_t *softc = (dprov_state_t *)provider;
3560 	/* LINTED E_FUNC_SET_NOT_USED */
3561 	int instance;
3562 
3563 	instance = ddi_get_instance(softc->ds_dip);
3564 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_attribute_value: "
3565 	    "started\n", instance));
3566 
3567 	/* submit request to the taskq */
3568 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE,
3569 	    softc, req, session_id, object, template, attribute_count,
3570 	    NULL, NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3571 
3572 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_attribute_value: "
3573 	    "done err = 0x0%x\n", instance, error));
3574 
3575 	return (error);
3576 }
3577 
3578 static int
3579 dprov_object_set_attribute_value(crypto_provider_handle_t provider,
3580     crypto_session_id_t session_id, crypto_object_id_t object,
3581     crypto_object_attribute_t *template, uint_t attribute_count,
3582     crypto_req_handle_t req)
3583 {
3584 	int error = CRYPTO_FAILED;
3585 	dprov_state_t *softc = (dprov_state_t *)provider;
3586 	/* LINTED E_FUNC_SET_NOT_USED */
3587 	int instance;
3588 
3589 	instance = ddi_get_instance(softc->ds_dip);
3590 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_set_attribute_value: "
3591 	    "started\n", instance));
3592 
3593 	/* submit request to the taskq */
3594 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE,
3595 	    softc, req, session_id, object, template, attribute_count,
3596 	    NULL, NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3597 
3598 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_set_attribute_value: "
3599 	    "done err = 0x0%x\n", instance, error));
3600 
3601 	return (error);
3602 }
3603 
3604 static int
3605 dprov_object_find_init(crypto_provider_handle_t provider,
3606     crypto_session_id_t session_id, crypto_object_attribute_t *template,
3607     uint_t attribute_count, void **provider_private,
3608     crypto_req_handle_t req)
3609 {
3610 	int error = CRYPTO_FAILED;
3611 	dprov_state_t *softc = (dprov_state_t *)provider;
3612 	/* LINTED E_FUNC_SET_NOT_USED */
3613 	int instance;
3614 
3615 	instance = ddi_get_instance(softc->ds_dip);
3616 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_init: started\n",
3617 	    instance));
3618 
3619 	/* submit request to the taskq */
3620 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND_INIT, softc, req,
3621 	    session_id, 0, template, attribute_count, NULL, NULL,
3622 	    provider_private, NULL, 0, NULL, KM_SLEEP);
3623 
3624 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_init: done "
3625 	    "err = 0x0%x\n", instance, error));
3626 
3627 	return (error);
3628 }
3629 
3630 static int
3631 dprov_object_find(crypto_provider_handle_t provider, void *provider_private,
3632     crypto_object_id_t *objects, uint_t max_object_count,
3633     uint_t *object_count, crypto_req_handle_t req)
3634 {
3635 	int error = CRYPTO_FAILED;
3636 	dprov_state_t *softc = (dprov_state_t *)provider;
3637 	/* LINTED E_FUNC_SET_NOT_USED */
3638 	int instance;
3639 
3640 	instance = ddi_get_instance(softc->ds_dip);
3641 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find: started\n",
3642 	    instance));
3643 
3644 	/* submit request to the taskq */
3645 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND, softc, req,
3646 	    0, 0, NULL, 0, objects, NULL, NULL, provider_private,
3647 	    max_object_count, object_count, KM_NOSLEEP);
3648 
3649 
3650 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find: done err = 0x0%x\n",
3651 	    instance, error));
3652 
3653 	return (error);
3654 }
3655 
3656 static int
3657 dprov_object_find_final(crypto_provider_handle_t provider,
3658     void *provider_private, crypto_req_handle_t req)
3659 {
3660 	int error = CRYPTO_FAILED;
3661 	dprov_state_t *softc = (dprov_state_t *)provider;
3662 	/* LINTED E_FUNC_SET_NOT_USED */
3663 	int instance;
3664 
3665 	instance = ddi_get_instance(softc->ds_dip);
3666 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_final: started\n",
3667 	    instance));
3668 
3669 	/* submit request to the taskq */
3670 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND_FINAL, softc, req,
3671 	    0, 0, NULL, 0, NULL, NULL, NULL, provider_private,
3672 	    0, NULL, KM_NOSLEEP);
3673 
3674 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_final: done "
3675 	    "err = 0x0%x\n", instance, error));
3676 
3677 	return (error);
3678 }
3679 
3680 /*
3681  * Key management entry points.
3682  */
3683 
3684 static int
3685 dprov_key_generate(crypto_provider_handle_t provider,
3686     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3687     crypto_object_attribute_t *template, uint_t attribute_count,
3688     crypto_object_id_t *object, crypto_req_handle_t req)
3689 {
3690 	int error = CRYPTO_FAILED;
3691 	dprov_state_t *softc = (dprov_state_t *)provider;
3692 	/* LINTED E_FUNC_SET_NOT_USED */
3693 	int instance;
3694 
3695 	instance = ddi_get_instance(softc->ds_dip);
3696 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate: started\n",
3697 	    instance));
3698 
3699 	/* submit request to the taskq */
3700 	error = dprov_key_submit_req(DPROV_REQ_KEY_GENERATE, softc, req,
3701 	    session_id, mechanism, template, attribute_count, object, NULL,
3702 	    0, NULL, NULL, NULL, 0);
3703 
3704 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate: done err = 0x0%x\n",
3705 	    instance, error));
3706 
3707 	return (error);
3708 }
3709 
3710 static int
3711 dprov_key_generate_pair(crypto_provider_handle_t provider,
3712     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3713     crypto_object_attribute_t *public_key_template,
3714     uint_t public_key_attribute_count,
3715     crypto_object_attribute_t *private_key_template,
3716     uint_t private_key_attribute_count,
3717     crypto_object_id_t *public_key, crypto_object_id_t *private_key,
3718     crypto_req_handle_t req)
3719 {
3720 	int error = CRYPTO_FAILED;
3721 	dprov_state_t *softc = (dprov_state_t *)provider;
3722 	/* LINTED E_FUNC_SET_NOT_USED */
3723 	int instance;
3724 
3725 	instance = ddi_get_instance(softc->ds_dip);
3726 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate_pair: started\n",
3727 	    instance));
3728 
3729 	/* submit request to the taskq */
3730 	error = dprov_key_submit_req(DPROV_REQ_KEY_GENERATE_PAIR, softc, req,
3731 	    session_id, mechanism, public_key_template,
3732 	    public_key_attribute_count, public_key, private_key_template,
3733 	    private_key_attribute_count, private_key, NULL, NULL, 0);
3734 
3735 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate_pair: done err = 0x0%x\n",
3736 	    instance, error));
3737 
3738 	return (error);
3739 }
3740 
3741 static int
3742 dprov_key_wrap(crypto_provider_handle_t provider,
3743     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3744     crypto_key_t *wrapping_key, crypto_object_id_t *key,
3745     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr, crypto_req_handle_t req)
3746 {
3747 	int error = CRYPTO_FAILED;
3748 	dprov_state_t *softc = (dprov_state_t *)provider;
3749 	/* LINTED E_FUNC_SET_NOT_USED */
3750 	int instance;
3751 
3752 	instance = ddi_get_instance(softc->ds_dip);
3753 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_wrap: started\n",
3754 	    instance));
3755 
3756 	/* submit request to the taskq */
3757 	error = dprov_key_submit_req(DPROV_REQ_KEY_WRAP, softc, req,
3758 	    session_id, mechanism, NULL, 0, key, NULL,
3759 	    0, NULL, wrapping_key, wrapped_key, wrapped_key_len_ptr);
3760 
3761 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_wrap: done err = 0x0%x\n",
3762 	    instance, error));
3763 
3764 	return (error);
3765 }
3766 
3767 static int
3768 dprov_key_unwrap(crypto_provider_handle_t provider,
3769     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3770     crypto_key_t *unwrapping_key, uchar_t *wrapped_key,
3771     size_t *wrapped_key_len_ptr, crypto_object_attribute_t *template,
3772     uint_t attribute_count, crypto_object_id_t *key, crypto_req_handle_t req)
3773 {
3774 	int error = CRYPTO_FAILED;
3775 	dprov_state_t *softc = (dprov_state_t *)provider;
3776 	/* LINTED E_FUNC_SET_NOT_USED */
3777 	int instance;
3778 
3779 	instance = ddi_get_instance(softc->ds_dip);
3780 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_unwrap: started\n",
3781 	    instance));
3782 
3783 	/* submit request to the taskq */
3784 	error = dprov_key_submit_req(DPROV_REQ_KEY_UNWRAP, softc, req,
3785 	    session_id, mechanism, template, attribute_count, key, NULL,
3786 	    0, NULL, unwrapping_key, wrapped_key, wrapped_key_len_ptr);
3787 
3788 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_unwrap: done err = 0x0%x\n",
3789 	    instance, error));
3790 
3791 	return (error);
3792 }
3793 
3794 static int
3795 dprov_key_derive(crypto_provider_handle_t provider,
3796     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3797     crypto_key_t *base_key, crypto_object_attribute_t *template,
3798     uint_t attribute_count, crypto_object_id_t *key, crypto_req_handle_t req)
3799 {
3800 	int error = CRYPTO_FAILED;
3801 	dprov_state_t *softc = (dprov_state_t *)provider;
3802 	/* LINTED E_FUNC_SET_NOT_USED */
3803 	int instance;
3804 
3805 	instance = ddi_get_instance(softc->ds_dip);
3806 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_derive: started\n",
3807 	    instance));
3808 
3809 	/* submit request to the taskq */
3810 	error = dprov_key_submit_req(DPROV_REQ_KEY_DERIVE, softc, req,
3811 	    session_id, mechanism, template, attribute_count, key, NULL,
3812 	    0, NULL, base_key, NULL, 0);
3813 
3814 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_derive: done err = 0x0%x\n",
3815 	    instance, error));
3816 
3817 	return (error);
3818 }
3819 
3820 /*
3821  * Provider management entry points.
3822  */
3823 
3824 static int
3825 dprov_ext_info(crypto_provider_handle_t provider,
3826     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t req)
3827 {
3828 	int error = CRYPTO_FAILED;
3829 	dprov_state_t *softc = (dprov_state_t *)provider;
3830 	/* LINTED E_FUNC_SET_NOT_USED */
3831 	int instance;
3832 
3833 	instance = ddi_get_instance(softc->ds_dip);
3834 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_ext_info: started\n",
3835 	    instance));
3836 
3837 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_EXTINFO, softc, req,
3838 	    0, NULL, 0, NULL, 0, NULL, ext_info);
3839 
3840 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_ext_info: done err = 0x0%x\n",
3841 	    instance, error));
3842 
3843 	return (error);
3844 }
3845 
3846 static int
3847 dprov_init_token(crypto_provider_handle_t provider, char *pin, size_t pin_len,
3848     char *label, crypto_req_handle_t req)
3849 {
3850 	int error = CRYPTO_FAILED;
3851 	dprov_state_t *softc = (dprov_state_t *)provider;
3852 	/* LINTED E_FUNC_SET_NOT_USED */
3853 	int instance;
3854 
3855 	instance = ddi_get_instance(softc->ds_dip);
3856 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_token: started\n",
3857 	    instance));
3858 
3859 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_INITTOKEN, softc, req,
3860 	    0, pin, pin_len, NULL, 0, label, NULL);
3861 
3862 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_token: done err = 0x0%x\n",
3863 	    instance, error));
3864 
3865 	return (error);
3866 }
3867 
3868 static int
3869 dprov_init_pin(crypto_provider_handle_t provider,
3870     crypto_session_id_t session_id, char *pin, size_t pin_len,
3871     crypto_req_handle_t req)
3872 {
3873 	int error = CRYPTO_FAILED;
3874 	dprov_state_t *softc = (dprov_state_t *)provider;
3875 	/* LINTED E_FUNC_SET_NOT_USED */
3876 	int instance;
3877 
3878 	instance = ddi_get_instance(softc->ds_dip);
3879 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_pin: started\n",
3880 	    instance));
3881 
3882 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_INITPIN, softc, req,
3883 	    session_id, pin, pin_len, NULL, 0, NULL, NULL);
3884 
3885 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_pin: done err = 0x0%x\n",
3886 	    instance, error));
3887 
3888 	return (error);
3889 }
3890 
3891 static int
3892 dprov_set_pin(crypto_provider_handle_t provider, crypto_session_id_t session_id,
3893     char *old_pin, size_t old_pin_len, char *new_pin, size_t new_pin_len,
3894     crypto_req_handle_t req)
3895 {
3896 	int error = CRYPTO_FAILED;
3897 	dprov_state_t *softc = (dprov_state_t *)provider;
3898 	/* LINTED E_FUNC_SET_NOT_USED */
3899 	int instance;
3900 
3901 	instance = ddi_get_instance(softc->ds_dip);
3902 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_set_pin: started\n",
3903 	    instance));
3904 
3905 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_SETPIN, softc, req,
3906 	    session_id, new_pin, new_pin_len, old_pin, old_pin_len, NULL, NULL);
3907 
3908 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_set_pin: done err = 0x0%x\n",
3909 	    instance, error));
3910 
3911 	return (error);
3912 }
3913 
3914 
3915 /*
3916  * Context management entry points.
3917  */
3918 
3919 /*
3920  * Allocate a dprov-private context based on the specified dprov request.
3921  * For dual cipher/mac requests, the allocated context will
3922  * contain a structure dprov_ctx_dual_t, for other request types,
3923  * it will contain a dprov_ctx_single.
3924  * Returns one of the CRYPTO_ status codes.
3925  */
3926 static int
3927 dprov_alloc_context(dprov_req_type_t req_type, crypto_ctx_t *spi_ctx)
3928 {
3929 	dprov_ctx_single_t *dprov_private;
3930 
3931 	switch (req_type) {
3932 	case DPROV_REQ_ENCRYPT_MAC_INIT:
3933 	case DPROV_REQ_MAC_DECRYPT_INIT:
3934 		dprov_private = kmem_zalloc(sizeof (dprov_ctx_dual_t),
3935 		    KM_NOSLEEP);
3936 		if (dprov_private == NULL)
3937 			return (CRYPTO_HOST_MEMORY);
3938 		dprov_private->dc_type = DPROV_CTX_DUAL;
3939 		break;
3940 	default:
3941 		dprov_private = kmem_zalloc(sizeof (dprov_ctx_single_t),
3942 		    KM_NOSLEEP);
3943 		if (dprov_private == NULL)
3944 			return (CRYPTO_HOST_MEMORY);
3945 		dprov_private->dc_type = DPROV_CTX_SINGLE;
3946 		break;
3947 	}
3948 
3949 	spi_ctx->cc_provider_private = (void *)dprov_private;
3950 
3951 	return (CRYPTO_SUCCESS);
3952 }
3953 
3954 static int
3955 dprov_free_context(crypto_ctx_t *ctx)
3956 {
3957 	if (ctx->cc_provider_private == NULL)
3958 		return (CRYPTO_SUCCESS);
3959 
3960 	DPROV_DEBUG(D_CONTEXT, ("dprov_free_context\n"));
3961 
3962 	{
3963 		/*
3964 		 * The dprov private context could contain either
3965 		 * a dprov_ctx_single_t or a dprov_ctx_dual_t. Free
3966 		 * the context based on its type. The k-API contexts
3967 		 * that were attached to the dprov private context
3968 		 * are freed by the framework.
3969 		 */
3970 		dprov_ctx_single_t *ctx_single =
3971 		    (dprov_ctx_single_t *)(ctx->cc_provider_private);
3972 
3973 		if (ctx_single->dc_type == DPROV_CTX_SINGLE) {
3974 			crypto_context_t context = DPROV_CTX_SINGLE(ctx);
3975 
3976 			/*
3977 			 * This case happens for the crypto_cancel_ctx() case.
3978 			 * We have to cancel the SW provider context also.
3979 			 */
3980 			if (context != NULL)
3981 				crypto_cancel_ctx(context);
3982 
3983 			kmem_free(ctx_single, sizeof (dprov_ctx_single_t));
3984 		} else {
3985 			crypto_context_t cipher_context =
3986 			    DPROV_CTX_DUAL_CIPHER(ctx);
3987 			crypto_context_t mac_context = DPROV_CTX_DUAL_MAC(ctx);
3988 
3989 			/* See comments above. */
3990 			if (cipher_context != NULL)
3991 				crypto_cancel_ctx(cipher_context);
3992 			if (mac_context != NULL)
3993 				crypto_cancel_ctx(mac_context);
3994 
3995 			ASSERT(ctx_single->dc_type == DPROV_CTX_DUAL);
3996 			kmem_free(ctx_single, sizeof (dprov_ctx_dual_t));
3997 		}
3998 		ctx->cc_provider_private = NULL;
3999 	}
4000 
4001 	return (CRYPTO_SUCCESS);
4002 }
4003 
4004 
4005 /*
4006  * Allocate a dprov taskq request and initialize the common fields.
4007  * Return NULL if the memory allocation failed.
4008  */
4009 static dprov_req_t *
4010 dprov_alloc_req(dprov_req_type_t req_type, dprov_state_t *softc,
4011     crypto_req_handle_t kcf_req, int kmflag)
4012 {
4013 	dprov_req_t *taskq_req;
4014 
4015 	if ((taskq_req = kmem_alloc(sizeof (dprov_req_t), kmflag)) == NULL)
4016 		return (NULL);
4017 
4018 	taskq_req->dr_type = req_type;
4019 	taskq_req->dr_softc = softc;
4020 	taskq_req->dr_kcf_req = kcf_req;
4021 
4022 	return (taskq_req);
4023 }
4024 
4025 /*
4026  * Dispatch a dprov request on the taskq associated with a softc.
4027  * Returns CRYPTO_HOST_MEMORY if the request cannot be queued,
4028  * CRYPTO_QUEUED on success.
4029  */
4030 static int
4031 dprov_taskq_dispatch(dprov_state_t *softc, dprov_req_t *taskq_req,
4032     task_func_t *func, int kmflag)
4033 {
4034 	if (taskq_dispatch(softc->ds_taskq, func, taskq_req,
4035 	    kmflag == KM_NOSLEEP ? TQ_NOSLEEP : TQ_SLEEP) == (taskqid_t)0) {
4036 		kmem_free(taskq_req, sizeof (dprov_req_t));
4037 		return (CRYPTO_HOST_MEMORY);
4038 	} else
4039 		return (CRYPTO_QUEUED);
4040 }
4041 
4042 /*
4043  * Helper function to submit digest operations to the taskq.
4044  * Returns one of the CRYPTO_ errors.
4045  */
4046 static int
4047 dprov_digest_submit_req(dprov_req_type_t req_type,
4048     dprov_state_t *softc, crypto_req_handle_t req,
4049     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
4050     crypto_data_t *digest, crypto_ctx_t *ctx, int kmflag)
4051 {
4052 	dprov_req_t *taskq_req;
4053 
4054 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4055 		return (CRYPTO_HOST_MEMORY);
4056 
4057 	taskq_req->dr_digest_req.dr_mechanism = mechanism;
4058 	taskq_req->dr_digest_req.dr_ctx = ctx;
4059 	taskq_req->dr_digest_req.dr_data = data;
4060 	taskq_req->dr_digest_req.dr_key = key;
4061 	taskq_req->dr_digest_req.dr_digest = digest;
4062 
4063 	return (dprov_taskq_dispatch(softc, taskq_req,
4064 	    (task_func_t *)dprov_digest_task, kmflag));
4065 }
4066 
4067 /*
4068  * Helper function to submit mac operations to the taskq.
4069  * Returns one of the CRYPTO_ errors.
4070  */
4071 static int
4072 dprov_mac_submit_req(dprov_req_type_t req_type,
4073     dprov_state_t *softc, crypto_req_handle_t req,
4074     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
4075     crypto_data_t *mac, crypto_ctx_t *ctx, crypto_session_id_t sid, int kmflag)
4076 {
4077 	dprov_req_t *taskq_req;
4078 
4079 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4080 		return (CRYPTO_HOST_MEMORY);
4081 
4082 	taskq_req->dr_mac_req.dr_mechanism = mechanism;
4083 	taskq_req->dr_mac_req.dr_ctx = ctx;
4084 	taskq_req->dr_mac_req.dr_data = data;
4085 	taskq_req->dr_mac_req.dr_key = key;
4086 	taskq_req->dr_mac_req.dr_mac = mac;
4087 	taskq_req->dr_mac_req.dr_session_id = sid;
4088 
4089 	return (dprov_taskq_dispatch(softc, taskq_req,
4090 	    (task_func_t *)dprov_mac_task, kmflag));
4091 }
4092 
4093 /*
4094  * Helper function to submit sign operations to the taskq.
4095  * Returns one of the CRYPTO_ errors.
4096  */
4097 static int
4098 dprov_sign_submit_req(dprov_req_type_t req_type,
4099     dprov_state_t *softc, crypto_req_handle_t req,
4100     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
4101     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
4102     int kmflag)
4103 {
4104 	dprov_req_t *taskq_req;
4105 
4106 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4107 		return (CRYPTO_HOST_MEMORY);
4108 
4109 	taskq_req->dr_sign_req.sr_mechanism = mechanism;
4110 	taskq_req->dr_sign_req.sr_ctx = ctx;
4111 	taskq_req->dr_sign_req.sr_key = key;
4112 	taskq_req->dr_sign_req.sr_data = data;
4113 	taskq_req->dr_sign_req.sr_signature = signature;
4114 	taskq_req->dr_sign_req.sr_session_id = sid;
4115 
4116 	return (dprov_taskq_dispatch(softc, taskq_req,
4117 	    (task_func_t *)dprov_sign_task, kmflag));
4118 }
4119 
4120 /*
4121  * Helper function to submit verify operations to the taskq.
4122  * Returns one of the CRYPTO_ errors.
4123  */
4124 static int
4125 dprov_verify_submit_req(dprov_req_type_t req_type,
4126     dprov_state_t *softc, crypto_req_handle_t req,
4127     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
4128     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
4129     int kmflag)
4130 {
4131 	dprov_req_t *taskq_req;
4132 
4133 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4134 		return (CRYPTO_HOST_MEMORY);
4135 
4136 	taskq_req->dr_verify_req.vr_mechanism = mechanism;
4137 	taskq_req->dr_verify_req.vr_ctx = ctx;
4138 	taskq_req->dr_verify_req.vr_key = key;
4139 	taskq_req->dr_verify_req.vr_data = data;
4140 	taskq_req->dr_verify_req.vr_signature = signature;
4141 	taskq_req->dr_verify_req.vr_session_id = sid;
4142 
4143 	return (dprov_taskq_dispatch(softc, taskq_req,
4144 	    (task_func_t *)dprov_verify_task, kmflag));
4145 }
4146 
4147 /*
4148  * Helper function to submit dual operations to the taskq.
4149  * Returns one of the CRYPTO_ errors.
4150  */
4151 static int
4152 dprov_dual_submit_req(dprov_req_type_t req_type, dprov_state_t *softc,
4153     crypto_req_handle_t req, crypto_ctx_t *signverify_ctx,
4154     crypto_ctx_t *cipher_ctx, crypto_data_t *plaintext,
4155     crypto_data_t *ciphertext)
4156 {
4157 	dprov_req_t *taskq_req;
4158 
4159 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4160 	    KM_NOSLEEP)) == NULL)
4161 		return (CRYPTO_HOST_MEMORY);
4162 
4163 	taskq_req->dr_dual_req.dr_signverify_ctx = signverify_ctx;
4164 	taskq_req->dr_dual_req.dr_cipher_ctx = cipher_ctx;
4165 	taskq_req->dr_dual_req.dr_plaintext = plaintext;
4166 	taskq_req->dr_dual_req.dr_ciphertext = ciphertext;
4167 
4168 	return (dprov_taskq_dispatch(softc, taskq_req,
4169 	    (task_func_t *)dprov_dual_task, KM_NOSLEEP));
4170 }
4171 
4172 /*
4173  * Helper function to submit dual cipher/mac operations to the taskq.
4174  * Returns one of the CRYPTO_ errors.
4175  */
4176 static int
4177 dprov_cipher_mac_submit_req(dprov_req_type_t req_type,
4178     dprov_state_t *softc, crypto_req_handle_t req, crypto_ctx_t *ctx,
4179     crypto_session_id_t sid, crypto_mechanism_t *cipher_mech,
4180     crypto_key_t *cipher_key, crypto_mechanism_t *mac_mech,
4181     crypto_key_t *mac_key, crypto_dual_data_t *dual_data,
4182     crypto_data_t *data, crypto_data_t *mac, int kmflag)
4183 {
4184 	dprov_req_t *taskq_req;
4185 
4186 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4187 		return (CRYPTO_HOST_MEMORY);
4188 
4189 	taskq_req->dr_cipher_mac_req.mr_session_id = sid;
4190 	taskq_req->dr_cipher_mac_req.mr_ctx = ctx;
4191 	taskq_req->dr_cipher_mac_req.mr_cipher_mech = cipher_mech;
4192 	taskq_req->dr_cipher_mac_req.mr_cipher_key = cipher_key;
4193 	taskq_req->dr_cipher_mac_req.mr_mac_mech = mac_mech;
4194 	taskq_req->dr_cipher_mac_req.mr_mac_key = mac_key;
4195 	taskq_req->dr_cipher_mac_req.mr_dual_data = dual_data;
4196 	taskq_req->dr_cipher_mac_req.mr_data = data;
4197 	taskq_req->dr_cipher_mac_req.mr_mac = mac;
4198 
4199 	return (dprov_taskq_dispatch(softc, taskq_req,
4200 	    (task_func_t *)dprov_cipher_mac_task, kmflag));
4201 }
4202 
4203 /*
4204  * Helper function to submit cipher operations to the taskq.
4205  * Returns one of the CRYPTO_ errors.
4206  */
4207 static int
4208 dprov_cipher_submit_req(dprov_req_type_t req_type,
4209     dprov_state_t *softc, crypto_req_handle_t req,
4210     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *plaintext,
4211     crypto_data_t *ciphertext, crypto_ctx_t *ctx, crypto_session_id_t sid,
4212     int kmflag)
4213 {
4214 	dprov_req_t *taskq_req;
4215 
4216 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4217 		return (CRYPTO_HOST_MEMORY);
4218 
4219 	taskq_req->dr_cipher_req.dr_mechanism = mechanism;
4220 	taskq_req->dr_cipher_req.dr_ctx = ctx;
4221 	taskq_req->dr_cipher_req.dr_key = key;
4222 	taskq_req->dr_cipher_req.dr_plaintext = plaintext;
4223 	taskq_req->dr_cipher_req.dr_ciphertext = ciphertext;
4224 	taskq_req->dr_cipher_req.dr_session_id = sid;
4225 
4226 	return (dprov_taskq_dispatch(softc, taskq_req,
4227 	    (task_func_t *)dprov_cipher_task, kmflag));
4228 }
4229 
4230 /*
4231  * Helper function to submit random number operations to the taskq.
4232  * Returns one of the CRYPTO_ errors.
4233  */
4234 static int
4235 dprov_random_submit_req(dprov_req_type_t req_type,
4236     dprov_state_t *softc, crypto_req_handle_t req, uchar_t *buf, size_t len,
4237     crypto_session_id_t sid)
4238 {
4239 	dprov_req_t *taskq_req;
4240 
4241 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4242 	    KM_NOSLEEP)) == NULL)
4243 		return (CRYPTO_HOST_MEMORY);
4244 
4245 	taskq_req->dr_random_req.rr_buf = buf;
4246 	taskq_req->dr_random_req.rr_len = len;
4247 	taskq_req->dr_random_req.rr_session_id = sid;
4248 
4249 	return (dprov_taskq_dispatch(softc, taskq_req,
4250 	    (task_func_t *)dprov_random_task, KM_NOSLEEP));
4251 }
4252 
4253 
4254 /*
4255  * Helper function to submit session management operations to the taskq.
4256  * Returns one of the CRYPTO_ errors.
4257  */
4258 static int
4259 dprov_session_submit_req(dprov_req_type_t req_type,
4260     dprov_state_t *softc, crypto_req_handle_t req,
4261     crypto_session_id_t *session_id_ptr, crypto_session_id_t session_id,
4262     crypto_user_type_t user_type, char *pin, size_t pin_len)
4263 {
4264 	dprov_req_t *taskq_req;
4265 
4266 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4267 	    KM_NOSLEEP)) == NULL)
4268 		return (CRYPTO_HOST_MEMORY);
4269 
4270 	taskq_req->dr_session_req.sr_session_id_ptr = session_id_ptr;
4271 	taskq_req->dr_session_req.sr_session_id = session_id;
4272 	taskq_req->dr_session_req.sr_user_type = user_type;
4273 	taskq_req->dr_session_req.sr_pin = pin;
4274 	taskq_req->dr_session_req.sr_pin_len = pin_len;
4275 
4276 	return (dprov_taskq_dispatch(softc, taskq_req,
4277 	    (task_func_t *)dprov_session_task, KM_NOSLEEP));
4278 }
4279 
4280 /*
4281  * Helper function to submit object management operations to the taskq.
4282  * Returns one of the CRYPTO_ errors.
4283  */
4284 static int
4285 dprov_object_submit_req(dprov_req_type_t req_type,
4286     dprov_state_t *softc, crypto_req_handle_t req,
4287     crypto_session_id_t session_id, crypto_object_id_t object_id,
4288     crypto_object_attribute_t *template, uint_t attribute_count,
4289     crypto_object_id_t *object_id_ptr, size_t *object_size,
4290     void **find_pp, void *find_p, uint_t max_object_count,
4291     uint_t *object_count_ptr, int kmflag)
4292 {
4293 	dprov_req_t *taskq_req;
4294 
4295 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4296 	    kmflag)) == NULL)
4297 		return (CRYPTO_HOST_MEMORY);
4298 
4299 	taskq_req->dr_object_req.or_session_id = session_id;
4300 	taskq_req->dr_object_req.or_object_id = object_id;
4301 	taskq_req->dr_object_req.or_template = template;
4302 	taskq_req->dr_object_req.or_attribute_count = attribute_count;
4303 	taskq_req->dr_object_req.or_object_id_ptr = object_id_ptr;
4304 	taskq_req->dr_object_req.or_object_size = object_size;
4305 	taskq_req->dr_object_req.or_find_pp = find_pp;
4306 	taskq_req->dr_object_req.or_find_p = find_p;
4307 	taskq_req->dr_object_req.or_max_object_count = max_object_count;
4308 	taskq_req->dr_object_req.or_object_count_ptr = object_count_ptr;
4309 
4310 	return (dprov_taskq_dispatch(softc, taskq_req,
4311 	    (task_func_t *)dprov_object_task, KM_NOSLEEP));
4312 }
4313 
4314 /*
4315  * Helper function to submit key management operations to the taskq.
4316  * Returns one of the CRYPTO_ errors.
4317  */
4318 static int
4319 dprov_key_submit_req(dprov_req_type_t req_type,
4320     dprov_state_t *softc, crypto_req_handle_t req,
4321     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4322     crypto_object_attribute_t *template, uint_t attribute_count,
4323     crypto_object_id_t *object_id_ptr,
4324     crypto_object_attribute_t *private_key_template,
4325     uint_t private_key_attribute_count,
4326     crypto_object_id_t *private_key_object_id_ptr, crypto_key_t *key,
4327     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr)
4328 {
4329 	dprov_req_t *taskq_req;
4330 
4331 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4332 	    KM_NOSLEEP)) == NULL)
4333 		return (CRYPTO_HOST_MEMORY);
4334 
4335 	taskq_req->dr_key_req.kr_session_id = session_id;
4336 	taskq_req->dr_key_req.kr_mechanism = mechanism;
4337 	taskq_req->dr_key_req.kr_template = template;
4338 	taskq_req->dr_key_req.kr_attribute_count = attribute_count;
4339 	taskq_req->dr_key_req.kr_object_id_ptr = object_id_ptr;
4340 	taskq_req->dr_key_req.kr_private_key_template = private_key_template;
4341 	taskq_req->dr_key_req.kr_private_key_attribute_count =
4342 	    private_key_attribute_count;
4343 	taskq_req->dr_key_req.kr_private_key_object_id_ptr =
4344 	    private_key_object_id_ptr;
4345 	taskq_req->dr_key_req.kr_key = key;
4346 	taskq_req->dr_key_req.kr_wrapped_key = wrapped_key;
4347 	taskq_req->dr_key_req.kr_wrapped_key_len_ptr = wrapped_key_len_ptr;
4348 
4349 	return (dprov_taskq_dispatch(softc, taskq_req,
4350 	    (task_func_t *)dprov_key_task, KM_NOSLEEP));
4351 }
4352 
4353 /*
4354  * Helper function to submit provider management operations to the taskq.
4355  * Returns one of the CRYPTO_ errors.
4356  */
4357 static int
4358 dprov_mgmt_submit_req(dprov_req_type_t req_type,
4359     dprov_state_t *softc, crypto_req_handle_t req,
4360     crypto_session_id_t session_id, char *pin, size_t pin_len,
4361     char *old_pin, size_t old_pin_len, char *label,
4362     crypto_provider_ext_info_t *ext_info)
4363 {
4364 	dprov_req_t *taskq_req;
4365 
4366 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4367 	    KM_NOSLEEP)) == NULL)
4368 		return (CRYPTO_HOST_MEMORY);
4369 
4370 	taskq_req->dr_mgmt_req.mr_session_id = session_id;
4371 	taskq_req->dr_mgmt_req.mr_pin = pin;
4372 	taskq_req->dr_mgmt_req.mr_pin_len = pin_len;
4373 	taskq_req->dr_mgmt_req.mr_old_pin = old_pin;
4374 	taskq_req->dr_mgmt_req.mr_old_pin_len = old_pin_len;
4375 	taskq_req->dr_mgmt_req.mr_label = label;
4376 	taskq_req->dr_mgmt_req.mr_ext_info = ext_info;
4377 
4378 	return (dprov_taskq_dispatch(softc, taskq_req,
4379 	    (task_func_t *)dprov_mgmt_task, KM_NOSLEEP));
4380 }
4381 
4382 /*
4383  * Helper function for taskq dispatcher routines. Notify the framework
4384  * that the operation corresponding to the specified request is done,
4385  * and pass it the error code. Finally, free the taskq_req.
4386  */
4387 static void
4388 dprov_op_done(dprov_req_t *taskq_req, int error)
4389 {
4390 	/* notify framework that request is completed */
4391 	crypto_op_notification(taskq_req->dr_kcf_req, error);
4392 
4393 	/* free taskq request structure */
4394 	kmem_free(taskq_req, sizeof (dprov_req_t));
4395 }
4396 
4397 /*
4398  * taskq dispatcher function for digest operations.
4399  */
4400 static void
4401 dprov_digest_task(dprov_req_t *taskq_req)
4402 {
4403 	kcf_provider_desc_t *pd;
4404 	dprov_state_t *softc;
4405 	/* LINTED E_FUNC_SET_NOT_USED */
4406 	int instance;
4407 	int error = CRYPTO_NOT_SUPPORTED;
4408 	crypto_ctx_t *ctx = taskq_req->dr_digest_req.dr_ctx;
4409 	crypto_mechanism_t mech;
4410 
4411 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4412 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: started\n", instance));
4413 
4414 	switch (taskq_req->dr_type) {
4415 
4416 	case DPROV_REQ_DIGEST_INIT:
4417 		/* allocate a dprov-private context */
4418 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4419 		    CRYPTO_SUCCESS)
4420 			break;
4421 
4422 		/* structure assignment */
4423 		mech = *taskq_req->dr_digest_req.dr_mechanism;
4424 
4425 		/* get the software provider for this mechanism */
4426 		if ((error = dprov_get_sw_prov(
4427 		    taskq_req->dr_digest_req.dr_mechanism, &pd,
4428 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4429 			break;
4430 
4431 		/* Use a session id of zero since we use a software provider */
4432 		error = crypto_digest_init_prov(pd, 0, &mech,
4433 		    &DPROV_CTX_SINGLE(ctx), NULL);
4434 
4435 		/* release provider reference */
4436 		KCF_PROV_REFRELE(pd);
4437 		break;
4438 
4439 	case DPROV_REQ_DIGEST:
4440 		error = crypto_digest_single(DPROV_CTX_SINGLE(ctx),
4441 		    taskq_req->dr_digest_req.dr_data,
4442 		    taskq_req->dr_digest_req.dr_digest, NULL);
4443 
4444 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4445 			DPROV_CTX_SINGLE(ctx) = NULL;
4446 			(void) dprov_free_context(ctx);
4447 		}
4448 		break;
4449 
4450 	case DPROV_REQ_DIGEST_UPDATE:
4451 		error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
4452 		    taskq_req->dr_digest_req.dr_data, NULL);
4453 		break;
4454 
4455 	case DPROV_REQ_DIGEST_KEY: {
4456 		crypto_data_t data;
4457 		crypto_key_t key;
4458 		size_t len;
4459 
4460 		mutex_enter(&softc->ds_lock);
4461 		error = dprov_key_value_secret(softc, ctx->cc_session,
4462 		    taskq_req->dr_type, taskq_req->dr_digest_req.dr_key, &key);
4463 		mutex_exit(&softc->ds_lock);
4464 		if (error != CRYPTO_SUCCESS)
4465 			break;
4466 
4467 		/* key lengths are specified in bits */
4468 		len = CRYPTO_BITS2BYTES(key.ck_length);
4469 		data.cd_format = CRYPTO_DATA_RAW;
4470 		data.cd_offset = 0;
4471 		data.cd_length = len;
4472 		data.cd_raw.iov_base = key.ck_data;
4473 		data.cd_raw.iov_len = len;
4474 		error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
4475 		    &data, NULL);
4476 		break;
4477 	}
4478 
4479 	case DPROV_REQ_DIGEST_FINAL:
4480 		error = crypto_digest_final(DPROV_CTX_SINGLE(ctx),
4481 		    taskq_req->dr_digest_req.dr_digest, NULL);
4482 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4483 			DPROV_CTX_SINGLE(ctx) = NULL;
4484 			(void) dprov_free_context(ctx);
4485 		}
4486 		break;
4487 
4488 	case DPROV_REQ_DIGEST_ATOMIC:
4489 		/* structure assignment */
4490 		mech = *taskq_req->dr_digest_req.dr_mechanism;
4491 
4492 		/* get the software provider for this mechanism */
4493 		if ((error = dprov_get_sw_prov(
4494 		    taskq_req->dr_digest_req.dr_mechanism, &pd,
4495 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4496 			break;
4497 
4498 		/* use a session id of zero since we use a software provider */
4499 		error = crypto_digest_prov(&mech,
4500 		    taskq_req->dr_digest_req.dr_data,
4501 		    taskq_req->dr_digest_req.dr_digest, NULL, pd, 0);
4502 
4503 		/* release provider reference */
4504 		KCF_PROV_REFRELE(pd);
4505 
4506 		break;
4507 	}
4508 
4509 	dprov_op_done(taskq_req, error);
4510 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: end\n", instance));
4511 }
4512 
4513 /*
4514  * taskq dispatcher function for mac operations.
4515  */
4516 static void
4517 dprov_mac_task(dprov_req_t *taskq_req)
4518 {
4519 	kcf_provider_desc_t *pd;
4520 	dprov_state_t *softc;
4521 	/* LINTED E_FUNC_SET_NOT_USED */
4522 	int instance;
4523 	int error = CRYPTO_NOT_SUPPORTED;
4524 	crypto_ctx_t *ctx = taskq_req->dr_mac_req.dr_ctx;
4525 	crypto_key_t key;
4526 	crypto_mechanism_t mech;
4527 
4528 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4529 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: started\n", instance));
4530 
4531 	switch (taskq_req->dr_type) {
4532 
4533 	case DPROV_REQ_MAC_INIT:
4534 		/* allocate a dprov-private context */
4535 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4536 		    CRYPTO_SUCCESS)
4537 			break;
4538 
4539 		/* get key value */
4540 		mutex_enter(&softc->ds_lock);
4541 		error = dprov_key_value_secret(softc, ctx->cc_session,
4542 		    taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
4543 		mutex_exit(&softc->ds_lock);
4544 		if (error != CRYPTO_SUCCESS)
4545 			break;
4546 
4547 		/* structure assignment */
4548 		mech = *taskq_req->dr_mac_req.dr_mechanism;
4549 
4550 		/* get the software provider for this mechanism */
4551 		if ((error = dprov_get_sw_prov(
4552 		    taskq_req->dr_mac_req.dr_mechanism, &pd,
4553 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4554 			break;
4555 
4556 		/* Use a session id of zero since we use a software provider */
4557 		error = crypto_mac_init_prov(pd, 0, &mech, &key, NULL,
4558 		    &DPROV_CTX_SINGLE(ctx), NULL);
4559 
4560 		/* release provider reference */
4561 		KCF_PROV_REFRELE(pd);
4562 		break;
4563 
4564 	case DPROV_REQ_MAC:
4565 		error = crypto_mac_single(DPROV_CTX_SINGLE(ctx),
4566 		    taskq_req->dr_mac_req.dr_data,
4567 		    taskq_req->dr_mac_req.dr_mac, NULL);
4568 
4569 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4570 			DPROV_CTX_SINGLE(ctx) = NULL;
4571 			(void) dprov_free_context(ctx);
4572 		}
4573 		break;
4574 
4575 	case DPROV_REQ_MAC_UPDATE:
4576 		error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
4577 		    taskq_req->dr_mac_req.dr_data, NULL);
4578 		break;
4579 
4580 	case DPROV_REQ_MAC_FINAL:
4581 		error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
4582 		    taskq_req->dr_mac_req.dr_mac, NULL);
4583 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4584 			DPROV_CTX_SINGLE(ctx) = NULL;
4585 			(void) dprov_free_context(ctx);
4586 		}
4587 		break;
4588 
4589 	case DPROV_REQ_MAC_ATOMIC:
4590 	case DPROV_REQ_MAC_VERIFY_ATOMIC:
4591 		/* get key value */
4592 		mutex_enter(&softc->ds_lock);
4593 		error = dprov_key_value_secret(softc,
4594 		    taskq_req->dr_mac_req.dr_session_id,
4595 		    taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
4596 		mutex_exit(&softc->ds_lock);
4597 		if (error != CRYPTO_SUCCESS)
4598 			break;
4599 
4600 		/* structure assignment */
4601 		mech = *taskq_req->dr_mac_req.dr_mechanism;
4602 
4603 		/* get the software provider for this mechanism */
4604 		if ((error = dprov_get_sw_prov(
4605 		    taskq_req->dr_mac_req.dr_mechanism, &pd,
4606 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4607 			break;
4608 
4609 		/* use a session id of zero since we use a software provider */
4610 		if (taskq_req->dr_type == DPROV_REQ_MAC_ATOMIC)
4611 			error = crypto_mac_prov(&mech,
4612 			    taskq_req->dr_mac_req.dr_data,
4613 			    &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL,
4614 			    pd, 0);
4615 		else
4616 			error = crypto_mac_verify_prov(&mech,
4617 			    taskq_req->dr_mac_req.dr_data,
4618 			    &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL,
4619 			    pd, 0);
4620 
4621 		/* release provider reference */
4622 		KCF_PROV_REFRELE(pd);
4623 
4624 		break;
4625 	}
4626 
4627 	dprov_op_done(taskq_req, error);
4628 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
4629 }
4630 
4631 /*
4632  * taskq dispatcher function for sign operations.
4633  */
4634 static void
4635 dprov_sign_task(dprov_req_t *taskq_req)
4636 {
4637 	kcf_provider_desc_t *pd;
4638 	dprov_state_t *softc;
4639 	/* LINTED E_FUNC_SET_NOT_USED */
4640 	int instance;
4641 	int error = CRYPTO_NOT_SUPPORTED;
4642 	crypto_ctx_t *ctx = taskq_req->dr_mac_req.dr_ctx;
4643 	crypto_key_t key, *keyp;
4644 	crypto_mechanism_t mech;
4645 
4646 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4647 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: started\n", instance));
4648 
4649 	switch (taskq_req->dr_type) {
4650 
4651 	case DPROV_REQ_SIGN_INIT:
4652 	case DPROV_REQ_SIGN_RECOVER_INIT:
4653 		/* allocate a dprov-private context */
4654 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4655 		    CRYPTO_SUCCESS)
4656 			break;
4657 
4658 		/* structure assignment */
4659 		mech = *taskq_req->dr_sign_req.sr_mechanism;
4660 
4661 		mutex_enter(&softc->ds_lock);
4662 		/* get key value for secret key algorithms */
4663 		if (is_publickey_mech(mech.cm_type)) {
4664 			if ((error = dprov_key_attr_asymmetric(softc,
4665 			    ctx->cc_session, taskq_req->dr_type,
4666 			    taskq_req->dr_sign_req.sr_key, &key))
4667 			    != CRYPTO_SUCCESS) {
4668 				mutex_exit(&softc->ds_lock);
4669 				break;
4670 			}
4671 			keyp = &key;
4672 		} else {
4673 			if ((error = dprov_key_value_secret(softc,
4674 			    ctx->cc_session, taskq_req->dr_type,
4675 			    taskq_req->dr_sign_req.sr_key, &key))
4676 			    != CRYPTO_SUCCESS) {
4677 				mutex_exit(&softc->ds_lock);
4678 				break;
4679 			}
4680 			keyp = &key;
4681 		}
4682 		mutex_exit(&softc->ds_lock);
4683 
4684 		/* get the software provider for this mechanism */
4685 		if ((error = dprov_get_sw_prov(
4686 		    taskq_req->dr_sign_req.sr_mechanism, &pd,
4687 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4688 			break;
4689 
4690 		/* Use a session id of zero since we use a software provider */
4691 		if (taskq_req->dr_type == DPROV_REQ_SIGN_INIT)
4692 			error = crypto_sign_init_prov(pd, 0, &mech, keyp,
4693 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
4694 		else
4695 			error = crypto_sign_recover_init_prov(pd, 0, &mech,
4696 			    keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
4697 
4698 		/* release provider reference */
4699 		KCF_PROV_REFRELE(pd);
4700 
4701 		break;
4702 
4703 	case DPROV_REQ_SIGN:
4704 		error = crypto_sign_single(DPROV_CTX_SINGLE(ctx),
4705 		    taskq_req->dr_sign_req.sr_data,
4706 		    taskq_req->dr_sign_req.sr_signature, NULL);
4707 
4708 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4709 			DPROV_CTX_SINGLE(ctx) = NULL;
4710 			(void) dprov_free_context(ctx);
4711 		}
4712 		break;
4713 
4714 	case DPROV_REQ_SIGN_UPDATE:
4715 		error = crypto_sign_update(DPROV_CTX_SINGLE(ctx),
4716 		    taskq_req->dr_sign_req.sr_data, NULL);
4717 		break;
4718 
4719 	case DPROV_REQ_SIGN_FINAL:
4720 		error = crypto_sign_final(DPROV_CTX_SINGLE(ctx),
4721 		    taskq_req->dr_sign_req.sr_signature, NULL);
4722 
4723 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4724 			DPROV_CTX_SINGLE(ctx) = NULL;
4725 			(void) dprov_free_context(ctx);
4726 		}
4727 		break;
4728 
4729 	case DPROV_REQ_SIGN_ATOMIC:
4730 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
4731 		/* structure assignment */
4732 		mech = *taskq_req->dr_sign_req.sr_mechanism;
4733 
4734 		mutex_enter(&softc->ds_lock);
4735 		/* get key value for secret key algorithms */
4736 		if (is_publickey_mech(mech.cm_type)) {
4737 			if ((error = dprov_key_attr_asymmetric(softc,
4738 			    taskq_req->dr_sign_req.sr_session_id,
4739 			    taskq_req->dr_type,
4740 			    taskq_req->dr_sign_req.sr_key, &key))
4741 			    != CRYPTO_SUCCESS) {
4742 				mutex_exit(&softc->ds_lock);
4743 				break;
4744 			}
4745 			keyp = &key;
4746 		} else {
4747 			if ((error = dprov_key_value_secret(softc,
4748 			    taskq_req->dr_sign_req.sr_session_id,
4749 			    taskq_req->dr_type,
4750 			    taskq_req->dr_sign_req.sr_key, &key))
4751 			    != CRYPTO_SUCCESS) {
4752 				mutex_exit(&softc->ds_lock);
4753 				break;
4754 			}
4755 			keyp = &key;
4756 		}
4757 		mutex_exit(&softc->ds_lock);
4758 
4759 		/* get the software provider for this mechanism */
4760 		if ((error = dprov_get_sw_prov(
4761 		    taskq_req->dr_sign_req.sr_mechanism, &pd,
4762 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4763 			break;
4764 
4765 		/* Use a session id of zero since we use a software provider */
4766 		if (taskq_req->dr_type == DPROV_REQ_SIGN_ATOMIC)
4767 			error = crypto_sign_prov(pd, 0, &mech, keyp,
4768 			    taskq_req->dr_sign_req.sr_data,
4769 			    NULL, taskq_req->dr_sign_req.sr_signature, NULL);
4770 		else
4771 			error = crypto_sign_recover_prov(pd, 0, &mech, keyp,
4772 			    taskq_req->dr_sign_req.sr_data,
4773 			    NULL, taskq_req->dr_sign_req.sr_signature, NULL);
4774 
4775 		/* release provider reference */
4776 		KCF_PROV_REFRELE(pd);
4777 		break;
4778 
4779 	case DPROV_REQ_SIGN_RECOVER:
4780 		error = crypto_sign_recover_single(DPROV_CTX_SINGLE(ctx),
4781 		    taskq_req->dr_sign_req.sr_data,
4782 		    taskq_req->dr_sign_req.sr_signature, NULL);
4783 
4784 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4785 			DPROV_CTX_SINGLE(ctx) = NULL;
4786 			(void) dprov_free_context(ctx);
4787 		}
4788 		break;
4789 	}
4790 
4791 	dprov_op_done(taskq_req, error);
4792 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: end\n", instance));
4793 }
4794 
4795 /*
4796  * taskq dispatcher function for verify operations.
4797  */
4798 static void
4799 dprov_verify_task(dprov_req_t *taskq_req)
4800 {
4801 	kcf_provider_desc_t *pd;
4802 	dprov_state_t *softc;
4803 	/* LINTED E_FUNC_SET_NOT_USED */
4804 	int instance;
4805 	int error = CRYPTO_NOT_SUPPORTED;
4806 	crypto_ctx_t *ctx = taskq_req->dr_verify_req.vr_ctx;
4807 	crypto_key_t key, *keyp;
4808 	crypto_mechanism_t mech;
4809 
4810 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4811 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: started\n", instance));
4812 
4813 	switch (taskq_req->dr_type) {
4814 
4815 	case DPROV_REQ_VERIFY_INIT:
4816 	case DPROV_REQ_VERIFY_RECOVER_INIT:
4817 		/* allocate a dprov-private context */
4818 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4819 		    CRYPTO_SUCCESS)
4820 			break;
4821 
4822 		/* structure assignment */
4823 		mech = *taskq_req->dr_verify_req.vr_mechanism;
4824 
4825 		mutex_enter(&softc->ds_lock);
4826 		/* get key value for secret key algorithms */
4827 		if (is_publickey_mech(mech.cm_type)) {
4828 			if ((error = dprov_key_attr_asymmetric(softc,
4829 			    ctx->cc_session, taskq_req->dr_type,
4830 			    taskq_req->dr_verify_req.vr_key, &key))
4831 			    != CRYPTO_SUCCESS) {
4832 				mutex_exit(&softc->ds_lock);
4833 				break;
4834 			}
4835 			keyp = &key;
4836 		} else {
4837 			if ((error = dprov_key_value_secret(softc,
4838 			    ctx->cc_session, taskq_req->dr_type,
4839 			    taskq_req->dr_verify_req.vr_key, &key))
4840 			    != CRYPTO_SUCCESS) {
4841 				mutex_exit(&softc->ds_lock);
4842 				break;
4843 			}
4844 			keyp = &key;
4845 		}
4846 		mutex_exit(&softc->ds_lock);
4847 
4848 		/* get the software provider for this mechanism */
4849 		if ((error = dprov_get_sw_prov(
4850 		    taskq_req->dr_verify_req.vr_mechanism, &pd,
4851 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4852 			break;
4853 
4854 		/* Use a session id of zero since we use a software provider */
4855 		if (taskq_req->dr_type == DPROV_REQ_VERIFY_INIT)
4856 			error = crypto_verify_init_prov(pd, 0, &mech, keyp,
4857 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
4858 		else
4859 			error = crypto_verify_recover_init_prov(pd, 0, &mech,
4860 			    keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
4861 
4862 		/* release provider reference */
4863 		KCF_PROV_REFRELE(pd);
4864 
4865 		break;
4866 
4867 	case DPROV_REQ_VERIFY:
4868 		error = crypto_verify_single(DPROV_CTX_SINGLE(ctx),
4869 		    taskq_req->dr_verify_req.vr_data,
4870 		    taskq_req->dr_verify_req.vr_signature, NULL);
4871 
4872 		ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
4873 		DPROV_CTX_SINGLE(ctx) = NULL;
4874 		(void) dprov_free_context(ctx);
4875 		break;
4876 
4877 	case DPROV_REQ_VERIFY_UPDATE:
4878 		error = crypto_verify_update(DPROV_CTX_SINGLE(ctx),
4879 		    taskq_req->dr_verify_req.vr_data, NULL);
4880 		break;
4881 
4882 	case DPROV_REQ_VERIFY_FINAL:
4883 		error = crypto_verify_final(DPROV_CTX_SINGLE(ctx),
4884 		    taskq_req->dr_verify_req.vr_signature, NULL);
4885 
4886 		ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
4887 		DPROV_CTX_SINGLE(ctx) = NULL;
4888 		(void) dprov_free_context(ctx);
4889 		break;
4890 
4891 	case DPROV_REQ_VERIFY_ATOMIC:
4892 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
4893 		/* structure assignment */
4894 		mech = *taskq_req->dr_verify_req.vr_mechanism;
4895 
4896 		mutex_enter(&softc->ds_lock);
4897 		/* get key value for secret key algorithms */
4898 		if (is_publickey_mech(mech.cm_type)) {
4899 			if ((error = dprov_key_attr_asymmetric(softc,
4900 			    taskq_req->dr_verify_req.vr_session_id,
4901 			    taskq_req->dr_type,
4902 			    taskq_req->dr_verify_req.vr_key, &key))
4903 			    != CRYPTO_SUCCESS) {
4904 				mutex_exit(&softc->ds_lock);
4905 				break;
4906 			}
4907 			keyp = &key;
4908 		} else {
4909 			if ((error = dprov_key_value_secret(softc,
4910 			    taskq_req->dr_verify_req.vr_session_id,
4911 			    taskq_req->dr_type,
4912 			    taskq_req->dr_verify_req.vr_key, &key))
4913 			    != CRYPTO_SUCCESS) {
4914 				mutex_exit(&softc->ds_lock);
4915 				break;
4916 			}
4917 			keyp = &key;
4918 		}
4919 		mutex_exit(&softc->ds_lock);
4920 
4921 		/* get the software provider for this mechanism */
4922 		if ((error = dprov_get_sw_prov(
4923 		    taskq_req->dr_verify_req.vr_mechanism, &pd,
4924 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4925 			break;
4926 
4927 		/* Use a session id of zero since we use a software provider */
4928 		if (taskq_req->dr_type == DPROV_REQ_VERIFY_ATOMIC)
4929 			error = crypto_verify_prov(pd, 0, &mech, keyp,
4930 			    taskq_req->dr_verify_req.vr_data,
4931 			    NULL, taskq_req->dr_verify_req.vr_signature, NULL);
4932 		else
4933 			/*
4934 			 * crypto_verify_recover_prov() has different argument
4935 			 * order than crypto_verify_prov().
4936 			 */
4937 			error = crypto_verify_recover_prov(pd, 0, &mech, keyp,
4938 			    taskq_req->dr_verify_req.vr_signature,
4939 			    NULL, taskq_req->dr_verify_req.vr_data, NULL);
4940 
4941 		/* release provider reference */
4942 		KCF_PROV_REFRELE(pd);
4943 		break;
4944 
4945 	case DPROV_REQ_VERIFY_RECOVER:
4946 		/*
4947 		 * crypto_verify_recover_single() has different argument
4948 		 * order than crypto_verify_single().
4949 		 */
4950 		error = crypto_verify_recover_single(DPROV_CTX_SINGLE(ctx),
4951 		    taskq_req->dr_verify_req.vr_signature,
4952 		    taskq_req->dr_verify_req.vr_data, NULL);
4953 
4954 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4955 			DPROV_CTX_SINGLE(ctx) = NULL;
4956 			(void) dprov_free_context(ctx);
4957 		}
4958 		break;
4959 	}
4960 
4961 	dprov_op_done(taskq_req, error);
4962 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: end\n", instance));
4963 }
4964 
4965 /*
4966  * taskq dispatcher function for dual operations.
4967  */
4968 static void
4969 dprov_dual_task(dprov_req_t *taskq_req)
4970 {
4971 	dprov_state_t *softc;
4972 	/* LINTED E_FUNC_SET_NOT_USED */
4973 	int instance;
4974 	int error = CRYPTO_NOT_SUPPORTED;
4975 	crypto_ctx_t *signverify_ctx = taskq_req->dr_dual_req.dr_signverify_ctx;
4976 	crypto_ctx_t *cipher_ctx = taskq_req->dr_dual_req.dr_cipher_ctx;
4977 
4978 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4979 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: started\n", instance));
4980 
4981 	switch (taskq_req->dr_type) {
4982 
4983 	case DPROV_REQ_DIGEST_ENCRYPT_UPDATE:
4984 		error = crypto_digest_encrypt_update(
4985 		    DPROV_CTX_SINGLE(signverify_ctx),
4986 		    DPROV_CTX_SINGLE(cipher_ctx),
4987 		    taskq_req->dr_dual_req.dr_plaintext,
4988 		    taskq_req->dr_dual_req.dr_ciphertext, NULL);
4989 		break;
4990 
4991 	case DPROV_REQ_DECRYPT_DIGEST_UPDATE:
4992 		error = crypto_decrypt_digest_update(
4993 		    DPROV_CTX_SINGLE(cipher_ctx),
4994 		    DPROV_CTX_SINGLE(signverify_ctx),
4995 		    taskq_req->dr_dual_req.dr_ciphertext,
4996 		    taskq_req->dr_dual_req.dr_plaintext, NULL);
4997 		break;
4998 
4999 	case DPROV_REQ_SIGN_ENCRYPT_UPDATE:
5000 		error = crypto_sign_encrypt_update(
5001 		    DPROV_CTX_SINGLE(signverify_ctx),
5002 		    DPROV_CTX_SINGLE(cipher_ctx),
5003 		    taskq_req->dr_dual_req.dr_plaintext,
5004 		    taskq_req->dr_dual_req.dr_ciphertext, NULL);
5005 		break;
5006 
5007 	case DPROV_REQ_DECRYPT_VERIFY_UPDATE:
5008 		error = crypto_decrypt_verify_update(
5009 		    DPROV_CTX_SINGLE(cipher_ctx),
5010 		    DPROV_CTX_SINGLE(signverify_ctx),
5011 		    taskq_req->dr_dual_req.dr_ciphertext,
5012 		    taskq_req->dr_dual_req.dr_plaintext, NULL);
5013 		break;
5014 	}
5015 
5016 	dprov_op_done(taskq_req, error);
5017 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: end\n", instance));
5018 }
5019 
5020 /*
5021  * taskq dispatcher function for cipher operations.
5022  */
5023 static void
5024 dprov_cipher_task(dprov_req_t *taskq_req)
5025 {
5026 	kcf_provider_desc_t *pd;
5027 	dprov_state_t *softc;
5028 	/* LINTED E_FUNC_SET_NOT_USED */
5029 	int instance;
5030 	int error = CRYPTO_NOT_SUPPORTED;
5031 	crypto_ctx_t *ctx = taskq_req->dr_cipher_req.dr_ctx;
5032 	crypto_key_t key, *keyp;
5033 	crypto_mechanism_t mech;
5034 
5035 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5036 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_cipher_task: started\n", instance));
5037 
5038 	switch (taskq_req->dr_type) {
5039 
5040 	case DPROV_REQ_ENCRYPT_INIT:
5041 	case DPROV_REQ_DECRYPT_INIT:
5042 		/* allocate a dprov-private context */
5043 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5044 		    CRYPTO_SUCCESS)
5045 			break;
5046 
5047 		/* structure assignment */
5048 		mech = *taskq_req->dr_cipher_req.dr_mechanism;
5049 
5050 		mutex_enter(&softc->ds_lock);
5051 		/* get key value for secret key algorithms */
5052 		if (is_publickey_mech(mech.cm_type)) {
5053 			if ((error = dprov_key_attr_asymmetric(softc,
5054 			    ctx->cc_session, taskq_req->dr_type,
5055 			    taskq_req->dr_cipher_req.dr_key, &key))
5056 			    != CRYPTO_SUCCESS) {
5057 				mutex_exit(&softc->ds_lock);
5058 				break;
5059 			}
5060 			keyp = &key;
5061 		} else {
5062 			if ((error = dprov_key_value_secret(softc,
5063 			    ctx->cc_session, taskq_req->dr_type,
5064 			    taskq_req->dr_cipher_req.dr_key, &key))
5065 			    != CRYPTO_SUCCESS) {
5066 				mutex_exit(&softc->ds_lock);
5067 				break;
5068 			}
5069 			keyp = &key;
5070 		}
5071 		mutex_exit(&softc->ds_lock);
5072 
5073 		/* get the software provider for this mechanism */
5074 		if ((error = dprov_get_sw_prov(
5075 		    taskq_req->dr_cipher_req.dr_mechanism, &pd,
5076 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5077 			break;
5078 
5079 		/* Use a session id of zero since we use a software provider */
5080 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_INIT)
5081 			error = crypto_encrypt_init_prov(pd, 0, &mech, keyp,
5082 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5083 		else
5084 			error = crypto_decrypt_init_prov(pd, 0, &mech, keyp,
5085 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5086 
5087 		/* release provider reference */
5088 		KCF_PROV_REFRELE(pd);
5089 		break;
5090 
5091 	case DPROV_REQ_ENCRYPT:
5092 		error = crypto_encrypt_single(DPROV_CTX_SINGLE(ctx),
5093 		    taskq_req->dr_cipher_req.dr_plaintext,
5094 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5095 
5096 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5097 			DPROV_CTX_SINGLE(ctx) = NULL;
5098 			(void) dprov_free_context(ctx);
5099 		}
5100 		break;
5101 
5102 	case DPROV_REQ_DECRYPT:
5103 		error = crypto_decrypt_single(DPROV_CTX_SINGLE(ctx),
5104 		    taskq_req->dr_cipher_req.dr_ciphertext,
5105 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5106 
5107 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5108 			DPROV_CTX_SINGLE(ctx) = NULL;
5109 			(void) dprov_free_context(ctx);
5110 		}
5111 		break;
5112 
5113 	case DPROV_REQ_ENCRYPT_UPDATE:
5114 		error = crypto_encrypt_update(DPROV_CTX_SINGLE(ctx),
5115 		    taskq_req->dr_cipher_req.dr_plaintext,
5116 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5117 		break;
5118 
5119 	case DPROV_REQ_DECRYPT_UPDATE:
5120 		error = crypto_decrypt_update(DPROV_CTX_SINGLE(ctx),
5121 		    taskq_req->dr_cipher_req.dr_ciphertext,
5122 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5123 		break;
5124 
5125 	case DPROV_REQ_ENCRYPT_FINAL:
5126 		error = crypto_encrypt_final(DPROV_CTX_SINGLE(ctx),
5127 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5128 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5129 			DPROV_CTX_SINGLE(ctx) = NULL;
5130 			(void) dprov_free_context(ctx);
5131 		}
5132 		break;
5133 
5134 	case DPROV_REQ_DECRYPT_FINAL:
5135 		error = crypto_decrypt_final(DPROV_CTX_SINGLE(ctx),
5136 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5137 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5138 			DPROV_CTX_SINGLE(ctx) = NULL;
5139 			(void) dprov_free_context(ctx);
5140 		}
5141 		break;
5142 
5143 	case DPROV_REQ_ENCRYPT_ATOMIC:
5144 	case DPROV_REQ_DECRYPT_ATOMIC:
5145 		/* structure assignment */
5146 		mech = *taskq_req->dr_cipher_req.dr_mechanism;
5147 
5148 		mutex_enter(&softc->ds_lock);
5149 		/* get key value for secret key algorithms */
5150 		if (is_publickey_mech(mech.cm_type)) {
5151 			if ((error = dprov_key_attr_asymmetric(softc,
5152 			    taskq_req->dr_cipher_req.dr_session_id,
5153 			    taskq_req->dr_type,
5154 			    taskq_req->dr_cipher_req.dr_key,
5155 			    &key)) != CRYPTO_SUCCESS) {
5156 				mutex_exit(&softc->ds_lock);
5157 				break;
5158 			}
5159 			keyp = &key;
5160 		} else {
5161 			if ((error = dprov_key_value_secret(softc,
5162 			    taskq_req->dr_cipher_req.dr_session_id,
5163 			    taskq_req->dr_type, taskq_req->dr_cipher_req.dr_key,
5164 			    &key))
5165 			    != CRYPTO_SUCCESS) {
5166 				mutex_exit(&softc->ds_lock);
5167 				break;
5168 			}
5169 			keyp = &key;
5170 		}
5171 		mutex_exit(&softc->ds_lock);
5172 
5173 		/* get the software provider for this mechanism */
5174 		if ((error = dprov_get_sw_prov(
5175 		    taskq_req->dr_cipher_req.dr_mechanism, &pd,
5176 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5177 			break;
5178 
5179 		/* use a session id of zero since we use a software provider */
5180 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_ATOMIC)
5181 			error = crypto_encrypt_prov(&mech,
5182 			    taskq_req->dr_cipher_req.dr_plaintext,
5183 			    keyp, NULL,
5184 			    taskq_req->dr_cipher_req.dr_ciphertext, NULL, pd,
5185 			    0);
5186 		else
5187 			error = crypto_decrypt_prov(&mech,
5188 			    taskq_req->dr_cipher_req.dr_ciphertext,
5189 			    keyp, NULL,
5190 			    taskq_req->dr_cipher_req.dr_plaintext, NULL, pd, 0);
5191 
5192 		/* release provider reference */
5193 		KCF_PROV_REFRELE(pd);
5194 
5195 		break;
5196 	}
5197 
5198 	dprov_op_done(taskq_req, error);
5199 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
5200 }
5201 
5202 /*
5203  * Helper function for the cipher/mac dual operation taskq dispatch
5204  * function. Initialize the cipher and mac key values and find the
5205  * providers that can process the request for the specified mechanisms.
5206  */
5207 static int
5208 dprov_cipher_mac_key_pd(dprov_state_t *softc, crypto_session_id_t sid,
5209     dprov_req_t *taskq_req, crypto_key_t *cipher_key, crypto_key_t *mac_key,
5210     kcf_provider_desc_t **cipher_pd, kcf_provider_desc_t **mac_pd,
5211     crypto_mech_type_t *cipher_mech_type, crypto_mech_type_t *mac_mech_type)
5212 {
5213 	int error;
5214 
5215 	/* get the cipher key value */
5216 	mutex_enter(&softc->ds_lock);
5217 	error = dprov_key_value_secret(softc, sid, taskq_req->dr_type,
5218 	    taskq_req->dr_cipher_mac_req.mr_cipher_key, cipher_key);
5219 	if (error != CRYPTO_SUCCESS) {
5220 		mutex_exit(&softc->ds_lock);
5221 		return (error);
5222 	}
5223 
5224 	/* get the mac key value */
5225 	error = dprov_key_value_secret(softc, sid, taskq_req->dr_type,
5226 	    taskq_req->dr_cipher_mac_req.mr_mac_key, mac_key);
5227 	mutex_exit(&softc->ds_lock);
5228 	if (error != CRYPTO_SUCCESS)
5229 		return (error);
5230 
5231 	/* get the SW provider to perform the cipher operation */
5232 	if ((error = dprov_get_sw_prov(
5233 	    taskq_req->dr_cipher_mac_req.mr_cipher_mech, cipher_pd,
5234 	    cipher_mech_type)) != CRYPTO_SUCCESS)
5235 		return (error);
5236 
5237 	/* get the SW provider to perform the mac operation */
5238 	error = dprov_get_sw_prov(taskq_req->dr_cipher_mac_req.mr_mac_mech,
5239 	    mac_pd, mac_mech_type);
5240 
5241 	return (error);
5242 }
5243 
5244 /*
5245  * taskq dispatcher function for cipher/mac dual operations.
5246  */
5247 static void
5248 dprov_cipher_mac_task(dprov_req_t *taskq_req)
5249 {
5250 	dprov_state_t *softc;
5251 	/* LINTED E_FUNC_SET_NOT_USED */
5252 	int instance;
5253 	int error = CRYPTO_NOT_SUPPORTED;
5254 	crypto_ctx_t *ctx = taskq_req->dr_cipher_mac_req.mr_ctx;
5255 	kcf_provider_desc_t *cipher_pd;
5256 	kcf_provider_desc_t *mac_pd;
5257 	crypto_key_t cipher_key;
5258 	crypto_key_t mac_key;
5259 	crypto_dual_data_t *dual_data =
5260 	    taskq_req->dr_cipher_mac_req.mr_dual_data;
5261 	crypto_data_t cipher_data;
5262 	crypto_data_t mac_data;
5263 	crypto_mechanism_t cipher_mech, mac_mech;
5264 	crypto_session_id_t session_id;
5265 
5266 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5267 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: started\n",
5268 	    instance));
5269 
5270 	switch (taskq_req->dr_type) {
5271 	case DPROV_REQ_ENCRYPT_MAC_INIT:
5272 	case DPROV_REQ_MAC_DECRYPT_INIT:
5273 		/* structure assignment */
5274 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5275 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5276 
5277 		/* get the keys values and providers to use for operations */
5278 		if ((error = dprov_cipher_mac_key_pd(softc, ctx->cc_session,
5279 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5280 		    &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
5281 			break;
5282 
5283 		/* allocate a dprov-private context */
5284 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5285 		    CRYPTO_SUCCESS)
5286 			break;
5287 
5288 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_MAC_INIT)
5289 			/* do the encryption initialization */
5290 			error = crypto_encrypt_init_prov(cipher_pd, 0,
5291 			    &cipher_mech, &cipher_key, NULL,
5292 			    &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
5293 		else
5294 			/* do the decryption initialization */
5295 			error = crypto_decrypt_init_prov(cipher_pd, 0,
5296 			    &cipher_mech, &cipher_key, NULL,
5297 			    &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
5298 		if (error != CRYPTO_SUCCESS)
5299 			break;
5300 
5301 		/* do the mac initialization */
5302 		if ((error = crypto_mac_init_prov(mac_pd, 0,
5303 		    &mac_mech, &mac_key, NULL, &DPROV_CTX_DUAL_MAC(ctx),
5304 		    NULL)) != CRYPTO_SUCCESS)
5305 			break;
5306 
5307 		/* release references to providers */
5308 		KCF_PROV_REFRELE(cipher_pd);
5309 		KCF_PROV_REFRELE(mac_pd);
5310 
5311 		break;
5312 
5313 	case DPROV_REQ_ENCRYPT_MAC: {
5314 		size_t encrypted;
5315 		boolean_t inplace;
5316 
5317 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5318 
5319 		cipher_data = *((crypto_data_t *)dual_data);
5320 
5321 		/* do an encrypt update */
5322 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5323 		if (inplace) {
5324 			plaintext_tmp = &cipher_data;
5325 			ciphertext_tmp = NULL;
5326 		} else {
5327 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5328 			ciphertext_tmp = &cipher_data;
5329 		}
5330 		if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5331 		    plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
5332 			break;
5333 
5334 		/* do an encrypt final */
5335 		encrypted = cipher_data.cd_length;
5336 
5337 		cipher_data.cd_offset += encrypted;
5338 		cipher_data.cd_length = dual_data->dd_len1 - encrypted;
5339 
5340 		if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5341 		    &cipher_data, NULL)) != CRYPTO_SUCCESS)
5342 			break;
5343 
5344 		/*
5345 		 * Do a mac update on the resulting ciphertext, but with no
5346 		 * more bytes than specified by dual_data, and starting at
5347 		 * offset specified by dual_data. For in-place operations,
5348 		 * we use the length specified by the dual_data.
5349 		 */
5350 		mac_data = cipher_data;
5351 		mac_data.cd_offset = dual_data->dd_offset2;
5352 		mac_data.cd_length = dual_data->dd_len2;
5353 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5354 		    &mac_data, NULL)) != CRYPTO_SUCCESS)
5355 			break;
5356 
5357 		/* do a mac final */
5358 		error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5359 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5360 
5361 		/* Set the total size of the ciphertext, when successful */
5362 		if (error == CRYPTO_SUCCESS)
5363 			dual_data->dd_len1 = encrypted + cipher_data.cd_length;
5364 
5365 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5366 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5367 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5368 			(void) dprov_free_context(ctx);
5369 		}
5370 		break;
5371 	}
5372 
5373 	case DPROV_REQ_ENCRYPT_MAC_UPDATE: {
5374 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5375 		size_t encrypted;
5376 		ssize_t maclen;
5377 		boolean_t inplace;
5378 
5379 		cipher_data = *((crypto_data_t *)dual_data);
5380 
5381 		/* do an encrypt update */
5382 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5383 		if (inplace) {
5384 			plaintext_tmp = &cipher_data;
5385 			ciphertext_tmp = NULL;
5386 		} else {
5387 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5388 			ciphertext_tmp = &cipher_data;
5389 		}
5390 		if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5391 		    plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
5392 			break;
5393 
5394 		encrypted = cipher_data.cd_length;
5395 
5396 		/*
5397 		 * Do a mac update on the resulting ciphertext, but with no
5398 		 * more bytes than specified by dual_data, and starting at
5399 		 * offset specified by dual_data. For in-place operations,
5400 		 * we use the length specified by the dual_data.
5401 		 * There is an edge case, when the encryption step produced
5402 		 * zero bytes in the ciphertext. Only the portion between
5403 		 * offset2 and offset1 is then thrown in the MAC mix.
5404 		 */
5405 		maclen = dual_data->dd_offset1 - dual_data->dd_offset2 +
5406 		    encrypted;
5407 		if (maclen > 0) {
5408 			mac_data = cipher_data;
5409 			mac_data.cd_offset = dual_data->dd_offset2;
5410 			mac_data.cd_length = min(dual_data->dd_len2, maclen);
5411 			if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5412 			    &mac_data, NULL)) != CRYPTO_SUCCESS)
5413 				break;
5414 		}
5415 		/* Set the total size of the ciphertext, when successful */
5416 		if (error == CRYPTO_SUCCESS)
5417 			dual_data->dd_len1 = encrypted;
5418 
5419 		break;
5420 	}
5421 
5422 	case DPROV_REQ_ENCRYPT_MAC_FINAL:
5423 		cipher_data = *((crypto_data_t *)dual_data);
5424 
5425 		/* do an encrypt final */
5426 		if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5427 		    taskq_req->dr_cipher_mac_req.mr_data == NULL ?
5428 		    &cipher_data : taskq_req->dr_cipher_mac_req.mr_data,
5429 		    NULL)) != CRYPTO_SUCCESS)
5430 			break;
5431 
5432 		/*
5433 		 * If ciphertext length is different from zero, do a mac
5434 		 * update on it. This does not apply to in-place since we
5435 		 * do not allow partial updates, hence no final residual.
5436 		 */
5437 		if (taskq_req->dr_cipher_mac_req.mr_data != NULL &&
5438 		    taskq_req->dr_cipher_mac_req.mr_data->cd_length > 0)
5439 			if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5440 			    taskq_req->dr_cipher_mac_req.mr_data, NULL)) !=
5441 			    CRYPTO_SUCCESS)
5442 				break;
5443 
5444 		/* do a mac final */
5445 		error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5446 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5447 
5448 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5449 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5450 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5451 			(void) dprov_free_context(ctx);
5452 		}
5453 		break;
5454 
5455 	case DPROV_REQ_ENCRYPT_MAC_ATOMIC: {
5456 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5457 		boolean_t inplace;
5458 
5459 		cipher_data = *((crypto_data_t *)dual_data);
5460 
5461 		/* do an encrypt atomic */
5462 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5463 		if (inplace) {
5464 			plaintext_tmp = &cipher_data;
5465 			ciphertext_tmp = NULL;
5466 		} else {
5467 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5468 			ciphertext_tmp = &cipher_data;
5469 		}
5470 
5471 		/* structure assignment */
5472 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5473 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5474 		session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
5475 
5476 		/* get the keys values and providers to use for operations */
5477 		if ((error = dprov_cipher_mac_key_pd(softc, session_id,
5478 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5479 		    &cipher_mech.cm_type, &mac_mech.cm_type)) !=
5480 		    CRYPTO_SUCCESS)
5481 			break;
5482 
5483 		/* do the atomic encrypt */
5484 		if ((error = crypto_encrypt_prov(
5485 		    &cipher_mech, plaintext_tmp, &cipher_key, NULL,
5486 		    ciphertext_tmp, NULL, cipher_pd, 0)) != CRYPTO_SUCCESS)
5487 			break;
5488 
5489 		/* do the atomic mac */
5490 		mac_data = cipher_data;
5491 		mac_data.cd_length = dual_data->dd_len2;
5492 		mac_data.cd_offset = dual_data->dd_offset2;
5493 		error = crypto_mac_prov(&mac_mech, &mac_data, &mac_key, NULL,
5494 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL, mac_pd, 0);
5495 
5496 		dual_data->dd_len1 = cipher_data.cd_length;
5497 
5498 		break;
5499 	}
5500 
5501 	case DPROV_REQ_MAC_DECRYPT: {
5502 		uint_t decrypted;
5503 		crypto_data_t plaintext_tmp;
5504 
5505 		cipher_data = *((crypto_data_t *)dual_data);
5506 
5507 		/* do a mac update and final on the ciphertext */
5508 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5509 		    &mac_data, NULL)) != CRYPTO_SUCCESS)
5510 			break;
5511 
5512 		/* do a mac final */
5513 		if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5514 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
5515 		    CRYPTO_SUCCESS)
5516 			break;
5517 
5518 		/* do an decrypt update */
5519 		cipher_data = mac_data;
5520 		cipher_data.cd_length = dual_data->dd_len2;
5521 		cipher_data.cd_offset = dual_data->dd_offset2;
5522 		if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
5523 			/* in-place */
5524 			plaintext_tmp = cipher_data;
5525 		else
5526 			plaintext_tmp = *taskq_req->dr_cipher_mac_req.mr_data;
5527 
5528 		if ((error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5529 		    &cipher_data, taskq_req->dr_cipher_mac_req.mr_data,
5530 		    NULL)) != CRYPTO_SUCCESS)
5531 			break;
5532 
5533 		/* do an decrypt final */
5534 		if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
5535 			/* in-place, everything must have been decrypted */
5536 			decrypted = cipher_data.cd_length;
5537 		else
5538 			decrypted =
5539 			    taskq_req->dr_cipher_mac_req.mr_data->cd_length;
5540 		plaintext_tmp.cd_offset += decrypted;
5541 		plaintext_tmp.cd_length -= decrypted;
5542 
5543 		error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5544 		    &plaintext_tmp, NULL);
5545 		if (taskq_req->dr_cipher_mac_req.mr_data != NULL)
5546 			taskq_req->dr_cipher_mac_req.mr_data->cd_length +=
5547 			    plaintext_tmp.cd_length;
5548 
5549 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5550 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5551 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5552 			(void) dprov_free_context(ctx);
5553 		}
5554 		break;
5555 	}
5556 
5557 	case DPROV_REQ_MAC_DECRYPT_UPDATE:
5558 		cipher_data = *((crypto_data_t *)dual_data);
5559 
5560 		/* do mac update */
5561 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5562 		    &cipher_data, NULL)) != CRYPTO_SUCCESS)
5563 			break;
5564 
5565 		/* do a decrypt update */
5566 		cipher_data.cd_length = dual_data->dd_len2;
5567 		cipher_data.cd_offset = dual_data->dd_offset2;
5568 		error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5569 		    &cipher_data, taskq_req->dr_cipher_mac_req.mr_data, NULL);
5570 
5571 		break;
5572 
5573 	case DPROV_REQ_MAC_DECRYPT_FINAL:
5574 		/* do a mac final */
5575 		if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5576 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
5577 		    CRYPTO_SUCCESS)
5578 			break;
5579 
5580 		/* do a decrypt final */
5581 		error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5582 		    taskq_req->dr_cipher_mac_req.mr_data, NULL);
5583 
5584 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5585 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5586 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5587 			(void) dprov_free_context(ctx);
5588 		}
5589 		break;
5590 
5591 	case DPROV_REQ_MAC_DECRYPT_ATOMIC:
5592 	case DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC:
5593 		cipher_data = *((crypto_data_t *)dual_data);
5594 
5595 		/* structure assignment */
5596 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5597 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5598 		session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
5599 
5600 		/* get the keys values and providers to use for operations */
5601 		if ((error = dprov_cipher_mac_key_pd(softc, session_id,
5602 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5603 		    &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
5604 			break;
5605 
5606 		/* do the atomic mac */
5607 		if (taskq_req->dr_type == DPROV_REQ_MAC_DECRYPT_ATOMIC)
5608 			error = crypto_mac_prov(&mac_mech, &cipher_data,
5609 			    &mac_key, NULL, taskq_req->dr_cipher_mac_req.mr_mac,
5610 			    NULL, mac_pd, 0);
5611 		else
5612 			/* DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC */
5613 			error = crypto_mac_verify_prov(&mac_mech, &cipher_data,
5614 			    &mac_key, NULL, taskq_req->dr_cipher_mac_req.mr_mac,
5615 			    NULL, mac_pd, 0);
5616 
5617 		if (error != CRYPTO_SUCCESS)
5618 			break;
5619 
5620 		/* do the atomic decrypt */
5621 		cipher_data.cd_length = dual_data->dd_len2;
5622 		cipher_data.cd_offset = dual_data->dd_offset2;
5623 		error = crypto_decrypt_prov(&cipher_mech, &cipher_data,
5624 		    &cipher_key, NULL, taskq_req->dr_cipher_mac_req.mr_data,
5625 		    NULL, cipher_pd, 0);
5626 
5627 		break;
5628 	}
5629 
5630 	dprov_op_done(taskq_req, error);
5631 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: end\n",
5632 	    instance));
5633 }
5634 
5635 /*
5636  * taskq dispatcher function for random number generation.
5637  */
5638 static void
5639 dprov_random_task(dprov_req_t *taskq_req)
5640 {
5641 	dprov_state_t *softc;
5642 	/* LINTED E_FUNC_SET_NOT_USED */
5643 	int instance;
5644 	int error = CRYPTO_SUCCESS;
5645 
5646 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5647 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: started\n", instance));
5648 
5649 	mutex_enter(&softc->ds_lock);
5650 
5651 	switch (taskq_req->dr_type) {
5652 
5653 	DPROV_REQ_RANDOM_SEED:
5654 		/*
5655 		 * Since we don't really generate random numbers
5656 		 * nothing to do.
5657 		 */
5658 		break;
5659 
5660 	case DPROV_REQ_RANDOM_GENERATE: {
5661 		uint_t i;
5662 		uchar_t c = 0;
5663 
5664 		/*
5665 		 * We don't generate random numbers so that the result
5666 		 * of the operation can be checked during testing.
5667 		 */
5668 
5669 		for (i = 0; i < taskq_req->dr_random_req.rr_len; i++)
5670 			taskq_req->dr_random_req.rr_buf[i] = c++;
5671 
5672 		break;
5673 	}
5674 	}
5675 
5676 	mutex_exit(&softc->ds_lock);
5677 	dprov_op_done(taskq_req, error);
5678 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: end\n", instance));
5679 }
5680 
5681 
5682 /*
5683  * taskq dispatcher function for session management operations.
5684  */
5685 static void
5686 dprov_session_task(dprov_req_t *taskq_req)
5687 {
5688 	dprov_state_t *softc;
5689 	/* LINTED E_FUNC_SET_NOT_USED */
5690 	int instance;
5691 	int error = CRYPTO_NOT_SUPPORTED;
5692 	crypto_session_id_t session_id =
5693 	    taskq_req->dr_session_req.sr_session_id;
5694 	dprov_session_t *session;
5695 	dprov_object_t *object;
5696 	int i;
5697 
5698 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5699 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: started\n",
5700 	    instance));
5701 
5702 	mutex_enter(&softc->ds_lock);
5703 
5704 	if (taskq_req->dr_type != DPROV_REQ_SESSION_OPEN)
5705 		/* validate session id and get ptr to session */
5706 		if ((session = softc->ds_sessions[session_id]) == NULL) {
5707 			mutex_exit(&softc->ds_lock);
5708 			dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
5709 			return;
5710 		}
5711 
5712 	switch (taskq_req->dr_type) {
5713 
5714 	case DPROV_REQ_SESSION_OPEN: {
5715 		dprov_session_t **new_sessions;
5716 
5717 		if (softc->ds_token_initialized == B_FALSE) {
5718 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
5719 			break;
5720 		}
5721 
5722 		/* search for available session slot */
5723 		for (i = 0; i < softc->ds_sessions_slots; i++)
5724 			if (softc->ds_sessions[i] == NULL)
5725 				break;
5726 
5727 		if (i == softc->ds_sessions_slots) {
5728 			/* ran out of slots, grow sessions array */
5729 			new_sessions = kmem_zalloc(2 * softc->ds_sessions_slots,
5730 			    KM_NOSLEEP);
5731 			if (new_sessions == NULL) {
5732 				error = CRYPTO_SESSION_COUNT;
5733 				break;
5734 			}
5735 			bcopy(softc->ds_sessions, new_sessions,
5736 			    softc->ds_sessions_slots);
5737 			kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
5738 			    sizeof (dprov_session_t *));
5739 			softc->ds_sessions = new_sessions;
5740 			softc->ds_sessions_slots *= 2;
5741 		}
5742 
5743 		/* allocate and initialize new session */
5744 		softc->ds_sessions[i] = kmem_zalloc(
5745 		    sizeof (dprov_session_t), KM_NOSLEEP);
5746 		if (softc->ds_sessions[i] == NULL) {
5747 			error = CRYPTO_HOST_MEMORY;
5748 			break;
5749 		}
5750 		softc->ds_sessions_count++;
5751 
5752 		/* initialize session state */
5753 		softc->ds_sessions[i]->ds_state = DPROV_SESSION_STATE_PUBLIC;
5754 
5755 		/* return new session id to caller */
5756 		*(taskq_req->dr_session_req.sr_session_id_ptr) = i;
5757 
5758 		error = CRYPTO_SUCCESS;
5759 		break;
5760 	}
5761 
5762 	case DPROV_REQ_SESSION_CLOSE:
5763 		softc->ds_sessions[session_id] = NULL;
5764 
5765 		if (softc->ds_token_initialized == B_FALSE) {
5766 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
5767 			break;
5768 		}
5769 
5770 		dprov_release_session_objects(session);
5771 
5772 		/* free session state and corresponding slot */
5773 		kmem_free(session, sizeof (dprov_session_t));
5774 		softc->ds_sessions_count--;
5775 
5776 		error = CRYPTO_SUCCESS;
5777 		break;
5778 
5779 	case DPROV_REQ_SESSION_LOGIN: {
5780 		char *pin = taskq_req->dr_session_req.sr_pin;
5781 		size_t pin_len = taskq_req->dr_session_req.sr_pin_len;
5782 		crypto_user_type_t user_type =
5783 		    taskq_req->dr_session_req.sr_user_type;
5784 
5785 		/* check user type */
5786 		if (user_type != CRYPTO_SO && user_type != CRYPTO_USER) {
5787 			error = CRYPTO_USER_TYPE_INVALID;
5788 			break;
5789 		}
5790 
5791 		/* check pin length */
5792 		if (pin_len > DPROV_MAX_PIN_LEN) {
5793 			error = CRYPTO_PIN_LEN_RANGE;
5794 			break;
5795 		}
5796 
5797 		/* check pin */
5798 		if (pin == NULL) {
5799 			error = CRYPTO_PIN_INVALID;
5800 			break;
5801 		}
5802 
5803 		/* validate PIN state */
5804 		if ((user_type == CRYPTO_SO) && !softc->ds_token_initialized ||
5805 		    (user_type == CRYPTO_USER) && !softc->ds_user_pin_set) {
5806 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
5807 			break;
5808 		}
5809 
5810 		if ((user_type == CRYPTO_SO &&
5811 		    softc->ds_sessions[session_id]->ds_state ==
5812 		    DPROV_SESSION_STATE_SO) ||
5813 		    (user_type == CRYPTO_USER &&
5814 		    softc->ds_sessions[session_id]->ds_state ==
5815 		    DPROV_SESSION_STATE_USER)) {
5816 			/* SO or user already logged in */
5817 			error = CRYPTO_USER_ALREADY_LOGGED_IN;
5818 			break;
5819 		}
5820 
5821 		if (softc->ds_sessions[session_id]->ds_state !=
5822 		    DPROV_SESSION_STATE_PUBLIC) {
5823 			/* another user already logged in */
5824 			error = CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN;
5825 			break;
5826 		}
5827 
5828 		/* everything's fine, update session */
5829 		softc->ds_sessions[session_id]->ds_state =
5830 		    user_type == CRYPTO_SO ?
5831 		    DPROV_SESSION_STATE_SO : DPROV_SESSION_STATE_USER;
5832 
5833 		error = CRYPTO_SUCCESS;
5834 		break;
5835 	}
5836 
5837 	case DPROV_REQ_SESSION_LOGOUT:
5838 		/* fail if not logged in */
5839 		if (softc->ds_sessions[session_id]->ds_state ==
5840 		    DPROV_SESSION_STATE_PUBLIC) {
5841 			error = CRYPTO_USER_NOT_LOGGED_IN;
5842 			break;
5843 		}
5844 
5845 		/*
5846 		 * Destroy all private session objects.
5847 		 * Invalidate handles to all private objects.
5848 		 */
5849 		for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
5850 			object = softc->ds_sessions[session_id]->ds_objects[i];
5851 			if (object != NULL && dprov_object_is_private(object)) {
5852 				if (!dprov_object_is_token(object))
5853 					/* It's a session object, free it */
5854 					DPROV_OBJECT_REFRELE(object);
5855 				softc->ds_sessions[session_id]->ds_objects[i] =
5856 				    NULL;
5857 			}
5858 		}
5859 
5860 		/* update session state */
5861 		softc->ds_sessions[session_id]->ds_state =
5862 		    DPROV_SESSION_STATE_PUBLIC;
5863 
5864 		error = CRYPTO_SUCCESS;
5865 		break;
5866 	}
5867 
5868 	mutex_exit(&softc->ds_lock);
5869 	dprov_op_done(taskq_req, error);
5870 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: end\n", instance));
5871 }
5872 
5873 /*
5874  * taskq dispatcher function for object management operations.
5875  */
5876 static void
5877 dprov_object_task(dprov_req_t *taskq_req)
5878 {
5879 	dprov_state_t *softc;
5880 	/* LINTED E_FUNC_SET_NOT_USED */
5881 	int instance;
5882 	int error = CRYPTO_NOT_SUPPORTED;
5883 	crypto_object_id_t object_id = taskq_req->dr_object_req.or_object_id;
5884 	crypto_session_id_t session_id = taskq_req->dr_object_req.or_session_id;
5885 	crypto_object_attribute_t *template =
5886 	    taskq_req->dr_object_req.or_template;
5887 	uint_t attr_count = taskq_req->dr_object_req.or_attribute_count;
5888 	dprov_object_t *object;
5889 	dprov_session_t *session;
5890 
5891 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5892 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: started\n", instance));
5893 
5894 	mutex_enter(&softc->ds_lock);
5895 
5896 	/* validate session id and get ptr to session */
5897 	if ((session = softc->ds_sessions[session_id]) == NULL) {
5898 		mutex_exit(&softc->ds_lock);
5899 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
5900 		return;
5901 	}
5902 
5903 	switch (taskq_req->dr_type) {
5904 
5905 	case DPROV_REQ_OBJECT_CREATE:
5906 		/* create the object from the specified template */
5907 		if ((error = dprov_create_object_from_template(softc, session,
5908 		    template, attr_count,
5909 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
5910 		    B_FALSE)) != CRYPTO_SUCCESS)
5911 			break;
5912 
5913 		break;
5914 
5915 	case DPROV_REQ_OBJECT_COPY:
5916 		/* check object id */
5917 		if (object_id >= DPROV_MAX_OBJECTS ||
5918 		    (object = session->ds_objects[object_id]) == NULL) {
5919 			error = CRYPTO_OBJECT_HANDLE_INVALID;
5920 			break;
5921 		}
5922 
5923 		/*
5924 		 * Create a new object from the object passed as
5925 		 * argument.
5926 		 */
5927 		if ((error = dprov_create_object_from_template(softc, session,
5928 		    object->do_attr, DPROV_MAX_ATTR,
5929 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
5930 		    B_FALSE)) != CRYPTO_SUCCESS)
5931 			break;
5932 
5933 		/*
5934 		 * Add the attributes specified by the template to the
5935 		 * newly created object, replacing existing ones if needed.
5936 		 */
5937 		error = dprov_object_set_attr(session,
5938 		    *taskq_req->dr_object_req.or_object_id_ptr,
5939 		    taskq_req->dr_object_req.or_template,
5940 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
5941 
5942 		break;
5943 
5944 	case DPROV_REQ_OBJECT_DESTROY:
5945 		/* destroy the object */
5946 		error = dprov_destroy_object(softc, session,
5947 		    taskq_req->dr_object_req.or_object_id);
5948 
5949 		break;
5950 
5951 	case DPROV_REQ_OBJECT_GET_SIZE:
5952 		/* get ptr to object */
5953 		if (object_id >= DPROV_MAX_OBJECTS ||
5954 		    session->ds_objects[object_id] == NULL) {
5955 			error = CRYPTO_OBJECT_HANDLE_INVALID;
5956 			break;
5957 		}
5958 
5959 		/*
5960 		 * The PKCS11 specification does not specifies what
5961 		 * the object size really is, here we just return
5962 		 * the number of possible attributes of the object.
5963 		 */
5964 		*taskq_req->dr_object_req.or_object_size = DPROV_MAX_ATTR;
5965 
5966 		error = CRYPTO_SUCCESS;
5967 		break;
5968 
5969 	case DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE: {
5970 		int tmpl_idx;
5971 		int object_idx;
5972 		ulong_t class = DPROV_CKO_DATA;
5973 		boolean_t extractable = B_TRUE;
5974 
5975 		error = CRYPTO_SUCCESS;
5976 
5977 		/* get ptr to object */
5978 		if (object_id >= DPROV_MAX_OBJECTS ||
5979 		    (object = session->ds_objects[object_id]) == NULL) {
5980 			error = CRYPTO_OBJECT_HANDLE_INVALID;
5981 			break;
5982 		}
5983 
5984 		(void) dprov_get_object_attr_boolean(object,
5985 		    DPROV_CKA_EXTRACTABLE, &extractable);
5986 
5987 		(void) dprov_get_object_attr_ulong(object,
5988 		    DPROV_CKA_CLASS, &class);
5989 
5990 		/* return the specified attributes, when possible */
5991 		for (tmpl_idx = 0; tmpl_idx < attr_count; tmpl_idx++) {
5992 			/*
5993 			 * Attribute can't be revealed if the CKA_EXTRACTABLE
5994 			 * attribute is set to false.
5995 			 */
5996 			if (!extractable && class == DPROV_CKO_SECRET_KEY) {
5997 				if (template[tmpl_idx].oa_type ==
5998 				    DPROV_CKA_VALUE) {
5999 					template[tmpl_idx].oa_value_len = -1;
6000 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6001 					continue;
6002 				}
6003 			}
6004 			if (!extractable && class == DPROV_CKO_PRIVATE_KEY) {
6005 				if (template[tmpl_idx].oa_type ==
6006 				    DPROV_CKA_PRIVATE_EXPONENT) {
6007 					template[tmpl_idx].oa_value_len = -1;
6008 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6009 					continue;
6010 				}
6011 			}
6012 
6013 			object_idx = dprov_find_attr(object->do_attr,
6014 			    DPROV_MAX_ATTR, template[tmpl_idx].oa_type);
6015 			if (object_idx == -1) {
6016 				/* attribute not found in object */
6017 				template[tmpl_idx].oa_value_len = -1;
6018 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
6019 				continue;
6020 			}
6021 
6022 			if (template[tmpl_idx].oa_value == NULL) {
6023 				/* return attribute length */
6024 				template[tmpl_idx].oa_value_len =
6025 				    object->do_attr[object_idx].oa_value_len;
6026 				continue;
6027 			}
6028 			if (template[tmpl_idx].oa_value_len <
6029 			    object->do_attr[object_idx].oa_value_len) {
6030 				/*
6031 				 * Template buffer for attribute value too
6032 				 * small.
6033 				 */
6034 				template[tmpl_idx].oa_value_len = -1;
6035 				error = CRYPTO_BUFFER_TOO_SMALL;
6036 				continue;
6037 			}
6038 			/* copy attribute value, update length */
6039 			bcopy(object->do_attr[object_idx].oa_value,
6040 			    template[tmpl_idx].oa_value,
6041 			    object->do_attr[object_idx].oa_value_len);
6042 			template[tmpl_idx].oa_value_len =
6043 			    object->do_attr[object_idx].oa_value_len;
6044 		}
6045 
6046 		break;
6047 	}
6048 
6049 	case DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE:
6050 		/*
6051 		 * Add the attributes specified by the template to the
6052 		 * newly created object, replacing existing ones if needed.
6053 		 */
6054 		error = dprov_object_set_attr(session,
6055 		    taskq_req->dr_object_req.or_object_id,
6056 		    taskq_req->dr_object_req.or_template,
6057 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6058 
6059 		break;
6060 
6061 	case DPROV_REQ_OBJECT_FIND_INIT: {
6062 		dprov_find_ctx_t *find_ctx;
6063 		int so_idx;		/* session object index */
6064 		int to_idx;		/* token object index */
6065 
6066 		error = CRYPTO_SUCCESS;
6067 		/* allocate find context */
6068 		find_ctx = kmem_zalloc(sizeof (dprov_find_ctx_t), KM_SLEEP);
6069 		*taskq_req->dr_object_req.or_find_pp = find_ctx;
6070 
6071 		/* first go through the existing session objects */
6072 		for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++) {
6073 			if ((object = session->ds_objects[so_idx]) == NULL)
6074 				continue;
6075 
6076 			/* setting count to zero means find all objects */
6077 			if (attr_count > 0) {
6078 				if (!dprov_attributes_match(object, template,
6079 				    attr_count))
6080 					continue;
6081 			}
6082 
6083 			/* session object attributes matches template */
6084 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
6085 			find_ctx->fc_nids++;
6086 		}
6087 
6088 		/*
6089 		 * Go through the token object. For each token object
6090 		 * that can be accessed:
6091 		 * If there was already an session object id assigned
6092 		 * to that token object, skip it, since it was returned
6093 		 * during the check of session objects, else,
6094 		 * assign a new object id for that token object and
6095 		 * add it to the array of matching objects.
6096 		 */
6097 		for (to_idx = 0; to_idx < DPROV_MAX_OBJECTS &&
6098 		    error == CRYPTO_SUCCESS; to_idx++) {
6099 			if ((object = softc->ds_objects[to_idx]) == NULL)
6100 				continue;
6101 
6102 			/* setting count to zero means find all objects */
6103 			if (attr_count > 0) {
6104 				if (!dprov_attributes_match(object, template,
6105 				    attr_count))
6106 					continue;
6107 			}
6108 
6109 			/* if the the object has been destroyed, skip it */
6110 			if (object->do_destroyed)
6111 				continue;
6112 
6113 			/* skip object if it cannot be accessed from session */
6114 			if (dprov_object_is_private(object) &&
6115 			    session->ds_state != DPROV_SESSION_STATE_USER)
6116 				continue;
6117 
6118 			/*
6119 			 * Is there already a session object id for this
6120 			 * token object?
6121 			 */
6122 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
6123 				if (session->ds_objects[so_idx] != NULL &&
6124 				    session->ds_objects[so_idx]->do_token_idx ==
6125 				    to_idx)
6126 					break;
6127 			if (so_idx < DPROV_MAX_OBJECTS)
6128 				/* object found in session table, skip it */
6129 				continue;
6130 
6131 			/* find free session slot for this object */
6132 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
6133 				if (session->ds_objects[so_idx] == NULL)
6134 					break;
6135 			if (so_idx == DPROV_MAX_OBJECTS) {
6136 				/* ran out of session objects slots */
6137 				kmem_free(find_ctx, sizeof (dprov_find_ctx_t));
6138 				error = CRYPTO_HOST_MEMORY;
6139 				break;
6140 			}
6141 
6142 			/* add object to session objects table */
6143 			session->ds_objects[so_idx] = object;
6144 			DPROV_OBJECT_REFHOLD(object);
6145 
6146 			/* add object to list of objects to return */
6147 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
6148 			find_ctx->fc_nids++;
6149 		}
6150 
6151 		break;
6152 	}
6153 
6154 	case DPROV_REQ_OBJECT_FIND: {
6155 		crypto_object_id_t *object_ids =
6156 			taskq_req->dr_object_req.or_object_id_ptr;
6157 		uint_t max_object_count =
6158 			taskq_req->dr_object_req.or_max_object_count;
6159 		dprov_find_ctx_t *find_ctx =
6160 			taskq_req->dr_object_req.or_find_p;
6161 		uint_t ret_oid_idx;
6162 
6163 		/* return the desired number of object ids */
6164 		for (ret_oid_idx = 0; ret_oid_idx < max_object_count &&
6165 		    find_ctx->fc_next < find_ctx->fc_nids; ret_oid_idx++)
6166 			object_ids[ret_oid_idx] =
6167 			    find_ctx->fc_ids[find_ctx->fc_next++];
6168 
6169 		*taskq_req->dr_object_req.or_object_count_ptr = ret_oid_idx;
6170 
6171 		error = CRYPTO_SUCCESS;
6172 		break;
6173 	}
6174 
6175 	case DPROV_REQ_OBJECT_FIND_FINAL:
6176 		kmem_free(taskq_req->dr_object_req.or_find_p,
6177 		    sizeof (dprov_find_ctx_t));
6178 
6179 		error = CRYPTO_SUCCESS;
6180 		break;
6181 	}
6182 
6183 	mutex_exit(&softc->ds_lock);
6184 	dprov_op_done(taskq_req, error);
6185 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: end\n", instance));
6186 }
6187 
6188 /*
6189  * taskq dispatcher function for key management operations.
6190  */
6191 static void
6192 dprov_key_task(dprov_req_t *taskq_req)
6193 {
6194 	dprov_state_t *softc;
6195 	/* LINTED E_FUNC_SET_NOT_USED */
6196 	int instance;
6197 	int error = CRYPTO_NOT_SUPPORTED;
6198 	kcf_provider_desc_t *pd;
6199 	crypto_session_id_t session_id = taskq_req->dr_key_req.kr_session_id;
6200 	dprov_session_t *session;
6201 
6202 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6203 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: started\n", instance));
6204 
6205 	mutex_enter(&softc->ds_lock);
6206 
6207 	/* validate session id and get ptr to session */
6208 	if ((session = softc->ds_sessions[session_id]) == NULL) {
6209 		mutex_exit(&softc->ds_lock);
6210 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6211 		return;
6212 	}
6213 
6214 	switch (taskq_req->dr_type) {
6215 	case DPROV_REQ_KEY_GENERATE: {
6216 		crypto_mechanism_t *mechp;
6217 		crypto_object_id_t *object_id_ptr;
6218 		crypto_object_attribute_t *template;
6219 		crypto_object_attribute_t attribute;
6220 		uint_t attribute_count;
6221 		ulong_t key_type = ~0UL, class = ~0UL;
6222 		ulong_t value_len;
6223 		size_t key_len = 0;
6224 
6225 		error = CRYPTO_SUCCESS;
6226 
6227 		template = taskq_req->dr_key_req.kr_template;
6228 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
6229 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
6230 		mechp = taskq_req->dr_key_req.kr_mechanism;
6231 
6232 		/* optional */
6233 		(void) dprov_get_template_attr_ulong(template, attribute_count,
6234 		    DPROV_CKA_CLASS, &class);
6235 
6236 		/* optional */
6237 		(void) dprov_get_template_attr_ulong(template, attribute_count,
6238 		    DPROV_CKA_KEY_TYPE, &key_type);
6239 
6240 		if (class != ~0UL && class != DPROV_CKO_SECRET_KEY) {
6241 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6242 			break;
6243 		}
6244 
6245 		switch (mechp->cm_type) {
6246 		case DES_KEY_GEN_MECH_INFO_TYPE:
6247 			if (key_type != ~0UL && key_type != DPROV_CKK_DES) {
6248 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6249 				break;
6250 			}
6251 			key_len = DES_KEY_LEN;
6252 			key_type = DPROV_CKK_DES;
6253 			break;
6254 
6255 		case DES3_KEY_GEN_MECH_INFO_TYPE:
6256 			if (key_type != ~0UL && key_type != DPROV_CKK_DES3) {
6257 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6258 				break;
6259 			}
6260 			key_len = DES3_KEY_LEN;
6261 			key_type = DPROV_CKK_DES3;
6262 			break;
6263 
6264 		case AES_KEY_GEN_MECH_INFO_TYPE:
6265 			if (key_type != ~0UL && key_type != DPROV_CKK_AES) {
6266 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6267 				break;
6268 			}
6269 			if (dprov_get_template_attr_ulong(template,
6270 			    attribute_count, DPROV_CKA_VALUE_LEN,
6271 			    &value_len) != CRYPTO_SUCCESS) {
6272 				error = CRYPTO_TEMPLATE_INCOMPLETE;
6273 				break;
6274 			}
6275 			if (value_len >= AES_MAX_KEY_LEN) {
6276 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6277 				break;
6278 			}
6279 			key_len = value_len;
6280 			key_type = DPROV_CKK_AES;
6281 			break;
6282 
6283 		case RC4_KEY_GEN_MECH_INFO_TYPE:
6284 			if (key_type != ~0UL && key_type != DPROV_CKK_RC4) {
6285 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6286 				break;
6287 			}
6288 			if (dprov_get_template_attr_ulong(template,
6289 			    attribute_count, DPROV_CKA_VALUE_LEN,
6290 			    &value_len) != CRYPTO_SUCCESS) {
6291 				error = CRYPTO_TEMPLATE_INCOMPLETE;
6292 				break;
6293 			}
6294 			if (value_len >=
6295 			    CRYPTO_BITS2BYTES(ARCFOUR_MAX_KEY_BITS)) {
6296 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6297 				break;
6298 			}
6299 			key_len = value_len;
6300 			key_type = DPROV_CKK_RC4;
6301 			break;
6302 
6303 		default:
6304 			error = CRYPTO_MECHANISM_INVALID;
6305 		}
6306 
6307 		if (error != CRYPTO_SUCCESS)
6308 			break;
6309 
6310 		error = dprov_create_object_from_template(softc, session,
6311 		    template, attribute_count, object_id_ptr, B_FALSE, B_TRUE);
6312 
6313 		if (error != CRYPTO_SUCCESS)
6314 			break;
6315 
6316 		/* make sure class is set */
6317 		attribute.oa_type = DPROV_CKA_CLASS;
6318 		attribute.oa_value = (char *)&class;
6319 		attribute.oa_value_len = sizeof (ulong_t);
6320 		error = dprov_object_set_attr(session, *object_id_ptr,
6321 		    &attribute, 1, B_FALSE);
6322 
6323 		if (error != CRYPTO_SUCCESS) {
6324 			goto destroy_object;
6325 		}
6326 
6327 		/* make sure key_type is set */
6328 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
6329 		attribute.oa_value = (char *)&key_type;
6330 		attribute.oa_value_len = sizeof (ulong_t);
6331 		error = dprov_object_set_attr(session, *object_id_ptr,
6332 		    &attribute, 1, B_FALSE);
6333 
6334 		if (error != CRYPTO_SUCCESS) {
6335 			goto destroy_object;
6336 		}
6337 
6338 		attribute.oa_type = DPROV_CKA_VALUE;
6339 		attribute.oa_value = kmem_alloc(key_len, KM_SLEEP);
6340 		attribute.oa_value_len = key_len;
6341 
6342 		if (random_get_pseudo_bytes((uchar_t *)attribute.oa_value,
6343 		    key_len) != 0) {
6344 			bzero(attribute.oa_value, key_len);
6345 			kmem_free(attribute.oa_value, key_len);
6346 			goto destroy_object;
6347 		}
6348 		error = dprov_object_set_attr(session, *object_id_ptr,
6349 		    &attribute, 1, B_FALSE);
6350 
6351 		bzero(attribute.oa_value, key_len);
6352 		kmem_free(attribute.oa_value, key_len);
6353 
6354 		if (error != CRYPTO_SUCCESS) {
6355 			goto destroy_object;
6356 		}
6357 		break;
6358 
6359 destroy_object:
6360 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
6361 		break;
6362 	}
6363 
6364 	case DPROV_REQ_KEY_GENERATE_PAIR: {
6365 		crypto_mechanism_t *mechp;
6366 		crypto_object_id_t *pub_object_id_ptr;
6367 		crypto_object_id_t *pri_object_id_ptr;
6368 		crypto_object_attribute_t *pub_template;
6369 		crypto_object_attribute_t *pri_template;
6370 		crypto_object_attribute_t attribute;
6371 		uint_t pub_attribute_count;
6372 		uint_t pri_attribute_count;
6373 		ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
6374 		ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
6375 		char public_exponent[3] = {
6376 		    0x01, 0x00, 0x01
6377 		};
6378 		static uchar_t private_exponent[128] = {
6379 		    0x4a, 0xef, 0xb9, 0x30, 0xa1, 0x44, 0x0a, 0xe0,
6380 		    0x30, 0xdd, 0xd3, 0x57, 0xc2, 0xb6, 0x6a, 0xba,
6381 		    0x5f, 0x81, 0xb0, 0x72, 0x55, 0x5b, 0x5b, 0xf3,
6382 		    0x07, 0xd2, 0x5f, 0x15, 0x87, 0xc0, 0x78, 0x7d,
6383 		    0x4f, 0x95, 0x09, 0x59, 0xd2, 0x9a, 0x95, 0xc3,
6384 		    0xcc, 0xdc, 0xf1, 0xa4, 0x60, 0x76, 0xd7, 0xa7,
6385 		    0xf8, 0x01, 0x13, 0xf8, 0x54, 0xd4, 0xf8, 0x2f,
6386 		    0xcf, 0x0c, 0x8b, 0x6e, 0xee, 0x34, 0x53, 0x19,
6387 		    0x14, 0xa6, 0x15, 0x14, 0xaf, 0xb2, 0x28, 0xa1,
6388 		    0x78, 0x1b, 0x2d, 0x9b, 0x28, 0x52, 0x14, 0xfa,
6389 		    0x72, 0x2b, 0x81, 0x11, 0xd0, 0x59, 0xde, 0xc6,
6390 		    0x52, 0x90, 0xa4, 0xae, 0xc9, 0xf1, 0x97, 0xd4,
6391 		    0x57, 0xbc, 0xe3, 0x90, 0x30, 0xc7, 0xff, 0xe8,
6392 		    0xd7, 0x2d, 0xd8, 0xef, 0x14, 0x2d, 0x2d, 0x60,
6393 		    0x54, 0x22, 0x9d, 0x32, 0x36, 0xcf, 0x4f, 0xf7,
6394 		    0x37, 0xcc, 0x8e, 0x00, 0x85, 0xb1, 0x00, 0x01
6395 		};
6396 
6397 		static uchar_t modulus[128] = {
6398 		    0x87, 0xb2, 0x2a, 0x54, 0x63, 0x83, 0x5e, 0x30,
6399 		    0xdc, 0x73, 0x03, 0xc6, 0x35, 0xf8, 0xa0, 0x25,
6400 		    0xa5, 0x6e, 0xcc, 0x14, 0xdd, 0x77, 0x2e, 0x80,
6401 		    0xd1, 0xa3, 0x05, 0x09, 0x1a, 0x2f, 0x88, 0xec,
6402 		    0xd1, 0x46, 0x92, 0x19, 0x8c, 0x7a, 0xf7, 0x63,
6403 		    0x28, 0xbf, 0x7a, 0xea, 0x9f, 0xfe, 0x96, 0x0f,
6404 		    0x80, 0xa1, 0x3e, 0xa6, 0xe1, 0x89, 0x7c, 0x4c,
6405 		    0x8e, 0x92, 0xdc, 0x6e, 0x69, 0xba, 0x4b, 0x3f,
6406 		    0x93, 0xc0, 0xaf, 0xbd, 0xbc, 0x81, 0xf2, 0x1e,
6407 		    0xc0, 0x7d, 0xc3, 0x4c, 0x8f, 0x5f, 0xfe, 0xdc,
6408 		    0xdb, 0xdb, 0x52, 0x03, 0x94, 0x78, 0x04, 0xa6,
6409 		    0x78, 0x1f, 0xdd, 0x5e, 0xd8, 0x85, 0x3e, 0x19,
6410 		    0x54, 0x7c, 0xd5, 0x81, 0xfb, 0x70, 0x69, 0x5d,
6411 		    0xbf, 0x23, 0x7a, 0xb1, 0xf9, 0x85, 0x6e, 0xc2,
6412 		    0x0a, 0x4d, 0x81, 0x21, 0xf8, 0xad, 0x71, 0x65,
6413 		    0xaf, 0xb6, 0x8f, 0xa1, 0xac, 0x46, 0x8a, 0x4d
6414 		};
6415 
6416 		pub_template = taskq_req->dr_key_req.kr_template;
6417 		pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
6418 		pub_object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
6419 		pri_template = taskq_req->dr_key_req.kr_private_key_template;
6420 		pri_attribute_count =
6421 		    taskq_req->dr_key_req.kr_private_key_attribute_count;
6422 		pri_object_id_ptr =
6423 		    taskq_req->dr_key_req.kr_private_key_object_id_ptr;
6424 		mechp = taskq_req->dr_key_req.kr_mechanism;
6425 
6426 		error = CRYPTO_SUCCESS;
6427 
6428 		/* optional */
6429 		(void) dprov_get_template_attr_ulong(pub_template,
6430 		    pub_attribute_count, DPROV_CKA_CLASS, &pub_class);
6431 
6432 		/* optional */
6433 		(void) dprov_get_template_attr_ulong(pri_template,
6434 		    pri_attribute_count, DPROV_CKA_CLASS, &pri_class);
6435 
6436 		/* optional */
6437 		(void) dprov_get_template_attr_ulong(pub_template,
6438 		    pub_attribute_count, DPROV_CKA_KEY_TYPE, &pub_key_type);
6439 
6440 		/* optional */
6441 		(void) dprov_get_template_attr_ulong(pri_template,
6442 		    pri_attribute_count, DPROV_CKA_KEY_TYPE, &pri_key_type);
6443 
6444 		if (pub_class != ~0UL && pub_class != DPROV_CKO_PUBLIC_KEY) {
6445 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6446 			break;
6447 		}
6448 
6449 		if (pri_class != ~0UL && pri_class != DPROV_CKO_PRIVATE_KEY) {
6450 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6451 			break;
6452 		}
6453 
6454 		switch (mechp->cm_type) {
6455 		case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
6456 			if (pub_key_type != ~0UL &&
6457 			    pub_key_type != DPROV_CKK_RSA) {
6458 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6459 				break;
6460 			}
6461 			pri_key_type = DPROV_CKK_RSA;
6462 
6463 			if (pri_key_type != ~0UL &&
6464 			    pri_key_type != DPROV_CKK_RSA) {
6465 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6466 				break;
6467 			}
6468 			pri_key_type = DPROV_CKK_RSA;
6469 
6470 			if (pub_class != ~0UL &&
6471 			    pub_class != DPROV_CKO_PUBLIC_KEY) {
6472 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6473 				break;
6474 			}
6475 			pub_class = DPROV_CKO_PUBLIC_KEY;
6476 
6477 			if (pri_class != ~0UL &&
6478 			    pri_class != DPROV_CKO_PRIVATE_KEY) {
6479 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6480 				break;
6481 			}
6482 			pri_class = DPROV_CKO_PRIVATE_KEY;
6483 			break;
6484 
6485 		default:
6486 			error = CRYPTO_MECHANISM_INVALID;
6487 		}
6488 
6489 		if (error != CRYPTO_SUCCESS)
6490 			break;
6491 
6492 		error = dprov_create_object_from_template(softc, session,
6493 		    pub_template, pub_attribute_count, pub_object_id_ptr,
6494 		    B_FALSE, B_TRUE);
6495 
6496 		if (error != CRYPTO_SUCCESS)
6497 			break;
6498 
6499 		/* make sure class is set */
6500 		attribute.oa_type = DPROV_CKA_CLASS;
6501 		attribute.oa_value = (char *)&pub_class;
6502 		attribute.oa_value_len = sizeof (ulong_t);
6503 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6504 		    &attribute, 1, B_FALSE);
6505 
6506 		if (error != CRYPTO_SUCCESS) {
6507 			goto destroy_public_object;
6508 		}
6509 
6510 		/* make sure key_type is set */
6511 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
6512 		attribute.oa_value = (char *)&pub_key_type;
6513 		attribute.oa_value_len = sizeof (ulong_t);
6514 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6515 		    &attribute, 1, B_FALSE);
6516 
6517 		if (error != CRYPTO_SUCCESS) {
6518 			goto destroy_public_object;
6519 		}
6520 
6521 		attribute.oa_type = DPROV_CKA_MODULUS;
6522 		attribute.oa_value = (char *)modulus;
6523 		attribute.oa_value_len = sizeof (modulus);
6524 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6525 		    &attribute, 1, B_FALSE);
6526 
6527 		if (error != CRYPTO_SUCCESS) {
6528 			goto destroy_public_object;
6529 		}
6530 
6531 		attribute.oa_type = DPROV_CKA_PUBLIC_EXPONENT;
6532 		attribute.oa_value = public_exponent;
6533 		attribute.oa_value_len = sizeof (public_exponent);
6534 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6535 		    &attribute, 1, B_FALSE);
6536 
6537 		if (error != CRYPTO_SUCCESS) {
6538 			goto destroy_public_object;
6539 		}
6540 
6541 		error = dprov_create_object_from_template(softc, session,
6542 		    pri_template, pri_attribute_count, pri_object_id_ptr,
6543 		    B_FALSE, B_TRUE);
6544 
6545 		if (error != CRYPTO_SUCCESS)
6546 			break;
6547 
6548 		/* make sure class is set */
6549 		attribute.oa_type = DPROV_CKA_CLASS;
6550 		attribute.oa_value = (char *)&pri_class;
6551 		attribute.oa_value_len = sizeof (ulong_t);
6552 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6553 		    &attribute, 1, B_FALSE);
6554 
6555 		if (error != CRYPTO_SUCCESS) {
6556 			goto destroy_private_object;
6557 		}
6558 
6559 		/* make sure key_type is set */
6560 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
6561 		attribute.oa_value = (char *)&pri_key_type;
6562 		attribute.oa_value_len = sizeof (ulong_t);
6563 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6564 		    &attribute, 1, B_FALSE);
6565 
6566 		if (error != CRYPTO_SUCCESS) {
6567 			goto destroy_private_object;
6568 		}
6569 
6570 		attribute.oa_type = DPROV_CKA_MODULUS;
6571 		attribute.oa_value = (char *)modulus;
6572 		attribute.oa_value_len = sizeof (modulus);
6573 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6574 		    &attribute, 1, B_FALSE);
6575 
6576 		if (error != CRYPTO_SUCCESS) {
6577 			goto destroy_private_object;
6578 		}
6579 
6580 		attribute.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
6581 		attribute.oa_value = (char *)private_exponent;
6582 		attribute.oa_value_len = sizeof (private_exponent);
6583 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6584 		    &attribute, 1, B_FALSE);
6585 
6586 		if (error != CRYPTO_SUCCESS) {
6587 			goto destroy_private_object;
6588 		}
6589 		break;
6590 
6591 destroy_private_object:
6592 		(void) dprov_destroy_object(softc, session,
6593 		    *pri_object_id_ptr);
6594 destroy_public_object:
6595 		(void) dprov_destroy_object(softc, session,
6596 		    *pub_object_id_ptr);
6597 
6598 		break;
6599 	}
6600 
6601 	case DPROV_REQ_KEY_WRAP: {
6602 		crypto_mechanism_t mech, *mechp;
6603 		crypto_key_t key, *keyp;
6604 		crypto_object_id_t object_id;
6605 		ulong_t class = DPROV_CKO_DATA;
6606 		boolean_t extractable = B_TRUE;
6607 		dprov_object_t *object;
6608 		int object_idx;
6609 		char *plaintext_key;
6610 		size_t plaintext_key_len;
6611 		crypto_data_t plaintext;
6612 		crypto_data_t ciphertext;
6613 		size_t *lenp;
6614 
6615 		mechp = taskq_req->dr_key_req.kr_mechanism;
6616 		/* structure assignment */
6617 		mech = *mechp;
6618 
6619 		/* get wrapping key value */
6620 		if (is_publickey_mech(mech.cm_type)) {
6621 			if ((error = dprov_key_attr_asymmetric(softc,
6622 			    session_id, taskq_req->dr_type,
6623 			    taskq_req->dr_key_req.kr_key,
6624 			    &key)) != CRYPTO_SUCCESS)
6625 				break;
6626 			keyp = &key;
6627 		} else {
6628 			if ((error = dprov_key_value_secret(softc,
6629 			    session_id, taskq_req->dr_type,
6630 			    taskq_req->dr_key_req.kr_key,
6631 			    &key)) != CRYPTO_SUCCESS)
6632 				break;
6633 			keyp = &key;
6634 		}
6635 
6636 		/* get the software provider for this mechanism */
6637 		if ((error = dprov_get_sw_prov(mechp, &pd,
6638 		    &mech.cm_type)) != CRYPTO_SUCCESS)
6639 			break;
6640 
6641 		object_id = *taskq_req->dr_key_req.kr_object_id_ptr;
6642 		if (object_id >= DPROV_MAX_OBJECTS) {
6643 			error = CRYPTO_KEY_HANDLE_INVALID;
6644 			break;
6645 		}
6646 
6647 		/* get ptr to object */
6648 		if ((object = session->ds_objects[object_id]) == NULL) {
6649 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6650 			break;
6651 		}
6652 
6653 		(void) dprov_get_object_attr_boolean(object,
6654 		    DPROV_CKA_EXTRACTABLE, &extractable);
6655 
6656 		if (!extractable) {
6657 			error = CRYPTO_ATTRIBUTE_SENSITIVE;
6658 			break;
6659 		}
6660 
6661 		(void) dprov_get_object_attr_ulong(object,
6662 		    DPROV_CKA_CLASS, &class);
6663 
6664 		switch (class) {
6665 		case DPROV_CKO_SECRET_KEY:
6666 			object_idx = dprov_find_attr(object->do_attr,
6667 			    DPROV_MAX_ATTR, DPROV_CKA_VALUE);
6668 			if (object_idx == -1) {
6669 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
6670 				break;
6671 			}
6672 			break;
6673 
6674 		case DPROV_CKO_PRIVATE_KEY:
6675 			/*
6676 			 * PKCS#11 says that ASN.1 should be used to encode
6677 			 * specific attributes before encrypting the blob.
6678 			 * We only encrypt the private exponent for the
6679 			 * purpose of testing.
6680 			 */
6681 			object_idx = dprov_find_attr(object->do_attr,
6682 			    DPROV_MAX_ATTR, DPROV_CKA_PRIVATE_EXPONENT);
6683 			if (object_idx == -1) {
6684 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
6685 				break;
6686 			}
6687 			break;
6688 		default:
6689 			error = CRYPTO_KEY_NOT_WRAPPABLE;
6690 			break;
6691 		}
6692 		if (error != CRYPTO_SUCCESS)
6693 			break;
6694 
6695 		plaintext_key = object->do_attr[object_idx].oa_value;
6696 		plaintext_key_len = object->do_attr[object_idx].oa_value_len;
6697 		lenp = taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
6698 
6699 		/* session id is 0 for software provider */
6700 		plaintext.cd_format = CRYPTO_DATA_RAW;
6701 		plaintext.cd_offset = 0;
6702 		plaintext.cd_length = plaintext_key_len;
6703 		plaintext.cd_raw.iov_base = plaintext_key;
6704 		plaintext.cd_raw.iov_len = plaintext_key_len;
6705 		plaintext.cd_miscdata = NULL;
6706 
6707 		ciphertext.cd_format = CRYPTO_DATA_RAW;
6708 		ciphertext.cd_offset = 0;
6709 		ciphertext.cd_length = *lenp;
6710 		ciphertext.cd_raw.iov_base =
6711 		    (char *)taskq_req->dr_key_req.kr_wrapped_key;
6712 		ciphertext.cd_raw.iov_len = ciphertext.cd_length;
6713 		ciphertext.cd_miscdata = NULL;
6714 
6715 		error = crypto_encrypt_prov(&mech, &plaintext, keyp,
6716 		    NULL, &ciphertext, NULL, pd, 0);
6717 
6718 		KCF_PROV_REFRELE(pd);
6719 		if (error == CRYPTO_SUCCESS ||
6720 		    error == CRYPTO_BUFFER_TOO_SMALL) {
6721 			*lenp = ciphertext.cd_length;
6722 		}
6723 		break;
6724 	}
6725 
6726 	case DPROV_REQ_KEY_UNWRAP: {
6727 		crypto_mechanism_t mech, *mechp;
6728 		crypto_key_t key, *keyp;
6729 		crypto_object_id_t *object_id_ptr;
6730 		ulong_t class = DPROV_CKO_DATA;
6731 		uchar_t *wrapped_key;
6732 		char *plaintext_buf;
6733 		size_t wrapped_key_len;
6734 		crypto_data_t plaintext;
6735 		crypto_data_t ciphertext;
6736 		crypto_object_attribute_t unwrapped_key;
6737 		crypto_object_attribute_t *template;
6738 		uint_t attribute_count;
6739 
6740 		template = taskq_req->dr_key_req.kr_template;
6741 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
6742 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
6743 
6744 		/* all objects must have an object class attribute */
6745 		if (dprov_get_template_attr_ulong(template, attribute_count,
6746 		    DPROV_CKA_CLASS, &class) != CRYPTO_SUCCESS) {
6747 			error = CRYPTO_TEMPLATE_INCOMPLETE;
6748 			break;
6749 		}
6750 
6751 		mechp = taskq_req->dr_key_req.kr_mechanism;
6752 		/* structure assignment */
6753 		mech = *mechp;
6754 
6755 		/* get unwrapping key value */
6756 		if (is_publickey_mech(mech.cm_type)) {
6757 			if ((error = dprov_key_attr_asymmetric(softc,
6758 			    session_id, taskq_req->dr_type,
6759 			    taskq_req->dr_key_req.kr_key,
6760 			    &key)) != CRYPTO_SUCCESS)
6761 				break;
6762 			keyp = &key;
6763 		} else {
6764 			if ((error = dprov_key_value_secret(softc,
6765 			    session_id, taskq_req->dr_type,
6766 			    taskq_req->dr_key_req.kr_key,
6767 			    &key)) != CRYPTO_SUCCESS)
6768 				break;
6769 			keyp = &key;
6770 		}
6771 
6772 		/* get the software provider for this mechanism */
6773 		if ((error = dprov_get_sw_prov(mechp, &pd,
6774 		    &mech.cm_type)) != CRYPTO_SUCCESS)
6775 			break;
6776 
6777 		wrapped_key = taskq_req->dr_key_req.kr_wrapped_key;
6778 		wrapped_key_len = *taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
6779 		ciphertext.cd_format = CRYPTO_DATA_RAW;
6780 		ciphertext.cd_offset = 0;
6781 		ciphertext.cd_length = wrapped_key_len;
6782 		ciphertext.cd_raw.iov_base = (char *)wrapped_key;
6783 		ciphertext.cd_raw.iov_len = wrapped_key_len;
6784 		ciphertext.cd_miscdata = NULL;
6785 
6786 		/*
6787 		 * Plaintext length is less than or equal to
6788 		 * the length of the ciphertext.
6789 		 */
6790 		plaintext_buf = kmem_alloc(wrapped_key_len, KM_SLEEP);
6791 		plaintext.cd_format = CRYPTO_DATA_RAW;
6792 		plaintext.cd_offset = 0;
6793 		plaintext.cd_length = wrapped_key_len;
6794 		plaintext.cd_raw.iov_base = plaintext_buf;
6795 		plaintext.cd_raw.iov_len = wrapped_key_len;
6796 		plaintext.cd_miscdata = NULL;
6797 
6798 		error = crypto_decrypt_prov(&mech, &ciphertext, keyp,
6799 		    NULL, &plaintext, NULL, pd, 0);
6800 
6801 		KCF_PROV_REFRELE(pd);
6802 
6803 		if (error != CRYPTO_SUCCESS)
6804 			goto free_unwrapped_key;
6805 
6806 		error = dprov_create_object_from_template(softc, session,
6807 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
6808 
6809 		if (error != CRYPTO_SUCCESS)
6810 			goto free_unwrapped_key;
6811 
6812 		switch (class) {
6813 		case DPROV_CKO_SECRET_KEY:
6814 			unwrapped_key.oa_type = DPROV_CKA_VALUE;
6815 			unwrapped_key.oa_value_len = plaintext.cd_length;
6816 			unwrapped_key.oa_value = plaintext_buf;
6817 			break;
6818 		case DPROV_CKO_PRIVATE_KEY:
6819 			/*
6820 			 * PKCS#11 says that ASN.1 should be used to encode
6821 			 * specific attributes before encrypting the blob.
6822 			 * We only encrypt the private exponent for the
6823 			 * purpose of testing.
6824 			 */
6825 			unwrapped_key.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
6826 			unwrapped_key.oa_value_len = plaintext.cd_length;
6827 			unwrapped_key.oa_value = plaintext_buf;
6828 			break;
6829 		default:
6830 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6831 			goto free_unwrapped_key;
6832 		}
6833 
6834 		if ((error = dprov_object_set_attr(session, *object_id_ptr,
6835 		    &unwrapped_key, 1, B_FALSE)) == CRYPTO_SUCCESS)
6836 			break;	/* don't free the unwrapped key */
6837 
6838 		/* failure */
6839 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
6840 		break;
6841 
6842 free_unwrapped_key:
6843 		bzero(plaintext_buf, wrapped_key_len);
6844 		kmem_free(plaintext_buf, wrapped_key_len);
6845 		break;
6846 	}
6847 
6848 	case DPROV_REQ_KEY_DERIVE: {
6849 		crypto_mechanism_t digest_mech, *mechp;
6850 		crypto_key_t key, *base_keyp;
6851 		crypto_object_id_t *object_id_ptr;
6852 		crypto_data_t data;
6853 		crypto_data_t digest;
6854 		size_t hash_size;
6855 		char *digest_buf;
6856 		crypto_object_attribute_t derived_key;
6857 		crypto_object_attribute_t *template;
6858 		uint_t attribute_count;
6859 		ulong_t key_type;
6860 		void *value;
6861 		size_t value_len = 0;
6862 
6863 		error = CRYPTO_SUCCESS;
6864 
6865 		template = taskq_req->dr_key_req.kr_template;
6866 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
6867 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
6868 
6869 		/* required */
6870 		if (dprov_get_template_attr_ulong(template, attribute_count,
6871 		    DPROV_CKA_KEY_TYPE, &key_type) != CRYPTO_SUCCESS) {
6872 			error = CRYPTO_TEMPLATE_INCOMPLETE;
6873 			break;
6874 		}
6875 
6876 		mechp = taskq_req->dr_key_req.kr_mechanism;
6877 		/* structure assignment */
6878 		digest_mech = *mechp;
6879 
6880 		switch (digest_mech.cm_type) {
6881 		case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:
6882 			hash_size = SHA1_DIGEST_LEN;
6883 			digest_mech.cm_type = SHA1_MECH_INFO_TYPE;
6884 			break;
6885 
6886 		case MD5_KEY_DERIVATION_MECH_INFO_TYPE:
6887 			hash_size = MD5_DIGEST_LEN;
6888 			digest_mech.cm_type = MD5_MECH_INFO_TYPE;
6889 			break;
6890 
6891 		default:
6892 			error = CRYPTO_MECHANISM_INVALID;
6893 		}
6894 
6895 		if (error != CRYPTO_SUCCESS)
6896 			break;
6897 
6898 		/* CKA_VALUE is optional */
6899 		(void) dprov_get_template_attr_array(template, attribute_count,
6900 		    DPROV_CKA_VALUE, &value, &value_len);
6901 
6902 		/* check for inconsistent value length */
6903 		switch (key_type) {
6904 		case DPROV_CKK_GENERIC_SECRET:
6905 			if (value_len > 0) {
6906 				if (value_len > hash_size)
6907 					error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6908 			} else {
6909 				value_len = hash_size;
6910 			}
6911 			break;
6912 
6913 		case DPROV_CKK_RC4:
6914 		case DPROV_CKK_AES:
6915 			if (value_len == 0 ||
6916 			    value_len > hash_size) {
6917 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6918 			}
6919 			break;
6920 
6921 		case DPROV_CKK_DES:
6922 			if (value_len > 0 &&
6923 			    value_len != DES_KEY_LEN) {
6924 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6925 			}
6926 			value_len = DES_KEY_LEN;
6927 			break;
6928 
6929 		case DPROV_CKK_DES3:
6930 			if (value_len > 0 &&
6931 			    value_len != DES3_KEY_LEN) {
6932 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6933 			}
6934 			value_len = DES3_KEY_LEN;
6935 			break;
6936 
6937 		default:
6938 			error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6939 			break;
6940 		}
6941 
6942 		if (error != CRYPTO_SUCCESS)
6943 			break;
6944 
6945 		/* get the software provider for this mechanism */
6946 		if ((error = dprov_get_sw_prov(&digest_mech, &pd,
6947 		    &digest_mech.cm_type)) != CRYPTO_SUCCESS)
6948 			break;
6949 
6950 		/* get the base key */
6951 		error = dprov_key_value_secret(softc, session_id,
6952 		    taskq_req->dr_type, taskq_req->dr_key_req.kr_key, &key);
6953 		if (error != CRYPTO_SUCCESS)
6954 			break;
6955 
6956 		base_keyp = &key;
6957 
6958 		data.cd_format = CRYPTO_DATA_RAW;
6959 		data.cd_offset = 0;
6960 		data.cd_length = CRYPTO_BITS2BYTES(base_keyp->ck_length);
6961 		data.cd_raw.iov_base = base_keyp->ck_data;
6962 		data.cd_raw.iov_len = data.cd_length;
6963 
6964 		digest_buf = kmem_alloc(hash_size, KM_SLEEP);
6965 		digest.cd_format = CRYPTO_DATA_RAW;
6966 		digest.cd_offset = 0;
6967 		digest.cd_length = hash_size;
6968 		digest.cd_raw.iov_base = digest_buf;
6969 		digest.cd_raw.iov_len = hash_size;
6970 
6971 		error = crypto_digest_prov(&digest_mech, &data,
6972 		    &digest, NULL, pd, 0);
6973 
6974 		KCF_PROV_REFRELE(pd);
6975 
6976 		if (error != CRYPTO_SUCCESS)
6977 			goto free_derived_key;
6978 
6979 		error = dprov_create_object_from_template(softc, session,
6980 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
6981 
6982 		if (error != CRYPTO_SUCCESS)
6983 			goto free_derived_key;
6984 
6985 		derived_key.oa_type = DPROV_CKA_VALUE;
6986 		derived_key.oa_value = digest_buf;
6987 		derived_key.oa_value_len = value_len;
6988 
6989 		error = dprov_object_set_attr(session, *object_id_ptr,
6990 		    &derived_key, 1, B_FALSE);
6991 
6992 		if (error != CRYPTO_SUCCESS) {
6993 			(void) dprov_destroy_object(softc, session,
6994 			    *object_id_ptr);
6995 		}
6996 
6997 free_derived_key:
6998 		bzero(digest_buf, hash_size);
6999 		kmem_free(digest_buf, hash_size);
7000 	}
7001 	}
7002 
7003 	mutex_exit(&softc->ds_lock);
7004 	dprov_op_done(taskq_req, error);
7005 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: end\n", instance));
7006 }
7007 
7008 
7009 /*
7010  * taskq dispatcher function for provider management operations.
7011  */
7012 static void
7013 dprov_mgmt_task(dprov_req_t *taskq_req)
7014 {
7015 	dprov_state_t *softc;
7016 	/* LINTED E_FUNC_SET_NOT_USED */
7017 	int instance;
7018 	int error = CRYPTO_NOT_SUPPORTED;
7019 
7020 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
7021 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: started\n", instance));
7022 
7023 	mutex_enter(&softc->ds_lock);
7024 
7025 	switch (taskq_req->dr_type) {
7026 	case DPROV_REQ_MGMT_EXTINFO: {
7027 		crypto_provider_ext_info_t *ext_info =
7028 		    taskq_req->dr_mgmt_req.mr_ext_info;
7029 
7030 		(void) memset(ext_info->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
7031 		if (!softc->ds_token_initialized) {
7032 			bcopy("(not initialized)", ext_info->ei_label,
7033 			    strlen("(not initialized)"));
7034 		} else {
7035 			bcopy(softc->ds_label, ext_info->ei_label,
7036 			    CRYPTO_EXT_SIZE_LABEL);
7037 		}
7038 
7039 		bcopy(DPROV_MANUFACTURER, ext_info->ei_manufacturerID,
7040 		    CRYPTO_EXT_SIZE_MANUF);
7041 		bcopy(DPROV_MODEL, ext_info->ei_model, CRYPTO_EXT_SIZE_MODEL);
7042 
7043 		(void) snprintf((char *)ext_info->ei_serial_number, 16, "%d%s",
7044 		    instance, DPROV_ALLSPACES);
7045 		/* PKCS#11 blank padding */
7046 		ext_info->ei_serial_number[15] = ' ';
7047 		ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
7048 		ext_info->ei_max_pin_len = (ulong_t)DPROV_MAX_PIN_LEN;
7049 		ext_info->ei_min_pin_len = 1;
7050 		ext_info->ei_total_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
7051 		ext_info->ei_free_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
7052 		ext_info->ei_total_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
7053 		ext_info->ei_free_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
7054 		ext_info->ei_hardware_version.cv_major = 1;
7055 		ext_info->ei_hardware_version.cv_minor = 0;
7056 		ext_info->ei_firmware_version.cv_major = 1;
7057 		ext_info->ei_firmware_version.cv_minor = 0;
7058 
7059 		ext_info->ei_flags = CRYPTO_EXTF_RNG |
7060 		    CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
7061 		if (softc->ds_user_pin_set)
7062 			ext_info->ei_flags |= CRYPTO_EXTF_USER_PIN_INITIALIZED;
7063 		if (softc->ds_token_initialized)
7064 			ext_info->ei_flags |= CRYPTO_EXTF_TOKEN_INITIALIZED;
7065 
7066 		error = CRYPTO_SUCCESS;
7067 		break;
7068 	}
7069 	case DPROV_REQ_MGMT_INITTOKEN: {
7070 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
7071 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
7072 		char *label = taskq_req->dr_mgmt_req.mr_label;
7073 
7074 		/* cannot initialize token when a session is open */
7075 		if (softc->ds_sessions_count > 0) {
7076 			error = CRYPTO_SESSION_EXISTS;
7077 			break;
7078 		}
7079 
7080 		/* check PIN length */
7081 		if (pin_len > DPROV_MAX_PIN_LEN) {
7082 			error = CRYPTO_PIN_LEN_RANGE;
7083 			break;
7084 		}
7085 
7086 		/* check PIN */
7087 		if (pin == NULL) {
7088 			error = CRYPTO_PIN_INVALID;
7089 			break;
7090 		}
7091 
7092 		/*
7093 		 * If the token has already been initialized, need
7094 		 * to validate supplied PIN.
7095 		 */
7096 		if (softc->ds_token_initialized &&
7097 		    (softc->ds_so_pin_len != pin_len ||
7098 		    strncmp(softc->ds_so_pin, pin, pin_len) != 0)) {
7099 			/* invalid SO PIN */
7100 			error = CRYPTO_PIN_INCORRECT;
7101 			break;
7102 		}
7103 
7104 		/* set label */
7105 		bcopy(label, softc->ds_label, CRYPTO_EXT_SIZE_LABEL);
7106 
7107 		/* set new SO PIN, update state */
7108 		bcopy(pin, softc->ds_so_pin, pin_len);
7109 		softc->ds_so_pin_len = pin_len;
7110 		softc->ds_token_initialized = B_TRUE;
7111 		softc->ds_user_pin_set = B_FALSE;
7112 
7113 		error = CRYPTO_SUCCESS;
7114 		break;
7115 	}
7116 	case DPROV_REQ_MGMT_INITPIN: {
7117 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
7118 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
7119 		crypto_session_id_t session_id =
7120 		    taskq_req->dr_mgmt_req.mr_session_id;
7121 
7122 		/* check session id */
7123 		if (softc->ds_sessions[session_id] == NULL) {
7124 			error = CRYPTO_SESSION_HANDLE_INVALID;
7125 			break;
7126 		}
7127 
7128 		/* fail if not logged in as SO */
7129 		if (softc->ds_sessions[session_id]->ds_state !=
7130 		    DPROV_SESSION_STATE_SO) {
7131 			error = CRYPTO_USER_NOT_LOGGED_IN;
7132 			break;
7133 		}
7134 
7135 		/* check PIN length */
7136 		if (pin_len > DPROV_MAX_PIN_LEN) {
7137 			error = CRYPTO_PIN_LEN_RANGE;
7138 			break;
7139 		}
7140 
7141 		/* check PIN */
7142 		if (pin == NULL) {
7143 			error = CRYPTO_PIN_INVALID;
7144 			break;
7145 		}
7146 
7147 		/* set new normal user PIN */
7148 		bcopy(pin, softc->ds_user_pin, pin_len);
7149 		softc->ds_user_pin_len = pin_len;
7150 		softc->ds_user_pin_set = B_TRUE;
7151 
7152 		error = CRYPTO_SUCCESS;
7153 		break;
7154 	}
7155 	case DPROV_REQ_MGMT_SETPIN: {
7156 		char *new_pin = taskq_req->dr_mgmt_req.mr_pin;
7157 		size_t new_pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
7158 		char *old_pin = taskq_req->dr_mgmt_req.mr_old_pin;
7159 		size_t old_pin_len = taskq_req->dr_mgmt_req.mr_old_pin_len;
7160 		crypto_session_id_t session_id =
7161 		    taskq_req->dr_mgmt_req.mr_session_id;
7162 
7163 		/* check session id */
7164 		if (softc->ds_sessions[session_id] == NULL) {
7165 			error = CRYPTO_SESSION_HANDLE_INVALID;
7166 			break;
7167 		}
7168 
7169 		/* check PIN length */
7170 		if (old_pin_len > DPROV_MAX_PIN_LEN ||
7171 		    new_pin_len > DPROV_MAX_PIN_LEN) {
7172 			error = CRYPTO_PIN_LEN_RANGE;
7173 			break;
7174 		}
7175 
7176 		/* check PIN */
7177 		if (old_pin == NULL || new_pin == NULL) {
7178 			error = CRYPTO_PIN_INVALID;
7179 			break;
7180 		}
7181 
7182 		/* check user PIN state */
7183 		if (!softc->ds_user_pin_set) {
7184 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
7185 			break;
7186 		}
7187 
7188 		/*
7189 		 * If the token has already been initialized, need
7190 		 * to validate supplied PIN.
7191 		 */
7192 		if (softc->ds_user_pin_len != old_pin_len ||
7193 		    strncmp(softc->ds_user_pin, old_pin, old_pin_len) != 0) {
7194 			/* invalid SO PIN */
7195 			error = CRYPTO_PIN_INCORRECT;
7196 			break;
7197 		}
7198 
7199 		/* set new PIN */
7200 		bcopy(new_pin, softc->ds_user_pin, new_pin_len);
7201 		softc->ds_user_pin_len = new_pin_len;
7202 
7203 		error = CRYPTO_SUCCESS;
7204 		break;
7205 	}
7206 	}
7207 
7208 	mutex_exit(&softc->ds_lock);
7209 	dprov_op_done(taskq_req, error);
7210 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: end\n", instance));
7211 }
7212 
7213 /*
7214  * Returns in the location pointed to by pd a pointer to the descriptor
7215  * for the software provider for the specified mechanism.
7216  * The provider descriptor is returned held. Returns one of the CRYPTO_
7217  * error codes on failure, CRYPTO_SUCCESS on success.
7218  */
7219 static int
7220 dprov_get_sw_prov(crypto_mechanism_t *mech, kcf_provider_desc_t **pd,
7221     crypto_mech_type_t *provider_mech_type)
7222 {
7223 	crypto_mech_type_t kcf_mech_type = CRYPTO_MECH_INVALID;
7224 	int i, rv;
7225 
7226 	/* lookup the KCF mech type associated with our mech type */
7227 	for (i = 0; i < sizeof (dprov_mech_info_tab)/
7228 	    sizeof (crypto_mech_info_t); i++) {
7229 		if (mech->cm_type == dprov_mech_info_tab[i].cm_mech_number) {
7230 			kcf_mech_type = crypto_mech2id_common(
7231 				dprov_mech_info_tab[i].cm_mech_name, B_TRUE);
7232 		}
7233 	}
7234 
7235 	rv = kcf_get_sw_prov(kcf_mech_type, pd, B_TRUE);
7236 	if (rv == CRYPTO_SUCCESS)
7237 		*provider_mech_type = kcf_mech_type;
7238 
7239 	return (rv);
7240 }
7241 
7242 /*
7243  * Object management helper functions.
7244  */
7245 
7246 /*
7247  * Given a crypto_key_t, return whether the key can be used or not
7248  * for the specified request. The attributes used here are defined
7249  * in table 42 of the PKCS#11 spec (Common secret key attributes).
7250  */
7251 static int
7252 dprov_key_can_use(dprov_object_t *object, dprov_req_type_t req_type)
7253 {
7254 	boolean_t ret = 0;
7255 	int rv = CRYPTO_SUCCESS;
7256 
7257 	/* check if object is allowed for specified operation */
7258 	switch (req_type) {
7259 	case DPROV_REQ_ENCRYPT_INIT:
7260 	case DPROV_REQ_ENCRYPT_ATOMIC:
7261 		rv = dprov_get_object_attr_boolean(object,
7262 		    DPROV_CKA_ENCRYPT, &ret);
7263 		break;
7264 	case DPROV_REQ_DECRYPT_INIT:
7265 	case DPROV_REQ_DECRYPT_ATOMIC:
7266 		rv = dprov_get_object_attr_boolean(object,
7267 		    DPROV_CKA_DECRYPT, &ret);
7268 		break;
7269 	case DPROV_REQ_SIGN_INIT:
7270 	case DPROV_REQ_SIGN_ATOMIC:
7271 	case DPROV_REQ_MAC_INIT:
7272 	case DPROV_REQ_MAC_ATOMIC:
7273 		rv = dprov_get_object_attr_boolean(object,
7274 		    DPROV_CKA_SIGN, &ret);
7275 		break;
7276 	case DPROV_REQ_SIGN_RECOVER_INIT:
7277 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
7278 		rv = dprov_get_object_attr_boolean(object,
7279 		    DPROV_CKA_SIGN_RECOVER, &ret);
7280 		break;
7281 	case DPROV_REQ_VERIFY_INIT:
7282 	case DPROV_REQ_VERIFY_ATOMIC:
7283 		rv = dprov_get_object_attr_boolean(object,
7284 		    DPROV_CKA_VERIFY, &ret);
7285 		break;
7286 	case DPROV_REQ_VERIFY_RECOVER_INIT:
7287 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
7288 		rv = dprov_get_object_attr_boolean(object,
7289 		    DPROV_CKA_VERIFY_RECOVER, &ret);
7290 		break;
7291 	case DPROV_REQ_KEY_WRAP:
7292 		rv = dprov_get_object_attr_boolean(object,
7293 		    DPROV_CKA_WRAP, &ret);
7294 		break;
7295 	case DPROV_REQ_KEY_UNWRAP:
7296 		rv = dprov_get_object_attr_boolean(object,
7297 		    DPROV_CKA_UNWRAP, &ret);
7298 		break;
7299 	case DPROV_REQ_DIGEST_KEY:
7300 		/*
7301 		 * There is no attribute to check for; therefore,
7302 		 * any secret key can be used.
7303 		 */
7304 		ret = B_TRUE;
7305 		rv = CRYPTO_SUCCESS;
7306 		break;
7307 	case DPROV_REQ_KEY_DERIVE:
7308 		rv = dprov_get_object_attr_boolean(object,
7309 		    DPROV_CKA_DERIVE, &ret);
7310 		break;
7311 	}
7312 
7313 	if (rv != CRYPTO_SUCCESS || !ret)
7314 		return (CRYPTO_KEY_FUNCTION_NOT_PERMITTED);
7315 
7316 	return (CRYPTO_SUCCESS);
7317 }
7318 
7319 /*
7320  * Given a crypto_key_t corresponding to a secret key (i.e. for
7321  * use with symmetric crypto algorithms) specified in raw format, by
7322  * attribute, or by reference, initialize the ck_data and ck_length
7323  * fields of the ret_key argument so that they specify the key value
7324  * and length.
7325  *
7326  * For a key by value, this function uess the ck_data and ck_length,
7327  * for a key by reference, it looks up the corresponding object and
7328  * returns the appropriate attribute. For a key by attribute, it returns
7329  * the appropriate attribute. The attributes used are CKA_VALUE to retrieve
7330  * the value of the key, and CKA_VALUE_LEN to retrieve its length in bytes.
7331  */
7332 static int
7333 dprov_key_value_secret(dprov_state_t *softc, crypto_session_id_t session_id,
7334     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
7335 {
7336 	ulong_t key_type;
7337 	int ret = CRYPTO_SUCCESS;
7338 
7339 	ret_key->ck_format = CRYPTO_KEY_RAW;
7340 
7341 	switch (key->ck_format) {
7342 
7343 	case CRYPTO_KEY_RAW:
7344 		ret_key->ck_data = key->ck_data;
7345 		ret_key->ck_length = key->ck_length;
7346 		break;
7347 
7348 	case CRYPTO_KEY_ATTR_LIST: {
7349 		void *value;
7350 		size_t len, value_len;
7351 
7352 		if ((ret = dprov_get_key_attr_ulong(key, DPROV_CKA_KEY_TYPE,
7353 		    &key_type)) != CRYPTO_SUCCESS)
7354 			break;
7355 
7356 		if ((ret = dprov_get_key_attr_array(key, DPROV_CKA_VALUE,
7357 		    &value, &len)) != CRYPTO_SUCCESS)
7358 			break;
7359 
7360 		/*
7361 		 * The length of the array is expressed in bytes.
7362 		 * Convert to bits now since that's how keys are measured.
7363 		 */
7364 		len  = len << 3;
7365 
7366 		/* optional */
7367 		if ((dprov_get_key_attr_ulong(key, DPROV_CKA_VALUE_LEN,
7368 		    &value_len)) == CRYPTO_SUCCESS) {
7369 			len = value_len;
7370 		}
7371 
7372 		ret_key->ck_data = value;
7373 		ret_key->ck_length = (uint_t)len;
7374 
7375 		break;
7376 	}
7377 
7378 	case CRYPTO_KEY_REFERENCE: {
7379 		dprov_object_t *object;
7380 		void *value;
7381 		size_t len, value_len;
7382 
7383 		/* check session id */
7384 		if (softc->ds_sessions[session_id] == NULL) {
7385 			ret = CRYPTO_SESSION_HANDLE_INVALID;
7386 			break;
7387 		}
7388 
7389 		if (key->ck_obj_id >= DPROV_MAX_OBJECTS) {
7390 			ret = CRYPTO_KEY_HANDLE_INVALID;
7391 			goto bail;
7392 		}
7393 
7394 		/* check if object id specified by key is valid */
7395 		object = softc->ds_sessions[session_id]->
7396 		    ds_objects[key->ck_obj_id];
7397 		if (object == NULL) {
7398 			ret = CRYPTO_KEY_HANDLE_INVALID;
7399 			goto bail;
7400 		}
7401 
7402 		/* check if object can be used for operation */
7403 		if ((ret = dprov_key_can_use(object, req_type)) !=
7404 		    CRYPTO_SUCCESS)
7405 			goto bail;
7406 
7407 		if ((ret = dprov_get_object_attr_ulong(object,
7408 		    DPROV_CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS)
7409 			goto bail;
7410 
7411 		if ((ret = dprov_get_object_attr_array(object,
7412 		    DPROV_CKA_VALUE, &value, &len)) != CRYPTO_SUCCESS)
7413 			goto bail;
7414 
7415 		/* optional */
7416 		if ((dprov_get_object_attr_ulong(object, DPROV_CKA_VALUE_LEN,
7417 		    &value_len)) == CRYPTO_SUCCESS) {
7418 			len = value_len;
7419 		}
7420 
7421 		/*
7422 		 * The length of attributes are in bytes.
7423 		 * Convert to bits now since that's how keys are measured.
7424 		 */
7425 		len  = len << 3;
7426 
7427 		ret_key->ck_data = value;
7428 		ret_key->ck_length = (uint_t)len;
7429 bail:
7430 		break;
7431 	}
7432 
7433 	default:
7434 		ret = CRYPTO_ARGUMENTS_BAD;
7435 		break;
7436 	}
7437 
7438 	return (ret);
7439 }
7440 
7441 /*
7442  * Get the attribute list for the specified asymmetric key.
7443  */
7444 static int
7445 dprov_key_attr_asymmetric(dprov_state_t *softc, crypto_session_id_t session_id,
7446     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
7447 {
7448 	int ret = CRYPTO_SUCCESS;
7449 
7450 	ret_key->ck_format = CRYPTO_KEY_ATTR_LIST;
7451 
7452 	switch (key->ck_format) {
7453 
7454 	case CRYPTO_KEY_ATTR_LIST:
7455 		ret_key->ck_attrs = key->ck_attrs;
7456 		ret_key->ck_count = key->ck_count;
7457 		break;
7458 
7459 	case CRYPTO_KEY_REFERENCE: {
7460 		dprov_object_t *object;
7461 
7462 		/* check session id */
7463 		if (softc->ds_sessions[session_id] == NULL) {
7464 			ret = CRYPTO_SESSION_HANDLE_INVALID;
7465 			break;
7466 		}
7467 
7468 		/* check if object id specified by key is valid */
7469 		object = softc->ds_sessions[session_id]->
7470 		    ds_objects[key->ck_obj_id];
7471 		if (object == NULL) {
7472 			ret = CRYPTO_KEY_HANDLE_INVALID;
7473 			break;
7474 		}
7475 
7476 		/* check if object can be used for operation */
7477 		if ((ret = dprov_key_can_use(object, req_type)) !=
7478 		    CRYPTO_SUCCESS)
7479 			break;
7480 
7481 		ret_key->ck_attrs = object->do_attr;
7482 		ret_key->ck_count = DPROV_MAX_ATTR;
7483 		break;
7484 	}
7485 
7486 	default:
7487 		ret = CRYPTO_ARGUMENTS_BAD;
7488 	}
7489 
7490 	return (ret);
7491 }
7492 
7493 /*
7494  * Return the index of an attribute of specified type found in
7495  * the specified array of attributes. If the attribute cannot
7496  * found, return -1.
7497  */
7498 static int
7499 dprov_find_attr(crypto_object_attribute_t *attr, uint_t nattr,
7500     uint64_t attr_type)
7501 {
7502 	int i;
7503 
7504 	for (i = 0; i < nattr; i++)
7505 		if (attr[i].oa_value != NULL &&
7506 		    attr[i].oa_type == attr_type)
7507 			return (i);
7508 
7509 	return (-1);
7510 }
7511 
7512 /*
7513  * Given the given object template and session, return whether
7514  * an object can be created from that template according to the
7515  * following rules:
7516  * - private objects can be created only by a logged-in user
7517  */
7518 static int
7519 dprov_template_can_create(dprov_session_t *session,
7520     crypto_object_attribute_t *template, uint_t nattr,
7521     boolean_t check_for_secret)
7522 {
7523 	boolean_t is_private = B_FALSE;
7524 	ulong_t key_type, class;
7525 	int error;
7526 
7527 	/* check CKA_PRIVATE attribute value */
7528 	error = dprov_get_template_attr_boolean(template, nattr,
7529 	    DPROV_CKA_PRIVATE, &is_private);
7530 	if (error == CRYPTO_SUCCESS && is_private) {
7531 		/* it's a private object */
7532 		if (session->ds_state != DPROV_SESSION_STATE_USER) {
7533 			/*
7534 			 * Cannot create private object with SO or public
7535 			 * sessions.
7536 			 */
7537 			return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
7538 		}
7539 	}
7540 
7541 	/* all objects must have an object class attribute */
7542 	if (dprov_get_template_attr_ulong(template, nattr, DPROV_CKA_CLASS,
7543 	    &class) != CRYPTO_SUCCESS) {
7544 		return (CRYPTO_TEMPLATE_INCOMPLETE);
7545 	}
7546 
7547 	/* key objects must have a key type attribute */
7548 	if (class == DPROV_CKO_SECRET_KEY ||
7549 	    class == DPROV_CKO_PUBLIC_KEY ||
7550 	    class == DPROV_CKO_PRIVATE_KEY) {
7551 		if (!dprov_template_attr_present(template, nattr,
7552 		    DPROV_CKA_KEY_TYPE)) {
7553 			return (CRYPTO_TEMPLATE_INCOMPLETE);
7554 		}
7555 	}
7556 
7557 	/* check for RSA public key attributes that must be present */
7558 	if (class == DPROV_CKO_PUBLIC_KEY) {
7559 		if (dprov_get_template_attr_ulong(template, nattr,
7560 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
7561 			if (key_type == DPROV_CKK_RSA) {
7562 				if (!dprov_template_attr_present(template,
7563 				    nattr, DPROV_CKA_MODULUS) ||
7564 				    !dprov_template_attr_present(template,
7565 				    nattr, DPROV_CKA_PUBLIC_EXPONENT)) {
7566 					return (CRYPTO_TEMPLATE_INCOMPLETE);
7567 				}
7568 
7569 				/* these attributes should not be present */
7570 				if (dprov_template_attr_present(template, nattr,
7571 				    DPROV_CKA_MODULUS_BITS)) {
7572 					return (CRYPTO_TEMPLATE_INCONSISTENT);
7573 				}
7574 			}
7575 		}
7576 	}
7577 
7578 	/* check for RSA private key attributes that must be present */
7579 	if (class == DPROV_CKO_PRIVATE_KEY) {
7580 		if (dprov_get_template_attr_ulong(template, nattr,
7581 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
7582 			if (key_type == DPROV_CKK_RSA) {
7583 				if (!dprov_template_attr_present(template,
7584 				    nattr, DPROV_CKA_MODULUS))
7585 					return (CRYPTO_TEMPLATE_INCOMPLETE);
7586 
7587 				if (check_for_secret) {
7588 					if (!dprov_template_attr_present(
7589 					    template, nattr,
7590 					    DPROV_CKA_PRIVATE_EXPONENT))
7591 						return (
7592 						    CRYPTO_TEMPLATE_INCOMPLETE);
7593 				}
7594 			}
7595 		}
7596 	}
7597 
7598 	/* check for secret key attributes that must be present */
7599 	if (class == DPROV_CKO_SECRET_KEY) {
7600 		if (check_for_secret) {
7601 			if (!dprov_template_attr_present(template, nattr,
7602 			    DPROV_CKA_VALUE)) {
7603 				return (CRYPTO_TEMPLATE_INCOMPLETE);
7604 			}
7605 		}
7606 
7607 		/* these attributes should not be present */
7608 		if (dprov_template_attr_present(template, nattr,
7609 		    DPROV_CKA_VALUE_LEN)) {
7610 			return (CRYPTO_TEMPLATE_INCONSISTENT);
7611 		}
7612 	}
7613 
7614 	return (CRYPTO_SUCCESS);
7615 }
7616 
7617 
7618 /*
7619  * Create an object from the specified template. Checks whether the
7620  * object can be created according to its attributes and the state
7621  * of the session. The new session object id is returned. If the
7622  * object is a token object, it is added to the per-instance object
7623  * table as well.
7624  */
7625 static int
7626 dprov_create_object_from_template(dprov_state_t *softc,
7627     dprov_session_t *session, crypto_object_attribute_t *template,
7628     uint_t nattr, crypto_object_id_t *object_id, boolean_t check_for_secret,
7629     boolean_t force)
7630 {
7631 	dprov_object_t *object;
7632 	boolean_t is_token = B_FALSE;
7633 	boolean_t extractable_attribute_present = B_FALSE;
7634 	boolean_t private_attribute_present = B_FALSE;
7635 	uint_t i;
7636 	int error;
7637 	uint_t attr;
7638 	uint_t oattr;
7639 
7640 	if (nattr > DPROV_MAX_ATTR)
7641 		return (CRYPTO_HOST_MEMORY);
7642 
7643 	if (!force) {
7644 		/* verify that object can be created */
7645 		if ((error = dprov_template_can_create(session, template,
7646 		    nattr, check_for_secret)) != CRYPTO_SUCCESS)
7647 			return (error);
7648 	}
7649 
7650 	/* allocate new object */
7651 	object = kmem_zalloc(sizeof (dprov_object_t), KM_SLEEP);
7652 	if (object == NULL)
7653 		return (CRYPTO_HOST_MEMORY);
7654 
7655 	/* is it a token object? */
7656 	/* check CKA_TOKEN attribute value */
7657 	error = dprov_get_template_attr_boolean(template, nattr,
7658 	    DPROV_CKA_TOKEN, &is_token);
7659 	if (error == CRYPTO_SUCCESS && is_token) {
7660 		/* token object, add it to the per-instance object table */
7661 		for (i = 0; i < DPROV_MAX_OBJECTS; i++)
7662 			if (softc->ds_objects[i] == NULL)
7663 				break;
7664 		if (i == DPROV_MAX_OBJECTS)
7665 			/* no free slot */
7666 			return (CRYPTO_HOST_MEMORY);
7667 		softc->ds_objects[i] = object;
7668 		object->do_token_idx = i;
7669 		DPROV_OBJECT_REFHOLD(object);
7670 	}
7671 
7672 	/* add object to session object table */
7673 	for (i = 0; i < DPROV_MAX_OBJECTS; i++)
7674 		if (session->ds_objects[i] == NULL)
7675 			break;
7676 	if (i == DPROV_MAX_OBJECTS) {
7677 		/* no more session object slots */
7678 		DPROV_OBJECT_REFRELE(object);
7679 		return (CRYPTO_HOST_MEMORY);
7680 	}
7681 	session->ds_objects[i] = object;
7682 	DPROV_OBJECT_REFHOLD(object);
7683 	*object_id = i;
7684 
7685 	/* initialize object from template */
7686 	for (attr = 0, oattr = 0; attr < nattr; attr++) {
7687 		if (template[attr].oa_value == NULL)
7688 			continue;
7689 		object->do_attr[oattr].oa_type = template[attr].oa_type;
7690 		if (template[attr].oa_type == DPROV_CKA_EXTRACTABLE) {
7691 			extractable_attribute_present = B_TRUE;
7692 		} else if (template[attr].oa_type == DPROV_CKA_PRIVATE) {
7693 			private_attribute_present = B_TRUE;
7694 		}
7695 		object->do_attr[oattr].oa_value_len =
7696 		    template[attr].oa_value_len;
7697 
7698 		object->do_attr[oattr].oa_value = kmem_alloc(
7699 		    template[attr].oa_value_len, KM_SLEEP);
7700 		bcopy(template[attr].oa_value, object->do_attr[oattr].oa_value,
7701 		    template[attr].oa_value_len);
7702 		oattr++;
7703 	}
7704 
7705 	/* add boolean attributes that must be present */
7706 	if (extractable_attribute_present == B_FALSE) {
7707 		object->do_attr[oattr].oa_type = DPROV_CKA_EXTRACTABLE;
7708 		object->do_attr[oattr].oa_value_len = 1;
7709 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
7710 		object->do_attr[oattr].oa_value[0] = B_TRUE;
7711 		oattr++;
7712 	}
7713 
7714 	if (private_attribute_present == B_FALSE) {
7715 		object->do_attr[oattr].oa_type = DPROV_CKA_PRIVATE;
7716 		object->do_attr[oattr].oa_value_len = 1;
7717 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
7718 		object->do_attr[oattr].oa_value[0] = B_FALSE;
7719 		oattr++;
7720 	}
7721 
7722 	return (CRYPTO_SUCCESS);
7723 }
7724 
7725 /*
7726  * Checks whether or not the object matches the specified attributes.
7727  */
7728 static boolean_t
7729 dprov_attributes_match(dprov_object_t *object,
7730     crypto_object_attribute_t *template, uint_t nattr)
7731 {
7732 	int ta_idx;	/* template attribute index */
7733 	int oa_idx;	/* object attribute index */
7734 
7735 	for (ta_idx = 0; ta_idx < nattr; ta_idx++) {
7736 		/* no value for template attribute */
7737 		if (template[ta_idx].oa_value == NULL)
7738 			continue;
7739 
7740 		/* find attribute in object */
7741 		oa_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
7742 		    template[ta_idx].oa_type);
7743 
7744 		if (oa_idx == -1)
7745 			/* attribute not found in object */
7746 			return (B_FALSE);
7747 
7748 		if (template[ta_idx].oa_value_len !=
7749 		    object->do_attr[oa_idx].oa_value_len)
7750 			/* value length mismatch */
7751 			return (B_FALSE);
7752 
7753 		if (bcmp(template[ta_idx].oa_value,
7754 		    object->do_attr[oa_idx].oa_value,
7755 		    template[ta_idx].oa_value_len) != 0)
7756 			/* value mismatch */
7757 			return (B_FALSE);
7758 	}
7759 
7760 	return (B_TRUE);
7761 }
7762 
7763 /*
7764  * Destroy the object specified by its session and object id.
7765  */
7766 static int
7767 dprov_destroy_object(dprov_state_t *softc, dprov_session_t *session,
7768     crypto_object_id_t object_id)
7769 {
7770 	dprov_object_t *object;
7771 
7772 	if ((object = session->ds_objects[object_id]) == NULL)
7773 		return (CRYPTO_OBJECT_HANDLE_INVALID);
7774 
7775 	if (dprov_object_is_token(object)) {
7776 		object->do_destroyed = B_TRUE;
7777 		/* it's a token object, remove from per-instance table */
7778 		softc->ds_objects[object->do_token_idx] = NULL;
7779 		DPROV_OBJECT_REFRELE(object);
7780 	}
7781 
7782 	/* remove from session table */
7783 	session->ds_objects[object_id] = NULL;
7784 	DPROV_OBJECT_REFRELE(object);
7785 	return (CRYPTO_SUCCESS);
7786 }
7787 
7788 static int
7789 dprov_object_can_modify(dprov_object_t *object,
7790     crypto_object_attribute_t *template, uint_t nattr)
7791 {
7792 	ulong_t object_class;
7793 
7794 	/* all objects should have an object class attribute */
7795 	if (dprov_get_object_attr_ulong(object, DPROV_CKA_CLASS,
7796 	    &object_class) != CRYPTO_SUCCESS) {
7797 		return (CRYPTO_SUCCESS);
7798 	}
7799 
7800 	if (object_class == DPROV_CKO_SECRET_KEY ||
7801 	    object_class == DPROV_CKO_PUBLIC_KEY ||
7802 	    object_class == DPROV_CKO_PRIVATE_KEY) {
7803 		if (dprov_template_attr_present(template, nattr,
7804 		    DPROV_CKA_CLASS) ||
7805 		    dprov_template_attr_present(template, nattr,
7806 		    DPROV_CKA_KEY_TYPE))
7807 			return (CRYPTO_TEMPLATE_INCONSISTENT);
7808 	}
7809 
7810 	switch (object_class) {
7811 	case DPROV_CKO_SECRET_KEY:
7812 		if (dprov_template_attr_present(template, nattr,
7813 		    DPROV_CKA_VALUE))
7814 			return (CRYPTO_TEMPLATE_INCONSISTENT);
7815 		break;
7816 
7817 	case DPROV_CKO_PUBLIC_KEY:
7818 		if (dprov_template_attr_present(template, nattr,
7819 		    DPROV_CKA_MODULUS) ||
7820 		    dprov_template_attr_present(template, nattr,
7821 		    DPROV_CKA_PUBLIC_EXPONENT))
7822 			return (CRYPTO_TEMPLATE_INCONSISTENT);
7823 		break;
7824 
7825 	case DPROV_CKO_PRIVATE_KEY:
7826 		if (dprov_template_attr_present(template, nattr,
7827 		    DPROV_CKA_MODULUS) ||
7828 		    dprov_template_attr_present(template, nattr,
7829 		    DPROV_CKA_PRIVATE_EXPONENT))
7830 			return (CRYPTO_TEMPLATE_INCONSISTENT);
7831 		break;
7832 
7833 	default:
7834 		return (CRYPTO_SUCCESS);
7835 	}
7836 
7837 	return (CRYPTO_SUCCESS);
7838 }
7839 
7840 /*
7841  * Set the attributes specified by the template in the specified object,
7842  * replacing existing ones if needed.
7843  */
7844 static int
7845 dprov_object_set_attr(dprov_session_t *session, crypto_object_id_t object_id,
7846     crypto_object_attribute_t *template, uint_t nattr,
7847     boolean_t check_attributes)
7848 {
7849 	dprov_object_t *object;
7850 	uint_t i, j;
7851 	int error;
7852 
7853 	if ((object = session->ds_objects[object_id]) == NULL)
7854 		return (CRYPTO_OBJECT_HANDLE_INVALID);
7855 
7856 	if (check_attributes) {
7857 		/* verify that attributes in the template can be modified */
7858 		if ((error = dprov_object_can_modify(object, template, nattr))
7859 		    != CRYPTO_SUCCESS)
7860 			return (error);
7861 	}
7862 
7863 	/* go through the attributes specified in the template */
7864 	for (i = 0; i < nattr; i++) {
7865 		if (template[i].oa_value == NULL)
7866 			continue;
7867 
7868 		/* find attribute in object */
7869 		j = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
7870 				    template[i].oa_type);
7871 
7872 		if (j != -1) {
7873 			/* attribute already exists, free old value */
7874 			kmem_free(object->do_attr[j].oa_value,
7875 			    object->do_attr[j].oa_value_len);
7876 		} else {
7877 			/* attribute does not exist, create it */
7878 			for (j = 0; j < DPROV_MAX_ATTR; j++)
7879 				if (object->do_attr[j].oa_value == NULL)
7880 					break;
7881 			if (j == DPROV_MAX_ATTR)
7882 				/* ran out of attribute slots */
7883 				return (CRYPTO_HOST_MEMORY);
7884 		}
7885 
7886 		/* set object attribute value */
7887 		object->do_attr[j].oa_value =
7888 		    kmem_alloc(template[i].oa_value_len, KM_SLEEP);
7889 		bcopy(template[i].oa_value, object->do_attr[j].oa_value,
7890 		    template[i].oa_value_len);
7891 		object->do_attr[j].oa_value_len =
7892 		    template[i].oa_value_len;
7893 
7894 		/* and the type */
7895 		object->do_attr[j].oa_type = template[i].oa_type;
7896 	}
7897 
7898 	return (CRYPTO_SUCCESS);
7899 }
7900 
7901 
7902 /*
7903  * Free the specified object.
7904  */
7905 static void
7906 dprov_free_object(dprov_object_t *object)
7907 {
7908 	int i;
7909 
7910 	/* free the object attributes values */
7911 	for (i = 0; i < DPROV_MAX_ATTR; i++)
7912 		if (object->do_attr[i].oa_value != NULL)
7913 			kmem_free(object->do_attr[i].oa_value,
7914 			    object->do_attr[i].oa_value_len);
7915 
7916 	/* free the object */
7917 	kmem_free(object, sizeof (dprov_object_t));
7918 }
7919 
7920 /*
7921  * Checks whether the specified object is a private or public object.
7922  */
7923 static boolean_t
7924 dprov_object_is_private(dprov_object_t *object)
7925 {
7926 	boolean_t ret;
7927 	int err;
7928 
7929 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_PRIVATE, &ret);
7930 
7931 	if (err != CRYPTO_SUCCESS)
7932 		/* by default, CKA_PRIVATE is false */
7933 		ret = B_FALSE;
7934 
7935 	return (ret);
7936 }
7937 
7938 /*
7939  * Checks whether the specified object is a token or session object.
7940  */
7941 static boolean_t
7942 dprov_object_is_token(dprov_object_t *object)
7943 {
7944 	boolean_t ret;
7945 	int err;
7946 
7947 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_TOKEN, &ret);
7948 
7949 	if (err != CRYPTO_SUCCESS)
7950 		/* by default, CKA_TOKEN is false */
7951 		ret = B_FALSE;
7952 
7953 	return (ret);
7954 }
7955 
7956 /*
7957  * Common function used by the dprov_get_object_attr_*() family of
7958  * functions. Returns the value of the specified attribute of specified
7959  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
7960  * if the length of the attribute does not match the specified length,
7961  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
7962  */
7963 static int
7964 dprov_get_object_attr_scalar_common(dprov_object_t *object, uint64_t attr_type,
7965 				    void *value, size_t value_len)
7966 {
7967 	int attr_idx;
7968 	size_t oa_value_len;
7969 	size_t offset = 0;
7970 
7971 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
7972 	    attr_type)) == -1)
7973 		return (CRYPTO_ARGUMENTS_BAD);
7974 
7975 	oa_value_len = object->do_attr[attr_idx].oa_value_len;
7976 	if (oa_value_len != value_len) {
7977 		/*
7978 		 * For some attributes, it's okay to copy the value
7979 		 * into a larger container, e.g. copy an unsigned
7980 		 * 32-bit integer into a 64-bit container.
7981 		 */
7982 		if (attr_type == DPROV_CKA_VALUE_LEN ||
7983 		    attr_type == DPROV_CKA_KEY_TYPE ||
7984 		    attr_type == DPROV_CKA_CLASS) {
7985 			if (oa_value_len < value_len) {
7986 #ifdef _BIG_ENDIAN
7987 				offset = value_len - oa_value_len;
7988 #endif
7989 				bzero(value, value_len);
7990 				goto do_copy;
7991 			}
7992 		}
7993 		/* incorrect attribute value length */
7994 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
7995 	}
7996 
7997 do_copy:
7998 	bcopy(object->do_attr[attr_idx].oa_value, (uchar_t *)value + offset,
7999 	    oa_value_len);
8000 
8001 	return (CRYPTO_SUCCESS);
8002 }
8003 
8004 /*
8005  * Get the value of the a boolean attribute from the specified object.
8006  */
8007 static int
8008 dprov_get_object_attr_boolean(dprov_object_t *object, uint64_t attr_type,
8009     boolean_t *attr_value)
8010 {
8011 	uchar_t val;
8012 	int ret;
8013 
8014 	/* PKCS#11 defines a boolean as one byte */
8015 	ret = dprov_get_object_attr_scalar_common(object, attr_type, &val, 1);
8016 	if (ret == CRYPTO_SUCCESS) {
8017 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
8018 	}
8019 	return (ret);
8020 }
8021 
8022 /*
8023  * Get the value of a ulong_t attribute from the specified object.
8024  */
8025 static int
8026 dprov_get_object_attr_ulong(dprov_object_t *object, uint64_t attr_type,
8027     ulong_t *attr_value)
8028 {
8029 	return (dprov_get_object_attr_scalar_common(object, attr_type,
8030 	    attr_value, sizeof (ulong_t)));
8031 }
8032 
8033 /*
8034  * Find the specified byte array attribute of specified type in
8035  * the specified object. Returns CRYPTO_SUCCESS
8036  * on success or CRYPTO_ARGUMENTS_BAD if the specified
8037  * attribute cannot be found.
8038  */
8039 static int
8040 dprov_get_object_attr_array(dprov_object_t *object, uint64_t attr_type,
8041     void **array, size_t *len)
8042 {
8043 	int attr_idx;
8044 
8045 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
8046 	    attr_type)) == -1)
8047 		return (CRYPTO_ARGUMENTS_BAD);
8048 
8049 	*array = object->do_attr[attr_idx].oa_value;
8050 	*len = object->do_attr[attr_idx].oa_value_len;
8051 
8052 	return (CRYPTO_SUCCESS);
8053 }
8054 
8055 /*
8056  * Common function used by the dprov_get_template_attr_*() family of
8057  * functions. Returns the value of the specified attribute of specified
8058  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
8059  * if the length of the attribute does not match the specified length,
8060  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
8061  */
8062 static int
8063 dprov_get_template_attr_scalar_common(crypto_object_attribute_t *template,
8064     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
8065 {
8066 	size_t oa_value_len;
8067 	size_t offset = 0;
8068 	int attr_idx;
8069 
8070 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
8071 		return (CRYPTO_ARGUMENTS_BAD);
8072 
8073 	oa_value_len = template[attr_idx].oa_value_len;
8074 	if (oa_value_len != value_len) {
8075 		/*
8076 		 * For some attributes, it's okay to copy the value
8077 		 * into a larger container, e.g. copy an unsigned
8078 		 * 32-bit integer into a 64-bit container.
8079 		 */
8080 		if (attr_type == DPROV_CKA_VALUE_LEN ||
8081 		    attr_type == DPROV_CKA_KEY_TYPE ||
8082 		    attr_type == DPROV_CKA_CLASS) {
8083 			if (oa_value_len < value_len) {
8084 #ifdef _BIG_ENDIAN
8085 				offset = value_len - oa_value_len;
8086 #endif
8087 				bzero(value, value_len);
8088 				goto do_copy;
8089 			}
8090 		}
8091 		/* incorrect attribute value length */
8092 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8093 	}
8094 
8095 do_copy:
8096 	bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
8097 	    oa_value_len);
8098 
8099 	return (CRYPTO_SUCCESS);
8100 }
8101 
8102 /*
8103  * Get the value of the a boolean attribute from the specified template
8104  */
8105 static int
8106 dprov_get_template_attr_boolean(crypto_object_attribute_t *template,
8107     uint_t nattr, uint64_t attr_type, boolean_t *attr_value)
8108 {
8109 	uchar_t val;
8110 	int ret;
8111 
8112 	/* PKCS#11 defines a boolean as one byte */
8113 	ret = dprov_get_template_attr_scalar_common(template, nattr,
8114 	    attr_type, &val, 1);
8115 	if (ret == CRYPTO_SUCCESS) {
8116 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
8117 	}
8118 	return (ret);
8119 }
8120 
8121 /*
8122  * Get the value of a ulong_t attribute from the specified template.
8123  */
8124 static int
8125 dprov_get_template_attr_ulong(crypto_object_attribute_t *template,
8126     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
8127 {
8128 	return (dprov_get_template_attr_scalar_common(template, nattr,
8129 	    attr_type, attr_value, sizeof (ulong_t)));
8130 }
8131 
8132 static int
8133 dprov_template_attr_present(crypto_object_attribute_t *template,
8134     uint_t nattr, uint64_t attr_type)
8135 {
8136 	return (dprov_find_attr(template, nattr,
8137 	    attr_type) == -1 ? B_FALSE : B_TRUE);
8138 }
8139 
8140 /*
8141  * Find the specified byte array attribute of specified type in
8142  * the specified template. Returns CRYPTO_SUCCESS on success or
8143  * CRYPTO_ARGUMENTS_BAD if the specified attribute cannot be found.
8144  */
8145 static int
8146 dprov_get_template_attr_array(crypto_object_attribute_t *template,
8147     uint_t nattr, uint64_t attr_type, void **array, size_t *len)
8148 {
8149 	int attr_idx;
8150 
8151 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
8152 		return (CRYPTO_ARGUMENTS_BAD);
8153 
8154 	*array = template[attr_idx].oa_value;
8155 	*len = template[attr_idx].oa_value_len;
8156 
8157 	return (CRYPTO_SUCCESS);
8158 }
8159 
8160 /*
8161  * Common function used by the dprov_get_key_attr_*() family of
8162  * functions. Returns the value of the specified attribute of specified
8163  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
8164  * if the length of the attribute does not match the specified length,
8165  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
8166  */
8167 static int
8168 dprov_get_key_attr_scalar_common(crypto_key_t *key, uint64_t attr_type,
8169     void *value, size_t value_len)
8170 {
8171 	int attr_idx;
8172 
8173 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
8174 
8175 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
8176 	    attr_type)) == -1)
8177 		return (CRYPTO_ARGUMENTS_BAD);
8178 
8179 	if (key->ck_attrs[attr_idx].oa_value_len != value_len)
8180 		/* incorrect attribute value length */
8181 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8182 
8183 	bcopy(key->ck_attrs[attr_idx].oa_value, value, value_len);
8184 
8185 	return (CRYPTO_SUCCESS);
8186 }
8187 
8188 /*
8189  * Get the value of a ulong_t attribute from the specified key.
8190  */
8191 static int
8192 dprov_get_key_attr_ulong(crypto_key_t *key, uint64_t attr_type,
8193     ulong_t *attr_value)
8194 {
8195 	return (dprov_get_key_attr_scalar_common(key, attr_type,
8196 	    attr_value, sizeof (ulong_t)));
8197 }
8198 
8199 /*
8200  * Find the specified byte array attribute of specified type in
8201  * the specified key by attributes. Returns CRYPTO_SUCCESS
8202  * on success or CRYPTO_ARGUMENTS_BAD if the specified
8203  * attribute cannot be found.
8204  */
8205 static int
8206 dprov_get_key_attr_array(crypto_key_t *key, uint64_t attr_type,
8207     void **array, size_t *len)
8208 {
8209 	int attr_idx;
8210 
8211 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
8212 
8213 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
8214 	    attr_type)) == -1)
8215 		return (CRYPTO_ARGUMENTS_BAD);
8216 
8217 	*array = key->ck_attrs[attr_idx].oa_value;
8218 	*len = key->ck_attrs[attr_idx].oa_value_len;
8219 
8220 	return (CRYPTO_SUCCESS);
8221 }
8222 
8223 static void
8224 dprov_release_session_objects(dprov_session_t *session)
8225 {
8226 	dprov_object_t *object;
8227 	int i;
8228 
8229 	for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
8230 		object = session->ds_objects[i];
8231 		if (object != NULL) {
8232 			DPROV_OBJECT_REFRELE(object);
8233 		}
8234 	}
8235 }
8236