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