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