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