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