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