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