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