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