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