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