xref: /illumos-gate/usr/src/uts/common/crypto/io/dprov.c (revision b9ccdc5a)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Dummy Cryptographic Provider:
30  *
31  * This file implements a "dummy" cryptographic provider. It is implemented
32  * as a pseudo device driver.
33  *
34  */
35 
36 /*
37  * This driver implements a KEF provider with the following capabilities:
38  *
39  * - registration/unregistration with KEF
40  * - digest entry points
41  * - mac entry points
42  * - ctx management
43  * - support for async requests
44  * - cipher entry points
45  * - dual entry points
46  * - sign entry points
47  * - verify entry points
48  * - dual operations entry points
49  * - dual cipher/mac operation entry points
50  * - session management
51  * - object management
52  * - key management
53  * - provider management
54  *
55  * In order to avoid duplicating the implementation of algorithms
56  * provided by software providers, this pseudo driver acts as
57  * a consumer of the framework. When invoking one of the framework's
58  * entry points, the driver specifies the software provider to
59  * be used for the operation.
60  *
61  * User management: we implement a PKCS#11 style provider which supports:
62  * - one normal user with a PIN, and
63  * - one SO user with a PIN.
64  * These values are kept in the per-instance structure, and are initialized
65  * with the provider management entry points.
66  *
67  */
68 
69 
70 #include <sys/types.h>
71 #include <sys/modctl.h>
72 #include <sys/conf.h>
73 #include <sys/stat.h>
74 #include <sys/ddi.h>
75 #include <sys/sunddi.h>
76 #include <sys/kmem.h>
77 #include <sys/errno.h>
78 #include <sys/ksynch.h>
79 #include <sys/file.h>
80 #include <sys/open.h>
81 #include <sys/cred.h>
82 #include <sys/model.h>
83 #include <sys/note.h>
84 #include <sys/random.h>
85 #include <sys/byteorder.h>
86 #include <sys/crypto/common.h>
87 #include <sys/crypto/spi.h>
88 
89 #include <sys/taskq.h>
90 #include <sys/disp.h>
91 #include <sys/sysmacros.h>
92 #include <sys/crypto/impl.h>
93 #include <sys/crypto/sched_impl.h>
94 
95 #include <sys/sha2.h>
96 #include <modes/modes.h>
97 #include <aes/aes_impl.h>
98 #include <des/des_impl.h>
99 #include <ecc/ecc_impl.h>
100 #include <blowfish/blowfish_impl.h>
101 
102 /*
103  * Debugging macros.
104  */
105 #ifdef DEBUG
106 #define	D_INIT		0x00000001	/* _init/_fini/_info */
107 #define	D_ATTACH	0x00000002	/* attach/detach */
108 #define	D_DIGEST	0x00000010	/* digest entry points */
109 #define	D_MAC		0x00000020	/* mac entry points */
110 #define	D_CONTEXT	0x00000040	/* context entry points */
111 #define	D_CIPHER	0x00000080	/* cipher entry points */
112 #define	D_SIGN		0x00000100	/* sign entry points */
113 #define	D_VERIFY	0x00000200	/* verify entry points */
114 #define	D_SESSION	0x00000400	/* session management entry points */
115 #define	D_MGMT		0x00000800	/* provider management entry points */
116 #define	D_DUAL		0x00001000	/* dual ops */
117 #define	D_CIPHER_MAC	0x00002000	/* cipher/mac dual ops */
118 #define	D_OBJECT	0x00004000	/* object management */
119 #define	D_RANDOM	0x00008000	/* random number generation */
120 #define	D_KEY		0x00010000	/* key management */
121 
122 static uint32_t dprov_debug = 0;
123 
124 #define	DPROV_DEBUG(f, x)	if (dprov_debug & (f)) { (void) printf x; }
125 #define	DPROV_CALL(f, r, x)	if (dprov_debug & (f)) { (void) r x; }
126 #else /* DEBUG */
127 #define	DPROV_DEBUG(f, x)
128 #define	DPROV_CALL(f, r, x)
129 #endif /* DEBUG */
130 
131 static int nostore_key_gen;
132 static boolean_t dprov_no_multipart = B_FALSE;
133 static int dprov_max_digestsz = INT_MAX;
134 
135 /*
136  * DDI entry points.
137  */
138 static int dprov_attach(dev_info_t *, ddi_attach_cmd_t);
139 static int dprov_detach(dev_info_t *, ddi_detach_cmd_t);
140 static int dprov_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
141 
142 /*
143  * Module linkage.
144  */
145 static struct cb_ops cbops = {
146 	nodev,			/* cb_open */
147 	nodev,			/* cb_close */
148 	nodev,			/* cb_strategy */
149 	nodev,			/* cb_print */
150 	nodev,			/* cb_dump */
151 	nodev,			/* cb_read */
152 	nodev,			/* cb_write */
153 	nodev,			/* cb_ioctl */
154 	nodev,			/* cb_devmap */
155 	nodev,			/* cb_mmap */
156 	nodev,			/* cb_segmap */
157 	nochpoll,		/* cb_chpoll */
158 	ddi_prop_op,		/* cb_prop_op */
159 	NULL,			/* cb_streamtab */
160 	D_MP,			/* cb_flag */
161 	CB_REV,			/* cb_rev */
162 	nodev,			/* cb_aread */
163 	nodev,			/* cb_awrite */
164 };
165 
166 static struct dev_ops devops = {
167 	DEVO_REV,		/* devo_rev */
168 	0,			/* devo_refcnt */
169 	dprov_getinfo,		/* devo_getinfo */
170 	nulldev,		/* devo_identify */
171 	nulldev,		/* devo_probe */
172 	dprov_attach,		/* devo_attach */
173 	dprov_detach,		/* devo_detach */
174 	nodev,			/* devo_reset */
175 	&cbops,			/* devo_cb_ops */
176 	NULL,			/* devo_bus_ops */
177 	NULL,			/* devo_power */
178 };
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(2 * softc->ds_sessions_slots,
6628 			    KM_NOSLEEP);
6629 			if (new_sessions == NULL) {
6630 				error = CRYPTO_SESSION_COUNT;
6631 				break;
6632 			}
6633 			bcopy(softc->ds_sessions, new_sessions,
6634 			    softc->ds_sessions_slots);
6635 			kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
6636 			    sizeof (dprov_session_t *));
6637 			softc->ds_sessions = new_sessions;
6638 			softc->ds_sessions_slots *= 2;
6639 		}
6640 
6641 		/* allocate and initialize new session */
6642 		softc->ds_sessions[i] = kmem_zalloc(
6643 		    sizeof (dprov_session_t), KM_NOSLEEP);
6644 		if (softc->ds_sessions[i] == NULL) {
6645 			error = CRYPTO_HOST_MEMORY;
6646 			break;
6647 		}
6648 		softc->ds_sessions_count++;
6649 
6650 		/* initialize session state */
6651 		softc->ds_sessions[i]->ds_state = DPROV_SESSION_STATE_PUBLIC;
6652 
6653 		/* return new session id to caller */
6654 		*(taskq_req->dr_session_req.sr_session_id_ptr) = i;
6655 
6656 		error = CRYPTO_SUCCESS;
6657 		break;
6658 	}
6659 
6660 	case DPROV_REQ_SESSION_CLOSE:
6661 		softc->ds_sessions[session_id] = NULL;
6662 
6663 		if (softc->ds_token_initialized == B_FALSE) {
6664 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
6665 			break;
6666 		}
6667 
6668 		dprov_release_session_objects(session);
6669 
6670 		/* free session state and corresponding slot */
6671 		kmem_free(session, sizeof (dprov_session_t));
6672 		softc->ds_sessions_count--;
6673 
6674 		error = CRYPTO_SUCCESS;
6675 		break;
6676 
6677 	case DPROV_REQ_SESSION_LOGIN: {
6678 		char *pin = taskq_req->dr_session_req.sr_pin;
6679 		size_t pin_len = taskq_req->dr_session_req.sr_pin_len;
6680 		crypto_user_type_t user_type =
6681 		    taskq_req->dr_session_req.sr_user_type;
6682 
6683 		/* check user type */
6684 		if (user_type != CRYPTO_SO && user_type != CRYPTO_USER) {
6685 			error = CRYPTO_USER_TYPE_INVALID;
6686 			break;
6687 		}
6688 
6689 		/* check pin length */
6690 		if (pin_len > DPROV_MAX_PIN_LEN) {
6691 			error = CRYPTO_PIN_LEN_RANGE;
6692 			break;
6693 		}
6694 
6695 		/* check pin */
6696 		if (pin == NULL) {
6697 			error = CRYPTO_PIN_INVALID;
6698 			break;
6699 		}
6700 
6701 		/* validate PIN state */
6702 		if ((user_type == CRYPTO_SO) && !softc->ds_token_initialized ||
6703 		    (user_type == CRYPTO_USER) && !softc->ds_user_pin_set) {
6704 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
6705 			break;
6706 		}
6707 
6708 		if ((user_type == CRYPTO_SO &&
6709 		    softc->ds_sessions[session_id]->ds_state ==
6710 		    DPROV_SESSION_STATE_SO) ||
6711 		    (user_type == CRYPTO_USER &&
6712 		    softc->ds_sessions[session_id]->ds_state ==
6713 		    DPROV_SESSION_STATE_USER)) {
6714 			/* SO or user already logged in */
6715 			error = CRYPTO_USER_ALREADY_LOGGED_IN;
6716 			break;
6717 		}
6718 
6719 		if (softc->ds_sessions[session_id]->ds_state !=
6720 		    DPROV_SESSION_STATE_PUBLIC) {
6721 			/* another user already logged in */
6722 			error = CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN;
6723 			break;
6724 		}
6725 
6726 		/* everything's fine, update session */
6727 		softc->ds_sessions[session_id]->ds_state =
6728 		    user_type == CRYPTO_SO ?
6729 		    DPROV_SESSION_STATE_SO : DPROV_SESSION_STATE_USER;
6730 
6731 		error = CRYPTO_SUCCESS;
6732 		break;
6733 	}
6734 
6735 	case DPROV_REQ_SESSION_LOGOUT:
6736 		/* fail if not logged in */
6737 		if (softc->ds_sessions[session_id]->ds_state ==
6738 		    DPROV_SESSION_STATE_PUBLIC) {
6739 			error = CRYPTO_USER_NOT_LOGGED_IN;
6740 			break;
6741 		}
6742 
6743 		/*
6744 		 * Destroy all private session objects.
6745 		 * Invalidate handles to all private objects.
6746 		 */
6747 		for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
6748 			object = softc->ds_sessions[session_id]->ds_objects[i];
6749 			if (object != NULL && dprov_object_is_private(object)) {
6750 				if (!dprov_object_is_token(object))
6751 					/* It's a session object, free it */
6752 					DPROV_OBJECT_REFRELE(object);
6753 				softc->ds_sessions[session_id]->ds_objects[i] =
6754 				    NULL;
6755 			}
6756 		}
6757 
6758 		/* update session state */
6759 		softc->ds_sessions[session_id]->ds_state =
6760 		    DPROV_SESSION_STATE_PUBLIC;
6761 
6762 		error = CRYPTO_SUCCESS;
6763 		break;
6764 	}
6765 
6766 	mutex_exit(&softc->ds_lock);
6767 	dprov_op_done(taskq_req, error);
6768 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: end\n", instance));
6769 }
6770 
6771 /* return true if attribute is defined to be a PKCS#11 long */
6772 static boolean_t
6773 fixed_size_attribute(crypto_attr_type_t type)
6774 {
6775 	return (type == DPROV_CKA_CLASS ||
6776 	    type == DPROV_CKA_CERTIFICATE_TYPE ||
6777 	    type == DPROV_CKA_KEY_TYPE ||
6778 	    type == DPROV_HW_FEATURE_TYPE);
6779 }
6780 
6781 /*
6782  * Attributes defined to be a PKCS#11 long causes problems for dprov
6783  * because 32-bit applications set the size to 4 and 64-bit applications
6784  * set the size to 8. dprov always stores these fixed-size attributes
6785  * as uint32_t.
6786  */
6787 static ssize_t
6788 attribute_size(crypto_attr_type_t type, ssize_t len)
6789 {
6790 	if (fixed_size_attribute(type))
6791 		return (sizeof (uint32_t));
6792 
6793 	return (len);
6794 }
6795 
6796 /*
6797  * taskq dispatcher function for object management operations.
6798  */
6799 static void
6800 dprov_object_task(dprov_req_t *taskq_req)
6801 {
6802 	dprov_state_t *softc;
6803 	/* LINTED E_FUNC_SET_NOT_USED */
6804 	int instance;
6805 	int error = CRYPTO_NOT_SUPPORTED;
6806 	crypto_object_id_t object_id = taskq_req->dr_object_req.or_object_id;
6807 	crypto_session_id_t session_id = taskq_req->dr_object_req.or_session_id;
6808 	crypto_object_attribute_t *template =
6809 	    taskq_req->dr_object_req.or_template;
6810 	uint_t attr_count = taskq_req->dr_object_req.or_attribute_count;
6811 	dprov_object_t *object;
6812 	dprov_session_t *session;
6813 
6814 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6815 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: started\n", instance));
6816 
6817 	mutex_enter(&softc->ds_lock);
6818 
6819 	/* validate session id and get ptr to session */
6820 	if ((session = softc->ds_sessions[session_id]) == NULL) {
6821 		mutex_exit(&softc->ds_lock);
6822 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6823 		return;
6824 	}
6825 
6826 	switch (taskq_req->dr_type) {
6827 
6828 	case DPROV_REQ_OBJECT_CREATE:
6829 		/* create the object from the specified template */
6830 		if ((error = dprov_create_object_from_template(softc, session,
6831 		    template, attr_count,
6832 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
6833 		    B_FALSE)) != CRYPTO_SUCCESS)
6834 			break;
6835 
6836 		break;
6837 
6838 	case DPROV_REQ_OBJECT_COPY:
6839 		/* check object id */
6840 		if (object_id >= DPROV_MAX_OBJECTS ||
6841 		    (object = session->ds_objects[object_id]) == NULL) {
6842 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6843 			break;
6844 		}
6845 
6846 		/*
6847 		 * Create a new object from the object passed as
6848 		 * argument.
6849 		 */
6850 		if ((error = dprov_create_object_from_template(softc, session,
6851 		    object->do_attr, DPROV_MAX_ATTR,
6852 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
6853 		    B_FALSE)) != CRYPTO_SUCCESS)
6854 			break;
6855 
6856 		/*
6857 		 * Add the attributes specified by the template to the
6858 		 * newly created object, replacing existing ones if needed.
6859 		 */
6860 		error = dprov_object_set_attr(session,
6861 		    *taskq_req->dr_object_req.or_object_id_ptr,
6862 		    taskq_req->dr_object_req.or_template,
6863 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6864 
6865 		break;
6866 
6867 	case DPROV_REQ_OBJECT_DESTROY:
6868 		/* destroy the object */
6869 		error = dprov_destroy_object(softc, session,
6870 		    taskq_req->dr_object_req.or_object_id);
6871 
6872 		break;
6873 
6874 	case DPROV_REQ_OBJECT_GET_SIZE:
6875 		/* get ptr to object */
6876 		if (object_id >= DPROV_MAX_OBJECTS ||
6877 		    session->ds_objects[object_id] == NULL) {
6878 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6879 			break;
6880 		}
6881 
6882 		/*
6883 		 * The PKCS11 specification does not specifies what
6884 		 * the object size really is, here we just return
6885 		 * the number of possible attributes of the object.
6886 		 */
6887 		*taskq_req->dr_object_req.or_object_size = DPROV_MAX_ATTR;
6888 
6889 		error = CRYPTO_SUCCESS;
6890 		break;
6891 
6892 	case DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE: {
6893 		crypto_attr_type_t type;
6894 		size_t olen, tlen;
6895 		offset_t offset;
6896 		int tmpl_idx;
6897 		int object_idx;
6898 		ulong_t class = DPROV_CKO_DATA;
6899 		boolean_t extractable = B_TRUE;
6900 
6901 		error = CRYPTO_SUCCESS;
6902 
6903 		/* get ptr to object */
6904 		if (object_id >= DPROV_MAX_OBJECTS ||
6905 		    (object = session->ds_objects[object_id]) == NULL) {
6906 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6907 			break;
6908 		}
6909 
6910 		(void) dprov_get_object_attr_boolean(object,
6911 		    DPROV_CKA_EXTRACTABLE, &extractable);
6912 
6913 		(void) dprov_get_object_attr_ulong(object,
6914 		    DPROV_CKA_CLASS, &class);
6915 
6916 		/* return the specified attributes, when possible */
6917 		for (tmpl_idx = 0; tmpl_idx < attr_count; tmpl_idx++) {
6918 			/*
6919 			 * Attribute can't be revealed if the CKA_EXTRACTABLE
6920 			 * attribute is set to false.
6921 			 */
6922 			type = template[tmpl_idx].oa_type;
6923 			if (!extractable && class == DPROV_CKO_SECRET_KEY) {
6924 				if (type == DPROV_CKA_VALUE) {
6925 					template[tmpl_idx].oa_value_len = -1;
6926 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6927 					continue;
6928 				}
6929 			}
6930 			if (!extractable && class == DPROV_CKO_PRIVATE_KEY) {
6931 				if (type == DPROV_CKA_PRIVATE_EXPONENT) {
6932 					template[tmpl_idx].oa_value_len = -1;
6933 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6934 					continue;
6935 				}
6936 			}
6937 
6938 			object_idx = dprov_find_attr(object->do_attr,
6939 			    DPROV_MAX_ATTR, type);
6940 			if (object_idx == -1) {
6941 				/* attribute not found in object */
6942 				template[tmpl_idx].oa_value_len = -1;
6943 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
6944 				continue;
6945 			}
6946 
6947 			tlen = template[tmpl_idx].oa_value_len;
6948 			olen = object->do_attr[object_idx].oa_value_len;
6949 			/* return attribute length */
6950 			if (template[tmpl_idx].oa_value == NULL) {
6951 				/*
6952 				 * The size of the attribute is set by the
6953 				 * library according to the data model of the
6954 				 * application, so don't overwrite it with
6955 				 * dprov's size.
6956 				 */
6957 				if (!fixed_size_attribute(type))
6958 					template[tmpl_idx].oa_value_len = olen;
6959 				continue;
6960 			}
6961 
6962 			if (tlen < olen) {
6963 				template[tmpl_idx].oa_value_len = -1;
6964 				error = CRYPTO_BUFFER_TOO_SMALL;
6965 				continue;
6966 			}
6967 
6968 			/* copy attribute value */
6969 			bzero(template[tmpl_idx].oa_value, tlen);
6970 
6971 			offset = 0;
6972 #ifdef _BIG_ENDIAN
6973 			if (fixed_size_attribute(type)) {
6974 				offset = tlen - olen;
6975 			}
6976 #endif
6977 			bcopy(object->do_attr[object_idx].oa_value,
6978 			    &template[tmpl_idx].oa_value[offset], olen);
6979 
6980 			/* don't update length for fixed-size attributes */
6981 			if (!fixed_size_attribute(type))
6982 				template[tmpl_idx].oa_value_len = olen;
6983 		}
6984 
6985 		break;
6986 	}
6987 
6988 	case DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE:
6989 		/*
6990 		 * Add the attributes specified by the template to the
6991 		 * newly created object, replacing existing ones if needed.
6992 		 */
6993 		error = dprov_object_set_attr(session,
6994 		    taskq_req->dr_object_req.or_object_id,
6995 		    taskq_req->dr_object_req.or_template,
6996 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6997 
6998 		break;
6999 
7000 	case DPROV_REQ_OBJECT_FIND_INIT: {
7001 		dprov_find_ctx_t *find_ctx;
7002 		int so_idx;		/* session object index */
7003 		int to_idx;		/* token object index */
7004 
7005 		error = CRYPTO_SUCCESS;
7006 		/* allocate find context */
7007 		find_ctx = kmem_zalloc(sizeof (dprov_find_ctx_t), KM_SLEEP);
7008 		*taskq_req->dr_object_req.or_find_pp = find_ctx;
7009 
7010 		/* first go through the existing session objects */
7011 		for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++) {
7012 			if ((object = session->ds_objects[so_idx]) == NULL)
7013 				continue;
7014 
7015 			/* setting count to zero means find all objects */
7016 			if (attr_count > 0) {
7017 				if (!dprov_attributes_match(object, template,
7018 				    attr_count))
7019 					continue;
7020 			}
7021 
7022 			/* session object attributes matches template */
7023 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
7024 			find_ctx->fc_nids++;
7025 		}
7026 
7027 		/*
7028 		 * Go through the token object. For each token object
7029 		 * that can be accessed:
7030 		 * If there was already an session object id assigned
7031 		 * to that token object, skip it, since it was returned
7032 		 * during the check of session objects, else,
7033 		 * assign a new object id for that token object and
7034 		 * add it to the array of matching objects.
7035 		 */
7036 		for (to_idx = 0; to_idx < DPROV_MAX_OBJECTS &&
7037 		    error == CRYPTO_SUCCESS; to_idx++) {
7038 			if ((object = softc->ds_objects[to_idx]) == NULL)
7039 				continue;
7040 
7041 			/* setting count to zero means find all objects */
7042 			if (attr_count > 0) {
7043 				if (!dprov_attributes_match(object, template,
7044 				    attr_count))
7045 					continue;
7046 			}
7047 
7048 			/* if the the object has been destroyed, skip it */
7049 			if (object->do_destroyed)
7050 				continue;
7051 
7052 			/* skip object if it cannot be accessed from session */
7053 			if (dprov_object_is_private(object) &&
7054 			    session->ds_state != DPROV_SESSION_STATE_USER)
7055 				continue;
7056 
7057 			/*
7058 			 * Is there already a session object id for this
7059 			 * token object?
7060 			 */
7061 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
7062 				if (session->ds_objects[so_idx] != NULL &&
7063 				    session->ds_objects[so_idx]->do_token_idx ==
7064 				    to_idx)
7065 					break;
7066 			if (so_idx < DPROV_MAX_OBJECTS)
7067 				/* object found in session table, skip it */
7068 				continue;
7069 
7070 			/* find free session slot for this object */
7071 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
7072 				if (session->ds_objects[so_idx] == NULL)
7073 					break;
7074 			if (so_idx == DPROV_MAX_OBJECTS) {
7075 				/* ran out of session objects slots */
7076 				kmem_free(find_ctx, sizeof (dprov_find_ctx_t));
7077 				error = CRYPTO_HOST_MEMORY;
7078 				break;
7079 			}
7080 
7081 			/* add object to session objects table */
7082 			session->ds_objects[so_idx] = object;
7083 			DPROV_OBJECT_REFHOLD(object);
7084 
7085 			/* add object to list of objects to return */
7086 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
7087 			find_ctx->fc_nids++;
7088 		}
7089 
7090 		break;
7091 	}
7092 
7093 	case DPROV_REQ_OBJECT_FIND: {
7094 		crypto_object_id_t *object_ids =
7095 		    taskq_req->dr_object_req.or_object_id_ptr;
7096 		uint_t max_object_count =
7097 		    taskq_req->dr_object_req.or_max_object_count;
7098 		dprov_find_ctx_t *find_ctx =
7099 		    taskq_req->dr_object_req.or_find_p;
7100 		uint_t ret_oid_idx;
7101 
7102 		/* return the desired number of object ids */
7103 		for (ret_oid_idx = 0; ret_oid_idx < max_object_count &&
7104 		    find_ctx->fc_next < find_ctx->fc_nids; ret_oid_idx++)
7105 			object_ids[ret_oid_idx] =
7106 			    find_ctx->fc_ids[find_ctx->fc_next++];
7107 
7108 		*taskq_req->dr_object_req.or_object_count_ptr = ret_oid_idx;
7109 
7110 		error = CRYPTO_SUCCESS;
7111 		break;
7112 	}
7113 
7114 	case DPROV_REQ_OBJECT_FIND_FINAL:
7115 		kmem_free(taskq_req->dr_object_req.or_find_p,
7116 		    sizeof (dprov_find_ctx_t));
7117 
7118 		error = CRYPTO_SUCCESS;
7119 		break;
7120 	}
7121 
7122 	mutex_exit(&softc->ds_lock);
7123 	dprov_op_done(taskq_req, error);
7124 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: end\n", instance));
7125 }
7126 
7127 /*
7128  * Copy attribute values into a template. RSA values are precomputed.
7129  */
7130 static int
7131 nostore_copy_attribute(crypto_object_attribute_t *template, uint_t count,
7132     uint64_t attr_type)
7133 {
7134 	void *value, *dprov_attribute_value;
7135 	size_t dprov_attribute_size;
7136 	size_t value_len = 0;
7137 	int error;
7138 
7139 	switch (attr_type) {
7140 	case DPROV_CKA_VALUE:
7141 		dprov_attribute_size = sizeof (dh_value);
7142 		dprov_attribute_value = dh_value;
7143 		break;
7144 
7145 	case DPROV_CKA_MODULUS:
7146 		dprov_attribute_size = sizeof (modulus);
7147 		dprov_attribute_value = modulus;
7148 		break;
7149 
7150 	case DPROV_CKA_PUBLIC_EXPONENT:
7151 		dprov_attribute_size = sizeof (public_exponent);
7152 		dprov_attribute_value = public_exponent;
7153 		break;
7154 
7155 	case DPROV_CKA_PRIVATE_EXPONENT:
7156 		dprov_attribute_size = sizeof (private_exponent);
7157 		dprov_attribute_value = private_exponent;
7158 		break;
7159 
7160 	default:
7161 		return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
7162 	}
7163 
7164 	error = dprov_get_template_attr_array(template, count, attr_type,
7165 	    &value, &value_len);
7166 	if (error != CRYPTO_SUCCESS)
7167 		return (error);
7168 
7169 	if (value_len < dprov_attribute_size)
7170 		return (CRYPTO_BUFFER_TOO_SMALL);
7171 
7172 	/*
7173 	 * The updated template will be returned to libpkcs11.
7174 	 */
7175 	bcopy(dprov_attribute_value, value, dprov_attribute_size);
7176 
7177 	return (CRYPTO_SUCCESS);
7178 }
7179 
7180 static void
7181 fill_dh(void *value, size_t len)
7182 {
7183 	int i = 0;
7184 	char *p = value;
7185 	while (i < len) {
7186 		p[i++] = 'D';
7187 		if (i >= len)
7188 			break;
7189 		p[i++] = 'H';
7190 	}
7191 }
7192 
7193 /*
7194  * taskq dispatcher function for key management operations.
7195  */
7196 static void
7197 dprov_key_task(dprov_req_t *taskq_req)
7198 {
7199 	dprov_state_t *softc;
7200 	/* LINTED E_FUNC_SET_NOT_USED */
7201 	int instance;
7202 	int error = CRYPTO_NOT_SUPPORTED;
7203 	kcf_provider_desc_t *pd;
7204 	crypto_session_id_t session_id = taskq_req->dr_key_req.kr_session_id;
7205 	dprov_session_t *session;
7206 
7207 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
7208 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: started\n", instance));
7209 
7210 	mutex_enter(&softc->ds_lock);
7211 
7212 	/* validate session id and get ptr to session */
7213 	if ((session = softc->ds_sessions[session_id]) == NULL) {
7214 		mutex_exit(&softc->ds_lock);
7215 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
7216 		return;
7217 	}
7218 
7219 	switch (taskq_req->dr_type) {
7220 	case DPROV_REQ_KEY_GENERATE: {
7221 		crypto_mechanism_t *mechp;
7222 		crypto_object_id_t *object_id_ptr;
7223 		crypto_object_attribute_t *template;
7224 		crypto_object_attribute_t attribute;
7225 		uint_t attribute_count;
7226 		ulong_t key_type = ~0UL, class = ~0UL;
7227 		ulong_t value_len;
7228 		size_t key_len = 0;
7229 
7230 		error = CRYPTO_SUCCESS;
7231 
7232 		template = taskq_req->dr_key_req.kr_template;
7233 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7234 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7235 		mechp = taskq_req->dr_key_req.kr_mechanism;
7236 
7237 		/* optional */
7238 		(void) dprov_get_template_attr_ulong(template, attribute_count,
7239 		    DPROV_CKA_CLASS, &class);
7240 
7241 		/* optional */
7242 		(void) dprov_get_template_attr_ulong(template, attribute_count,
7243 		    DPROV_CKA_KEY_TYPE, &key_type);
7244 
7245 		if (class != ~0UL && class != DPROV_CKO_SECRET_KEY) {
7246 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7247 			break;
7248 		}
7249 
7250 		switch (mechp->cm_type) {
7251 		case DES_KEY_GEN_MECH_INFO_TYPE:
7252 			if (key_type != ~0UL && key_type != DPROV_CKK_DES) {
7253 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7254 				break;
7255 			}
7256 			key_len = DES_KEY_LEN;
7257 			key_type = DPROV_CKK_DES;
7258 			break;
7259 
7260 		case DES3_KEY_GEN_MECH_INFO_TYPE:
7261 			if (key_type != ~0UL && key_type != DPROV_CKK_DES3) {
7262 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7263 				break;
7264 			}
7265 			key_len = DES3_KEY_LEN;
7266 			key_type = DPROV_CKK_DES3;
7267 			break;
7268 
7269 		case AES_KEY_GEN_MECH_INFO_TYPE:
7270 			if (key_type != ~0UL && key_type != DPROV_CKK_AES) {
7271 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7272 				break;
7273 			}
7274 			if (dprov_get_template_attr_ulong(template,
7275 			    attribute_count, DPROV_CKA_VALUE_LEN,
7276 			    &value_len) != CRYPTO_SUCCESS) {
7277 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7278 				break;
7279 			}
7280 			if (value_len >= AES_MAX_KEY_LEN) {
7281 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7282 				break;
7283 			}
7284 			key_len = value_len;
7285 			key_type = DPROV_CKK_AES;
7286 			break;
7287 
7288 		case BLOWFISH_KEY_GEN_MECH_INFO_TYPE:
7289 			if (key_type != ~0UL &&
7290 			    key_type != DPROV_CKK_BLOWFISH) {
7291 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7292 				break;
7293 			}
7294 			if (dprov_get_template_attr_ulong(template,
7295 			    attribute_count, DPROV_CKA_VALUE_LEN,
7296 			    &value_len) != CRYPTO_SUCCESS) {
7297 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7298 				break;
7299 			}
7300 			if (value_len >= BLOWFISH_MAX_KEY_LEN) {
7301 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7302 				break;
7303 			}
7304 			key_len = value_len;
7305 			key_type = DPROV_CKK_BLOWFISH;
7306 			break;
7307 
7308 		case RC4_KEY_GEN_MECH_INFO_TYPE:
7309 			if (key_type != ~0UL && key_type != DPROV_CKK_RC4) {
7310 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7311 				break;
7312 			}
7313 			if (dprov_get_template_attr_ulong(template,
7314 			    attribute_count, DPROV_CKA_VALUE_LEN,
7315 			    &value_len) != CRYPTO_SUCCESS) {
7316 				error = CRYPTO_TEMPLATE_INCOMPLETE;
7317 				break;
7318 			}
7319 			if (value_len >=
7320 			    CRYPTO_BITS2BYTES(ARCFOUR_MAX_KEY_BITS)) {
7321 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7322 				break;
7323 			}
7324 			key_len = value_len;
7325 			key_type = DPROV_CKK_RC4;
7326 			break;
7327 
7328 		default:
7329 			error = CRYPTO_MECHANISM_INVALID;
7330 		}
7331 
7332 		if (error != CRYPTO_SUCCESS)
7333 			break;
7334 
7335 		error = dprov_create_object_from_template(softc, session,
7336 		    template, attribute_count, object_id_ptr, B_FALSE, B_TRUE);
7337 
7338 		if (error != CRYPTO_SUCCESS)
7339 			break;
7340 
7341 		/* make sure class is set */
7342 		attribute.oa_type = DPROV_CKA_CLASS;
7343 		attribute.oa_value = (char *)&class;
7344 		attribute.oa_value_len = sizeof (ulong_t);
7345 		error = dprov_object_set_attr(session, *object_id_ptr,
7346 		    &attribute, 1, B_FALSE);
7347 
7348 		if (error != CRYPTO_SUCCESS) {
7349 			goto destroy_object;
7350 		}
7351 
7352 		/* make sure key_type is set */
7353 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
7354 		attribute.oa_value = (char *)&key_type;
7355 		attribute.oa_value_len = sizeof (ulong_t);
7356 		error = dprov_object_set_attr(session, *object_id_ptr,
7357 		    &attribute, 1, B_FALSE);
7358 
7359 		if (error != CRYPTO_SUCCESS) {
7360 			goto destroy_object;
7361 		}
7362 
7363 		attribute.oa_type = DPROV_CKA_VALUE;
7364 		attribute.oa_value = kmem_alloc(key_len, KM_SLEEP);
7365 		attribute.oa_value_len = key_len;
7366 
7367 		if (random_get_pseudo_bytes((uchar_t *)attribute.oa_value,
7368 		    key_len) != 0) {
7369 			bzero(attribute.oa_value, key_len);
7370 			kmem_free(attribute.oa_value, key_len);
7371 			goto destroy_object;
7372 		}
7373 		error = dprov_object_set_attr(session, *object_id_ptr,
7374 		    &attribute, 1, B_FALSE);
7375 
7376 		bzero(attribute.oa_value, key_len);
7377 		kmem_free(attribute.oa_value, key_len);
7378 
7379 		if (error != CRYPTO_SUCCESS) {
7380 			goto destroy_object;
7381 		}
7382 		break;
7383 
7384 destroy_object:
7385 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
7386 		break;
7387 	}
7388 
7389 	case DPROV_REQ_KEY_GENERATE_PAIR: {
7390 		crypto_mechanism_t *mechp;
7391 		crypto_object_id_t *pub_object_id_ptr;
7392 		crypto_object_id_t *pri_object_id_ptr;
7393 		crypto_object_attribute_t *pub_template;
7394 		crypto_object_attribute_t *pri_template;
7395 		crypto_object_attribute_t attribute;
7396 		uint_t pub_attribute_count;
7397 		uint_t pri_attribute_count;
7398 		ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
7399 		ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
7400 
7401 		pub_template = taskq_req->dr_key_req.kr_template;
7402 		pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7403 		pub_object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7404 		pri_template = taskq_req->dr_key_req.kr_private_key_template;
7405 		pri_attribute_count =
7406 		    taskq_req->dr_key_req.kr_private_key_attribute_count;
7407 		pri_object_id_ptr =
7408 		    taskq_req->dr_key_req.kr_private_key_object_id_ptr;
7409 		mechp = taskq_req->dr_key_req.kr_mechanism;
7410 
7411 		error = CRYPTO_SUCCESS;
7412 
7413 		/* optional */
7414 		(void) dprov_get_template_attr_ulong(pub_template,
7415 		    pub_attribute_count, DPROV_CKA_CLASS, &pub_class);
7416 
7417 		/* optional */
7418 		(void) dprov_get_template_attr_ulong(pri_template,
7419 		    pri_attribute_count, DPROV_CKA_CLASS, &pri_class);
7420 
7421 		/* optional */
7422 		(void) dprov_get_template_attr_ulong(pub_template,
7423 		    pub_attribute_count, DPROV_CKA_KEY_TYPE, &pub_key_type);
7424 
7425 		/* optional */
7426 		(void) dprov_get_template_attr_ulong(pri_template,
7427 		    pri_attribute_count, DPROV_CKA_KEY_TYPE, &pri_key_type);
7428 
7429 		if (pub_class != ~0UL && pub_class != DPROV_CKO_PUBLIC_KEY) {
7430 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7431 			break;
7432 		}
7433 
7434 		if (pri_class != ~0UL && pri_class != DPROV_CKO_PRIVATE_KEY) {
7435 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7436 			break;
7437 		}
7438 
7439 		switch (mechp->cm_type) {
7440 		case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
7441 			if (pub_key_type != ~0UL &&
7442 			    pub_key_type != DPROV_CKK_RSA) {
7443 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7444 				break;
7445 			}
7446 			pub_key_type = DPROV_CKK_RSA;
7447 
7448 			if (pri_key_type != ~0UL &&
7449 			    pri_key_type != DPROV_CKK_RSA) {
7450 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7451 				break;
7452 			}
7453 			pri_key_type = DPROV_CKK_RSA;
7454 
7455 			if (pub_class != ~0UL &&
7456 			    pub_class != DPROV_CKO_PUBLIC_KEY) {
7457 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7458 				break;
7459 			}
7460 			pub_class = DPROV_CKO_PUBLIC_KEY;
7461 
7462 			if (pri_class != ~0UL &&
7463 			    pri_class != DPROV_CKO_PRIVATE_KEY) {
7464 				error = CRYPTO_TEMPLATE_INCONSISTENT;
7465 				break;
7466 			}
7467 			pri_class = DPROV_CKO_PRIVATE_KEY;
7468 			break;
7469 
7470 		default:
7471 			error = CRYPTO_MECHANISM_INVALID;
7472 		}
7473 
7474 		if (error != CRYPTO_SUCCESS)
7475 			break;
7476 
7477 		error = dprov_create_object_from_template(softc, session,
7478 		    pub_template, pub_attribute_count, pub_object_id_ptr,
7479 		    B_FALSE, B_TRUE);
7480 
7481 		if (error != CRYPTO_SUCCESS)
7482 			break;
7483 
7484 		/* make sure class is set */
7485 		attribute.oa_type = DPROV_CKA_CLASS;
7486 		attribute.oa_value = (char *)&pub_class;
7487 		attribute.oa_value_len = sizeof (ulong_t);
7488 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7489 		    &attribute, 1, B_FALSE);
7490 
7491 		if (error != CRYPTO_SUCCESS) {
7492 			goto destroy_public_object;
7493 		}
7494 
7495 		/* make sure key_type is set */
7496 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
7497 		attribute.oa_value = (char *)&pub_key_type;
7498 		attribute.oa_value_len = sizeof (ulong_t);
7499 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7500 		    &attribute, 1, B_FALSE);
7501 
7502 		if (error != CRYPTO_SUCCESS) {
7503 			goto destroy_public_object;
7504 		}
7505 
7506 		attribute.oa_type = DPROV_CKA_MODULUS;
7507 		attribute.oa_value = (char *)modulus;
7508 		attribute.oa_value_len = sizeof (modulus);
7509 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7510 		    &attribute, 1, B_FALSE);
7511 
7512 		if (error != CRYPTO_SUCCESS) {
7513 			goto destroy_public_object;
7514 		}
7515 
7516 		attribute.oa_type = DPROV_CKA_PUBLIC_EXPONENT;
7517 		attribute.oa_value = public_exponent;
7518 		attribute.oa_value_len = sizeof (public_exponent);
7519 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
7520 		    &attribute, 1, B_FALSE);
7521 
7522 		if (error != CRYPTO_SUCCESS) {
7523 			goto destroy_public_object;
7524 		}
7525 
7526 		error = dprov_create_object_from_template(softc, session,
7527 		    pri_template, pri_attribute_count, pri_object_id_ptr,
7528 		    B_FALSE, B_TRUE);
7529 
7530 		if (error != CRYPTO_SUCCESS)
7531 			break;
7532 
7533 		/* make sure class is set */
7534 		attribute.oa_type = DPROV_CKA_CLASS;
7535 		attribute.oa_value = (char *)&pri_class;
7536 		attribute.oa_value_len = sizeof (ulong_t);
7537 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7538 		    &attribute, 1, B_FALSE);
7539 
7540 		if (error != CRYPTO_SUCCESS) {
7541 			goto destroy_private_object;
7542 		}
7543 
7544 		/* make sure key_type is set */
7545 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
7546 		attribute.oa_value = (char *)&pri_key_type;
7547 		attribute.oa_value_len = sizeof (ulong_t);
7548 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7549 		    &attribute, 1, B_FALSE);
7550 
7551 		if (error != CRYPTO_SUCCESS) {
7552 			goto destroy_private_object;
7553 		}
7554 
7555 		attribute.oa_type = DPROV_CKA_MODULUS;
7556 		attribute.oa_value = (char *)modulus;
7557 		attribute.oa_value_len = sizeof (modulus);
7558 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7559 		    &attribute, 1, B_FALSE);
7560 
7561 		if (error != CRYPTO_SUCCESS) {
7562 			goto destroy_private_object;
7563 		}
7564 
7565 		attribute.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
7566 		attribute.oa_value = (char *)private_exponent;
7567 		attribute.oa_value_len = sizeof (private_exponent);
7568 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
7569 		    &attribute, 1, B_FALSE);
7570 
7571 		if (error != CRYPTO_SUCCESS) {
7572 			goto destroy_private_object;
7573 		}
7574 		break;
7575 
7576 destroy_private_object:
7577 		(void) dprov_destroy_object(softc, session,
7578 		    *pri_object_id_ptr);
7579 destroy_public_object:
7580 		(void) dprov_destroy_object(softc, session,
7581 		    *pub_object_id_ptr);
7582 
7583 		break;
7584 	}
7585 
7586 	case DPROV_REQ_KEY_WRAP: {
7587 		crypto_mechanism_t mech, *mechp;
7588 		crypto_key_t key, *keyp;
7589 		crypto_object_id_t object_id;
7590 		ulong_t class = DPROV_CKO_DATA;
7591 		boolean_t extractable = B_TRUE;
7592 		dprov_object_t *object;
7593 		int object_idx;
7594 		char *plaintext_key;
7595 		size_t plaintext_key_len;
7596 		crypto_data_t plaintext;
7597 		crypto_data_t ciphertext;
7598 		size_t *lenp;
7599 
7600 		mechp = taskq_req->dr_key_req.kr_mechanism;
7601 		/* structure assignment */
7602 		mech = *mechp;
7603 
7604 		/* get wrapping key value */
7605 		if (is_publickey_mech(mech.cm_type)) {
7606 			if ((error = dprov_key_attr_asymmetric(softc,
7607 			    session_id, taskq_req->dr_type,
7608 			    taskq_req->dr_key_req.kr_key,
7609 			    &key)) != CRYPTO_SUCCESS)
7610 				break;
7611 			keyp = &key;
7612 		} else {
7613 			if ((error = dprov_key_value_secret(softc,
7614 			    session_id, taskq_req->dr_type,
7615 			    taskq_req->dr_key_req.kr_key,
7616 			    &key)) != CRYPTO_SUCCESS)
7617 				break;
7618 			keyp = &key;
7619 		}
7620 
7621 		/* get the software provider for this mechanism */
7622 		if ((error = dprov_get_sw_prov(mechp, &pd,
7623 		    &mech.cm_type)) != CRYPTO_SUCCESS)
7624 			break;
7625 
7626 		object_id = *taskq_req->dr_key_req.kr_object_id_ptr;
7627 		if (object_id >= DPROV_MAX_OBJECTS) {
7628 			error = CRYPTO_KEY_HANDLE_INVALID;
7629 			break;
7630 		}
7631 
7632 		/* get ptr to object */
7633 		if ((object = session->ds_objects[object_id]) == NULL) {
7634 			error = CRYPTO_OBJECT_HANDLE_INVALID;
7635 			break;
7636 		}
7637 
7638 		(void) dprov_get_object_attr_boolean(object,
7639 		    DPROV_CKA_EXTRACTABLE, &extractable);
7640 
7641 		if (!extractable) {
7642 			error = CRYPTO_ATTRIBUTE_SENSITIVE;
7643 			break;
7644 		}
7645 
7646 		(void) dprov_get_object_attr_ulong(object,
7647 		    DPROV_CKA_CLASS, &class);
7648 
7649 		switch (class) {
7650 		case DPROV_CKO_SECRET_KEY:
7651 			object_idx = dprov_find_attr(object->do_attr,
7652 			    DPROV_MAX_ATTR, DPROV_CKA_VALUE);
7653 			if (object_idx == -1) {
7654 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7655 				break;
7656 			}
7657 			break;
7658 
7659 			case DPROV_CKO_PRIVATE_KEY:
7660 			/*
7661 			 * PKCS#11 says that ASN.1 should be used to encode
7662 			 * specific attributes before encrypting the blob.
7663 			 * We only encrypt the private exponent for the
7664 			 * purpose of testing.
7665 			 */
7666 			object_idx = dprov_find_attr(object->do_attr,
7667 			    DPROV_MAX_ATTR, DPROV_CKA_PRIVATE_EXPONENT);
7668 			if (object_idx == -1) {
7669 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7670 				break;
7671 			}
7672 			break;
7673 		default:
7674 			error = CRYPTO_KEY_NOT_WRAPPABLE;
7675 			break;
7676 		}
7677 		if (error != CRYPTO_SUCCESS)
7678 			break;
7679 
7680 		plaintext_key = object->do_attr[object_idx].oa_value;
7681 		plaintext_key_len = object->do_attr[object_idx].oa_value_len;
7682 		lenp = taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7683 
7684 		/* session id is 0 for software provider */
7685 		plaintext.cd_format = CRYPTO_DATA_RAW;
7686 		plaintext.cd_offset = 0;
7687 		plaintext.cd_length = plaintext_key_len;
7688 		plaintext.cd_raw.iov_base = plaintext_key;
7689 		plaintext.cd_raw.iov_len = plaintext_key_len;
7690 		plaintext.cd_miscdata = NULL;
7691 
7692 		ciphertext.cd_format = CRYPTO_DATA_RAW;
7693 		ciphertext.cd_offset = 0;
7694 		ciphertext.cd_length = *lenp;
7695 		ciphertext.cd_raw.iov_base =
7696 		    (char *)taskq_req->dr_key_req.kr_wrapped_key;
7697 		ciphertext.cd_raw.iov_len = ciphertext.cd_length;
7698 		ciphertext.cd_miscdata = NULL;
7699 
7700 		error = crypto_encrypt_prov(pd, 0, &mech, &plaintext, keyp,
7701 		    NULL, &ciphertext, NULL);
7702 
7703 		KCF_PROV_REFRELE(pd);
7704 		if (error == CRYPTO_SUCCESS ||
7705 		    error == CRYPTO_BUFFER_TOO_SMALL) {
7706 			*lenp = ciphertext.cd_length;
7707 		}
7708 		break;
7709 	}
7710 
7711 	case DPROV_REQ_KEY_UNWRAP: {
7712 		crypto_mechanism_t mech, *mechp;
7713 		crypto_key_t key, *keyp;
7714 		crypto_object_id_t *object_id_ptr;
7715 		ulong_t class = DPROV_CKO_DATA;
7716 		uchar_t *wrapped_key;
7717 		char *plaintext_buf;
7718 		size_t wrapped_key_len;
7719 		crypto_data_t plaintext;
7720 		crypto_data_t ciphertext;
7721 		crypto_object_attribute_t unwrapped_key;
7722 		crypto_object_attribute_t *template;
7723 		uint_t attribute_count;
7724 
7725 		template = taskq_req->dr_key_req.kr_template;
7726 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7727 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7728 
7729 		/* all objects must have an object class attribute */
7730 		if (dprov_get_template_attr_ulong(template, attribute_count,
7731 		    DPROV_CKA_CLASS, &class) != CRYPTO_SUCCESS) {
7732 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7733 			break;
7734 		}
7735 
7736 		mechp = taskq_req->dr_key_req.kr_mechanism;
7737 		/* structure assignment */
7738 		mech = *mechp;
7739 
7740 		/* get unwrapping key value */
7741 		if (is_publickey_mech(mech.cm_type)) {
7742 			if ((error = dprov_key_attr_asymmetric(softc,
7743 			    session_id, taskq_req->dr_type,
7744 			    taskq_req->dr_key_req.kr_key,
7745 			    &key)) != CRYPTO_SUCCESS)
7746 				break;
7747 			keyp = &key;
7748 		} else {
7749 			if ((error = dprov_key_value_secret(softc,
7750 			    session_id, taskq_req->dr_type,
7751 			    taskq_req->dr_key_req.kr_key,
7752 			    &key)) != CRYPTO_SUCCESS)
7753 				break;
7754 			keyp = &key;
7755 		}
7756 
7757 		/* get the software provider for this mechanism */
7758 		if ((error = dprov_get_sw_prov(mechp, &pd,
7759 		    &mech.cm_type)) != CRYPTO_SUCCESS)
7760 			break;
7761 
7762 		wrapped_key = taskq_req->dr_key_req.kr_wrapped_key;
7763 		wrapped_key_len = *taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7764 		ciphertext.cd_format = CRYPTO_DATA_RAW;
7765 		ciphertext.cd_offset = 0;
7766 		ciphertext.cd_length = wrapped_key_len;
7767 		ciphertext.cd_raw.iov_base = (char *)wrapped_key;
7768 		ciphertext.cd_raw.iov_len = wrapped_key_len;
7769 		ciphertext.cd_miscdata = NULL;
7770 
7771 		/*
7772 		 * Plaintext length is less than or equal to
7773 		 * the length of the ciphertext.
7774 		 */
7775 		plaintext_buf = kmem_alloc(wrapped_key_len, KM_SLEEP);
7776 		plaintext.cd_format = CRYPTO_DATA_RAW;
7777 		plaintext.cd_offset = 0;
7778 		plaintext.cd_length = wrapped_key_len;
7779 		plaintext.cd_raw.iov_base = plaintext_buf;
7780 		plaintext.cd_raw.iov_len = wrapped_key_len;
7781 		plaintext.cd_miscdata = NULL;
7782 
7783 		error = crypto_decrypt_prov(pd, 0, &mech, &ciphertext, keyp,
7784 		    NULL, &plaintext, NULL);
7785 
7786 		KCF_PROV_REFRELE(pd);
7787 
7788 		if (error != CRYPTO_SUCCESS)
7789 			goto free_unwrapped_key;
7790 
7791 		error = dprov_create_object_from_template(softc, session,
7792 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7793 
7794 		if (error != CRYPTO_SUCCESS)
7795 			goto free_unwrapped_key;
7796 
7797 		switch (class) {
7798 		case DPROV_CKO_SECRET_KEY:
7799 			unwrapped_key.oa_type = DPROV_CKA_VALUE;
7800 			unwrapped_key.oa_value_len = plaintext.cd_length;
7801 			unwrapped_key.oa_value = plaintext_buf;
7802 			break;
7803 		case DPROV_CKO_PRIVATE_KEY:
7804 			/*
7805 			 * PKCS#11 says that ASN.1 should be used to encode
7806 			 * specific attributes before encrypting the blob.
7807 			 * We only encrypt the private exponent for the
7808 			 * purpose of testing.
7809 			 */
7810 			unwrapped_key.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
7811 			unwrapped_key.oa_value_len = plaintext.cd_length;
7812 			unwrapped_key.oa_value = plaintext_buf;
7813 			break;
7814 		default:
7815 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7816 			goto free_unwrapped_key;
7817 		}
7818 
7819 		if ((error = dprov_object_set_attr(session, *object_id_ptr,
7820 		    &unwrapped_key, 1, B_FALSE)) == CRYPTO_SUCCESS)
7821 			break;	/* don't free the unwrapped key */
7822 
7823 		/* failure */
7824 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
7825 		break;
7826 
7827 free_unwrapped_key:
7828 		bzero(plaintext_buf, wrapped_key_len);
7829 		kmem_free(plaintext_buf, wrapped_key_len);
7830 		break;
7831 	}
7832 
7833 	case DPROV_REQ_KEY_DERIVE: {
7834 		crypto_mechanism_t digest_mech, *mechp;
7835 		crypto_key_t key, *base_keyp;
7836 		crypto_object_id_t *object_id_ptr;
7837 		crypto_data_t data;
7838 		crypto_data_t digest;
7839 		size_t hash_size;
7840 		char *digest_buf;
7841 		crypto_object_attribute_t derived_key;
7842 		crypto_object_attribute_t *template;
7843 		uint_t attribute_count;
7844 		ulong_t key_type;
7845 		void *value;
7846 		size_t value_len = 0;
7847 
7848 		error = CRYPTO_SUCCESS;
7849 
7850 		template = taskq_req->dr_key_req.kr_template;
7851 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7852 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7853 
7854 		/* required */
7855 		if (dprov_get_template_attr_ulong(template, attribute_count,
7856 		    DPROV_CKA_KEY_TYPE, &key_type) != CRYPTO_SUCCESS) {
7857 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7858 			break;
7859 		}
7860 
7861 		mechp = taskq_req->dr_key_req.kr_mechanism;
7862 		/* structure assignment */
7863 		digest_mech = *mechp;
7864 
7865 		switch (digest_mech.cm_type) {
7866 		case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:
7867 			hash_size = SHA1_DIGEST_LEN;
7868 			digest_mech.cm_type = SHA1_MECH_INFO_TYPE;
7869 			break;
7870 
7871 		case SHA256_KEY_DERIVATION_MECH_INFO_TYPE:
7872 			hash_size = SHA256_DIGEST_LENGTH;
7873 			digest_mech.cm_type = SHA256_MECH_INFO_TYPE;
7874 			break;
7875 
7876 		case SHA384_KEY_DERIVATION_MECH_INFO_TYPE:
7877 			hash_size = SHA384_DIGEST_LENGTH;
7878 			digest_mech.cm_type = SHA384_MECH_INFO_TYPE;
7879 			break;
7880 
7881 		case SHA512_KEY_DERIVATION_MECH_INFO_TYPE:
7882 			hash_size = SHA512_DIGEST_LENGTH;
7883 			digest_mech.cm_type = SHA512_MECH_INFO_TYPE;
7884 			break;
7885 
7886 		case MD5_KEY_DERIVATION_MECH_INFO_TYPE:
7887 			hash_size = MD5_DIGEST_LEN;
7888 			digest_mech.cm_type = MD5_MECH_INFO_TYPE;
7889 			break;
7890 
7891 		default:
7892 			error = CRYPTO_MECHANISM_INVALID;
7893 		}
7894 
7895 		if (error != CRYPTO_SUCCESS)
7896 			break;
7897 
7898 		/* CKA_VALUE is optional */
7899 		(void) dprov_get_template_attr_array(template, attribute_count,
7900 		    DPROV_CKA_VALUE, &value, &value_len);
7901 
7902 		/* check for inconsistent value length */
7903 		switch (key_type) {
7904 		case DPROV_CKK_GENERIC_SECRET:
7905 			if (value_len > 0) {
7906 				if (value_len > hash_size)
7907 					error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7908 			} else {
7909 				value_len = hash_size;
7910 			}
7911 			break;
7912 
7913 		case DPROV_CKK_RC4:
7914 		case DPROV_CKK_AES:
7915 			if (value_len == 0 ||
7916 			    value_len > hash_size) {
7917 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7918 			}
7919 			break;
7920 
7921 		case DPROV_CKK_DES:
7922 			if (value_len > 0 &&
7923 			    value_len != DES_KEY_LEN) {
7924 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7925 			}
7926 			value_len = DES_KEY_LEN;
7927 			break;
7928 
7929 		case DPROV_CKK_DES3:
7930 			if (value_len > 0 &&
7931 			    value_len != DES3_KEY_LEN) {
7932 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7933 			}
7934 			value_len = DES3_KEY_LEN;
7935 			break;
7936 
7937 		default:
7938 			error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7939 			break;
7940 		}
7941 
7942 		if (error != CRYPTO_SUCCESS)
7943 			break;
7944 
7945 		/* get the software provider for this mechanism */
7946 		if ((error = dprov_get_sw_prov(&digest_mech, &pd,
7947 		    &digest_mech.cm_type)) != CRYPTO_SUCCESS)
7948 			break;
7949 
7950 		/* get the base key */
7951 		error = dprov_key_value_secret(softc, session_id,
7952 		    taskq_req->dr_type, taskq_req->dr_key_req.kr_key, &key);
7953 		if (error != CRYPTO_SUCCESS)
7954 			break;
7955 
7956 		base_keyp = &key;
7957 
7958 		data.cd_format = CRYPTO_DATA_RAW;
7959 		data.cd_offset = 0;
7960 		data.cd_length = CRYPTO_BITS2BYTES(base_keyp->ck_length);
7961 		data.cd_raw.iov_base = base_keyp->ck_data;
7962 		data.cd_raw.iov_len = data.cd_length;
7963 
7964 		digest_buf = kmem_alloc(hash_size, KM_SLEEP);
7965 		digest.cd_format = CRYPTO_DATA_RAW;
7966 		digest.cd_offset = 0;
7967 		digest.cd_length = hash_size;
7968 		digest.cd_raw.iov_base = digest_buf;
7969 		digest.cd_raw.iov_len = hash_size;
7970 
7971 		error = crypto_digest_prov(pd, 0, &digest_mech, &data,
7972 		    &digest, NULL);
7973 
7974 		KCF_PROV_REFRELE(pd);
7975 
7976 		if (error != CRYPTO_SUCCESS)
7977 			goto free_derived_key;
7978 
7979 		error = dprov_create_object_from_template(softc, session,
7980 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7981 
7982 		if (error != CRYPTO_SUCCESS)
7983 			goto free_derived_key;
7984 
7985 		derived_key.oa_type = DPROV_CKA_VALUE;
7986 		derived_key.oa_value = digest_buf;
7987 		derived_key.oa_value_len = value_len;
7988 
7989 		error = dprov_object_set_attr(session, *object_id_ptr,
7990 		    &derived_key, 1, B_FALSE);
7991 
7992 		if (error != CRYPTO_SUCCESS) {
7993 			(void) dprov_destroy_object(softc, session,
7994 			    *object_id_ptr);
7995 		}
7996 
7997 free_derived_key:
7998 		bzero(digest_buf, hash_size);
7999 		kmem_free(digest_buf, hash_size);
8000 		break;
8001 	}
8002 
8003 	case DPROV_REQ_NOSTORE_KEY_GENERATE: {
8004 		crypto_object_attribute_t *out_template;
8005 		uint_t out_attribute_count;
8006 		void *value;
8007 		size_t value_len = 0;
8008 
8009 		out_template = taskq_req->dr_key_req.kr_out_template1;
8010 		out_attribute_count =
8011 		    taskq_req->dr_key_req.kr_out_attribute_count1;
8012 
8013 		error = dprov_get_template_attr_array(out_template,
8014 		    out_attribute_count, DPROV_CKA_VALUE, &value, &value_len);
8015 		if (error != CRYPTO_SUCCESS)
8016 			break;
8017 
8018 		/* fill the entire array with pattern */
8019 		{
8020 			int i = 0;
8021 			char *p = value;
8022 			while (i < value_len) {
8023 				p[i++] = 'A';
8024 				if (i >= value_len)
8025 					break;
8026 				p[i++] = 'B';
8027 				if (i >= value_len)
8028 					break;
8029 				p[i++] = 'C';
8030 			}
8031 		}
8032 
8033 		error = CRYPTO_SUCCESS;
8034 		break;
8035 	}
8036 
8037 	case DPROV_REQ_NOSTORE_KEY_GENERATE_PAIR: {
8038 		crypto_mechanism_t *mechp;
8039 		crypto_object_attribute_t *pub_template;
8040 		crypto_object_attribute_t *pri_template;
8041 		uint_t pub_attribute_count;
8042 		uint_t pri_attribute_count;
8043 		crypto_object_attribute_t *out_pub_template;
8044 		crypto_object_attribute_t *out_pri_template;
8045 		uint_t out_pub_attribute_count;
8046 		uint_t out_pri_attribute_count;
8047 
8048 		mechp = taskq_req->dr_key_req.kr_mechanism;
8049 		pub_template = taskq_req->dr_key_req.kr_template;
8050 		pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
8051 		pri_template = taskq_req->dr_key_req.kr_private_key_template;
8052 		pri_attribute_count =
8053 		    taskq_req->dr_key_req.kr_private_key_attribute_count;
8054 		out_pub_template = taskq_req->dr_key_req.kr_out_template1;
8055 		out_pub_attribute_count =
8056 		    taskq_req->dr_key_req.kr_out_attribute_count1;
8057 		out_pri_template = taskq_req->dr_key_req.kr_out_template2;
8058 		out_pri_attribute_count =
8059 		    taskq_req->dr_key_req.kr_out_attribute_count2;
8060 
8061 		switch (mechp->cm_type) {
8062 		case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
8063 			error = nostore_copy_attribute(out_pub_template,
8064 			    out_pub_attribute_count, DPROV_CKA_MODULUS);
8065 			if (error != CRYPTO_SUCCESS)
8066 				break;
8067 
8068 			error = nostore_copy_attribute(out_pub_template,
8069 			    out_pub_attribute_count, DPROV_CKA_PUBLIC_EXPONENT);
8070 			if (error == CRYPTO_ARGUMENTS_BAD) {
8071 				size_t tmp_len = 0;
8072 				void *tmp;
8073 
8074 				/* public exponent must be here */
8075 				error = dprov_get_template_attr_array(
8076 				    pub_template, pub_attribute_count,
8077 				    DPROV_CKA_PUBLIC_EXPONENT, &tmp, &tmp_len);
8078 				if (error != CRYPTO_SUCCESS)
8079 					break;
8080 			}
8081 			error = nostore_copy_attribute(out_pri_template,
8082 			    out_pri_attribute_count, DPROV_CKA_MODULUS);
8083 			if (error != CRYPTO_SUCCESS)
8084 				break;
8085 
8086 			error = nostore_copy_attribute(out_pri_template,
8087 			    out_pri_attribute_count,
8088 			    DPROV_CKA_PRIVATE_EXPONENT);
8089 			break;
8090 
8091 		case DH_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
8092 			/*
8093 			 * There is no software provider for DH mechanism;
8094 			 * Just return pre-defined values.
8095 			 */
8096 			error = nostore_copy_attribute(out_pub_template,
8097 			    out_pub_attribute_count, DPROV_CKA_VALUE);
8098 			error = nostore_copy_attribute(out_pri_template,
8099 			    out_pri_attribute_count, DPROV_CKA_VALUE);
8100 			break;
8101 
8102 		case EC_KEY_PAIR_GEN_MECH_INFO_TYPE: {
8103 			crypto_mechanism_t mech, *mechp;
8104 			kcf_req_params_t params;
8105 			crypto_object_attribute_t *pub_template;
8106 			uint_t pub_attribute_count;
8107 			crypto_object_attribute_t *out_pub_template;
8108 			crypto_object_attribute_t *out_pri_template;
8109 			uint_t out_pub_attribute_count;
8110 			uint_t out_pri_attribute_count;
8111 
8112 			mechp = taskq_req->dr_key_req.kr_mechanism;
8113 			pub_template = taskq_req->dr_key_req.kr_template;
8114 			pub_attribute_count =
8115 			    taskq_req->dr_key_req.kr_attribute_count;
8116 			out_pub_template =
8117 			    taskq_req->dr_key_req.kr_out_template1;
8118 			out_pub_attribute_count =
8119 			    taskq_req->dr_key_req.kr_out_attribute_count1;
8120 			out_pri_template =
8121 			    taskq_req->dr_key_req.kr_out_template2;
8122 			out_pri_attribute_count =
8123 			    taskq_req->dr_key_req.kr_out_attribute_count2;
8124 
8125 			/* get the software provider for this mechanism */
8126 			mech = *mechp;
8127 			if ((error = dprov_get_sw_prov(mechp, &pd,
8128 			    &mech.cm_type)) != CRYPTO_SUCCESS)
8129 				break;
8130 			/*
8131 			 * Turn 32-bit values into 64-bit values for certain
8132 			 * attributes like CKA_CLASS.
8133 			 */
8134 			dprov_adjust_attrs(pub_template, pub_attribute_count);
8135 			dprov_adjust_attrs(pri_template, pri_attribute_count);
8136 
8137 			/* bypass the kernel API for now */
8138 			KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params,
8139 			    KCF_OP_KEY_GENERATE_PAIR,
8140 			    0, /* session 0 for sw provider */
8141 			    &mech, pub_template, pub_attribute_count,
8142 			    pri_template, pri_attribute_count, NULL,
8143 			    out_pub_template, out_pub_attribute_count,
8144 			    out_pri_template, out_pri_attribute_count);
8145 
8146 			error = kcf_submit_request(pd, NULL, NULL, &params,
8147 			    B_FALSE);
8148 
8149 			KCF_PROV_REFRELE(pd);
8150 			break;
8151 		}
8152 		default:
8153 			error = CRYPTO_MECHANISM_INVALID;
8154 		}
8155 		break;
8156 	}
8157 
8158 	case DPROV_REQ_NOSTORE_KEY_DERIVE: {
8159 		crypto_mechanism_t *mechp;
8160 		crypto_object_attribute_t *in_template, *out_template;
8161 		crypto_key_t *base_key;
8162 		uint_t in_attribute_count, out_attribute_count;
8163 		ulong_t key_type;
8164 		void *value;
8165 		size_t value_len = 0;
8166 		size_t value_len_value = 0;
8167 
8168 		in_template = taskq_req->dr_key_req.kr_template;
8169 		out_template = taskq_req->dr_key_req.kr_out_template1;
8170 		in_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
8171 		out_attribute_count =
8172 		    taskq_req->dr_key_req.kr_out_attribute_count1;
8173 		mechp = taskq_req->dr_key_req.kr_mechanism;
8174 		base_key = taskq_req->dr_key_req.kr_key;
8175 
8176 		/*
8177 		 * CKA_VALUE must be present so the derived key can
8178 		 * be returned by value.
8179 		 */
8180 		if (dprov_get_template_attr_array(out_template,
8181 		    out_attribute_count, DPROV_CKA_VALUE, &value,
8182 		    &value_len) != CRYPTO_SUCCESS) {
8183 			error = CRYPTO_TEMPLATE_INCOMPLETE;
8184 			break;
8185 		}
8186 
8187 		if (dprov_get_template_attr_ulong(in_template,
8188 		    in_attribute_count, DPROV_CKA_KEY_TYPE,
8189 		    &key_type) != CRYPTO_SUCCESS) {
8190 			error = CRYPTO_TEMPLATE_INCOMPLETE;
8191 			break;
8192 		}
8193 		switch (mechp->cm_type) {
8194 		case DH_PKCS_DERIVE_MECH_INFO_TYPE: {
8195 			size_t tmp_len = 0;
8196 			void *tmp;
8197 
8198 			if (base_key->ck_format != CRYPTO_KEY_ATTR_LIST) {
8199 				error = CRYPTO_ARGUMENTS_BAD;
8200 				break;
8201 			}
8202 
8203 			if ((dprov_get_template_attr_array(base_key->ck_attrs,
8204 			    base_key->ck_count, DPROV_CKA_BASE, &tmp,
8205 			    &tmp_len) != CRYPTO_SUCCESS) ||
8206 			    (dprov_get_template_attr_array(base_key->ck_attrs,
8207 			    base_key->ck_count, DPROV_CKA_PRIME, &tmp,
8208 			    &tmp_len) != CRYPTO_SUCCESS) ||
8209 			    (dprov_get_template_attr_array(base_key->ck_attrs,
8210 			    base_key->ck_count, DPROV_CKA_VALUE, &tmp,
8211 			    &tmp_len) != CRYPTO_SUCCESS)) {
8212 				error = CRYPTO_TEMPLATE_INCOMPLETE;
8213 				break;
8214 			}
8215 
8216 			/*
8217 			 * CKA_VALUE is added to the derived key template by
8218 			 * the library.
8219 			 */
8220 			error = CRYPTO_SUCCESS;
8221 			switch (key_type) {
8222 			case DPROV_CKK_AES:
8223 				if (dprov_get_template_attr_ulong(in_template,
8224 				    in_attribute_count, DPROV_CKA_VALUE_LEN,
8225 				    &value_len_value) != CRYPTO_SUCCESS) {
8226 					error = CRYPTO_TEMPLATE_INCOMPLETE;
8227 					break;
8228 				}
8229 				if (value_len != value_len_value) {
8230 					error = CRYPTO_TEMPLATE_INCONSISTENT;
8231 					break;
8232 				}
8233 			default:
8234 				error = CRYPTO_MECHANISM_INVALID;
8235 			}
8236 			if (error == CRYPTO_SUCCESS)
8237 				fill_dh(value, value_len);
8238 			break;
8239 		}
8240 		case ECDH1_DERIVE_MECH_INFO_TYPE: {
8241 			crypto_mechanism_t mech;
8242 			kcf_req_params_t params;
8243 
8244 			/* get the software provider for this mechanism */
8245 			mech = *mechp;
8246 			if ((error = dprov_get_sw_prov(mechp, &pd,
8247 			    &mech.cm_type)) != CRYPTO_SUCCESS)
8248 				break;
8249 
8250 			/*
8251 			 * Turn 32-bit values into 64-bit values for certain
8252 			 * attributes like CKA_VALUE_LEN.
8253 			 */
8254 			dprov_adjust_attrs(in_template, in_attribute_count);
8255 
8256 			/* bypass the kernel API for now */
8257 			KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params,
8258 			    KCF_OP_KEY_DERIVE,
8259 			    0, /* session 0 for sw provider */
8260 			    &mech, in_template, in_attribute_count,
8261 			    NULL, 0, base_key,
8262 			    out_template, out_attribute_count,
8263 			    NULL, 0);
8264 
8265 			error = kcf_submit_request(pd, NULL, NULL, &params,
8266 			    B_FALSE);
8267 
8268 			KCF_PROV_REFRELE(pd);
8269 			break;
8270 		}
8271 
8272 		default:
8273 			error = CRYPTO_MECHANISM_INVALID;
8274 		}
8275 		break;
8276 	default:
8277 		error = CRYPTO_MECHANISM_INVALID;
8278 	}
8279 	} /* end case */
8280 
8281 	mutex_exit(&softc->ds_lock);
8282 	dprov_op_done(taskq_req, error);
8283 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: end\n", instance));
8284 }
8285 
8286 /*
8287  * taskq dispatcher function for provider management operations.
8288  */
8289 static void
8290 dprov_mgmt_task(dprov_req_t *taskq_req)
8291 {
8292 	dprov_state_t *softc;
8293 	/* LINTED E_FUNC_SET_NOT_USED */
8294 	int instance;
8295 	int error = CRYPTO_NOT_SUPPORTED;
8296 
8297 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
8298 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: started\n", instance));
8299 
8300 	mutex_enter(&softc->ds_lock);
8301 
8302 	switch (taskq_req->dr_type) {
8303 	case DPROV_REQ_MGMT_EXTINFO: {
8304 		crypto_provider_ext_info_t *ext_info =
8305 		    taskq_req->dr_mgmt_req.mr_ext_info;
8306 
8307 		(void) memset(ext_info->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
8308 		if (!softc->ds_token_initialized) {
8309 			bcopy("(not initialized)", ext_info->ei_label,
8310 			    strlen("(not initialized)"));
8311 		} else {
8312 			bcopy(softc->ds_label, ext_info->ei_label,
8313 			    CRYPTO_EXT_SIZE_LABEL);
8314 		}
8315 
8316 		bcopy(DPROV_MANUFACTURER, ext_info->ei_manufacturerID,
8317 		    CRYPTO_EXT_SIZE_MANUF);
8318 		bcopy(DPROV_MODEL, ext_info->ei_model, CRYPTO_EXT_SIZE_MODEL);
8319 
8320 		(void) snprintf((char *)ext_info->ei_serial_number, 16, "%d%s",
8321 		    instance, DPROV_ALLSPACES);
8322 		/* PKCS#11 blank padding */
8323 		ext_info->ei_serial_number[15] = ' ';
8324 		ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
8325 		ext_info->ei_max_pin_len = (ulong_t)DPROV_MAX_PIN_LEN;
8326 		ext_info->ei_min_pin_len = 1;
8327 		ext_info->ei_total_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
8328 		ext_info->ei_free_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
8329 		ext_info->ei_total_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
8330 		ext_info->ei_free_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
8331 		ext_info->ei_hardware_version.cv_major = 1;
8332 		ext_info->ei_hardware_version.cv_minor = 0;
8333 		ext_info->ei_firmware_version.cv_major = 1;
8334 		ext_info->ei_firmware_version.cv_minor = 0;
8335 
8336 		ext_info->ei_flags = CRYPTO_EXTF_RNG |
8337 		    CRYPTO_EXTF_LOGIN_REQUIRED |
8338 		    CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
8339 		if (softc->ds_user_pin_set)
8340 			ext_info->ei_flags |= CRYPTO_EXTF_USER_PIN_INITIALIZED;
8341 		if (softc->ds_token_initialized)
8342 			ext_info->ei_flags |= CRYPTO_EXTF_TOKEN_INITIALIZED;
8343 
8344 		error = CRYPTO_SUCCESS;
8345 		break;
8346 	}
8347 	case DPROV_REQ_MGMT_INITTOKEN: {
8348 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
8349 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8350 		char *label = taskq_req->dr_mgmt_req.mr_label;
8351 
8352 		/* cannot initialize token when a session is open */
8353 		if (softc->ds_sessions_count > 0) {
8354 			error = CRYPTO_SESSION_EXISTS;
8355 			break;
8356 		}
8357 
8358 		/* check PIN length */
8359 		if (pin_len > DPROV_MAX_PIN_LEN) {
8360 			error = CRYPTO_PIN_LEN_RANGE;
8361 			break;
8362 		}
8363 
8364 		/* check PIN */
8365 		if (pin == NULL) {
8366 			error = CRYPTO_PIN_INVALID;
8367 			break;
8368 		}
8369 
8370 		/*
8371 		 * If the token has already been initialized, need
8372 		 * to validate supplied PIN.
8373 		 */
8374 		if (softc->ds_token_initialized &&
8375 		    (softc->ds_so_pin_len != pin_len ||
8376 		    strncmp(softc->ds_so_pin, pin, pin_len) != 0)) {
8377 			/* invalid SO PIN */
8378 			error = CRYPTO_PIN_INCORRECT;
8379 			break;
8380 		}
8381 
8382 		/* set label */
8383 		bcopy(label, softc->ds_label, CRYPTO_EXT_SIZE_LABEL);
8384 
8385 		/* set new SO PIN, update state */
8386 		bcopy(pin, softc->ds_so_pin, pin_len);
8387 		softc->ds_so_pin_len = pin_len;
8388 		softc->ds_token_initialized = B_TRUE;
8389 		softc->ds_user_pin_set = B_FALSE;
8390 
8391 		error = CRYPTO_SUCCESS;
8392 		break;
8393 	}
8394 	case DPROV_REQ_MGMT_INITPIN: {
8395 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
8396 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8397 		crypto_session_id_t session_id =
8398 		    taskq_req->dr_mgmt_req.mr_session_id;
8399 
8400 		/* check session id */
8401 		if (softc->ds_sessions[session_id] == NULL) {
8402 			error = CRYPTO_SESSION_HANDLE_INVALID;
8403 			break;
8404 		}
8405 
8406 		/* fail if not logged in as SO */
8407 		if (softc->ds_sessions[session_id]->ds_state !=
8408 		    DPROV_SESSION_STATE_SO) {
8409 			error = CRYPTO_USER_NOT_LOGGED_IN;
8410 			break;
8411 		}
8412 
8413 		/* check PIN length */
8414 		if (pin_len > DPROV_MAX_PIN_LEN) {
8415 			error = CRYPTO_PIN_LEN_RANGE;
8416 			break;
8417 		}
8418 
8419 		/* check PIN */
8420 		if (pin == NULL) {
8421 			error = CRYPTO_PIN_INVALID;
8422 			break;
8423 		}
8424 
8425 		/* set new normal user PIN */
8426 		bcopy(pin, softc->ds_user_pin, pin_len);
8427 		softc->ds_user_pin_len = pin_len;
8428 		softc->ds_user_pin_set = B_TRUE;
8429 
8430 		error = CRYPTO_SUCCESS;
8431 		break;
8432 	}
8433 	case DPROV_REQ_MGMT_SETPIN: {
8434 		char *new_pin = taskq_req->dr_mgmt_req.mr_pin;
8435 		size_t new_pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8436 		char *old_pin = taskq_req->dr_mgmt_req.mr_old_pin;
8437 		size_t old_pin_len = taskq_req->dr_mgmt_req.mr_old_pin_len;
8438 		crypto_session_id_t session_id =
8439 		    taskq_req->dr_mgmt_req.mr_session_id;
8440 
8441 		/* check session id */
8442 		if (softc->ds_sessions[session_id] == NULL) {
8443 			error = CRYPTO_SESSION_HANDLE_INVALID;
8444 			break;
8445 		}
8446 
8447 		/* check PIN length */
8448 		if (old_pin_len > DPROV_MAX_PIN_LEN ||
8449 		    new_pin_len > DPROV_MAX_PIN_LEN) {
8450 			error = CRYPTO_PIN_LEN_RANGE;
8451 			break;
8452 		}
8453 
8454 		/* check PIN */
8455 		if (old_pin == NULL || new_pin == NULL) {
8456 			error = CRYPTO_PIN_INVALID;
8457 			break;
8458 		}
8459 
8460 		/* check user PIN state */
8461 		if (!softc->ds_user_pin_set) {
8462 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
8463 			break;
8464 		}
8465 
8466 		/*
8467 		 * If the token has already been initialized, need
8468 		 * to validate supplied PIN.
8469 		 */
8470 		if (softc->ds_user_pin_len != old_pin_len ||
8471 		    strncmp(softc->ds_user_pin, old_pin, old_pin_len) != 0) {
8472 			/* invalid SO PIN */
8473 			error = CRYPTO_PIN_INCORRECT;
8474 			break;
8475 		}
8476 
8477 		/* set new PIN */
8478 		bcopy(new_pin, softc->ds_user_pin, new_pin_len);
8479 		softc->ds_user_pin_len = new_pin_len;
8480 
8481 		error = CRYPTO_SUCCESS;
8482 		break;
8483 	}
8484 	}
8485 
8486 	mutex_exit(&softc->ds_lock);
8487 	dprov_op_done(taskq_req, error);
8488 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: end\n", instance));
8489 }
8490 
8491 /*
8492  * Returns in the location pointed to by pd a pointer to the descriptor
8493  * for the software provider for the specified mechanism.
8494  * The provider descriptor is returned held. Returns one of the CRYPTO_
8495  * error codes on failure, CRYPTO_SUCCESS on success.
8496  */
8497 static int
8498 dprov_get_sw_prov(crypto_mechanism_t *mech, kcf_provider_desc_t **pd,
8499     crypto_mech_type_t *provider_mech_type)
8500 {
8501 	crypto_mech_type_t kcf_mech_type = CRYPTO_MECH_INVALID;
8502 	int i, rv;
8503 
8504 	/* lookup the KCF mech type associated with our mech type */
8505 	for (i = 0; i < sizeof (dprov_mech_info_tab)/
8506 	    sizeof (crypto_mech_info_t); i++) {
8507 		if (mech->cm_type == dprov_mech_info_tab[i].cm_mech_number) {
8508 			kcf_mech_type = crypto_mech2id_common(
8509 			    dprov_mech_info_tab[i].cm_mech_name, B_TRUE);
8510 		}
8511 	}
8512 
8513 	rv = kcf_get_sw_prov(kcf_mech_type, pd, NULL, B_TRUE);
8514 	if (rv == CRYPTO_SUCCESS)
8515 		*provider_mech_type = kcf_mech_type;
8516 
8517 	return (rv);
8518 }
8519 
8520 /*
8521  * Object management helper functions.
8522  */
8523 
8524 /*
8525  * Given a crypto_key_t, return whether the key can be used or not
8526  * for the specified request. The attributes used here are defined
8527  * in table 42 of the PKCS#11 spec (Common secret key attributes).
8528  */
8529 static int
8530 dprov_key_can_use(dprov_object_t *object, dprov_req_type_t req_type)
8531 {
8532 	boolean_t ret = 0;
8533 	int rv = CRYPTO_SUCCESS;
8534 
8535 	/* check if object is allowed for specified operation */
8536 	switch (req_type) {
8537 	case DPROV_REQ_ENCRYPT_INIT:
8538 	case DPROV_REQ_ENCRYPT_ATOMIC:
8539 		rv = dprov_get_object_attr_boolean(object,
8540 		    DPROV_CKA_ENCRYPT, &ret);
8541 		break;
8542 	case DPROV_REQ_DECRYPT_INIT:
8543 	case DPROV_REQ_DECRYPT_ATOMIC:
8544 		rv = dprov_get_object_attr_boolean(object,
8545 		    DPROV_CKA_DECRYPT, &ret);
8546 		break;
8547 	case DPROV_REQ_SIGN_INIT:
8548 	case DPROV_REQ_SIGN_ATOMIC:
8549 	case DPROV_REQ_MAC_INIT:
8550 	case DPROV_REQ_MAC_ATOMIC:
8551 	case DPROV_REQ_MAC_VERIFY_ATOMIC:
8552 		rv = dprov_get_object_attr_boolean(object,
8553 		    DPROV_CKA_SIGN, &ret);
8554 		break;
8555 	case DPROV_REQ_SIGN_RECOVER_INIT:
8556 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
8557 		rv = dprov_get_object_attr_boolean(object,
8558 		    DPROV_CKA_SIGN_RECOVER, &ret);
8559 		break;
8560 	case DPROV_REQ_VERIFY_INIT:
8561 	case DPROV_REQ_VERIFY_ATOMIC:
8562 		rv = dprov_get_object_attr_boolean(object,
8563 		    DPROV_CKA_VERIFY, &ret);
8564 		break;
8565 	case DPROV_REQ_VERIFY_RECOVER_INIT:
8566 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
8567 		rv = dprov_get_object_attr_boolean(object,
8568 		    DPROV_CKA_VERIFY_RECOVER, &ret);
8569 		break;
8570 	case DPROV_REQ_KEY_WRAP:
8571 		rv = dprov_get_object_attr_boolean(object,
8572 		    DPROV_CKA_WRAP, &ret);
8573 		break;
8574 	case DPROV_REQ_KEY_UNWRAP:
8575 		rv = dprov_get_object_attr_boolean(object,
8576 		    DPROV_CKA_UNWRAP, &ret);
8577 		break;
8578 	case DPROV_REQ_DIGEST_KEY:
8579 		/*
8580 		 * There is no attribute to check for; therefore,
8581 		 * any secret key can be used.
8582 		 */
8583 		ret = B_TRUE;
8584 		rv = CRYPTO_SUCCESS;
8585 		break;
8586 	case DPROV_REQ_KEY_DERIVE:
8587 		rv = dprov_get_object_attr_boolean(object,
8588 		    DPROV_CKA_DERIVE, &ret);
8589 		break;
8590 	}
8591 
8592 	if (rv != CRYPTO_SUCCESS || !ret)
8593 		return (CRYPTO_KEY_FUNCTION_NOT_PERMITTED);
8594 
8595 	return (CRYPTO_SUCCESS);
8596 }
8597 
8598 /*
8599  * Given a crypto_key_t corresponding to a secret key (i.e. for
8600  * use with symmetric crypto algorithms) specified in raw format, by
8601  * attribute, or by reference, initialize the ck_data and ck_length
8602  * fields of the ret_key argument so that they specify the key value
8603  * and length.
8604  *
8605  * For a key by value, this function uess the ck_data and ck_length,
8606  * for a key by reference, it looks up the corresponding object and
8607  * returns the appropriate attribute. For a key by attribute, it returns
8608  * the appropriate attribute. The attributes used are CKA_VALUE to retrieve
8609  * the value of the key, and CKA_VALUE_LEN to retrieve its length in bytes.
8610  */
8611 static int
8612 dprov_key_value_secret(dprov_state_t *softc, crypto_session_id_t session_id,
8613     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
8614 {
8615 	ulong_t key_type;
8616 	int ret = CRYPTO_SUCCESS;
8617 
8618 	ret_key->ck_format = CRYPTO_KEY_RAW;
8619 
8620 	switch (key->ck_format) {
8621 
8622 	case CRYPTO_KEY_RAW:
8623 		ret_key->ck_data = key->ck_data;
8624 		ret_key->ck_length = key->ck_length;
8625 		break;
8626 
8627 	case CRYPTO_KEY_ATTR_LIST: {
8628 		void *value;
8629 		size_t len, value_len;
8630 
8631 		if ((ret = dprov_get_key_attr_ulong(key, DPROV_CKA_KEY_TYPE,
8632 		    &key_type)) != CRYPTO_SUCCESS)
8633 			break;
8634 
8635 		if ((ret = dprov_get_key_attr_array(key, DPROV_CKA_VALUE,
8636 		    &value, &len)) != CRYPTO_SUCCESS)
8637 			break;
8638 
8639 		/*
8640 		 * The length of the array is expressed in bytes.
8641 		 * Convert to bits now since that's how keys are measured.
8642 		 */
8643 		len  = len << 3;
8644 
8645 		/* optional */
8646 		if ((dprov_get_key_attr_ulong(key, DPROV_CKA_VALUE_LEN,
8647 		    &value_len)) == CRYPTO_SUCCESS) {
8648 			len = value_len;
8649 		}
8650 
8651 		ret_key->ck_data = value;
8652 		ret_key->ck_length = (uint_t)len;
8653 
8654 		break;
8655 	}
8656 
8657 	case CRYPTO_KEY_REFERENCE: {
8658 		dprov_object_t *object;
8659 		void *value;
8660 		size_t len, value_len;
8661 
8662 		/* check session id */
8663 		if (softc->ds_sessions[session_id] == NULL) {
8664 			ret = CRYPTO_SESSION_HANDLE_INVALID;
8665 			break;
8666 		}
8667 
8668 		if (key->ck_obj_id >= DPROV_MAX_OBJECTS) {
8669 			ret = CRYPTO_KEY_HANDLE_INVALID;
8670 			goto bail;
8671 		}
8672 
8673 		/* check if object id specified by key is valid */
8674 		object = softc->ds_sessions[session_id]->
8675 		    ds_objects[key->ck_obj_id];
8676 		if (object == NULL) {
8677 			ret = CRYPTO_KEY_HANDLE_INVALID;
8678 			goto bail;
8679 		}
8680 
8681 		/* check if object can be used for operation */
8682 		if ((ret = dprov_key_can_use(object, req_type)) !=
8683 		    CRYPTO_SUCCESS)
8684 			goto bail;
8685 
8686 		if ((ret = dprov_get_object_attr_ulong(object,
8687 		    DPROV_CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS)
8688 			goto bail;
8689 
8690 		if ((ret = dprov_get_object_attr_array(object,
8691 		    DPROV_CKA_VALUE, &value, &len)) != CRYPTO_SUCCESS)
8692 			goto bail;
8693 
8694 		/* optional */
8695 		if ((dprov_get_object_attr_ulong(object, DPROV_CKA_VALUE_LEN,
8696 		    &value_len)) == CRYPTO_SUCCESS) {
8697 			len = value_len;
8698 		}
8699 
8700 		/*
8701 		 * The length of attributes are in bytes.
8702 		 * Convert to bits now since that's how keys are measured.
8703 		 */
8704 		len  = len << 3;
8705 
8706 		ret_key->ck_data = value;
8707 		ret_key->ck_length = (uint_t)len;
8708 bail:
8709 		break;
8710 	}
8711 
8712 	default:
8713 		ret = CRYPTO_ARGUMENTS_BAD;
8714 		break;
8715 	}
8716 
8717 	return (ret);
8718 }
8719 
8720 /*
8721  * Get the attribute list for the specified asymmetric key.
8722  */
8723 static int
8724 dprov_key_attr_asymmetric(dprov_state_t *softc, crypto_session_id_t session_id,
8725     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
8726 {
8727 	int ret = CRYPTO_SUCCESS;
8728 
8729 	ret_key->ck_format = CRYPTO_KEY_ATTR_LIST;
8730 
8731 	switch (key->ck_format) {
8732 
8733 	case CRYPTO_KEY_ATTR_LIST:
8734 		ret_key->ck_attrs = key->ck_attrs;
8735 		ret_key->ck_count = key->ck_count;
8736 		break;
8737 
8738 	case CRYPTO_KEY_REFERENCE: {
8739 		dprov_object_t *object;
8740 
8741 		/* check session id */
8742 		if (softc->ds_sessions[session_id] == NULL) {
8743 			ret = CRYPTO_SESSION_HANDLE_INVALID;
8744 			break;
8745 		}
8746 
8747 		/* check if object id specified by key is valid */
8748 		object = softc->ds_sessions[session_id]->
8749 		    ds_objects[key->ck_obj_id];
8750 		if (object == NULL) {
8751 			ret = CRYPTO_KEY_HANDLE_INVALID;
8752 			break;
8753 		}
8754 
8755 		/* check if object can be used for operation */
8756 		if ((ret = dprov_key_can_use(object, req_type)) !=
8757 		    CRYPTO_SUCCESS)
8758 			break;
8759 
8760 		ret_key->ck_attrs = object->do_attr;
8761 		ret_key->ck_count = DPROV_MAX_ATTR;
8762 		break;
8763 	}
8764 
8765 	default:
8766 		ret = CRYPTO_ARGUMENTS_BAD;
8767 	}
8768 
8769 	return (ret);
8770 }
8771 
8772 /*
8773  * Return the index of an attribute of specified type found in
8774  * the specified array of attributes. If the attribute cannot
8775  * found, return -1.
8776  */
8777 static int
8778 dprov_find_attr(crypto_object_attribute_t *attr, uint_t nattr,
8779     uint64_t attr_type)
8780 {
8781 	int i;
8782 
8783 	for (i = 0; i < nattr; i++)
8784 		if (attr[i].oa_value != NULL &&
8785 		    attr[i].oa_type == attr_type)
8786 			return (i);
8787 
8788 	return (-1);
8789 }
8790 
8791 /*
8792  * Given the given object template and session, return whether
8793  * an object can be created from that template according to the
8794  * following rules:
8795  * - private objects can be created only by a logged-in user
8796  */
8797 static int
8798 dprov_template_can_create(dprov_session_t *session,
8799     crypto_object_attribute_t *template, uint_t nattr,
8800     boolean_t check_for_secret)
8801 {
8802 	boolean_t is_private = B_FALSE;
8803 	ulong_t key_type, class;
8804 	int error;
8805 
8806 	/* check CKA_PRIVATE attribute value */
8807 	error = dprov_get_template_attr_boolean(template, nattr,
8808 	    DPROV_CKA_PRIVATE, &is_private);
8809 	if (error == CRYPTO_SUCCESS && is_private) {
8810 		/* it's a private object */
8811 		if (session->ds_state != DPROV_SESSION_STATE_USER) {
8812 			/*
8813 			 * Cannot create private object with SO or public
8814 			 * sessions.
8815 			 */
8816 			return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8817 		}
8818 	}
8819 
8820 	/* all objects must have an object class attribute */
8821 	if (dprov_get_template_attr_ulong(template, nattr, DPROV_CKA_CLASS,
8822 	    &class) != CRYPTO_SUCCESS) {
8823 		return (CRYPTO_TEMPLATE_INCOMPLETE);
8824 	}
8825 
8826 	/* key objects must have a key type attribute */
8827 	if (class == DPROV_CKO_SECRET_KEY ||
8828 	    class == DPROV_CKO_PUBLIC_KEY ||
8829 	    class == DPROV_CKO_PRIVATE_KEY) {
8830 		if (!dprov_template_attr_present(template, nattr,
8831 		    DPROV_CKA_KEY_TYPE)) {
8832 			return (CRYPTO_TEMPLATE_INCOMPLETE);
8833 		}
8834 	}
8835 
8836 	/* check for RSA public key attributes that must be present */
8837 	if (class == DPROV_CKO_PUBLIC_KEY) {
8838 		if (dprov_get_template_attr_ulong(template, nattr,
8839 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
8840 			if (key_type == DPROV_CKK_RSA) {
8841 				if (!dprov_template_attr_present(template,
8842 				    nattr, DPROV_CKA_MODULUS) ||
8843 				    !dprov_template_attr_present(template,
8844 				    nattr, DPROV_CKA_PUBLIC_EXPONENT)) {
8845 					return (CRYPTO_TEMPLATE_INCOMPLETE);
8846 				}
8847 
8848 				/* these attributes should not be present */
8849 				if (dprov_template_attr_present(template, nattr,
8850 				    DPROV_CKA_MODULUS_BITS)) {
8851 					return (CRYPTO_TEMPLATE_INCONSISTENT);
8852 				}
8853 			}
8854 		}
8855 	}
8856 
8857 	/* check for RSA private key attributes that must be present */
8858 	if (class == DPROV_CKO_PRIVATE_KEY) {
8859 		if (dprov_get_template_attr_ulong(template, nattr,
8860 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
8861 			if (key_type == DPROV_CKK_RSA) {
8862 				if (!dprov_template_attr_present(template,
8863 				    nattr, DPROV_CKA_MODULUS))
8864 					return (CRYPTO_TEMPLATE_INCOMPLETE);
8865 
8866 				if (check_for_secret) {
8867 					if (!dprov_template_attr_present(
8868 					    template, nattr,
8869 					    DPROV_CKA_PRIVATE_EXPONENT))
8870 						return (
8871 						    CRYPTO_TEMPLATE_INCOMPLETE);
8872 				}
8873 			}
8874 		}
8875 	}
8876 
8877 	/* check for secret key attributes that must be present */
8878 	if (class == DPROV_CKO_SECRET_KEY) {
8879 		if (check_for_secret) {
8880 			if (!dprov_template_attr_present(template, nattr,
8881 			    DPROV_CKA_VALUE)) {
8882 				return (CRYPTO_TEMPLATE_INCOMPLETE);
8883 			}
8884 		}
8885 
8886 		/* these attributes should not be present */
8887 		if (dprov_template_attr_present(template, nattr,
8888 		    DPROV_CKA_VALUE_LEN)) {
8889 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8890 		}
8891 	}
8892 
8893 	return (CRYPTO_SUCCESS);
8894 }
8895 
8896 /*
8897  * Create an object from the specified template. Checks whether the
8898  * object can be created according to its attributes and the state
8899  * of the session. The new session object id is returned. If the
8900  * object is a token object, it is added to the per-instance object
8901  * table as well.
8902  */
8903 static int
8904 dprov_create_object_from_template(dprov_state_t *softc,
8905     dprov_session_t *session, crypto_object_attribute_t *template,
8906     uint_t nattr, crypto_object_id_t *object_id, boolean_t check_for_secret,
8907     boolean_t force)
8908 {
8909 	dprov_object_t *object;
8910 	boolean_t is_token = B_FALSE;
8911 	boolean_t extractable_attribute_present = B_FALSE;
8912 	boolean_t sensitive_attribute_present = B_FALSE;
8913 	boolean_t private_attribute_present = B_FALSE;
8914 	boolean_t token_attribute_present = B_FALSE;
8915 	uint_t i;
8916 	int error;
8917 	uint_t attr;
8918 	uint_t oattr;
8919 	crypto_attr_type_t type;
8920 	size_t old_len, new_len;
8921 	offset_t offset;
8922 
8923 	if (nattr > DPROV_MAX_ATTR)
8924 		return (CRYPTO_HOST_MEMORY);
8925 
8926 	if (!force) {
8927 		/* verify that object can be created */
8928 		if ((error = dprov_template_can_create(session, template,
8929 		    nattr, check_for_secret)) != CRYPTO_SUCCESS)
8930 			return (error);
8931 	}
8932 
8933 	/* allocate new object */
8934 	object = kmem_zalloc(sizeof (dprov_object_t), KM_SLEEP);
8935 	if (object == NULL)
8936 		return (CRYPTO_HOST_MEMORY);
8937 
8938 	/* is it a token object? */
8939 	/* check CKA_TOKEN attribute value */
8940 	error = dprov_get_template_attr_boolean(template, nattr,
8941 	    DPROV_CKA_TOKEN, &is_token);
8942 	if (error == CRYPTO_SUCCESS && is_token) {
8943 		/* token object, add it to the per-instance object table */
8944 		for (i = 0; i < DPROV_MAX_OBJECTS; i++)
8945 			if (softc->ds_objects[i] == NULL)
8946 				break;
8947 		if (i == DPROV_MAX_OBJECTS)
8948 			/* no free slot */
8949 			return (CRYPTO_HOST_MEMORY);
8950 		softc->ds_objects[i] = object;
8951 		object->do_token_idx = i;
8952 		DPROV_OBJECT_REFHOLD(object);
8953 	}
8954 
8955 	/* add object to session object table */
8956 	for (i = 0; i < DPROV_MAX_OBJECTS; i++)
8957 		if (session->ds_objects[i] == NULL)
8958 			break;
8959 	if (i == DPROV_MAX_OBJECTS) {
8960 		/* no more session object slots */
8961 		DPROV_OBJECT_REFRELE(object);
8962 		return (CRYPTO_HOST_MEMORY);
8963 	}
8964 	session->ds_objects[i] = object;
8965 	DPROV_OBJECT_REFHOLD(object);
8966 	*object_id = i;
8967 
8968 	/* initialize object from template */
8969 	for (attr = 0, oattr = 0; attr < nattr; attr++) {
8970 		if (template[attr].oa_value == NULL)
8971 			continue;
8972 		type = template[attr].oa_type;
8973 		old_len = template[attr].oa_value_len;
8974 		new_len = attribute_size(type, old_len);
8975 
8976 		if (type == DPROV_CKA_EXTRACTABLE) {
8977 			extractable_attribute_present = B_TRUE;
8978 		} else if (type == DPROV_CKA_PRIVATE) {
8979 			private_attribute_present = B_TRUE;
8980 		} else if (type == DPROV_CKA_TOKEN) {
8981 			token_attribute_present = B_TRUE;
8982 		}
8983 		object->do_attr[oattr].oa_type = type;
8984 		object->do_attr[oattr].oa_value_len = new_len;
8985 
8986 		object->do_attr[oattr].oa_value = kmem_zalloc(new_len,
8987 		    KM_SLEEP);
8988 
8989 		offset = 0;
8990 #ifdef _BIG_ENDIAN
8991 		if (fixed_size_attribute(type)) {
8992 			offset = old_len - new_len;
8993 		}
8994 #endif
8995 		bcopy(&template[attr].oa_value[offset],
8996 		    object->do_attr[oattr].oa_value, new_len);
8997 		oattr++;
8998 	}
8999 
9000 	/* add boolean attributes that must be present */
9001 	if (extractable_attribute_present == B_FALSE) {
9002 		object->do_attr[oattr].oa_type = DPROV_CKA_EXTRACTABLE;
9003 		object->do_attr[oattr].oa_value_len = 1;
9004 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9005 		object->do_attr[oattr].oa_value[0] = B_TRUE;
9006 		oattr++;
9007 	}
9008 
9009 	if (private_attribute_present == B_FALSE) {
9010 		object->do_attr[oattr].oa_type = DPROV_CKA_PRIVATE;
9011 		object->do_attr[oattr].oa_value_len = 1;
9012 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9013 		object->do_attr[oattr].oa_value[0] = B_FALSE;
9014 		oattr++;
9015 	}
9016 
9017 	if (token_attribute_present == B_FALSE) {
9018 		object->do_attr[oattr].oa_type = DPROV_CKA_TOKEN;
9019 		object->do_attr[oattr].oa_value_len = 1;
9020 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9021 		object->do_attr[oattr].oa_value[0] = B_FALSE;
9022 		oattr++;
9023 	}
9024 
9025 	if (sensitive_attribute_present == B_FALSE) {
9026 		object->do_attr[oattr].oa_type = DPROV_CKA_SENSITIVE;
9027 		object->do_attr[oattr].oa_value_len = 1;
9028 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9029 		object->do_attr[oattr].oa_value[0] = B_FALSE;
9030 		oattr++;
9031 	}
9032 	return (CRYPTO_SUCCESS);
9033 }
9034 
9035 /*
9036  * Checks whether or not the object matches the specified attributes.
9037  *
9038  * PKCS#11 attributes which are longs are stored in uint32_t containers
9039  * so they can be matched by both 32 and 64-bit applications.
9040  */
9041 static boolean_t
9042 dprov_attributes_match(dprov_object_t *object,
9043     crypto_object_attribute_t *template, uint_t nattr)
9044 {
9045 	crypto_attr_type_t type;
9046 	size_t tlen, olen, diff;
9047 	int ta_idx;	/* template attribute index */
9048 	int oa_idx;	/* object attribute index */
9049 
9050 	for (ta_idx = 0; ta_idx < nattr; ta_idx++) {
9051 		/* no value for template attribute */
9052 		if (template[ta_idx].oa_value == NULL)
9053 			continue;
9054 
9055 		/* find attribute in object */
9056 		type = template[ta_idx].oa_type;
9057 		oa_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
9058 
9059 		if (oa_idx == -1)
9060 			/* attribute not found in object */
9061 			return (B_FALSE);
9062 
9063 		tlen = template[ta_idx].oa_value_len;
9064 		olen = object->do_attr[oa_idx].oa_value_len;
9065 		if (tlen < olen)
9066 			return (B_FALSE);
9067 
9068 		diff = 0;
9069 #ifdef _BIG_ENDIAN
9070 		/* application may think attribute is 8 bytes */
9071 		if (fixed_size_attribute(type))
9072 			diff = tlen - olen;
9073 #endif
9074 
9075 		if (bcmp(&template[ta_idx].oa_value[diff],
9076 		    object->do_attr[oa_idx].oa_value, olen) != 0)
9077 			/* value mismatch */
9078 			return (B_FALSE);
9079 	}
9080 
9081 	return (B_TRUE);
9082 }
9083 
9084 /*
9085  * Destroy the object specified by its session and object id.
9086  */
9087 static int
9088 dprov_destroy_object(dprov_state_t *softc, dprov_session_t *session,
9089     crypto_object_id_t object_id)
9090 {
9091 	dprov_object_t *object;
9092 
9093 	if ((object = session->ds_objects[object_id]) == NULL)
9094 		return (CRYPTO_OBJECT_HANDLE_INVALID);
9095 
9096 	/* remove from session table */
9097 	session->ds_objects[object_id] = NULL;
9098 
9099 	if (dprov_object_is_token(object)) {
9100 		if (!object->do_destroyed) {
9101 			object->do_destroyed = B_TRUE;
9102 			/* remove from per-instance token table */
9103 			softc->ds_objects[object->do_token_idx] = NULL;
9104 			DPROV_OBJECT_REFRELE(object);
9105 		} else {
9106 			DPROV_DEBUG(D_OBJECT, ("dprov_destroy_object: "
9107 			    "object %p already destroyed\n", (void *)object));
9108 		}
9109 	}
9110 
9111 	DPROV_OBJECT_REFRELE(object);
9112 	return (CRYPTO_SUCCESS);
9113 }
9114 
9115 static int
9116 dprov_object_can_modify(dprov_object_t *object,
9117     crypto_object_attribute_t *template, uint_t nattr)
9118 {
9119 	ulong_t object_class;
9120 
9121 	/* all objects should have an object class attribute */
9122 	if (dprov_get_object_attr_ulong(object, DPROV_CKA_CLASS,
9123 	    &object_class) != CRYPTO_SUCCESS) {
9124 		return (CRYPTO_SUCCESS);
9125 	}
9126 
9127 	if (object_class == DPROV_CKO_SECRET_KEY ||
9128 	    object_class == DPROV_CKO_PUBLIC_KEY ||
9129 	    object_class == DPROV_CKO_PRIVATE_KEY) {
9130 		if (dprov_template_attr_present(template, nattr,
9131 		    DPROV_CKA_CLASS) ||
9132 		    dprov_template_attr_present(template, nattr,
9133 		    DPROV_CKA_KEY_TYPE))
9134 			return (CRYPTO_TEMPLATE_INCONSISTENT);
9135 	}
9136 
9137 	switch (object_class) {
9138 	case DPROV_CKO_SECRET_KEY:
9139 		if (dprov_template_attr_present(template, nattr,
9140 		    DPROV_CKA_VALUE))
9141 			return (CRYPTO_TEMPLATE_INCONSISTENT);
9142 		break;
9143 
9144 	case DPROV_CKO_PUBLIC_KEY:
9145 		if (dprov_template_attr_present(template, nattr,
9146 		    DPROV_CKA_MODULUS) ||
9147 		    dprov_template_attr_present(template, nattr,
9148 		    DPROV_CKA_PUBLIC_EXPONENT))
9149 			return (CRYPTO_TEMPLATE_INCONSISTENT);
9150 		break;
9151 
9152 	case DPROV_CKO_PRIVATE_KEY:
9153 		if (dprov_template_attr_present(template, nattr,
9154 		    DPROV_CKA_MODULUS) ||
9155 		    dprov_template_attr_present(template, nattr,
9156 		    DPROV_CKA_PRIVATE_EXPONENT))
9157 			return (CRYPTO_TEMPLATE_INCONSISTENT);
9158 		break;
9159 
9160 	default:
9161 		return (CRYPTO_SUCCESS);
9162 	}
9163 
9164 	return (CRYPTO_SUCCESS);
9165 }
9166 
9167 /*
9168  * Set the attributes specified by the template in the specified object,
9169  * replacing existing ones if needed.
9170  */
9171 static int
9172 dprov_object_set_attr(dprov_session_t *session, crypto_object_id_t object_id,
9173     crypto_object_attribute_t *template, uint_t nattr,
9174     boolean_t check_attributes)
9175 {
9176 	crypto_attr_type_t type;
9177 	dprov_object_t *object;
9178 	size_t old_len, new_len;
9179 	uint_t i, j;
9180 	int error;
9181 
9182 	if ((object = session->ds_objects[object_id]) == NULL)
9183 		return (CRYPTO_OBJECT_HANDLE_INVALID);
9184 
9185 	if (check_attributes) {
9186 		/* verify that attributes in the template can be modified */
9187 		if ((error = dprov_object_can_modify(object, template, nattr))
9188 		    != CRYPTO_SUCCESS)
9189 			return (error);
9190 	}
9191 
9192 	/* go through the attributes specified in the template */
9193 	for (i = 0; i < nattr; i++) {
9194 		if (template[i].oa_value == NULL)
9195 			continue;
9196 
9197 		/* find attribute in object */
9198 		type = template[i].oa_type;
9199 		j = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
9200 
9201 		if (j != -1) {
9202 			/* attribute already exists, free old value */
9203 			kmem_free(object->do_attr[j].oa_value,
9204 			    object->do_attr[j].oa_value_len);
9205 		} else {
9206 			/* attribute does not exist, create it */
9207 			for (j = 0; j < DPROV_MAX_ATTR; j++)
9208 				if (object->do_attr[j].oa_value == NULL)
9209 					break;
9210 			if (j == DPROV_MAX_ATTR)
9211 				/* ran out of attribute slots */
9212 				return (CRYPTO_HOST_MEMORY);
9213 		}
9214 
9215 		old_len = template[i].oa_value_len;
9216 		new_len = attribute_size(type, old_len);
9217 
9218 		/* set object attribute value */
9219 		object->do_attr[j].oa_value = kmem_alloc(new_len, KM_SLEEP);
9220 		bcopy(&template[i].oa_value[old_len - new_len],
9221 		    object->do_attr[j].oa_value, new_len);
9222 		object->do_attr[j].oa_value_len = new_len;
9223 
9224 		/* and the type */
9225 		object->do_attr[j].oa_type = type;
9226 	}
9227 
9228 	return (CRYPTO_SUCCESS);
9229 }
9230 
9231 
9232 /*
9233  * Free the specified object.
9234  */
9235 static void
9236 dprov_free_object(dprov_object_t *object)
9237 {
9238 	int i;
9239 
9240 	/* free the object attributes values */
9241 	for (i = 0; i < DPROV_MAX_ATTR; i++)
9242 		if (object->do_attr[i].oa_value != NULL)
9243 			kmem_free(object->do_attr[i].oa_value,
9244 			    object->do_attr[i].oa_value_len);
9245 
9246 	/* free the object */
9247 	kmem_free(object, sizeof (dprov_object_t));
9248 }
9249 
9250 /*
9251  * Checks whether the specified object is a private or public object.
9252  */
9253 static boolean_t
9254 dprov_object_is_private(dprov_object_t *object)
9255 {
9256 	boolean_t ret;
9257 	int err;
9258 
9259 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_PRIVATE, &ret);
9260 
9261 	if (err != CRYPTO_SUCCESS)
9262 		/* by default, CKA_PRIVATE is false */
9263 		ret = B_FALSE;
9264 
9265 	return (ret);
9266 }
9267 
9268 /*
9269  * Checks whether the specified object is a token or session object.
9270  */
9271 static boolean_t
9272 dprov_object_is_token(dprov_object_t *object)
9273 {
9274 	boolean_t ret;
9275 	int err;
9276 
9277 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_TOKEN, &ret);
9278 
9279 	if (err != CRYPTO_SUCCESS)
9280 		/* by default, CKA_TOKEN is false */
9281 		ret = B_FALSE;
9282 
9283 	return (ret);
9284 }
9285 
9286 /*
9287  * Common function used by the dprov_get_object_attr_*() family of
9288  * functions. Returns the value of the specified attribute of specified
9289  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9290  * if the length of the attribute does not match the specified length,
9291  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9292  */
9293 static int
9294 dprov_get_object_attr_scalar_common(dprov_object_t *object, uint64_t attr_type,
9295 				    void *value, size_t value_len)
9296 {
9297 	int attr_idx;
9298 	size_t oa_value_len;
9299 	size_t offset = 0;
9300 
9301 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
9302 	    attr_type)) == -1)
9303 		return (CRYPTO_ARGUMENTS_BAD);
9304 
9305 	oa_value_len = object->do_attr[attr_idx].oa_value_len;
9306 	if (oa_value_len != value_len) {
9307 		/*
9308 		 * For some attributes, it's okay to copy the value
9309 		 * into a larger container, e.g. copy an unsigned
9310 		 * 32-bit integer into a 64-bit container.
9311 		 */
9312 		if (attr_type == DPROV_CKA_VALUE_LEN ||
9313 		    attr_type == DPROV_CKA_KEY_TYPE ||
9314 		    attr_type == DPROV_CKA_CLASS) {
9315 			if (oa_value_len < value_len) {
9316 #ifdef _BIG_ENDIAN
9317 				offset = value_len - oa_value_len;
9318 #endif
9319 				bzero(value, value_len);
9320 				goto do_copy;
9321 			}
9322 		}
9323 		/* incorrect attribute value length */
9324 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9325 	}
9326 
9327 do_copy:
9328 	bcopy(object->do_attr[attr_idx].oa_value, (uchar_t *)value + offset,
9329 	    oa_value_len);
9330 
9331 	return (CRYPTO_SUCCESS);
9332 }
9333 
9334 /*
9335  * Get the value of the a boolean attribute from the specified object.
9336  */
9337 static int
9338 dprov_get_object_attr_boolean(dprov_object_t *object, uint64_t attr_type,
9339     boolean_t *attr_value)
9340 {
9341 	uchar_t val;
9342 	int ret;
9343 
9344 	/* PKCS#11 defines a boolean as one byte */
9345 	ret = dprov_get_object_attr_scalar_common(object, attr_type, &val, 1);
9346 	if (ret == CRYPTO_SUCCESS) {
9347 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
9348 	}
9349 	return (ret);
9350 }
9351 
9352 /*
9353  * Get the value of a ulong_t attribute from the specified object.
9354  */
9355 static int
9356 dprov_get_object_attr_ulong(dprov_object_t *object, uint64_t attr_type,
9357     ulong_t *attr_value)
9358 {
9359 	return (dprov_get_object_attr_scalar_common(object, attr_type,
9360 	    attr_value, sizeof (ulong_t)));
9361 }
9362 
9363 /*
9364  * Find the specified byte array attribute of specified type in
9365  * the specified object. Returns CRYPTO_SUCCESS
9366  * on success or CRYPTO_ARGUMENTS_BAD if the specified
9367  * attribute cannot be found.
9368  */
9369 static int
9370 dprov_get_object_attr_array(dprov_object_t *object, uint64_t attr_type,
9371     void **array, size_t *len)
9372 {
9373 	int attr_idx;
9374 
9375 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
9376 	    attr_type)) == -1)
9377 		return (CRYPTO_ARGUMENTS_BAD);
9378 
9379 	*array = object->do_attr[attr_idx].oa_value;
9380 	*len = object->do_attr[attr_idx].oa_value_len;
9381 
9382 	return (CRYPTO_SUCCESS);
9383 }
9384 
9385 /*
9386  * Common function used by the dprov_get_template_attr_*() family of
9387  * functions. Returns the value of the specified attribute of specified
9388  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9389  * if the length of the attribute does not match the specified length,
9390  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9391  */
9392 static int
9393 dprov_get_template_attr_scalar_common(crypto_object_attribute_t *template,
9394     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
9395 {
9396 	size_t oa_value_len;
9397 	size_t offset = 0;
9398 	int attr_idx;
9399 
9400 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
9401 		return (CRYPTO_ARGUMENTS_BAD);
9402 
9403 	oa_value_len = template[attr_idx].oa_value_len;
9404 	if (oa_value_len != value_len) {
9405 		/*
9406 		 * For some attributes, it's okay to copy the value
9407 		 * into a larger container, e.g. copy an unsigned
9408 		 * 32-bit integer into a 64-bit container.
9409 		 */
9410 		if (attr_type == DPROV_CKA_VALUE_LEN ||
9411 		    attr_type == DPROV_CKA_KEY_TYPE ||
9412 		    attr_type == DPROV_CKA_CLASS) {
9413 			if (oa_value_len < value_len) {
9414 #ifdef _BIG_ENDIAN
9415 				offset = value_len - oa_value_len;
9416 #endif
9417 				bzero(value, value_len);
9418 				goto do_copy;
9419 			}
9420 		}
9421 		/* incorrect attribute value length */
9422 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9423 	}
9424 
9425 do_copy:
9426 	bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
9427 	    oa_value_len);
9428 
9429 	return (CRYPTO_SUCCESS);
9430 }
9431 
9432 /*
9433  * Get the value of the a boolean attribute from the specified template
9434  */
9435 static int
9436 dprov_get_template_attr_boolean(crypto_object_attribute_t *template,
9437     uint_t nattr, uint64_t attr_type, boolean_t *attr_value)
9438 {
9439 	uchar_t val;
9440 	int ret;
9441 
9442 	/* PKCS#11 defines a boolean as one byte */
9443 	ret = dprov_get_template_attr_scalar_common(template, nattr,
9444 	    attr_type, &val, 1);
9445 	if (ret == CRYPTO_SUCCESS) {
9446 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
9447 	}
9448 	return (ret);
9449 }
9450 
9451 /*
9452  * Get the value of a ulong_t attribute from the specified template.
9453  */
9454 static int
9455 dprov_get_template_attr_ulong(crypto_object_attribute_t *template,
9456     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
9457 {
9458 	return (dprov_get_template_attr_scalar_common(template, nattr,
9459 	    attr_type, attr_value, sizeof (ulong_t)));
9460 }
9461 
9462 static int
9463 dprov_template_attr_present(crypto_object_attribute_t *template,
9464     uint_t nattr, uint64_t attr_type)
9465 {
9466 	return (dprov_find_attr(template, nattr,
9467 	    attr_type) == -1 ? B_FALSE : B_TRUE);
9468 }
9469 
9470 /*
9471  * Find the specified byte array attribute of specified type in
9472  * the specified template. Returns CRYPTO_SUCCESS on success or
9473  * CRYPTO_ARGUMENTS_BAD if the specified attribute cannot be found.
9474  */
9475 static int
9476 dprov_get_template_attr_array(crypto_object_attribute_t *template,
9477     uint_t nattr, uint64_t attr_type, void **array, size_t *len)
9478 {
9479 	int attr_idx;
9480 
9481 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
9482 		return (CRYPTO_ARGUMENTS_BAD);
9483 
9484 	*array = template[attr_idx].oa_value;
9485 	*len = template[attr_idx].oa_value_len;
9486 
9487 	return (CRYPTO_SUCCESS);
9488 }
9489 
9490 /*
9491  * Common function used by the dprov_get_key_attr_*() family of
9492  * functions. Returns the value of the specified attribute of specified
9493  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9494  * if the length of the attribute does not match the specified length,
9495  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9496  */
9497 static int
9498 dprov_get_key_attr_scalar_common(crypto_key_t *key, uint64_t attr_type,
9499     void *value, size_t value_len)
9500 {
9501 	int attr_idx;
9502 
9503 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
9504 
9505 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
9506 	    attr_type)) == -1)
9507 		return (CRYPTO_ARGUMENTS_BAD);
9508 
9509 	if (key->ck_attrs[attr_idx].oa_value_len != value_len)
9510 		/* incorrect attribute value length */
9511 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9512 
9513 	bcopy(key->ck_attrs[attr_idx].oa_value, value, value_len);
9514 
9515 	return (CRYPTO_SUCCESS);
9516 }
9517 
9518 /*
9519  * Get the value of a ulong_t attribute from the specified key.
9520  */
9521 static int
9522 dprov_get_key_attr_ulong(crypto_key_t *key, uint64_t attr_type,
9523     ulong_t *attr_value)
9524 {
9525 	return (dprov_get_key_attr_scalar_common(key, attr_type,
9526 	    attr_value, sizeof (ulong_t)));
9527 }
9528 
9529 /*
9530  * Find the specified byte array attribute of specified type in
9531  * the specified key by attributes. Returns CRYPTO_SUCCESS
9532  * on success or CRYPTO_ARGUMENTS_BAD if the specified
9533  * attribute cannot be found.
9534  */
9535 static int
9536 dprov_get_key_attr_array(crypto_key_t *key, uint64_t attr_type,
9537     void **array, size_t *len)
9538 {
9539 	int attr_idx;
9540 
9541 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
9542 
9543 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
9544 	    attr_type)) == -1)
9545 		return (CRYPTO_ARGUMENTS_BAD);
9546 
9547 	*array = key->ck_attrs[attr_idx].oa_value;
9548 	*len = key->ck_attrs[attr_idx].oa_value_len;
9549 
9550 	return (CRYPTO_SUCCESS);
9551 }
9552 
9553 static void
9554 dprov_release_session_objects(dprov_session_t *session)
9555 {
9556 	dprov_object_t *object;
9557 	int i;
9558 
9559 	for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
9560 		object = session->ds_objects[i];
9561 		if (object != NULL) {
9562 			DPROV_OBJECT_REFRELE(object);
9563 		}
9564 	}
9565 }
9566 
9567 /*
9568  * Adjust an attribute list by turning 32-bit values into 64-bit values
9569  * for certain attributes like CKA_CLASS. Assumes that at least 8 bytes
9570  * of storage have been allocated for all attributes.
9571  */
9572 static void
9573 dprov_adjust_attrs(crypto_object_attribute_t *in, int in_count)
9574 {
9575 	int i;
9576 	size_t offset = 0;
9577 	ulong_t tmp = 0;
9578 
9579 	for (i = 0; i < in_count; i++) {
9580 		/*
9581 		 * For some attributes, it's okay to copy the value
9582 		 * into a larger container, e.g. copy an unsigned
9583 		 * 32-bit integer into a 64-bit container.
9584 		 */
9585 		if (in[i].oa_type == CKA_VALUE_LEN ||
9586 		    in[i].oa_type == CKA_KEY_TYPE ||
9587 		    in[i].oa_type == CKA_CLASS) {
9588 			if (in[i].oa_value_len < sizeof (ulong_t)) {
9589 #ifdef _BIG_ENDIAN
9590 				offset = sizeof (ulong_t) - in[i].oa_value_len;
9591 #endif
9592 				bcopy(in[i].oa_value, (uchar_t *)&tmp + offset,
9593 				    in[i].oa_value_len);
9594 				bcopy(&tmp, in[i].oa_value, sizeof (ulong_t));
9595 				in[i].oa_value_len = sizeof (ulong_t);
9596 			}
9597 		}
9598 	}
9599 }
9600