xref: /onnv-gate/usr/src/uts/common/crypto/io/dprov.c (revision 4424:2e1b1291c75f)
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 	if (ddi_create_minor_node(dip, devname, S_IFCHR, instance,
1720 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
1721 		cmn_err(CE_WARN, "attach: failed creating minor node");
1722 		mutex_destroy(&softc->ds_lock);
1723 		ddi_soft_state_free(statep, instance);
1724 		return (DDI_FAILURE);
1725 	}
1726 
1727 	nostore_key_gen = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1728 	    DDI_PROP_DONTPASS, "nostore_key_gen", 0);
1729 	if (nostore_key_gen != 0) {
1730 		dprov_prov_info.pi_interface_version = CRYPTO_SPI_VERSION_3;
1731 		dprov_crypto_ops.co_object_ops = NULL;
1732 		dprov_crypto_ops.co_nostore_key_ops = &dprov_nostore_key_ops;
1733 	}
1734 
1735 	dprov_max_digestsz = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1736 	    DDI_PROP_DONTPASS, "max_digest_sz", INT_MAX);
1737 	if (dprov_max_digestsz != INT_MAX && dprov_max_digestsz != 0 &&
1738 	    dprov_max_digestsz != DDI_PROP_NOT_FOUND) {
1739 		int i, nmechs;
1740 
1741 		dprov_no_multipart = B_TRUE;
1742 		dprov_prov_info.pi_flags |= CRYPTO_HASH_NO_UPDATE;
1743 
1744 		/* Set cm_max_input_length for all hash mechs */
1745 		nmechs = sizeof (dprov_mech_info_tab) /
1746 		    sizeof (crypto_mech_info_t);
1747 		for (i = 0; i < nmechs; i++) {
1748 			if (dprov_mech_info_tab[i].cm_func_group_mask &
1749 			    CRYPTO_FG_DIGEST) {
1750 				dprov_mech_info_tab[i].cm_max_input_length =
1751 				    dprov_max_digestsz;
1752 			}
1753 		}
1754 	}
1755 
1756 	/* create taskq */
1757 	softc->ds_taskq = taskq_create(devname, 1, minclsyspri,
1758 	    crypto_taskq_minalloc, crypto_taskq_maxalloc, TASKQ_PREPOPULATE);
1759 
1760 	/* initialize table of sessions */
1761 	softc->ds_sessions = kmem_zalloc(DPROV_MIN_SESSIONS *
1762 	    sizeof (dprov_session_t *), KM_SLEEP);
1763 	softc->ds_sessions_slots = DPROV_MIN_SESSIONS;
1764 	softc->ds_sessions_count = 0;
1765 
1766 	/* initialized done by init_token entry point */
1767 	softc->ds_token_initialized = B_TRUE;
1768 
1769 	(void) memset(softc->ds_label, ' ', CRYPTO_EXT_SIZE_LABEL);
1770 	bcopy("Dummy Pseudo HW Provider", softc->ds_label, 24);
1771 
1772 	bcopy("changeme", softc->ds_user_pin, 8);
1773 	softc->ds_user_pin_len = 8;
1774 	softc->ds_user_pin_set = B_TRUE;
1775 
1776 	/* register with the crypto framework */
1777 	dprov_prov_info.pi_provider_dev.pd_hw = dip;
1778 	dprov_prov_info.pi_provider_handle = softc;
1779 
1780 	if (dprov_no_multipart) { /* Export only single part */
1781 		dprov_digest_ops.digest_update = NULL;
1782 		dprov_digest_ops.digest_key = NULL;
1783 		dprov_digest_ops.digest_final = NULL;
1784 		dprov_object_ops.object_create = NULL;
1785 	}
1786 
1787 	if ((ret = crypto_register_provider(&dprov_prov_info,
1788 	    &softc->ds_prov_handle)) != CRYPTO_SUCCESS) {
1789 		cmn_err(CE_WARN,
1790 		    "dprov crypto_register_provider() failed (0x%x)", ret);
1791 		taskq_destroy(softc->ds_taskq);
1792 		kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
1793 		    sizeof (dprov_session_t *));
1794 		mutex_destroy(&softc->ds_lock);
1795 		ddi_soft_state_free(statep, instance);
1796 		ddi_remove_minor_node(dip, NULL);
1797 		return (DDI_FAILURE);
1798 	}
1799 
1800 	/*
1801 	 * This call is for testing only; it is not required by the SPI.
1802 	 */
1803 	crypto_provider_notification(softc->ds_prov_handle,
1804 	    CRYPTO_PROVIDER_READY);
1805 
1806 	return (DDI_SUCCESS);
1807 }
1808 
1809 static int
1810 dprov_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1811 {
1812 	int instance = ddi_get_instance(dip);
1813 	dprov_state_t *softc = ddi_get_soft_state(statep, instance);
1814 	dprov_session_t *session;
1815 	int i, ret;
1816 
1817 	DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_detach() for %d\n",
1818 	    instance));
1819 
1820 	if (cmd != DDI_DETACH)
1821 		return (DDI_FAILURE);
1822 
1823 	/* unregister from the crypto framework */
1824 	if (softc->ds_prov_handle != NULL)
1825 		if ((ret = crypto_unregister_provider(
1826 		    softc->ds_prov_handle)) != CRYPTO_SUCCESS) {
1827 			cmn_err(CE_WARN, "dprov_detach: "
1828 			    "crypto_unregister_provider() "
1829 			    "failed (0x%x)", ret);
1830 			return (DDI_FAILURE);
1831 		}
1832 
1833 
1834 	taskq_destroy(softc->ds_taskq);
1835 
1836 	for (i = 0; i < softc->ds_sessions_slots; i++) {
1837 		if ((session = softc->ds_sessions[i]) == NULL)
1838 			continue;
1839 
1840 		dprov_release_session_objects(session);
1841 
1842 		kmem_free(session, sizeof (dprov_session_t));
1843 		softc->ds_sessions_count--;
1844 
1845 	}
1846 
1847 	kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
1848 	    sizeof (dprov_session_t *));
1849 	/* free token objects */
1850 	for (i = 0; i < DPROV_MAX_OBJECTS; i++)
1851 		if (softc->ds_objects[i] != NULL)
1852 			dprov_free_object(softc->ds_objects[i]);
1853 
1854 	mutex_destroy(&softc->ds_lock);
1855 	ddi_soft_state_free(statep, instance);
1856 
1857 	ddi_remove_minor_node(dip, NULL);
1858 
1859 	return (DDI_SUCCESS);
1860 }
1861 
1862 /*
1863  * Control entry points.
1864  */
1865 static void
1866 dprov_provider_status(crypto_provider_handle_t provider, uint_t *status)
1867 {
1868 	_NOTE(ARGUNUSED(provider))
1869 
1870 	*status = CRYPTO_PROVIDER_READY;
1871 }
1872 
1873 /*
1874  * Digest entry points.
1875  */
1876 
1877 static int
1878 dprov_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
1879     crypto_req_handle_t req)
1880 {
1881 	int error = CRYPTO_FAILED;
1882 	dprov_state_t *softc;
1883 	/* LINTED E_FUNC_SET_NOT_USED */
1884 	int instance;
1885 
1886 	/* extract softc and instance number from context */
1887 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1888 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_init: started\n", instance));
1889 
1890 	/* check mechanism */
1891 	if (mechanism->cm_type != MD4_MECH_INFO_TYPE &&
1892 	    mechanism->cm_type != MD5_MECH_INFO_TYPE &&
1893 	    mechanism->cm_type != SHA1_MECH_INFO_TYPE &&
1894 	    mechanism->cm_type != SHA256_MECH_INFO_TYPE &&
1895 	    mechanism->cm_type != SHA384_MECH_INFO_TYPE &&
1896 	    mechanism->cm_type != SHA512_MECH_INFO_TYPE) {
1897 		cmn_err(CE_WARN, "dprov_digest_init: unexpected mech type "
1898 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
1899 		return (CRYPTO_MECHANISM_INVALID);
1900 	}
1901 
1902 	/* submit request to the taskq */
1903 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_INIT, softc, req,
1904 	    mechanism, NULL, NULL, NULL, ctx, KM_SLEEP);
1905 
1906 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_init: done err = 0x%x\n",
1907 	    instance, error));
1908 
1909 	return (error);
1910 }
1911 
1912 static int
1913 dprov_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
1914     crypto_req_handle_t req)
1915 {
1916 	int error = CRYPTO_FAILED;
1917 	dprov_state_t *softc;
1918 	/* LINTED E_FUNC_SET_NOT_USED */
1919 	int instance;
1920 
1921 	if (dprov_no_multipart && data->cd_length > dprov_max_digestsz)
1922 		return (CRYPTO_BUFFER_TOO_BIG);
1923 
1924 	/* extract softc and instance number from context */
1925 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1926 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest: started\n", instance));
1927 
1928 	/* submit request to the taskq */
1929 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST, softc, req,
1930 	    NULL, data, NULL, digest, ctx, KM_NOSLEEP);
1931 
1932 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest: done, err = 0x%x\n",
1933 	    instance, error));
1934 
1935 	return (error);
1936 }
1937 
1938 static int
1939 dprov_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
1940     crypto_req_handle_t req)
1941 {
1942 	int error = CRYPTO_FAILED;
1943 	dprov_state_t *softc;
1944 	/* LINTED E_FUNC_SET_NOT_USED */
1945 	int instance;
1946 
1947 	/* extract softc and instance number from context */
1948 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1949 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_update: started\n",
1950 	    instance));
1951 
1952 	/* submit request to the taskq */
1953 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_UPDATE, softc,
1954 	    req, NULL, data, NULL, NULL, ctx, KM_NOSLEEP);
1955 
1956 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_update: done err = 0x0%x\n",
1957 	    instance, error));
1958 
1959 	return (error);
1960 }
1961 
1962 static int
1963 dprov_digest_key(crypto_ctx_t *ctx, crypto_key_t *key, crypto_req_handle_t req)
1964 {
1965 	int error = CRYPTO_FAILED;
1966 	dprov_state_t *softc;
1967 	/* LINTED E_FUNC_SET_NOT_USED */
1968 	int instance;
1969 
1970 	/* extract softc and instance number from context */
1971 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1972 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_key: started\n", instance));
1973 
1974 	/* submit request to the taskq */
1975 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_KEY, softc, req, NULL,
1976 	    NULL, key, NULL, ctx, KM_NOSLEEP);
1977 
1978 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_key: done err = 0x0%x\n",
1979 	    instance, error));
1980 
1981 	return (error);
1982 }
1983 
1984 static int
1985 dprov_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
1986     crypto_req_handle_t req)
1987 {
1988 	int error = CRYPTO_FAILED;
1989 	dprov_state_t *softc;
1990 	/* LINTED E_FUNC_SET_NOT_USED */
1991 	int instance;
1992 
1993 	/* extract softc and instance number from context */
1994 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1995 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_final: started\n", instance));
1996 
1997 	/* submit request to the taskq */
1998 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_FINAL, softc, req,
1999 	    NULL, NULL, NULL, digest, ctx, KM_NOSLEEP);
2000 
2001 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_final: done err = 0x0%x\n",
2002 	    instance, error));
2003 
2004 	return (error);
2005 }
2006 
2007 /* ARGSUSED */
2008 static int
2009 dprov_digest_atomic(crypto_provider_handle_t provider,
2010     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2011     crypto_data_t *data, crypto_data_t *digest,
2012     crypto_req_handle_t req)
2013 {
2014 	int error = CRYPTO_FAILED;
2015 	dprov_state_t *softc = (dprov_state_t *)provider;
2016 	/* LINTED E_FUNC_SET_NOT_USED */
2017 	int instance;
2018 
2019 	if (dprov_no_multipart && data->cd_length > dprov_max_digestsz)
2020 		return (CRYPTO_BUFFER_TOO_BIG);
2021 
2022 	instance = ddi_get_instance(softc->ds_dip);
2023 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_atomic: started\n",
2024 	    instance));
2025 
2026 	/* check mechanism */
2027 	if (mechanism->cm_type != MD4_MECH_INFO_TYPE &&
2028 	    mechanism->cm_type != MD5_MECH_INFO_TYPE &&
2029 	    mechanism->cm_type != SHA1_MECH_INFO_TYPE &&
2030 	    mechanism->cm_type != SHA256_MECH_INFO_TYPE &&
2031 	    mechanism->cm_type != SHA384_MECH_INFO_TYPE &&
2032 	    mechanism->cm_type != SHA512_MECH_INFO_TYPE) {
2033 		cmn_err(CE_WARN, "dprov_digest_atomic: unexpected mech type "
2034 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2035 		return (CRYPTO_MECHANISM_INVALID);
2036 	}
2037 
2038 	/* submit request to the taskq */
2039 	error = dprov_digest_submit_req(DPROV_REQ_DIGEST_ATOMIC, softc, req,
2040 	    mechanism, data, NULL, digest, NULL, KM_SLEEP);
2041 
2042 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_atomic: done err = 0x0%x\n",
2043 	    instance, error));
2044 
2045 	return (error);
2046 }
2047 
2048 /*
2049  * MAC entry points.
2050  */
2051 
2052 /*
2053  * Checks whether the specified mech_type is supported by mac
2054  * entry points.
2055  */
2056 static boolean_t
2057 dprov_valid_mac_mech(crypto_mech_type_t mech_type)
2058 {
2059 	return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
2060 	    mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE ||
2061 	    mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
2062 	    mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE ||
2063 	    mech_type == SHA256_HMAC_MECH_INFO_TYPE ||
2064 	    mech_type == SHA256_HMAC_GEN_MECH_INFO_TYPE ||
2065 	    mech_type == SHA384_HMAC_MECH_INFO_TYPE ||
2066 	    mech_type == SHA384_HMAC_GEN_MECH_INFO_TYPE ||
2067 	    mech_type == SHA512_HMAC_MECH_INFO_TYPE ||
2068 	    mech_type == SHA512_HMAC_GEN_MECH_INFO_TYPE);
2069 }
2070 
2071 static int
2072 dprov_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2073     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2074     crypto_req_handle_t req)
2075 {
2076 	int error = CRYPTO_FAILED;
2077 	dprov_state_t *softc;
2078 	/* LINTED E_FUNC_SET_NOT_USED */
2079 	int instance;
2080 
2081 	/* extract softc and instance number from context */
2082 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2083 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_init: started\n", instance));
2084 
2085 	/* check mechanism */
2086 	if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2087 		cmn_err(CE_WARN, "dprov_mac_init: unexpected mech type "
2088 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2089 		return (CRYPTO_MECHANISM_INVALID);
2090 	}
2091 
2092 	if (ctx_template != NULL)
2093 		return (CRYPTO_ARGUMENTS_BAD);
2094 
2095 	/* submit request to the taskq */
2096 	error = dprov_mac_submit_req(DPROV_REQ_MAC_INIT, softc, req,
2097 	    mechanism, NULL, key, NULL, ctx, 0, KM_SLEEP);
2098 
2099 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_init: done err = 0x%x\n",
2100 	    instance, error));
2101 
2102 	return (error);
2103 }
2104 
2105 static int
2106 dprov_mac(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *mac,
2107     crypto_req_handle_t req)
2108 {
2109 	int error = CRYPTO_FAILED;
2110 	dprov_state_t *softc;
2111 	/* LINTED E_FUNC_SET_NOT_USED */
2112 	int instance;
2113 
2114 	/* extract softc and instance number from context */
2115 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2116 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac: started\n", instance));
2117 
2118 	/* submit request to the taskq */
2119 	error = dprov_mac_submit_req(DPROV_REQ_MAC, softc, req,
2120 	    NULL, data, NULL, mac, ctx, 0, KM_NOSLEEP);
2121 
2122 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac: done, err = 0x%x\n", instance,
2123 	    error));
2124 
2125 	return (error);
2126 }
2127 
2128 static int
2129 dprov_mac_update(crypto_ctx_t *ctx, crypto_data_t *data,
2130     crypto_req_handle_t req)
2131 {
2132 	int error = CRYPTO_FAILED;
2133 	dprov_state_t *softc;
2134 	/* LINTED E_FUNC_SET_NOT_USED */
2135 	int instance;
2136 
2137 	/* extract softc and instance number from context */
2138 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2139 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_update: started\n", instance));
2140 
2141 	/* submit request to the taskq */
2142 	error = dprov_mac_submit_req(DPROV_REQ_MAC_UPDATE, softc,
2143 	    req, NULL, data, NULL, NULL, ctx, 0, KM_NOSLEEP);
2144 
2145 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_update: done err = 0x0%x\n",
2146 	    instance, error));
2147 
2148 	return (error);
2149 }
2150 
2151 static int
2152 dprov_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
2153 {
2154 	int error = CRYPTO_FAILED;
2155 	dprov_state_t *softc;
2156 	/* LINTED E_FUNC_SET_NOT_USED */
2157 	int instance;
2158 
2159 	/* extract softc and instance number from context */
2160 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2161 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_final: started\n", instance));
2162 
2163 	/* submit request to the taskq */
2164 	error = dprov_mac_submit_req(DPROV_REQ_MAC_FINAL, softc, req,
2165 	    NULL, NULL, NULL, mac, ctx, 0, KM_NOSLEEP);
2166 
2167 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_final: done err = 0x0%x\n",
2168 	    instance, error));
2169 
2170 	return (error);
2171 }
2172 
2173 static int
2174 dprov_mac_atomic(crypto_provider_handle_t provider,
2175     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2176     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
2177     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2178 {
2179 	int error = CRYPTO_FAILED;
2180 	dprov_state_t *softc = (dprov_state_t *)provider;
2181 	/* LINTED E_FUNC_SET_NOT_USED */
2182 	int instance;
2183 
2184 	instance = ddi_get_instance(softc->ds_dip);
2185 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_atomic: started\n", instance));
2186 
2187 	if (ctx_template != NULL)
2188 		return (CRYPTO_ARGUMENTS_BAD);
2189 
2190 	/* check mechanism */
2191 	if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2192 		cmn_err(CE_WARN, "dprov_mac_atomic: unexpected mech type "
2193 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2194 		return (CRYPTO_MECHANISM_INVALID);
2195 	}
2196 
2197 	/* submit request to the taskq */
2198 	error = dprov_mac_submit_req(DPROV_REQ_MAC_ATOMIC, softc, req,
2199 	    mechanism, data, key, mac, NULL, session_id, KM_SLEEP);
2200 
2201 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_atomic: done err = 0x0%x\n",
2202 	    instance, error));
2203 
2204 	return (error);
2205 }
2206 
2207 static int
2208 dprov_mac_verify_atomic(crypto_provider_handle_t provider,
2209     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2210     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
2211     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2212 {
2213 	int error = CRYPTO_FAILED;
2214 	dprov_state_t *softc = (dprov_state_t *)provider;
2215 	/* LINTED E_FUNC_SET_NOT_USED */
2216 	int instance;
2217 
2218 	instance = ddi_get_instance(softc->ds_dip);
2219 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_verify_atomic: started\n",
2220 	    instance));
2221 
2222 	if (ctx_template != NULL)
2223 		return (CRYPTO_ARGUMENTS_BAD);
2224 
2225 	/* check mechanism */
2226 	if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2227 		cmn_err(CE_WARN, "dprov_mac_verify_atomic: unexpected mech "
2228 		    "type 0x%llx\n", (unsigned long long)mechanism->cm_type);
2229 		return (CRYPTO_MECHANISM_INVALID);
2230 	}
2231 
2232 	/* submit request to the taskq */
2233 	error = dprov_mac_submit_req(DPROV_REQ_MAC_VERIFY_ATOMIC, softc, req,
2234 	    mechanism, data, key, mac, NULL, session_id, KM_SLEEP);
2235 
2236 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_verify_atomic: done err = 0x0%x\n",
2237 	    instance, error));
2238 
2239 	return (error);
2240 }
2241 
2242 /*
2243  * Cipher (encrypt/decrypt) entry points.
2244  */
2245 
2246 /*
2247  * Checks whether the specified mech_type is supported by cipher entry
2248  * points.
2249  */
2250 static boolean_t
2251 dprov_valid_cipher_mech(crypto_mech_type_t mech_type)
2252 {
2253 	return (mech_type == DES_CBC_MECH_INFO_TYPE ||
2254 	    mech_type == DES3_CBC_MECH_INFO_TYPE ||
2255 	    mech_type == DES_ECB_MECH_INFO_TYPE ||
2256 	    mech_type == DES3_ECB_MECH_INFO_TYPE ||
2257 	    mech_type == BLOWFISH_CBC_MECH_INFO_TYPE ||
2258 	    mech_type == BLOWFISH_ECB_MECH_INFO_TYPE ||
2259 	    mech_type == AES_CBC_MECH_INFO_TYPE ||
2260 	    mech_type == AES_ECB_MECH_INFO_TYPE ||
2261 	    mech_type == AES_CTR_MECH_INFO_TYPE ||
2262 	    mech_type == RC4_MECH_INFO_TYPE ||
2263 	    mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2264 	    mech_type == RSA_X_509_MECH_INFO_TYPE ||
2265 	    mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2266 	    mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||
2267 	    mech_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||
2268 	    mech_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||
2269 	    mech_type == SHA512_RSA_PKCS_MECH_INFO_TYPE);
2270 }
2271 
2272 static boolean_t
2273 is_publickey_mech(crypto_mech_type_t mech_type)
2274 {
2275 	return (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2276 	    mech_type == RSA_X_509_MECH_INFO_TYPE ||
2277 	    mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2278 	    mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||
2279 	    mech_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||
2280 	    mech_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||
2281 	    mech_type == SHA512_RSA_PKCS_MECH_INFO_TYPE);
2282 }
2283 
2284 
2285 /* ARGSUSED */
2286 static int
2287 dprov_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2288     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2289     crypto_req_handle_t req)
2290 {
2291 	int error = CRYPTO_FAILED;
2292 	dprov_state_t *softc;
2293 	/* LINTED E_FUNC_SET_NOT_USED */
2294 	int instance;
2295 
2296 	/* extract softc and instance number from context */
2297 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2298 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_init: started\n",
2299 	    instance));
2300 
2301 	/* check mechanism */
2302 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2303 		cmn_err(CE_WARN, "dprov_encrypt_init: unexpected mech type "
2304 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2305 		return (CRYPTO_MECHANISM_INVALID);
2306 	}
2307 
2308 	/* submit request to the taskq */
2309 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_INIT, softc,
2310 	    req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2311 
2312 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_init: done err = 0x0%x\n",
2313 	    instance, error));
2314 
2315 	return (error);
2316 }
2317 
2318 /* ARGSUSED */
2319 static int
2320 dprov_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2321     crypto_data_t *ciphertext, crypto_req_handle_t req)
2322 {
2323 	int error = CRYPTO_FAILED;
2324 	dprov_state_t *softc;
2325 	/* LINTED E_FUNC_SET_NOT_USED */
2326 	int instance;
2327 
2328 	/* extract softc and instance number from context */
2329 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2330 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt: started\n", instance));
2331 
2332 	/* submit request to the taskq */
2333 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT, softc,
2334 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2335 
2336 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt: done err = 0x0%x\n",
2337 	    instance, error));
2338 
2339 	return (error);
2340 }
2341 
2342 /* ARGSUSED */
2343 static int
2344 dprov_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2345     crypto_data_t *ciphertext, crypto_req_handle_t req)
2346 {
2347 	int error = CRYPTO_FAILED;
2348 	dprov_state_t *softc;
2349 	/* LINTED E_FUNC_SET_NOT_USED */
2350 	int instance;
2351 
2352 	/* extract softc and instance number from context */
2353 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2354 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_update: started\n",
2355 	    instance));
2356 
2357 	/* submit request to the taskq */
2358 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_UPDATE, softc,
2359 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2360 
2361 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_update: done err = 0x0%x\n",
2362 	    instance, error));
2363 
2364 	return (error);
2365 }
2366 
2367 /* ARGSUSED */
2368 static int
2369 dprov_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2370     crypto_req_handle_t req)
2371 {
2372 	int error = CRYPTO_FAILED;
2373 	dprov_state_t *softc;
2374 	/* LINTED E_FUNC_SET_NOT_USED */
2375 	int instance;
2376 
2377 	/* extract softc and instance number from context */
2378 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2379 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_final: started\n",
2380 	    instance));
2381 
2382 	/* submit request to the taskq */
2383 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_FINAL, softc,
2384 	    req, NULL, NULL, NULL, ciphertext, ctx, 0, KM_NOSLEEP);
2385 
2386 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_final: done err = 0x0%x\n",
2387 	    instance, error));
2388 
2389 	return (error);
2390 }
2391 
2392 static int
2393 dprov_encrypt_atomic(crypto_provider_handle_t provider,
2394     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2395     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
2396     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2397 {
2398 	int error = CRYPTO_FAILED;
2399 	dprov_state_t *softc = (dprov_state_t *)provider;
2400 	/* LINTED E_FUNC_SET_NOT_USED */
2401 	int instance;
2402 
2403 	instance = ddi_get_instance(softc->ds_dip);
2404 	DPROV_DEBUG(D_MAC, ("(%d) dprov_encrypt_atomic: started\n", instance));
2405 
2406 	if (ctx_template != NULL)
2407 		return (CRYPTO_ARGUMENTS_BAD);
2408 
2409 	/* check mechanism */
2410 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2411 		cmn_err(CE_WARN, "dprov_encrypt_atomic: unexpected mech type "
2412 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2413 		return (CRYPTO_MECHANISM_INVALID);
2414 	}
2415 
2416 	error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_ATOMIC, softc,
2417 	    req, mechanism, key, plaintext, ciphertext, NULL, session_id,
2418 	    KM_SLEEP);
2419 
2420 	DPROV_DEBUG(D_MAC, ("(%d) dprov_encrypt_atomic: done err = 0x0%x\n",
2421 	    instance, error));
2422 
2423 	return (error);
2424 }
2425 
2426 /* ARGSUSED */
2427 static int
2428 dprov_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2429     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2430     crypto_req_handle_t req)
2431 {
2432 	int error = CRYPTO_FAILED;
2433 	dprov_state_t *softc;
2434 	/* LINTED E_FUNC_SET_NOT_USED */
2435 	int instance;
2436 
2437 	/* extract softc and instance number from context */
2438 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2439 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_init: started\n",
2440 	    instance));
2441 
2442 	/* check mechanism */
2443 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2444 		cmn_err(CE_WARN, "dprov_decrypt_init: unexpected mech type "
2445 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2446 		return (CRYPTO_MECHANISM_INVALID);
2447 	}
2448 
2449 	/* submit request to the taskq */
2450 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_INIT, softc,
2451 	    req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2452 
2453 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_init: done err = 0x0%x\n",
2454 	    instance, error));
2455 
2456 	return (error);
2457 }
2458 
2459 /* ARGSUSED */
2460 static int
2461 dprov_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2462     crypto_data_t *plaintext, crypto_req_handle_t req)
2463 {
2464 	int error = CRYPTO_FAILED;
2465 
2466 	dprov_state_t *softc;
2467 	/* LINTED E_FUNC_SET_NOT_USED */
2468 	int instance;
2469 
2470 	/* extract softc and instance number from context */
2471 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2472 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt: started\n", instance));
2473 
2474 	/* submit request to the taskq */
2475 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT, softc,
2476 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2477 
2478 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt: done err = 0x0%x\n",
2479 	    instance, error));
2480 
2481 	return (error);
2482 }
2483 
2484 /* ARGSUSED */
2485 static int
2486 dprov_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2487     crypto_data_t *plaintext, crypto_req_handle_t req)
2488 {
2489 	int error = CRYPTO_FAILED;
2490 	dprov_state_t *softc;
2491 	/* LINTED E_FUNC_SET_NOT_USED */
2492 	int instance;
2493 
2494 	/* extract softc and instance number from context */
2495 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2496 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_update: started\n",
2497 	    instance));
2498 
2499 	/* submit request to the taskq */
2500 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_UPDATE, softc,
2501 	    req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2502 
2503 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_update: done err = 0x0%x\n",
2504 	    instance, error));
2505 
2506 	return (error);
2507 }
2508 
2509 /* ARGSUSED */
2510 static int
2511 dprov_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2512     crypto_req_handle_t req)
2513 {
2514 	int error = CRYPTO_FAILED;
2515 	dprov_state_t *softc;
2516 	/* LINTED E_FUNC_SET_NOT_USED */
2517 	int instance;
2518 
2519 	/* extract softc and instance number from context */
2520 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2521 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_final: started\n",
2522 	    instance));
2523 
2524 	/* submit request to the taskq */
2525 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_FINAL, softc,
2526 	    req, NULL, NULL, plaintext, NULL, ctx, 0, KM_NOSLEEP);
2527 
2528 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_final: done err = 0x0%x\n",
2529 	    instance, error));
2530 
2531 	return (error);
2532 }
2533 
2534 static int
2535 dprov_decrypt_atomic(crypto_provider_handle_t provider,
2536     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2537     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
2538     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2539 {
2540 	int error = CRYPTO_FAILED;
2541 	dprov_state_t *softc = (dprov_state_t *)provider;
2542 	/* LINTED E_FUNC_SET_NOT_USED */
2543 	int instance;
2544 
2545 	instance = ddi_get_instance(softc->ds_dip);
2546 	DPROV_DEBUG(D_MAC, ("(%d) dprov_decrypt_atomic: started\n", instance));
2547 
2548 	if (ctx_template != NULL)
2549 		return (CRYPTO_ARGUMENTS_BAD);
2550 
2551 	/* check mechanism */
2552 	if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2553 		cmn_err(CE_WARN, "dprov_atomic_init: unexpected mech type "
2554 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2555 		return (CRYPTO_MECHANISM_INVALID);
2556 	}
2557 
2558 	error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_ATOMIC, softc,
2559 	    req, mechanism, key, plaintext, ciphertext, NULL, session_id,
2560 	    KM_SLEEP);
2561 
2562 	DPROV_DEBUG(D_MAC, ("(%d) dprov_decrypt_atomic: done err = 0x0%x\n",
2563 	    instance, error));
2564 
2565 	return (error);
2566 }
2567 
2568 /*
2569  * Sign entry points.
2570  */
2571 
2572 /*
2573  * Checks whether the specified mech_type is supported by sign/verify
2574  * entry points.
2575  */
2576 static boolean_t
2577 dprov_valid_sign_verif_mech(crypto_mech_type_t mech_type)
2578 {
2579 	return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
2580 	    mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE ||
2581 	    mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
2582 	    mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE ||
2583 	    mech_type == SHA256_HMAC_MECH_INFO_TYPE ||
2584 	    mech_type == SHA256_HMAC_GEN_MECH_INFO_TYPE ||
2585 	    mech_type == SHA384_HMAC_MECH_INFO_TYPE ||
2586 	    mech_type == SHA384_HMAC_GEN_MECH_INFO_TYPE ||
2587 	    mech_type == SHA512_HMAC_MECH_INFO_TYPE ||
2588 	    mech_type == SHA512_HMAC_GEN_MECH_INFO_TYPE ||
2589 	    mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2590 	    mech_type == RSA_X_509_MECH_INFO_TYPE ||
2591 	    mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2592 	    mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||
2593 	    mech_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||
2594 	    mech_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||
2595 	    mech_type == SHA512_RSA_PKCS_MECH_INFO_TYPE);
2596 }
2597 
2598 static int
2599 dprov_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2600     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2601     crypto_req_handle_t req)
2602 {
2603 	int error = CRYPTO_FAILED;
2604 	dprov_state_t *softc;
2605 	/* LINTED E_FUNC_SET_NOT_USED */
2606 	int instance;
2607 
2608 	/* extract softc and instance number from context */
2609 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2610 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_init: started\n", instance));
2611 
2612 	/* check mechanism */
2613 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2614 		cmn_err(CE_WARN, "dprov_sign_init: unexpected mech type "
2615 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2616 		return (CRYPTO_MECHANISM_INVALID);
2617 	}
2618 
2619 	if (ctx_template != NULL)
2620 		return (CRYPTO_ARGUMENTS_BAD);
2621 
2622 	/* submit request to the taskq */
2623 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_INIT, softc, req,
2624 	    mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2625 
2626 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_init: done err = 0x%x\n",
2627 	    instance, error));
2628 
2629 	return (error);
2630 }
2631 
2632 static int
2633 dprov_sign(crypto_ctx_t *ctx, crypto_data_t *data,
2634     crypto_data_t *signature, crypto_req_handle_t req)
2635 {
2636 	int error = CRYPTO_FAILED;
2637 	dprov_state_t *softc;
2638 	/* LINTED E_FUNC_SET_NOT_USED */
2639 	int instance;
2640 
2641 	/* extract softc and instance number from context */
2642 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2643 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign: started\n", instance));
2644 
2645 	/* submit request to the taskq */
2646 	error = dprov_sign_submit_req(DPROV_REQ_SIGN, softc, req,
2647 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2648 
2649 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign: done err = 0x%x\n",
2650 	    instance, error));
2651 
2652 	return (error);
2653 }
2654 
2655 static int
2656 dprov_sign_update(crypto_ctx_t *ctx, crypto_data_t *data,
2657     crypto_req_handle_t req)
2658 {
2659 	int error = CRYPTO_FAILED;
2660 	dprov_state_t *softc;
2661 	/* LINTED E_FUNC_SET_NOT_USED */
2662 	int instance;
2663 
2664 	/* extract softc and instance number from context */
2665 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2666 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_update: started\n", instance));
2667 
2668 	/* submit request to the taskq */
2669 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_UPDATE, softc, req,
2670 	    NULL, NULL, data, NULL, ctx, 0, KM_NOSLEEP);
2671 
2672 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_update: done err = 0x%x\n",
2673 	    instance, error));
2674 
2675 	return (error);
2676 }
2677 
2678 static int
2679 dprov_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
2680     crypto_req_handle_t req)
2681 {
2682 	int error = CRYPTO_FAILED;
2683 	dprov_state_t *softc;
2684 	/* LINTED E_FUNC_SET_NOT_USED */
2685 	int instance;
2686 
2687 	/* extract softc and instance number from context */
2688 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2689 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_final: started\n", instance));
2690 
2691 	/* submit request to the taskq */
2692 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_FINAL, softc, req,
2693 	    NULL, NULL, NULL, signature, ctx, 0, KM_NOSLEEP);
2694 
2695 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_final: done err = 0x%x\n",
2696 	    instance, error));
2697 
2698 	return (error);
2699 }
2700 
2701 static int
2702 dprov_sign_atomic(crypto_provider_handle_t provider,
2703     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2704     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2705     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2706 {
2707 	int error = CRYPTO_FAILED;
2708 	dprov_state_t *softc = (dprov_state_t *)provider;
2709 	/* LINTED E_FUNC_SET_NOT_USED */
2710 	int instance;
2711 
2712 	instance = ddi_get_instance(softc->ds_dip);
2713 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_atomic: started\n", instance));
2714 
2715 	/* check mechanism */
2716 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2717 		cmn_err(CE_WARN, "dprov_sign_atomic: unexpected mech type "
2718 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2719 		return (CRYPTO_MECHANISM_INVALID);
2720 	}
2721 
2722 	if (ctx_template != NULL)
2723 		return (CRYPTO_ARGUMENTS_BAD);
2724 
2725 	/* submit request to the taskq */
2726 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_ATOMIC, softc, req,
2727 	    mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2728 
2729 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_atomic: done err = 0x%x\n",
2730 	    instance, error));
2731 
2732 	return (error);
2733 }
2734 
2735 static int
2736 dprov_sign_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2737     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2738     crypto_req_handle_t req)
2739 {
2740 	int error = CRYPTO_FAILED;
2741 	dprov_state_t *softc;
2742 	/* LINTED E_FUNC_SET_NOT_USED */
2743 	int instance;
2744 
2745 	/* extract softc and instance number from context */
2746 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2747 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_init: started\n",
2748 	    instance));
2749 
2750 	if (ctx_template != NULL)
2751 		return (CRYPTO_ARGUMENTS_BAD);
2752 
2753 	/* submit request to the taskq */
2754 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER_INIT, softc, req,
2755 	    mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2756 
2757 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_init: done err = 0x%x\n",
2758 	    instance, error));
2759 
2760 	return (error);
2761 }
2762 
2763 static int
2764 dprov_sign_recover(crypto_ctx_t *ctx, crypto_data_t *data,
2765     crypto_data_t *signature, crypto_req_handle_t req)
2766 {
2767 	int error = CRYPTO_FAILED;
2768 	dprov_state_t *softc;
2769 	/* LINTED E_FUNC_SET_NOT_USED */
2770 	int instance;
2771 
2772 	/* extract softc and instance number from context */
2773 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2774 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover: started\n", instance));
2775 
2776 	/* submit request to the taskq */
2777 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER, softc, req,
2778 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2779 
2780 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover: done err = 0x%x\n",
2781 	    instance, error));
2782 
2783 	return (error);
2784 }
2785 
2786 static int
2787 dprov_sign_recover_atomic(crypto_provider_handle_t provider,
2788     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2789     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2790     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2791 {
2792 	int error = CRYPTO_FAILED;
2793 	dprov_state_t *softc = (dprov_state_t *)provider;
2794 	/* LINTED E_FUNC_SET_NOT_USED */
2795 	int instance;
2796 
2797 	instance = ddi_get_instance(softc->ds_dip);
2798 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_atomic: started\n",
2799 	    instance));
2800 
2801 	if (ctx_template != NULL)
2802 		return (CRYPTO_ARGUMENTS_BAD);
2803 
2804 	/* submit request to the taskq */
2805 	error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER_ATOMIC, softc, req,
2806 	    mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2807 
2808 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_atomic: done "
2809 	    "err = 0x%x\n", instance, error));
2810 
2811 	return (error);
2812 }
2813 
2814 /*
2815  * Verify entry points.
2816  */
2817 
2818 static int
2819 dprov_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2820     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2821     crypto_req_handle_t req)
2822 {
2823 	int error = CRYPTO_FAILED;
2824 	dprov_state_t *softc;
2825 	/* LINTED E_FUNC_SET_NOT_USED */
2826 	int instance;
2827 
2828 	/* extract softc and instance number from context */
2829 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2830 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_init: started\n", instance));
2831 
2832 	/* check mechanism */
2833 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2834 		cmn_err(CE_WARN, "dprov_verify_init: unexpected mech type "
2835 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2836 		return (CRYPTO_MECHANISM_INVALID);
2837 	}
2838 
2839 	if (ctx_template != NULL)
2840 		return (CRYPTO_ARGUMENTS_BAD);
2841 
2842 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_INIT, softc, req,
2843 	    mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2844 
2845 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_init: done err = 0x%x\n",
2846 	    instance, error));
2847 
2848 	return (error);
2849 }
2850 
2851 static int
2852 dprov_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
2853     crypto_req_handle_t req)
2854 {
2855 	int error = CRYPTO_FAILED;
2856 	dprov_state_t *softc;
2857 	/* LINTED E_FUNC_SET_NOT_USED */
2858 	int instance;
2859 
2860 	/* extract softc and instance number from context */
2861 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2862 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify: started\n", instance));
2863 
2864 	/* submit request to the taskq */
2865 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY, softc, req,
2866 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2867 
2868 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify: done err = 0x%x\n",
2869 	    instance, error));
2870 
2871 	return (error);
2872 }
2873 
2874 static int
2875 dprov_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
2876     crypto_req_handle_t req)
2877 {
2878 	int error = CRYPTO_FAILED;
2879 	dprov_state_t *softc;
2880 	/* LINTED E_FUNC_SET_NOT_USED */
2881 	int instance;
2882 
2883 	/* extract softc and instance number from context */
2884 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2885 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_update: started\n",
2886 	    instance));
2887 
2888 	/* submit request to the taskq */
2889 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_UPDATE, softc, req,
2890 	    NULL, NULL, data, NULL, ctx, 0, KM_NOSLEEP);
2891 
2892 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_update: done err = 0x%x\n",
2893 	    instance, error));
2894 
2895 	return (error);
2896 }
2897 
2898 static int
2899 dprov_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
2900     crypto_req_handle_t req)
2901 {
2902 	int error = CRYPTO_FAILED;
2903 	dprov_state_t *softc;
2904 	/* LINTED E_FUNC_SET_NOT_USED */
2905 	int instance;
2906 
2907 	/* extract softc and instance number from context */
2908 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2909 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_final: started\n", instance));
2910 
2911 	/* submit request to the taskq */
2912 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_FINAL, softc, req,
2913 	    NULL, NULL, NULL, signature, ctx, 0, KM_NOSLEEP);
2914 
2915 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_final: done err = 0x%x\n",
2916 	    instance, error));
2917 
2918 	return (error);
2919 }
2920 
2921 static int
2922 dprov_verify_atomic(crypto_provider_handle_t provider,
2923     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2924     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2925     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2926 {
2927 	int error = CRYPTO_FAILED;
2928 	dprov_state_t *softc = (dprov_state_t *)provider;
2929 	/* LINTED E_FUNC_SET_NOT_USED */
2930 	int instance;
2931 
2932 	instance = ddi_get_instance(softc->ds_dip);
2933 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_atomic: started\n",
2934 	    instance));
2935 
2936 	/* check mechanism */
2937 	if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2938 		cmn_err(CE_WARN, "dprov_verify_atomic: unexpected mech type "
2939 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
2940 		return (CRYPTO_MECHANISM_INVALID);
2941 	}
2942 
2943 	if (ctx_template != NULL)
2944 		return (CRYPTO_ARGUMENTS_BAD);
2945 
2946 	/* submit request to the taskq */
2947 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_ATOMIC, softc, req,
2948 	    mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2949 
2950 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_atomic: done err = 0x%x\n",
2951 	    instance, error));
2952 
2953 	return (error);
2954 }
2955 
2956 static int
2957 dprov_verify_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2958     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2959     crypto_req_handle_t req)
2960 {
2961 	int error = CRYPTO_FAILED;
2962 	dprov_state_t *softc;
2963 	/* LINTED E_FUNC_SET_NOT_USED */
2964 	int instance;
2965 
2966 	/* extract softc and instance number from context */
2967 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2968 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_init: started\n",
2969 	    instance));
2970 
2971 	if (ctx_template != NULL)
2972 		return (CRYPTO_ARGUMENTS_BAD);
2973 
2974 	/* submit request to the taskq */
2975 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER_INIT, softc,
2976 	    req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2977 
2978 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_init: done "
2979 	    "err = 0x%x\n", instance, error));
2980 
2981 	return (error);
2982 }
2983 
2984 static int
2985 dprov_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
2986     crypto_data_t *data, crypto_req_handle_t req)
2987 {
2988 	int error = CRYPTO_FAILED;
2989 	dprov_state_t *softc;
2990 	/* LINTED E_FUNC_SET_NOT_USED */
2991 	int instance;
2992 
2993 	/* extract softc and instance number from context */
2994 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2995 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover: started\n",
2996 	    instance));
2997 
2998 	/* submit request to the taskq */
2999 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER, softc, req,
3000 	    NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
3001 
3002 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover: done err = 0x%x\n",
3003 	    instance, error));
3004 
3005 	return (error);
3006 }
3007 
3008 static int
3009 dprov_verify_recover_atomic(crypto_provider_handle_t provider,
3010     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3011     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
3012     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
3013 {
3014 	int error = CRYPTO_FAILED;
3015 	dprov_state_t *softc = (dprov_state_t *)provider;
3016 	/* LINTED E_FUNC_SET_NOT_USED */
3017 	int instance;
3018 
3019 	instance = ddi_get_instance(softc->ds_dip);
3020 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_atomic: started\n",
3021 	    instance));
3022 
3023 	if (ctx_template != NULL)
3024 		return (CRYPTO_ARGUMENTS_BAD);
3025 
3026 	/* submit request to the taskq */
3027 	error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER_ATOMIC, softc,
3028 	    req, mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
3029 
3030 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_atomic: done "
3031 	    "err = 0x%x\n", instance, error));
3032 
3033 	return (error);
3034 }
3035 
3036 /*
3037  * Dual operations entry points.
3038  */
3039 
3040 static int
3041 dprov_digest_encrypt_update(crypto_ctx_t *digest_ctx,
3042     crypto_ctx_t *encrypt_ctx, crypto_data_t *plaintext,
3043     crypto_data_t *ciphertext, crypto_req_handle_t req)
3044 {
3045 	int error = CRYPTO_FAILED;
3046 	dprov_state_t *softc;
3047 	/* LINTED E_FUNC_SET_NOT_USED */
3048 	int instance;
3049 
3050 	/* extract softc and instance number from context */
3051 	DPROV_SOFTC_FROM_CTX(digest_ctx, softc, instance);
3052 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_digest_encrypt_update: started\n",
3053 	    instance));
3054 
3055 	if (digest_ctx->cc_provider != encrypt_ctx->cc_provider)
3056 		return (CRYPTO_INVALID_CONTEXT);
3057 
3058 	/* submit request to the taskq */
3059 	error = dprov_dual_submit_req(DPROV_REQ_DIGEST_ENCRYPT_UPDATE,
3060 	    softc, req, digest_ctx, encrypt_ctx, plaintext, ciphertext);
3061 
3062 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_digest_encrypt_update: done "
3063 	    "err = 0x%x\n", instance, error));
3064 
3065 	return (error);
3066 }
3067 
3068 static int
3069 dprov_decrypt_digest_update(crypto_ctx_t *decrypt_ctx, crypto_ctx_t *digest_ctx,
3070     crypto_data_t *ciphertext, crypto_data_t *plaintext,
3071     crypto_req_handle_t req)
3072 {
3073 	int error = CRYPTO_FAILED;
3074 	dprov_state_t *softc;
3075 	/* LINTED E_FUNC_SET_NOT_USED */
3076 	int instance;
3077 
3078 	/* extract softc and instance number from context */
3079 	DPROV_SOFTC_FROM_CTX(decrypt_ctx, softc, instance);
3080 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_digest_update: started\n",
3081 	    instance));
3082 
3083 	if (decrypt_ctx->cc_provider != digest_ctx->cc_provider)
3084 		return (CRYPTO_INVALID_CONTEXT);
3085 
3086 	/* submit request to the taskq */
3087 	error = dprov_dual_submit_req(DPROV_REQ_DECRYPT_DIGEST_UPDATE,
3088 	    softc, req, digest_ctx, decrypt_ctx, plaintext, ciphertext);
3089 
3090 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_digest_update: done "
3091 	    "err = 0x%x\n", instance, error));
3092 
3093 	return (error);
3094 }
3095 
3096 static int
3097 dprov_sign_encrypt_update(crypto_ctx_t *sign_ctx, crypto_ctx_t *encrypt_ctx,
3098     crypto_data_t *plaintext, crypto_data_t *ciphertext,
3099     crypto_req_handle_t req)
3100 {
3101 	int error = CRYPTO_FAILED;
3102 	dprov_state_t *softc;
3103 	/* LINTED E_FUNC_SET_NOT_USED */
3104 	int instance;
3105 
3106 	/* extract softc and instance number from context */
3107 	DPROV_SOFTC_FROM_CTX(sign_ctx, softc, instance);
3108 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_sign_encrypt_update: started\n",
3109 	    instance));
3110 
3111 	if (sign_ctx->cc_provider != encrypt_ctx->cc_provider)
3112 		return (CRYPTO_INVALID_CONTEXT);
3113 
3114 	/* submit request to the taskq */
3115 	error = dprov_dual_submit_req(DPROV_REQ_SIGN_ENCRYPT_UPDATE,
3116 	    softc, req, sign_ctx, encrypt_ctx, plaintext, ciphertext);
3117 
3118 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_sign_encrypt_update: done "
3119 	    "err = 0x%x\n", instance, error));
3120 
3121 	return (error);
3122 }
3123 
3124 static int
3125 dprov_decrypt_verify_update(crypto_ctx_t *decrypt_ctx, crypto_ctx_t *verify_ctx,
3126     crypto_data_t *ciphertext, crypto_data_t *plaintext,
3127     crypto_req_handle_t req)
3128 {
3129 	int error = CRYPTO_FAILED;
3130 	dprov_state_t *softc;
3131 	/* LINTED E_FUNC_SET_NOT_USED */
3132 	int instance;
3133 
3134 	/* extract softc and instance number from context */
3135 	DPROV_SOFTC_FROM_CTX(decrypt_ctx, softc, instance);
3136 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_verify_update: started\n",
3137 	    instance));
3138 
3139 	if (decrypt_ctx->cc_provider != verify_ctx->cc_provider)
3140 		return (CRYPTO_INVALID_CONTEXT);
3141 
3142 	/* submit request to the taskq */
3143 	error = dprov_dual_submit_req(DPROV_REQ_DECRYPT_VERIFY_UPDATE,
3144 	    softc, req, verify_ctx, decrypt_ctx, plaintext, ciphertext);
3145 
3146 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_verify_update: done "
3147 	    "err = 0x%x\n", instance, error));
3148 
3149 	return (error);
3150 }
3151 
3152 /*
3153  * Dual cipher-mac entry points.
3154  */
3155 
3156 static int
3157 dprov_encrypt_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *encrypt_mech,
3158     crypto_key_t *encrypt_key, crypto_mechanism_t *mac_mech,
3159     crypto_key_t *mac_key, crypto_spi_ctx_template_t encr_ctx_template,
3160     crypto_spi_ctx_template_t mac_ctx_template,
3161     crypto_req_handle_t req)
3162 {
3163 	int error = CRYPTO_FAILED;
3164 	dprov_state_t *softc;
3165 	/* LINTED E_FUNC_SET_NOT_USED */
3166 	int instance;
3167 
3168 	/* extract softc and instance number from context */
3169 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3170 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_init: started\n",
3171 	    instance));
3172 
3173 	/* check mechanisms */
3174 	if (!dprov_valid_cipher_mech(encrypt_mech->cm_type)) {
3175 		cmn_err(CE_WARN, "dprov_encrypt_mac_init: unexpected encrypt "
3176 		    "mech type 0x%llx\n",
3177 		    (unsigned long long)encrypt_mech->cm_type);
3178 		return (CRYPTO_MECHANISM_INVALID);
3179 	}
3180 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3181 		cmn_err(CE_WARN, "dprov_encrypt_mac_init: unexpected mac "
3182 		    "mech type 0x%llx\n",
3183 		    (unsigned long long)mac_mech->cm_type);
3184 		return (CRYPTO_MECHANISM_INVALID);
3185 	}
3186 
3187 	if (encr_ctx_template != NULL || mac_ctx_template != NULL)
3188 		return (CRYPTO_ARGUMENTS_BAD);
3189 
3190 	/* submit request to the taskq */
3191 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_INIT,
3192 	    softc, req, ctx, 0, encrypt_mech, encrypt_key, mac_mech, mac_key,
3193 	    NULL, NULL, NULL, KM_SLEEP);
3194 
3195 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_init: done "
3196 	    "err = 0x%x\n", instance, error));
3197 
3198 	return (error);
3199 }
3200 
3201 static int
3202 dprov_encrypt_mac(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3203     crypto_dual_data_t *ciphertext, crypto_data_t *mac, crypto_req_handle_t req)
3204 {
3205 	int error = CRYPTO_FAILED;
3206 	dprov_state_t *softc;
3207 	/* LINTED E_FUNC_SET_NOT_USED */
3208 	int instance;
3209 
3210 	/* extract softc and instance number from context */
3211 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3212 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac: started\n",
3213 	    instance));
3214 
3215 	/*
3216 	 * submit request to the taskq
3217 	 * Careful! cihertext/plaintext order inversion
3218 	 */
3219 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC,
3220 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3221 	    ciphertext, plaintext, mac, KM_NOSLEEP);
3222 
3223 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac: done "
3224 	    "err = 0x%x\n", instance, error));
3225 
3226 	return (error);
3227 }
3228 
3229 static int
3230 dprov_encrypt_mac_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3231     crypto_dual_data_t *ciphertext, crypto_req_handle_t req)
3232 {
3233 	int error = CRYPTO_FAILED;
3234 	dprov_state_t *softc;
3235 	/* LINTED E_FUNC_SET_NOT_USED */
3236 	int instance;
3237 
3238 	/* extract softc and instance number from context */
3239 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3240 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_update: started\n",
3241 	    instance));
3242 
3243 	/* submit request to the taskq */
3244 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_UPDATE,
3245 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3246 	    ciphertext, plaintext, NULL, KM_NOSLEEP);
3247 
3248 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_update: done "
3249 	    "err = 0x%x\n", instance, error));
3250 
3251 	return (error);
3252 }
3253 
3254 static int
3255 dprov_encrypt_mac_final(crypto_ctx_t *ctx,
3256     crypto_dual_data_t *ciphertext, crypto_data_t *mac,
3257     crypto_req_handle_t req)
3258 {
3259 	int error = CRYPTO_FAILED;
3260 	dprov_state_t *softc;
3261 	/* LINTED E_FUNC_SET_NOT_USED */
3262 	int instance;
3263 
3264 	/* extract softc and instance number from context */
3265 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3266 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_final: started\n",
3267 	    instance));
3268 
3269 	/* submit request to the taskq */
3270 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_FINAL,
3271 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3272 	    ciphertext, NULL, mac, KM_NOSLEEP);
3273 
3274 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_final: done "
3275 	    "err = 0x%x\n", instance, error));
3276 
3277 	return (error);
3278 }
3279 
3280 static int
3281 dprov_encrypt_mac_atomic(crypto_provider_handle_t provider,
3282     crypto_session_id_t session_id, crypto_mechanism_t *encrypt_mech,
3283     crypto_key_t *encrypt_key, crypto_mechanism_t *mac_mech,
3284     crypto_key_t *mac_key, crypto_data_t *plaintext,
3285     crypto_dual_data_t *ciphertext, crypto_data_t *mac,
3286     crypto_spi_ctx_template_t encr_ctx_template,
3287     crypto_spi_ctx_template_t mac_ctx_template,
3288     crypto_req_handle_t req)
3289 {
3290 	int error = CRYPTO_FAILED;
3291 	dprov_state_t *softc = (dprov_state_t *)provider;
3292 	/* LINTED E_FUNC_SET_NOT_USED */
3293 	int instance;
3294 
3295 	instance = ddi_get_instance(softc->ds_dip);
3296 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_atomic: started\n",
3297 	    instance));
3298 
3299 	/* check mechanisms */
3300 	if (!dprov_valid_cipher_mech(encrypt_mech->cm_type)) {
3301 		cmn_err(CE_WARN, "dprov_encrypt_mac_atomic: unexpected encrypt "
3302 		    "mech type 0x%llx\n",
3303 		    (unsigned long long)encrypt_mech->cm_type);
3304 		return (CRYPTO_MECHANISM_INVALID);
3305 	}
3306 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3307 		cmn_err(CE_WARN, "dprov_encrypt_mac_atomic: unexpected mac "
3308 		    "mech type 0x%llx\n",
3309 		    (unsigned long long)mac_mech->cm_type);
3310 		return (CRYPTO_MECHANISM_INVALID);
3311 	}
3312 
3313 	if (encr_ctx_template != NULL || mac_ctx_template != NULL)
3314 		return (CRYPTO_ARGUMENTS_BAD);
3315 
3316 	/* submit request to the taskq */
3317 	error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_ATOMIC,
3318 	    softc, req, NULL, session_id, encrypt_mech, encrypt_key, mac_mech,
3319 	    mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3320 
3321 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_atomic: done "
3322 	    "err = 0x%x\n", instance, error));
3323 
3324 	return (error);
3325 }
3326 
3327 static int
3328 dprov_mac_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mac_mech,
3329     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3330     crypto_key_t *decrypt_key, crypto_spi_ctx_template_t mac_ctx_template,
3331     crypto_spi_ctx_template_t decr_ctx_template,
3332     crypto_req_handle_t req)
3333 {
3334 	int error = CRYPTO_FAILED;
3335 	dprov_state_t *softc;
3336 	/* LINTED E_FUNC_SET_NOT_USED */
3337 	int instance;
3338 
3339 	/* extract softc and instance number from context */
3340 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3341 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_init: started\n",
3342 	    instance));
3343 
3344 	/* check mechanisms */
3345 	if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3346 		cmn_err(CE_WARN, "dprov_mac_decrypt_init: unexpected decrypt "
3347 		    "mech type 0x%llx\n",
3348 		    (unsigned long long)decrypt_mech->cm_type);
3349 		return (CRYPTO_MECHANISM_INVALID);
3350 	}
3351 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3352 		cmn_err(CE_WARN, "dprov_mac_decrypt_init: unexpected mac "
3353 		    "mech type 0x%llx\n",
3354 		    (unsigned long long)mac_mech->cm_type);
3355 		return (CRYPTO_MECHANISM_INVALID);
3356 	}
3357 
3358 	if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3359 		return (CRYPTO_ARGUMENTS_BAD);
3360 
3361 	/* submit request to the taskq */
3362 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_INIT,
3363 	    softc, req, ctx, 0, decrypt_mech, decrypt_key, mac_mech, mac_key,
3364 	    NULL, NULL, NULL, KM_SLEEP);
3365 
3366 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_init: done "
3367 	    "err = 0x%x\n", instance, error));
3368 
3369 	return (error);
3370 }
3371 
3372 static int
3373 dprov_mac_decrypt(crypto_ctx_t *ctx, crypto_dual_data_t *ciphertext,
3374     crypto_data_t *mac, crypto_data_t *plaintext, crypto_req_handle_t req)
3375 {
3376 	int error = CRYPTO_FAILED;
3377 	dprov_state_t *softc;
3378 	/* LINTED E_FUNC_SET_NOT_USED */
3379 	int instance;
3380 
3381 	/* extract softc and instance number from context */
3382 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3383 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt: started\n",
3384 	    instance));
3385 
3386 	/* submit request to the taskq */
3387 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT,
3388 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3389 	    ciphertext, plaintext, mac, KM_NOSLEEP);
3390 
3391 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt: done "
3392 	    "err = 0x%x\n", instance, error));
3393 
3394 	return (error);
3395 }
3396 
3397 static int
3398 dprov_mac_decrypt_update(crypto_ctx_t *ctx, crypto_dual_data_t *ciphertext,
3399     crypto_data_t *plaintext, crypto_req_handle_t req)
3400 {
3401 	int error = CRYPTO_FAILED;
3402 	dprov_state_t *softc;
3403 	/* LINTED E_FUNC_SET_NOT_USED */
3404 	int instance;
3405 
3406 	/* extract softc and instance number from context */
3407 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3408 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_update: started\n",
3409 	    instance));
3410 
3411 	/* submit request to the taskq */
3412 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_UPDATE,
3413 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3414 	    ciphertext, plaintext, NULL, KM_NOSLEEP);
3415 
3416 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_update: done "
3417 	    "err = 0x%x\n", instance, error));
3418 
3419 	return (error);
3420 }
3421 
3422 static int
3423 dprov_mac_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *mac,
3424     crypto_data_t *plaintext, crypto_req_handle_t req)
3425 {
3426 	int error = CRYPTO_FAILED;
3427 	dprov_state_t *softc;
3428 	/* LINTED E_FUNC_SET_NOT_USED */
3429 	int instance;
3430 
3431 	/* extract softc and instance number from context */
3432 	DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3433 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_final: started\n",
3434 	    instance));
3435 
3436 	/* submit request to the taskq */
3437 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_FINAL,
3438 	    softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3439 	    NULL, plaintext, mac, KM_NOSLEEP);
3440 
3441 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_final: done "
3442 	    "err = 0x%x\n", instance, error));
3443 
3444 	return (error);
3445 }
3446 
3447 static int
3448 dprov_mac_decrypt_atomic(crypto_provider_handle_t provider,
3449     crypto_session_id_t session_id, crypto_mechanism_t *mac_mech,
3450     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3451     crypto_key_t *decrypt_key, crypto_dual_data_t *ciphertext,
3452     crypto_data_t *mac, crypto_data_t *plaintext,
3453     crypto_spi_ctx_template_t mac_ctx_template,
3454     crypto_spi_ctx_template_t decr_ctx_template,
3455     crypto_req_handle_t req)
3456 {
3457 	int error = CRYPTO_FAILED;
3458 	dprov_state_t *softc = (dprov_state_t *)provider;
3459 	/* LINTED E_FUNC_SET_NOT_USED */
3460 	int instance;
3461 
3462 	instance = ddi_get_instance(softc->ds_dip);
3463 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_atomic: started\n",
3464 	    instance));
3465 
3466 	/* check mechanisms */
3467 	if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3468 		cmn_err(CE_WARN, "dprov_mac_decrypt_atomic: unexpected encrypt "
3469 		    "mech type 0x%llx\n",
3470 		    (unsigned long long)decrypt_mech->cm_type);
3471 		return (CRYPTO_MECHANISM_INVALID);
3472 	}
3473 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3474 		cmn_err(CE_WARN, "dprov_mac_decrypt_atomic: unexpected mac "
3475 		    "mech type 0x%llx\n",
3476 		    (unsigned long long)mac_mech->cm_type);
3477 		return (CRYPTO_MECHANISM_INVALID);
3478 	}
3479 
3480 	if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3481 		return (CRYPTO_ARGUMENTS_BAD);
3482 
3483 	/* submit request to the taskq */
3484 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_ATOMIC,
3485 	    softc, req, NULL, session_id, decrypt_mech, decrypt_key, mac_mech,
3486 	    mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3487 
3488 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_atomic: done "
3489 	    "err = 0x%x\n", instance, error));
3490 
3491 	return (error);
3492 }
3493 
3494 static int
3495 dprov_mac_verify_decrypt_atomic(crypto_provider_handle_t provider,
3496     crypto_session_id_t session_id, crypto_mechanism_t *mac_mech,
3497     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3498     crypto_key_t *decrypt_key, crypto_dual_data_t *ciphertext,
3499     crypto_data_t *mac, crypto_data_t *plaintext,
3500     crypto_spi_ctx_template_t mac_ctx_template,
3501     crypto_spi_ctx_template_t decr_ctx_template,
3502     crypto_req_handle_t req)
3503 {
3504 	int error = CRYPTO_FAILED;
3505 	dprov_state_t *softc = (dprov_state_t *)provider;
3506 	/* LINTED E_FUNC_SET_NOT_USED */
3507 	int instance;
3508 
3509 	instance = ddi_get_instance(softc->ds_dip);
3510 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_verify_decrypt_atomic:"
3511 	    "started\n", instance));
3512 
3513 	/* check mechanisms */
3514 	if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3515 		cmn_err(CE_WARN, "dprov_mac_verify_decrypt_atomic: "
3516 		    "unexpected encrypt mech type 0x%llx\n",
3517 		    (unsigned long long)decrypt_mech->cm_type);
3518 		return (CRYPTO_MECHANISM_INVALID);
3519 	}
3520 	if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3521 		cmn_err(CE_WARN, "dprov_mac_verify_decrypt_atomic: "
3522 		    "unexpected mac mech type 0x%llx\n",
3523 		    (unsigned long long)mac_mech->cm_type);
3524 		return (CRYPTO_MECHANISM_INVALID);
3525 	}
3526 
3527 	if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3528 		return (CRYPTO_ARGUMENTS_BAD);
3529 
3530 	/* submit request to the taskq */
3531 	error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC,
3532 	    softc, req, NULL, session_id, decrypt_mech, decrypt_key, mac_mech,
3533 	    mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3534 
3535 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_verify_decrypt_atomic: done "
3536 	    "err = 0x%x\n", instance, error));
3537 
3538 	return (error);
3539 }
3540 
3541 /*
3542  * Random number entry points.
3543  */
3544 
3545 static int
3546 dprov_seed_random(crypto_provider_handle_t provider,  crypto_session_id_t sid,
3547     uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags,
3548     crypto_req_handle_t req)
3549 {
3550 	int error = CRYPTO_FAILED;
3551 	dprov_state_t *softc = (dprov_state_t *)provider;
3552 	/* LINTED E_FUNC_SET_NOT_USED */
3553 	int instance;
3554 
3555 	instance = ddi_get_instance(softc->ds_dip);
3556 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: started\n",
3557 	    instance));
3558 
3559 	error = dprov_random_submit_req(DPROV_REQ_RANDOM_SEED, softc,
3560 	    req, buf, len, sid, entropy_est, flags);
3561 
3562 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: done err = 0x0%x\n",
3563 	    instance, error));
3564 
3565 	return (error);
3566 }
3567 
3568 static int
3569 dprov_generate_random(crypto_provider_handle_t provider,
3570     crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req)
3571 {
3572 	int error = CRYPTO_FAILED;
3573 	dprov_state_t *softc = (dprov_state_t *)provider;
3574 	/* LINTED E_FUNC_SET_NOT_USED */
3575 	int instance;
3576 
3577 	instance = ddi_get_instance(softc->ds_dip);
3578 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: started\n",
3579 	    instance));
3580 
3581 	error = dprov_random_submit_req(DPROV_REQ_RANDOM_GENERATE, softc,
3582 	    req, buf, len, sid, 0, 0);
3583 
3584 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: done "
3585 	    "err = 0x0%x\n", instance, error));
3586 
3587 	return (error);
3588 }
3589 
3590 /*
3591  * Session Management entry points.
3592  */
3593 
3594 static int
3595 dprov_session_open(crypto_provider_handle_t provider,
3596     crypto_session_id_t *session_id, crypto_req_handle_t req)
3597 {
3598 	int error = CRYPTO_FAILED;
3599 	dprov_state_t *softc = (dprov_state_t *)provider;
3600 	/* LINTED E_FUNC_SET_NOT_USED */
3601 	int instance;
3602 
3603 	instance = ddi_get_instance(softc->ds_dip);
3604 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_open: started\n",
3605 	    instance));
3606 
3607 	error = dprov_session_submit_req(DPROV_REQ_SESSION_OPEN, softc,
3608 	    req, session_id, 0, 0, NULL, 0);
3609 
3610 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_open: done err = 0x0%x\n",
3611 	    instance, error));
3612 
3613 	return (error);
3614 }
3615 
3616 static int
3617 dprov_session_close(crypto_provider_handle_t provider,
3618     crypto_session_id_t session_id, crypto_req_handle_t req)
3619 {
3620 	int error = CRYPTO_FAILED;
3621 	dprov_state_t *softc = (dprov_state_t *)provider;
3622 	/* LINTED E_FUNC_SET_NOT_USED */
3623 	int instance;
3624 
3625 	instance = ddi_get_instance(softc->ds_dip);
3626 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_close: started\n",
3627 	    instance));
3628 
3629 	error = dprov_session_submit_req(DPROV_REQ_SESSION_CLOSE, softc,
3630 	    req, 0, session_id, 0, NULL, 0);
3631 
3632 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_close: done err = 0x0%x\n",
3633 	    instance, error));
3634 
3635 	return (error);
3636 }
3637 
3638 static int
3639 dprov_session_login(crypto_provider_handle_t provider,
3640     crypto_session_id_t session_id, crypto_user_type_t user_type,
3641     char *pin, size_t pin_len, crypto_req_handle_t req)
3642 {
3643 	int error = CRYPTO_FAILED;
3644 	dprov_state_t *softc = (dprov_state_t *)provider;
3645 	/* LINTED E_FUNC_SET_NOT_USED */
3646 	int instance;
3647 
3648 	instance = ddi_get_instance(softc->ds_dip);
3649 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_login: started\n",
3650 	    instance));
3651 
3652 	error = dprov_session_submit_req(DPROV_REQ_SESSION_LOGIN, softc,
3653 	    req, 0, session_id, user_type, pin, pin_len);
3654 
3655 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_login: done err = 0x0%x\n",
3656 	    instance, error));
3657 
3658 	return (error);
3659 }
3660 
3661 static int
3662 dprov_session_logout(crypto_provider_handle_t provider,
3663     crypto_session_id_t session_id, crypto_req_handle_t req)
3664 {
3665 	int error = CRYPTO_FAILED;
3666 	dprov_state_t *softc = (dprov_state_t *)provider;
3667 	/* LINTED E_FUNC_SET_NOT_USED */
3668 	int instance;
3669 
3670 	instance = ddi_get_instance(softc->ds_dip);
3671 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_logout: started\n",
3672 	    instance));
3673 
3674 	error = dprov_session_submit_req(DPROV_REQ_SESSION_LOGOUT, softc,
3675 	    req, 0, session_id, 0, NULL, 0);
3676 
3677 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_logout: done err = 0x0%x\n",
3678 	    instance, error));
3679 
3680 	return (error);
3681 }
3682 
3683 /*
3684  * Object management entry points.
3685  */
3686 
3687 static int
3688 dprov_object_create(crypto_provider_handle_t provider,
3689     crypto_session_id_t session_id, crypto_object_attribute_t *template,
3690     uint_t attribute_count, crypto_object_id_t *object,
3691     crypto_req_handle_t req)
3692 {
3693 	int error = CRYPTO_FAILED;
3694 	dprov_state_t *softc = (dprov_state_t *)provider;
3695 	/* LINTED E_FUNC_SET_NOT_USED */
3696 	int instance;
3697 
3698 	instance = ddi_get_instance(softc->ds_dip);
3699 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_create: started\n",
3700 	    instance));
3701 
3702 	/* submit request to the taskq */
3703 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_CREATE, softc, req,
3704 	    session_id, 0, template, attribute_count, object, NULL, NULL,
3705 	    NULL, 0, NULL, KM_NOSLEEP);
3706 
3707 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_create: done err = 0x0%x\n",
3708 	    instance, error));
3709 
3710 	return (error);
3711 }
3712 
3713 static int
3714 dprov_object_copy(crypto_provider_handle_t provider,
3715     crypto_session_id_t session_id, crypto_object_id_t object,
3716     crypto_object_attribute_t *template, uint_t attribute_count,
3717     crypto_object_id_t *new_object, crypto_req_handle_t req)
3718 {
3719 	int error = CRYPTO_FAILED;
3720 	dprov_state_t *softc = (dprov_state_t *)provider;
3721 	/* LINTED E_FUNC_SET_NOT_USED */
3722 	int instance;
3723 
3724 	instance = ddi_get_instance(softc->ds_dip);
3725 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_copy: started\n",
3726 	    instance));
3727 
3728 	/* submit request to the taskq */
3729 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_COPY, softc, req,
3730 	    session_id, object, template, attribute_count, new_object,
3731 	    NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3732 
3733 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_copy: done err = 0x0%x\n",
3734 	    instance, error));
3735 
3736 	return (error);
3737 }
3738 
3739 static int
3740 dprov_object_destroy(crypto_provider_handle_t provider,
3741     crypto_session_id_t session_id, crypto_object_id_t object,
3742     crypto_req_handle_t req)
3743 {
3744 	int error = CRYPTO_FAILED;
3745 	dprov_state_t *softc = (dprov_state_t *)provider;
3746 	/* LINTED E_FUNC_SET_NOT_USED */
3747 	int instance;
3748 
3749 	instance = ddi_get_instance(softc->ds_dip);
3750 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_destroy: started\n",
3751 	    instance));
3752 
3753 	/* submit request to the taskq */
3754 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_DESTROY, softc, req,
3755 	    session_id, object, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL,
3756 	    KM_NOSLEEP);
3757 
3758 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_destroy: done err = 0x0%x\n",
3759 	    instance, error));
3760 
3761 	return (error);
3762 }
3763 
3764 static int
3765 dprov_object_get_size(crypto_provider_handle_t provider,
3766     crypto_session_id_t session_id, crypto_object_id_t object,
3767     size_t *size, crypto_req_handle_t req)
3768 {
3769 	int error = CRYPTO_FAILED;
3770 	dprov_state_t *softc = (dprov_state_t *)provider;
3771 	/* LINTED E_FUNC_SET_NOT_USED */
3772 	int instance;
3773 
3774 	instance = ddi_get_instance(softc->ds_dip);
3775 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_size: started\n",
3776 	    instance));
3777 
3778 	/* submit request to the taskq */
3779 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_GET_SIZE, softc, req,
3780 	    session_id, object, NULL, 0, NULL, size, NULL, NULL, 0, NULL,
3781 	    KM_NOSLEEP);
3782 
3783 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_size: done err = 0x0%x\n",
3784 	    instance, error));
3785 
3786 	return (error);
3787 }
3788 
3789 static int
3790 dprov_object_get_attribute_value(crypto_provider_handle_t provider,
3791     crypto_session_id_t session_id, crypto_object_id_t object,
3792     crypto_object_attribute_t *template, uint_t attribute_count,
3793     crypto_req_handle_t req)
3794 {
3795 	int error = CRYPTO_FAILED;
3796 	dprov_state_t *softc = (dprov_state_t *)provider;
3797 	/* LINTED E_FUNC_SET_NOT_USED */
3798 	int instance;
3799 
3800 	instance = ddi_get_instance(softc->ds_dip);
3801 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_attribute_value: "
3802 	    "started\n", instance));
3803 
3804 	/* submit request to the taskq */
3805 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE,
3806 	    softc, req, session_id, object, template, attribute_count,
3807 	    NULL, NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3808 
3809 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_attribute_value: "
3810 	    "done err = 0x0%x\n", instance, error));
3811 
3812 	return (error);
3813 }
3814 
3815 static int
3816 dprov_object_set_attribute_value(crypto_provider_handle_t provider,
3817     crypto_session_id_t session_id, crypto_object_id_t object,
3818     crypto_object_attribute_t *template, uint_t attribute_count,
3819     crypto_req_handle_t req)
3820 {
3821 	int error = CRYPTO_FAILED;
3822 	dprov_state_t *softc = (dprov_state_t *)provider;
3823 	/* LINTED E_FUNC_SET_NOT_USED */
3824 	int instance;
3825 
3826 	instance = ddi_get_instance(softc->ds_dip);
3827 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_set_attribute_value: "
3828 	    "started\n", instance));
3829 
3830 	/* submit request to the taskq */
3831 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE,
3832 	    softc, req, session_id, object, template, attribute_count,
3833 	    NULL, NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3834 
3835 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_set_attribute_value: "
3836 	    "done err = 0x0%x\n", instance, error));
3837 
3838 	return (error);
3839 }
3840 
3841 static int
3842 dprov_object_find_init(crypto_provider_handle_t provider,
3843     crypto_session_id_t session_id, crypto_object_attribute_t *template,
3844     uint_t attribute_count, void **provider_private,
3845     crypto_req_handle_t req)
3846 {
3847 	int error = CRYPTO_FAILED;
3848 	dprov_state_t *softc = (dprov_state_t *)provider;
3849 	/* LINTED E_FUNC_SET_NOT_USED */
3850 	int instance;
3851 
3852 	instance = ddi_get_instance(softc->ds_dip);
3853 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_init: started\n",
3854 	    instance));
3855 
3856 	/* submit request to the taskq */
3857 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND_INIT, softc, req,
3858 	    session_id, 0, template, attribute_count, NULL, NULL,
3859 	    provider_private, NULL, 0, NULL, KM_SLEEP);
3860 
3861 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_init: done "
3862 	    "err = 0x0%x\n", instance, error));
3863 
3864 	return (error);
3865 }
3866 
3867 static int
3868 dprov_object_find(crypto_provider_handle_t provider, void *provider_private,
3869     crypto_object_id_t *objects, uint_t max_object_count,
3870     uint_t *object_count, crypto_req_handle_t req)
3871 {
3872 	int error = CRYPTO_FAILED;
3873 	dprov_state_t *softc = (dprov_state_t *)provider;
3874 	/* LINTED E_FUNC_SET_NOT_USED */
3875 	int instance;
3876 
3877 	instance = ddi_get_instance(softc->ds_dip);
3878 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find: started\n",
3879 	    instance));
3880 
3881 	/* submit request to the taskq */
3882 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND, softc, req,
3883 	    0, 0, NULL, 0, objects, NULL, NULL, provider_private,
3884 	    max_object_count, object_count, KM_NOSLEEP);
3885 
3886 
3887 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find: done err = 0x0%x\n",
3888 	    instance, error));
3889 
3890 	return (error);
3891 }
3892 
3893 static int
3894 dprov_object_find_final(crypto_provider_handle_t provider,
3895     void *provider_private, crypto_req_handle_t req)
3896 {
3897 	int error = CRYPTO_FAILED;
3898 	dprov_state_t *softc = (dprov_state_t *)provider;
3899 	/* LINTED E_FUNC_SET_NOT_USED */
3900 	int instance;
3901 
3902 	instance = ddi_get_instance(softc->ds_dip);
3903 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_final: started\n",
3904 	    instance));
3905 
3906 	/* submit request to the taskq */
3907 	error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND_FINAL, softc, req,
3908 	    0, 0, NULL, 0, NULL, NULL, NULL, provider_private,
3909 	    0, NULL, KM_NOSLEEP);
3910 
3911 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_final: done "
3912 	    "err = 0x0%x\n", instance, error));
3913 
3914 	return (error);
3915 }
3916 
3917 /*
3918  * Key management entry points.
3919  */
3920 
3921 static int
3922 dprov_key_generate(crypto_provider_handle_t provider,
3923     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3924     crypto_object_attribute_t *template, uint_t attribute_count,
3925     crypto_object_id_t *object, crypto_req_handle_t req)
3926 {
3927 	int error = CRYPTO_FAILED;
3928 	dprov_state_t *softc = (dprov_state_t *)provider;
3929 	/* LINTED E_FUNC_SET_NOT_USED */
3930 	int instance;
3931 
3932 	instance = ddi_get_instance(softc->ds_dip);
3933 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate: started\n",
3934 	    instance));
3935 
3936 	/* submit request to the taskq */
3937 	error = dprov_key_submit_req(DPROV_REQ_KEY_GENERATE, softc, req,
3938 	    session_id, mechanism, template, attribute_count, object, NULL,
3939 	    0, NULL, NULL, NULL, 0, NULL, 0, NULL, 0);
3940 
3941 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate: done err = 0x0%x\n",
3942 	    instance, error));
3943 
3944 	return (error);
3945 }
3946 
3947 static int
3948 dprov_key_generate_pair(crypto_provider_handle_t provider,
3949     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3950     crypto_object_attribute_t *public_key_template,
3951     uint_t public_key_attribute_count,
3952     crypto_object_attribute_t *private_key_template,
3953     uint_t private_key_attribute_count,
3954     crypto_object_id_t *public_key, crypto_object_id_t *private_key,
3955     crypto_req_handle_t req)
3956 {
3957 	int error = CRYPTO_FAILED;
3958 	dprov_state_t *softc = (dprov_state_t *)provider;
3959 	/* LINTED E_FUNC_SET_NOT_USED */
3960 	int instance;
3961 
3962 	instance = ddi_get_instance(softc->ds_dip);
3963 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate_pair: started\n",
3964 	    instance));
3965 
3966 	/* submit request to the taskq */
3967 	error = dprov_key_submit_req(DPROV_REQ_KEY_GENERATE_PAIR, softc, req,
3968 	    session_id, mechanism, public_key_template,
3969 	    public_key_attribute_count, public_key, private_key_template,
3970 	    private_key_attribute_count, private_key, NULL, NULL, 0, NULL, 0,
3971 	    NULL, 0);
3972 
3973 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate_pair: done err = 0x0%x\n",
3974 	    instance, error));
3975 
3976 	return (error);
3977 }
3978 
3979 static int
3980 dprov_key_wrap(crypto_provider_handle_t provider,
3981     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3982     crypto_key_t *wrapping_key, crypto_object_id_t *key,
3983     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr, crypto_req_handle_t req)
3984 {
3985 	int error = CRYPTO_FAILED;
3986 	dprov_state_t *softc = (dprov_state_t *)provider;
3987 	/* LINTED E_FUNC_SET_NOT_USED */
3988 	int instance;
3989 
3990 	instance = ddi_get_instance(softc->ds_dip);
3991 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_wrap: started\n",
3992 	    instance));
3993 
3994 	/* submit request to the taskq */
3995 	error = dprov_key_submit_req(DPROV_REQ_KEY_WRAP, softc, req,
3996 	    session_id, mechanism, NULL, 0, key, NULL,
3997 	    0, NULL, wrapping_key, wrapped_key, wrapped_key_len_ptr,
3998 	    NULL, 0, NULL, 0);
3999 
4000 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_wrap: done err = 0x0%x\n",
4001 	    instance, error));
4002 
4003 	return (error);
4004 }
4005 
4006 static int
4007 dprov_key_unwrap(crypto_provider_handle_t provider,
4008     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4009     crypto_key_t *unwrapping_key, uchar_t *wrapped_key,
4010     size_t *wrapped_key_len_ptr, crypto_object_attribute_t *template,
4011     uint_t attribute_count, crypto_object_id_t *key, crypto_req_handle_t req)
4012 {
4013 	int error = CRYPTO_FAILED;
4014 	dprov_state_t *softc = (dprov_state_t *)provider;
4015 	/* LINTED E_FUNC_SET_NOT_USED */
4016 	int instance;
4017 
4018 	instance = ddi_get_instance(softc->ds_dip);
4019 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_unwrap: started\n",
4020 	    instance));
4021 
4022 	/* submit request to the taskq */
4023 	error = dprov_key_submit_req(DPROV_REQ_KEY_UNWRAP, softc, req,
4024 	    session_id, mechanism, template, attribute_count, key, NULL,
4025 	    0, NULL, unwrapping_key, wrapped_key, wrapped_key_len_ptr,
4026 	    NULL, 0, NULL, 0);
4027 
4028 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_unwrap: done err = 0x0%x\n",
4029 	    instance, error));
4030 
4031 	return (error);
4032 }
4033 
4034 static int
4035 dprov_key_derive(crypto_provider_handle_t provider,
4036     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4037     crypto_key_t *base_key, crypto_object_attribute_t *template,
4038     uint_t attribute_count, crypto_object_id_t *key, crypto_req_handle_t req)
4039 {
4040 	int error = CRYPTO_FAILED;
4041 	dprov_state_t *softc = (dprov_state_t *)provider;
4042 	/* LINTED E_FUNC_SET_NOT_USED */
4043 	int instance;
4044 
4045 	instance = ddi_get_instance(softc->ds_dip);
4046 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_derive: started\n",
4047 	    instance));
4048 
4049 	/* submit request to the taskq */
4050 	error = dprov_key_submit_req(DPROV_REQ_KEY_DERIVE, softc, req,
4051 	    session_id, mechanism, template, attribute_count, key, NULL,
4052 	    0, NULL, base_key, NULL, 0, NULL, 0, NULL, 0);
4053 
4054 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_derive: done err = 0x0%x\n",
4055 	    instance, error));
4056 
4057 	return (error);
4058 }
4059 
4060 /*
4061  * Provider management entry points.
4062  */
4063 
4064 static int
4065 dprov_ext_info(crypto_provider_handle_t provider,
4066     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t req)
4067 {
4068 	int error = CRYPTO_FAILED;
4069 	dprov_state_t *softc = (dprov_state_t *)provider;
4070 	/* LINTED E_FUNC_SET_NOT_USED */
4071 	int instance;
4072 
4073 	instance = ddi_get_instance(softc->ds_dip);
4074 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_ext_info: started\n",
4075 	    instance));
4076 
4077 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_EXTINFO, softc, req,
4078 	    0, NULL, 0, NULL, 0, NULL, ext_info);
4079 
4080 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_ext_info: done err = 0x0%x\n",
4081 	    instance, error));
4082 
4083 	return (error);
4084 }
4085 
4086 static int
4087 dprov_init_token(crypto_provider_handle_t provider, char *pin, size_t pin_len,
4088     char *label, crypto_req_handle_t req)
4089 {
4090 	int error = CRYPTO_FAILED;
4091 	dprov_state_t *softc = (dprov_state_t *)provider;
4092 	/* LINTED E_FUNC_SET_NOT_USED */
4093 	int instance;
4094 
4095 	instance = ddi_get_instance(softc->ds_dip);
4096 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_token: started\n",
4097 	    instance));
4098 
4099 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_INITTOKEN, softc, req,
4100 	    0, pin, pin_len, NULL, 0, label, NULL);
4101 
4102 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_token: done err = 0x0%x\n",
4103 	    instance, error));
4104 
4105 	return (error);
4106 }
4107 
4108 static int
4109 dprov_init_pin(crypto_provider_handle_t provider,
4110     crypto_session_id_t session_id, char *pin, size_t pin_len,
4111     crypto_req_handle_t req)
4112 {
4113 	int error = CRYPTO_FAILED;
4114 	dprov_state_t *softc = (dprov_state_t *)provider;
4115 	/* LINTED E_FUNC_SET_NOT_USED */
4116 	int instance;
4117 
4118 	instance = ddi_get_instance(softc->ds_dip);
4119 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_pin: started\n",
4120 	    instance));
4121 
4122 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_INITPIN, softc, req,
4123 	    session_id, pin, pin_len, NULL, 0, NULL, NULL);
4124 
4125 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_pin: done err = 0x0%x\n",
4126 	    instance, error));
4127 
4128 	return (error);
4129 }
4130 
4131 static int
4132 dprov_set_pin(crypto_provider_handle_t provider, crypto_session_id_t session_id,
4133     char *old_pin, size_t old_pin_len, char *new_pin, size_t new_pin_len,
4134     crypto_req_handle_t req)
4135 {
4136 	int error = CRYPTO_FAILED;
4137 	dprov_state_t *softc = (dprov_state_t *)provider;
4138 	/* LINTED E_FUNC_SET_NOT_USED */
4139 	int instance;
4140 
4141 	instance = ddi_get_instance(softc->ds_dip);
4142 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_set_pin: started\n",
4143 	    instance));
4144 
4145 	error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_SETPIN, softc, req,
4146 	    session_id, new_pin, new_pin_len, old_pin, old_pin_len, NULL, NULL);
4147 
4148 	DPROV_DEBUG(D_MGMT, ("(%d) dprov_set_pin: done err = 0x0%x\n",
4149 	    instance, error));
4150 
4151 	return (error);
4152 }
4153 
4154 
4155 /*
4156  * Context management entry points.
4157  */
4158 
4159 /*
4160  * Allocate a dprov-private context based on the specified dprov request.
4161  * For dual cipher/mac requests, the allocated context will
4162  * contain a structure dprov_ctx_dual_t, for other request types,
4163  * it will contain a dprov_ctx_single.
4164  * Returns one of the CRYPTO_ status codes.
4165  */
4166 static int
4167 dprov_alloc_context(dprov_req_type_t req_type, crypto_ctx_t *spi_ctx)
4168 {
4169 	dprov_ctx_single_t *dprov_private;
4170 
4171 	switch (req_type) {
4172 	case DPROV_REQ_ENCRYPT_MAC_INIT:
4173 	case DPROV_REQ_MAC_DECRYPT_INIT:
4174 		dprov_private = kmem_zalloc(sizeof (dprov_ctx_dual_t),
4175 		    KM_NOSLEEP);
4176 		if (dprov_private == NULL)
4177 			return (CRYPTO_HOST_MEMORY);
4178 		dprov_private->dc_type = DPROV_CTX_DUAL;
4179 		break;
4180 	default:
4181 		dprov_private = kmem_zalloc(sizeof (dprov_ctx_single_t),
4182 		    KM_NOSLEEP);
4183 		if (dprov_private == NULL)
4184 			return (CRYPTO_HOST_MEMORY);
4185 		dprov_private->dc_type = DPROV_CTX_SINGLE;
4186 		dprov_private->dc_svrfy_to_mac = B_FALSE;
4187 		break;
4188 	}
4189 
4190 	spi_ctx->cc_provider_private = (void *)dprov_private;
4191 
4192 	return (CRYPTO_SUCCESS);
4193 }
4194 
4195 static int
4196 dprov_free_context(crypto_ctx_t *ctx)
4197 {
4198 	if (ctx->cc_provider_private == NULL)
4199 		return (CRYPTO_SUCCESS);
4200 
4201 	DPROV_DEBUG(D_CONTEXT, ("dprov_free_context\n"));
4202 
4203 	{
4204 		/*
4205 		 * The dprov private context could contain either
4206 		 * a dprov_ctx_single_t or a dprov_ctx_dual_t. Free
4207 		 * the context based on its type. The k-API contexts
4208 		 * that were attached to the dprov private context
4209 		 * are freed by the framework.
4210 		 */
4211 		dprov_ctx_single_t *ctx_single =
4212 		    (dprov_ctx_single_t *)(ctx->cc_provider_private);
4213 
4214 		if (ctx_single->dc_type == DPROV_CTX_SINGLE) {
4215 			crypto_context_t context = DPROV_CTX_SINGLE(ctx);
4216 
4217 			/*
4218 			 * This case happens for the crypto_cancel_ctx() case.
4219 			 * We have to cancel the SW provider context also.
4220 			 */
4221 			if (context != NULL)
4222 				crypto_cancel_ctx(context);
4223 
4224 			kmem_free(ctx_single, sizeof (dprov_ctx_single_t));
4225 		} else {
4226 			crypto_context_t cipher_context =
4227 			    DPROV_CTX_DUAL_CIPHER(ctx);
4228 			crypto_context_t mac_context = DPROV_CTX_DUAL_MAC(ctx);
4229 
4230 			/* See comments above. */
4231 			if (cipher_context != NULL)
4232 				crypto_cancel_ctx(cipher_context);
4233 			if (mac_context != NULL)
4234 				crypto_cancel_ctx(mac_context);
4235 
4236 			ASSERT(ctx_single->dc_type == DPROV_CTX_DUAL);
4237 			kmem_free(ctx_single, sizeof (dprov_ctx_dual_t));
4238 		}
4239 		ctx->cc_provider_private = NULL;
4240 	}
4241 
4242 	return (CRYPTO_SUCCESS);
4243 }
4244 
4245 /*
4246  * Resource control checks don't need to be done. Why? Because this routine
4247  * knows the size of the structure, and it can't be overridden by a user.
4248  * This is different from the crypto module, which has no knowledge of
4249  * specific mechanisms, and therefore has to trust specified size of the
4250  * parameter.  This trust, or lack of trust, is why the size of the
4251  * parameter has to be charged against the project resource control.
4252  */
4253 static int
4254 copyin_aes_ctr_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4255     int *out_error, int mode)
4256 {
4257 	STRUCT_DECL(crypto_mechanism, mech);
4258 	STRUCT_DECL(CK_AES_CTR_PARAMS, params);
4259 	CK_AES_CTR_PARAMS *aes_ctr_params;
4260 	caddr_t pp;
4261 	size_t param_len;
4262 	int error = 0;
4263 	int rv = 0;
4264 
4265 	STRUCT_INIT(mech, mode);
4266 	STRUCT_INIT(params, mode);
4267 	bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4268 	pp = STRUCT_FGETP(mech, cm_param);
4269 	param_len = STRUCT_FGET(mech, cm_param_len);
4270 
4271 	if (param_len != STRUCT_SIZE(params)) {
4272 		rv = CRYPTO_ARGUMENTS_BAD;
4273 		goto out;
4274 	}
4275 
4276 	out_mech->cm_type = STRUCT_FGET(mech, cm_type);
4277 	out_mech->cm_param = NULL;
4278 	out_mech->cm_param_len = 0;
4279 	if (pp != NULL) {
4280 		if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4281 			out_mech->cm_param = NULL;
4282 			error = EFAULT;
4283 			goto out;
4284 		}
4285 		/* allocate param structure and counter block */
4286 		aes_ctr_params = kmem_alloc(sizeof (CK_AES_CTR_PARAMS) + 16,
4287 		    KM_NOSLEEP);
4288 		if (aes_ctr_params == NULL) {
4289 			rv = CRYPTO_HOST_MEMORY;
4290 			goto out;
4291 		}
4292 		aes_ctr_params->cb = (uchar_t *)aes_ctr_params +
4293 		    sizeof (CK_AES_CTR_PARAMS);
4294 		aes_ctr_params->ulCounterBits = STRUCT_FGET(params,
4295 		    ulCounterBits);
4296 		if (copyin((char *)STRUCT_FGETP(params, cb),
4297 		    &aes_ctr_params->cb[0], 16) != 0) {
4298 			kmem_free(aes_ctr_params,
4299 			    sizeof (CK_AES_CTR_PARAMS) + 16);
4300 			out_mech->cm_param = NULL;
4301 			error = EFAULT;
4302 			goto out;
4303 		}
4304 		out_mech->cm_param = (char *)aes_ctr_params;
4305 		out_mech->cm_param_len = sizeof (CK_AES_CTR_PARAMS);
4306 	}
4307 out:
4308 	*out_error = error;
4309 	return (rv);
4310 }
4311 
4312 /* ARGSUSED */
4313 static int
4314 copyout_aes_ctr_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4315     int *out_error, int mode)
4316 {
4317 	STRUCT_DECL(crypto_mechanism, mech);
4318 	STRUCT_DECL(CK_AES_CTR_PARAMS, params);
4319 	uint8_t cb[16];
4320 	caddr_t pp;
4321 	size_t param_len;
4322 	int error = 0;
4323 	int rv = 0;
4324 
4325 	STRUCT_INIT(mech, mode);
4326 	STRUCT_INIT(params, mode);
4327 	bcopy(out_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4328 	pp = STRUCT_FGETP(mech, cm_param);
4329 	param_len = STRUCT_FGET(mech, cm_param_len);
4330 	if (param_len != STRUCT_SIZE(params)) {
4331 		rv = CRYPTO_ARGUMENTS_BAD;
4332 		goto out;
4333 	}
4334 
4335 	if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4336 		error = EFAULT;
4337 		goto out;
4338 	}
4339 
4340 	/* for testing, overwrite the iv with 16 X 'A' */
4341 	if (pp != NULL) {
4342 		(void) memset(cb, 'A', 16);
4343 		if (copyout(cb, STRUCT_FGETP(params, cb),  16) != 0) {
4344 			error = EFAULT;
4345 			goto out;
4346 		}
4347 	}
4348 out:
4349 	*out_error = error;
4350 	return (rv);
4351 }
4352 
4353 /* ARGSUSED */
4354 static int
4355 dprov_copyin_mechanism(crypto_provider_handle_t provider,
4356     crypto_mechanism_t *umech, crypto_mechanism_t *kmech,
4357     int *out_error, int mode)
4358 {
4359 	STRUCT_DECL(crypto_mechanism, mech);
4360 	size_t param_len, expected_param_len;
4361 	caddr_t pp;
4362 	char *param;
4363 	int rv;
4364 	int error = 0;
4365 
4366 	ASSERT(!servicing_interrupt());
4367 
4368 	STRUCT_INIT(mech, mode);
4369 	bcopy(umech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4370 	pp = STRUCT_FGETP(mech, cm_param);
4371 	param_len = STRUCT_FGET(mech, cm_param_len);
4372 
4373 	kmech->cm_param = NULL;
4374 	kmech->cm_param_len = 0;
4375 
4376 	switch (kmech->cm_type) {
4377 	case DES_CBC_MECH_INFO_TYPE:
4378 	case DES3_CBC_MECH_INFO_TYPE:
4379 		expected_param_len = DES_BLOCK_LEN;
4380 		break;
4381 
4382 	case BLOWFISH_CBC_MECH_INFO_TYPE:
4383 		expected_param_len = BLOWFISH_BLOCK_LEN;
4384 		break;
4385 
4386 	case AES_CBC_MECH_INFO_TYPE:
4387 		expected_param_len = AES_BLOCK_LEN;
4388 		break;
4389 
4390 	case AES_CTR_MECH_INFO_TYPE:
4391 	case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:	/* for testing only */
4392 		rv = copyin_aes_ctr_mech(umech, kmech, &error, mode);
4393 		goto out;
4394 
4395 	case DH_PKCS_DERIVE_MECH_INFO_TYPE:
4396 		expected_param_len = param_len;
4397 		break;
4398 
4399 	default:
4400 		/* nothing to do - mechanism has no parameters */
4401 		rv = CRYPTO_SUCCESS;
4402 		goto out;
4403 	}
4404 
4405 	if (param_len != expected_param_len) {
4406 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
4407 		goto out;
4408 	}
4409 	if (pp == NULL) {
4410 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
4411 		goto out;
4412 	}
4413 	if ((param = kmem_alloc(param_len, KM_NOSLEEP)) == NULL) {
4414 		rv = CRYPTO_HOST_MEMORY;
4415 		goto out;
4416 	}
4417 	if (copyin((char *)pp, param, param_len) != 0) {
4418 		kmem_free(param, param_len);
4419 		error = EFAULT;
4420 		rv = CRYPTO_FAILED;
4421 		goto out;
4422 	}
4423 	kmech->cm_param = (char *)param;
4424 	kmech->cm_param_len = param_len;
4425 	rv = CRYPTO_SUCCESS;
4426 out:
4427 	*out_error = error;
4428 	return (rv);
4429 }
4430 
4431 /* ARGSUSED */
4432 static int
4433 dprov_copyout_mechanism(crypto_provider_handle_t provider,
4434     crypto_mechanism_t *kmech, crypto_mechanism_t *umech,
4435     int *out_error, int mode)
4436 {
4437 	ASSERT(!servicing_interrupt());
4438 
4439 	switch (kmech->cm_type) {
4440 	case AES_CTR_MECH_INFO_TYPE:
4441 	case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:	/* for testing only */
4442 		return (copyout_aes_ctr_mech(kmech, umech, out_error, mode));
4443 	default:
4444 		return (CRYPTO_MECHANISM_INVALID);
4445 	}
4446 }
4447 
4448 /*
4449  * Free mechanism parameter that was allocated by the provider.
4450  */
4451 /* ARGSUSED */
4452 static int
4453 dprov_free_mechanism(crypto_provider_handle_t provider,
4454     crypto_mechanism_t *mech)
4455 {
4456 	size_t len;
4457 
4458 	if (mech->cm_param == NULL || mech->cm_param_len == 0)
4459 		return (CRYPTO_SUCCESS);
4460 
4461 	if (mech->cm_type == AES_CTR_MECH_INFO_TYPE ||
4462 	    mech->cm_type == SHA1_KEY_DERIVATION_MECH_INFO_TYPE) {
4463 		len = sizeof (CK_AES_CTR_PARAMS) + 16;
4464 	} else {
4465 		len = mech->cm_param_len;
4466 	}
4467 	kmem_free(mech->cm_param, len);
4468 	return (CRYPTO_SUCCESS);
4469 }
4470 
4471 /*
4472  * No (Key)Store Key management entry point.
4473  */
4474 static int
4475 dprov_nostore_key_generate(crypto_provider_handle_t provider,
4476     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4477     crypto_object_attribute_t *template, uint_t attribute_count,
4478     crypto_object_attribute_t *out_template, uint_t out_attribute_count,
4479     crypto_req_handle_t req)
4480 {
4481 	int error = CRYPTO_FAILED;
4482 	dprov_state_t *softc = (dprov_state_t *)provider;
4483 	/* LINTED E_FUNC_SET_NOT_USED */
4484 	int instance;
4485 
4486 	instance = ddi_get_instance(softc->ds_dip);
4487 	DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate: started\n",
4488 	    instance));
4489 
4490 	/* submit request to the taskq */
4491 	error = dprov_key_submit_req(DPROV_REQ_NOSTORE_KEY_GENERATE,
4492 	    softc, req, session_id, mechanism, template, attribute_count,
4493 	    NULL, NULL, 0, NULL, NULL, NULL, 0, out_template,
4494 	    out_attribute_count, NULL, 0);
4495 
4496 	DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate: "
4497 	    "done err = 0x0%x\n", instance, error));
4498 
4499 	return (error);
4500 }
4501 
4502 static int
4503 dprov_nostore_key_generate_pair(crypto_provider_handle_t provider,
4504     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4505     crypto_object_attribute_t *public_key_template,
4506     uint_t public_key_attribute_count,
4507     crypto_object_attribute_t *private_key_template,
4508     uint_t private_key_attribute_count,
4509     crypto_object_attribute_t *out_public_key_template,
4510     uint_t out_public_key_attribute_count,
4511     crypto_object_attribute_t *out_private_key_template,
4512     uint_t out_private_key_attribute_count,
4513     crypto_req_handle_t req)
4514 {
4515 	int error = CRYPTO_FAILED;
4516 	dprov_state_t *softc = (dprov_state_t *)provider;
4517 	/* LINTED E_FUNC_SET_NOT_USED */
4518 	int instance;
4519 
4520 	instance = ddi_get_instance(softc->ds_dip);
4521 	DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate_pair: started\n",
4522 	    instance));
4523 
4524 	/* submit request to the taskq */
4525 	error = dprov_key_submit_req(DPROV_REQ_NOSTORE_KEY_GENERATE_PAIR,
4526 	    softc, req, session_id, mechanism, public_key_template,
4527 	    public_key_attribute_count, NULL, private_key_template,
4528 	    private_key_attribute_count, NULL, NULL, NULL, 0,
4529 	    out_public_key_template, out_public_key_attribute_count,
4530 	    out_private_key_template, out_private_key_attribute_count);
4531 
4532 	DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate_pair: "
4533 	    "done err = 0x0%x\n", instance, error));
4534 
4535 	return (error);
4536 }
4537 
4538 static int
4539 dprov_nostore_key_derive(crypto_provider_handle_t provider,
4540     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4541     crypto_key_t *base_key, crypto_object_attribute_t *template,
4542     uint_t attribute_count, crypto_object_attribute_t *out_template,
4543     uint_t out_attribute_count, crypto_req_handle_t req)
4544 {
4545 	int error = CRYPTO_FAILED;
4546 	dprov_state_t *softc = (dprov_state_t *)provider;
4547 	/* LINTED E_FUNC_SET_NOT_USED */
4548 	int instance;
4549 
4550 	instance = ddi_get_instance(softc->ds_dip);
4551 	DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_derive: started\n",
4552 	    instance));
4553 
4554 	/* submit request to the taskq */
4555 	error = dprov_key_submit_req(DPROV_REQ_NOSTORE_KEY_DERIVE, softc, req,
4556 	    session_id, mechanism, template, attribute_count, NULL, NULL,
4557 	    0, NULL, base_key, NULL, 0, out_template, out_attribute_count,
4558 	    NULL, 0);
4559 
4560 	DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_derive: "
4561 	    "done err = 0x0%x\n", instance, error));
4562 
4563 	return (error);
4564 }
4565 
4566 /*
4567  * Allocate a dprov taskq request and initialize the common fields.
4568  * Return NULL if the memory allocation failed.
4569  */
4570 static dprov_req_t *
4571 dprov_alloc_req(dprov_req_type_t req_type, dprov_state_t *softc,
4572     crypto_req_handle_t kcf_req, int kmflag)
4573 {
4574 	dprov_req_t *taskq_req;
4575 
4576 	if ((taskq_req = kmem_alloc(sizeof (dprov_req_t), kmflag)) == NULL)
4577 		return (NULL);
4578 
4579 	taskq_req->dr_type = req_type;
4580 	taskq_req->dr_softc = softc;
4581 	taskq_req->dr_kcf_req = kcf_req;
4582 
4583 	return (taskq_req);
4584 }
4585 
4586 /*
4587  * Dispatch a dprov request on the taskq associated with a softc.
4588  * Returns CRYPTO_HOST_MEMORY if the request cannot be queued,
4589  * CRYPTO_QUEUED on success.
4590  */
4591 static int
4592 dprov_taskq_dispatch(dprov_state_t *softc, dprov_req_t *taskq_req,
4593     task_func_t *func, int kmflag)
4594 {
4595 	if (taskq_dispatch(softc->ds_taskq, func, taskq_req,
4596 	    kmflag == KM_NOSLEEP ? TQ_NOSLEEP : TQ_SLEEP) == (taskqid_t)0) {
4597 		kmem_free(taskq_req, sizeof (dprov_req_t));
4598 		return (CRYPTO_HOST_MEMORY);
4599 	} else
4600 		return (CRYPTO_QUEUED);
4601 }
4602 
4603 /*
4604  * Helper function to submit digest operations to the taskq.
4605  * Returns one of the CRYPTO_ errors.
4606  */
4607 static int
4608 dprov_digest_submit_req(dprov_req_type_t req_type,
4609     dprov_state_t *softc, crypto_req_handle_t req,
4610     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
4611     crypto_data_t *digest, crypto_ctx_t *ctx, int kmflag)
4612 {
4613 	dprov_req_t *taskq_req;
4614 
4615 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4616 		return (CRYPTO_HOST_MEMORY);
4617 
4618 	taskq_req->dr_digest_req.dr_mechanism = mechanism;
4619 	taskq_req->dr_digest_req.dr_ctx = ctx;
4620 	taskq_req->dr_digest_req.dr_data = data;
4621 	taskq_req->dr_digest_req.dr_key = key;
4622 	taskq_req->dr_digest_req.dr_digest = digest;
4623 
4624 	return (dprov_taskq_dispatch(softc, taskq_req,
4625 	    (task_func_t *)dprov_digest_task, kmflag));
4626 }
4627 
4628 /*
4629  * Helper function to submit mac operations to the taskq.
4630  * Returns one of the CRYPTO_ errors.
4631  */
4632 static int
4633 dprov_mac_submit_req(dprov_req_type_t req_type,
4634     dprov_state_t *softc, crypto_req_handle_t req,
4635     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
4636     crypto_data_t *mac, crypto_ctx_t *ctx, crypto_session_id_t sid, int kmflag)
4637 {
4638 	dprov_req_t *taskq_req;
4639 
4640 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4641 		return (CRYPTO_HOST_MEMORY);
4642 
4643 	taskq_req->dr_mac_req.dr_mechanism = mechanism;
4644 	taskq_req->dr_mac_req.dr_ctx = ctx;
4645 	taskq_req->dr_mac_req.dr_data = data;
4646 	taskq_req->dr_mac_req.dr_key = key;
4647 	taskq_req->dr_mac_req.dr_mac = mac;
4648 	taskq_req->dr_mac_req.dr_session_id = sid;
4649 
4650 	return (dprov_taskq_dispatch(softc, taskq_req,
4651 	    (task_func_t *)dprov_mac_task, kmflag));
4652 }
4653 
4654 /*
4655  * Helper function to submit sign operations to the taskq.
4656  * Returns one of the CRYPTO_ errors.
4657  */
4658 static int
4659 dprov_sign_submit_req(dprov_req_type_t req_type,
4660     dprov_state_t *softc, crypto_req_handle_t req,
4661     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
4662     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
4663     int kmflag)
4664 {
4665 	dprov_req_t *taskq_req;
4666 
4667 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4668 		return (CRYPTO_HOST_MEMORY);
4669 
4670 	taskq_req->dr_sign_req.sr_mechanism = mechanism;
4671 	taskq_req->dr_sign_req.sr_ctx = ctx;
4672 	taskq_req->dr_sign_req.sr_key = key;
4673 	taskq_req->dr_sign_req.sr_data = data;
4674 	taskq_req->dr_sign_req.sr_signature = signature;
4675 	taskq_req->dr_sign_req.sr_session_id = sid;
4676 
4677 	return (dprov_taskq_dispatch(softc, taskq_req,
4678 	    (task_func_t *)dprov_sign_task, kmflag));
4679 }
4680 
4681 /*
4682  * Helper function to submit verify operations to the taskq.
4683  * Returns one of the CRYPTO_ errors.
4684  */
4685 static int
4686 dprov_verify_submit_req(dprov_req_type_t req_type,
4687     dprov_state_t *softc, crypto_req_handle_t req,
4688     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
4689     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
4690     int kmflag)
4691 {
4692 	dprov_req_t *taskq_req;
4693 
4694 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4695 		return (CRYPTO_HOST_MEMORY);
4696 
4697 	taskq_req->dr_verify_req.vr_mechanism = mechanism;
4698 	taskq_req->dr_verify_req.vr_ctx = ctx;
4699 	taskq_req->dr_verify_req.vr_key = key;
4700 	taskq_req->dr_verify_req.vr_data = data;
4701 	taskq_req->dr_verify_req.vr_signature = signature;
4702 	taskq_req->dr_verify_req.vr_session_id = sid;
4703 
4704 	return (dprov_taskq_dispatch(softc, taskq_req,
4705 	    (task_func_t *)dprov_verify_task, kmflag));
4706 }
4707 
4708 /*
4709  * Helper function to submit dual operations to the taskq.
4710  * Returns one of the CRYPTO_ errors.
4711  */
4712 static int
4713 dprov_dual_submit_req(dprov_req_type_t req_type, dprov_state_t *softc,
4714     crypto_req_handle_t req, crypto_ctx_t *signverify_ctx,
4715     crypto_ctx_t *cipher_ctx, crypto_data_t *plaintext,
4716     crypto_data_t *ciphertext)
4717 {
4718 	dprov_req_t *taskq_req;
4719 
4720 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4721 	    KM_NOSLEEP)) == NULL)
4722 		return (CRYPTO_HOST_MEMORY);
4723 
4724 	taskq_req->dr_dual_req.dr_signverify_ctx = signverify_ctx;
4725 	taskq_req->dr_dual_req.dr_cipher_ctx = cipher_ctx;
4726 	taskq_req->dr_dual_req.dr_plaintext = plaintext;
4727 	taskq_req->dr_dual_req.dr_ciphertext = ciphertext;
4728 
4729 	return (dprov_taskq_dispatch(softc, taskq_req,
4730 	    (task_func_t *)dprov_dual_task, KM_NOSLEEP));
4731 }
4732 
4733 /*
4734  * Helper function to submit dual cipher/mac operations to the taskq.
4735  * Returns one of the CRYPTO_ errors.
4736  */
4737 static int
4738 dprov_cipher_mac_submit_req(dprov_req_type_t req_type,
4739     dprov_state_t *softc, crypto_req_handle_t req, crypto_ctx_t *ctx,
4740     crypto_session_id_t sid, crypto_mechanism_t *cipher_mech,
4741     crypto_key_t *cipher_key, crypto_mechanism_t *mac_mech,
4742     crypto_key_t *mac_key, crypto_dual_data_t *dual_data,
4743     crypto_data_t *data, crypto_data_t *mac, int kmflag)
4744 {
4745 	dprov_req_t *taskq_req;
4746 
4747 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4748 		return (CRYPTO_HOST_MEMORY);
4749 
4750 	taskq_req->dr_cipher_mac_req.mr_session_id = sid;
4751 	taskq_req->dr_cipher_mac_req.mr_ctx = ctx;
4752 	taskq_req->dr_cipher_mac_req.mr_cipher_mech = cipher_mech;
4753 	taskq_req->dr_cipher_mac_req.mr_cipher_key = cipher_key;
4754 	taskq_req->dr_cipher_mac_req.mr_mac_mech = mac_mech;
4755 	taskq_req->dr_cipher_mac_req.mr_mac_key = mac_key;
4756 	taskq_req->dr_cipher_mac_req.mr_dual_data = dual_data;
4757 	taskq_req->dr_cipher_mac_req.mr_data = data;
4758 	taskq_req->dr_cipher_mac_req.mr_mac = mac;
4759 
4760 	return (dprov_taskq_dispatch(softc, taskq_req,
4761 	    (task_func_t *)dprov_cipher_mac_task, kmflag));
4762 }
4763 
4764 /*
4765  * Helper function to submit cipher operations to the taskq.
4766  * Returns one of the CRYPTO_ errors.
4767  */
4768 static int
4769 dprov_cipher_submit_req(dprov_req_type_t req_type,
4770     dprov_state_t *softc, crypto_req_handle_t req,
4771     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *plaintext,
4772     crypto_data_t *ciphertext, crypto_ctx_t *ctx, crypto_session_id_t sid,
4773     int kmflag)
4774 {
4775 	dprov_req_t *taskq_req;
4776 
4777 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4778 		return (CRYPTO_HOST_MEMORY);
4779 
4780 	taskq_req->dr_cipher_req.dr_mechanism = mechanism;
4781 	taskq_req->dr_cipher_req.dr_ctx = ctx;
4782 	taskq_req->dr_cipher_req.dr_key = key;
4783 	taskq_req->dr_cipher_req.dr_plaintext = plaintext;
4784 	taskq_req->dr_cipher_req.dr_ciphertext = ciphertext;
4785 	taskq_req->dr_cipher_req.dr_session_id = sid;
4786 
4787 	return (dprov_taskq_dispatch(softc, taskq_req,
4788 	    (task_func_t *)dprov_cipher_task, kmflag));
4789 }
4790 
4791 /*
4792  * Helper function to submit random number operations to the taskq.
4793  * Returns one of the CRYPTO_ errors.
4794  */
4795 static int
4796 dprov_random_submit_req(dprov_req_type_t req_type,
4797     dprov_state_t *softc, crypto_req_handle_t req, uchar_t *buf, size_t len,
4798     crypto_session_id_t sid, uint_t entropy_est, uint32_t flags)
4799 {
4800 	dprov_req_t *taskq_req;
4801 
4802 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4803 	    KM_NOSLEEP)) == NULL)
4804 		return (CRYPTO_HOST_MEMORY);
4805 
4806 	taskq_req->dr_random_req.rr_buf = buf;
4807 	taskq_req->dr_random_req.rr_len = len;
4808 	taskq_req->dr_random_req.rr_session_id = sid;
4809 	taskq_req->dr_random_req.rr_entropy_est = entropy_est;
4810 	taskq_req->dr_random_req.rr_flags = flags;
4811 
4812 	return (dprov_taskq_dispatch(softc, taskq_req,
4813 	    (task_func_t *)dprov_random_task, KM_NOSLEEP));
4814 }
4815 
4816 
4817 /*
4818  * Helper function to submit session management operations to the taskq.
4819  * Returns one of the CRYPTO_ errors.
4820  */
4821 static int
4822 dprov_session_submit_req(dprov_req_type_t req_type,
4823     dprov_state_t *softc, crypto_req_handle_t req,
4824     crypto_session_id_t *session_id_ptr, crypto_session_id_t session_id,
4825     crypto_user_type_t user_type, char *pin, size_t pin_len)
4826 {
4827 	dprov_req_t *taskq_req;
4828 
4829 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4830 	    KM_NOSLEEP)) == NULL)
4831 		return (CRYPTO_HOST_MEMORY);
4832 
4833 	taskq_req->dr_session_req.sr_session_id_ptr = session_id_ptr;
4834 	taskq_req->dr_session_req.sr_session_id = session_id;
4835 	taskq_req->dr_session_req.sr_user_type = user_type;
4836 	taskq_req->dr_session_req.sr_pin = pin;
4837 	taskq_req->dr_session_req.sr_pin_len = pin_len;
4838 
4839 	return (dprov_taskq_dispatch(softc, taskq_req,
4840 	    (task_func_t *)dprov_session_task, KM_NOSLEEP));
4841 }
4842 
4843 /*
4844  * Helper function to submit object management operations to the taskq.
4845  * Returns one of the CRYPTO_ errors.
4846  */
4847 static int
4848 dprov_object_submit_req(dprov_req_type_t req_type,
4849     dprov_state_t *softc, crypto_req_handle_t req,
4850     crypto_session_id_t session_id, crypto_object_id_t object_id,
4851     crypto_object_attribute_t *template, uint_t attribute_count,
4852     crypto_object_id_t *object_id_ptr, size_t *object_size,
4853     void **find_pp, void *find_p, uint_t max_object_count,
4854     uint_t *object_count_ptr, int kmflag)
4855 {
4856 	dprov_req_t *taskq_req;
4857 
4858 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4859 	    kmflag)) == NULL)
4860 		return (CRYPTO_HOST_MEMORY);
4861 
4862 	taskq_req->dr_object_req.or_session_id = session_id;
4863 	taskq_req->dr_object_req.or_object_id = object_id;
4864 	taskq_req->dr_object_req.or_template = template;
4865 	taskq_req->dr_object_req.or_attribute_count = attribute_count;
4866 	taskq_req->dr_object_req.or_object_id_ptr = object_id_ptr;
4867 	taskq_req->dr_object_req.or_object_size = object_size;
4868 	taskq_req->dr_object_req.or_find_pp = find_pp;
4869 	taskq_req->dr_object_req.or_find_p = find_p;
4870 	taskq_req->dr_object_req.or_max_object_count = max_object_count;
4871 	taskq_req->dr_object_req.or_object_count_ptr = object_count_ptr;
4872 
4873 	return (dprov_taskq_dispatch(softc, taskq_req,
4874 	    (task_func_t *)dprov_object_task, KM_NOSLEEP));
4875 }
4876 
4877 /*
4878  * Helper function to submit key management operations to the taskq.
4879  * Returns one of the CRYPTO_ errors.
4880  */
4881 static int
4882 dprov_key_submit_req(dprov_req_type_t req_type,
4883     dprov_state_t *softc, crypto_req_handle_t req,
4884     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4885     crypto_object_attribute_t *template, uint_t attribute_count,
4886     crypto_object_id_t *object_id_ptr,
4887     crypto_object_attribute_t *private_key_template,
4888     uint_t private_key_attribute_count,
4889     crypto_object_id_t *private_key_object_id_ptr, crypto_key_t *key,
4890     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr,
4891     crypto_object_attribute_t *out_template1, uint_t out_attribute_count1,
4892     crypto_object_attribute_t *out_template2, uint_t out_attribute_count2)
4893 {
4894 	dprov_req_t *taskq_req;
4895 
4896 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4897 	    KM_NOSLEEP)) == NULL)
4898 		return (CRYPTO_HOST_MEMORY);
4899 
4900 	taskq_req->dr_key_req.kr_session_id = session_id;
4901 	taskq_req->dr_key_req.kr_mechanism = mechanism;
4902 	taskq_req->dr_key_req.kr_template = template;
4903 	taskq_req->dr_key_req.kr_attribute_count = attribute_count;
4904 	taskq_req->dr_key_req.kr_object_id_ptr = object_id_ptr;
4905 	taskq_req->dr_key_req.kr_private_key_template = private_key_template;
4906 	taskq_req->dr_key_req.kr_private_key_attribute_count =
4907 	    private_key_attribute_count;
4908 	taskq_req->dr_key_req.kr_private_key_object_id_ptr =
4909 	    private_key_object_id_ptr;
4910 	taskq_req->dr_key_req.kr_key = key;
4911 	taskq_req->dr_key_req.kr_wrapped_key = wrapped_key;
4912 	taskq_req->dr_key_req.kr_wrapped_key_len_ptr = wrapped_key_len_ptr;
4913 	taskq_req->dr_key_req.kr_out_template1 = out_template1;
4914 	taskq_req->dr_key_req.kr_out_attribute_count1 = out_attribute_count1;
4915 	taskq_req->dr_key_req.kr_out_template2 = out_template2;
4916 	taskq_req->dr_key_req.kr_out_attribute_count2 = out_attribute_count2;
4917 
4918 	return (dprov_taskq_dispatch(softc, taskq_req,
4919 	    (task_func_t *)dprov_key_task, KM_NOSLEEP));
4920 }
4921 
4922 /*
4923  * Helper function to submit provider management operations to the taskq.
4924  * Returns one of the CRYPTO_ errors.
4925  */
4926 static int
4927 dprov_mgmt_submit_req(dprov_req_type_t req_type,
4928     dprov_state_t *softc, crypto_req_handle_t req,
4929     crypto_session_id_t session_id, char *pin, size_t pin_len,
4930     char *old_pin, size_t old_pin_len, char *label,
4931     crypto_provider_ext_info_t *ext_info)
4932 {
4933 	dprov_req_t *taskq_req;
4934 
4935 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4936 	    KM_NOSLEEP)) == NULL)
4937 		return (CRYPTO_HOST_MEMORY);
4938 
4939 	taskq_req->dr_mgmt_req.mr_session_id = session_id;
4940 	taskq_req->dr_mgmt_req.mr_pin = pin;
4941 	taskq_req->dr_mgmt_req.mr_pin_len = pin_len;
4942 	taskq_req->dr_mgmt_req.mr_old_pin = old_pin;
4943 	taskq_req->dr_mgmt_req.mr_old_pin_len = old_pin_len;
4944 	taskq_req->dr_mgmt_req.mr_label = label;
4945 	taskq_req->dr_mgmt_req.mr_ext_info = ext_info;
4946 
4947 	return (dprov_taskq_dispatch(softc, taskq_req,
4948 	    (task_func_t *)dprov_mgmt_task, KM_NOSLEEP));
4949 }
4950 
4951 /*
4952  * Helper function for taskq dispatcher routines. Notify the framework
4953  * that the operation corresponding to the specified request is done,
4954  * and pass it the error code. Finally, free the taskq_req.
4955  */
4956 static void
4957 dprov_op_done(dprov_req_t *taskq_req, int error)
4958 {
4959 	/* notify framework that request is completed */
4960 	crypto_op_notification(taskq_req->dr_kcf_req, error);
4961 
4962 	/* free taskq request structure */
4963 	kmem_free(taskq_req, sizeof (dprov_req_t));
4964 }
4965 
4966 /*
4967  * taskq dispatcher function for digest operations.
4968  */
4969 static void
4970 dprov_digest_task(dprov_req_t *taskq_req)
4971 {
4972 	kcf_provider_desc_t *pd;
4973 	dprov_state_t *softc;
4974 	/* LINTED E_FUNC_SET_NOT_USED */
4975 	int instance;
4976 	int error = CRYPTO_NOT_SUPPORTED;
4977 	crypto_ctx_t *ctx = taskq_req->dr_digest_req.dr_ctx;
4978 	crypto_mechanism_t mech;
4979 
4980 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4981 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: started\n", instance));
4982 
4983 	switch (taskq_req->dr_type) {
4984 
4985 	case DPROV_REQ_DIGEST_INIT:
4986 		/* allocate a dprov-private context */
4987 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4988 		    CRYPTO_SUCCESS)
4989 			break;
4990 
4991 		/* structure assignment */
4992 		mech = *taskq_req->dr_digest_req.dr_mechanism;
4993 
4994 		/* get the software provider for this mechanism */
4995 		if ((error = dprov_get_sw_prov(
4996 		    taskq_req->dr_digest_req.dr_mechanism, &pd,
4997 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4998 			break;
4999 
5000 		/* Use a session id of zero since we use a software provider */
5001 		error = crypto_digest_init_prov(pd, 0, &mech,
5002 		    &DPROV_CTX_SINGLE(ctx), NULL);
5003 
5004 		/* release provider reference */
5005 		KCF_PROV_REFRELE(pd);
5006 		break;
5007 
5008 	case DPROV_REQ_DIGEST:
5009 		error = crypto_digest_single(DPROV_CTX_SINGLE(ctx),
5010 		    taskq_req->dr_digest_req.dr_data,
5011 		    taskq_req->dr_digest_req.dr_digest, NULL);
5012 
5013 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5014 			DPROV_CTX_SINGLE(ctx) = NULL;
5015 			(void) dprov_free_context(ctx);
5016 		}
5017 		break;
5018 
5019 	case DPROV_REQ_DIGEST_UPDATE:
5020 		error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
5021 		    taskq_req->dr_digest_req.dr_data, NULL);
5022 		break;
5023 
5024 	case DPROV_REQ_DIGEST_KEY: {
5025 		crypto_data_t data;
5026 		crypto_key_t key;
5027 		size_t len;
5028 
5029 		mutex_enter(&softc->ds_lock);
5030 		error = dprov_key_value_secret(softc, ctx->cc_session,
5031 		    taskq_req->dr_type, taskq_req->dr_digest_req.dr_key, &key);
5032 		mutex_exit(&softc->ds_lock);
5033 		if (error != CRYPTO_SUCCESS)
5034 			break;
5035 
5036 		/* key lengths are specified in bits */
5037 		len = CRYPTO_BITS2BYTES(key.ck_length);
5038 		data.cd_format = CRYPTO_DATA_RAW;
5039 		data.cd_offset = 0;
5040 		data.cd_length = len;
5041 		data.cd_raw.iov_base = key.ck_data;
5042 		data.cd_raw.iov_len = len;
5043 		error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
5044 		    &data, NULL);
5045 		break;
5046 	}
5047 
5048 	case DPROV_REQ_DIGEST_FINAL:
5049 		error = crypto_digest_final(DPROV_CTX_SINGLE(ctx),
5050 		    taskq_req->dr_digest_req.dr_digest, NULL);
5051 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5052 			DPROV_CTX_SINGLE(ctx) = NULL;
5053 			(void) dprov_free_context(ctx);
5054 		}
5055 		break;
5056 
5057 	case DPROV_REQ_DIGEST_ATOMIC:
5058 		/* structure assignment */
5059 		mech = *taskq_req->dr_digest_req.dr_mechanism;
5060 
5061 		/* get the software provider for this mechanism */
5062 		if ((error = dprov_get_sw_prov(
5063 		    taskq_req->dr_digest_req.dr_mechanism, &pd,
5064 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5065 			break;
5066 
5067 		/* use a session id of zero since we use a software provider */
5068 		error = crypto_digest_prov(pd, 0, &mech,
5069 		    taskq_req->dr_digest_req.dr_data,
5070 		    taskq_req->dr_digest_req.dr_digest, NULL);
5071 
5072 		/* release provider reference */
5073 		KCF_PROV_REFRELE(pd);
5074 
5075 		break;
5076 	}
5077 
5078 	dprov_op_done(taskq_req, error);
5079 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: end\n", instance));
5080 }
5081 
5082 /*
5083  * taskq dispatcher function for mac operations.
5084  */
5085 static void
5086 dprov_mac_task(dprov_req_t *taskq_req)
5087 {
5088 	kcf_provider_desc_t *pd;
5089 	dprov_state_t *softc;
5090 	/* LINTED E_FUNC_SET_NOT_USED */
5091 	int instance;
5092 	int error = CRYPTO_NOT_SUPPORTED;
5093 	crypto_ctx_t *ctx = taskq_req->dr_mac_req.dr_ctx;
5094 	crypto_key_t key;
5095 	crypto_mechanism_t mech;
5096 
5097 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5098 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: started\n", instance));
5099 
5100 	switch (taskq_req->dr_type) {
5101 
5102 	case DPROV_REQ_MAC_INIT:
5103 		/* allocate a dprov-private context */
5104 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5105 		    CRYPTO_SUCCESS)
5106 			break;
5107 
5108 		/* get key value */
5109 		mutex_enter(&softc->ds_lock);
5110 		error = dprov_key_value_secret(softc, ctx->cc_session,
5111 		    taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
5112 		mutex_exit(&softc->ds_lock);
5113 		if (error != CRYPTO_SUCCESS)
5114 			break;
5115 
5116 		/* structure assignment */
5117 		mech = *taskq_req->dr_mac_req.dr_mechanism;
5118 
5119 		/* get the software provider for this mechanism */
5120 		if ((error = dprov_get_sw_prov(
5121 		    taskq_req->dr_mac_req.dr_mechanism, &pd,
5122 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5123 			break;
5124 
5125 		/* Use a session id of zero since we use a software provider */
5126 		error = crypto_mac_init_prov(pd, 0, &mech, &key, NULL,
5127 		    &DPROV_CTX_SINGLE(ctx), NULL);
5128 
5129 		/* release provider reference */
5130 		KCF_PROV_REFRELE(pd);
5131 		break;
5132 
5133 	case DPROV_REQ_MAC:
5134 		error = crypto_mac_single(DPROV_CTX_SINGLE(ctx),
5135 		    taskq_req->dr_mac_req.dr_data,
5136 		    taskq_req->dr_mac_req.dr_mac, NULL);
5137 
5138 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5139 			DPROV_CTX_SINGLE(ctx) = NULL;
5140 			(void) dprov_free_context(ctx);
5141 		}
5142 		break;
5143 
5144 	case DPROV_REQ_MAC_UPDATE:
5145 		error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5146 		    taskq_req->dr_mac_req.dr_data, NULL);
5147 		break;
5148 
5149 	case DPROV_REQ_MAC_FINAL:
5150 		error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
5151 		    taskq_req->dr_mac_req.dr_mac, NULL);
5152 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5153 			DPROV_CTX_SINGLE(ctx) = NULL;
5154 			(void) dprov_free_context(ctx);
5155 		}
5156 		break;
5157 
5158 	case DPROV_REQ_MAC_ATOMIC:
5159 	case DPROV_REQ_MAC_VERIFY_ATOMIC:
5160 		/* get key value */
5161 		mutex_enter(&softc->ds_lock);
5162 		error = dprov_key_value_secret(softc,
5163 		    taskq_req->dr_mac_req.dr_session_id,
5164 		    taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
5165 		mutex_exit(&softc->ds_lock);
5166 		if (error != CRYPTO_SUCCESS)
5167 			break;
5168 
5169 		/* structure assignment */
5170 		mech = *taskq_req->dr_mac_req.dr_mechanism;
5171 
5172 		/* get the software provider for this mechanism */
5173 		if ((error = dprov_get_sw_prov(
5174 		    taskq_req->dr_mac_req.dr_mechanism, &pd,
5175 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5176 			break;
5177 
5178 		/* use a session id of zero since we use a software provider */
5179 		if (taskq_req->dr_type == DPROV_REQ_MAC_ATOMIC)
5180 			error = crypto_mac_prov(pd, 0, &mech,
5181 			    taskq_req->dr_mac_req.dr_data,
5182 			    &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL);
5183 		else
5184 			error = crypto_mac_verify_prov(pd, 0, &mech,
5185 			    taskq_req->dr_mac_req.dr_data,
5186 			    &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL);
5187 
5188 		/* release provider reference */
5189 		KCF_PROV_REFRELE(pd);
5190 
5191 		break;
5192 	}
5193 
5194 	dprov_op_done(taskq_req, error);
5195 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
5196 }
5197 
5198 /*
5199  * taskq dispatcher function for sign operations.
5200  */
5201 static void
5202 dprov_sign_task(dprov_req_t *taskq_req)
5203 {
5204 	kcf_provider_desc_t *pd;
5205 	dprov_state_t *softc;
5206 	/* LINTED E_FUNC_SET_NOT_USED */
5207 	int instance;
5208 	int error = CRYPTO_NOT_SUPPORTED;
5209 	crypto_ctx_t *ctx = taskq_req->dr_sign_req.sr_ctx;
5210 	crypto_key_t key, *keyp;
5211 	crypto_mechanism_t mech;
5212 
5213 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5214 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: started\n", instance));
5215 
5216 	switch (taskq_req->dr_type) {
5217 
5218 	case DPROV_REQ_SIGN_INIT:
5219 	case DPROV_REQ_SIGN_RECOVER_INIT:
5220 		/* allocate a dprov-private context */
5221 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5222 		    CRYPTO_SUCCESS)
5223 			break;
5224 
5225 		/* structure assignment */
5226 		mech = *taskq_req->dr_sign_req.sr_mechanism;
5227 		if (dprov_valid_mac_mech(mech.cm_type)) {
5228 			DPROV_CTX_P(ctx)->dc_svrfy_to_mac = B_TRUE;
5229 		}
5230 
5231 		mutex_enter(&softc->ds_lock);
5232 		/* get key value for secret key algorithms */
5233 		if (is_publickey_mech(mech.cm_type)) {
5234 			if ((error = dprov_key_attr_asymmetric(softc,
5235 			    ctx->cc_session, taskq_req->dr_type,
5236 			    taskq_req->dr_sign_req.sr_key, &key))
5237 			    != CRYPTO_SUCCESS) {
5238 				mutex_exit(&softc->ds_lock);
5239 				break;
5240 			}
5241 			keyp = &key;
5242 		} else {
5243 			if ((error = dprov_key_value_secret(softc,
5244 			    ctx->cc_session, taskq_req->dr_type,
5245 			    taskq_req->dr_sign_req.sr_key, &key))
5246 			    != CRYPTO_SUCCESS) {
5247 				mutex_exit(&softc->ds_lock);
5248 				break;
5249 			}
5250 			keyp = &key;
5251 		}
5252 		mutex_exit(&softc->ds_lock);
5253 
5254 		/* get the software provider for this mechanism */
5255 		if ((error = dprov_get_sw_prov(
5256 		    taskq_req->dr_sign_req.sr_mechanism, &pd,
5257 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5258 			break;
5259 
5260 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5261 			error = crypto_mac_init_prov(pd, 0, &mech, keyp, NULL,
5262 			    &DPROV_CTX_SINGLE(ctx), NULL);
5263 
5264 			/* release provider reference */
5265 			KCF_PROV_REFRELE(pd);
5266 			break;
5267 		}
5268 
5269 		/* Use a session id of zero since we use a software provider */
5270 		if (taskq_req->dr_type == DPROV_REQ_SIGN_INIT)
5271 			error = crypto_sign_init_prov(pd, 0, &mech, keyp,
5272 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5273 		else
5274 			error = crypto_sign_recover_init_prov(pd, 0, &mech,
5275 			    keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5276 
5277 		/* release provider reference */
5278 		KCF_PROV_REFRELE(pd);
5279 
5280 		break;
5281 
5282 	case DPROV_REQ_SIGN:
5283 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5284 			/* Emulate using update and final */
5285 			error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5286 			    taskq_req->dr_mac_req.dr_data, NULL);
5287 			if (error == CRYPTO_SUCCESS) {
5288 				error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
5289 				    taskq_req->dr_mac_req.dr_mac, NULL);
5290 			}
5291 		} else {
5292 			error = crypto_sign_single(DPROV_CTX_SINGLE(ctx),
5293 			    taskq_req->dr_sign_req.sr_data,
5294 			    taskq_req->dr_sign_req.sr_signature, NULL);
5295 		}
5296 
5297 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5298 			DPROV_CTX_SINGLE(ctx) = NULL;
5299 			(void) dprov_free_context(ctx);
5300 		}
5301 		break;
5302 
5303 	case DPROV_REQ_SIGN_UPDATE:
5304 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5305 			error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5306 			    taskq_req->dr_mac_req.dr_data, NULL);
5307 		} else {
5308 			error = crypto_sign_update(DPROV_CTX_SINGLE(ctx),
5309 			    taskq_req->dr_sign_req.sr_data, NULL);
5310 		}
5311 		break;
5312 
5313 	case DPROV_REQ_SIGN_FINAL:
5314 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5315 			error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
5316 			    taskq_req->dr_mac_req.dr_mac, NULL);
5317 		} else {
5318 			error = crypto_sign_final(DPROV_CTX_SINGLE(ctx),
5319 			    taskq_req->dr_sign_req.sr_signature, NULL);
5320 		}
5321 
5322 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5323 			DPROV_CTX_SINGLE(ctx) = NULL;
5324 			(void) dprov_free_context(ctx);
5325 		}
5326 		break;
5327 
5328 	case DPROV_REQ_SIGN_ATOMIC:
5329 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
5330 		/* structure assignment */
5331 		mech = *taskq_req->dr_sign_req.sr_mechanism;
5332 
5333 		mutex_enter(&softc->ds_lock);
5334 		/* get key value for secret key algorithms */
5335 		if (is_publickey_mech(mech.cm_type)) {
5336 			if ((error = dprov_key_attr_asymmetric(softc,
5337 			    taskq_req->dr_sign_req.sr_session_id,
5338 			    taskq_req->dr_type,
5339 			    taskq_req->dr_sign_req.sr_key, &key))
5340 			    != CRYPTO_SUCCESS) {
5341 				mutex_exit(&softc->ds_lock);
5342 				break;
5343 			}
5344 			keyp = &key;
5345 		} else {
5346 			if ((error = dprov_key_value_secret(softc,
5347 			    taskq_req->dr_sign_req.sr_session_id,
5348 			    taskq_req->dr_type,
5349 			    taskq_req->dr_sign_req.sr_key, &key))
5350 			    != CRYPTO_SUCCESS) {
5351 				mutex_exit(&softc->ds_lock);
5352 				break;
5353 			}
5354 			keyp = &key;
5355 		}
5356 		mutex_exit(&softc->ds_lock);
5357 
5358 		/* get the software provider for this mechanism */
5359 		if ((error = dprov_get_sw_prov(
5360 		    taskq_req->dr_sign_req.sr_mechanism, &pd,
5361 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5362 			break;
5363 
5364 		/* Use a session id of zero since we use a software provider */
5365 		if (taskq_req->dr_type == DPROV_REQ_SIGN_ATOMIC)
5366 			error = crypto_sign_prov(pd, 0, &mech, keyp,
5367 			    taskq_req->dr_sign_req.sr_data,
5368 			    NULL, taskq_req->dr_sign_req.sr_signature, NULL);
5369 		else
5370 			error = crypto_sign_recover_prov(pd, 0, &mech, keyp,
5371 			    taskq_req->dr_sign_req.sr_data,
5372 			    NULL, taskq_req->dr_sign_req.sr_signature, NULL);
5373 
5374 		/* release provider reference */
5375 		KCF_PROV_REFRELE(pd);
5376 		break;
5377 
5378 	case DPROV_REQ_SIGN_RECOVER:
5379 		error = crypto_sign_recover_single(DPROV_CTX_SINGLE(ctx),
5380 		    taskq_req->dr_sign_req.sr_data,
5381 		    taskq_req->dr_sign_req.sr_signature, NULL);
5382 
5383 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5384 			DPROV_CTX_SINGLE(ctx) = NULL;
5385 			(void) dprov_free_context(ctx);
5386 		}
5387 		break;
5388 	}
5389 
5390 	dprov_op_done(taskq_req, error);
5391 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: end\n", instance));
5392 }
5393 
5394 static int
5395 emulate_verify_with_mac(crypto_ctx_t *ctx, crypto_data_t *in_mac)
5396 {
5397 	int error;
5398 	crypto_data_t tmpd;
5399 	crypto_data_t *out_mac;
5400 	char digest[SHA512_DIGEST_LENGTH];
5401 
5402 	bzero(&tmpd, sizeof (crypto_data_t));
5403 	tmpd.cd_format = CRYPTO_DATA_RAW;
5404 	tmpd.cd_length = SHA512_DIGEST_LENGTH;
5405 	tmpd.cd_raw.iov_base = digest;
5406 	tmpd.cd_raw.iov_len = SHA512_DIGEST_LENGTH;
5407 	out_mac = &tmpd;
5408 
5409 	error = crypto_mac_final(DPROV_CTX_SINGLE(ctx), out_mac, NULL);
5410 	if (in_mac->cd_length != out_mac->cd_length ||
5411 	    (bcmp(digest, (unsigned char *)in_mac->cd_raw.iov_base +
5412 	    in_mac->cd_offset, out_mac->cd_length) != 0)) {
5413 		error = CRYPTO_INVALID_MAC;
5414 	}
5415 
5416 	return (error);
5417 }
5418 
5419 /*
5420  * taskq dispatcher function for verify operations.
5421  */
5422 static void
5423 dprov_verify_task(dprov_req_t *taskq_req)
5424 {
5425 	kcf_provider_desc_t *pd;
5426 	dprov_state_t *softc;
5427 	/* LINTED E_FUNC_SET_NOT_USED */
5428 	int instance;
5429 	int error = CRYPTO_NOT_SUPPORTED;
5430 	crypto_ctx_t *ctx = taskq_req->dr_verify_req.vr_ctx;
5431 	crypto_key_t key, *keyp;
5432 	crypto_mechanism_t mech;
5433 
5434 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5435 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: started\n", instance));
5436 
5437 	switch (taskq_req->dr_type) {
5438 
5439 	case DPROV_REQ_VERIFY_INIT:
5440 	case DPROV_REQ_VERIFY_RECOVER_INIT:
5441 		/* allocate a dprov-private context */
5442 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5443 		    CRYPTO_SUCCESS)
5444 			break;
5445 
5446 		/* structure assignment */
5447 		mech = *taskq_req->dr_verify_req.vr_mechanism;
5448 		if (dprov_valid_mac_mech(mech.cm_type)) {
5449 			DPROV_CTX_P(ctx)->dc_svrfy_to_mac = B_TRUE;
5450 		}
5451 
5452 		mutex_enter(&softc->ds_lock);
5453 		/* get key value for secret key algorithms */
5454 		if (is_publickey_mech(mech.cm_type)) {
5455 			if ((error = dprov_key_attr_asymmetric(softc,
5456 			    ctx->cc_session, taskq_req->dr_type,
5457 			    taskq_req->dr_verify_req.vr_key, &key))
5458 			    != CRYPTO_SUCCESS) {
5459 				mutex_exit(&softc->ds_lock);
5460 				break;
5461 			}
5462 			keyp = &key;
5463 		} else {
5464 			if ((error = dprov_key_value_secret(softc,
5465 			    ctx->cc_session, taskq_req->dr_type,
5466 			    taskq_req->dr_verify_req.vr_key, &key))
5467 			    != CRYPTO_SUCCESS) {
5468 				mutex_exit(&softc->ds_lock);
5469 				break;
5470 			}
5471 			keyp = &key;
5472 		}
5473 		mutex_exit(&softc->ds_lock);
5474 
5475 		/* get the software provider for this mechanism */
5476 		if ((error = dprov_get_sw_prov(
5477 		    taskq_req->dr_verify_req.vr_mechanism, &pd,
5478 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5479 			break;
5480 
5481 
5482 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5483 			error = crypto_mac_init_prov(pd, 0, &mech, keyp, NULL,
5484 			    &DPROV_CTX_SINGLE(ctx), NULL);
5485 
5486 			/* release provider reference */
5487 			KCF_PROV_REFRELE(pd);
5488 			break;
5489 		}
5490 
5491 		/* Use a session id of zero since we use a software provider */
5492 		if (taskq_req->dr_type == DPROV_REQ_VERIFY_INIT)
5493 			error = crypto_verify_init_prov(pd, 0, &mech, keyp,
5494 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5495 		else
5496 			error = crypto_verify_recover_init_prov(pd, 0, &mech,
5497 			    keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5498 
5499 		/* release provider reference */
5500 		KCF_PROV_REFRELE(pd);
5501 
5502 		break;
5503 
5504 	case DPROV_REQ_VERIFY:
5505 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5506 			/* Emulate using update and final */
5507 			error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5508 			    taskq_req->dr_mac_req.dr_data, NULL);
5509 			if (error == CRYPTO_SUCCESS) {
5510 				error = emulate_verify_with_mac(ctx,
5511 				    taskq_req->dr_mac_req.dr_mac);
5512 			}
5513 		} else {
5514 			error = crypto_verify_single(DPROV_CTX_SINGLE(ctx),
5515 			    taskq_req->dr_verify_req.vr_data,
5516 			    taskq_req->dr_verify_req.vr_signature, NULL);
5517 		}
5518 
5519 		ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
5520 		DPROV_CTX_SINGLE(ctx) = NULL;
5521 		(void) dprov_free_context(ctx);
5522 		break;
5523 
5524 	case DPROV_REQ_VERIFY_UPDATE:
5525 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5526 			error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5527 			    taskq_req->dr_mac_req.dr_data, NULL);
5528 		} else {
5529 			error = crypto_verify_update(DPROV_CTX_SINGLE(ctx),
5530 			    taskq_req->dr_verify_req.vr_data, NULL);
5531 		}
5532 		break;
5533 
5534 	case DPROV_REQ_VERIFY_FINAL:
5535 		if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5536 			error = emulate_verify_with_mac(ctx,
5537 			    taskq_req->dr_mac_req.dr_mac);
5538 		} else {
5539 			error = crypto_verify_final(DPROV_CTX_SINGLE(ctx),
5540 			    taskq_req->dr_verify_req.vr_signature, NULL);
5541 		}
5542 
5543 		ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
5544 		DPROV_CTX_SINGLE(ctx) = NULL;
5545 		(void) dprov_free_context(ctx);
5546 		break;
5547 
5548 	case DPROV_REQ_VERIFY_ATOMIC:
5549 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
5550 		/* structure assignment */
5551 		mech = *taskq_req->dr_verify_req.vr_mechanism;
5552 
5553 		mutex_enter(&softc->ds_lock);
5554 		/* get key value for secret key algorithms */
5555 		if (is_publickey_mech(mech.cm_type)) {
5556 			if ((error = dprov_key_attr_asymmetric(softc,
5557 			    taskq_req->dr_verify_req.vr_session_id,
5558 			    taskq_req->dr_type,
5559 			    taskq_req->dr_verify_req.vr_key, &key))
5560 			    != CRYPTO_SUCCESS) {
5561 				mutex_exit(&softc->ds_lock);
5562 				break;
5563 			}
5564 			keyp = &key;
5565 		} else {
5566 			if ((error = dprov_key_value_secret(softc,
5567 			    taskq_req->dr_verify_req.vr_session_id,
5568 			    taskq_req->dr_type,
5569 			    taskq_req->dr_verify_req.vr_key, &key))
5570 			    != CRYPTO_SUCCESS) {
5571 				mutex_exit(&softc->ds_lock);
5572 				break;
5573 			}
5574 			keyp = &key;
5575 		}
5576 		mutex_exit(&softc->ds_lock);
5577 
5578 		/* get the software provider for this mechanism */
5579 		if ((error = dprov_get_sw_prov(
5580 		    taskq_req->dr_verify_req.vr_mechanism, &pd,
5581 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5582 			break;
5583 
5584 		/* Use a session id of zero since we use a software provider */
5585 		if (taskq_req->dr_type == DPROV_REQ_VERIFY_ATOMIC)
5586 			error = crypto_verify_prov(pd, 0, &mech, keyp,
5587 			    taskq_req->dr_verify_req.vr_data,
5588 			    NULL, taskq_req->dr_verify_req.vr_signature, NULL);
5589 		else
5590 			/*
5591 			 * crypto_verify_recover_prov() has different argument
5592 			 * order than crypto_verify_prov().
5593 			 */
5594 			error = crypto_verify_recover_prov(pd, 0, &mech, keyp,
5595 			    taskq_req->dr_verify_req.vr_signature,
5596 			    NULL, taskq_req->dr_verify_req.vr_data, NULL);
5597 
5598 		/* release provider reference */
5599 		KCF_PROV_REFRELE(pd);
5600 		break;
5601 
5602 	case DPROV_REQ_VERIFY_RECOVER:
5603 		/*
5604 		 * crypto_verify_recover_single() has different argument
5605 		 * order than crypto_verify_single().
5606 		 */
5607 		error = crypto_verify_recover_single(DPROV_CTX_SINGLE(ctx),
5608 		    taskq_req->dr_verify_req.vr_signature,
5609 		    taskq_req->dr_verify_req.vr_data, NULL);
5610 
5611 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5612 			DPROV_CTX_SINGLE(ctx) = NULL;
5613 			(void) dprov_free_context(ctx);
5614 		}
5615 		break;
5616 	}
5617 
5618 	dprov_op_done(taskq_req, error);
5619 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: end\n", instance));
5620 }
5621 
5622 /*
5623  * taskq dispatcher function for dual operations.
5624  */
5625 static void
5626 dprov_dual_task(dprov_req_t *taskq_req)
5627 {
5628 	dprov_state_t *softc;
5629 	/* LINTED E_FUNC_SET_NOT_USED */
5630 	int instance;
5631 	int error = CRYPTO_NOT_SUPPORTED;
5632 	crypto_ctx_t *signverify_ctx = taskq_req->dr_dual_req.dr_signverify_ctx;
5633 	crypto_ctx_t *cipher_ctx = taskq_req->dr_dual_req.dr_cipher_ctx;
5634 
5635 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5636 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: started\n", instance));
5637 
5638 	switch (taskq_req->dr_type) {
5639 
5640 	case DPROV_REQ_DIGEST_ENCRYPT_UPDATE:
5641 		error = crypto_digest_encrypt_update(
5642 		    DPROV_CTX_SINGLE(signverify_ctx),
5643 		    DPROV_CTX_SINGLE(cipher_ctx),
5644 		    taskq_req->dr_dual_req.dr_plaintext,
5645 		    taskq_req->dr_dual_req.dr_ciphertext, NULL);
5646 		break;
5647 
5648 	case DPROV_REQ_DECRYPT_DIGEST_UPDATE:
5649 		error = crypto_decrypt_digest_update(
5650 		    DPROV_CTX_SINGLE(cipher_ctx),
5651 		    DPROV_CTX_SINGLE(signverify_ctx),
5652 		    taskq_req->dr_dual_req.dr_ciphertext,
5653 		    taskq_req->dr_dual_req.dr_plaintext, NULL);
5654 		break;
5655 
5656 	case DPROV_REQ_SIGN_ENCRYPT_UPDATE:
5657 		error = crypto_sign_encrypt_update(
5658 		    DPROV_CTX_SINGLE(signverify_ctx),
5659 		    DPROV_CTX_SINGLE(cipher_ctx),
5660 		    taskq_req->dr_dual_req.dr_plaintext,
5661 		    taskq_req->dr_dual_req.dr_ciphertext, NULL);
5662 		break;
5663 
5664 	case DPROV_REQ_DECRYPT_VERIFY_UPDATE:
5665 		error = crypto_decrypt_verify_update(
5666 		    DPROV_CTX_SINGLE(cipher_ctx),
5667 		    DPROV_CTX_SINGLE(signverify_ctx),
5668 		    taskq_req->dr_dual_req.dr_ciphertext,
5669 		    taskq_req->dr_dual_req.dr_plaintext, NULL);
5670 		break;
5671 	}
5672 
5673 	dprov_op_done(taskq_req, error);
5674 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: end\n", instance));
5675 }
5676 
5677 /*
5678  * taskq dispatcher function for cipher operations.
5679  */
5680 static void
5681 dprov_cipher_task(dprov_req_t *taskq_req)
5682 {
5683 	kcf_provider_desc_t *pd;
5684 	dprov_state_t *softc;
5685 	/* LINTED E_FUNC_SET_NOT_USED */
5686 	int instance;
5687 	int error = CRYPTO_NOT_SUPPORTED;
5688 	crypto_ctx_t *ctx = taskq_req->dr_cipher_req.dr_ctx;
5689 	crypto_key_t key, *keyp;
5690 	crypto_mechanism_t mech;
5691 
5692 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5693 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_cipher_task: started\n", instance));
5694 
5695 	switch (taskq_req->dr_type) {
5696 
5697 	case DPROV_REQ_ENCRYPT_INIT:
5698 	case DPROV_REQ_DECRYPT_INIT:
5699 		/* allocate a dprov-private context */
5700 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5701 		    CRYPTO_SUCCESS)
5702 			break;
5703 
5704 		/* structure assignment */
5705 		mech = *taskq_req->dr_cipher_req.dr_mechanism;
5706 
5707 		mutex_enter(&softc->ds_lock);
5708 		/* get key value for secret key algorithms */
5709 		if (is_publickey_mech(mech.cm_type)) {
5710 			if ((error = dprov_key_attr_asymmetric(softc,
5711 			    ctx->cc_session, taskq_req->dr_type,
5712 			    taskq_req->dr_cipher_req.dr_key, &key))
5713 			    != CRYPTO_SUCCESS) {
5714 				mutex_exit(&softc->ds_lock);
5715 				break;
5716 			}
5717 			keyp = &key;
5718 		} else {
5719 			if ((error = dprov_key_value_secret(softc,
5720 			    ctx->cc_session, taskq_req->dr_type,
5721 			    taskq_req->dr_cipher_req.dr_key, &key))
5722 			    != CRYPTO_SUCCESS) {
5723 				mutex_exit(&softc->ds_lock);
5724 				break;
5725 			}
5726 			keyp = &key;
5727 		}
5728 		mutex_exit(&softc->ds_lock);
5729 
5730 		/* get the software provider for this mechanism */
5731 		if ((error = dprov_get_sw_prov(
5732 		    taskq_req->dr_cipher_req.dr_mechanism, &pd,
5733 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5734 			break;
5735 
5736 		/* Use a session id of zero since we use a software provider */
5737 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_INIT)
5738 			error = crypto_encrypt_init_prov(pd, 0, &mech, keyp,
5739 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5740 		else
5741 			error = crypto_decrypt_init_prov(pd, 0, &mech, keyp,
5742 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5743 
5744 		if (ctx->cc_flags & CRYPTO_INIT_OPSTATE) {
5745 			crypto_ctx_t *lctx =
5746 			    (crypto_ctx_t *)(DPROV_CTX_SINGLE(ctx));
5747 
5748 			ctx->cc_opstate = lctx->cc_provider_private;
5749 			ctx->cc_flags |= CRYPTO_USE_OPSTATE;
5750 		}
5751 
5752 		/* release provider reference */
5753 		KCF_PROV_REFRELE(pd);
5754 		break;
5755 
5756 	case DPROV_REQ_ENCRYPT:
5757 		error = crypto_encrypt_single(DPROV_CTX_SINGLE(ctx),
5758 		    taskq_req->dr_cipher_req.dr_plaintext,
5759 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5760 
5761 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5762 			DPROV_CTX_SINGLE(ctx) = NULL;
5763 			(void) dprov_free_context(ctx);
5764 		}
5765 		break;
5766 
5767 	case DPROV_REQ_DECRYPT:
5768 		error = crypto_decrypt_single(DPROV_CTX_SINGLE(ctx),
5769 		    taskq_req->dr_cipher_req.dr_ciphertext,
5770 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5771 
5772 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5773 			DPROV_CTX_SINGLE(ctx) = NULL;
5774 			(void) dprov_free_context(ctx);
5775 		}
5776 		break;
5777 
5778 	case DPROV_REQ_ENCRYPT_UPDATE:
5779 		ASSERT(!(ctx->cc_flags & CRYPTO_INIT_OPSTATE) ||
5780 		    (ctx->cc_flags & CRYPTO_USE_OPSTATE));
5781 		error = crypto_encrypt_update(DPROV_CTX_SINGLE(ctx),
5782 		    taskq_req->dr_cipher_req.dr_plaintext,
5783 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5784 		break;
5785 
5786 	case DPROV_REQ_DECRYPT_UPDATE:
5787 		ASSERT(!(ctx->cc_flags & CRYPTO_INIT_OPSTATE) ||
5788 		    (ctx->cc_flags & CRYPTO_USE_OPSTATE));
5789 		error = crypto_decrypt_update(DPROV_CTX_SINGLE(ctx),
5790 		    taskq_req->dr_cipher_req.dr_ciphertext,
5791 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5792 		break;
5793 
5794 	case DPROV_REQ_ENCRYPT_FINAL:
5795 		error = crypto_encrypt_final(DPROV_CTX_SINGLE(ctx),
5796 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5797 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5798 			DPROV_CTX_SINGLE(ctx) = NULL;
5799 			(void) dprov_free_context(ctx);
5800 		}
5801 		break;
5802 
5803 	case DPROV_REQ_DECRYPT_FINAL:
5804 		error = crypto_decrypt_final(DPROV_CTX_SINGLE(ctx),
5805 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5806 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5807 			DPROV_CTX_SINGLE(ctx) = NULL;
5808 			(void) dprov_free_context(ctx);
5809 		}
5810 		break;
5811 
5812 	case DPROV_REQ_ENCRYPT_ATOMIC:
5813 	case DPROV_REQ_DECRYPT_ATOMIC:
5814 		/* structure assignment */
5815 		mech = *taskq_req->dr_cipher_req.dr_mechanism;
5816 
5817 		mutex_enter(&softc->ds_lock);
5818 		/* get key value for secret key algorithms */
5819 		if (is_publickey_mech(mech.cm_type)) {
5820 			if ((error = dprov_key_attr_asymmetric(softc,
5821 			    taskq_req->dr_cipher_req.dr_session_id,
5822 			    taskq_req->dr_type,
5823 			    taskq_req->dr_cipher_req.dr_key,
5824 			    &key)) != CRYPTO_SUCCESS) {
5825 				mutex_exit(&softc->ds_lock);
5826 				break;
5827 			}
5828 			keyp = &key;
5829 		} else {
5830 			if ((error = dprov_key_value_secret(softc,
5831 			    taskq_req->dr_cipher_req.dr_session_id,
5832 			    taskq_req->dr_type, taskq_req->dr_cipher_req.dr_key,
5833 			    &key))
5834 			    != CRYPTO_SUCCESS) {
5835 				mutex_exit(&softc->ds_lock);
5836 				break;
5837 			}
5838 			keyp = &key;
5839 		}
5840 		mutex_exit(&softc->ds_lock);
5841 
5842 		/* get the software provider for this mechanism */
5843 		if ((error = dprov_get_sw_prov(
5844 		    taskq_req->dr_cipher_req.dr_mechanism, &pd,
5845 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5846 			break;
5847 
5848 		/* use a session id of zero since we use a software provider */
5849 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_ATOMIC)
5850 			error = crypto_encrypt_prov(pd, 0, &mech,
5851 			    taskq_req->dr_cipher_req.dr_plaintext,
5852 			    keyp, NULL,
5853 			    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5854 		else
5855 			error = crypto_decrypt_prov(pd, 0, &mech,
5856 			    taskq_req->dr_cipher_req.dr_ciphertext,
5857 			    keyp, NULL,
5858 			    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5859 
5860 		/* release provider reference */
5861 		KCF_PROV_REFRELE(pd);
5862 
5863 		break;
5864 	}
5865 
5866 	dprov_op_done(taskq_req, error);
5867 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
5868 }
5869 
5870 /*
5871  * Helper function for the cipher/mac dual operation taskq dispatch
5872  * function. Initialize the cipher and mac key values and find the
5873  * providers that can process the request for the specified mechanisms.
5874  */
5875 static int
5876 dprov_cipher_mac_key_pd(dprov_state_t *softc, crypto_session_id_t sid,
5877     dprov_req_t *taskq_req, crypto_key_t *cipher_key, crypto_key_t *mac_key,
5878     kcf_provider_desc_t **cipher_pd, kcf_provider_desc_t **mac_pd,
5879     crypto_mech_type_t *cipher_mech_type, crypto_mech_type_t *mac_mech_type)
5880 {
5881 	int error;
5882 
5883 	/* get the cipher key value */
5884 	mutex_enter(&softc->ds_lock);
5885 	error = dprov_key_value_secret(softc, sid, DPROV_REQ_ENCRYPT_ATOMIC,
5886 	    taskq_req->dr_cipher_mac_req.mr_cipher_key, cipher_key);
5887 	if (error != CRYPTO_SUCCESS) {
5888 		mutex_exit(&softc->ds_lock);
5889 		return (error);
5890 	}
5891 
5892 	/* get the mac key value */
5893 	error = dprov_key_value_secret(softc, sid, DPROV_REQ_MAC_ATOMIC,
5894 	    taskq_req->dr_cipher_mac_req.mr_mac_key, mac_key);
5895 	mutex_exit(&softc->ds_lock);
5896 	if (error != CRYPTO_SUCCESS)
5897 		return (error);
5898 
5899 	/* get the SW provider to perform the cipher operation */
5900 	if ((error = dprov_get_sw_prov(
5901 	    taskq_req->dr_cipher_mac_req.mr_cipher_mech, cipher_pd,
5902 	    cipher_mech_type)) != CRYPTO_SUCCESS)
5903 		return (error);
5904 
5905 	/* get the SW provider to perform the mac operation */
5906 	error = dprov_get_sw_prov(taskq_req->dr_cipher_mac_req.mr_mac_mech,
5907 	    mac_pd, mac_mech_type);
5908 
5909 	return (error);
5910 }
5911 
5912 /*
5913  * taskq dispatcher function for cipher/mac dual operations.
5914  */
5915 static void
5916 dprov_cipher_mac_task(dprov_req_t *taskq_req)
5917 {
5918 	dprov_state_t *softc;
5919 	/* LINTED E_FUNC_SET_NOT_USED */
5920 	int instance;
5921 	int error = CRYPTO_NOT_SUPPORTED;
5922 	crypto_ctx_t *ctx = taskq_req->dr_cipher_mac_req.mr_ctx;
5923 	kcf_provider_desc_t *cipher_pd;
5924 	kcf_provider_desc_t *mac_pd;
5925 	crypto_key_t cipher_key;
5926 	crypto_key_t mac_key;
5927 	crypto_dual_data_t *dual_data =
5928 	    taskq_req->dr_cipher_mac_req.mr_dual_data;
5929 	crypto_data_t cipher_data;
5930 	crypto_data_t mac_data;
5931 	crypto_mechanism_t cipher_mech, mac_mech;
5932 	crypto_session_id_t session_id;
5933 
5934 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5935 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: started\n",
5936 	    instance));
5937 
5938 	switch (taskq_req->dr_type) {
5939 	case DPROV_REQ_ENCRYPT_MAC_INIT:
5940 	case DPROV_REQ_MAC_DECRYPT_INIT:
5941 		/* structure assignment */
5942 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5943 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5944 
5945 		/* get the keys values and providers to use for operations */
5946 		if ((error = dprov_cipher_mac_key_pd(softc, ctx->cc_session,
5947 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5948 		    &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
5949 			break;
5950 
5951 		/* allocate a dprov-private context */
5952 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5953 		    CRYPTO_SUCCESS)
5954 			break;
5955 
5956 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_MAC_INIT)
5957 			/* do the encryption initialization */
5958 			error = crypto_encrypt_init_prov(cipher_pd, 0,
5959 			    &cipher_mech, &cipher_key, NULL,
5960 			    &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
5961 		else
5962 			/* do the decryption initialization */
5963 			error = crypto_decrypt_init_prov(cipher_pd, 0,
5964 			    &cipher_mech, &cipher_key, NULL,
5965 			    &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
5966 		if (error != CRYPTO_SUCCESS)
5967 			break;
5968 
5969 		/* do the mac initialization */
5970 		if ((error = crypto_mac_init_prov(mac_pd, 0,
5971 		    &mac_mech, &mac_key, NULL, &DPROV_CTX_DUAL_MAC(ctx),
5972 		    NULL)) != CRYPTO_SUCCESS)
5973 			break;
5974 
5975 		/* release references to providers */
5976 		KCF_PROV_REFRELE(cipher_pd);
5977 		KCF_PROV_REFRELE(mac_pd);
5978 
5979 		break;
5980 
5981 	case DPROV_REQ_ENCRYPT_MAC: {
5982 		size_t encrypted;
5983 		boolean_t inplace;
5984 
5985 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5986 
5987 		cipher_data = *((crypto_data_t *)dual_data);
5988 
5989 		/* do an encrypt update */
5990 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5991 		if (inplace) {
5992 			plaintext_tmp = &cipher_data;
5993 			ciphertext_tmp = NULL;
5994 		} else {
5995 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5996 			ciphertext_tmp = &cipher_data;
5997 		}
5998 		if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5999 		    plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
6000 			break;
6001 
6002 		/* do an encrypt final */
6003 		encrypted = cipher_data.cd_length;
6004 
6005 		cipher_data.cd_offset += encrypted;
6006 		cipher_data.cd_length = dual_data->dd_len1 - encrypted;
6007 
6008 		if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6009 		    &cipher_data, NULL)) != CRYPTO_SUCCESS)
6010 			break;
6011 
6012 		/*
6013 		 * Do a mac update on the resulting ciphertext, but with no
6014 		 * more bytes than specified by dual_data, and starting at
6015 		 * offset specified by dual_data. For in-place operations,
6016 		 * we use the length specified by the dual_data.
6017 		 */
6018 		mac_data = cipher_data;
6019 		mac_data.cd_offset = dual_data->dd_offset2;
6020 		mac_data.cd_length = dual_data->dd_len2;
6021 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6022 		    &mac_data, NULL)) != CRYPTO_SUCCESS)
6023 			break;
6024 
6025 		/* do a mac final */
6026 		error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6027 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6028 
6029 		/* Set the total size of the ciphertext, when successful */
6030 		if (error == CRYPTO_SUCCESS)
6031 			dual_data->dd_len1 = encrypted + cipher_data.cd_length;
6032 
6033 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
6034 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6035 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
6036 			(void) dprov_free_context(ctx);
6037 		}
6038 		break;
6039 	}
6040 
6041 	case DPROV_REQ_ENCRYPT_MAC_UPDATE: {
6042 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
6043 		size_t encrypted;
6044 		ssize_t maclen;
6045 		boolean_t inplace;
6046 
6047 		cipher_data = *((crypto_data_t *)dual_data);
6048 
6049 		/* do an encrypt update */
6050 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
6051 		if (inplace) {
6052 			plaintext_tmp = &cipher_data;
6053 			ciphertext_tmp = NULL;
6054 		} else {
6055 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
6056 			ciphertext_tmp = &cipher_data;
6057 		}
6058 		if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6059 		    plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
6060 			break;
6061 
6062 		encrypted = cipher_data.cd_length;
6063 
6064 		/*
6065 		 * Do a mac update on the resulting ciphertext, but with no
6066 		 * more bytes than specified by dual_data, and starting at
6067 		 * offset specified by dual_data. For in-place operations,
6068 		 * we use the length specified by the dual_data.
6069 		 * There is an edge case, when the encryption step produced
6070 		 * zero bytes in the ciphertext. Only the portion between
6071 		 * offset2 and offset1 is then thrown in the MAC mix.
6072 		 */
6073 		maclen = dual_data->dd_offset1 - dual_data->dd_offset2 +
6074 		    encrypted;
6075 		if (maclen > 0) {
6076 			mac_data = cipher_data;
6077 			mac_data.cd_offset = dual_data->dd_offset2;
6078 			mac_data.cd_length = min(dual_data->dd_len2, maclen);
6079 			if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6080 			    &mac_data, NULL)) != CRYPTO_SUCCESS)
6081 				break;
6082 		}
6083 		/* Set the total size of the ciphertext, when successful */
6084 		if (error == CRYPTO_SUCCESS)
6085 			dual_data->dd_len1 = encrypted;
6086 
6087 		break;
6088 	}
6089 
6090 	case DPROV_REQ_ENCRYPT_MAC_FINAL:
6091 		cipher_data = *((crypto_data_t *)dual_data);
6092 
6093 		/* do an encrypt final */
6094 		if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6095 		    taskq_req->dr_cipher_mac_req.mr_data == NULL ?
6096 		    &cipher_data : taskq_req->dr_cipher_mac_req.mr_data,
6097 		    NULL)) != CRYPTO_SUCCESS)
6098 			break;
6099 
6100 		/*
6101 		 * If ciphertext length is different from zero, do a mac
6102 		 * update on it. This does not apply to in-place since we
6103 		 * do not allow partial updates, hence no final residual.
6104 		 */
6105 		if (taskq_req->dr_cipher_mac_req.mr_data != NULL &&
6106 		    taskq_req->dr_cipher_mac_req.mr_data->cd_length > 0)
6107 			if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6108 			    taskq_req->dr_cipher_mac_req.mr_data, NULL)) !=
6109 			    CRYPTO_SUCCESS)
6110 				break;
6111 
6112 		/* do a mac final */
6113 		error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6114 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6115 
6116 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
6117 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6118 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
6119 			(void) dprov_free_context(ctx);
6120 		}
6121 		break;
6122 
6123 	case DPROV_REQ_ENCRYPT_MAC_ATOMIC: {
6124 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
6125 		boolean_t inplace;
6126 
6127 		cipher_data = *((crypto_data_t *)dual_data);
6128 
6129 		/* do an encrypt atomic */
6130 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
6131 		if (inplace) {
6132 			plaintext_tmp = &cipher_data;
6133 			ciphertext_tmp = NULL;
6134 		} else {
6135 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
6136 			ciphertext_tmp = &cipher_data;
6137 		}
6138 
6139 		/* structure assignment */
6140 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
6141 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
6142 		session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
6143 
6144 		/* get the keys values and providers to use for operations */
6145 		if ((error = dprov_cipher_mac_key_pd(softc, session_id,
6146 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
6147 		    &cipher_mech.cm_type, &mac_mech.cm_type)) !=
6148 		    CRYPTO_SUCCESS)
6149 			break;
6150 
6151 		/* do the atomic encrypt */
6152 		if ((error = crypto_encrypt_prov(cipher_pd, 0,
6153 		    &cipher_mech, plaintext_tmp, &cipher_key, NULL,
6154 		    ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
6155 			break;
6156 
6157 		/* do the atomic mac */
6158 		mac_data = cipher_data;
6159 		mac_data.cd_length = dual_data->dd_len2;
6160 		mac_data.cd_offset = dual_data->dd_offset2;
6161 		error = crypto_mac_prov(mac_pd, 0, &mac_mech, &mac_data,
6162 		    &mac_key, NULL, taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6163 
6164 		dual_data->dd_len1 = cipher_data.cd_length;
6165 
6166 		break;
6167 	}
6168 
6169 	case DPROV_REQ_MAC_DECRYPT: {
6170 		uint_t decrypted;
6171 		crypto_data_t plaintext_tmp;
6172 
6173 		cipher_data = *((crypto_data_t *)dual_data);
6174 
6175 		/* do a mac update and final on the ciphertext */
6176 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6177 		    &mac_data, NULL)) != CRYPTO_SUCCESS)
6178 			break;
6179 
6180 		/* do a mac final */
6181 		if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6182 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
6183 		    CRYPTO_SUCCESS)
6184 			break;
6185 
6186 		/* do an decrypt update */
6187 		cipher_data = mac_data;
6188 		cipher_data.cd_length = dual_data->dd_len2;
6189 		cipher_data.cd_offset = dual_data->dd_offset2;
6190 		if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
6191 			/* in-place */
6192 			plaintext_tmp = cipher_data;
6193 		else
6194 			plaintext_tmp = *taskq_req->dr_cipher_mac_req.mr_data;
6195 
6196 		if ((error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6197 		    &cipher_data, taskq_req->dr_cipher_mac_req.mr_data,
6198 		    NULL)) != CRYPTO_SUCCESS)
6199 			break;
6200 
6201 		/* do an decrypt final */
6202 		if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
6203 			/* in-place, everything must have been decrypted */
6204 			decrypted = cipher_data.cd_length;
6205 		else
6206 			decrypted =
6207 			    taskq_req->dr_cipher_mac_req.mr_data->cd_length;
6208 		plaintext_tmp.cd_offset += decrypted;
6209 		plaintext_tmp.cd_length -= decrypted;
6210 
6211 		error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6212 		    &plaintext_tmp, NULL);
6213 		if (taskq_req->dr_cipher_mac_req.mr_data != NULL)
6214 			taskq_req->dr_cipher_mac_req.mr_data->cd_length +=
6215 			    plaintext_tmp.cd_length;
6216 
6217 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
6218 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
6219 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6220 			(void) dprov_free_context(ctx);
6221 		}
6222 		break;
6223 	}
6224 
6225 	case DPROV_REQ_MAC_DECRYPT_UPDATE:
6226 		cipher_data = *((crypto_data_t *)dual_data);
6227 
6228 		/* do mac update */
6229 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6230 		    &cipher_data, NULL)) != CRYPTO_SUCCESS)
6231 			break;
6232 
6233 		/* do a decrypt update */
6234 		cipher_data.cd_length = dual_data->dd_len2;
6235 		cipher_data.cd_offset = dual_data->dd_offset2;
6236 		error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6237 		    &cipher_data, taskq_req->dr_cipher_mac_req.mr_data, NULL);
6238 
6239 		break;
6240 
6241 	case DPROV_REQ_MAC_DECRYPT_FINAL:
6242 		/* do a mac final */
6243 		if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6244 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
6245 		    CRYPTO_SUCCESS)
6246 			break;
6247 
6248 		/* do a decrypt final */
6249 		error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6250 		    taskq_req->dr_cipher_mac_req.mr_data, NULL);
6251 
6252 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
6253 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
6254 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6255 			(void) dprov_free_context(ctx);
6256 		}
6257 		break;
6258 
6259 	case DPROV_REQ_MAC_DECRYPT_ATOMIC:
6260 	case DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC:
6261 		cipher_data = *((crypto_data_t *)dual_data);
6262 
6263 		/* structure assignment */
6264 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
6265 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
6266 		session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
6267 
6268 		/* get the keys values and providers to use for operations */
6269 		if ((error = dprov_cipher_mac_key_pd(softc, session_id,
6270 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
6271 		    &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
6272 			break;
6273 
6274 		/* do the atomic mac */
6275 		if (taskq_req->dr_type == DPROV_REQ_MAC_DECRYPT_ATOMIC)
6276 			error = crypto_mac_prov(mac_pd, 0, &mac_mech,
6277 			    &cipher_data, &mac_key, NULL,
6278 			    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6279 		else
6280 			/* DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC */
6281 			error = crypto_mac_verify_prov(mac_pd, 0, &mac_mech,
6282 			    &cipher_data, &mac_key, NULL,
6283 			    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6284 
6285 		if (error != CRYPTO_SUCCESS)
6286 			break;
6287 
6288 		/* do the atomic decrypt */
6289 		cipher_data.cd_length = dual_data->dd_len2;
6290 		cipher_data.cd_offset = dual_data->dd_offset2;
6291 		error = crypto_decrypt_prov(cipher_pd, 0, &cipher_mech,
6292 		    &cipher_data, &cipher_key, NULL,
6293 		    taskq_req->dr_cipher_mac_req.mr_data, NULL);
6294 
6295 		break;
6296 	}
6297 
6298 	dprov_op_done(taskq_req, error);
6299 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: end\n",
6300 	    instance));
6301 }
6302 
6303 /*
6304  * taskq dispatcher function for random number generation.
6305  */
6306 static void
6307 dprov_random_task(dprov_req_t *taskq_req)
6308 {
6309 	dprov_state_t *softc;
6310 	/* LINTED E_FUNC_SET_NOT_USED */
6311 	int instance;
6312 	int error = CRYPTO_SUCCESS;
6313 
6314 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6315 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: started\n", instance));
6316 
6317 	mutex_enter(&softc->ds_lock);
6318 
6319 	switch (taskq_req->dr_type) {
6320 
6321 	DPROV_REQ_RANDOM_SEED:
6322 		/*
6323 		 * Since we don't really generate random numbers
6324 		 * nothing to do.
6325 		 */
6326 		break;
6327 
6328 	case DPROV_REQ_RANDOM_GENERATE: {
6329 		uint_t i;
6330 		uchar_t c = 0;
6331 
6332 		/*
6333 		 * We don't generate random numbers so that the result
6334 		 * of the operation can be checked during testing.
6335 		 */
6336 
6337 		for (i = 0; i < taskq_req->dr_random_req.rr_len; i++)
6338 			taskq_req->dr_random_req.rr_buf[i] = c++;
6339 
6340 		break;
6341 	}
6342 	}
6343 
6344 	mutex_exit(&softc->ds_lock);
6345 	dprov_op_done(taskq_req, error);
6346 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: end\n", instance));
6347 }
6348 
6349 
6350 /*
6351  * taskq dispatcher function for session management operations.
6352  */
6353 static void
6354 dprov_session_task(dprov_req_t *taskq_req)
6355 {
6356 	dprov_state_t *softc;
6357 	/* LINTED E_FUNC_SET_NOT_USED */
6358 	int instance;
6359 	int error = CRYPTO_NOT_SUPPORTED;
6360 	crypto_session_id_t session_id =
6361 	    taskq_req->dr_session_req.sr_session_id;
6362 	dprov_session_t *session;
6363 	dprov_object_t *object;
6364 	int i;
6365 
6366 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6367 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: started\n",
6368 	    instance));
6369 
6370 	mutex_enter(&softc->ds_lock);
6371 
6372 	if (taskq_req->dr_type != DPROV_REQ_SESSION_OPEN)
6373 		/* validate session id and get ptr to session */
6374 		if ((session = softc->ds_sessions[session_id]) == NULL) {
6375 			mutex_exit(&softc->ds_lock);
6376 			dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6377 			return;
6378 		}
6379 
6380 	switch (taskq_req->dr_type) {
6381 
6382 	case DPROV_REQ_SESSION_OPEN: {
6383 		dprov_session_t **new_sessions;
6384 
6385 		if (softc->ds_token_initialized == B_FALSE) {
6386 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
6387 			break;
6388 		}
6389 
6390 		/* search for available session slot */
6391 		for (i = 0; i < softc->ds_sessions_slots; i++)
6392 			if (softc->ds_sessions[i] == NULL)
6393 				break;
6394 
6395 		if (i == softc->ds_sessions_slots) {
6396 			/* ran out of slots, grow sessions array */
6397 			new_sessions = kmem_zalloc(2 * softc->ds_sessions_slots,
6398 			    KM_NOSLEEP);
6399 			if (new_sessions == NULL) {
6400 				error = CRYPTO_SESSION_COUNT;
6401 				break;
6402 			}
6403 			bcopy(softc->ds_sessions, new_sessions,
6404 			    softc->ds_sessions_slots);
6405 			kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
6406 			    sizeof (dprov_session_t *));
6407 			softc->ds_sessions = new_sessions;
6408 			softc->ds_sessions_slots *= 2;
6409 		}
6410 
6411 		/* allocate and initialize new session */
6412 		softc->ds_sessions[i] = kmem_zalloc(
6413 		    sizeof (dprov_session_t), KM_NOSLEEP);
6414 		if (softc->ds_sessions[i] == NULL) {
6415 			error = CRYPTO_HOST_MEMORY;
6416 			break;
6417 		}
6418 		softc->ds_sessions_count++;
6419 
6420 		/* initialize session state */
6421 		softc->ds_sessions[i]->ds_state = DPROV_SESSION_STATE_PUBLIC;
6422 
6423 		/* return new session id to caller */
6424 		*(taskq_req->dr_session_req.sr_session_id_ptr) = i;
6425 
6426 		error = CRYPTO_SUCCESS;
6427 		break;
6428 	}
6429 
6430 	case DPROV_REQ_SESSION_CLOSE:
6431 		softc->ds_sessions[session_id] = NULL;
6432 
6433 		if (softc->ds_token_initialized == B_FALSE) {
6434 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
6435 			break;
6436 		}
6437 
6438 		dprov_release_session_objects(session);
6439 
6440 		/* free session state and corresponding slot */
6441 		kmem_free(session, sizeof (dprov_session_t));
6442 		softc->ds_sessions_count--;
6443 
6444 		error = CRYPTO_SUCCESS;
6445 		break;
6446 
6447 	case DPROV_REQ_SESSION_LOGIN: {
6448 		char *pin = taskq_req->dr_session_req.sr_pin;
6449 		size_t pin_len = taskq_req->dr_session_req.sr_pin_len;
6450 		crypto_user_type_t user_type =
6451 		    taskq_req->dr_session_req.sr_user_type;
6452 
6453 		/* check user type */
6454 		if (user_type != CRYPTO_SO && user_type != CRYPTO_USER) {
6455 			error = CRYPTO_USER_TYPE_INVALID;
6456 			break;
6457 		}
6458 
6459 		/* check pin length */
6460 		if (pin_len > DPROV_MAX_PIN_LEN) {
6461 			error = CRYPTO_PIN_LEN_RANGE;
6462 			break;
6463 		}
6464 
6465 		/* check pin */
6466 		if (pin == NULL) {
6467 			error = CRYPTO_PIN_INVALID;
6468 			break;
6469 		}
6470 
6471 		/* validate PIN state */
6472 		if ((user_type == CRYPTO_SO) && !softc->ds_token_initialized ||
6473 		    (user_type == CRYPTO_USER) && !softc->ds_user_pin_set) {
6474 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
6475 			break;
6476 		}
6477 
6478 		if ((user_type == CRYPTO_SO &&
6479 		    softc->ds_sessions[session_id]->ds_state ==
6480 		    DPROV_SESSION_STATE_SO) ||
6481 		    (user_type == CRYPTO_USER &&
6482 		    softc->ds_sessions[session_id]->ds_state ==
6483 		    DPROV_SESSION_STATE_USER)) {
6484 			/* SO or user already logged in */
6485 			error = CRYPTO_USER_ALREADY_LOGGED_IN;
6486 			break;
6487 		}
6488 
6489 		if (softc->ds_sessions[session_id]->ds_state !=
6490 		    DPROV_SESSION_STATE_PUBLIC) {
6491 			/* another user already logged in */
6492 			error = CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN;
6493 			break;
6494 		}
6495 
6496 		/* everything's fine, update session */
6497 		softc->ds_sessions[session_id]->ds_state =
6498 		    user_type == CRYPTO_SO ?
6499 		    DPROV_SESSION_STATE_SO : DPROV_SESSION_STATE_USER;
6500 
6501 		error = CRYPTO_SUCCESS;
6502 		break;
6503 	}
6504 
6505 	case DPROV_REQ_SESSION_LOGOUT:
6506 		/* fail if not logged in */
6507 		if (softc->ds_sessions[session_id]->ds_state ==
6508 		    DPROV_SESSION_STATE_PUBLIC) {
6509 			error = CRYPTO_USER_NOT_LOGGED_IN;
6510 			break;
6511 		}
6512 
6513 		/*
6514 		 * Destroy all private session objects.
6515 		 * Invalidate handles to all private objects.
6516 		 */
6517 		for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
6518 			object = softc->ds_sessions[session_id]->ds_objects[i];
6519 			if (object != NULL && dprov_object_is_private(object)) {
6520 				if (!dprov_object_is_token(object))
6521 					/* It's a session object, free it */
6522 					DPROV_OBJECT_REFRELE(object);
6523 				softc->ds_sessions[session_id]->ds_objects[i] =
6524 				    NULL;
6525 			}
6526 		}
6527 
6528 		/* update session state */
6529 		softc->ds_sessions[session_id]->ds_state =
6530 		    DPROV_SESSION_STATE_PUBLIC;
6531 
6532 		error = CRYPTO_SUCCESS;
6533 		break;
6534 	}
6535 
6536 	mutex_exit(&softc->ds_lock);
6537 	dprov_op_done(taskq_req, error);
6538 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: end\n", instance));
6539 }
6540 
6541 /* return true if attribute is defined to be a PKCS#11 long */
6542 static boolean_t
6543 fixed_size_attribute(crypto_attr_type_t type)
6544 {
6545 	return (type == DPROV_CKA_CLASS ||
6546 	    type == DPROV_CKA_CERTIFICATE_TYPE ||
6547 	    type == DPROV_CKA_KEY_TYPE ||
6548 	    type == DPROV_HW_FEATURE_TYPE);
6549 }
6550 
6551 /*
6552  * Attributes defined to be a PKCS#11 long causes problems for dprov
6553  * because 32-bit applications set the size to 4 and 64-bit applications
6554  * set the size to 8. dprov always stores these fixed-size attributes
6555  * as uint32_t.
6556  */
6557 static ssize_t
6558 attribute_size(crypto_attr_type_t type, ssize_t len)
6559 {
6560 	if (fixed_size_attribute(type))
6561 		return (sizeof (uint32_t));
6562 
6563 	return (len);
6564 }
6565 
6566 /*
6567  * taskq dispatcher function for object management operations.
6568  */
6569 static void
6570 dprov_object_task(dprov_req_t *taskq_req)
6571 {
6572 	dprov_state_t *softc;
6573 	/* LINTED E_FUNC_SET_NOT_USED */
6574 	int instance;
6575 	int error = CRYPTO_NOT_SUPPORTED;
6576 	crypto_object_id_t object_id = taskq_req->dr_object_req.or_object_id;
6577 	crypto_session_id_t session_id = taskq_req->dr_object_req.or_session_id;
6578 	crypto_object_attribute_t *template =
6579 	    taskq_req->dr_object_req.or_template;
6580 	uint_t attr_count = taskq_req->dr_object_req.or_attribute_count;
6581 	dprov_object_t *object;
6582 	dprov_session_t *session;
6583 
6584 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6585 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: started\n", instance));
6586 
6587 	mutex_enter(&softc->ds_lock);
6588 
6589 	/* validate session id and get ptr to session */
6590 	if ((session = softc->ds_sessions[session_id]) == NULL) {
6591 		mutex_exit(&softc->ds_lock);
6592 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6593 		return;
6594 	}
6595 
6596 	switch (taskq_req->dr_type) {
6597 
6598 	case DPROV_REQ_OBJECT_CREATE:
6599 		/* create the object from the specified template */
6600 		if ((error = dprov_create_object_from_template(softc, session,
6601 		    template, attr_count,
6602 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
6603 		    B_FALSE)) != CRYPTO_SUCCESS)
6604 			break;
6605 
6606 		break;
6607 
6608 	case DPROV_REQ_OBJECT_COPY:
6609 		/* check object id */
6610 		if (object_id >= DPROV_MAX_OBJECTS ||
6611 		    (object = session->ds_objects[object_id]) == NULL) {
6612 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6613 			break;
6614 		}
6615 
6616 		/*
6617 		 * Create a new object from the object passed as
6618 		 * argument.
6619 		 */
6620 		if ((error = dprov_create_object_from_template(softc, session,
6621 		    object->do_attr, DPROV_MAX_ATTR,
6622 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
6623 		    B_FALSE)) != CRYPTO_SUCCESS)
6624 			break;
6625 
6626 		/*
6627 		 * Add the attributes specified by the template to the
6628 		 * newly created object, replacing existing ones if needed.
6629 		 */
6630 		error = dprov_object_set_attr(session,
6631 		    *taskq_req->dr_object_req.or_object_id_ptr,
6632 		    taskq_req->dr_object_req.or_template,
6633 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6634 
6635 		break;
6636 
6637 	case DPROV_REQ_OBJECT_DESTROY:
6638 		/* destroy the object */
6639 		error = dprov_destroy_object(softc, session,
6640 		    taskq_req->dr_object_req.or_object_id);
6641 
6642 		break;
6643 
6644 	case DPROV_REQ_OBJECT_GET_SIZE:
6645 		/* get ptr to object */
6646 		if (object_id >= DPROV_MAX_OBJECTS ||
6647 		    session->ds_objects[object_id] == NULL) {
6648 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6649 			break;
6650 		}
6651 
6652 		/*
6653 		 * The PKCS11 specification does not specifies what
6654 		 * the object size really is, here we just return
6655 		 * the number of possible attributes of the object.
6656 		 */
6657 		*taskq_req->dr_object_req.or_object_size = DPROV_MAX_ATTR;
6658 
6659 		error = CRYPTO_SUCCESS;
6660 		break;
6661 
6662 	case DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE: {
6663 		crypto_attr_type_t type;
6664 		size_t olen, tlen;
6665 		offset_t offset;
6666 		int tmpl_idx;
6667 		int object_idx;
6668 		ulong_t class = DPROV_CKO_DATA;
6669 		boolean_t extractable = B_TRUE;
6670 
6671 		error = CRYPTO_SUCCESS;
6672 
6673 		/* get ptr to object */
6674 		if (object_id >= DPROV_MAX_OBJECTS ||
6675 		    (object = session->ds_objects[object_id]) == NULL) {
6676 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6677 			break;
6678 		}
6679 
6680 		(void) dprov_get_object_attr_boolean(object,
6681 		    DPROV_CKA_EXTRACTABLE, &extractable);
6682 
6683 		(void) dprov_get_object_attr_ulong(object,
6684 		    DPROV_CKA_CLASS, &class);
6685 
6686 		/* return the specified attributes, when possible */
6687 		for (tmpl_idx = 0; tmpl_idx < attr_count; tmpl_idx++) {
6688 			/*
6689 			 * Attribute can't be revealed if the CKA_EXTRACTABLE
6690 			 * attribute is set to false.
6691 			 */
6692 			type = template[tmpl_idx].oa_type;
6693 			if (!extractable && class == DPROV_CKO_SECRET_KEY) {
6694 				if (type == DPROV_CKA_VALUE) {
6695 					template[tmpl_idx].oa_value_len = -1;
6696 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6697 					continue;
6698 				}
6699 			}
6700 			if (!extractable && class == DPROV_CKO_PRIVATE_KEY) {
6701 				if (type == DPROV_CKA_PRIVATE_EXPONENT) {
6702 					template[tmpl_idx].oa_value_len = -1;
6703 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6704 					continue;
6705 				}
6706 			}
6707 
6708 			object_idx = dprov_find_attr(object->do_attr,
6709 			    DPROV_MAX_ATTR, type);
6710 			if (object_idx == -1) {
6711 				/* attribute not found in object */
6712 				template[tmpl_idx].oa_value_len = -1;
6713 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
6714 				continue;
6715 			}
6716 
6717 			tlen = template[tmpl_idx].oa_value_len;
6718 			olen = object->do_attr[object_idx].oa_value_len;
6719 			/* return attribute length */
6720 			if (template[tmpl_idx].oa_value == NULL) {
6721 				/*
6722 				 * The size of the attribute is set by the
6723 				 * library according to the data model of the
6724 				 * application, so don't overwrite it with
6725 				 * dprov's size.
6726 				 */
6727 				if (!fixed_size_attribute(type))
6728 					template[tmpl_idx].oa_value_len = olen;
6729 				continue;
6730 			}
6731 
6732 			if (tlen < olen) {
6733 				template[tmpl_idx].oa_value_len = -1;
6734 				error = CRYPTO_BUFFER_TOO_SMALL;
6735 				continue;
6736 			}
6737 
6738 			/* copy attribute value */
6739 			bzero(template[tmpl_idx].oa_value, tlen);
6740 
6741 			offset = 0;
6742 #ifdef _BIG_ENDIAN
6743 			if (fixed_size_attribute(type)) {
6744 				offset = tlen - olen;
6745 			}
6746 #endif
6747 			bcopy(object->do_attr[object_idx].oa_value,
6748 			    &template[tmpl_idx].oa_value[offset], olen);
6749 
6750 			/* don't update length for fixed-size attributes */
6751 			if (!fixed_size_attribute(type))
6752 				template[tmpl_idx].oa_value_len = olen;
6753 		}
6754 
6755 		break;
6756 	}
6757 
6758 	case DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE:
6759 		/*
6760 		 * Add the attributes specified by the template to the
6761 		 * newly created object, replacing existing ones if needed.
6762 		 */
6763 		error = dprov_object_set_attr(session,
6764 		    taskq_req->dr_object_req.or_object_id,
6765 		    taskq_req->dr_object_req.or_template,
6766 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6767 
6768 		break;
6769 
6770 	case DPROV_REQ_OBJECT_FIND_INIT: {
6771 		dprov_find_ctx_t *find_ctx;
6772 		int so_idx;		/* session object index */
6773 		int to_idx;		/* token object index */
6774 
6775 		error = CRYPTO_SUCCESS;
6776 		/* allocate find context */
6777 		find_ctx = kmem_zalloc(sizeof (dprov_find_ctx_t), KM_SLEEP);
6778 		*taskq_req->dr_object_req.or_find_pp = find_ctx;
6779 
6780 		/* first go through the existing session objects */
6781 		for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++) {
6782 			if ((object = session->ds_objects[so_idx]) == NULL)
6783 				continue;
6784 
6785 			/* setting count to zero means find all objects */
6786 			if (attr_count > 0) {
6787 				if (!dprov_attributes_match(object, template,
6788 				    attr_count))
6789 					continue;
6790 			}
6791 
6792 			/* session object attributes matches template */
6793 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
6794 			find_ctx->fc_nids++;
6795 		}
6796 
6797 		/*
6798 		 * Go through the token object. For each token object
6799 		 * that can be accessed:
6800 		 * If there was already an session object id assigned
6801 		 * to that token object, skip it, since it was returned
6802 		 * during the check of session objects, else,
6803 		 * assign a new object id for that token object and
6804 		 * add it to the array of matching objects.
6805 		 */
6806 		for (to_idx = 0; to_idx < DPROV_MAX_OBJECTS &&
6807 		    error == CRYPTO_SUCCESS; to_idx++) {
6808 			if ((object = softc->ds_objects[to_idx]) == NULL)
6809 				continue;
6810 
6811 			/* setting count to zero means find all objects */
6812 			if (attr_count > 0) {
6813 				if (!dprov_attributes_match(object, template,
6814 				    attr_count))
6815 					continue;
6816 			}
6817 
6818 			/* if the the object has been destroyed, skip it */
6819 			if (object->do_destroyed)
6820 				continue;
6821 
6822 			/* skip object if it cannot be accessed from session */
6823 			if (dprov_object_is_private(object) &&
6824 			    session->ds_state != DPROV_SESSION_STATE_USER)
6825 				continue;
6826 
6827 			/*
6828 			 * Is there already a session object id for this
6829 			 * token object?
6830 			 */
6831 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
6832 				if (session->ds_objects[so_idx] != NULL &&
6833 				    session->ds_objects[so_idx]->do_token_idx ==
6834 				    to_idx)
6835 					break;
6836 			if (so_idx < DPROV_MAX_OBJECTS)
6837 				/* object found in session table, skip it */
6838 				continue;
6839 
6840 			/* find free session slot for this object */
6841 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
6842 				if (session->ds_objects[so_idx] == NULL)
6843 					break;
6844 			if (so_idx == DPROV_MAX_OBJECTS) {
6845 				/* ran out of session objects slots */
6846 				kmem_free(find_ctx, sizeof (dprov_find_ctx_t));
6847 				error = CRYPTO_HOST_MEMORY;
6848 				break;
6849 			}
6850 
6851 			/* add object to session objects table */
6852 			session->ds_objects[so_idx] = object;
6853 			DPROV_OBJECT_REFHOLD(object);
6854 
6855 			/* add object to list of objects to return */
6856 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
6857 			find_ctx->fc_nids++;
6858 		}
6859 
6860 		break;
6861 	}
6862 
6863 	case DPROV_REQ_OBJECT_FIND: {
6864 		crypto_object_id_t *object_ids =
6865 		    taskq_req->dr_object_req.or_object_id_ptr;
6866 		uint_t max_object_count =
6867 		    taskq_req->dr_object_req.or_max_object_count;
6868 		dprov_find_ctx_t *find_ctx =
6869 		    taskq_req->dr_object_req.or_find_p;
6870 		uint_t ret_oid_idx;
6871 
6872 		/* return the desired number of object ids */
6873 		for (ret_oid_idx = 0; ret_oid_idx < max_object_count &&
6874 		    find_ctx->fc_next < find_ctx->fc_nids; ret_oid_idx++)
6875 			object_ids[ret_oid_idx] =
6876 			    find_ctx->fc_ids[find_ctx->fc_next++];
6877 
6878 		*taskq_req->dr_object_req.or_object_count_ptr = ret_oid_idx;
6879 
6880 		error = CRYPTO_SUCCESS;
6881 		break;
6882 	}
6883 
6884 	case DPROV_REQ_OBJECT_FIND_FINAL:
6885 		kmem_free(taskq_req->dr_object_req.or_find_p,
6886 		    sizeof (dprov_find_ctx_t));
6887 
6888 		error = CRYPTO_SUCCESS;
6889 		break;
6890 	}
6891 
6892 	mutex_exit(&softc->ds_lock);
6893 	dprov_op_done(taskq_req, error);
6894 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: end\n", instance));
6895 }
6896 
6897 /*
6898  * Copy attribute values into a template. RSA values are precomputed.
6899  */
6900 static int
6901 nostore_copy_attribute(crypto_object_attribute_t *template, uint_t count,
6902     uint64_t attr_type)
6903 {
6904 	void *value, *dprov_attribute_value;
6905 	size_t dprov_attribute_size;
6906 	size_t value_len = 0;
6907 	int error;
6908 
6909 	switch (attr_type) {
6910 	case DPROV_CKA_VALUE:
6911 		dprov_attribute_size = sizeof (dh_value);
6912 		dprov_attribute_value = dh_value;
6913 		break;
6914 
6915 	case DPROV_CKA_MODULUS:
6916 		dprov_attribute_size = sizeof (modulus);
6917 		dprov_attribute_value = modulus;
6918 		break;
6919 
6920 	case DPROV_CKA_PUBLIC_EXPONENT:
6921 		dprov_attribute_size = sizeof (public_exponent);
6922 		dprov_attribute_value = public_exponent;
6923 		break;
6924 
6925 	case DPROV_CKA_PRIVATE_EXPONENT:
6926 		dprov_attribute_size = sizeof (private_exponent);
6927 		dprov_attribute_value = private_exponent;
6928 		break;
6929 
6930 	default:
6931 		return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
6932 	}
6933 
6934 	error = dprov_get_template_attr_array(template, count, attr_type,
6935 	    &value, &value_len);
6936 	if (error != CRYPTO_SUCCESS)
6937 		return (error);
6938 
6939 	if (value_len < dprov_attribute_size)
6940 		return (CRYPTO_BUFFER_TOO_SMALL);
6941 
6942 	/*
6943 	 * The updated template will be returned to libpkcs11.
6944 	 */
6945 	bcopy(dprov_attribute_value, value, dprov_attribute_size);
6946 
6947 	return (CRYPTO_SUCCESS);
6948 }
6949 
6950 static void
6951 fill_dh(void *value, size_t len)
6952 {
6953 	int i = 0;
6954 	char *p = value;
6955 	while (i < len) {
6956 		p[i++] = 'D';
6957 		if (i >= len)
6958 			break;
6959 		p[i++] = 'H';
6960 	}
6961 }
6962 
6963 /*
6964  * taskq dispatcher function for key management operations.
6965  */
6966 static void
6967 dprov_key_task(dprov_req_t *taskq_req)
6968 {
6969 	dprov_state_t *softc;
6970 	/* LINTED E_FUNC_SET_NOT_USED */
6971 	int instance;
6972 	int error = CRYPTO_NOT_SUPPORTED;
6973 	kcf_provider_desc_t *pd;
6974 	crypto_session_id_t session_id = taskq_req->dr_key_req.kr_session_id;
6975 	dprov_session_t *session;
6976 
6977 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6978 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: started\n", instance));
6979 
6980 	mutex_enter(&softc->ds_lock);
6981 
6982 	/* validate session id and get ptr to session */
6983 	if ((session = softc->ds_sessions[session_id]) == NULL) {
6984 		mutex_exit(&softc->ds_lock);
6985 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6986 		return;
6987 	}
6988 
6989 	switch (taskq_req->dr_type) {
6990 	case DPROV_REQ_KEY_GENERATE: {
6991 		crypto_mechanism_t *mechp;
6992 		crypto_object_id_t *object_id_ptr;
6993 		crypto_object_attribute_t *template;
6994 		crypto_object_attribute_t attribute;
6995 		uint_t attribute_count;
6996 		ulong_t key_type = ~0UL, class = ~0UL;
6997 		ulong_t value_len;
6998 		size_t key_len = 0;
6999 
7000 		error = CRYPTO_SUCCESS;
7001 
7002 		template = taskq_req->dr_key_req.kr_template;
7003 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7004 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7005 		mechp = taskq_req->dr_key_req.kr_mechanism;
7006 
7007 		/* optional */
7008 		(void) dprov_get_template_attr_ulong(template, attribute_count,
7009 		    DPROV_CKA_CLASS, &class);
7010 
7011 		/* optional */
7012 		(void) dprov_get_template_attr_ulong(template, attribute_count,
7013 		    DPROV_CKA_KEY_TYPE, &key_type);
7014 
7015 		if (class != ~0UL && class != DPROV_CKO_SECRET_KEY) {
7016 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7017 			break;
7018 		}
7019 
7020 		switch (mechp->cm_type) {
7021 		case DES_KEY_GEN_MECH_INFO_TYPE:
7022 			if (key_type != ~0UL && key_type != DPROV_CKK_DES) {
7023 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7024 				break;
7025 			}
7026 			key_len = DES_KEY_LEN;
7027 			key_type = DPROV_CKK_DES;
7028 			break;
7029 
7030 		case DES3_KEY_GEN_MECH_INFO_TYPE:
7031 			if (key_type != ~0UL && key_type != DPROV_CKK_DES3) {
7032 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7033 				break;
7034 			}
7035 			key_len = DES3_KEY_LEN;
7036 			key_type = DPROV_CKK_DES3;
7037 			break;
7038 
7039 		case AES_KEY_GEN_MECH_INFO_TYPE:
7040 			if (key_type != ~0UL && key_type != DPROV_CKK_AES) {
7041 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7042 				break;
7043 			}
7044 			if (dprov_get_template_attr_ulong(template,
7045 			    attribute_count, DPROV_CKA_VALUE_LEN,
7046 			    &value_len) != CRYPTO_SUCCESS) {
7047 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7048 				break;
7049 			}
7050 			if (value_len >= AES_MAX_KEY_LEN) {
7051 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7052 				break;
7053 			}
7054 			key_len = value_len;
7055 			key_type = DPROV_CKK_AES;
7056 			break;
7057 
7058 		case BLOWFISH_KEY_GEN_MECH_INFO_TYPE:
7059 			if (key_type != ~0UL &&
7060 			    key_type != DPROV_CKK_BLOWFISH) {
7061 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7062 				break;
7063 			}
7064 			if (dprov_get_template_attr_ulong(template,
7065 			    attribute_count, DPROV_CKA_VALUE_LEN,
7066 			    &value_len) != CRYPTO_SUCCESS) {
7067 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7068 				break;
7069 			}
7070 			if (value_len >= BLOWFISH_MAX_KEY_LEN) {
7071 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7072 				break;
7073 			}
7074 			key_len = value_len;
7075 			key_type = DPROV_CKK_BLOWFISH;
7076 			break;
7077 
7078 		case RC4_KEY_GEN_MECH_INFO_TYPE:
7079 			if (key_type != ~0UL && key_type != DPROV_CKK_RC4) {
7080 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7081 				break;
7082 			}
7083 			if (dprov_get_template_attr_ulong(template,
7084 			    attribute_count, DPROV_CKA_VALUE_LEN,
7085 			    &value_len) != CRYPTO_SUCCESS) {
7086 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7087 				break;
7088 			}
7089 			if (value_len >=
7090 			    CRYPTO_BITS2BYTES(ARCFOUR_MAX_KEY_BITS)) {
7091 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7092 				break;
7093 			}
7094 			key_len = value_len;
7095 			key_type = DPROV_CKK_RC4;
7096 			break;
7097 
7098 		default:
7099 			error = CRYPTO_MECHANISM_INVALID;
7100 		}
7101 
7102 		if (error != CRYPTO_SUCCESS)
7103 			break;
7104 
7105 		error = dprov_create_object_from_template(softc, session,
7106 		    template, attribute_count, object_id_ptr, B_FALSE, B_TRUE);
7107 
7108 		if (error != CRYPTO_SUCCESS)
7109 			break;
7110 
7111 		/* make sure class is set */
7112 		attribute.oa_type = DPROV_CKA_CLASS;
7113 		attribute.oa_value = (char *)&class;
7114 		attribute.oa_value_len = sizeof (ulong_t);
7115 		error = dprov_object_set_attr(session, *object_id_ptr,
7116 		    &attribute, 1, B_FALSE);
7117 
7118 		if (error != CRYPTO_SUCCESS) {
7119 			goto destroy_object;
7120 		}
7121 
7122 		/* make sure key_type is set */
7123 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
7124 		attribute.oa_value = (char *)&key_type;
7125 		attribute.oa_value_len = sizeof (ulong_t);
7126 		error = dprov_object_set_attr(session, *object_id_ptr,
7127 		    &attribute, 1, B_FALSE);
7128 
7129 		if (error != CRYPTO_SUCCESS) {
7130 			goto destroy_object;
7131 		}
7132 
7133 		attribute.oa_type = DPROV_CKA_VALUE;
7134 		attribute.oa_value = kmem_alloc(key_len, KM_SLEEP);
7135 		attribute.oa_value_len = key_len;
7136 
7137 		if (random_get_pseudo_bytes((uchar_t *)attribute.oa_value,
7138 		    key_len) != 0) {
7139 			bzero(attribute.oa_value, key_len);
7140 			kmem_free(attribute.oa_value, key_len);
7141 			goto destroy_object;
7142 		}
7143 		error = dprov_object_set_attr(session, *object_id_ptr,
7144 		    &attribute, 1, B_FALSE);
7145 
7146 		bzero(attribute.oa_value, key_len);
7147 		kmem_free(attribute.oa_value, key_len);
7148 
7149 		if (error != CRYPTO_SUCCESS) {
7150 			goto destroy_object;
7151 		}
7152 		break;
7153 
7154 destroy_object:
7155 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
7156 		break;
7157 	}
7158 
7159 	case DPROV_REQ_KEY_GENERATE_PAIR: {
7160 		crypto_mechanism_t *mechp;
7161 		crypto_object_id_t *pub_object_id_ptr;
7162 		crypto_object_id_t *pri_object_id_ptr;
7163 		crypto_object_attribute_t *pub_template;
7164 		crypto_object_attribute_t *pri_template;
7165 		crypto_object_attribute_t attribute;
7166 		uint_t pub_attribute_count;
7167 		uint_t pri_attribute_count;
7168 		ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
7169 		ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
7170 
7171 		pub_template = taskq_req->dr_key_req.kr_template;
7172 		pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7173 		pub_object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7174 		pri_template = taskq_req->dr_key_req.kr_private_key_template;
7175 		pri_attribute_count =
7176 		    taskq_req->dr_key_req.kr_private_key_attribute_count;
7177 		pri_object_id_ptr =
7178 		    taskq_req->dr_key_req.kr_private_key_object_id_ptr;
7179 		mechp = taskq_req->dr_key_req.kr_mechanism;
7180 
7181 		error = CRYPTO_SUCCESS;
7182 
7183 		/* optional */
7184 		(void) dprov_get_template_attr_ulong(pub_template,
7185 		    pub_attribute_count, DPROV_CKA_CLASS, &pub_class);
7186 
7187 		/* optional */
7188 		(void) dprov_get_template_attr_ulong(pri_template,
7189 		    pri_attribute_count, DPROV_CKA_CLASS, &pri_class);
7190 
7191 		/* optional */
7192 		(void) dprov_get_template_attr_ulong(pub_template,
7193 		    pub_attribute_count, DPROV_CKA_KEY_TYPE, &pub_key_type);
7194 
7195 		/* optional */
7196 		(void) dprov_get_template_attr_ulong(pri_template,
7197 		    pri_attribute_count, DPROV_CKA_KEY_TYPE, &pri_key_type);
7198 
7199 		if (pub_class != ~0UL && pub_class != DPROV_CKO_PUBLIC_KEY) {
7200 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7201 			break;
7202 		}
7203 
7204 		if (pri_class != ~0UL && pri_class != DPROV_CKO_PRIVATE_KEY) {
7205 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7206 			break;
7207 		}
7208 
7209 		switch (mechp->cm_type) {
7210 		case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
7211 			if (pub_key_type != ~0UL &&
7212 			    pub_key_type != DPROV_CKK_RSA) {
7213 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7214 				break;
7215 			}
7216 			pub_key_type = DPROV_CKK_RSA;
7217 
7218 			if (pri_key_type != ~0UL &&
7219 			    pri_key_type != DPROV_CKK_RSA) {
7220 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7221 				break;
7222 			}
7223 			pri_key_type = DPROV_CKK_RSA;
7224 
7225 			if (pub_class != ~0UL &&
7226 			    pub_class != DPROV_CKO_PUBLIC_KEY) {
7227 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7228 				break;
7229 			}
7230 			pub_class = DPROV_CKO_PUBLIC_KEY;
7231 
7232 			if (pri_class != ~0UL &&
7233 			    pri_class != DPROV_CKO_PRIVATE_KEY) {
7234 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7235 				break;
7236 			}
7237 			pri_class = DPROV_CKO_PRIVATE_KEY;
7238 			break;
7239 
7240 		default:
7241 			error = CRYPTO_MECHANISM_INVALID;
7242 		}
7243 
7244 		if (error != CRYPTO_SUCCESS)
7245 			break;
7246 
7247 		error = dprov_create_object_from_template(softc, session,
7248 		    pub_template, pub_attribute_count, pub_object_id_ptr,
7249 		    B_FALSE, B_TRUE);
7250 
7251 		if (error != CRYPTO_SUCCESS)
7252 			break;
7253 
7254 		/* make sure class is set */
7255 		attribute.oa_type = DPROV_CKA_CLASS;
7256 		attribute.oa_value = (char *)&pub_class;
7257 		attribute.oa_value_len = sizeof (ulong_t);
7258 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7259 		    &attribute, 1, B_FALSE);
7260 
7261 		if (error != CRYPTO_SUCCESS) {
7262 			goto destroy_public_object;
7263 		}
7264 
7265 		/* make sure key_type is set */
7266 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
7267 		attribute.oa_value = (char *)&pub_key_type;
7268 		attribute.oa_value_len = sizeof (ulong_t);
7269 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7270 		    &attribute, 1, B_FALSE);
7271 
7272 		if (error != CRYPTO_SUCCESS) {
7273 			goto destroy_public_object;
7274 		}
7275 
7276 		attribute.oa_type = DPROV_CKA_MODULUS;
7277 		attribute.oa_value = (char *)modulus;
7278 		attribute.oa_value_len = sizeof (modulus);
7279 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7280 		    &attribute, 1, B_FALSE);
7281 
7282 		if (error != CRYPTO_SUCCESS) {
7283 			goto destroy_public_object;
7284 		}
7285 
7286 		attribute.oa_type = DPROV_CKA_PUBLIC_EXPONENT;
7287 		attribute.oa_value = public_exponent;
7288 		attribute.oa_value_len = sizeof (public_exponent);
7289 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7290 		    &attribute, 1, B_FALSE);
7291 
7292 		if (error != CRYPTO_SUCCESS) {
7293 			goto destroy_public_object;
7294 		}
7295 
7296 		error = dprov_create_object_from_template(softc, session,
7297 		    pri_template, pri_attribute_count, pri_object_id_ptr,
7298 		    B_FALSE, B_TRUE);
7299 
7300 		if (error != CRYPTO_SUCCESS)
7301 			break;
7302 
7303 		/* make sure class is set */
7304 		attribute.oa_type = DPROV_CKA_CLASS;
7305 		attribute.oa_value = (char *)&pri_class;
7306 		attribute.oa_value_len = sizeof (ulong_t);
7307 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7308 		    &attribute, 1, B_FALSE);
7309 
7310 		if (error != CRYPTO_SUCCESS) {
7311 			goto destroy_private_object;
7312 		}
7313 
7314 		/* make sure key_type is set */
7315 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
7316 		attribute.oa_value = (char *)&pri_key_type;
7317 		attribute.oa_value_len = sizeof (ulong_t);
7318 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7319 		    &attribute, 1, B_FALSE);
7320 
7321 		if (error != CRYPTO_SUCCESS) {
7322 			goto destroy_private_object;
7323 		}
7324 
7325 		attribute.oa_type = DPROV_CKA_MODULUS;
7326 		attribute.oa_value = (char *)modulus;
7327 		attribute.oa_value_len = sizeof (modulus);
7328 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7329 		    &attribute, 1, B_FALSE);
7330 
7331 		if (error != CRYPTO_SUCCESS) {
7332 			goto destroy_private_object;
7333 		}
7334 
7335 		attribute.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
7336 		attribute.oa_value = (char *)private_exponent;
7337 		attribute.oa_value_len = sizeof (private_exponent);
7338 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7339 		    &attribute, 1, B_FALSE);
7340 
7341 		if (error != CRYPTO_SUCCESS) {
7342 			goto destroy_private_object;
7343 		}
7344 		break;
7345 
7346 destroy_private_object:
7347 		(void) dprov_destroy_object(softc, session,
7348 		    *pri_object_id_ptr);
7349 destroy_public_object:
7350 		(void) dprov_destroy_object(softc, session,
7351 		    *pub_object_id_ptr);
7352 
7353 		break;
7354 	}
7355 
7356 	case DPROV_REQ_KEY_WRAP: {
7357 		crypto_mechanism_t mech, *mechp;
7358 		crypto_key_t key, *keyp;
7359 		crypto_object_id_t object_id;
7360 		ulong_t class = DPROV_CKO_DATA;
7361 		boolean_t extractable = B_TRUE;
7362 		dprov_object_t *object;
7363 		int object_idx;
7364 		char *plaintext_key;
7365 		size_t plaintext_key_len;
7366 		crypto_data_t plaintext;
7367 		crypto_data_t ciphertext;
7368 		size_t *lenp;
7369 
7370 		mechp = taskq_req->dr_key_req.kr_mechanism;
7371 		/* structure assignment */
7372 		mech = *mechp;
7373 
7374 		/* get wrapping key value */
7375 		if (is_publickey_mech(mech.cm_type)) {
7376 			if ((error = dprov_key_attr_asymmetric(softc,
7377 			    session_id, taskq_req->dr_type,
7378 			    taskq_req->dr_key_req.kr_key,
7379 			    &key)) != CRYPTO_SUCCESS)
7380 				break;
7381 			keyp = &key;
7382 		} else {
7383 			if ((error = dprov_key_value_secret(softc,
7384 			    session_id, taskq_req->dr_type,
7385 			    taskq_req->dr_key_req.kr_key,
7386 			    &key)) != CRYPTO_SUCCESS)
7387 				break;
7388 			keyp = &key;
7389 		}
7390 
7391 		/* get the software provider for this mechanism */
7392 		if ((error = dprov_get_sw_prov(mechp, &pd,
7393 		    &mech.cm_type)) != CRYPTO_SUCCESS)
7394 			break;
7395 
7396 		object_id = *taskq_req->dr_key_req.kr_object_id_ptr;
7397 		if (object_id >= DPROV_MAX_OBJECTS) {
7398 			error = CRYPTO_KEY_HANDLE_INVALID;
7399 			break;
7400 		}
7401 
7402 		/* get ptr to object */
7403 		if ((object = session->ds_objects[object_id]) == NULL) {
7404 			error = CRYPTO_OBJECT_HANDLE_INVALID;
7405 			break;
7406 		}
7407 
7408 		(void) dprov_get_object_attr_boolean(object,
7409 		    DPROV_CKA_EXTRACTABLE, &extractable);
7410 
7411 		if (!extractable) {
7412 			error = CRYPTO_ATTRIBUTE_SENSITIVE;
7413 			break;
7414 		}
7415 
7416 		(void) dprov_get_object_attr_ulong(object,
7417 		    DPROV_CKA_CLASS, &class);
7418 
7419 		switch (class) {
7420 		case DPROV_CKO_SECRET_KEY:
7421 			object_idx = dprov_find_attr(object->do_attr,
7422 			    DPROV_MAX_ATTR, DPROV_CKA_VALUE);
7423 			if (object_idx == -1) {
7424 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7425 				break;
7426 			}
7427 			break;
7428 
7429 			case DPROV_CKO_PRIVATE_KEY:
7430 			/*
7431 			 * PKCS#11 says that ASN.1 should be used to encode
7432 			 * specific attributes before encrypting the blob.
7433 			 * We only encrypt the private exponent for the
7434 			 * purpose of testing.
7435 			 */
7436 			object_idx = dprov_find_attr(object->do_attr,
7437 			    DPROV_MAX_ATTR, DPROV_CKA_PRIVATE_EXPONENT);
7438 			if (object_idx == -1) {
7439 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7440 				break;
7441 			}
7442 			break;
7443 		default:
7444 			error = CRYPTO_KEY_NOT_WRAPPABLE;
7445 			break;
7446 		}
7447 		if (error != CRYPTO_SUCCESS)
7448 			break;
7449 
7450 		plaintext_key = object->do_attr[object_idx].oa_value;
7451 		plaintext_key_len = object->do_attr[object_idx].oa_value_len;
7452 		lenp = taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7453 
7454 		/* session id is 0 for software provider */
7455 		plaintext.cd_format = CRYPTO_DATA_RAW;
7456 		plaintext.cd_offset = 0;
7457 		plaintext.cd_length = plaintext_key_len;
7458 		plaintext.cd_raw.iov_base = plaintext_key;
7459 		plaintext.cd_raw.iov_len = plaintext_key_len;
7460 		plaintext.cd_miscdata = NULL;
7461 
7462 		ciphertext.cd_format = CRYPTO_DATA_RAW;
7463 		ciphertext.cd_offset = 0;
7464 		ciphertext.cd_length = *lenp;
7465 		ciphertext.cd_raw.iov_base =
7466 		    (char *)taskq_req->dr_key_req.kr_wrapped_key;
7467 		ciphertext.cd_raw.iov_len = ciphertext.cd_length;
7468 		ciphertext.cd_miscdata = NULL;
7469 
7470 		error = crypto_encrypt_prov(pd, 0, &mech, &plaintext, keyp,
7471 		    NULL, &ciphertext, NULL);
7472 
7473 		KCF_PROV_REFRELE(pd);
7474 		if (error == CRYPTO_SUCCESS ||
7475 		    error == CRYPTO_BUFFER_TOO_SMALL) {
7476 			*lenp = ciphertext.cd_length;
7477 		}
7478 		break;
7479 	}
7480 
7481 	case DPROV_REQ_KEY_UNWRAP: {
7482 		crypto_mechanism_t mech, *mechp;
7483 		crypto_key_t key, *keyp;
7484 		crypto_object_id_t *object_id_ptr;
7485 		ulong_t class = DPROV_CKO_DATA;
7486 		uchar_t *wrapped_key;
7487 		char *plaintext_buf;
7488 		size_t wrapped_key_len;
7489 		crypto_data_t plaintext;
7490 		crypto_data_t ciphertext;
7491 		crypto_object_attribute_t unwrapped_key;
7492 		crypto_object_attribute_t *template;
7493 		uint_t attribute_count;
7494 
7495 		template = taskq_req->dr_key_req.kr_template;
7496 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7497 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7498 
7499 		/* all objects must have an object class attribute */
7500 		if (dprov_get_template_attr_ulong(template, attribute_count,
7501 		    DPROV_CKA_CLASS, &class) != CRYPTO_SUCCESS) {
7502 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7503 			break;
7504 		}
7505 
7506 		mechp = taskq_req->dr_key_req.kr_mechanism;
7507 		/* structure assignment */
7508 		mech = *mechp;
7509 
7510 		/* get unwrapping key value */
7511 		if (is_publickey_mech(mech.cm_type)) {
7512 			if ((error = dprov_key_attr_asymmetric(softc,
7513 			    session_id, taskq_req->dr_type,
7514 			    taskq_req->dr_key_req.kr_key,
7515 			    &key)) != CRYPTO_SUCCESS)
7516 				break;
7517 			keyp = &key;
7518 		} else {
7519 			if ((error = dprov_key_value_secret(softc,
7520 			    session_id, taskq_req->dr_type,
7521 			    taskq_req->dr_key_req.kr_key,
7522 			    &key)) != CRYPTO_SUCCESS)
7523 				break;
7524 			keyp = &key;
7525 		}
7526 
7527 		/* get the software provider for this mechanism */
7528 		if ((error = dprov_get_sw_prov(mechp, &pd,
7529 		    &mech.cm_type)) != CRYPTO_SUCCESS)
7530 			break;
7531 
7532 		wrapped_key = taskq_req->dr_key_req.kr_wrapped_key;
7533 		wrapped_key_len = *taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7534 		ciphertext.cd_format = CRYPTO_DATA_RAW;
7535 		ciphertext.cd_offset = 0;
7536 		ciphertext.cd_length = wrapped_key_len;
7537 		ciphertext.cd_raw.iov_base = (char *)wrapped_key;
7538 		ciphertext.cd_raw.iov_len = wrapped_key_len;
7539 		ciphertext.cd_miscdata = NULL;
7540 
7541 		/*
7542 		 * Plaintext length is less than or equal to
7543 		 * the length of the ciphertext.
7544 		 */
7545 		plaintext_buf = kmem_alloc(wrapped_key_len, KM_SLEEP);
7546 		plaintext.cd_format = CRYPTO_DATA_RAW;
7547 		plaintext.cd_offset = 0;
7548 		plaintext.cd_length = wrapped_key_len;
7549 		plaintext.cd_raw.iov_base = plaintext_buf;
7550 		plaintext.cd_raw.iov_len = wrapped_key_len;
7551 		plaintext.cd_miscdata = NULL;
7552 
7553 		error = crypto_decrypt_prov(pd, 0, &mech, &ciphertext, keyp,
7554 		    NULL, &plaintext, NULL);
7555 
7556 		KCF_PROV_REFRELE(pd);
7557 
7558 		if (error != CRYPTO_SUCCESS)
7559 			goto free_unwrapped_key;
7560 
7561 		error = dprov_create_object_from_template(softc, session,
7562 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7563 
7564 		if (error != CRYPTO_SUCCESS)
7565 			goto free_unwrapped_key;
7566 
7567 		switch (class) {
7568 		case DPROV_CKO_SECRET_KEY:
7569 			unwrapped_key.oa_type = DPROV_CKA_VALUE;
7570 			unwrapped_key.oa_value_len = plaintext.cd_length;
7571 			unwrapped_key.oa_value = plaintext_buf;
7572 			break;
7573 		case DPROV_CKO_PRIVATE_KEY:
7574 			/*
7575 			 * PKCS#11 says that ASN.1 should be used to encode
7576 			 * specific attributes before encrypting the blob.
7577 			 * We only encrypt the private exponent for the
7578 			 * purpose of testing.
7579 			 */
7580 			unwrapped_key.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
7581 			unwrapped_key.oa_value_len = plaintext.cd_length;
7582 			unwrapped_key.oa_value = plaintext_buf;
7583 			break;
7584 		default:
7585 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7586 			goto free_unwrapped_key;
7587 		}
7588 
7589 		if ((error = dprov_object_set_attr(session, *object_id_ptr,
7590 		    &unwrapped_key, 1, B_FALSE)) == CRYPTO_SUCCESS)
7591 			break;	/* don't free the unwrapped key */
7592 
7593 		/* failure */
7594 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
7595 		break;
7596 
7597 free_unwrapped_key:
7598 		bzero(plaintext_buf, wrapped_key_len);
7599 		kmem_free(plaintext_buf, wrapped_key_len);
7600 		break;
7601 	}
7602 
7603 	case DPROV_REQ_KEY_DERIVE: {
7604 		crypto_mechanism_t digest_mech, *mechp;
7605 		crypto_key_t key, *base_keyp;
7606 		crypto_object_id_t *object_id_ptr;
7607 		crypto_data_t data;
7608 		crypto_data_t digest;
7609 		size_t hash_size;
7610 		char *digest_buf;
7611 		crypto_object_attribute_t derived_key;
7612 		crypto_object_attribute_t *template;
7613 		uint_t attribute_count;
7614 		ulong_t key_type;
7615 		void *value;
7616 		size_t value_len = 0;
7617 
7618 		error = CRYPTO_SUCCESS;
7619 
7620 		template = taskq_req->dr_key_req.kr_template;
7621 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7622 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7623 
7624 		/* required */
7625 		if (dprov_get_template_attr_ulong(template, attribute_count,
7626 		    DPROV_CKA_KEY_TYPE, &key_type) != CRYPTO_SUCCESS) {
7627 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7628 			break;
7629 		}
7630 
7631 		mechp = taskq_req->dr_key_req.kr_mechanism;
7632 		/* structure assignment */
7633 		digest_mech = *mechp;
7634 
7635 		switch (digest_mech.cm_type) {
7636 		case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:
7637 			hash_size = SHA1_DIGEST_LEN;
7638 			digest_mech.cm_type = SHA1_MECH_INFO_TYPE;
7639 			break;
7640 
7641 		case SHA256_KEY_DERIVATION_MECH_INFO_TYPE:
7642 			hash_size = SHA256_DIGEST_LENGTH;
7643 			digest_mech.cm_type = SHA256_MECH_INFO_TYPE;
7644 			break;
7645 
7646 		case SHA384_KEY_DERIVATION_MECH_INFO_TYPE:
7647 			hash_size = SHA384_DIGEST_LENGTH;
7648 			digest_mech.cm_type = SHA384_MECH_INFO_TYPE;
7649 			break;
7650 
7651 		case SHA512_KEY_DERIVATION_MECH_INFO_TYPE:
7652 			hash_size = SHA512_DIGEST_LENGTH;
7653 			digest_mech.cm_type = SHA512_MECH_INFO_TYPE;
7654 			break;
7655 
7656 		case MD5_KEY_DERIVATION_MECH_INFO_TYPE:
7657 			hash_size = MD5_DIGEST_LEN;
7658 			digest_mech.cm_type = MD5_MECH_INFO_TYPE;
7659 			break;
7660 
7661 		default:
7662 			error = CRYPTO_MECHANISM_INVALID;
7663 		}
7664 
7665 		if (error != CRYPTO_SUCCESS)
7666 			break;
7667 
7668 		/* CKA_VALUE is optional */
7669 		(void) dprov_get_template_attr_array(template, attribute_count,
7670 		    DPROV_CKA_VALUE, &value, &value_len);
7671 
7672 		/* check for inconsistent value length */
7673 		switch (key_type) {
7674 		case DPROV_CKK_GENERIC_SECRET:
7675 			if (value_len > 0) {
7676 				if (value_len > hash_size)
7677 					error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7678 			} else {
7679 				value_len = hash_size;
7680 			}
7681 			break;
7682 
7683 		case DPROV_CKK_RC4:
7684 		case DPROV_CKK_AES:
7685 			if (value_len == 0 ||
7686 			    value_len > hash_size) {
7687 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7688 			}
7689 			break;
7690 
7691 		case DPROV_CKK_DES:
7692 			if (value_len > 0 &&
7693 			    value_len != DES_KEY_LEN) {
7694 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7695 			}
7696 			value_len = DES_KEY_LEN;
7697 			break;
7698 
7699 		case DPROV_CKK_DES3:
7700 			if (value_len > 0 &&
7701 			    value_len != DES3_KEY_LEN) {
7702 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7703 			}
7704 			value_len = DES3_KEY_LEN;
7705 			break;
7706 
7707 		default:
7708 			error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7709 			break;
7710 		}
7711 
7712 		if (error != CRYPTO_SUCCESS)
7713 			break;
7714 
7715 		/* get the software provider for this mechanism */
7716 		if ((error = dprov_get_sw_prov(&digest_mech, &pd,
7717 		    &digest_mech.cm_type)) != CRYPTO_SUCCESS)
7718 			break;
7719 
7720 		/* get the base key */
7721 		error = dprov_key_value_secret(softc, session_id,
7722 		    taskq_req->dr_type, taskq_req->dr_key_req.kr_key, &key);
7723 		if (error != CRYPTO_SUCCESS)
7724 			break;
7725 
7726 		base_keyp = &key;
7727 
7728 		data.cd_format = CRYPTO_DATA_RAW;
7729 		data.cd_offset = 0;
7730 		data.cd_length = CRYPTO_BITS2BYTES(base_keyp->ck_length);
7731 		data.cd_raw.iov_base = base_keyp->ck_data;
7732 		data.cd_raw.iov_len = data.cd_length;
7733 
7734 		digest_buf = kmem_alloc(hash_size, KM_SLEEP);
7735 		digest.cd_format = CRYPTO_DATA_RAW;
7736 		digest.cd_offset = 0;
7737 		digest.cd_length = hash_size;
7738 		digest.cd_raw.iov_base = digest_buf;
7739 		digest.cd_raw.iov_len = hash_size;
7740 
7741 		error = crypto_digest_prov(pd, 0, &digest_mech, &data,
7742 		    &digest, NULL);
7743 
7744 		KCF_PROV_REFRELE(pd);
7745 
7746 		if (error != CRYPTO_SUCCESS)
7747 			goto free_derived_key;
7748 
7749 		error = dprov_create_object_from_template(softc, session,
7750 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7751 
7752 		if (error != CRYPTO_SUCCESS)
7753 			goto free_derived_key;
7754 
7755 		derived_key.oa_type = DPROV_CKA_VALUE;
7756 		derived_key.oa_value = digest_buf;
7757 		derived_key.oa_value_len = value_len;
7758 
7759 		error = dprov_object_set_attr(session, *object_id_ptr,
7760 		    &derived_key, 1, B_FALSE);
7761 
7762 		if (error != CRYPTO_SUCCESS) {
7763 			(void) dprov_destroy_object(softc, session,
7764 			    *object_id_ptr);
7765 		}
7766 
7767 free_derived_key:
7768 		bzero(digest_buf, hash_size);
7769 		kmem_free(digest_buf, hash_size);
7770 		break;
7771 	}
7772 
7773 	case DPROV_REQ_NOSTORE_KEY_GENERATE: {
7774 		crypto_object_attribute_t *out_template;
7775 		uint_t out_attribute_count;
7776 		void *value;
7777 		size_t value_len = 0;
7778 
7779 		out_template = taskq_req->dr_key_req.kr_out_template1;
7780 		out_attribute_count =
7781 		    taskq_req->dr_key_req.kr_out_attribute_count1;
7782 
7783 		error = dprov_get_template_attr_array(out_template,
7784 		    out_attribute_count, DPROV_CKA_VALUE, &value, &value_len);
7785 		if (error != CRYPTO_SUCCESS)
7786 			break;
7787 
7788 		/* fill the entire array with pattern */
7789 		{
7790 			int i = 0;
7791 			char *p = value;
7792 			while (i < value_len) {
7793 				p[i++] = 'A';
7794 				if (i >= value_len)
7795 					break;
7796 				p[i++] = 'B';
7797 				if (i >= value_len)
7798 					break;
7799 				p[i++] = 'C';
7800 			}
7801 		}
7802 
7803 		error = CRYPTO_SUCCESS;
7804 		break;
7805 	}
7806 
7807 	case DPROV_REQ_NOSTORE_KEY_GENERATE_PAIR: {
7808 		crypto_mechanism_t *mechp;
7809 		crypto_object_attribute_t *pub_template;
7810 		uint_t pub_attribute_count;
7811 		crypto_object_attribute_t *out_pub_template;
7812 		crypto_object_attribute_t *out_pri_template;
7813 		uint_t out_pub_attribute_count;
7814 		uint_t out_pri_attribute_count;
7815 
7816 		mechp = taskq_req->dr_key_req.kr_mechanism;
7817 		pub_template = taskq_req->dr_key_req.kr_template;
7818 		pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7819 		out_pub_template = taskq_req->dr_key_req.kr_out_template1;
7820 		out_pub_attribute_count =
7821 		    taskq_req->dr_key_req.kr_out_attribute_count1;
7822 		out_pri_template = taskq_req->dr_key_req.kr_out_template2;
7823 		out_pri_attribute_count =
7824 		    taskq_req->dr_key_req.kr_out_attribute_count2;
7825 
7826 		switch (mechp->cm_type) {
7827 		case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
7828 			error = nostore_copy_attribute(out_pub_template,
7829 			    out_pub_attribute_count, DPROV_CKA_MODULUS);
7830 			if (error != CRYPTO_SUCCESS)
7831 				break;
7832 
7833 			error = nostore_copy_attribute(out_pub_template,
7834 			    out_pub_attribute_count, DPROV_CKA_PUBLIC_EXPONENT);
7835 			if (error == CRYPTO_ARGUMENTS_BAD) {
7836 				size_t tmp_len = 0;
7837 				void *tmp;
7838 
7839 				/* public exponent must be here */
7840 				error = dprov_get_template_attr_array(
7841 				    pub_template, pub_attribute_count,
7842 				    DPROV_CKA_PUBLIC_EXPONENT, &tmp, &tmp_len);
7843 				if (error != CRYPTO_SUCCESS)
7844 					break;
7845 			}
7846 			error = nostore_copy_attribute(out_pri_template,
7847 			    out_pri_attribute_count, DPROV_CKA_MODULUS);
7848 			if (error != CRYPTO_SUCCESS)
7849 				break;
7850 
7851 			error = nostore_copy_attribute(out_pri_template,
7852 			    out_pri_attribute_count,
7853 			    DPROV_CKA_PRIVATE_EXPONENT);
7854 			break;
7855 
7856 		case DH_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
7857 			/*
7858 			 * There is no software provider for DH mechanism;
7859 			 * Just return pre-defined values.
7860 			 */
7861 			error = nostore_copy_attribute(out_pub_template,
7862 			    out_pub_attribute_count, DPROV_CKA_VALUE);
7863 			error = nostore_copy_attribute(out_pri_template,
7864 			    out_pri_attribute_count, DPROV_CKA_VALUE);
7865 			break;
7866 
7867 		default:
7868 			error = CRYPTO_MECHANISM_INVALID;
7869 		}
7870 		break;
7871 	}
7872 
7873 	case DPROV_REQ_NOSTORE_KEY_DERIVE: {
7874 		crypto_mechanism_t *mechp;
7875 		crypto_object_attribute_t *in_template, *out_template;
7876 		crypto_key_t *base_key;
7877 		uint_t in_attribute_count, out_attribute_count;
7878 		ulong_t key_type;
7879 		void *value;
7880 		size_t value_len = 0;
7881 		size_t value_len_value = 0;
7882 
7883 		in_template = taskq_req->dr_key_req.kr_template;
7884 		out_template = taskq_req->dr_key_req.kr_out_template1;
7885 		in_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7886 		out_attribute_count =
7887 		    taskq_req->dr_key_req.kr_out_attribute_count1;
7888 		mechp = taskq_req->dr_key_req.kr_mechanism;
7889 		base_key = taskq_req->dr_key_req.kr_key;
7890 
7891 		/*
7892 		 * CKA_VALUE must be present so the derived key can
7893 		 * be returned by value.
7894 		 */
7895 		if (dprov_get_template_attr_array(out_template,
7896 		    out_attribute_count, DPROV_CKA_VALUE, &value,
7897 		    &value_len) != CRYPTO_SUCCESS) {
7898 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7899 			break;
7900 		}
7901 
7902 		if (dprov_get_template_attr_ulong(in_template,
7903 		    in_attribute_count, DPROV_CKA_KEY_TYPE,
7904 		    &key_type) != CRYPTO_SUCCESS) {
7905 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7906 			break;
7907 		}
7908 		switch (mechp->cm_type) {
7909 		case DH_PKCS_DERIVE_MECH_INFO_TYPE: {
7910 			size_t tmp_len = 0;
7911 			void *tmp;
7912 
7913 			if (base_key->ck_format != CRYPTO_KEY_ATTR_LIST) {
7914 				error = CRYPTO_ARGUMENTS_BAD;
7915 				break;
7916 			}
7917 
7918 			if ((dprov_get_template_attr_array(base_key->ck_attrs,
7919 			    base_key->ck_count, DPROV_CKA_BASE, &tmp,
7920 			    &tmp_len) != CRYPTO_SUCCESS) ||
7921 			    (dprov_get_template_attr_array(base_key->ck_attrs,
7922 			    base_key->ck_count, DPROV_CKA_PRIME, &tmp,
7923 			    &tmp_len) != CRYPTO_SUCCESS) ||
7924 			    (dprov_get_template_attr_array(base_key->ck_attrs,
7925 			    base_key->ck_count, DPROV_CKA_VALUE, &tmp,
7926 			    &tmp_len) != CRYPTO_SUCCESS)) {
7927 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7928 				break;
7929 			}
7930 
7931 			/*
7932 			 * CKA_VALUE is added to the derived key template by
7933 			 * the library.
7934 			 */
7935 			error = CRYPTO_SUCCESS;
7936 			switch (key_type) {
7937 			case DPROV_CKK_AES:
7938 				if (dprov_get_template_attr_ulong(in_template,
7939 				    in_attribute_count, DPROV_CKA_VALUE_LEN,
7940 				    &value_len_value) != CRYPTO_SUCCESS) {
7941 					error = CRYPTO_TEMPLATE_INCOMPLETE;
7942 					break;
7943 				}
7944 				if (value_len != value_len_value) {
7945 					error = CRYPTO_TEMPLATE_INCONSISTENT;
7946 					break;
7947 				}
7948 			default:
7949 				error = CRYPTO_MECHANISM_INVALID;
7950 			}
7951 			if (error == CRYPTO_SUCCESS)
7952 				fill_dh(value, value_len);
7953 			break;
7954 		}
7955 		default:
7956 			error = CRYPTO_MECHANISM_INVALID;
7957 		}
7958 		break;
7959 	default:
7960 		error = CRYPTO_MECHANISM_INVALID;
7961 	}
7962 	} /* end case */
7963 
7964 	mutex_exit(&softc->ds_lock);
7965 	dprov_op_done(taskq_req, error);
7966 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: end\n", instance));
7967 }
7968 
7969 /*
7970  * taskq dispatcher function for provider management operations.
7971  */
7972 static void
7973 dprov_mgmt_task(dprov_req_t *taskq_req)
7974 {
7975 	dprov_state_t *softc;
7976 	/* LINTED E_FUNC_SET_NOT_USED */
7977 	int instance;
7978 	int error = CRYPTO_NOT_SUPPORTED;
7979 
7980 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
7981 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: started\n", instance));
7982 
7983 	mutex_enter(&softc->ds_lock);
7984 
7985 	switch (taskq_req->dr_type) {
7986 	case DPROV_REQ_MGMT_EXTINFO: {
7987 		crypto_provider_ext_info_t *ext_info =
7988 		    taskq_req->dr_mgmt_req.mr_ext_info;
7989 
7990 		(void) memset(ext_info->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
7991 		if (!softc->ds_token_initialized) {
7992 			bcopy("(not initialized)", ext_info->ei_label,
7993 			    strlen("(not initialized)"));
7994 		} else {
7995 			bcopy(softc->ds_label, ext_info->ei_label,
7996 			    CRYPTO_EXT_SIZE_LABEL);
7997 		}
7998 
7999 		bcopy(DPROV_MANUFACTURER, ext_info->ei_manufacturerID,
8000 		    CRYPTO_EXT_SIZE_MANUF);
8001 		bcopy(DPROV_MODEL, ext_info->ei_model, CRYPTO_EXT_SIZE_MODEL);
8002 
8003 		(void) snprintf((char *)ext_info->ei_serial_number, 16, "%d%s",
8004 		    instance, DPROV_ALLSPACES);
8005 		/* PKCS#11 blank padding */
8006 		ext_info->ei_serial_number[15] = ' ';
8007 		ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
8008 		ext_info->ei_max_pin_len = (ulong_t)DPROV_MAX_PIN_LEN;
8009 		ext_info->ei_min_pin_len = 1;
8010 		ext_info->ei_total_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
8011 		ext_info->ei_free_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
8012 		ext_info->ei_total_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
8013 		ext_info->ei_free_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
8014 		ext_info->ei_hardware_version.cv_major = 1;
8015 		ext_info->ei_hardware_version.cv_minor = 0;
8016 		ext_info->ei_firmware_version.cv_major = 1;
8017 		ext_info->ei_firmware_version.cv_minor = 0;
8018 
8019 		ext_info->ei_flags = CRYPTO_EXTF_RNG |
8020 		    CRYPTO_EXTF_LOGIN_REQUIRED |
8021 		    CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
8022 		if (softc->ds_user_pin_set)
8023 			ext_info->ei_flags |= CRYPTO_EXTF_USER_PIN_INITIALIZED;
8024 		if (softc->ds_token_initialized)
8025 			ext_info->ei_flags |= CRYPTO_EXTF_TOKEN_INITIALIZED;
8026 
8027 		error = CRYPTO_SUCCESS;
8028 		break;
8029 	}
8030 	case DPROV_REQ_MGMT_INITTOKEN: {
8031 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
8032 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8033 		char *label = taskq_req->dr_mgmt_req.mr_label;
8034 
8035 		/* cannot initialize token when a session is open */
8036 		if (softc->ds_sessions_count > 0) {
8037 			error = CRYPTO_SESSION_EXISTS;
8038 			break;
8039 		}
8040 
8041 		/* check PIN length */
8042 		if (pin_len > DPROV_MAX_PIN_LEN) {
8043 			error = CRYPTO_PIN_LEN_RANGE;
8044 			break;
8045 		}
8046 
8047 		/* check PIN */
8048 		if (pin == NULL) {
8049 			error = CRYPTO_PIN_INVALID;
8050 			break;
8051 		}
8052 
8053 		/*
8054 		 * If the token has already been initialized, need
8055 		 * to validate supplied PIN.
8056 		 */
8057 		if (softc->ds_token_initialized &&
8058 		    (softc->ds_so_pin_len != pin_len ||
8059 		    strncmp(softc->ds_so_pin, pin, pin_len) != 0)) {
8060 			/* invalid SO PIN */
8061 			error = CRYPTO_PIN_INCORRECT;
8062 			break;
8063 		}
8064 
8065 		/* set label */
8066 		bcopy(label, softc->ds_label, CRYPTO_EXT_SIZE_LABEL);
8067 
8068 		/* set new SO PIN, update state */
8069 		bcopy(pin, softc->ds_so_pin, pin_len);
8070 		softc->ds_so_pin_len = pin_len;
8071 		softc->ds_token_initialized = B_TRUE;
8072 		softc->ds_user_pin_set = B_FALSE;
8073 
8074 		error = CRYPTO_SUCCESS;
8075 		break;
8076 	}
8077 	case DPROV_REQ_MGMT_INITPIN: {
8078 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
8079 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8080 		crypto_session_id_t session_id =
8081 		    taskq_req->dr_mgmt_req.mr_session_id;
8082 
8083 		/* check session id */
8084 		if (softc->ds_sessions[session_id] == NULL) {
8085 			error = CRYPTO_SESSION_HANDLE_INVALID;
8086 			break;
8087 		}
8088 
8089 		/* fail if not logged in as SO */
8090 		if (softc->ds_sessions[session_id]->ds_state !=
8091 		    DPROV_SESSION_STATE_SO) {
8092 			error = CRYPTO_USER_NOT_LOGGED_IN;
8093 			break;
8094 		}
8095 
8096 		/* check PIN length */
8097 		if (pin_len > DPROV_MAX_PIN_LEN) {
8098 			error = CRYPTO_PIN_LEN_RANGE;
8099 			break;
8100 		}
8101 
8102 		/* check PIN */
8103 		if (pin == NULL) {
8104 			error = CRYPTO_PIN_INVALID;
8105 			break;
8106 		}
8107 
8108 		/* set new normal user PIN */
8109 		bcopy(pin, softc->ds_user_pin, pin_len);
8110 		softc->ds_user_pin_len = pin_len;
8111 		softc->ds_user_pin_set = B_TRUE;
8112 
8113 		error = CRYPTO_SUCCESS;
8114 		break;
8115 	}
8116 	case DPROV_REQ_MGMT_SETPIN: {
8117 		char *new_pin = taskq_req->dr_mgmt_req.mr_pin;
8118 		size_t new_pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8119 		char *old_pin = taskq_req->dr_mgmt_req.mr_old_pin;
8120 		size_t old_pin_len = taskq_req->dr_mgmt_req.mr_old_pin_len;
8121 		crypto_session_id_t session_id =
8122 		    taskq_req->dr_mgmt_req.mr_session_id;
8123 
8124 		/* check session id */
8125 		if (softc->ds_sessions[session_id] == NULL) {
8126 			error = CRYPTO_SESSION_HANDLE_INVALID;
8127 			break;
8128 		}
8129 
8130 		/* check PIN length */
8131 		if (old_pin_len > DPROV_MAX_PIN_LEN ||
8132 		    new_pin_len > DPROV_MAX_PIN_LEN) {
8133 			error = CRYPTO_PIN_LEN_RANGE;
8134 			break;
8135 		}
8136 
8137 		/* check PIN */
8138 		if (old_pin == NULL || new_pin == NULL) {
8139 			error = CRYPTO_PIN_INVALID;
8140 			break;
8141 		}
8142 
8143 		/* check user PIN state */
8144 		if (!softc->ds_user_pin_set) {
8145 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
8146 			break;
8147 		}
8148 
8149 		/*
8150 		 * If the token has already been initialized, need
8151 		 * to validate supplied PIN.
8152 		 */
8153 		if (softc->ds_user_pin_len != old_pin_len ||
8154 		    strncmp(softc->ds_user_pin, old_pin, old_pin_len) != 0) {
8155 			/* invalid SO PIN */
8156 			error = CRYPTO_PIN_INCORRECT;
8157 			break;
8158 		}
8159 
8160 		/* set new PIN */
8161 		bcopy(new_pin, softc->ds_user_pin, new_pin_len);
8162 		softc->ds_user_pin_len = new_pin_len;
8163 
8164 		error = CRYPTO_SUCCESS;
8165 		break;
8166 	}
8167 	}
8168 
8169 	mutex_exit(&softc->ds_lock);
8170 	dprov_op_done(taskq_req, error);
8171 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: end\n", instance));
8172 }
8173 
8174 /*
8175  * Returns in the location pointed to by pd a pointer to the descriptor
8176  * for the software provider for the specified mechanism.
8177  * The provider descriptor is returned held. Returns one of the CRYPTO_
8178  * error codes on failure, CRYPTO_SUCCESS on success.
8179  */
8180 static int
8181 dprov_get_sw_prov(crypto_mechanism_t *mech, kcf_provider_desc_t **pd,
8182     crypto_mech_type_t *provider_mech_type)
8183 {
8184 	crypto_mech_type_t kcf_mech_type = CRYPTO_MECH_INVALID;
8185 	int i, rv;
8186 
8187 	/* lookup the KCF mech type associated with our mech type */
8188 	for (i = 0; i < sizeof (dprov_mech_info_tab)/
8189 	    sizeof (crypto_mech_info_t); i++) {
8190 		if (mech->cm_type == dprov_mech_info_tab[i].cm_mech_number) {
8191 			kcf_mech_type = crypto_mech2id_common(
8192 			    dprov_mech_info_tab[i].cm_mech_name, B_TRUE);
8193 		}
8194 	}
8195 
8196 	rv = kcf_get_sw_prov(kcf_mech_type, pd, NULL, B_TRUE);
8197 	if (rv == CRYPTO_SUCCESS)
8198 		*provider_mech_type = kcf_mech_type;
8199 
8200 	return (rv);
8201 }
8202 
8203 /*
8204  * Object management helper functions.
8205  */
8206 
8207 /*
8208  * Given a crypto_key_t, return whether the key can be used or not
8209  * for the specified request. The attributes used here are defined
8210  * in table 42 of the PKCS#11 spec (Common secret key attributes).
8211  */
8212 static int
8213 dprov_key_can_use(dprov_object_t *object, dprov_req_type_t req_type)
8214 {
8215 	boolean_t ret = 0;
8216 	int rv = CRYPTO_SUCCESS;
8217 
8218 	/* check if object is allowed for specified operation */
8219 	switch (req_type) {
8220 	case DPROV_REQ_ENCRYPT_INIT:
8221 	case DPROV_REQ_ENCRYPT_ATOMIC:
8222 		rv = dprov_get_object_attr_boolean(object,
8223 		    DPROV_CKA_ENCRYPT, &ret);
8224 		break;
8225 	case DPROV_REQ_DECRYPT_INIT:
8226 	case DPROV_REQ_DECRYPT_ATOMIC:
8227 		rv = dprov_get_object_attr_boolean(object,
8228 		    DPROV_CKA_DECRYPT, &ret);
8229 		break;
8230 	case DPROV_REQ_SIGN_INIT:
8231 	case DPROV_REQ_SIGN_ATOMIC:
8232 	case DPROV_REQ_MAC_INIT:
8233 	case DPROV_REQ_MAC_ATOMIC:
8234 	case DPROV_REQ_MAC_VERIFY_ATOMIC:
8235 		rv = dprov_get_object_attr_boolean(object,
8236 		    DPROV_CKA_SIGN, &ret);
8237 		break;
8238 	case DPROV_REQ_SIGN_RECOVER_INIT:
8239 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
8240 		rv = dprov_get_object_attr_boolean(object,
8241 		    DPROV_CKA_SIGN_RECOVER, &ret);
8242 		break;
8243 	case DPROV_REQ_VERIFY_INIT:
8244 	case DPROV_REQ_VERIFY_ATOMIC:
8245 		rv = dprov_get_object_attr_boolean(object,
8246 		    DPROV_CKA_VERIFY, &ret);
8247 		break;
8248 	case DPROV_REQ_VERIFY_RECOVER_INIT:
8249 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
8250 		rv = dprov_get_object_attr_boolean(object,
8251 		    DPROV_CKA_VERIFY_RECOVER, &ret);
8252 		break;
8253 	case DPROV_REQ_KEY_WRAP:
8254 		rv = dprov_get_object_attr_boolean(object,
8255 		    DPROV_CKA_WRAP, &ret);
8256 		break;
8257 	case DPROV_REQ_KEY_UNWRAP:
8258 		rv = dprov_get_object_attr_boolean(object,
8259 		    DPROV_CKA_UNWRAP, &ret);
8260 		break;
8261 	case DPROV_REQ_DIGEST_KEY:
8262 		/*
8263 		 * There is no attribute to check for; therefore,
8264 		 * any secret key can be used.
8265 		 */
8266 		ret = B_TRUE;
8267 		rv = CRYPTO_SUCCESS;
8268 		break;
8269 	case DPROV_REQ_KEY_DERIVE:
8270 		rv = dprov_get_object_attr_boolean(object,
8271 		    DPROV_CKA_DERIVE, &ret);
8272 		break;
8273 	}
8274 
8275 	if (rv != CRYPTO_SUCCESS || !ret)
8276 		return (CRYPTO_KEY_FUNCTION_NOT_PERMITTED);
8277 
8278 	return (CRYPTO_SUCCESS);
8279 }
8280 
8281 /*
8282  * Given a crypto_key_t corresponding to a secret key (i.e. for
8283  * use with symmetric crypto algorithms) specified in raw format, by
8284  * attribute, or by reference, initialize the ck_data and ck_length
8285  * fields of the ret_key argument so that they specify the key value
8286  * and length.
8287  *
8288  * For a key by value, this function uess the ck_data and ck_length,
8289  * for a key by reference, it looks up the corresponding object and
8290  * returns the appropriate attribute. For a key by attribute, it returns
8291  * the appropriate attribute. The attributes used are CKA_VALUE to retrieve
8292  * the value of the key, and CKA_VALUE_LEN to retrieve its length in bytes.
8293  */
8294 static int
8295 dprov_key_value_secret(dprov_state_t *softc, crypto_session_id_t session_id,
8296     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
8297 {
8298 	ulong_t key_type;
8299 	int ret = CRYPTO_SUCCESS;
8300 
8301 	ret_key->ck_format = CRYPTO_KEY_RAW;
8302 
8303 	switch (key->ck_format) {
8304 
8305 	case CRYPTO_KEY_RAW:
8306 		ret_key->ck_data = key->ck_data;
8307 		ret_key->ck_length = key->ck_length;
8308 		break;
8309 
8310 	case CRYPTO_KEY_ATTR_LIST: {
8311 		void *value;
8312 		size_t len, value_len;
8313 
8314 		if ((ret = dprov_get_key_attr_ulong(key, DPROV_CKA_KEY_TYPE,
8315 		    &key_type)) != CRYPTO_SUCCESS)
8316 			break;
8317 
8318 		if ((ret = dprov_get_key_attr_array(key, DPROV_CKA_VALUE,
8319 		    &value, &len)) != CRYPTO_SUCCESS)
8320 			break;
8321 
8322 		/*
8323 		 * The length of the array is expressed in bytes.
8324 		 * Convert to bits now since that's how keys are measured.
8325 		 */
8326 		len  = len << 3;
8327 
8328 		/* optional */
8329 		if ((dprov_get_key_attr_ulong(key, DPROV_CKA_VALUE_LEN,
8330 		    &value_len)) == CRYPTO_SUCCESS) {
8331 			len = value_len;
8332 		}
8333 
8334 		ret_key->ck_data = value;
8335 		ret_key->ck_length = (uint_t)len;
8336 
8337 		break;
8338 	}
8339 
8340 	case CRYPTO_KEY_REFERENCE: {
8341 		dprov_object_t *object;
8342 		void *value;
8343 		size_t len, value_len;
8344 
8345 		/* check session id */
8346 		if (softc->ds_sessions[session_id] == NULL) {
8347 			ret = CRYPTO_SESSION_HANDLE_INVALID;
8348 			break;
8349 		}
8350 
8351 		if (key->ck_obj_id >= DPROV_MAX_OBJECTS) {
8352 			ret = CRYPTO_KEY_HANDLE_INVALID;
8353 			goto bail;
8354 		}
8355 
8356 		/* check if object id specified by key is valid */
8357 		object = softc->ds_sessions[session_id]->
8358 		    ds_objects[key->ck_obj_id];
8359 		if (object == NULL) {
8360 			ret = CRYPTO_KEY_HANDLE_INVALID;
8361 			goto bail;
8362 		}
8363 
8364 		/* check if object can be used for operation */
8365 		if ((ret = dprov_key_can_use(object, req_type)) !=
8366 		    CRYPTO_SUCCESS)
8367 			goto bail;
8368 
8369 		if ((ret = dprov_get_object_attr_ulong(object,
8370 		    DPROV_CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS)
8371 			goto bail;
8372 
8373 		if ((ret = dprov_get_object_attr_array(object,
8374 		    DPROV_CKA_VALUE, &value, &len)) != CRYPTO_SUCCESS)
8375 			goto bail;
8376 
8377 		/* optional */
8378 		if ((dprov_get_object_attr_ulong(object, DPROV_CKA_VALUE_LEN,
8379 		    &value_len)) == CRYPTO_SUCCESS) {
8380 			len = value_len;
8381 		}
8382 
8383 		/*
8384 		 * The length of attributes are in bytes.
8385 		 * Convert to bits now since that's how keys are measured.
8386 		 */
8387 		len  = len << 3;
8388 
8389 		ret_key->ck_data = value;
8390 		ret_key->ck_length = (uint_t)len;
8391 bail:
8392 		break;
8393 	}
8394 
8395 	default:
8396 		ret = CRYPTO_ARGUMENTS_BAD;
8397 		break;
8398 	}
8399 
8400 	return (ret);
8401 }
8402 
8403 /*
8404  * Get the attribute list for the specified asymmetric key.
8405  */
8406 static int
8407 dprov_key_attr_asymmetric(dprov_state_t *softc, crypto_session_id_t session_id,
8408     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
8409 {
8410 	int ret = CRYPTO_SUCCESS;
8411 
8412 	ret_key->ck_format = CRYPTO_KEY_ATTR_LIST;
8413 
8414 	switch (key->ck_format) {
8415 
8416 	case CRYPTO_KEY_ATTR_LIST:
8417 		ret_key->ck_attrs = key->ck_attrs;
8418 		ret_key->ck_count = key->ck_count;
8419 		break;
8420 
8421 	case CRYPTO_KEY_REFERENCE: {
8422 		dprov_object_t *object;
8423 
8424 		/* check session id */
8425 		if (softc->ds_sessions[session_id] == NULL) {
8426 			ret = CRYPTO_SESSION_HANDLE_INVALID;
8427 			break;
8428 		}
8429 
8430 		/* check if object id specified by key is valid */
8431 		object = softc->ds_sessions[session_id]->
8432 		    ds_objects[key->ck_obj_id];
8433 		if (object == NULL) {
8434 			ret = CRYPTO_KEY_HANDLE_INVALID;
8435 			break;
8436 		}
8437 
8438 		/* check if object can be used for operation */
8439 		if ((ret = dprov_key_can_use(object, req_type)) !=
8440 		    CRYPTO_SUCCESS)
8441 			break;
8442 
8443 		ret_key->ck_attrs = object->do_attr;
8444 		ret_key->ck_count = DPROV_MAX_ATTR;
8445 		break;
8446 	}
8447 
8448 	default:
8449 		ret = CRYPTO_ARGUMENTS_BAD;
8450 	}
8451 
8452 	return (ret);
8453 }
8454 
8455 /*
8456  * Return the index of an attribute of specified type found in
8457  * the specified array of attributes. If the attribute cannot
8458  * found, return -1.
8459  */
8460 static int
8461 dprov_find_attr(crypto_object_attribute_t *attr, uint_t nattr,
8462     uint64_t attr_type)
8463 {
8464 	int i;
8465 
8466 	for (i = 0; i < nattr; i++)
8467 		if (attr[i].oa_value != NULL &&
8468 		    attr[i].oa_type == attr_type)
8469 			return (i);
8470 
8471 	return (-1);
8472 }
8473 
8474 /*
8475  * Given the given object template and session, return whether
8476  * an object can be created from that template according to the
8477  * following rules:
8478  * - private objects can be created only by a logged-in user
8479  */
8480 static int
8481 dprov_template_can_create(dprov_session_t *session,
8482     crypto_object_attribute_t *template, uint_t nattr,
8483     boolean_t check_for_secret)
8484 {
8485 	boolean_t is_private = B_FALSE;
8486 	ulong_t key_type, class;
8487 	int error;
8488 
8489 	/* check CKA_PRIVATE attribute value */
8490 	error = dprov_get_template_attr_boolean(template, nattr,
8491 	    DPROV_CKA_PRIVATE, &is_private);
8492 	if (error == CRYPTO_SUCCESS && is_private) {
8493 		/* it's a private object */
8494 		if (session->ds_state != DPROV_SESSION_STATE_USER) {
8495 			/*
8496 			 * Cannot create private object with SO or public
8497 			 * sessions.
8498 			 */
8499 			return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8500 		}
8501 	}
8502 
8503 	/* all objects must have an object class attribute */
8504 	if (dprov_get_template_attr_ulong(template, nattr, DPROV_CKA_CLASS,
8505 	    &class) != CRYPTO_SUCCESS) {
8506 		return (CRYPTO_TEMPLATE_INCOMPLETE);
8507 	}
8508 
8509 	/* key objects must have a key type attribute */
8510 	if (class == DPROV_CKO_SECRET_KEY ||
8511 	    class == DPROV_CKO_PUBLIC_KEY ||
8512 	    class == DPROV_CKO_PRIVATE_KEY) {
8513 		if (!dprov_template_attr_present(template, nattr,
8514 		    DPROV_CKA_KEY_TYPE)) {
8515 			return (CRYPTO_TEMPLATE_INCOMPLETE);
8516 		}
8517 	}
8518 
8519 	/* check for RSA public key attributes that must be present */
8520 	if (class == DPROV_CKO_PUBLIC_KEY) {
8521 		if (dprov_get_template_attr_ulong(template, nattr,
8522 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
8523 			if (key_type == DPROV_CKK_RSA) {
8524 				if (!dprov_template_attr_present(template,
8525 				    nattr, DPROV_CKA_MODULUS) ||
8526 				    !dprov_template_attr_present(template,
8527 				    nattr, DPROV_CKA_PUBLIC_EXPONENT)) {
8528 					return (CRYPTO_TEMPLATE_INCOMPLETE);
8529 				}
8530 
8531 				/* these attributes should not be present */
8532 				if (dprov_template_attr_present(template, nattr,
8533 				    DPROV_CKA_MODULUS_BITS)) {
8534 					return (CRYPTO_TEMPLATE_INCONSISTENT);
8535 				}
8536 			}
8537 		}
8538 	}
8539 
8540 	/* check for RSA private key attributes that must be present */
8541 	if (class == DPROV_CKO_PRIVATE_KEY) {
8542 		if (dprov_get_template_attr_ulong(template, nattr,
8543 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
8544 			if (key_type == DPROV_CKK_RSA) {
8545 				if (!dprov_template_attr_present(template,
8546 				    nattr, DPROV_CKA_MODULUS))
8547 					return (CRYPTO_TEMPLATE_INCOMPLETE);
8548 
8549 				if (check_for_secret) {
8550 					if (!dprov_template_attr_present(
8551 					    template, nattr,
8552 					    DPROV_CKA_PRIVATE_EXPONENT))
8553 						return (
8554 						    CRYPTO_TEMPLATE_INCOMPLETE);
8555 				}
8556 			}
8557 		}
8558 	}
8559 
8560 	/* check for secret key attributes that must be present */
8561 	if (class == DPROV_CKO_SECRET_KEY) {
8562 		if (check_for_secret) {
8563 			if (!dprov_template_attr_present(template, nattr,
8564 			    DPROV_CKA_VALUE)) {
8565 				return (CRYPTO_TEMPLATE_INCOMPLETE);
8566 			}
8567 		}
8568 
8569 		/* these attributes should not be present */
8570 		if (dprov_template_attr_present(template, nattr,
8571 		    DPROV_CKA_VALUE_LEN)) {
8572 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8573 		}
8574 	}
8575 
8576 	return (CRYPTO_SUCCESS);
8577 }
8578 
8579 /*
8580  * Create an object from the specified template. Checks whether the
8581  * object can be created according to its attributes and the state
8582  * of the session. The new session object id is returned. If the
8583  * object is a token object, it is added to the per-instance object
8584  * table as well.
8585  */
8586 static int
8587 dprov_create_object_from_template(dprov_state_t *softc,
8588     dprov_session_t *session, crypto_object_attribute_t *template,
8589     uint_t nattr, crypto_object_id_t *object_id, boolean_t check_for_secret,
8590     boolean_t force)
8591 {
8592 	dprov_object_t *object;
8593 	boolean_t is_token = B_FALSE;
8594 	boolean_t extractable_attribute_present = B_FALSE;
8595 	boolean_t sensitive_attribute_present = B_FALSE;
8596 	boolean_t private_attribute_present = B_FALSE;
8597 	boolean_t token_attribute_present = B_FALSE;
8598 	uint_t i;
8599 	int error;
8600 	uint_t attr;
8601 	uint_t oattr;
8602 	crypto_attr_type_t type;
8603 	size_t old_len, new_len;
8604 	offset_t offset;
8605 
8606 	if (nattr > DPROV_MAX_ATTR)
8607 		return (CRYPTO_HOST_MEMORY);
8608 
8609 	if (!force) {
8610 		/* verify that object can be created */
8611 		if ((error = dprov_template_can_create(session, template,
8612 		    nattr, check_for_secret)) != CRYPTO_SUCCESS)
8613 			return (error);
8614 	}
8615 
8616 	/* allocate new object */
8617 	object = kmem_zalloc(sizeof (dprov_object_t), KM_SLEEP);
8618 	if (object == NULL)
8619 		return (CRYPTO_HOST_MEMORY);
8620 
8621 	/* is it a token object? */
8622 	/* check CKA_TOKEN attribute value */
8623 	error = dprov_get_template_attr_boolean(template, nattr,
8624 	    DPROV_CKA_TOKEN, &is_token);
8625 	if (error == CRYPTO_SUCCESS && is_token) {
8626 		/* token object, add it to the per-instance object table */
8627 		for (i = 0; i < DPROV_MAX_OBJECTS; i++)
8628 			if (softc->ds_objects[i] == NULL)
8629 				break;
8630 		if (i == DPROV_MAX_OBJECTS)
8631 			/* no free slot */
8632 			return (CRYPTO_HOST_MEMORY);
8633 		softc->ds_objects[i] = object;
8634 		object->do_token_idx = i;
8635 		DPROV_OBJECT_REFHOLD(object);
8636 	}
8637 
8638 	/* add object to session object table */
8639 	for (i = 0; i < DPROV_MAX_OBJECTS; i++)
8640 		if (session->ds_objects[i] == NULL)
8641 			break;
8642 	if (i == DPROV_MAX_OBJECTS) {
8643 		/* no more session object slots */
8644 		DPROV_OBJECT_REFRELE(object);
8645 		return (CRYPTO_HOST_MEMORY);
8646 	}
8647 	session->ds_objects[i] = object;
8648 	DPROV_OBJECT_REFHOLD(object);
8649 	*object_id = i;
8650 
8651 	/* initialize object from template */
8652 	for (attr = 0, oattr = 0; attr < nattr; attr++) {
8653 		if (template[attr].oa_value == NULL)
8654 			continue;
8655 		type = template[attr].oa_type;
8656 		old_len = template[attr].oa_value_len;
8657 		new_len = attribute_size(type, old_len);
8658 
8659 		if (type == DPROV_CKA_EXTRACTABLE) {
8660 			extractable_attribute_present = B_TRUE;
8661 		} else if (type == DPROV_CKA_PRIVATE) {
8662 			private_attribute_present = B_TRUE;
8663 		} else if (type == DPROV_CKA_TOKEN) {
8664 			token_attribute_present = B_TRUE;
8665 		}
8666 		object->do_attr[oattr].oa_type = type;
8667 		object->do_attr[oattr].oa_value_len = new_len;
8668 
8669 		object->do_attr[oattr].oa_value = kmem_zalloc(new_len,
8670 		    KM_SLEEP);
8671 
8672 		offset = 0;
8673 #ifdef _BIG_ENDIAN
8674 		if (fixed_size_attribute(type)) {
8675 			offset = old_len - new_len;
8676 		}
8677 #endif
8678 		bcopy(&template[attr].oa_value[offset],
8679 		    object->do_attr[oattr].oa_value, new_len);
8680 		oattr++;
8681 	}
8682 
8683 	/* add boolean attributes that must be present */
8684 	if (extractable_attribute_present == B_FALSE) {
8685 		object->do_attr[oattr].oa_type = DPROV_CKA_EXTRACTABLE;
8686 		object->do_attr[oattr].oa_value_len = 1;
8687 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
8688 		object->do_attr[oattr].oa_value[0] = B_TRUE;
8689 		oattr++;
8690 	}
8691 
8692 	if (private_attribute_present == B_FALSE) {
8693 		object->do_attr[oattr].oa_type = DPROV_CKA_PRIVATE;
8694 		object->do_attr[oattr].oa_value_len = 1;
8695 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
8696 		object->do_attr[oattr].oa_value[0] = B_FALSE;
8697 		oattr++;
8698 	}
8699 
8700 	if (token_attribute_present == B_FALSE) {
8701 		object->do_attr[oattr].oa_type = DPROV_CKA_TOKEN;
8702 		object->do_attr[oattr].oa_value_len = 1;
8703 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
8704 		object->do_attr[oattr].oa_value[0] = B_FALSE;
8705 		oattr++;
8706 	}
8707 
8708 	if (sensitive_attribute_present == B_FALSE) {
8709 		object->do_attr[oattr].oa_type = DPROV_CKA_SENSITIVE;
8710 		object->do_attr[oattr].oa_value_len = 1;
8711 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
8712 		object->do_attr[oattr].oa_value[0] = B_FALSE;
8713 		oattr++;
8714 	}
8715 	return (CRYPTO_SUCCESS);
8716 }
8717 
8718 /*
8719  * Checks whether or not the object matches the specified attributes.
8720  *
8721  * PKCS#11 attributes which are longs are stored in uint32_t containers
8722  * so they can be matched by both 32 and 64-bit applications.
8723  */
8724 static boolean_t
8725 dprov_attributes_match(dprov_object_t *object,
8726     crypto_object_attribute_t *template, uint_t nattr)
8727 {
8728 	crypto_attr_type_t type;
8729 	size_t tlen, olen, diff;
8730 	int ta_idx;	/* template attribute index */
8731 	int oa_idx;	/* object attribute index */
8732 
8733 	for (ta_idx = 0; ta_idx < nattr; ta_idx++) {
8734 		/* no value for template attribute */
8735 		if (template[ta_idx].oa_value == NULL)
8736 			continue;
8737 
8738 		/* find attribute in object */
8739 		type = template[ta_idx].oa_type;
8740 		oa_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
8741 
8742 		if (oa_idx == -1)
8743 			/* attribute not found in object */
8744 			return (B_FALSE);
8745 
8746 		tlen = template[ta_idx].oa_value_len;
8747 		olen = object->do_attr[oa_idx].oa_value_len;
8748 		if (tlen < olen)
8749 			return (B_FALSE);
8750 
8751 		diff = 0;
8752 #ifdef _BIG_ENDIAN
8753 		/* application may think attribute is 8 bytes */
8754 		if (fixed_size_attribute(type))
8755 			diff = tlen - olen;
8756 #endif
8757 
8758 		if (bcmp(&template[ta_idx].oa_value[diff],
8759 		    object->do_attr[oa_idx].oa_value, olen) != 0)
8760 			/* value mismatch */
8761 			return (B_FALSE);
8762 	}
8763 
8764 	return (B_TRUE);
8765 }
8766 
8767 /*
8768  * Destroy the object specified by its session and object id.
8769  */
8770 static int
8771 dprov_destroy_object(dprov_state_t *softc, dprov_session_t *session,
8772     crypto_object_id_t object_id)
8773 {
8774 	dprov_object_t *object;
8775 
8776 	if ((object = session->ds_objects[object_id]) == NULL)
8777 		return (CRYPTO_OBJECT_HANDLE_INVALID);
8778 
8779 	/* remove from session table */
8780 	session->ds_objects[object_id] = NULL;
8781 
8782 	if (dprov_object_is_token(object)) {
8783 		if (!object->do_destroyed) {
8784 			object->do_destroyed = B_TRUE;
8785 			/* remove from per-instance token table */
8786 			softc->ds_objects[object->do_token_idx] = NULL;
8787 			DPROV_OBJECT_REFRELE(object);
8788 		} else {
8789 			DPROV_DEBUG(D_OBJECT, ("dprov_destroy_object: "
8790 			    "object %p already destroyed\n", (void *)object));
8791 		}
8792 	}
8793 
8794 	DPROV_OBJECT_REFRELE(object);
8795 	return (CRYPTO_SUCCESS);
8796 }
8797 
8798 static int
8799 dprov_object_can_modify(dprov_object_t *object,
8800     crypto_object_attribute_t *template, uint_t nattr)
8801 {
8802 	ulong_t object_class;
8803 
8804 	/* all objects should have an object class attribute */
8805 	if (dprov_get_object_attr_ulong(object, DPROV_CKA_CLASS,
8806 	    &object_class) != CRYPTO_SUCCESS) {
8807 		return (CRYPTO_SUCCESS);
8808 	}
8809 
8810 	if (object_class == DPROV_CKO_SECRET_KEY ||
8811 	    object_class == DPROV_CKO_PUBLIC_KEY ||
8812 	    object_class == DPROV_CKO_PRIVATE_KEY) {
8813 		if (dprov_template_attr_present(template, nattr,
8814 		    DPROV_CKA_CLASS) ||
8815 		    dprov_template_attr_present(template, nattr,
8816 		    DPROV_CKA_KEY_TYPE))
8817 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8818 	}
8819 
8820 	switch (object_class) {
8821 	case DPROV_CKO_SECRET_KEY:
8822 		if (dprov_template_attr_present(template, nattr,
8823 		    DPROV_CKA_VALUE))
8824 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8825 		break;
8826 
8827 	case DPROV_CKO_PUBLIC_KEY:
8828 		if (dprov_template_attr_present(template, nattr,
8829 		    DPROV_CKA_MODULUS) ||
8830 		    dprov_template_attr_present(template, nattr,
8831 		    DPROV_CKA_PUBLIC_EXPONENT))
8832 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8833 		break;
8834 
8835 	case DPROV_CKO_PRIVATE_KEY:
8836 		if (dprov_template_attr_present(template, nattr,
8837 		    DPROV_CKA_MODULUS) ||
8838 		    dprov_template_attr_present(template, nattr,
8839 		    DPROV_CKA_PRIVATE_EXPONENT))
8840 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8841 		break;
8842 
8843 	default:
8844 		return (CRYPTO_SUCCESS);
8845 	}
8846 
8847 	return (CRYPTO_SUCCESS);
8848 }
8849 
8850 /*
8851  * Set the attributes specified by the template in the specified object,
8852  * replacing existing ones if needed.
8853  */
8854 static int
8855 dprov_object_set_attr(dprov_session_t *session, crypto_object_id_t object_id,
8856     crypto_object_attribute_t *template, uint_t nattr,
8857     boolean_t check_attributes)
8858 {
8859 	crypto_attr_type_t type;
8860 	dprov_object_t *object;
8861 	size_t old_len, new_len;
8862 	uint_t i, j;
8863 	int error;
8864 
8865 	if ((object = session->ds_objects[object_id]) == NULL)
8866 		return (CRYPTO_OBJECT_HANDLE_INVALID);
8867 
8868 	if (check_attributes) {
8869 		/* verify that attributes in the template can be modified */
8870 		if ((error = dprov_object_can_modify(object, template, nattr))
8871 		    != CRYPTO_SUCCESS)
8872 			return (error);
8873 	}
8874 
8875 	/* go through the attributes specified in the template */
8876 	for (i = 0; i < nattr; i++) {
8877 		if (template[i].oa_value == NULL)
8878 			continue;
8879 
8880 		/* find attribute in object */
8881 		type = template[i].oa_type;
8882 		j = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
8883 
8884 		if (j != -1) {
8885 			/* attribute already exists, free old value */
8886 			kmem_free(object->do_attr[j].oa_value,
8887 			    object->do_attr[j].oa_value_len);
8888 		} else {
8889 			/* attribute does not exist, create it */
8890 			for (j = 0; j < DPROV_MAX_ATTR; j++)
8891 				if (object->do_attr[j].oa_value == NULL)
8892 					break;
8893 			if (j == DPROV_MAX_ATTR)
8894 				/* ran out of attribute slots */
8895 				return (CRYPTO_HOST_MEMORY);
8896 		}
8897 
8898 		old_len = template[i].oa_value_len;
8899 		new_len = attribute_size(type, old_len);
8900 
8901 		/* set object attribute value */
8902 		object->do_attr[j].oa_value = kmem_alloc(new_len, KM_SLEEP);
8903 		bcopy(&template[i].oa_value[old_len - new_len],
8904 		    object->do_attr[j].oa_value, new_len);
8905 		object->do_attr[j].oa_value_len = new_len;
8906 
8907 		/* and the type */
8908 		object->do_attr[j].oa_type = type;
8909 	}
8910 
8911 	return (CRYPTO_SUCCESS);
8912 }
8913 
8914 
8915 /*
8916  * Free the specified object.
8917  */
8918 static void
8919 dprov_free_object(dprov_object_t *object)
8920 {
8921 	int i;
8922 
8923 	/* free the object attributes values */
8924 	for (i = 0; i < DPROV_MAX_ATTR; i++)
8925 		if (object->do_attr[i].oa_value != NULL)
8926 			kmem_free(object->do_attr[i].oa_value,
8927 			    object->do_attr[i].oa_value_len);
8928 
8929 	/* free the object */
8930 	kmem_free(object, sizeof (dprov_object_t));
8931 }
8932 
8933 /*
8934  * Checks whether the specified object is a private or public object.
8935  */
8936 static boolean_t
8937 dprov_object_is_private(dprov_object_t *object)
8938 {
8939 	boolean_t ret;
8940 	int err;
8941 
8942 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_PRIVATE, &ret);
8943 
8944 	if (err != CRYPTO_SUCCESS)
8945 		/* by default, CKA_PRIVATE is false */
8946 		ret = B_FALSE;
8947 
8948 	return (ret);
8949 }
8950 
8951 /*
8952  * Checks whether the specified object is a token or session object.
8953  */
8954 static boolean_t
8955 dprov_object_is_token(dprov_object_t *object)
8956 {
8957 	boolean_t ret;
8958 	int err;
8959 
8960 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_TOKEN, &ret);
8961 
8962 	if (err != CRYPTO_SUCCESS)
8963 		/* by default, CKA_TOKEN is false */
8964 		ret = B_FALSE;
8965 
8966 	return (ret);
8967 }
8968 
8969 /*
8970  * Common function used by the dprov_get_object_attr_*() family of
8971  * functions. Returns the value of the specified attribute of specified
8972  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
8973  * if the length of the attribute does not match the specified length,
8974  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
8975  */
8976 static int
8977 dprov_get_object_attr_scalar_common(dprov_object_t *object, uint64_t attr_type,
8978 				    void *value, size_t value_len)
8979 {
8980 	int attr_idx;
8981 	size_t oa_value_len;
8982 	size_t offset = 0;
8983 
8984 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
8985 	    attr_type)) == -1)
8986 		return (CRYPTO_ARGUMENTS_BAD);
8987 
8988 	oa_value_len = object->do_attr[attr_idx].oa_value_len;
8989 	if (oa_value_len != value_len) {
8990 		/*
8991 		 * For some attributes, it's okay to copy the value
8992 		 * into a larger container, e.g. copy an unsigned
8993 		 * 32-bit integer into a 64-bit container.
8994 		 */
8995 		if (attr_type == DPROV_CKA_VALUE_LEN ||
8996 		    attr_type == DPROV_CKA_KEY_TYPE ||
8997 		    attr_type == DPROV_CKA_CLASS) {
8998 			if (oa_value_len < value_len) {
8999 #ifdef _BIG_ENDIAN
9000 				offset = value_len - oa_value_len;
9001 #endif
9002 				bzero(value, value_len);
9003 				goto do_copy;
9004 			}
9005 		}
9006 		/* incorrect attribute value length */
9007 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9008 	}
9009 
9010 do_copy:
9011 	bcopy(object->do_attr[attr_idx].oa_value, (uchar_t *)value + offset,
9012 	    oa_value_len);
9013 
9014 	return (CRYPTO_SUCCESS);
9015 }
9016 
9017 /*
9018  * Get the value of the a boolean attribute from the specified object.
9019  */
9020 static int
9021 dprov_get_object_attr_boolean(dprov_object_t *object, uint64_t attr_type,
9022     boolean_t *attr_value)
9023 {
9024 	uchar_t val;
9025 	int ret;
9026 
9027 	/* PKCS#11 defines a boolean as one byte */
9028 	ret = dprov_get_object_attr_scalar_common(object, attr_type, &val, 1);
9029 	if (ret == CRYPTO_SUCCESS) {
9030 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
9031 	}
9032 	return (ret);
9033 }
9034 
9035 /*
9036  * Get the value of a ulong_t attribute from the specified object.
9037  */
9038 static int
9039 dprov_get_object_attr_ulong(dprov_object_t *object, uint64_t attr_type,
9040     ulong_t *attr_value)
9041 {
9042 	return (dprov_get_object_attr_scalar_common(object, attr_type,
9043 	    attr_value, sizeof (ulong_t)));
9044 }
9045 
9046 /*
9047  * Find the specified byte array attribute of specified type in
9048  * the specified object. Returns CRYPTO_SUCCESS
9049  * on success or CRYPTO_ARGUMENTS_BAD if the specified
9050  * attribute cannot be found.
9051  */
9052 static int
9053 dprov_get_object_attr_array(dprov_object_t *object, uint64_t attr_type,
9054     void **array, size_t *len)
9055 {
9056 	int attr_idx;
9057 
9058 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
9059 	    attr_type)) == -1)
9060 		return (CRYPTO_ARGUMENTS_BAD);
9061 
9062 	*array = object->do_attr[attr_idx].oa_value;
9063 	*len = object->do_attr[attr_idx].oa_value_len;
9064 
9065 	return (CRYPTO_SUCCESS);
9066 }
9067 
9068 /*
9069  * Common function used by the dprov_get_template_attr_*() family of
9070  * functions. Returns the value of the specified attribute of specified
9071  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9072  * if the length of the attribute does not match the specified length,
9073  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9074  */
9075 static int
9076 dprov_get_template_attr_scalar_common(crypto_object_attribute_t *template,
9077     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
9078 {
9079 	size_t oa_value_len;
9080 	size_t offset = 0;
9081 	int attr_idx;
9082 
9083 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
9084 		return (CRYPTO_ARGUMENTS_BAD);
9085 
9086 	oa_value_len = template[attr_idx].oa_value_len;
9087 	if (oa_value_len != value_len) {
9088 		/*
9089 		 * For some attributes, it's okay to copy the value
9090 		 * into a larger container, e.g. copy an unsigned
9091 		 * 32-bit integer into a 64-bit container.
9092 		 */
9093 		if (attr_type == DPROV_CKA_VALUE_LEN ||
9094 		    attr_type == DPROV_CKA_KEY_TYPE ||
9095 		    attr_type == DPROV_CKA_CLASS) {
9096 			if (oa_value_len < value_len) {
9097 #ifdef _BIG_ENDIAN
9098 				offset = value_len - oa_value_len;
9099 #endif
9100 				bzero(value, value_len);
9101 				goto do_copy;
9102 			}
9103 		}
9104 		/* incorrect attribute value length */
9105 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9106 	}
9107 
9108 do_copy:
9109 	bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
9110 	    oa_value_len);
9111 
9112 	return (CRYPTO_SUCCESS);
9113 }
9114 
9115 /*
9116  * Get the value of the a boolean attribute from the specified template
9117  */
9118 static int
9119 dprov_get_template_attr_boolean(crypto_object_attribute_t *template,
9120     uint_t nattr, uint64_t attr_type, boolean_t *attr_value)
9121 {
9122 	uchar_t val;
9123 	int ret;
9124 
9125 	/* PKCS#11 defines a boolean as one byte */
9126 	ret = dprov_get_template_attr_scalar_common(template, nattr,
9127 	    attr_type, &val, 1);
9128 	if (ret == CRYPTO_SUCCESS) {
9129 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
9130 	}
9131 	return (ret);
9132 }
9133 
9134 /*
9135  * Get the value of a ulong_t attribute from the specified template.
9136  */
9137 static int
9138 dprov_get_template_attr_ulong(crypto_object_attribute_t *template,
9139     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
9140 {
9141 	return (dprov_get_template_attr_scalar_common(template, nattr,
9142 	    attr_type, attr_value, sizeof (ulong_t)));
9143 }
9144 
9145 static int
9146 dprov_template_attr_present(crypto_object_attribute_t *template,
9147     uint_t nattr, uint64_t attr_type)
9148 {
9149 	return (dprov_find_attr(template, nattr,
9150 	    attr_type) == -1 ? B_FALSE : B_TRUE);
9151 }
9152 
9153 /*
9154  * Find the specified byte array attribute of specified type in
9155  * the specified template. Returns CRYPTO_SUCCESS on success or
9156  * CRYPTO_ARGUMENTS_BAD if the specified attribute cannot be found.
9157  */
9158 static int
9159 dprov_get_template_attr_array(crypto_object_attribute_t *template,
9160     uint_t nattr, uint64_t attr_type, void **array, size_t *len)
9161 {
9162 	int attr_idx;
9163 
9164 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
9165 		return (CRYPTO_ARGUMENTS_BAD);
9166 
9167 	*array = template[attr_idx].oa_value;
9168 	*len = template[attr_idx].oa_value_len;
9169 
9170 	return (CRYPTO_SUCCESS);
9171 }
9172 
9173 /*
9174  * Common function used by the dprov_get_key_attr_*() family of
9175  * functions. Returns the value of the specified attribute of specified
9176  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9177  * if the length of the attribute does not match the specified length,
9178  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9179  */
9180 static int
9181 dprov_get_key_attr_scalar_common(crypto_key_t *key, uint64_t attr_type,
9182     void *value, size_t value_len)
9183 {
9184 	int attr_idx;
9185 
9186 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
9187 
9188 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
9189 	    attr_type)) == -1)
9190 		return (CRYPTO_ARGUMENTS_BAD);
9191 
9192 	if (key->ck_attrs[attr_idx].oa_value_len != value_len)
9193 		/* incorrect attribute value length */
9194 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9195 
9196 	bcopy(key->ck_attrs[attr_idx].oa_value, value, value_len);
9197 
9198 	return (CRYPTO_SUCCESS);
9199 }
9200 
9201 /*
9202  * Get the value of a ulong_t attribute from the specified key.
9203  */
9204 static int
9205 dprov_get_key_attr_ulong(crypto_key_t *key, uint64_t attr_type,
9206     ulong_t *attr_value)
9207 {
9208 	return (dprov_get_key_attr_scalar_common(key, attr_type,
9209 	    attr_value, sizeof (ulong_t)));
9210 }
9211 
9212 /*
9213  * Find the specified byte array attribute of specified type in
9214  * the specified key by attributes. Returns CRYPTO_SUCCESS
9215  * on success or CRYPTO_ARGUMENTS_BAD if the specified
9216  * attribute cannot be found.
9217  */
9218 static int
9219 dprov_get_key_attr_array(crypto_key_t *key, uint64_t attr_type,
9220     void **array, size_t *len)
9221 {
9222 	int attr_idx;
9223 
9224 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
9225 
9226 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
9227 	    attr_type)) == -1)
9228 		return (CRYPTO_ARGUMENTS_BAD);
9229 
9230 	*array = key->ck_attrs[attr_idx].oa_value;
9231 	*len = key->ck_attrs[attr_idx].oa_value_len;
9232 
9233 	return (CRYPTO_SUCCESS);
9234 }
9235 
9236 static void
9237 dprov_release_session_objects(dprov_session_t *session)
9238 {
9239 	dprov_object_t *object;
9240 	int i;
9241 
9242 	for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
9243 		object = session->ds_objects[i];
9244 		if (object != NULL) {
9245 			DPROV_OBJECT_REFRELE(object);
9246 		}
9247 	}
9248 }
9249