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