xref: /titanic_41/usr/src/uts/common/crypto/io/dprov.c (revision 18c2aff776a775d34a4c9893a4c72e0434d68e36)
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 2006 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},
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 AES_ECB_MECH_INFO_TYPE:
4216 	case BLOWFISH_ECB_MECH_INFO_TYPE:
4217 	case DES_ECB_MECH_INFO_TYPE:
4218 	case DES3_ECB_MECH_INFO_TYPE:
4219 		rv = CRYPTO_SUCCESS;
4220 		goto out;
4221 
4222 	case DES_CBC_MECH_INFO_TYPE:
4223 	case DES3_CBC_MECH_INFO_TYPE:
4224 		expected_param_len = DES_BLOCK_LEN;
4225 		break;
4226 
4227 	case BLOWFISH_CBC_MECH_INFO_TYPE:
4228 		expected_param_len = BLOWFISH_BLOCK_LEN;
4229 		break;
4230 
4231 	case AES_CBC_MECH_INFO_TYPE:
4232 		expected_param_len = AES_BLOCK_LEN;
4233 		break;
4234 
4235 	case AES_CTR_MECH_INFO_TYPE:
4236 	case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:	/* for testing only */
4237 		rv = copyin_aes_ctr_mech(umech, kmech, &error, mode);
4238 		goto out;
4239 
4240 	case RC4_MECH_INFO_TYPE:
4241 	case RSA_PKCS_MECH_INFO_TYPE:
4242 	case RSA_X_509_MECH_INFO_TYPE:
4243 	case MD5_RSA_PKCS_MECH_INFO_TYPE:
4244 	case SHA1_RSA_PKCS_MECH_INFO_TYPE:
4245 	case SHA256_RSA_PKCS_MECH_INFO_TYPE:
4246 	case SHA384_RSA_PKCS_MECH_INFO_TYPE:
4247 	case SHA512_RSA_PKCS_MECH_INFO_TYPE:
4248 		rv = CRYPTO_SUCCESS;
4249 		goto out;
4250 
4251 	default:
4252 		rv = CRYPTO_MECHANISM_INVALID;
4253 		goto out;
4254 	}
4255 
4256 	if (param_len != expected_param_len) {
4257 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
4258 		goto out;
4259 	}
4260 	if (pp == NULL) {
4261 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
4262 		goto out;
4263 	}
4264 	if ((param = kmem_alloc(param_len, KM_NOSLEEP)) == NULL) {
4265 		rv = CRYPTO_HOST_MEMORY;
4266 		goto out;
4267 	}
4268 	if (copyin((char *)pp, param, param_len) != 0) {
4269 		kmem_free(param, param_len);
4270 		error = EFAULT;
4271 		rv = CRYPTO_FAILED;
4272 		goto out;
4273 	}
4274 	kmech->cm_param = (char *)param;
4275 	kmech->cm_param_len = param_len;
4276 	rv = CRYPTO_SUCCESS;
4277 out:
4278 	*out_error = error;
4279 	return (rv);
4280 }
4281 
4282 /* ARGSUSED */
4283 static int
4284 dprov_copyout_mechanism(crypto_provider_handle_t provider,
4285     crypto_mechanism_t *kmech, crypto_mechanism_t *umech,
4286     int *out_error, int mode)
4287 {
4288 	ASSERT(!servicing_interrupt());
4289 
4290 	switch (kmech->cm_type) {
4291 	case AES_CTR_MECH_INFO_TYPE:
4292 	case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:	/* for testing only */
4293 		return (copyout_aes_ctr_mech(kmech, umech, out_error, mode));
4294 	default:
4295 		return (CRYPTO_MECHANISM_INVALID);
4296 	}
4297 }
4298 
4299 /*
4300  * Free mechanism parameter that was allocated by the provider.
4301  */
4302 /* ARGSUSED */
4303 static int
4304 dprov_free_mechanism(crypto_provider_handle_t provider,
4305     crypto_mechanism_t *mech)
4306 {
4307 	size_t len;
4308 
4309 	if (mech->cm_param == NULL || mech->cm_param_len == 0)
4310 		return (CRYPTO_SUCCESS);
4311 
4312 	if (mech->cm_type == AES_CTR_MECH_INFO_TYPE ||
4313 	    mech->cm_type == SHA1_KEY_DERIVATION_MECH_INFO_TYPE) {
4314 		len = sizeof (CK_AES_CTR_PARAMS) + 16;
4315 	} else {
4316 		len = mech->cm_param_len;
4317 	}
4318 	kmem_free(mech->cm_param, len);
4319 	return (CRYPTO_SUCCESS);
4320 }
4321 
4322 /*
4323  * Allocate a dprov taskq request and initialize the common fields.
4324  * Return NULL if the memory allocation failed.
4325  */
4326 static dprov_req_t *
4327 dprov_alloc_req(dprov_req_type_t req_type, dprov_state_t *softc,
4328     crypto_req_handle_t kcf_req, int kmflag)
4329 {
4330 	dprov_req_t *taskq_req;
4331 
4332 	if ((taskq_req = kmem_alloc(sizeof (dprov_req_t), kmflag)) == NULL)
4333 		return (NULL);
4334 
4335 	taskq_req->dr_type = req_type;
4336 	taskq_req->dr_softc = softc;
4337 	taskq_req->dr_kcf_req = kcf_req;
4338 
4339 	return (taskq_req);
4340 }
4341 
4342 /*
4343  * Dispatch a dprov request on the taskq associated with a softc.
4344  * Returns CRYPTO_HOST_MEMORY if the request cannot be queued,
4345  * CRYPTO_QUEUED on success.
4346  */
4347 static int
4348 dprov_taskq_dispatch(dprov_state_t *softc, dprov_req_t *taskq_req,
4349     task_func_t *func, int kmflag)
4350 {
4351 	if (taskq_dispatch(softc->ds_taskq, func, taskq_req,
4352 	    kmflag == KM_NOSLEEP ? TQ_NOSLEEP : TQ_SLEEP) == (taskqid_t)0) {
4353 		kmem_free(taskq_req, sizeof (dprov_req_t));
4354 		return (CRYPTO_HOST_MEMORY);
4355 	} else
4356 		return (CRYPTO_QUEUED);
4357 }
4358 
4359 /*
4360  * Helper function to submit digest operations to the taskq.
4361  * Returns one of the CRYPTO_ errors.
4362  */
4363 static int
4364 dprov_digest_submit_req(dprov_req_type_t req_type,
4365     dprov_state_t *softc, crypto_req_handle_t req,
4366     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
4367     crypto_data_t *digest, crypto_ctx_t *ctx, int kmflag)
4368 {
4369 	dprov_req_t *taskq_req;
4370 
4371 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4372 		return (CRYPTO_HOST_MEMORY);
4373 
4374 	taskq_req->dr_digest_req.dr_mechanism = mechanism;
4375 	taskq_req->dr_digest_req.dr_ctx = ctx;
4376 	taskq_req->dr_digest_req.dr_data = data;
4377 	taskq_req->dr_digest_req.dr_key = key;
4378 	taskq_req->dr_digest_req.dr_digest = digest;
4379 
4380 	return (dprov_taskq_dispatch(softc, taskq_req,
4381 	    (task_func_t *)dprov_digest_task, kmflag));
4382 }
4383 
4384 /*
4385  * Helper function to submit mac operations to the taskq.
4386  * Returns one of the CRYPTO_ errors.
4387  */
4388 static int
4389 dprov_mac_submit_req(dprov_req_type_t req_type,
4390     dprov_state_t *softc, crypto_req_handle_t req,
4391     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
4392     crypto_data_t *mac, crypto_ctx_t *ctx, crypto_session_id_t sid, int kmflag)
4393 {
4394 	dprov_req_t *taskq_req;
4395 
4396 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4397 		return (CRYPTO_HOST_MEMORY);
4398 
4399 	taskq_req->dr_mac_req.dr_mechanism = mechanism;
4400 	taskq_req->dr_mac_req.dr_ctx = ctx;
4401 	taskq_req->dr_mac_req.dr_data = data;
4402 	taskq_req->dr_mac_req.dr_key = key;
4403 	taskq_req->dr_mac_req.dr_mac = mac;
4404 	taskq_req->dr_mac_req.dr_session_id = sid;
4405 
4406 	return (dprov_taskq_dispatch(softc, taskq_req,
4407 	    (task_func_t *)dprov_mac_task, kmflag));
4408 }
4409 
4410 /*
4411  * Helper function to submit sign operations to the taskq.
4412  * Returns one of the CRYPTO_ errors.
4413  */
4414 static int
4415 dprov_sign_submit_req(dprov_req_type_t req_type,
4416     dprov_state_t *softc, crypto_req_handle_t req,
4417     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
4418     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
4419     int kmflag)
4420 {
4421 	dprov_req_t *taskq_req;
4422 
4423 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4424 		return (CRYPTO_HOST_MEMORY);
4425 
4426 	taskq_req->dr_sign_req.sr_mechanism = mechanism;
4427 	taskq_req->dr_sign_req.sr_ctx = ctx;
4428 	taskq_req->dr_sign_req.sr_key = key;
4429 	taskq_req->dr_sign_req.sr_data = data;
4430 	taskq_req->dr_sign_req.sr_signature = signature;
4431 	taskq_req->dr_sign_req.sr_session_id = sid;
4432 
4433 	return (dprov_taskq_dispatch(softc, taskq_req,
4434 	    (task_func_t *)dprov_sign_task, kmflag));
4435 }
4436 
4437 /*
4438  * Helper function to submit verify operations to the taskq.
4439  * Returns one of the CRYPTO_ errors.
4440  */
4441 static int
4442 dprov_verify_submit_req(dprov_req_type_t req_type,
4443     dprov_state_t *softc, crypto_req_handle_t req,
4444     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
4445     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
4446     int kmflag)
4447 {
4448 	dprov_req_t *taskq_req;
4449 
4450 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4451 		return (CRYPTO_HOST_MEMORY);
4452 
4453 	taskq_req->dr_verify_req.vr_mechanism = mechanism;
4454 	taskq_req->dr_verify_req.vr_ctx = ctx;
4455 	taskq_req->dr_verify_req.vr_key = key;
4456 	taskq_req->dr_verify_req.vr_data = data;
4457 	taskq_req->dr_verify_req.vr_signature = signature;
4458 	taskq_req->dr_verify_req.vr_session_id = sid;
4459 
4460 	return (dprov_taskq_dispatch(softc, taskq_req,
4461 	    (task_func_t *)dprov_verify_task, kmflag));
4462 }
4463 
4464 /*
4465  * Helper function to submit dual operations to the taskq.
4466  * Returns one of the CRYPTO_ errors.
4467  */
4468 static int
4469 dprov_dual_submit_req(dprov_req_type_t req_type, dprov_state_t *softc,
4470     crypto_req_handle_t req, crypto_ctx_t *signverify_ctx,
4471     crypto_ctx_t *cipher_ctx, crypto_data_t *plaintext,
4472     crypto_data_t *ciphertext)
4473 {
4474 	dprov_req_t *taskq_req;
4475 
4476 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4477 	    KM_NOSLEEP)) == NULL)
4478 		return (CRYPTO_HOST_MEMORY);
4479 
4480 	taskq_req->dr_dual_req.dr_signverify_ctx = signverify_ctx;
4481 	taskq_req->dr_dual_req.dr_cipher_ctx = cipher_ctx;
4482 	taskq_req->dr_dual_req.dr_plaintext = plaintext;
4483 	taskq_req->dr_dual_req.dr_ciphertext = ciphertext;
4484 
4485 	return (dprov_taskq_dispatch(softc, taskq_req,
4486 	    (task_func_t *)dprov_dual_task, KM_NOSLEEP));
4487 }
4488 
4489 /*
4490  * Helper function to submit dual cipher/mac operations to the taskq.
4491  * Returns one of the CRYPTO_ errors.
4492  */
4493 static int
4494 dprov_cipher_mac_submit_req(dprov_req_type_t req_type,
4495     dprov_state_t *softc, crypto_req_handle_t req, crypto_ctx_t *ctx,
4496     crypto_session_id_t sid, crypto_mechanism_t *cipher_mech,
4497     crypto_key_t *cipher_key, crypto_mechanism_t *mac_mech,
4498     crypto_key_t *mac_key, crypto_dual_data_t *dual_data,
4499     crypto_data_t *data, crypto_data_t *mac, int kmflag)
4500 {
4501 	dprov_req_t *taskq_req;
4502 
4503 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4504 		return (CRYPTO_HOST_MEMORY);
4505 
4506 	taskq_req->dr_cipher_mac_req.mr_session_id = sid;
4507 	taskq_req->dr_cipher_mac_req.mr_ctx = ctx;
4508 	taskq_req->dr_cipher_mac_req.mr_cipher_mech = cipher_mech;
4509 	taskq_req->dr_cipher_mac_req.mr_cipher_key = cipher_key;
4510 	taskq_req->dr_cipher_mac_req.mr_mac_mech = mac_mech;
4511 	taskq_req->dr_cipher_mac_req.mr_mac_key = mac_key;
4512 	taskq_req->dr_cipher_mac_req.mr_dual_data = dual_data;
4513 	taskq_req->dr_cipher_mac_req.mr_data = data;
4514 	taskq_req->dr_cipher_mac_req.mr_mac = mac;
4515 
4516 	return (dprov_taskq_dispatch(softc, taskq_req,
4517 	    (task_func_t *)dprov_cipher_mac_task, kmflag));
4518 }
4519 
4520 /*
4521  * Helper function to submit cipher operations to the taskq.
4522  * Returns one of the CRYPTO_ errors.
4523  */
4524 static int
4525 dprov_cipher_submit_req(dprov_req_type_t req_type,
4526     dprov_state_t *softc, crypto_req_handle_t req,
4527     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *plaintext,
4528     crypto_data_t *ciphertext, crypto_ctx_t *ctx, crypto_session_id_t sid,
4529     int kmflag)
4530 {
4531 	dprov_req_t *taskq_req;
4532 
4533 	if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
4534 		return (CRYPTO_HOST_MEMORY);
4535 
4536 	taskq_req->dr_cipher_req.dr_mechanism = mechanism;
4537 	taskq_req->dr_cipher_req.dr_ctx = ctx;
4538 	taskq_req->dr_cipher_req.dr_key = key;
4539 	taskq_req->dr_cipher_req.dr_plaintext = plaintext;
4540 	taskq_req->dr_cipher_req.dr_ciphertext = ciphertext;
4541 	taskq_req->dr_cipher_req.dr_session_id = sid;
4542 
4543 	return (dprov_taskq_dispatch(softc, taskq_req,
4544 	    (task_func_t *)dprov_cipher_task, kmflag));
4545 }
4546 
4547 /*
4548  * Helper function to submit random number operations to the taskq.
4549  * Returns one of the CRYPTO_ errors.
4550  */
4551 static int
4552 dprov_random_submit_req(dprov_req_type_t req_type,
4553     dprov_state_t *softc, crypto_req_handle_t req, uchar_t *buf, size_t len,
4554     crypto_session_id_t sid, uint_t entropy_est, uint32_t flags)
4555 {
4556 	dprov_req_t *taskq_req;
4557 
4558 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4559 	    KM_NOSLEEP)) == NULL)
4560 		return (CRYPTO_HOST_MEMORY);
4561 
4562 	taskq_req->dr_random_req.rr_buf = buf;
4563 	taskq_req->dr_random_req.rr_len = len;
4564 	taskq_req->dr_random_req.rr_session_id = sid;
4565 	taskq_req->dr_random_req.rr_entropy_est = entropy_est;
4566 	taskq_req->dr_random_req.rr_flags = flags;
4567 
4568 	return (dprov_taskq_dispatch(softc, taskq_req,
4569 	    (task_func_t *)dprov_random_task, KM_NOSLEEP));
4570 }
4571 
4572 
4573 /*
4574  * Helper function to submit session management operations to the taskq.
4575  * Returns one of the CRYPTO_ errors.
4576  */
4577 static int
4578 dprov_session_submit_req(dprov_req_type_t req_type,
4579     dprov_state_t *softc, crypto_req_handle_t req,
4580     crypto_session_id_t *session_id_ptr, crypto_session_id_t session_id,
4581     crypto_user_type_t user_type, char *pin, size_t pin_len)
4582 {
4583 	dprov_req_t *taskq_req;
4584 
4585 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4586 	    KM_NOSLEEP)) == NULL)
4587 		return (CRYPTO_HOST_MEMORY);
4588 
4589 	taskq_req->dr_session_req.sr_session_id_ptr = session_id_ptr;
4590 	taskq_req->dr_session_req.sr_session_id = session_id;
4591 	taskq_req->dr_session_req.sr_user_type = user_type;
4592 	taskq_req->dr_session_req.sr_pin = pin;
4593 	taskq_req->dr_session_req.sr_pin_len = pin_len;
4594 
4595 	return (dprov_taskq_dispatch(softc, taskq_req,
4596 	    (task_func_t *)dprov_session_task, KM_NOSLEEP));
4597 }
4598 
4599 /*
4600  * Helper function to submit object management operations to the taskq.
4601  * Returns one of the CRYPTO_ errors.
4602  */
4603 static int
4604 dprov_object_submit_req(dprov_req_type_t req_type,
4605     dprov_state_t *softc, crypto_req_handle_t req,
4606     crypto_session_id_t session_id, crypto_object_id_t object_id,
4607     crypto_object_attribute_t *template, uint_t attribute_count,
4608     crypto_object_id_t *object_id_ptr, size_t *object_size,
4609     void **find_pp, void *find_p, uint_t max_object_count,
4610     uint_t *object_count_ptr, int kmflag)
4611 {
4612 	dprov_req_t *taskq_req;
4613 
4614 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4615 	    kmflag)) == NULL)
4616 		return (CRYPTO_HOST_MEMORY);
4617 
4618 	taskq_req->dr_object_req.or_session_id = session_id;
4619 	taskq_req->dr_object_req.or_object_id = object_id;
4620 	taskq_req->dr_object_req.or_template = template;
4621 	taskq_req->dr_object_req.or_attribute_count = attribute_count;
4622 	taskq_req->dr_object_req.or_object_id_ptr = object_id_ptr;
4623 	taskq_req->dr_object_req.or_object_size = object_size;
4624 	taskq_req->dr_object_req.or_find_pp = find_pp;
4625 	taskq_req->dr_object_req.or_find_p = find_p;
4626 	taskq_req->dr_object_req.or_max_object_count = max_object_count;
4627 	taskq_req->dr_object_req.or_object_count_ptr = object_count_ptr;
4628 
4629 	return (dprov_taskq_dispatch(softc, taskq_req,
4630 	    (task_func_t *)dprov_object_task, KM_NOSLEEP));
4631 }
4632 
4633 /*
4634  * Helper function to submit key management operations to the taskq.
4635  * Returns one of the CRYPTO_ errors.
4636  */
4637 static int
4638 dprov_key_submit_req(dprov_req_type_t req_type,
4639     dprov_state_t *softc, crypto_req_handle_t req,
4640     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4641     crypto_object_attribute_t *template, uint_t attribute_count,
4642     crypto_object_id_t *object_id_ptr,
4643     crypto_object_attribute_t *private_key_template,
4644     uint_t private_key_attribute_count,
4645     crypto_object_id_t *private_key_object_id_ptr, crypto_key_t *key,
4646     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr)
4647 {
4648 	dprov_req_t *taskq_req;
4649 
4650 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4651 	    KM_NOSLEEP)) == NULL)
4652 		return (CRYPTO_HOST_MEMORY);
4653 
4654 	taskq_req->dr_key_req.kr_session_id = session_id;
4655 	taskq_req->dr_key_req.kr_mechanism = mechanism;
4656 	taskq_req->dr_key_req.kr_template = template;
4657 	taskq_req->dr_key_req.kr_attribute_count = attribute_count;
4658 	taskq_req->dr_key_req.kr_object_id_ptr = object_id_ptr;
4659 	taskq_req->dr_key_req.kr_private_key_template = private_key_template;
4660 	taskq_req->dr_key_req.kr_private_key_attribute_count =
4661 	    private_key_attribute_count;
4662 	taskq_req->dr_key_req.kr_private_key_object_id_ptr =
4663 	    private_key_object_id_ptr;
4664 	taskq_req->dr_key_req.kr_key = key;
4665 	taskq_req->dr_key_req.kr_wrapped_key = wrapped_key;
4666 	taskq_req->dr_key_req.kr_wrapped_key_len_ptr = wrapped_key_len_ptr;
4667 
4668 	return (dprov_taskq_dispatch(softc, taskq_req,
4669 	    (task_func_t *)dprov_key_task, KM_NOSLEEP));
4670 }
4671 
4672 /*
4673  * Helper function to submit provider management operations to the taskq.
4674  * Returns one of the CRYPTO_ errors.
4675  */
4676 static int
4677 dprov_mgmt_submit_req(dprov_req_type_t req_type,
4678     dprov_state_t *softc, crypto_req_handle_t req,
4679     crypto_session_id_t session_id, char *pin, size_t pin_len,
4680     char *old_pin, size_t old_pin_len, char *label,
4681     crypto_provider_ext_info_t *ext_info)
4682 {
4683 	dprov_req_t *taskq_req;
4684 
4685 	if ((taskq_req = dprov_alloc_req(req_type, softc, req,
4686 	    KM_NOSLEEP)) == NULL)
4687 		return (CRYPTO_HOST_MEMORY);
4688 
4689 	taskq_req->dr_mgmt_req.mr_session_id = session_id;
4690 	taskq_req->dr_mgmt_req.mr_pin = pin;
4691 	taskq_req->dr_mgmt_req.mr_pin_len = pin_len;
4692 	taskq_req->dr_mgmt_req.mr_old_pin = old_pin;
4693 	taskq_req->dr_mgmt_req.mr_old_pin_len = old_pin_len;
4694 	taskq_req->dr_mgmt_req.mr_label = label;
4695 	taskq_req->dr_mgmt_req.mr_ext_info = ext_info;
4696 
4697 	return (dprov_taskq_dispatch(softc, taskq_req,
4698 	    (task_func_t *)dprov_mgmt_task, KM_NOSLEEP));
4699 }
4700 
4701 /*
4702  * Helper function for taskq dispatcher routines. Notify the framework
4703  * that the operation corresponding to the specified request is done,
4704  * and pass it the error code. Finally, free the taskq_req.
4705  */
4706 static void
4707 dprov_op_done(dprov_req_t *taskq_req, int error)
4708 {
4709 	/* notify framework that request is completed */
4710 	crypto_op_notification(taskq_req->dr_kcf_req, error);
4711 
4712 	/* free taskq request structure */
4713 	kmem_free(taskq_req, sizeof (dprov_req_t));
4714 }
4715 
4716 /*
4717  * taskq dispatcher function for digest operations.
4718  */
4719 static void
4720 dprov_digest_task(dprov_req_t *taskq_req)
4721 {
4722 	kcf_provider_desc_t *pd;
4723 	dprov_state_t *softc;
4724 	/* LINTED E_FUNC_SET_NOT_USED */
4725 	int instance;
4726 	int error = CRYPTO_NOT_SUPPORTED;
4727 	crypto_ctx_t *ctx = taskq_req->dr_digest_req.dr_ctx;
4728 	crypto_mechanism_t mech;
4729 
4730 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4731 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: started\n", instance));
4732 
4733 	switch (taskq_req->dr_type) {
4734 
4735 	case DPROV_REQ_DIGEST_INIT:
4736 		/* allocate a dprov-private context */
4737 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4738 		    CRYPTO_SUCCESS)
4739 			break;
4740 
4741 		/* structure assignment */
4742 		mech = *taskq_req->dr_digest_req.dr_mechanism;
4743 
4744 		/* get the software provider for this mechanism */
4745 		if ((error = dprov_get_sw_prov(
4746 		    taskq_req->dr_digest_req.dr_mechanism, &pd,
4747 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4748 			break;
4749 
4750 		/* Use a session id of zero since we use a software provider */
4751 		error = crypto_digest_init_prov(pd, 0, &mech,
4752 		    &DPROV_CTX_SINGLE(ctx), NULL);
4753 
4754 		/* release provider reference */
4755 		KCF_PROV_REFRELE(pd);
4756 		break;
4757 
4758 	case DPROV_REQ_DIGEST:
4759 		error = crypto_digest_single(DPROV_CTX_SINGLE(ctx),
4760 		    taskq_req->dr_digest_req.dr_data,
4761 		    taskq_req->dr_digest_req.dr_digest, NULL);
4762 
4763 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4764 			DPROV_CTX_SINGLE(ctx) = NULL;
4765 			(void) dprov_free_context(ctx);
4766 		}
4767 		break;
4768 
4769 	case DPROV_REQ_DIGEST_UPDATE:
4770 		error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
4771 		    taskq_req->dr_digest_req.dr_data, NULL);
4772 		break;
4773 
4774 	case DPROV_REQ_DIGEST_KEY: {
4775 		crypto_data_t data;
4776 		crypto_key_t key;
4777 		size_t len;
4778 
4779 		mutex_enter(&softc->ds_lock);
4780 		error = dprov_key_value_secret(softc, ctx->cc_session,
4781 		    taskq_req->dr_type, taskq_req->dr_digest_req.dr_key, &key);
4782 		mutex_exit(&softc->ds_lock);
4783 		if (error != CRYPTO_SUCCESS)
4784 			break;
4785 
4786 		/* key lengths are specified in bits */
4787 		len = CRYPTO_BITS2BYTES(key.ck_length);
4788 		data.cd_format = CRYPTO_DATA_RAW;
4789 		data.cd_offset = 0;
4790 		data.cd_length = len;
4791 		data.cd_raw.iov_base = key.ck_data;
4792 		data.cd_raw.iov_len = len;
4793 		error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
4794 		    &data, NULL);
4795 		break;
4796 	}
4797 
4798 	case DPROV_REQ_DIGEST_FINAL:
4799 		error = crypto_digest_final(DPROV_CTX_SINGLE(ctx),
4800 		    taskq_req->dr_digest_req.dr_digest, NULL);
4801 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4802 			DPROV_CTX_SINGLE(ctx) = NULL;
4803 			(void) dprov_free_context(ctx);
4804 		}
4805 		break;
4806 
4807 	case DPROV_REQ_DIGEST_ATOMIC:
4808 		/* structure assignment */
4809 		mech = *taskq_req->dr_digest_req.dr_mechanism;
4810 
4811 		/* get the software provider for this mechanism */
4812 		if ((error = dprov_get_sw_prov(
4813 		    taskq_req->dr_digest_req.dr_mechanism, &pd,
4814 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4815 			break;
4816 
4817 		/* use a session id of zero since we use a software provider */
4818 		error = crypto_digest_prov(pd, 0, &mech,
4819 		    taskq_req->dr_digest_req.dr_data,
4820 		    taskq_req->dr_digest_req.dr_digest, NULL);
4821 
4822 		/* release provider reference */
4823 		KCF_PROV_REFRELE(pd);
4824 
4825 		break;
4826 	}
4827 
4828 	dprov_op_done(taskq_req, error);
4829 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: end\n", instance));
4830 }
4831 
4832 /*
4833  * taskq dispatcher function for mac operations.
4834  */
4835 static void
4836 dprov_mac_task(dprov_req_t *taskq_req)
4837 {
4838 	kcf_provider_desc_t *pd;
4839 	dprov_state_t *softc;
4840 	/* LINTED E_FUNC_SET_NOT_USED */
4841 	int instance;
4842 	int error = CRYPTO_NOT_SUPPORTED;
4843 	crypto_ctx_t *ctx = taskq_req->dr_mac_req.dr_ctx;
4844 	crypto_key_t key;
4845 	crypto_mechanism_t mech;
4846 
4847 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4848 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: started\n", instance));
4849 
4850 	switch (taskq_req->dr_type) {
4851 
4852 	case DPROV_REQ_MAC_INIT:
4853 		/* allocate a dprov-private context */
4854 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4855 		    CRYPTO_SUCCESS)
4856 			break;
4857 
4858 		/* get key value */
4859 		mutex_enter(&softc->ds_lock);
4860 		error = dprov_key_value_secret(softc, ctx->cc_session,
4861 		    taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
4862 		mutex_exit(&softc->ds_lock);
4863 		if (error != CRYPTO_SUCCESS)
4864 			break;
4865 
4866 		/* structure assignment */
4867 		mech = *taskq_req->dr_mac_req.dr_mechanism;
4868 
4869 		/* get the software provider for this mechanism */
4870 		if ((error = dprov_get_sw_prov(
4871 		    taskq_req->dr_mac_req.dr_mechanism, &pd,
4872 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4873 			break;
4874 
4875 		/* Use a session id of zero since we use a software provider */
4876 		error = crypto_mac_init_prov(pd, 0, &mech, &key, NULL,
4877 		    &DPROV_CTX_SINGLE(ctx), NULL);
4878 
4879 		/* release provider reference */
4880 		KCF_PROV_REFRELE(pd);
4881 		break;
4882 
4883 	case DPROV_REQ_MAC:
4884 		error = crypto_mac_single(DPROV_CTX_SINGLE(ctx),
4885 		    taskq_req->dr_mac_req.dr_data,
4886 		    taskq_req->dr_mac_req.dr_mac, NULL);
4887 
4888 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4889 			DPROV_CTX_SINGLE(ctx) = NULL;
4890 			(void) dprov_free_context(ctx);
4891 		}
4892 		break;
4893 
4894 	case DPROV_REQ_MAC_UPDATE:
4895 		error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
4896 		    taskq_req->dr_mac_req.dr_data, NULL);
4897 		break;
4898 
4899 	case DPROV_REQ_MAC_FINAL:
4900 		error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
4901 		    taskq_req->dr_mac_req.dr_mac, NULL);
4902 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
4903 			DPROV_CTX_SINGLE(ctx) = NULL;
4904 			(void) dprov_free_context(ctx);
4905 		}
4906 		break;
4907 
4908 	case DPROV_REQ_MAC_ATOMIC:
4909 	case DPROV_REQ_MAC_VERIFY_ATOMIC:
4910 		/* get key value */
4911 		mutex_enter(&softc->ds_lock);
4912 		error = dprov_key_value_secret(softc,
4913 		    taskq_req->dr_mac_req.dr_session_id,
4914 		    taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
4915 		mutex_exit(&softc->ds_lock);
4916 		if (error != CRYPTO_SUCCESS)
4917 			break;
4918 
4919 		/* structure assignment */
4920 		mech = *taskq_req->dr_mac_req.dr_mechanism;
4921 
4922 		/* get the software provider for this mechanism */
4923 		if ((error = dprov_get_sw_prov(
4924 		    taskq_req->dr_mac_req.dr_mechanism, &pd,
4925 		    &mech.cm_type)) != CRYPTO_SUCCESS)
4926 			break;
4927 
4928 		/* use a session id of zero since we use a software provider */
4929 		if (taskq_req->dr_type == DPROV_REQ_MAC_ATOMIC)
4930 			error = crypto_mac_prov(pd, 0, &mech,
4931 			    taskq_req->dr_mac_req.dr_data,
4932 			    &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL);
4933 		else
4934 			error = crypto_mac_verify_prov(pd, 0, &mech,
4935 			    taskq_req->dr_mac_req.dr_data,
4936 			    &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL);
4937 
4938 		/* release provider reference */
4939 		KCF_PROV_REFRELE(pd);
4940 
4941 		break;
4942 	}
4943 
4944 	dprov_op_done(taskq_req, error);
4945 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
4946 }
4947 
4948 /*
4949  * taskq dispatcher function for sign operations.
4950  */
4951 static void
4952 dprov_sign_task(dprov_req_t *taskq_req)
4953 {
4954 	kcf_provider_desc_t *pd;
4955 	dprov_state_t *softc;
4956 	/* LINTED E_FUNC_SET_NOT_USED */
4957 	int instance;
4958 	int error = CRYPTO_NOT_SUPPORTED;
4959 	crypto_ctx_t *ctx = taskq_req->dr_mac_req.dr_ctx;
4960 	crypto_key_t key, *keyp;
4961 	crypto_mechanism_t mech;
4962 
4963 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
4964 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: started\n", instance));
4965 
4966 	switch (taskq_req->dr_type) {
4967 
4968 	case DPROV_REQ_SIGN_INIT:
4969 	case DPROV_REQ_SIGN_RECOVER_INIT:
4970 		/* allocate a dprov-private context */
4971 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
4972 		    CRYPTO_SUCCESS)
4973 			break;
4974 
4975 		/* structure assignment */
4976 		mech = *taskq_req->dr_sign_req.sr_mechanism;
4977 
4978 		mutex_enter(&softc->ds_lock);
4979 		/* get key value for secret key algorithms */
4980 		if (is_publickey_mech(mech.cm_type)) {
4981 			if ((error = dprov_key_attr_asymmetric(softc,
4982 			    ctx->cc_session, taskq_req->dr_type,
4983 			    taskq_req->dr_sign_req.sr_key, &key))
4984 			    != CRYPTO_SUCCESS) {
4985 				mutex_exit(&softc->ds_lock);
4986 				break;
4987 			}
4988 			keyp = &key;
4989 		} else {
4990 			if ((error = dprov_key_value_secret(softc,
4991 			    ctx->cc_session, taskq_req->dr_type,
4992 			    taskq_req->dr_sign_req.sr_key, &key))
4993 			    != CRYPTO_SUCCESS) {
4994 				mutex_exit(&softc->ds_lock);
4995 				break;
4996 			}
4997 			keyp = &key;
4998 		}
4999 		mutex_exit(&softc->ds_lock);
5000 
5001 		/* get the software provider for this mechanism */
5002 		if ((error = dprov_get_sw_prov(
5003 		    taskq_req->dr_sign_req.sr_mechanism, &pd,
5004 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5005 			break;
5006 
5007 		/* Use a session id of zero since we use a software provider */
5008 		if (taskq_req->dr_type == DPROV_REQ_SIGN_INIT)
5009 			error = crypto_sign_init_prov(pd, 0, &mech, keyp,
5010 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5011 		else
5012 			error = crypto_sign_recover_init_prov(pd, 0, &mech,
5013 			    keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5014 
5015 		/* release provider reference */
5016 		KCF_PROV_REFRELE(pd);
5017 
5018 		break;
5019 
5020 	case DPROV_REQ_SIGN:
5021 		error = crypto_sign_single(DPROV_CTX_SINGLE(ctx),
5022 		    taskq_req->dr_sign_req.sr_data,
5023 		    taskq_req->dr_sign_req.sr_signature, NULL);
5024 
5025 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5026 			DPROV_CTX_SINGLE(ctx) = NULL;
5027 			(void) dprov_free_context(ctx);
5028 		}
5029 		break;
5030 
5031 	case DPROV_REQ_SIGN_UPDATE:
5032 		error = crypto_sign_update(DPROV_CTX_SINGLE(ctx),
5033 		    taskq_req->dr_sign_req.sr_data, NULL);
5034 		break;
5035 
5036 	case DPROV_REQ_SIGN_FINAL:
5037 		error = crypto_sign_final(DPROV_CTX_SINGLE(ctx),
5038 		    taskq_req->dr_sign_req.sr_signature, NULL);
5039 
5040 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5041 			DPROV_CTX_SINGLE(ctx) = NULL;
5042 			(void) dprov_free_context(ctx);
5043 		}
5044 		break;
5045 
5046 	case DPROV_REQ_SIGN_ATOMIC:
5047 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
5048 		/* structure assignment */
5049 		mech = *taskq_req->dr_sign_req.sr_mechanism;
5050 
5051 		mutex_enter(&softc->ds_lock);
5052 		/* get key value for secret key algorithms */
5053 		if (is_publickey_mech(mech.cm_type)) {
5054 			if ((error = dprov_key_attr_asymmetric(softc,
5055 			    taskq_req->dr_sign_req.sr_session_id,
5056 			    taskq_req->dr_type,
5057 			    taskq_req->dr_sign_req.sr_key, &key))
5058 			    != CRYPTO_SUCCESS) {
5059 				mutex_exit(&softc->ds_lock);
5060 				break;
5061 			}
5062 			keyp = &key;
5063 		} else {
5064 			if ((error = dprov_key_value_secret(softc,
5065 			    taskq_req->dr_sign_req.sr_session_id,
5066 			    taskq_req->dr_type,
5067 			    taskq_req->dr_sign_req.sr_key, &key))
5068 			    != CRYPTO_SUCCESS) {
5069 				mutex_exit(&softc->ds_lock);
5070 				break;
5071 			}
5072 			keyp = &key;
5073 		}
5074 		mutex_exit(&softc->ds_lock);
5075 
5076 		/* get the software provider for this mechanism */
5077 		if ((error = dprov_get_sw_prov(
5078 		    taskq_req->dr_sign_req.sr_mechanism, &pd,
5079 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5080 			break;
5081 
5082 		/* Use a session id of zero since we use a software provider */
5083 		if (taskq_req->dr_type == DPROV_REQ_SIGN_ATOMIC)
5084 			error = crypto_sign_prov(pd, 0, &mech, keyp,
5085 			    taskq_req->dr_sign_req.sr_data,
5086 			    NULL, taskq_req->dr_sign_req.sr_signature, NULL);
5087 		else
5088 			error = crypto_sign_recover_prov(pd, 0, &mech, keyp,
5089 			    taskq_req->dr_sign_req.sr_data,
5090 			    NULL, taskq_req->dr_sign_req.sr_signature, NULL);
5091 
5092 		/* release provider reference */
5093 		KCF_PROV_REFRELE(pd);
5094 		break;
5095 
5096 	case DPROV_REQ_SIGN_RECOVER:
5097 		error = crypto_sign_recover_single(DPROV_CTX_SINGLE(ctx),
5098 		    taskq_req->dr_sign_req.sr_data,
5099 		    taskq_req->dr_sign_req.sr_signature, NULL);
5100 
5101 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5102 			DPROV_CTX_SINGLE(ctx) = NULL;
5103 			(void) dprov_free_context(ctx);
5104 		}
5105 		break;
5106 	}
5107 
5108 	dprov_op_done(taskq_req, error);
5109 	DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: end\n", instance));
5110 }
5111 
5112 /*
5113  * taskq dispatcher function for verify operations.
5114  */
5115 static void
5116 dprov_verify_task(dprov_req_t *taskq_req)
5117 {
5118 	kcf_provider_desc_t *pd;
5119 	dprov_state_t *softc;
5120 	/* LINTED E_FUNC_SET_NOT_USED */
5121 	int instance;
5122 	int error = CRYPTO_NOT_SUPPORTED;
5123 	crypto_ctx_t *ctx = taskq_req->dr_verify_req.vr_ctx;
5124 	crypto_key_t key, *keyp;
5125 	crypto_mechanism_t mech;
5126 
5127 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5128 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: started\n", instance));
5129 
5130 	switch (taskq_req->dr_type) {
5131 
5132 	case DPROV_REQ_VERIFY_INIT:
5133 	case DPROV_REQ_VERIFY_RECOVER_INIT:
5134 		/* allocate a dprov-private context */
5135 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5136 		    CRYPTO_SUCCESS)
5137 			break;
5138 
5139 		/* structure assignment */
5140 		mech = *taskq_req->dr_verify_req.vr_mechanism;
5141 
5142 		mutex_enter(&softc->ds_lock);
5143 		/* get key value for secret key algorithms */
5144 		if (is_publickey_mech(mech.cm_type)) {
5145 			if ((error = dprov_key_attr_asymmetric(softc,
5146 			    ctx->cc_session, taskq_req->dr_type,
5147 			    taskq_req->dr_verify_req.vr_key, &key))
5148 			    != CRYPTO_SUCCESS) {
5149 				mutex_exit(&softc->ds_lock);
5150 				break;
5151 			}
5152 			keyp = &key;
5153 		} else {
5154 			if ((error = dprov_key_value_secret(softc,
5155 			    ctx->cc_session, taskq_req->dr_type,
5156 			    taskq_req->dr_verify_req.vr_key, &key))
5157 			    != CRYPTO_SUCCESS) {
5158 				mutex_exit(&softc->ds_lock);
5159 				break;
5160 			}
5161 			keyp = &key;
5162 		}
5163 		mutex_exit(&softc->ds_lock);
5164 
5165 		/* get the software provider for this mechanism */
5166 		if ((error = dprov_get_sw_prov(
5167 		    taskq_req->dr_verify_req.vr_mechanism, &pd,
5168 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5169 			break;
5170 
5171 		/* Use a session id of zero since we use a software provider */
5172 		if (taskq_req->dr_type == DPROV_REQ_VERIFY_INIT)
5173 			error = crypto_verify_init_prov(pd, 0, &mech, keyp,
5174 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5175 		else
5176 			error = crypto_verify_recover_init_prov(pd, 0, &mech,
5177 			    keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5178 
5179 		/* release provider reference */
5180 		KCF_PROV_REFRELE(pd);
5181 
5182 		break;
5183 
5184 	case DPROV_REQ_VERIFY:
5185 		error = crypto_verify_single(DPROV_CTX_SINGLE(ctx),
5186 		    taskq_req->dr_verify_req.vr_data,
5187 		    taskq_req->dr_verify_req.vr_signature, NULL);
5188 
5189 		ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
5190 		DPROV_CTX_SINGLE(ctx) = NULL;
5191 		(void) dprov_free_context(ctx);
5192 		break;
5193 
5194 	case DPROV_REQ_VERIFY_UPDATE:
5195 		error = crypto_verify_update(DPROV_CTX_SINGLE(ctx),
5196 		    taskq_req->dr_verify_req.vr_data, NULL);
5197 		break;
5198 
5199 	case DPROV_REQ_VERIFY_FINAL:
5200 		error = crypto_verify_final(DPROV_CTX_SINGLE(ctx),
5201 		    taskq_req->dr_verify_req.vr_signature, NULL);
5202 
5203 		ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
5204 		DPROV_CTX_SINGLE(ctx) = NULL;
5205 		(void) dprov_free_context(ctx);
5206 		break;
5207 
5208 	case DPROV_REQ_VERIFY_ATOMIC:
5209 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
5210 		/* structure assignment */
5211 		mech = *taskq_req->dr_verify_req.vr_mechanism;
5212 
5213 		mutex_enter(&softc->ds_lock);
5214 		/* get key value for secret key algorithms */
5215 		if (is_publickey_mech(mech.cm_type)) {
5216 			if ((error = dprov_key_attr_asymmetric(softc,
5217 			    taskq_req->dr_verify_req.vr_session_id,
5218 			    taskq_req->dr_type,
5219 			    taskq_req->dr_verify_req.vr_key, &key))
5220 			    != CRYPTO_SUCCESS) {
5221 				mutex_exit(&softc->ds_lock);
5222 				break;
5223 			}
5224 			keyp = &key;
5225 		} else {
5226 			if ((error = dprov_key_value_secret(softc,
5227 			    taskq_req->dr_verify_req.vr_session_id,
5228 			    taskq_req->dr_type,
5229 			    taskq_req->dr_verify_req.vr_key, &key))
5230 			    != CRYPTO_SUCCESS) {
5231 				mutex_exit(&softc->ds_lock);
5232 				break;
5233 			}
5234 			keyp = &key;
5235 		}
5236 		mutex_exit(&softc->ds_lock);
5237 
5238 		/* get the software provider for this mechanism */
5239 		if ((error = dprov_get_sw_prov(
5240 		    taskq_req->dr_verify_req.vr_mechanism, &pd,
5241 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5242 			break;
5243 
5244 		/* Use a session id of zero since we use a software provider */
5245 		if (taskq_req->dr_type == DPROV_REQ_VERIFY_ATOMIC)
5246 			error = crypto_verify_prov(pd, 0, &mech, keyp,
5247 			    taskq_req->dr_verify_req.vr_data,
5248 			    NULL, taskq_req->dr_verify_req.vr_signature, NULL);
5249 		else
5250 			/*
5251 			 * crypto_verify_recover_prov() has different argument
5252 			 * order than crypto_verify_prov().
5253 			 */
5254 			error = crypto_verify_recover_prov(pd, 0, &mech, keyp,
5255 			    taskq_req->dr_verify_req.vr_signature,
5256 			    NULL, taskq_req->dr_verify_req.vr_data, NULL);
5257 
5258 		/* release provider reference */
5259 		KCF_PROV_REFRELE(pd);
5260 		break;
5261 
5262 	case DPROV_REQ_VERIFY_RECOVER:
5263 		/*
5264 		 * crypto_verify_recover_single() has different argument
5265 		 * order than crypto_verify_single().
5266 		 */
5267 		error = crypto_verify_recover_single(DPROV_CTX_SINGLE(ctx),
5268 		    taskq_req->dr_verify_req.vr_signature,
5269 		    taskq_req->dr_verify_req.vr_data, NULL);
5270 
5271 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5272 			DPROV_CTX_SINGLE(ctx) = NULL;
5273 			(void) dprov_free_context(ctx);
5274 		}
5275 		break;
5276 	}
5277 
5278 	dprov_op_done(taskq_req, error);
5279 	DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: end\n", instance));
5280 }
5281 
5282 /*
5283  * taskq dispatcher function for dual operations.
5284  */
5285 static void
5286 dprov_dual_task(dprov_req_t *taskq_req)
5287 {
5288 	dprov_state_t *softc;
5289 	/* LINTED E_FUNC_SET_NOT_USED */
5290 	int instance;
5291 	int error = CRYPTO_NOT_SUPPORTED;
5292 	crypto_ctx_t *signverify_ctx = taskq_req->dr_dual_req.dr_signverify_ctx;
5293 	crypto_ctx_t *cipher_ctx = taskq_req->dr_dual_req.dr_cipher_ctx;
5294 
5295 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5296 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: started\n", instance));
5297 
5298 	switch (taskq_req->dr_type) {
5299 
5300 	case DPROV_REQ_DIGEST_ENCRYPT_UPDATE:
5301 		error = crypto_digest_encrypt_update(
5302 		    DPROV_CTX_SINGLE(signverify_ctx),
5303 		    DPROV_CTX_SINGLE(cipher_ctx),
5304 		    taskq_req->dr_dual_req.dr_plaintext,
5305 		    taskq_req->dr_dual_req.dr_ciphertext, NULL);
5306 		break;
5307 
5308 	case DPROV_REQ_DECRYPT_DIGEST_UPDATE:
5309 		error = crypto_decrypt_digest_update(
5310 		    DPROV_CTX_SINGLE(cipher_ctx),
5311 		    DPROV_CTX_SINGLE(signverify_ctx),
5312 		    taskq_req->dr_dual_req.dr_ciphertext,
5313 		    taskq_req->dr_dual_req.dr_plaintext, NULL);
5314 		break;
5315 
5316 	case DPROV_REQ_SIGN_ENCRYPT_UPDATE:
5317 		error = crypto_sign_encrypt_update(
5318 		    DPROV_CTX_SINGLE(signverify_ctx),
5319 		    DPROV_CTX_SINGLE(cipher_ctx),
5320 		    taskq_req->dr_dual_req.dr_plaintext,
5321 		    taskq_req->dr_dual_req.dr_ciphertext, NULL);
5322 		break;
5323 
5324 	case DPROV_REQ_DECRYPT_VERIFY_UPDATE:
5325 		error = crypto_decrypt_verify_update(
5326 		    DPROV_CTX_SINGLE(cipher_ctx),
5327 		    DPROV_CTX_SINGLE(signverify_ctx),
5328 		    taskq_req->dr_dual_req.dr_ciphertext,
5329 		    taskq_req->dr_dual_req.dr_plaintext, NULL);
5330 		break;
5331 	}
5332 
5333 	dprov_op_done(taskq_req, error);
5334 	DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: end\n", instance));
5335 }
5336 
5337 /*
5338  * taskq dispatcher function for cipher operations.
5339  */
5340 static void
5341 dprov_cipher_task(dprov_req_t *taskq_req)
5342 {
5343 	kcf_provider_desc_t *pd;
5344 	dprov_state_t *softc;
5345 	/* LINTED E_FUNC_SET_NOT_USED */
5346 	int instance;
5347 	int error = CRYPTO_NOT_SUPPORTED;
5348 	crypto_ctx_t *ctx = taskq_req->dr_cipher_req.dr_ctx;
5349 	crypto_key_t key, *keyp;
5350 	crypto_mechanism_t mech;
5351 
5352 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5353 	DPROV_DEBUG(D_CIPHER, ("(%d) dprov_cipher_task: started\n", instance));
5354 
5355 	switch (taskq_req->dr_type) {
5356 
5357 	case DPROV_REQ_ENCRYPT_INIT:
5358 	case DPROV_REQ_DECRYPT_INIT:
5359 		/* allocate a dprov-private context */
5360 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5361 		    CRYPTO_SUCCESS)
5362 			break;
5363 
5364 		/* structure assignment */
5365 		mech = *taskq_req->dr_cipher_req.dr_mechanism;
5366 
5367 		mutex_enter(&softc->ds_lock);
5368 		/* get key value for secret key algorithms */
5369 		if (is_publickey_mech(mech.cm_type)) {
5370 			if ((error = dprov_key_attr_asymmetric(softc,
5371 			    ctx->cc_session, taskq_req->dr_type,
5372 			    taskq_req->dr_cipher_req.dr_key, &key))
5373 			    != CRYPTO_SUCCESS) {
5374 				mutex_exit(&softc->ds_lock);
5375 				break;
5376 			}
5377 			keyp = &key;
5378 		} else {
5379 			if ((error = dprov_key_value_secret(softc,
5380 			    ctx->cc_session, taskq_req->dr_type,
5381 			    taskq_req->dr_cipher_req.dr_key, &key))
5382 			    != CRYPTO_SUCCESS) {
5383 				mutex_exit(&softc->ds_lock);
5384 				break;
5385 			}
5386 			keyp = &key;
5387 		}
5388 		mutex_exit(&softc->ds_lock);
5389 
5390 		/* get the software provider for this mechanism */
5391 		if ((error = dprov_get_sw_prov(
5392 		    taskq_req->dr_cipher_req.dr_mechanism, &pd,
5393 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5394 			break;
5395 
5396 		/* Use a session id of zero since we use a software provider */
5397 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_INIT)
5398 			error = crypto_encrypt_init_prov(pd, 0, &mech, keyp,
5399 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5400 		else
5401 			error = crypto_decrypt_init_prov(pd, 0, &mech, keyp,
5402 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5403 
5404 		/* release provider reference */
5405 		KCF_PROV_REFRELE(pd);
5406 		break;
5407 
5408 	case DPROV_REQ_ENCRYPT:
5409 		error = crypto_encrypt_single(DPROV_CTX_SINGLE(ctx),
5410 		    taskq_req->dr_cipher_req.dr_plaintext,
5411 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5412 
5413 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5414 			DPROV_CTX_SINGLE(ctx) = NULL;
5415 			(void) dprov_free_context(ctx);
5416 		}
5417 		break;
5418 
5419 	case DPROV_REQ_DECRYPT:
5420 		error = crypto_decrypt_single(DPROV_CTX_SINGLE(ctx),
5421 		    taskq_req->dr_cipher_req.dr_ciphertext,
5422 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5423 
5424 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5425 			DPROV_CTX_SINGLE(ctx) = NULL;
5426 			(void) dprov_free_context(ctx);
5427 		}
5428 		break;
5429 
5430 	case DPROV_REQ_ENCRYPT_UPDATE:
5431 		error = crypto_encrypt_update(DPROV_CTX_SINGLE(ctx),
5432 		    taskq_req->dr_cipher_req.dr_plaintext,
5433 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5434 		break;
5435 
5436 	case DPROV_REQ_DECRYPT_UPDATE:
5437 		error = crypto_decrypt_update(DPROV_CTX_SINGLE(ctx),
5438 		    taskq_req->dr_cipher_req.dr_ciphertext,
5439 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5440 		break;
5441 
5442 	case DPROV_REQ_ENCRYPT_FINAL:
5443 		error = crypto_encrypt_final(DPROV_CTX_SINGLE(ctx),
5444 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5445 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5446 			DPROV_CTX_SINGLE(ctx) = NULL;
5447 			(void) dprov_free_context(ctx);
5448 		}
5449 		break;
5450 
5451 	case DPROV_REQ_DECRYPT_FINAL:
5452 		error = crypto_decrypt_final(DPROV_CTX_SINGLE(ctx),
5453 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5454 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5455 			DPROV_CTX_SINGLE(ctx) = NULL;
5456 			(void) dprov_free_context(ctx);
5457 		}
5458 		break;
5459 
5460 	case DPROV_REQ_ENCRYPT_ATOMIC:
5461 	case DPROV_REQ_DECRYPT_ATOMIC:
5462 		/* structure assignment */
5463 		mech = *taskq_req->dr_cipher_req.dr_mechanism;
5464 
5465 		mutex_enter(&softc->ds_lock);
5466 		/* get key value for secret key algorithms */
5467 		if (is_publickey_mech(mech.cm_type)) {
5468 			if ((error = dprov_key_attr_asymmetric(softc,
5469 			    taskq_req->dr_cipher_req.dr_session_id,
5470 			    taskq_req->dr_type,
5471 			    taskq_req->dr_cipher_req.dr_key,
5472 			    &key)) != CRYPTO_SUCCESS) {
5473 				mutex_exit(&softc->ds_lock);
5474 				break;
5475 			}
5476 			keyp = &key;
5477 		} else {
5478 			if ((error = dprov_key_value_secret(softc,
5479 			    taskq_req->dr_cipher_req.dr_session_id,
5480 			    taskq_req->dr_type, taskq_req->dr_cipher_req.dr_key,
5481 			    &key))
5482 			    != CRYPTO_SUCCESS) {
5483 				mutex_exit(&softc->ds_lock);
5484 				break;
5485 			}
5486 			keyp = &key;
5487 		}
5488 		mutex_exit(&softc->ds_lock);
5489 
5490 		/* get the software provider for this mechanism */
5491 		if ((error = dprov_get_sw_prov(
5492 		    taskq_req->dr_cipher_req.dr_mechanism, &pd,
5493 		    &mech.cm_type)) != CRYPTO_SUCCESS)
5494 			break;
5495 
5496 		/* use a session id of zero since we use a software provider */
5497 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_ATOMIC)
5498 			error = crypto_encrypt_prov(pd, 0, &mech,
5499 			    taskq_req->dr_cipher_req.dr_plaintext,
5500 			    keyp, NULL,
5501 			    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
5502 		else
5503 			error = crypto_decrypt_prov(pd, 0, &mech,
5504 			    taskq_req->dr_cipher_req.dr_ciphertext,
5505 			    keyp, NULL,
5506 			    taskq_req->dr_cipher_req.dr_plaintext, NULL);
5507 
5508 		/* release provider reference */
5509 		KCF_PROV_REFRELE(pd);
5510 
5511 		break;
5512 	}
5513 
5514 	dprov_op_done(taskq_req, error);
5515 	DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
5516 }
5517 
5518 /*
5519  * Helper function for the cipher/mac dual operation taskq dispatch
5520  * function. Initialize the cipher and mac key values and find the
5521  * providers that can process the request for the specified mechanisms.
5522  */
5523 static int
5524 dprov_cipher_mac_key_pd(dprov_state_t *softc, crypto_session_id_t sid,
5525     dprov_req_t *taskq_req, crypto_key_t *cipher_key, crypto_key_t *mac_key,
5526     kcf_provider_desc_t **cipher_pd, kcf_provider_desc_t **mac_pd,
5527     crypto_mech_type_t *cipher_mech_type, crypto_mech_type_t *mac_mech_type)
5528 {
5529 	int error;
5530 
5531 	/* get the cipher key value */
5532 	mutex_enter(&softc->ds_lock);
5533 	error = dprov_key_value_secret(softc, sid, DPROV_REQ_ENCRYPT_ATOMIC,
5534 	    taskq_req->dr_cipher_mac_req.mr_cipher_key, cipher_key);
5535 	if (error != CRYPTO_SUCCESS) {
5536 		mutex_exit(&softc->ds_lock);
5537 		return (error);
5538 	}
5539 
5540 	/* get the mac key value */
5541 	error = dprov_key_value_secret(softc, sid, DPROV_REQ_MAC_ATOMIC,
5542 	    taskq_req->dr_cipher_mac_req.mr_mac_key, mac_key);
5543 	mutex_exit(&softc->ds_lock);
5544 	if (error != CRYPTO_SUCCESS)
5545 		return (error);
5546 
5547 	/* get the SW provider to perform the cipher operation */
5548 	if ((error = dprov_get_sw_prov(
5549 	    taskq_req->dr_cipher_mac_req.mr_cipher_mech, cipher_pd,
5550 	    cipher_mech_type)) != CRYPTO_SUCCESS)
5551 		return (error);
5552 
5553 	/* get the SW provider to perform the mac operation */
5554 	error = dprov_get_sw_prov(taskq_req->dr_cipher_mac_req.mr_mac_mech,
5555 	    mac_pd, mac_mech_type);
5556 
5557 	return (error);
5558 }
5559 
5560 /*
5561  * taskq dispatcher function for cipher/mac dual operations.
5562  */
5563 static void
5564 dprov_cipher_mac_task(dprov_req_t *taskq_req)
5565 {
5566 	dprov_state_t *softc;
5567 	/* LINTED E_FUNC_SET_NOT_USED */
5568 	int instance;
5569 	int error = CRYPTO_NOT_SUPPORTED;
5570 	crypto_ctx_t *ctx = taskq_req->dr_cipher_mac_req.mr_ctx;
5571 	kcf_provider_desc_t *cipher_pd;
5572 	kcf_provider_desc_t *mac_pd;
5573 	crypto_key_t cipher_key;
5574 	crypto_key_t mac_key;
5575 	crypto_dual_data_t *dual_data =
5576 	    taskq_req->dr_cipher_mac_req.mr_dual_data;
5577 	crypto_data_t cipher_data;
5578 	crypto_data_t mac_data;
5579 	crypto_mechanism_t cipher_mech, mac_mech;
5580 	crypto_session_id_t session_id;
5581 
5582 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5583 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: started\n",
5584 	    instance));
5585 
5586 	switch (taskq_req->dr_type) {
5587 	case DPROV_REQ_ENCRYPT_MAC_INIT:
5588 	case DPROV_REQ_MAC_DECRYPT_INIT:
5589 		/* structure assignment */
5590 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5591 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5592 
5593 		/* get the keys values and providers to use for operations */
5594 		if ((error = dprov_cipher_mac_key_pd(softc, ctx->cc_session,
5595 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5596 		    &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
5597 			break;
5598 
5599 		/* allocate a dprov-private context */
5600 		if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5601 		    CRYPTO_SUCCESS)
5602 			break;
5603 
5604 		if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_MAC_INIT)
5605 			/* do the encryption initialization */
5606 			error = crypto_encrypt_init_prov(cipher_pd, 0,
5607 			    &cipher_mech, &cipher_key, NULL,
5608 			    &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
5609 		else
5610 			/* do the decryption initialization */
5611 			error = crypto_decrypt_init_prov(cipher_pd, 0,
5612 			    &cipher_mech, &cipher_key, NULL,
5613 			    &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
5614 		if (error != CRYPTO_SUCCESS)
5615 			break;
5616 
5617 		/* do the mac initialization */
5618 		if ((error = crypto_mac_init_prov(mac_pd, 0,
5619 		    &mac_mech, &mac_key, NULL, &DPROV_CTX_DUAL_MAC(ctx),
5620 		    NULL)) != CRYPTO_SUCCESS)
5621 			break;
5622 
5623 		/* release references to providers */
5624 		KCF_PROV_REFRELE(cipher_pd);
5625 		KCF_PROV_REFRELE(mac_pd);
5626 
5627 		break;
5628 
5629 	case DPROV_REQ_ENCRYPT_MAC: {
5630 		size_t encrypted;
5631 		boolean_t inplace;
5632 
5633 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5634 
5635 		cipher_data = *((crypto_data_t *)dual_data);
5636 
5637 		/* do an encrypt update */
5638 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5639 		if (inplace) {
5640 			plaintext_tmp = &cipher_data;
5641 			ciphertext_tmp = NULL;
5642 		} else {
5643 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5644 			ciphertext_tmp = &cipher_data;
5645 		}
5646 		if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5647 		    plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
5648 			break;
5649 
5650 		/* do an encrypt final */
5651 		encrypted = cipher_data.cd_length;
5652 
5653 		cipher_data.cd_offset += encrypted;
5654 		cipher_data.cd_length = dual_data->dd_len1 - encrypted;
5655 
5656 		if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5657 		    &cipher_data, NULL)) != CRYPTO_SUCCESS)
5658 			break;
5659 
5660 		/*
5661 		 * Do a mac update on the resulting ciphertext, but with no
5662 		 * more bytes than specified by dual_data, and starting at
5663 		 * offset specified by dual_data. For in-place operations,
5664 		 * we use the length specified by the dual_data.
5665 		 */
5666 		mac_data = cipher_data;
5667 		mac_data.cd_offset = dual_data->dd_offset2;
5668 		mac_data.cd_length = dual_data->dd_len2;
5669 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5670 		    &mac_data, NULL)) != CRYPTO_SUCCESS)
5671 			break;
5672 
5673 		/* do a mac final */
5674 		error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5675 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5676 
5677 		/* Set the total size of the ciphertext, when successful */
5678 		if (error == CRYPTO_SUCCESS)
5679 			dual_data->dd_len1 = encrypted + cipher_data.cd_length;
5680 
5681 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5682 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5683 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5684 			(void) dprov_free_context(ctx);
5685 		}
5686 		break;
5687 	}
5688 
5689 	case DPROV_REQ_ENCRYPT_MAC_UPDATE: {
5690 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5691 		size_t encrypted;
5692 		ssize_t maclen;
5693 		boolean_t inplace;
5694 
5695 		cipher_data = *((crypto_data_t *)dual_data);
5696 
5697 		/* do an encrypt update */
5698 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5699 		if (inplace) {
5700 			plaintext_tmp = &cipher_data;
5701 			ciphertext_tmp = NULL;
5702 		} else {
5703 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5704 			ciphertext_tmp = &cipher_data;
5705 		}
5706 		if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5707 		    plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
5708 			break;
5709 
5710 		encrypted = cipher_data.cd_length;
5711 
5712 		/*
5713 		 * Do a mac update on the resulting ciphertext, but with no
5714 		 * more bytes than specified by dual_data, and starting at
5715 		 * offset specified by dual_data. For in-place operations,
5716 		 * we use the length specified by the dual_data.
5717 		 * There is an edge case, when the encryption step produced
5718 		 * zero bytes in the ciphertext. Only the portion between
5719 		 * offset2 and offset1 is then thrown in the MAC mix.
5720 		 */
5721 		maclen = dual_data->dd_offset1 - dual_data->dd_offset2 +
5722 		    encrypted;
5723 		if (maclen > 0) {
5724 			mac_data = cipher_data;
5725 			mac_data.cd_offset = dual_data->dd_offset2;
5726 			mac_data.cd_length = min(dual_data->dd_len2, maclen);
5727 			if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5728 			    &mac_data, NULL)) != CRYPTO_SUCCESS)
5729 				break;
5730 		}
5731 		/* Set the total size of the ciphertext, when successful */
5732 		if (error == CRYPTO_SUCCESS)
5733 			dual_data->dd_len1 = encrypted;
5734 
5735 		break;
5736 	}
5737 
5738 	case DPROV_REQ_ENCRYPT_MAC_FINAL:
5739 		cipher_data = *((crypto_data_t *)dual_data);
5740 
5741 		/* do an encrypt final */
5742 		if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5743 		    taskq_req->dr_cipher_mac_req.mr_data == NULL ?
5744 		    &cipher_data : taskq_req->dr_cipher_mac_req.mr_data,
5745 		    NULL)) != CRYPTO_SUCCESS)
5746 			break;
5747 
5748 		/*
5749 		 * If ciphertext length is different from zero, do a mac
5750 		 * update on it. This does not apply to in-place since we
5751 		 * do not allow partial updates, hence no final residual.
5752 		 */
5753 		if (taskq_req->dr_cipher_mac_req.mr_data != NULL &&
5754 		    taskq_req->dr_cipher_mac_req.mr_data->cd_length > 0)
5755 			if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5756 			    taskq_req->dr_cipher_mac_req.mr_data, NULL)) !=
5757 			    CRYPTO_SUCCESS)
5758 				break;
5759 
5760 		/* do a mac final */
5761 		error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5762 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5763 
5764 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5765 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5766 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5767 			(void) dprov_free_context(ctx);
5768 		}
5769 		break;
5770 
5771 	case DPROV_REQ_ENCRYPT_MAC_ATOMIC: {
5772 		crypto_data_t *plaintext_tmp, *ciphertext_tmp;
5773 		boolean_t inplace;
5774 
5775 		cipher_data = *((crypto_data_t *)dual_data);
5776 
5777 		/* do an encrypt atomic */
5778 		inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
5779 		if (inplace) {
5780 			plaintext_tmp = &cipher_data;
5781 			ciphertext_tmp = NULL;
5782 		} else {
5783 			plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
5784 			ciphertext_tmp = &cipher_data;
5785 		}
5786 
5787 		/* structure assignment */
5788 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5789 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5790 		session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
5791 
5792 		/* get the keys values and providers to use for operations */
5793 		if ((error = dprov_cipher_mac_key_pd(softc, session_id,
5794 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5795 		    &cipher_mech.cm_type, &mac_mech.cm_type)) !=
5796 		    CRYPTO_SUCCESS)
5797 			break;
5798 
5799 		/* do the atomic encrypt */
5800 		if ((error = crypto_encrypt_prov(cipher_pd, 0,
5801 		    &cipher_mech, plaintext_tmp, &cipher_key, NULL,
5802 		    ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
5803 			break;
5804 
5805 		/* do the atomic mac */
5806 		mac_data = cipher_data;
5807 		mac_data.cd_length = dual_data->dd_len2;
5808 		mac_data.cd_offset = dual_data->dd_offset2;
5809 		error = crypto_mac_prov(mac_pd, 0, &mac_mech, &mac_data,
5810 		    &mac_key, NULL, taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5811 
5812 		dual_data->dd_len1 = cipher_data.cd_length;
5813 
5814 		break;
5815 	}
5816 
5817 	case DPROV_REQ_MAC_DECRYPT: {
5818 		uint_t decrypted;
5819 		crypto_data_t plaintext_tmp;
5820 
5821 		cipher_data = *((crypto_data_t *)dual_data);
5822 
5823 		/* do a mac update and final on the ciphertext */
5824 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5825 		    &mac_data, NULL)) != CRYPTO_SUCCESS)
5826 			break;
5827 
5828 		/* do a mac final */
5829 		if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5830 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
5831 		    CRYPTO_SUCCESS)
5832 			break;
5833 
5834 		/* do an decrypt update */
5835 		cipher_data = mac_data;
5836 		cipher_data.cd_length = dual_data->dd_len2;
5837 		cipher_data.cd_offset = dual_data->dd_offset2;
5838 		if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
5839 			/* in-place */
5840 			plaintext_tmp = cipher_data;
5841 		else
5842 			plaintext_tmp = *taskq_req->dr_cipher_mac_req.mr_data;
5843 
5844 		if ((error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5845 		    &cipher_data, taskq_req->dr_cipher_mac_req.mr_data,
5846 		    NULL)) != CRYPTO_SUCCESS)
5847 			break;
5848 
5849 		/* do an decrypt final */
5850 		if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
5851 			/* in-place, everything must have been decrypted */
5852 			decrypted = cipher_data.cd_length;
5853 		else
5854 			decrypted =
5855 			    taskq_req->dr_cipher_mac_req.mr_data->cd_length;
5856 		plaintext_tmp.cd_offset += decrypted;
5857 		plaintext_tmp.cd_length -= decrypted;
5858 
5859 		error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5860 		    &plaintext_tmp, NULL);
5861 		if (taskq_req->dr_cipher_mac_req.mr_data != NULL)
5862 			taskq_req->dr_cipher_mac_req.mr_data->cd_length +=
5863 			    plaintext_tmp.cd_length;
5864 
5865 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5866 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5867 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5868 			(void) dprov_free_context(ctx);
5869 		}
5870 		break;
5871 	}
5872 
5873 	case DPROV_REQ_MAC_DECRYPT_UPDATE:
5874 		cipher_data = *((crypto_data_t *)dual_data);
5875 
5876 		/* do mac update */
5877 		if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
5878 		    &cipher_data, NULL)) != CRYPTO_SUCCESS)
5879 			break;
5880 
5881 		/* do a decrypt update */
5882 		cipher_data.cd_length = dual_data->dd_len2;
5883 		cipher_data.cd_offset = dual_data->dd_offset2;
5884 		error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
5885 		    &cipher_data, taskq_req->dr_cipher_mac_req.mr_data, NULL);
5886 
5887 		break;
5888 
5889 	case DPROV_REQ_MAC_DECRYPT_FINAL:
5890 		/* do a mac final */
5891 		if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
5892 		    taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
5893 		    CRYPTO_SUCCESS)
5894 			break;
5895 
5896 		/* do a decrypt final */
5897 		error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
5898 		    taskq_req->dr_cipher_mac_req.mr_data, NULL);
5899 
5900 		if (error != CRYPTO_BUFFER_TOO_SMALL) {
5901 			DPROV_CTX_DUAL_MAC(ctx) = NULL;
5902 			DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
5903 			(void) dprov_free_context(ctx);
5904 		}
5905 		break;
5906 
5907 	case DPROV_REQ_MAC_DECRYPT_ATOMIC:
5908 	case DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC:
5909 		cipher_data = *((crypto_data_t *)dual_data);
5910 
5911 		/* structure assignment */
5912 		cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
5913 		mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
5914 		session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
5915 
5916 		/* get the keys values and providers to use for operations */
5917 		if ((error = dprov_cipher_mac_key_pd(softc, session_id,
5918 		    taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
5919 		    &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
5920 			break;
5921 
5922 		/* do the atomic mac */
5923 		if (taskq_req->dr_type == DPROV_REQ_MAC_DECRYPT_ATOMIC)
5924 			error = crypto_mac_prov(mac_pd, 0, &mac_mech,
5925 			    &cipher_data, &mac_key, NULL,
5926 			    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5927 		else
5928 			/* DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC */
5929 			error = crypto_mac_verify_prov(mac_pd, 0, &mac_mech,
5930 			    &cipher_data, &mac_key, NULL,
5931 			    taskq_req->dr_cipher_mac_req.mr_mac, NULL);
5932 
5933 		if (error != CRYPTO_SUCCESS)
5934 			break;
5935 
5936 		/* do the atomic decrypt */
5937 		cipher_data.cd_length = dual_data->dd_len2;
5938 		cipher_data.cd_offset = dual_data->dd_offset2;
5939 		error = crypto_decrypt_prov(cipher_pd, 0, &cipher_mech,
5940 		    &cipher_data, &cipher_key, NULL,
5941 		    taskq_req->dr_cipher_mac_req.mr_data, NULL);
5942 
5943 		break;
5944 	}
5945 
5946 	dprov_op_done(taskq_req, error);
5947 	DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: end\n",
5948 	    instance));
5949 }
5950 
5951 /*
5952  * taskq dispatcher function for random number generation.
5953  */
5954 static void
5955 dprov_random_task(dprov_req_t *taskq_req)
5956 {
5957 	dprov_state_t *softc;
5958 	/* LINTED E_FUNC_SET_NOT_USED */
5959 	int instance;
5960 	int error = CRYPTO_SUCCESS;
5961 
5962 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5963 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: started\n", instance));
5964 
5965 	mutex_enter(&softc->ds_lock);
5966 
5967 	switch (taskq_req->dr_type) {
5968 
5969 	DPROV_REQ_RANDOM_SEED:
5970 		/*
5971 		 * Since we don't really generate random numbers
5972 		 * nothing to do.
5973 		 */
5974 		break;
5975 
5976 	case DPROV_REQ_RANDOM_GENERATE: {
5977 		uint_t i;
5978 		uchar_t c = 0;
5979 
5980 		/*
5981 		 * We don't generate random numbers so that the result
5982 		 * of the operation can be checked during testing.
5983 		 */
5984 
5985 		for (i = 0; i < taskq_req->dr_random_req.rr_len; i++)
5986 			taskq_req->dr_random_req.rr_buf[i] = c++;
5987 
5988 		break;
5989 	}
5990 	}
5991 
5992 	mutex_exit(&softc->ds_lock);
5993 	dprov_op_done(taskq_req, error);
5994 	DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: end\n", instance));
5995 }
5996 
5997 
5998 /*
5999  * taskq dispatcher function for session management operations.
6000  */
6001 static void
6002 dprov_session_task(dprov_req_t *taskq_req)
6003 {
6004 	dprov_state_t *softc;
6005 	/* LINTED E_FUNC_SET_NOT_USED */
6006 	int instance;
6007 	int error = CRYPTO_NOT_SUPPORTED;
6008 	crypto_session_id_t session_id =
6009 	    taskq_req->dr_session_req.sr_session_id;
6010 	dprov_session_t *session;
6011 	dprov_object_t *object;
6012 	int i;
6013 
6014 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6015 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: started\n",
6016 	    instance));
6017 
6018 	mutex_enter(&softc->ds_lock);
6019 
6020 	if (taskq_req->dr_type != DPROV_REQ_SESSION_OPEN)
6021 		/* validate session id and get ptr to session */
6022 		if ((session = softc->ds_sessions[session_id]) == NULL) {
6023 			mutex_exit(&softc->ds_lock);
6024 			dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6025 			return;
6026 		}
6027 
6028 	switch (taskq_req->dr_type) {
6029 
6030 	case DPROV_REQ_SESSION_OPEN: {
6031 		dprov_session_t **new_sessions;
6032 
6033 		if (softc->ds_token_initialized == B_FALSE) {
6034 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
6035 			break;
6036 		}
6037 
6038 		/* search for available session slot */
6039 		for (i = 0; i < softc->ds_sessions_slots; i++)
6040 			if (softc->ds_sessions[i] == NULL)
6041 				break;
6042 
6043 		if (i == softc->ds_sessions_slots) {
6044 			/* ran out of slots, grow sessions array */
6045 			new_sessions = kmem_zalloc(2 * softc->ds_sessions_slots,
6046 			    KM_NOSLEEP);
6047 			if (new_sessions == NULL) {
6048 				error = CRYPTO_SESSION_COUNT;
6049 				break;
6050 			}
6051 			bcopy(softc->ds_sessions, new_sessions,
6052 			    softc->ds_sessions_slots);
6053 			kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
6054 			    sizeof (dprov_session_t *));
6055 			softc->ds_sessions = new_sessions;
6056 			softc->ds_sessions_slots *= 2;
6057 		}
6058 
6059 		/* allocate and initialize new session */
6060 		softc->ds_sessions[i] = kmem_zalloc(
6061 		    sizeof (dprov_session_t), KM_NOSLEEP);
6062 		if (softc->ds_sessions[i] == NULL) {
6063 			error = CRYPTO_HOST_MEMORY;
6064 			break;
6065 		}
6066 		softc->ds_sessions_count++;
6067 
6068 		/* initialize session state */
6069 		softc->ds_sessions[i]->ds_state = DPROV_SESSION_STATE_PUBLIC;
6070 
6071 		/* return new session id to caller */
6072 		*(taskq_req->dr_session_req.sr_session_id_ptr) = i;
6073 
6074 		error = CRYPTO_SUCCESS;
6075 		break;
6076 	}
6077 
6078 	case DPROV_REQ_SESSION_CLOSE:
6079 		softc->ds_sessions[session_id] = NULL;
6080 
6081 		if (softc->ds_token_initialized == B_FALSE) {
6082 			error = CRYPTO_OPERATION_NOT_INITIALIZED;
6083 			break;
6084 		}
6085 
6086 		dprov_release_session_objects(session);
6087 
6088 		/* free session state and corresponding slot */
6089 		kmem_free(session, sizeof (dprov_session_t));
6090 		softc->ds_sessions_count--;
6091 
6092 		error = CRYPTO_SUCCESS;
6093 		break;
6094 
6095 	case DPROV_REQ_SESSION_LOGIN: {
6096 		char *pin = taskq_req->dr_session_req.sr_pin;
6097 		size_t pin_len = taskq_req->dr_session_req.sr_pin_len;
6098 		crypto_user_type_t user_type =
6099 		    taskq_req->dr_session_req.sr_user_type;
6100 
6101 		/* check user type */
6102 		if (user_type != CRYPTO_SO && user_type != CRYPTO_USER) {
6103 			error = CRYPTO_USER_TYPE_INVALID;
6104 			break;
6105 		}
6106 
6107 		/* check pin length */
6108 		if (pin_len > DPROV_MAX_PIN_LEN) {
6109 			error = CRYPTO_PIN_LEN_RANGE;
6110 			break;
6111 		}
6112 
6113 		/* check pin */
6114 		if (pin == NULL) {
6115 			error = CRYPTO_PIN_INVALID;
6116 			break;
6117 		}
6118 
6119 		/* validate PIN state */
6120 		if ((user_type == CRYPTO_SO) && !softc->ds_token_initialized ||
6121 		    (user_type == CRYPTO_USER) && !softc->ds_user_pin_set) {
6122 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
6123 			break;
6124 		}
6125 
6126 		if ((user_type == CRYPTO_SO &&
6127 		    softc->ds_sessions[session_id]->ds_state ==
6128 		    DPROV_SESSION_STATE_SO) ||
6129 		    (user_type == CRYPTO_USER &&
6130 		    softc->ds_sessions[session_id]->ds_state ==
6131 		    DPROV_SESSION_STATE_USER)) {
6132 			/* SO or user already logged in */
6133 			error = CRYPTO_USER_ALREADY_LOGGED_IN;
6134 			break;
6135 		}
6136 
6137 		if (softc->ds_sessions[session_id]->ds_state !=
6138 		    DPROV_SESSION_STATE_PUBLIC) {
6139 			/* another user already logged in */
6140 			error = CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN;
6141 			break;
6142 		}
6143 
6144 		/* everything's fine, update session */
6145 		softc->ds_sessions[session_id]->ds_state =
6146 		    user_type == CRYPTO_SO ?
6147 		    DPROV_SESSION_STATE_SO : DPROV_SESSION_STATE_USER;
6148 
6149 		error = CRYPTO_SUCCESS;
6150 		break;
6151 	}
6152 
6153 	case DPROV_REQ_SESSION_LOGOUT:
6154 		/* fail if not logged in */
6155 		if (softc->ds_sessions[session_id]->ds_state ==
6156 		    DPROV_SESSION_STATE_PUBLIC) {
6157 			error = CRYPTO_USER_NOT_LOGGED_IN;
6158 			break;
6159 		}
6160 
6161 		/*
6162 		 * Destroy all private session objects.
6163 		 * Invalidate handles to all private objects.
6164 		 */
6165 		for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
6166 			object = softc->ds_sessions[session_id]->ds_objects[i];
6167 			if (object != NULL && dprov_object_is_private(object)) {
6168 				if (!dprov_object_is_token(object))
6169 					/* It's a session object, free it */
6170 					DPROV_OBJECT_REFRELE(object);
6171 				softc->ds_sessions[session_id]->ds_objects[i] =
6172 				    NULL;
6173 			}
6174 		}
6175 
6176 		/* update session state */
6177 		softc->ds_sessions[session_id]->ds_state =
6178 		    DPROV_SESSION_STATE_PUBLIC;
6179 
6180 		error = CRYPTO_SUCCESS;
6181 		break;
6182 	}
6183 
6184 	mutex_exit(&softc->ds_lock);
6185 	dprov_op_done(taskq_req, error);
6186 	DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: end\n", instance));
6187 }
6188 
6189 /* return true if attribute is defined to be a PKCS#11 long */
6190 static boolean_t
6191 fixed_size_attribute(crypto_attr_type_t type)
6192 {
6193 	return (type == DPROV_CKA_CLASS ||
6194 	    type == DPROV_CKA_CERTIFICATE_TYPE ||
6195 	    type == DPROV_CKA_KEY_TYPE ||
6196 	    type == DPROV_HW_FEATURE_TYPE);
6197 }
6198 
6199 /*
6200  * Attributes defined to be a PKCS#11 long causes problems for dprov
6201  * because 32-bit applications set the size to 4 and 64-bit applications
6202  * set the size to 8. dprov always stores these fixed-size attributes
6203  * as uint32_t.
6204  */
6205 static ssize_t
6206 attribute_size(crypto_attr_type_t type, ssize_t len)
6207 {
6208 	if (fixed_size_attribute(type))
6209 		return (sizeof (uint32_t));
6210 
6211 	return (len);
6212 }
6213 
6214 /*
6215  * taskq dispatcher function for object management operations.
6216  */
6217 static void
6218 dprov_object_task(dprov_req_t *taskq_req)
6219 {
6220 	dprov_state_t *softc;
6221 	/* LINTED E_FUNC_SET_NOT_USED */
6222 	int instance;
6223 	int error = CRYPTO_NOT_SUPPORTED;
6224 	crypto_object_id_t object_id = taskq_req->dr_object_req.or_object_id;
6225 	crypto_session_id_t session_id = taskq_req->dr_object_req.or_session_id;
6226 	crypto_object_attribute_t *template =
6227 	    taskq_req->dr_object_req.or_template;
6228 	uint_t attr_count = taskq_req->dr_object_req.or_attribute_count;
6229 	dprov_object_t *object;
6230 	dprov_session_t *session;
6231 
6232 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6233 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: started\n", instance));
6234 
6235 	mutex_enter(&softc->ds_lock);
6236 
6237 	/* validate session id and get ptr to session */
6238 	if ((session = softc->ds_sessions[session_id]) == NULL) {
6239 		mutex_exit(&softc->ds_lock);
6240 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6241 		return;
6242 	}
6243 
6244 	switch (taskq_req->dr_type) {
6245 
6246 	case DPROV_REQ_OBJECT_CREATE:
6247 		/* create the object from the specified template */
6248 		if ((error = dprov_create_object_from_template(softc, session,
6249 		    template, attr_count,
6250 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
6251 		    B_FALSE)) != CRYPTO_SUCCESS)
6252 			break;
6253 
6254 		break;
6255 
6256 	case DPROV_REQ_OBJECT_COPY:
6257 		/* check object id */
6258 		if (object_id >= DPROV_MAX_OBJECTS ||
6259 		    (object = session->ds_objects[object_id]) == NULL) {
6260 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6261 			break;
6262 		}
6263 
6264 		/*
6265 		 * Create a new object from the object passed as
6266 		 * argument.
6267 		 */
6268 		if ((error = dprov_create_object_from_template(softc, session,
6269 		    object->do_attr, DPROV_MAX_ATTR,
6270 		    taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
6271 		    B_FALSE)) != CRYPTO_SUCCESS)
6272 			break;
6273 
6274 		/*
6275 		 * Add the attributes specified by the template to the
6276 		 * newly created object, replacing existing ones if needed.
6277 		 */
6278 		error = dprov_object_set_attr(session,
6279 		    *taskq_req->dr_object_req.or_object_id_ptr,
6280 		    taskq_req->dr_object_req.or_template,
6281 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6282 
6283 		break;
6284 
6285 	case DPROV_REQ_OBJECT_DESTROY:
6286 		/* destroy the object */
6287 		error = dprov_destroy_object(softc, session,
6288 		    taskq_req->dr_object_req.or_object_id);
6289 
6290 		break;
6291 
6292 	case DPROV_REQ_OBJECT_GET_SIZE:
6293 		/* get ptr to object */
6294 		if (object_id >= DPROV_MAX_OBJECTS ||
6295 		    session->ds_objects[object_id] == NULL) {
6296 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6297 			break;
6298 		}
6299 
6300 		/*
6301 		 * The PKCS11 specification does not specifies what
6302 		 * the object size really is, here we just return
6303 		 * the number of possible attributes of the object.
6304 		 */
6305 		*taskq_req->dr_object_req.or_object_size = DPROV_MAX_ATTR;
6306 
6307 		error = CRYPTO_SUCCESS;
6308 		break;
6309 
6310 	case DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE: {
6311 		crypto_attr_type_t type;
6312 		size_t olen, tlen;
6313 		offset_t offset;
6314 		int tmpl_idx;
6315 		int object_idx;
6316 		ulong_t class = DPROV_CKO_DATA;
6317 		boolean_t extractable = B_TRUE;
6318 
6319 		error = CRYPTO_SUCCESS;
6320 
6321 		/* get ptr to object */
6322 		if (object_id >= DPROV_MAX_OBJECTS ||
6323 		    (object = session->ds_objects[object_id]) == NULL) {
6324 			error = CRYPTO_OBJECT_HANDLE_INVALID;
6325 			break;
6326 		}
6327 
6328 		(void) dprov_get_object_attr_boolean(object,
6329 		    DPROV_CKA_EXTRACTABLE, &extractable);
6330 
6331 		(void) dprov_get_object_attr_ulong(object,
6332 		    DPROV_CKA_CLASS, &class);
6333 
6334 		/* return the specified attributes, when possible */
6335 		for (tmpl_idx = 0; tmpl_idx < attr_count; tmpl_idx++) {
6336 			/*
6337 			 * Attribute can't be revealed if the CKA_EXTRACTABLE
6338 			 * attribute is set to false.
6339 			 */
6340 			type = template[tmpl_idx].oa_type;
6341 			if (!extractable && class == DPROV_CKO_SECRET_KEY) {
6342 				if (type == DPROV_CKA_VALUE) {
6343 					template[tmpl_idx].oa_value_len = -1;
6344 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6345 					continue;
6346 				}
6347 			}
6348 			if (!extractable && class == DPROV_CKO_PRIVATE_KEY) {
6349 				if (type == DPROV_CKA_PRIVATE_EXPONENT) {
6350 					template[tmpl_idx].oa_value_len = -1;
6351 					error = CRYPTO_ATTRIBUTE_SENSITIVE;
6352 					continue;
6353 				}
6354 			}
6355 
6356 			object_idx = dprov_find_attr(object->do_attr,
6357 			    DPROV_MAX_ATTR, type);
6358 			if (object_idx == -1) {
6359 				/* attribute not found in object */
6360 				template[tmpl_idx].oa_value_len = -1;
6361 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
6362 				continue;
6363 			}
6364 
6365 			tlen = template[tmpl_idx].oa_value_len;
6366 			olen = object->do_attr[object_idx].oa_value_len;
6367 			/* return attribute length */
6368 			if (template[tmpl_idx].oa_value == NULL) {
6369 				/*
6370 				 * The size of the attribute is set by the
6371 				 * library according to the data model of the
6372 				 * application, so don't overwrite it with
6373 				 * dprov's size.
6374 				 */
6375 				if (!fixed_size_attribute(type))
6376 					template[tmpl_idx].oa_value_len = olen;
6377 				continue;
6378 			}
6379 
6380 			if (tlen < olen) {
6381 				template[tmpl_idx].oa_value_len = -1;
6382 				error = CRYPTO_BUFFER_TOO_SMALL;
6383 				continue;
6384 			}
6385 
6386 			/* copy attribute value */
6387 			bzero(template[tmpl_idx].oa_value, tlen);
6388 
6389 			offset = 0;
6390 #ifdef _BIG_ENDIAN
6391 			if (fixed_size_attribute(type)) {
6392 				offset = tlen - olen;
6393 			}
6394 #endif
6395 			bcopy(object->do_attr[object_idx].oa_value,
6396 			    &template[tmpl_idx].oa_value[offset], olen);
6397 
6398 			/* don't update length for fixed-size attributes */
6399 			if (!fixed_size_attribute(type))
6400 				template[tmpl_idx].oa_value_len = olen;
6401 		}
6402 
6403 		break;
6404 	}
6405 
6406 	case DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE:
6407 		/*
6408 		 * Add the attributes specified by the template to the
6409 		 * newly created object, replacing existing ones if needed.
6410 		 */
6411 		error = dprov_object_set_attr(session,
6412 		    taskq_req->dr_object_req.or_object_id,
6413 		    taskq_req->dr_object_req.or_template,
6414 		    taskq_req->dr_object_req.or_attribute_count, B_TRUE);
6415 
6416 		break;
6417 
6418 	case DPROV_REQ_OBJECT_FIND_INIT: {
6419 		dprov_find_ctx_t *find_ctx;
6420 		int so_idx;		/* session object index */
6421 		int to_idx;		/* token object index */
6422 
6423 		error = CRYPTO_SUCCESS;
6424 		/* allocate find context */
6425 		find_ctx = kmem_zalloc(sizeof (dprov_find_ctx_t), KM_SLEEP);
6426 		*taskq_req->dr_object_req.or_find_pp = find_ctx;
6427 
6428 		/* first go through the existing session objects */
6429 		for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++) {
6430 			if ((object = session->ds_objects[so_idx]) == NULL)
6431 				continue;
6432 
6433 			/* setting count to zero means find all objects */
6434 			if (attr_count > 0) {
6435 				if (!dprov_attributes_match(object, template,
6436 				    attr_count))
6437 					continue;
6438 			}
6439 
6440 			/* session object attributes matches template */
6441 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
6442 			find_ctx->fc_nids++;
6443 		}
6444 
6445 		/*
6446 		 * Go through the token object. For each token object
6447 		 * that can be accessed:
6448 		 * If there was already an session object id assigned
6449 		 * to that token object, skip it, since it was returned
6450 		 * during the check of session objects, else,
6451 		 * assign a new object id for that token object and
6452 		 * add it to the array of matching objects.
6453 		 */
6454 		for (to_idx = 0; to_idx < DPROV_MAX_OBJECTS &&
6455 		    error == CRYPTO_SUCCESS; to_idx++) {
6456 			if ((object = softc->ds_objects[to_idx]) == NULL)
6457 				continue;
6458 
6459 			/* setting count to zero means find all objects */
6460 			if (attr_count > 0) {
6461 				if (!dprov_attributes_match(object, template,
6462 				    attr_count))
6463 					continue;
6464 			}
6465 
6466 			/* if the the object has been destroyed, skip it */
6467 			if (object->do_destroyed)
6468 				continue;
6469 
6470 			/* skip object if it cannot be accessed from session */
6471 			if (dprov_object_is_private(object) &&
6472 			    session->ds_state != DPROV_SESSION_STATE_USER)
6473 				continue;
6474 
6475 			/*
6476 			 * Is there already a session object id for this
6477 			 * token object?
6478 			 */
6479 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
6480 				if (session->ds_objects[so_idx] != NULL &&
6481 				    session->ds_objects[so_idx]->do_token_idx ==
6482 				    to_idx)
6483 					break;
6484 			if (so_idx < DPROV_MAX_OBJECTS)
6485 				/* object found in session table, skip it */
6486 				continue;
6487 
6488 			/* find free session slot for this object */
6489 			for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
6490 				if (session->ds_objects[so_idx] == NULL)
6491 					break;
6492 			if (so_idx == DPROV_MAX_OBJECTS) {
6493 				/* ran out of session objects slots */
6494 				kmem_free(find_ctx, sizeof (dprov_find_ctx_t));
6495 				error = CRYPTO_HOST_MEMORY;
6496 				break;
6497 			}
6498 
6499 			/* add object to session objects table */
6500 			session->ds_objects[so_idx] = object;
6501 			DPROV_OBJECT_REFHOLD(object);
6502 
6503 			/* add object to list of objects to return */
6504 			find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
6505 			find_ctx->fc_nids++;
6506 		}
6507 
6508 		break;
6509 	}
6510 
6511 	case DPROV_REQ_OBJECT_FIND: {
6512 		crypto_object_id_t *object_ids =
6513 			taskq_req->dr_object_req.or_object_id_ptr;
6514 		uint_t max_object_count =
6515 			taskq_req->dr_object_req.or_max_object_count;
6516 		dprov_find_ctx_t *find_ctx =
6517 			taskq_req->dr_object_req.or_find_p;
6518 		uint_t ret_oid_idx;
6519 
6520 		/* return the desired number of object ids */
6521 		for (ret_oid_idx = 0; ret_oid_idx < max_object_count &&
6522 		    find_ctx->fc_next < find_ctx->fc_nids; ret_oid_idx++)
6523 			object_ids[ret_oid_idx] =
6524 			    find_ctx->fc_ids[find_ctx->fc_next++];
6525 
6526 		*taskq_req->dr_object_req.or_object_count_ptr = ret_oid_idx;
6527 
6528 		error = CRYPTO_SUCCESS;
6529 		break;
6530 	}
6531 
6532 	case DPROV_REQ_OBJECT_FIND_FINAL:
6533 		kmem_free(taskq_req->dr_object_req.or_find_p,
6534 		    sizeof (dprov_find_ctx_t));
6535 
6536 		error = CRYPTO_SUCCESS;
6537 		break;
6538 	}
6539 
6540 	mutex_exit(&softc->ds_lock);
6541 	dprov_op_done(taskq_req, error);
6542 	DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: end\n", instance));
6543 }
6544 
6545 /*
6546  * taskq dispatcher function for key management operations.
6547  */
6548 static void
6549 dprov_key_task(dprov_req_t *taskq_req)
6550 {
6551 	dprov_state_t *softc;
6552 	/* LINTED E_FUNC_SET_NOT_USED */
6553 	int instance;
6554 	int error = CRYPTO_NOT_SUPPORTED;
6555 	kcf_provider_desc_t *pd;
6556 	crypto_session_id_t session_id = taskq_req->dr_key_req.kr_session_id;
6557 	dprov_session_t *session;
6558 
6559 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6560 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: started\n", instance));
6561 
6562 	mutex_enter(&softc->ds_lock);
6563 
6564 	/* validate session id and get ptr to session */
6565 	if ((session = softc->ds_sessions[session_id]) == NULL) {
6566 		mutex_exit(&softc->ds_lock);
6567 		dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6568 		return;
6569 	}
6570 
6571 	switch (taskq_req->dr_type) {
6572 	case DPROV_REQ_KEY_GENERATE: {
6573 		crypto_mechanism_t *mechp;
6574 		crypto_object_id_t *object_id_ptr;
6575 		crypto_object_attribute_t *template;
6576 		crypto_object_attribute_t attribute;
6577 		uint_t attribute_count;
6578 		ulong_t key_type = ~0UL, class = ~0UL;
6579 		ulong_t value_len;
6580 		size_t key_len = 0;
6581 
6582 		error = CRYPTO_SUCCESS;
6583 
6584 		template = taskq_req->dr_key_req.kr_template;
6585 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
6586 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
6587 		mechp = taskq_req->dr_key_req.kr_mechanism;
6588 
6589 		/* optional */
6590 		(void) dprov_get_template_attr_ulong(template, attribute_count,
6591 		    DPROV_CKA_CLASS, &class);
6592 
6593 		/* optional */
6594 		(void) dprov_get_template_attr_ulong(template, attribute_count,
6595 		    DPROV_CKA_KEY_TYPE, &key_type);
6596 
6597 		if (class != ~0UL && class != DPROV_CKO_SECRET_KEY) {
6598 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6599 			break;
6600 		}
6601 
6602 		switch (mechp->cm_type) {
6603 		case DES_KEY_GEN_MECH_INFO_TYPE:
6604 			if (key_type != ~0UL && key_type != DPROV_CKK_DES) {
6605 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6606 				break;
6607 			}
6608 			key_len = DES_KEY_LEN;
6609 			key_type = DPROV_CKK_DES;
6610 			break;
6611 
6612 		case DES3_KEY_GEN_MECH_INFO_TYPE:
6613 			if (key_type != ~0UL && key_type != DPROV_CKK_DES3) {
6614 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6615 				break;
6616 			}
6617 			key_len = DES3_KEY_LEN;
6618 			key_type = DPROV_CKK_DES3;
6619 			break;
6620 
6621 		case AES_KEY_GEN_MECH_INFO_TYPE:
6622 			if (key_type != ~0UL && key_type != DPROV_CKK_AES) {
6623 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6624 				break;
6625 			}
6626 			if (dprov_get_template_attr_ulong(template,
6627 			    attribute_count, DPROV_CKA_VALUE_LEN,
6628 			    &value_len) != CRYPTO_SUCCESS) {
6629 				error = CRYPTO_TEMPLATE_INCOMPLETE;
6630 				break;
6631 			}
6632 			if (value_len >= AES_MAX_KEY_LEN) {
6633 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6634 				break;
6635 			}
6636 			key_len = value_len;
6637 			key_type = DPROV_CKK_AES;
6638 			break;
6639 
6640 		case BLOWFISH_KEY_GEN_MECH_INFO_TYPE:
6641 			if (key_type != ~0UL &&
6642 			    key_type != DPROV_CKK_BLOWFISH) {
6643 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6644 				break;
6645 			}
6646 			if (dprov_get_template_attr_ulong(template,
6647 			    attribute_count, DPROV_CKA_VALUE_LEN,
6648 			    &value_len) != CRYPTO_SUCCESS) {
6649 				error = CRYPTO_TEMPLATE_INCOMPLETE;
6650 				break;
6651 			}
6652 			if (value_len >= BLOWFISH_MAX_KEY_LEN) {
6653 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6654 				break;
6655 			}
6656 			key_len = value_len;
6657 			key_type = DPROV_CKK_BLOWFISH;
6658 			break;
6659 
6660 		case RC4_KEY_GEN_MECH_INFO_TYPE:
6661 			if (key_type != ~0UL && key_type != DPROV_CKK_RC4) {
6662 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6663 				break;
6664 			}
6665 			if (dprov_get_template_attr_ulong(template,
6666 			    attribute_count, DPROV_CKA_VALUE_LEN,
6667 			    &value_len) != CRYPTO_SUCCESS) {
6668 				error = CRYPTO_TEMPLATE_INCOMPLETE;
6669 				break;
6670 			}
6671 			if (value_len >=
6672 			    CRYPTO_BITS2BYTES(ARCFOUR_MAX_KEY_BITS)) {
6673 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
6674 				break;
6675 			}
6676 			key_len = value_len;
6677 			key_type = DPROV_CKK_RC4;
6678 			break;
6679 
6680 		default:
6681 			error = CRYPTO_MECHANISM_INVALID;
6682 		}
6683 
6684 		if (error != CRYPTO_SUCCESS)
6685 			break;
6686 
6687 		error = dprov_create_object_from_template(softc, session,
6688 		    template, attribute_count, object_id_ptr, B_FALSE, B_TRUE);
6689 
6690 		if (error != CRYPTO_SUCCESS)
6691 			break;
6692 
6693 		/* make sure class is set */
6694 		attribute.oa_type = DPROV_CKA_CLASS;
6695 		attribute.oa_value = (char *)&class;
6696 		attribute.oa_value_len = sizeof (ulong_t);
6697 		error = dprov_object_set_attr(session, *object_id_ptr,
6698 		    &attribute, 1, B_FALSE);
6699 
6700 		if (error != CRYPTO_SUCCESS) {
6701 			goto destroy_object;
6702 		}
6703 
6704 		/* make sure key_type is set */
6705 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
6706 		attribute.oa_value = (char *)&key_type;
6707 		attribute.oa_value_len = sizeof (ulong_t);
6708 		error = dprov_object_set_attr(session, *object_id_ptr,
6709 		    &attribute, 1, B_FALSE);
6710 
6711 		if (error != CRYPTO_SUCCESS) {
6712 			goto destroy_object;
6713 		}
6714 
6715 		attribute.oa_type = DPROV_CKA_VALUE;
6716 		attribute.oa_value = kmem_alloc(key_len, KM_SLEEP);
6717 		attribute.oa_value_len = key_len;
6718 
6719 		if (random_get_pseudo_bytes((uchar_t *)attribute.oa_value,
6720 		    key_len) != 0) {
6721 			bzero(attribute.oa_value, key_len);
6722 			kmem_free(attribute.oa_value, key_len);
6723 			goto destroy_object;
6724 		}
6725 		error = dprov_object_set_attr(session, *object_id_ptr,
6726 		    &attribute, 1, B_FALSE);
6727 
6728 		bzero(attribute.oa_value, key_len);
6729 		kmem_free(attribute.oa_value, key_len);
6730 
6731 		if (error != CRYPTO_SUCCESS) {
6732 			goto destroy_object;
6733 		}
6734 		break;
6735 
6736 destroy_object:
6737 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
6738 		break;
6739 	}
6740 
6741 	case DPROV_REQ_KEY_GENERATE_PAIR: {
6742 		crypto_mechanism_t *mechp;
6743 		crypto_object_id_t *pub_object_id_ptr;
6744 		crypto_object_id_t *pri_object_id_ptr;
6745 		crypto_object_attribute_t *pub_template;
6746 		crypto_object_attribute_t *pri_template;
6747 		crypto_object_attribute_t attribute;
6748 		uint_t pub_attribute_count;
6749 		uint_t pri_attribute_count;
6750 		ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
6751 		ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
6752 		char public_exponent[3] = {
6753 		    0x01, 0x00, 0x01
6754 		};
6755 		static uchar_t private_exponent[128] = {
6756 		    0x4a, 0xef, 0xb9, 0x30, 0xa1, 0x44, 0x0a, 0xe0,
6757 		    0x30, 0xdd, 0xd3, 0x57, 0xc2, 0xb6, 0x6a, 0xba,
6758 		    0x5f, 0x81, 0xb0, 0x72, 0x55, 0x5b, 0x5b, 0xf3,
6759 		    0x07, 0xd2, 0x5f, 0x15, 0x87, 0xc0, 0x78, 0x7d,
6760 		    0x4f, 0x95, 0x09, 0x59, 0xd2, 0x9a, 0x95, 0xc3,
6761 		    0xcc, 0xdc, 0xf1, 0xa4, 0x60, 0x76, 0xd7, 0xa7,
6762 		    0xf8, 0x01, 0x13, 0xf8, 0x54, 0xd4, 0xf8, 0x2f,
6763 		    0xcf, 0x0c, 0x8b, 0x6e, 0xee, 0x34, 0x53, 0x19,
6764 		    0x14, 0xa6, 0x15, 0x14, 0xaf, 0xb2, 0x28, 0xa1,
6765 		    0x78, 0x1b, 0x2d, 0x9b, 0x28, 0x52, 0x14, 0xfa,
6766 		    0x72, 0x2b, 0x81, 0x11, 0xd0, 0x59, 0xde, 0xc6,
6767 		    0x52, 0x90, 0xa4, 0xae, 0xc9, 0xf1, 0x97, 0xd4,
6768 		    0x57, 0xbc, 0xe3, 0x90, 0x30, 0xc7, 0xff, 0xe8,
6769 		    0xd7, 0x2d, 0xd8, 0xef, 0x14, 0x2d, 0x2d, 0x60,
6770 		    0x54, 0x22, 0x9d, 0x32, 0x36, 0xcf, 0x4f, 0xf7,
6771 		    0x37, 0xcc, 0x8e, 0x00, 0x85, 0xb1, 0x00, 0x01
6772 		};
6773 
6774 		static uchar_t modulus[128] = {
6775 		    0x87, 0xb2, 0x2a, 0x54, 0x63, 0x83, 0x5e, 0x30,
6776 		    0xdc, 0x73, 0x03, 0xc6, 0x35, 0xf8, 0xa0, 0x25,
6777 		    0xa5, 0x6e, 0xcc, 0x14, 0xdd, 0x77, 0x2e, 0x80,
6778 		    0xd1, 0xa3, 0x05, 0x09, 0x1a, 0x2f, 0x88, 0xec,
6779 		    0xd1, 0x46, 0x92, 0x19, 0x8c, 0x7a, 0xf7, 0x63,
6780 		    0x28, 0xbf, 0x7a, 0xea, 0x9f, 0xfe, 0x96, 0x0f,
6781 		    0x80, 0xa1, 0x3e, 0xa6, 0xe1, 0x89, 0x7c, 0x4c,
6782 		    0x8e, 0x92, 0xdc, 0x6e, 0x69, 0xba, 0x4b, 0x3f,
6783 		    0x93, 0xc0, 0xaf, 0xbd, 0xbc, 0x81, 0xf2, 0x1e,
6784 		    0xc0, 0x7d, 0xc3, 0x4c, 0x8f, 0x5f, 0xfe, 0xdc,
6785 		    0xdb, 0xdb, 0x52, 0x03, 0x94, 0x78, 0x04, 0xa6,
6786 		    0x78, 0x1f, 0xdd, 0x5e, 0xd8, 0x85, 0x3e, 0x19,
6787 		    0x54, 0x7c, 0xd5, 0x81, 0xfb, 0x70, 0x69, 0x5d,
6788 		    0xbf, 0x23, 0x7a, 0xb1, 0xf9, 0x85, 0x6e, 0xc2,
6789 		    0x0a, 0x4d, 0x81, 0x21, 0xf8, 0xad, 0x71, 0x65,
6790 		    0xaf, 0xb6, 0x8f, 0xa1, 0xac, 0x46, 0x8a, 0x4d
6791 		};
6792 
6793 		pub_template = taskq_req->dr_key_req.kr_template;
6794 		pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
6795 		pub_object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
6796 		pri_template = taskq_req->dr_key_req.kr_private_key_template;
6797 		pri_attribute_count =
6798 		    taskq_req->dr_key_req.kr_private_key_attribute_count;
6799 		pri_object_id_ptr =
6800 		    taskq_req->dr_key_req.kr_private_key_object_id_ptr;
6801 		mechp = taskq_req->dr_key_req.kr_mechanism;
6802 
6803 		error = CRYPTO_SUCCESS;
6804 
6805 		/* optional */
6806 		(void) dprov_get_template_attr_ulong(pub_template,
6807 		    pub_attribute_count, DPROV_CKA_CLASS, &pub_class);
6808 
6809 		/* optional */
6810 		(void) dprov_get_template_attr_ulong(pri_template,
6811 		    pri_attribute_count, DPROV_CKA_CLASS, &pri_class);
6812 
6813 		/* optional */
6814 		(void) dprov_get_template_attr_ulong(pub_template,
6815 		    pub_attribute_count, DPROV_CKA_KEY_TYPE, &pub_key_type);
6816 
6817 		/* optional */
6818 		(void) dprov_get_template_attr_ulong(pri_template,
6819 		    pri_attribute_count, DPROV_CKA_KEY_TYPE, &pri_key_type);
6820 
6821 		if (pub_class != ~0UL && pub_class != DPROV_CKO_PUBLIC_KEY) {
6822 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6823 			break;
6824 		}
6825 
6826 		if (pri_class != ~0UL && pri_class != DPROV_CKO_PRIVATE_KEY) {
6827 			error = CRYPTO_TEMPLATE_INCONSISTENT;
6828 			break;
6829 		}
6830 
6831 		switch (mechp->cm_type) {
6832 		case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
6833 			if (pub_key_type != ~0UL &&
6834 			    pub_key_type != DPROV_CKK_RSA) {
6835 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6836 				break;
6837 			}
6838 			pri_key_type = DPROV_CKK_RSA;
6839 
6840 			if (pri_key_type != ~0UL &&
6841 			    pri_key_type != DPROV_CKK_RSA) {
6842 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6843 				break;
6844 			}
6845 			pri_key_type = DPROV_CKK_RSA;
6846 
6847 			if (pub_class != ~0UL &&
6848 			    pub_class != DPROV_CKO_PUBLIC_KEY) {
6849 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6850 				break;
6851 			}
6852 			pub_class = DPROV_CKO_PUBLIC_KEY;
6853 
6854 			if (pri_class != ~0UL &&
6855 			    pri_class != DPROV_CKO_PRIVATE_KEY) {
6856 				error = CRYPTO_TEMPLATE_INCONSISTENT;
6857 				break;
6858 			}
6859 			pri_class = DPROV_CKO_PRIVATE_KEY;
6860 			break;
6861 
6862 		default:
6863 			error = CRYPTO_MECHANISM_INVALID;
6864 		}
6865 
6866 		if (error != CRYPTO_SUCCESS)
6867 			break;
6868 
6869 		error = dprov_create_object_from_template(softc, session,
6870 		    pub_template, pub_attribute_count, pub_object_id_ptr,
6871 		    B_FALSE, B_TRUE);
6872 
6873 		if (error != CRYPTO_SUCCESS)
6874 			break;
6875 
6876 		/* make sure class is set */
6877 		attribute.oa_type = DPROV_CKA_CLASS;
6878 		attribute.oa_value = (char *)&pub_class;
6879 		attribute.oa_value_len = sizeof (ulong_t);
6880 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6881 		    &attribute, 1, B_FALSE);
6882 
6883 		if (error != CRYPTO_SUCCESS) {
6884 			goto destroy_public_object;
6885 		}
6886 
6887 		/* make sure key_type is set */
6888 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
6889 		attribute.oa_value = (char *)&pub_key_type;
6890 		attribute.oa_value_len = sizeof (ulong_t);
6891 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6892 		    &attribute, 1, B_FALSE);
6893 
6894 		if (error != CRYPTO_SUCCESS) {
6895 			goto destroy_public_object;
6896 		}
6897 
6898 		attribute.oa_type = DPROV_CKA_MODULUS;
6899 		attribute.oa_value = (char *)modulus;
6900 		attribute.oa_value_len = sizeof (modulus);
6901 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6902 		    &attribute, 1, B_FALSE);
6903 
6904 		if (error != CRYPTO_SUCCESS) {
6905 			goto destroy_public_object;
6906 		}
6907 
6908 		attribute.oa_type = DPROV_CKA_PUBLIC_EXPONENT;
6909 		attribute.oa_value = public_exponent;
6910 		attribute.oa_value_len = sizeof (public_exponent);
6911 		error = dprov_object_set_attr(session, *pub_object_id_ptr,
6912 		    &attribute, 1, B_FALSE);
6913 
6914 		if (error != CRYPTO_SUCCESS) {
6915 			goto destroy_public_object;
6916 		}
6917 
6918 		error = dprov_create_object_from_template(softc, session,
6919 		    pri_template, pri_attribute_count, pri_object_id_ptr,
6920 		    B_FALSE, B_TRUE);
6921 
6922 		if (error != CRYPTO_SUCCESS)
6923 			break;
6924 
6925 		/* make sure class is set */
6926 		attribute.oa_type = DPROV_CKA_CLASS;
6927 		attribute.oa_value = (char *)&pri_class;
6928 		attribute.oa_value_len = sizeof (ulong_t);
6929 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6930 		    &attribute, 1, B_FALSE);
6931 
6932 		if (error != CRYPTO_SUCCESS) {
6933 			goto destroy_private_object;
6934 		}
6935 
6936 		/* make sure key_type is set */
6937 		attribute.oa_type = DPROV_CKA_KEY_TYPE;
6938 		attribute.oa_value = (char *)&pri_key_type;
6939 		attribute.oa_value_len = sizeof (ulong_t);
6940 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6941 		    &attribute, 1, B_FALSE);
6942 
6943 		if (error != CRYPTO_SUCCESS) {
6944 			goto destroy_private_object;
6945 		}
6946 
6947 		attribute.oa_type = DPROV_CKA_MODULUS;
6948 		attribute.oa_value = (char *)modulus;
6949 		attribute.oa_value_len = sizeof (modulus);
6950 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6951 		    &attribute, 1, B_FALSE);
6952 
6953 		if (error != CRYPTO_SUCCESS) {
6954 			goto destroy_private_object;
6955 		}
6956 
6957 		attribute.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
6958 		attribute.oa_value = (char *)private_exponent;
6959 		attribute.oa_value_len = sizeof (private_exponent);
6960 		error = dprov_object_set_attr(session, *pri_object_id_ptr,
6961 		    &attribute, 1, B_FALSE);
6962 
6963 		if (error != CRYPTO_SUCCESS) {
6964 			goto destroy_private_object;
6965 		}
6966 		break;
6967 
6968 destroy_private_object:
6969 		(void) dprov_destroy_object(softc, session,
6970 		    *pri_object_id_ptr);
6971 destroy_public_object:
6972 		(void) dprov_destroy_object(softc, session,
6973 		    *pub_object_id_ptr);
6974 
6975 		break;
6976 	}
6977 
6978 	case DPROV_REQ_KEY_WRAP: {
6979 		crypto_mechanism_t mech, *mechp;
6980 		crypto_key_t key, *keyp;
6981 		crypto_object_id_t object_id;
6982 		ulong_t class = DPROV_CKO_DATA;
6983 		boolean_t extractable = B_TRUE;
6984 		dprov_object_t *object;
6985 		int object_idx;
6986 		char *plaintext_key;
6987 		size_t plaintext_key_len;
6988 		crypto_data_t plaintext;
6989 		crypto_data_t ciphertext;
6990 		size_t *lenp;
6991 
6992 		mechp = taskq_req->dr_key_req.kr_mechanism;
6993 		/* structure assignment */
6994 		mech = *mechp;
6995 
6996 		/* get wrapping key value */
6997 		if (is_publickey_mech(mech.cm_type)) {
6998 			if ((error = dprov_key_attr_asymmetric(softc,
6999 			    session_id, taskq_req->dr_type,
7000 			    taskq_req->dr_key_req.kr_key,
7001 			    &key)) != CRYPTO_SUCCESS)
7002 				break;
7003 			keyp = &key;
7004 		} else {
7005 			if ((error = dprov_key_value_secret(softc,
7006 			    session_id, taskq_req->dr_type,
7007 			    taskq_req->dr_key_req.kr_key,
7008 			    &key)) != CRYPTO_SUCCESS)
7009 				break;
7010 			keyp = &key;
7011 		}
7012 
7013 		/* get the software provider for this mechanism */
7014 		if ((error = dprov_get_sw_prov(mechp, &pd,
7015 		    &mech.cm_type)) != CRYPTO_SUCCESS)
7016 			break;
7017 
7018 		object_id = *taskq_req->dr_key_req.kr_object_id_ptr;
7019 		if (object_id >= DPROV_MAX_OBJECTS) {
7020 			error = CRYPTO_KEY_HANDLE_INVALID;
7021 			break;
7022 		}
7023 
7024 		/* get ptr to object */
7025 		if ((object = session->ds_objects[object_id]) == NULL) {
7026 			error = CRYPTO_OBJECT_HANDLE_INVALID;
7027 			break;
7028 		}
7029 
7030 		(void) dprov_get_object_attr_boolean(object,
7031 		    DPROV_CKA_EXTRACTABLE, &extractable);
7032 
7033 		if (!extractable) {
7034 			error = CRYPTO_ATTRIBUTE_SENSITIVE;
7035 			break;
7036 		}
7037 
7038 		(void) dprov_get_object_attr_ulong(object,
7039 		    DPROV_CKA_CLASS, &class);
7040 
7041 		switch (class) {
7042 		case DPROV_CKO_SECRET_KEY:
7043 			object_idx = dprov_find_attr(object->do_attr,
7044 			    DPROV_MAX_ATTR, DPROV_CKA_VALUE);
7045 			if (object_idx == -1) {
7046 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7047 				break;
7048 			}
7049 			break;
7050 
7051 		case DPROV_CKO_PRIVATE_KEY:
7052 			/*
7053 			 * PKCS#11 says that ASN.1 should be used to encode
7054 			 * specific attributes before encrypting the blob.
7055 			 * We only encrypt the private exponent for the
7056 			 * purpose of testing.
7057 			 */
7058 			object_idx = dprov_find_attr(object->do_attr,
7059 			    DPROV_MAX_ATTR, DPROV_CKA_PRIVATE_EXPONENT);
7060 			if (object_idx == -1) {
7061 				error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7062 				break;
7063 			}
7064 			break;
7065 		default:
7066 			error = CRYPTO_KEY_NOT_WRAPPABLE;
7067 			break;
7068 		}
7069 		if (error != CRYPTO_SUCCESS)
7070 			break;
7071 
7072 		plaintext_key = object->do_attr[object_idx].oa_value;
7073 		plaintext_key_len = object->do_attr[object_idx].oa_value_len;
7074 		lenp = taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7075 
7076 		/* session id is 0 for software provider */
7077 		plaintext.cd_format = CRYPTO_DATA_RAW;
7078 		plaintext.cd_offset = 0;
7079 		plaintext.cd_length = plaintext_key_len;
7080 		plaintext.cd_raw.iov_base = plaintext_key;
7081 		plaintext.cd_raw.iov_len = plaintext_key_len;
7082 		plaintext.cd_miscdata = NULL;
7083 
7084 		ciphertext.cd_format = CRYPTO_DATA_RAW;
7085 		ciphertext.cd_offset = 0;
7086 		ciphertext.cd_length = *lenp;
7087 		ciphertext.cd_raw.iov_base =
7088 		    (char *)taskq_req->dr_key_req.kr_wrapped_key;
7089 		ciphertext.cd_raw.iov_len = ciphertext.cd_length;
7090 		ciphertext.cd_miscdata = NULL;
7091 
7092 		error = crypto_encrypt_prov(pd, 0, &mech, &plaintext, keyp,
7093 		    NULL, &ciphertext, NULL);
7094 
7095 		KCF_PROV_REFRELE(pd);
7096 		if (error == CRYPTO_SUCCESS ||
7097 		    error == CRYPTO_BUFFER_TOO_SMALL) {
7098 			*lenp = ciphertext.cd_length;
7099 		}
7100 		break;
7101 	}
7102 
7103 	case DPROV_REQ_KEY_UNWRAP: {
7104 		crypto_mechanism_t mech, *mechp;
7105 		crypto_key_t key, *keyp;
7106 		crypto_object_id_t *object_id_ptr;
7107 		ulong_t class = DPROV_CKO_DATA;
7108 		uchar_t *wrapped_key;
7109 		char *plaintext_buf;
7110 		size_t wrapped_key_len;
7111 		crypto_data_t plaintext;
7112 		crypto_data_t ciphertext;
7113 		crypto_object_attribute_t unwrapped_key;
7114 		crypto_object_attribute_t *template;
7115 		uint_t attribute_count;
7116 
7117 		template = taskq_req->dr_key_req.kr_template;
7118 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7119 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7120 
7121 		/* all objects must have an object class attribute */
7122 		if (dprov_get_template_attr_ulong(template, attribute_count,
7123 		    DPROV_CKA_CLASS, &class) != CRYPTO_SUCCESS) {
7124 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7125 			break;
7126 		}
7127 
7128 		mechp = taskq_req->dr_key_req.kr_mechanism;
7129 		/* structure assignment */
7130 		mech = *mechp;
7131 
7132 		/* get unwrapping key value */
7133 		if (is_publickey_mech(mech.cm_type)) {
7134 			if ((error = dprov_key_attr_asymmetric(softc,
7135 			    session_id, taskq_req->dr_type,
7136 			    taskq_req->dr_key_req.kr_key,
7137 			    &key)) != CRYPTO_SUCCESS)
7138 				break;
7139 			keyp = &key;
7140 		} else {
7141 			if ((error = dprov_key_value_secret(softc,
7142 			    session_id, taskq_req->dr_type,
7143 			    taskq_req->dr_key_req.kr_key,
7144 			    &key)) != CRYPTO_SUCCESS)
7145 				break;
7146 			keyp = &key;
7147 		}
7148 
7149 		/* get the software provider for this mechanism */
7150 		if ((error = dprov_get_sw_prov(mechp, &pd,
7151 		    &mech.cm_type)) != CRYPTO_SUCCESS)
7152 			break;
7153 
7154 		wrapped_key = taskq_req->dr_key_req.kr_wrapped_key;
7155 		wrapped_key_len = *taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7156 		ciphertext.cd_format = CRYPTO_DATA_RAW;
7157 		ciphertext.cd_offset = 0;
7158 		ciphertext.cd_length = wrapped_key_len;
7159 		ciphertext.cd_raw.iov_base = (char *)wrapped_key;
7160 		ciphertext.cd_raw.iov_len = wrapped_key_len;
7161 		ciphertext.cd_miscdata = NULL;
7162 
7163 		/*
7164 		 * Plaintext length is less than or equal to
7165 		 * the length of the ciphertext.
7166 		 */
7167 		plaintext_buf = kmem_alloc(wrapped_key_len, KM_SLEEP);
7168 		plaintext.cd_format = CRYPTO_DATA_RAW;
7169 		plaintext.cd_offset = 0;
7170 		plaintext.cd_length = wrapped_key_len;
7171 		plaintext.cd_raw.iov_base = plaintext_buf;
7172 		plaintext.cd_raw.iov_len = wrapped_key_len;
7173 		plaintext.cd_miscdata = NULL;
7174 
7175 		error = crypto_decrypt_prov(pd, 0, &mech, &ciphertext, keyp,
7176 		    NULL, &plaintext, NULL);
7177 
7178 		KCF_PROV_REFRELE(pd);
7179 
7180 		if (error != CRYPTO_SUCCESS)
7181 			goto free_unwrapped_key;
7182 
7183 		error = dprov_create_object_from_template(softc, session,
7184 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7185 
7186 		if (error != CRYPTO_SUCCESS)
7187 			goto free_unwrapped_key;
7188 
7189 		switch (class) {
7190 		case DPROV_CKO_SECRET_KEY:
7191 			unwrapped_key.oa_type = DPROV_CKA_VALUE;
7192 			unwrapped_key.oa_value_len = plaintext.cd_length;
7193 			unwrapped_key.oa_value = plaintext_buf;
7194 			break;
7195 		case DPROV_CKO_PRIVATE_KEY:
7196 			/*
7197 			 * PKCS#11 says that ASN.1 should be used to encode
7198 			 * specific attributes before encrypting the blob.
7199 			 * We only encrypt the private exponent for the
7200 			 * purpose of testing.
7201 			 */
7202 			unwrapped_key.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
7203 			unwrapped_key.oa_value_len = plaintext.cd_length;
7204 			unwrapped_key.oa_value = plaintext_buf;
7205 			break;
7206 		default:
7207 			error = CRYPTO_TEMPLATE_INCONSISTENT;
7208 			goto free_unwrapped_key;
7209 		}
7210 
7211 		if ((error = dprov_object_set_attr(session, *object_id_ptr,
7212 		    &unwrapped_key, 1, B_FALSE)) == CRYPTO_SUCCESS)
7213 			break;	/* don't free the unwrapped key */
7214 
7215 		/* failure */
7216 		(void) dprov_destroy_object(softc, session, *object_id_ptr);
7217 		break;
7218 
7219 free_unwrapped_key:
7220 		bzero(plaintext_buf, wrapped_key_len);
7221 		kmem_free(plaintext_buf, wrapped_key_len);
7222 		break;
7223 	}
7224 
7225 	case DPROV_REQ_KEY_DERIVE: {
7226 		crypto_mechanism_t digest_mech, *mechp;
7227 		crypto_key_t key, *base_keyp;
7228 		crypto_object_id_t *object_id_ptr;
7229 		crypto_data_t data;
7230 		crypto_data_t digest;
7231 		size_t hash_size;
7232 		char *digest_buf;
7233 		crypto_object_attribute_t derived_key;
7234 		crypto_object_attribute_t *template;
7235 		uint_t attribute_count;
7236 		ulong_t key_type;
7237 		void *value;
7238 		size_t value_len = 0;
7239 
7240 		error = CRYPTO_SUCCESS;
7241 
7242 		template = taskq_req->dr_key_req.kr_template;
7243 		attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7244 		object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7245 
7246 		/* required */
7247 		if (dprov_get_template_attr_ulong(template, attribute_count,
7248 		    DPROV_CKA_KEY_TYPE, &key_type) != CRYPTO_SUCCESS) {
7249 			error = CRYPTO_TEMPLATE_INCOMPLETE;
7250 			break;
7251 		}
7252 
7253 		mechp = taskq_req->dr_key_req.kr_mechanism;
7254 		/* structure assignment */
7255 		digest_mech = *mechp;
7256 
7257 		switch (digest_mech.cm_type) {
7258 		case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:
7259 			hash_size = SHA1_DIGEST_LEN;
7260 			digest_mech.cm_type = SHA1_MECH_INFO_TYPE;
7261 			break;
7262 
7263 		case SHA256_KEY_DERIVATION_MECH_INFO_TYPE:
7264 			hash_size = SHA256_DIGEST_LENGTH;
7265 			digest_mech.cm_type = SHA256_MECH_INFO_TYPE;
7266 			break;
7267 
7268 		case SHA384_KEY_DERIVATION_MECH_INFO_TYPE:
7269 			hash_size = SHA384_DIGEST_LENGTH;
7270 			digest_mech.cm_type = SHA384_MECH_INFO_TYPE;
7271 			break;
7272 
7273 		case SHA512_KEY_DERIVATION_MECH_INFO_TYPE:
7274 			hash_size = SHA512_DIGEST_LENGTH;
7275 			digest_mech.cm_type = SHA512_MECH_INFO_TYPE;
7276 			break;
7277 
7278 		case MD5_KEY_DERIVATION_MECH_INFO_TYPE:
7279 			hash_size = MD5_DIGEST_LEN;
7280 			digest_mech.cm_type = MD5_MECH_INFO_TYPE;
7281 			break;
7282 
7283 		default:
7284 			error = CRYPTO_MECHANISM_INVALID;
7285 		}
7286 
7287 		if (error != CRYPTO_SUCCESS)
7288 			break;
7289 
7290 		/* CKA_VALUE is optional */
7291 		(void) dprov_get_template_attr_array(template, attribute_count,
7292 		    DPROV_CKA_VALUE, &value, &value_len);
7293 
7294 		/* check for inconsistent value length */
7295 		switch (key_type) {
7296 		case DPROV_CKK_GENERIC_SECRET:
7297 			if (value_len > 0) {
7298 				if (value_len > hash_size)
7299 					error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7300 			} else {
7301 				value_len = hash_size;
7302 			}
7303 			break;
7304 
7305 		case DPROV_CKK_RC4:
7306 		case DPROV_CKK_AES:
7307 			if (value_len == 0 ||
7308 			    value_len > hash_size) {
7309 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7310 			}
7311 			break;
7312 
7313 		case DPROV_CKK_DES:
7314 			if (value_len > 0 &&
7315 			    value_len != DES_KEY_LEN) {
7316 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7317 			}
7318 			value_len = DES_KEY_LEN;
7319 			break;
7320 
7321 		case DPROV_CKK_DES3:
7322 			if (value_len > 0 &&
7323 			    value_len != DES3_KEY_LEN) {
7324 				error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7325 			}
7326 			value_len = DES3_KEY_LEN;
7327 			break;
7328 
7329 		default:
7330 			error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7331 			break;
7332 		}
7333 
7334 		if (error != CRYPTO_SUCCESS)
7335 			break;
7336 
7337 		/* get the software provider for this mechanism */
7338 		if ((error = dprov_get_sw_prov(&digest_mech, &pd,
7339 		    &digest_mech.cm_type)) != CRYPTO_SUCCESS)
7340 			break;
7341 
7342 		/* get the base key */
7343 		error = dprov_key_value_secret(softc, session_id,
7344 		    taskq_req->dr_type, taskq_req->dr_key_req.kr_key, &key);
7345 		if (error != CRYPTO_SUCCESS)
7346 			break;
7347 
7348 		base_keyp = &key;
7349 
7350 		data.cd_format = CRYPTO_DATA_RAW;
7351 		data.cd_offset = 0;
7352 		data.cd_length = CRYPTO_BITS2BYTES(base_keyp->ck_length);
7353 		data.cd_raw.iov_base = base_keyp->ck_data;
7354 		data.cd_raw.iov_len = data.cd_length;
7355 
7356 		digest_buf = kmem_alloc(hash_size, KM_SLEEP);
7357 		digest.cd_format = CRYPTO_DATA_RAW;
7358 		digest.cd_offset = 0;
7359 		digest.cd_length = hash_size;
7360 		digest.cd_raw.iov_base = digest_buf;
7361 		digest.cd_raw.iov_len = hash_size;
7362 
7363 		error = crypto_digest_prov(pd, 0, &digest_mech, &data,
7364 		    &digest, NULL);
7365 
7366 		KCF_PROV_REFRELE(pd);
7367 
7368 		if (error != CRYPTO_SUCCESS)
7369 			goto free_derived_key;
7370 
7371 		error = dprov_create_object_from_template(softc, session,
7372 		    template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7373 
7374 		if (error != CRYPTO_SUCCESS)
7375 			goto free_derived_key;
7376 
7377 		derived_key.oa_type = DPROV_CKA_VALUE;
7378 		derived_key.oa_value = digest_buf;
7379 		derived_key.oa_value_len = value_len;
7380 
7381 		error = dprov_object_set_attr(session, *object_id_ptr,
7382 		    &derived_key, 1, B_FALSE);
7383 
7384 		if (error != CRYPTO_SUCCESS) {
7385 			(void) dprov_destroy_object(softc, session,
7386 			    *object_id_ptr);
7387 		}
7388 
7389 free_derived_key:
7390 		bzero(digest_buf, hash_size);
7391 		kmem_free(digest_buf, hash_size);
7392 	}
7393 	}
7394 
7395 	mutex_exit(&softc->ds_lock);
7396 	dprov_op_done(taskq_req, error);
7397 	DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: end\n", instance));
7398 }
7399 
7400 
7401 /*
7402  * taskq dispatcher function for provider management operations.
7403  */
7404 static void
7405 dprov_mgmt_task(dprov_req_t *taskq_req)
7406 {
7407 	dprov_state_t *softc;
7408 	/* LINTED E_FUNC_SET_NOT_USED */
7409 	int instance;
7410 	int error = CRYPTO_NOT_SUPPORTED;
7411 
7412 	DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
7413 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: started\n", instance));
7414 
7415 	mutex_enter(&softc->ds_lock);
7416 
7417 	switch (taskq_req->dr_type) {
7418 	case DPROV_REQ_MGMT_EXTINFO: {
7419 		crypto_provider_ext_info_t *ext_info =
7420 		    taskq_req->dr_mgmt_req.mr_ext_info;
7421 
7422 		(void) memset(ext_info->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
7423 		if (!softc->ds_token_initialized) {
7424 			bcopy("(not initialized)", ext_info->ei_label,
7425 			    strlen("(not initialized)"));
7426 		} else {
7427 			bcopy(softc->ds_label, ext_info->ei_label,
7428 			    CRYPTO_EXT_SIZE_LABEL);
7429 		}
7430 
7431 		bcopy(DPROV_MANUFACTURER, ext_info->ei_manufacturerID,
7432 		    CRYPTO_EXT_SIZE_MANUF);
7433 		bcopy(DPROV_MODEL, ext_info->ei_model, CRYPTO_EXT_SIZE_MODEL);
7434 
7435 		(void) snprintf((char *)ext_info->ei_serial_number, 16, "%d%s",
7436 		    instance, DPROV_ALLSPACES);
7437 		/* PKCS#11 blank padding */
7438 		ext_info->ei_serial_number[15] = ' ';
7439 		ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
7440 		ext_info->ei_max_pin_len = (ulong_t)DPROV_MAX_PIN_LEN;
7441 		ext_info->ei_min_pin_len = 1;
7442 		ext_info->ei_total_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
7443 		ext_info->ei_free_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
7444 		ext_info->ei_total_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
7445 		ext_info->ei_free_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
7446 		ext_info->ei_hardware_version.cv_major = 1;
7447 		ext_info->ei_hardware_version.cv_minor = 0;
7448 		ext_info->ei_firmware_version.cv_major = 1;
7449 		ext_info->ei_firmware_version.cv_minor = 0;
7450 
7451 		ext_info->ei_flags = CRYPTO_EXTF_RNG |
7452 		    CRYPTO_EXTF_LOGIN_REQUIRED |
7453 		    CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
7454 		if (softc->ds_user_pin_set)
7455 			ext_info->ei_flags |= CRYPTO_EXTF_USER_PIN_INITIALIZED;
7456 		if (softc->ds_token_initialized)
7457 			ext_info->ei_flags |= CRYPTO_EXTF_TOKEN_INITIALIZED;
7458 
7459 		error = CRYPTO_SUCCESS;
7460 		break;
7461 	}
7462 	case DPROV_REQ_MGMT_INITTOKEN: {
7463 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
7464 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
7465 		char *label = taskq_req->dr_mgmt_req.mr_label;
7466 
7467 		/* cannot initialize token when a session is open */
7468 		if (softc->ds_sessions_count > 0) {
7469 			error = CRYPTO_SESSION_EXISTS;
7470 			break;
7471 		}
7472 
7473 		/* check PIN length */
7474 		if (pin_len > DPROV_MAX_PIN_LEN) {
7475 			error = CRYPTO_PIN_LEN_RANGE;
7476 			break;
7477 		}
7478 
7479 		/* check PIN */
7480 		if (pin == NULL) {
7481 			error = CRYPTO_PIN_INVALID;
7482 			break;
7483 		}
7484 
7485 		/*
7486 		 * If the token has already been initialized, need
7487 		 * to validate supplied PIN.
7488 		 */
7489 		if (softc->ds_token_initialized &&
7490 		    (softc->ds_so_pin_len != pin_len ||
7491 		    strncmp(softc->ds_so_pin, pin, pin_len) != 0)) {
7492 			/* invalid SO PIN */
7493 			error = CRYPTO_PIN_INCORRECT;
7494 			break;
7495 		}
7496 
7497 		/* set label */
7498 		bcopy(label, softc->ds_label, CRYPTO_EXT_SIZE_LABEL);
7499 
7500 		/* set new SO PIN, update state */
7501 		bcopy(pin, softc->ds_so_pin, pin_len);
7502 		softc->ds_so_pin_len = pin_len;
7503 		softc->ds_token_initialized = B_TRUE;
7504 		softc->ds_user_pin_set = B_FALSE;
7505 
7506 		error = CRYPTO_SUCCESS;
7507 		break;
7508 	}
7509 	case DPROV_REQ_MGMT_INITPIN: {
7510 		char *pin = taskq_req->dr_mgmt_req.mr_pin;
7511 		size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
7512 		crypto_session_id_t session_id =
7513 		    taskq_req->dr_mgmt_req.mr_session_id;
7514 
7515 		/* check session id */
7516 		if (softc->ds_sessions[session_id] == NULL) {
7517 			error = CRYPTO_SESSION_HANDLE_INVALID;
7518 			break;
7519 		}
7520 
7521 		/* fail if not logged in as SO */
7522 		if (softc->ds_sessions[session_id]->ds_state !=
7523 		    DPROV_SESSION_STATE_SO) {
7524 			error = CRYPTO_USER_NOT_LOGGED_IN;
7525 			break;
7526 		}
7527 
7528 		/* check PIN length */
7529 		if (pin_len > DPROV_MAX_PIN_LEN) {
7530 			error = CRYPTO_PIN_LEN_RANGE;
7531 			break;
7532 		}
7533 
7534 		/* check PIN */
7535 		if (pin == NULL) {
7536 			error = CRYPTO_PIN_INVALID;
7537 			break;
7538 		}
7539 
7540 		/* set new normal user PIN */
7541 		bcopy(pin, softc->ds_user_pin, pin_len);
7542 		softc->ds_user_pin_len = pin_len;
7543 		softc->ds_user_pin_set = B_TRUE;
7544 
7545 		error = CRYPTO_SUCCESS;
7546 		break;
7547 	}
7548 	case DPROV_REQ_MGMT_SETPIN: {
7549 		char *new_pin = taskq_req->dr_mgmt_req.mr_pin;
7550 		size_t new_pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
7551 		char *old_pin = taskq_req->dr_mgmt_req.mr_old_pin;
7552 		size_t old_pin_len = taskq_req->dr_mgmt_req.mr_old_pin_len;
7553 		crypto_session_id_t session_id =
7554 		    taskq_req->dr_mgmt_req.mr_session_id;
7555 
7556 		/* check session id */
7557 		if (softc->ds_sessions[session_id] == NULL) {
7558 			error = CRYPTO_SESSION_HANDLE_INVALID;
7559 			break;
7560 		}
7561 
7562 		/* check PIN length */
7563 		if (old_pin_len > DPROV_MAX_PIN_LEN ||
7564 		    new_pin_len > DPROV_MAX_PIN_LEN) {
7565 			error = CRYPTO_PIN_LEN_RANGE;
7566 			break;
7567 		}
7568 
7569 		/* check PIN */
7570 		if (old_pin == NULL || new_pin == NULL) {
7571 			error = CRYPTO_PIN_INVALID;
7572 			break;
7573 		}
7574 
7575 		/* check user PIN state */
7576 		if (!softc->ds_user_pin_set) {
7577 			error = CRYPTO_USER_PIN_NOT_INITIALIZED;
7578 			break;
7579 		}
7580 
7581 		/*
7582 		 * If the token has already been initialized, need
7583 		 * to validate supplied PIN.
7584 		 */
7585 		if (softc->ds_user_pin_len != old_pin_len ||
7586 		    strncmp(softc->ds_user_pin, old_pin, old_pin_len) != 0) {
7587 			/* invalid SO PIN */
7588 			error = CRYPTO_PIN_INCORRECT;
7589 			break;
7590 		}
7591 
7592 		/* set new PIN */
7593 		bcopy(new_pin, softc->ds_user_pin, new_pin_len);
7594 		softc->ds_user_pin_len = new_pin_len;
7595 
7596 		error = CRYPTO_SUCCESS;
7597 		break;
7598 	}
7599 	}
7600 
7601 	mutex_exit(&softc->ds_lock);
7602 	dprov_op_done(taskq_req, error);
7603 	DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: end\n", instance));
7604 }
7605 
7606 /*
7607  * Returns in the location pointed to by pd a pointer to the descriptor
7608  * for the software provider for the specified mechanism.
7609  * The provider descriptor is returned held. Returns one of the CRYPTO_
7610  * error codes on failure, CRYPTO_SUCCESS on success.
7611  */
7612 static int
7613 dprov_get_sw_prov(crypto_mechanism_t *mech, kcf_provider_desc_t **pd,
7614     crypto_mech_type_t *provider_mech_type)
7615 {
7616 	crypto_mech_type_t kcf_mech_type = CRYPTO_MECH_INVALID;
7617 	int i, rv;
7618 
7619 	/* lookup the KCF mech type associated with our mech type */
7620 	for (i = 0; i < sizeof (dprov_mech_info_tab)/
7621 	    sizeof (crypto_mech_info_t); i++) {
7622 		if (mech->cm_type == dprov_mech_info_tab[i].cm_mech_number) {
7623 			kcf_mech_type = crypto_mech2id_common(
7624 				dprov_mech_info_tab[i].cm_mech_name, B_TRUE);
7625 		}
7626 	}
7627 
7628 	rv = kcf_get_sw_prov(kcf_mech_type, pd, B_TRUE);
7629 	if (rv == CRYPTO_SUCCESS)
7630 		*provider_mech_type = kcf_mech_type;
7631 
7632 	return (rv);
7633 }
7634 
7635 /*
7636  * Object management helper functions.
7637  */
7638 
7639 /*
7640  * Given a crypto_key_t, return whether the key can be used or not
7641  * for the specified request. The attributes used here are defined
7642  * in table 42 of the PKCS#11 spec (Common secret key attributes).
7643  */
7644 static int
7645 dprov_key_can_use(dprov_object_t *object, dprov_req_type_t req_type)
7646 {
7647 	boolean_t ret = 0;
7648 	int rv = CRYPTO_SUCCESS;
7649 
7650 	/* check if object is allowed for specified operation */
7651 	switch (req_type) {
7652 	case DPROV_REQ_ENCRYPT_INIT:
7653 	case DPROV_REQ_ENCRYPT_ATOMIC:
7654 		rv = dprov_get_object_attr_boolean(object,
7655 		    DPROV_CKA_ENCRYPT, &ret);
7656 		break;
7657 	case DPROV_REQ_DECRYPT_INIT:
7658 	case DPROV_REQ_DECRYPT_ATOMIC:
7659 		rv = dprov_get_object_attr_boolean(object,
7660 		    DPROV_CKA_DECRYPT, &ret);
7661 		break;
7662 	case DPROV_REQ_SIGN_INIT:
7663 	case DPROV_REQ_SIGN_ATOMIC:
7664 	case DPROV_REQ_MAC_INIT:
7665 	case DPROV_REQ_MAC_ATOMIC:
7666 	case DPROV_REQ_MAC_VERIFY_ATOMIC:
7667 		rv = dprov_get_object_attr_boolean(object,
7668 		    DPROV_CKA_SIGN, &ret);
7669 		break;
7670 	case DPROV_REQ_SIGN_RECOVER_INIT:
7671 	case DPROV_REQ_SIGN_RECOVER_ATOMIC:
7672 		rv = dprov_get_object_attr_boolean(object,
7673 		    DPROV_CKA_SIGN_RECOVER, &ret);
7674 		break;
7675 	case DPROV_REQ_VERIFY_INIT:
7676 	case DPROV_REQ_VERIFY_ATOMIC:
7677 		rv = dprov_get_object_attr_boolean(object,
7678 		    DPROV_CKA_VERIFY, &ret);
7679 		break;
7680 	case DPROV_REQ_VERIFY_RECOVER_INIT:
7681 	case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
7682 		rv = dprov_get_object_attr_boolean(object,
7683 		    DPROV_CKA_VERIFY_RECOVER, &ret);
7684 		break;
7685 	case DPROV_REQ_KEY_WRAP:
7686 		rv = dprov_get_object_attr_boolean(object,
7687 		    DPROV_CKA_WRAP, &ret);
7688 		break;
7689 	case DPROV_REQ_KEY_UNWRAP:
7690 		rv = dprov_get_object_attr_boolean(object,
7691 		    DPROV_CKA_UNWRAP, &ret);
7692 		break;
7693 	case DPROV_REQ_DIGEST_KEY:
7694 		/*
7695 		 * There is no attribute to check for; therefore,
7696 		 * any secret key can be used.
7697 		 */
7698 		ret = B_TRUE;
7699 		rv = CRYPTO_SUCCESS;
7700 		break;
7701 	case DPROV_REQ_KEY_DERIVE:
7702 		rv = dprov_get_object_attr_boolean(object,
7703 		    DPROV_CKA_DERIVE, &ret);
7704 		break;
7705 	}
7706 
7707 	if (rv != CRYPTO_SUCCESS || !ret)
7708 		return (CRYPTO_KEY_FUNCTION_NOT_PERMITTED);
7709 
7710 	return (CRYPTO_SUCCESS);
7711 }
7712 
7713 /*
7714  * Given a crypto_key_t corresponding to a secret key (i.e. for
7715  * use with symmetric crypto algorithms) specified in raw format, by
7716  * attribute, or by reference, initialize the ck_data and ck_length
7717  * fields of the ret_key argument so that they specify the key value
7718  * and length.
7719  *
7720  * For a key by value, this function uess the ck_data and ck_length,
7721  * for a key by reference, it looks up the corresponding object and
7722  * returns the appropriate attribute. For a key by attribute, it returns
7723  * the appropriate attribute. The attributes used are CKA_VALUE to retrieve
7724  * the value of the key, and CKA_VALUE_LEN to retrieve its length in bytes.
7725  */
7726 static int
7727 dprov_key_value_secret(dprov_state_t *softc, crypto_session_id_t session_id,
7728     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
7729 {
7730 	ulong_t key_type;
7731 	int ret = CRYPTO_SUCCESS;
7732 
7733 	ret_key->ck_format = CRYPTO_KEY_RAW;
7734 
7735 	switch (key->ck_format) {
7736 
7737 	case CRYPTO_KEY_RAW:
7738 		ret_key->ck_data = key->ck_data;
7739 		ret_key->ck_length = key->ck_length;
7740 		break;
7741 
7742 	case CRYPTO_KEY_ATTR_LIST: {
7743 		void *value;
7744 		size_t len, value_len;
7745 
7746 		if ((ret = dprov_get_key_attr_ulong(key, DPROV_CKA_KEY_TYPE,
7747 		    &key_type)) != CRYPTO_SUCCESS)
7748 			break;
7749 
7750 		if ((ret = dprov_get_key_attr_array(key, DPROV_CKA_VALUE,
7751 		    &value, &len)) != CRYPTO_SUCCESS)
7752 			break;
7753 
7754 		/*
7755 		 * The length of the array is expressed in bytes.
7756 		 * Convert to bits now since that's how keys are measured.
7757 		 */
7758 		len  = len << 3;
7759 
7760 		/* optional */
7761 		if ((dprov_get_key_attr_ulong(key, DPROV_CKA_VALUE_LEN,
7762 		    &value_len)) == CRYPTO_SUCCESS) {
7763 			len = value_len;
7764 		}
7765 
7766 		ret_key->ck_data = value;
7767 		ret_key->ck_length = (uint_t)len;
7768 
7769 		break;
7770 	}
7771 
7772 	case CRYPTO_KEY_REFERENCE: {
7773 		dprov_object_t *object;
7774 		void *value;
7775 		size_t len, value_len;
7776 
7777 		/* check session id */
7778 		if (softc->ds_sessions[session_id] == NULL) {
7779 			ret = CRYPTO_SESSION_HANDLE_INVALID;
7780 			break;
7781 		}
7782 
7783 		if (key->ck_obj_id >= DPROV_MAX_OBJECTS) {
7784 			ret = CRYPTO_KEY_HANDLE_INVALID;
7785 			goto bail;
7786 		}
7787 
7788 		/* check if object id specified by key is valid */
7789 		object = softc->ds_sessions[session_id]->
7790 		    ds_objects[key->ck_obj_id];
7791 		if (object == NULL) {
7792 			ret = CRYPTO_KEY_HANDLE_INVALID;
7793 			goto bail;
7794 		}
7795 
7796 		/* check if object can be used for operation */
7797 		if ((ret = dprov_key_can_use(object, req_type)) !=
7798 		    CRYPTO_SUCCESS)
7799 			goto bail;
7800 
7801 		if ((ret = dprov_get_object_attr_ulong(object,
7802 		    DPROV_CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS)
7803 			goto bail;
7804 
7805 		if ((ret = dprov_get_object_attr_array(object,
7806 		    DPROV_CKA_VALUE, &value, &len)) != CRYPTO_SUCCESS)
7807 			goto bail;
7808 
7809 		/* optional */
7810 		if ((dprov_get_object_attr_ulong(object, DPROV_CKA_VALUE_LEN,
7811 		    &value_len)) == CRYPTO_SUCCESS) {
7812 			len = value_len;
7813 		}
7814 
7815 		/*
7816 		 * The length of attributes are in bytes.
7817 		 * Convert to bits now since that's how keys are measured.
7818 		 */
7819 		len  = len << 3;
7820 
7821 		ret_key->ck_data = value;
7822 		ret_key->ck_length = (uint_t)len;
7823 bail:
7824 		break;
7825 	}
7826 
7827 	default:
7828 		ret = CRYPTO_ARGUMENTS_BAD;
7829 		break;
7830 	}
7831 
7832 	return (ret);
7833 }
7834 
7835 /*
7836  * Get the attribute list for the specified asymmetric key.
7837  */
7838 static int
7839 dprov_key_attr_asymmetric(dprov_state_t *softc, crypto_session_id_t session_id,
7840     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
7841 {
7842 	int ret = CRYPTO_SUCCESS;
7843 
7844 	ret_key->ck_format = CRYPTO_KEY_ATTR_LIST;
7845 
7846 	switch (key->ck_format) {
7847 
7848 	case CRYPTO_KEY_ATTR_LIST:
7849 		ret_key->ck_attrs = key->ck_attrs;
7850 		ret_key->ck_count = key->ck_count;
7851 		break;
7852 
7853 	case CRYPTO_KEY_REFERENCE: {
7854 		dprov_object_t *object;
7855 
7856 		/* check session id */
7857 		if (softc->ds_sessions[session_id] == NULL) {
7858 			ret = CRYPTO_SESSION_HANDLE_INVALID;
7859 			break;
7860 		}
7861 
7862 		/* check if object id specified by key is valid */
7863 		object = softc->ds_sessions[session_id]->
7864 		    ds_objects[key->ck_obj_id];
7865 		if (object == NULL) {
7866 			ret = CRYPTO_KEY_HANDLE_INVALID;
7867 			break;
7868 		}
7869 
7870 		/* check if object can be used for operation */
7871 		if ((ret = dprov_key_can_use(object, req_type)) !=
7872 		    CRYPTO_SUCCESS)
7873 			break;
7874 
7875 		ret_key->ck_attrs = object->do_attr;
7876 		ret_key->ck_count = DPROV_MAX_ATTR;
7877 		break;
7878 	}
7879 
7880 	default:
7881 		ret = CRYPTO_ARGUMENTS_BAD;
7882 	}
7883 
7884 	return (ret);
7885 }
7886 
7887 /*
7888  * Return the index of an attribute of specified type found in
7889  * the specified array of attributes. If the attribute cannot
7890  * found, return -1.
7891  */
7892 static int
7893 dprov_find_attr(crypto_object_attribute_t *attr, uint_t nattr,
7894     uint64_t attr_type)
7895 {
7896 	int i;
7897 
7898 	for (i = 0; i < nattr; i++)
7899 		if (attr[i].oa_value != NULL &&
7900 		    attr[i].oa_type == attr_type)
7901 			return (i);
7902 
7903 	return (-1);
7904 }
7905 
7906 /*
7907  * Given the given object template and session, return whether
7908  * an object can be created from that template according to the
7909  * following rules:
7910  * - private objects can be created only by a logged-in user
7911  */
7912 static int
7913 dprov_template_can_create(dprov_session_t *session,
7914     crypto_object_attribute_t *template, uint_t nattr,
7915     boolean_t check_for_secret)
7916 {
7917 	boolean_t is_private = B_FALSE;
7918 	ulong_t key_type, class;
7919 	int error;
7920 
7921 	/* check CKA_PRIVATE attribute value */
7922 	error = dprov_get_template_attr_boolean(template, nattr,
7923 	    DPROV_CKA_PRIVATE, &is_private);
7924 	if (error == CRYPTO_SUCCESS && is_private) {
7925 		/* it's a private object */
7926 		if (session->ds_state != DPROV_SESSION_STATE_USER) {
7927 			/*
7928 			 * Cannot create private object with SO or public
7929 			 * sessions.
7930 			 */
7931 			return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
7932 		}
7933 	}
7934 
7935 	/* all objects must have an object class attribute */
7936 	if (dprov_get_template_attr_ulong(template, nattr, DPROV_CKA_CLASS,
7937 	    &class) != CRYPTO_SUCCESS) {
7938 		return (CRYPTO_TEMPLATE_INCOMPLETE);
7939 	}
7940 
7941 	/* key objects must have a key type attribute */
7942 	if (class == DPROV_CKO_SECRET_KEY ||
7943 	    class == DPROV_CKO_PUBLIC_KEY ||
7944 	    class == DPROV_CKO_PRIVATE_KEY) {
7945 		if (!dprov_template_attr_present(template, nattr,
7946 		    DPROV_CKA_KEY_TYPE)) {
7947 			return (CRYPTO_TEMPLATE_INCOMPLETE);
7948 		}
7949 	}
7950 
7951 	/* check for RSA public key attributes that must be present */
7952 	if (class == DPROV_CKO_PUBLIC_KEY) {
7953 		if (dprov_get_template_attr_ulong(template, nattr,
7954 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
7955 			if (key_type == DPROV_CKK_RSA) {
7956 				if (!dprov_template_attr_present(template,
7957 				    nattr, DPROV_CKA_MODULUS) ||
7958 				    !dprov_template_attr_present(template,
7959 				    nattr, DPROV_CKA_PUBLIC_EXPONENT)) {
7960 					return (CRYPTO_TEMPLATE_INCOMPLETE);
7961 				}
7962 
7963 				/* these attributes should not be present */
7964 				if (dprov_template_attr_present(template, nattr,
7965 				    DPROV_CKA_MODULUS_BITS)) {
7966 					return (CRYPTO_TEMPLATE_INCONSISTENT);
7967 				}
7968 			}
7969 		}
7970 	}
7971 
7972 	/* check for RSA private key attributes that must be present */
7973 	if (class == DPROV_CKO_PRIVATE_KEY) {
7974 		if (dprov_get_template_attr_ulong(template, nattr,
7975 		    DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
7976 			if (key_type == DPROV_CKK_RSA) {
7977 				if (!dprov_template_attr_present(template,
7978 				    nattr, DPROV_CKA_MODULUS))
7979 					return (CRYPTO_TEMPLATE_INCOMPLETE);
7980 
7981 				if (check_for_secret) {
7982 					if (!dprov_template_attr_present(
7983 					    template, nattr,
7984 					    DPROV_CKA_PRIVATE_EXPONENT))
7985 						return (
7986 						    CRYPTO_TEMPLATE_INCOMPLETE);
7987 				}
7988 			}
7989 		}
7990 	}
7991 
7992 	/* check for secret key attributes that must be present */
7993 	if (class == DPROV_CKO_SECRET_KEY) {
7994 		if (check_for_secret) {
7995 			if (!dprov_template_attr_present(template, nattr,
7996 			    DPROV_CKA_VALUE)) {
7997 				return (CRYPTO_TEMPLATE_INCOMPLETE);
7998 			}
7999 		}
8000 
8001 		/* these attributes should not be present */
8002 		if (dprov_template_attr_present(template, nattr,
8003 		    DPROV_CKA_VALUE_LEN)) {
8004 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8005 		}
8006 	}
8007 
8008 	return (CRYPTO_SUCCESS);
8009 }
8010 
8011 /*
8012  * Create an object from the specified template. Checks whether the
8013  * object can be created according to its attributes and the state
8014  * of the session. The new session object id is returned. If the
8015  * object is a token object, it is added to the per-instance object
8016  * table as well.
8017  */
8018 static int
8019 dprov_create_object_from_template(dprov_state_t *softc,
8020     dprov_session_t *session, crypto_object_attribute_t *template,
8021     uint_t nattr, crypto_object_id_t *object_id, boolean_t check_for_secret,
8022     boolean_t force)
8023 {
8024 	dprov_object_t *object;
8025 	boolean_t is_token = B_FALSE;
8026 	boolean_t extractable_attribute_present = B_FALSE;
8027 	boolean_t private_attribute_present = B_FALSE;
8028 	uint_t i;
8029 	int error;
8030 	uint_t attr;
8031 	uint_t oattr;
8032 	crypto_attr_type_t type;
8033 	size_t old_len, new_len;
8034 	offset_t offset;
8035 
8036 	if (nattr > DPROV_MAX_ATTR)
8037 		return (CRYPTO_HOST_MEMORY);
8038 
8039 	if (!force) {
8040 		/* verify that object can be created */
8041 		if ((error = dprov_template_can_create(session, template,
8042 		    nattr, check_for_secret)) != CRYPTO_SUCCESS)
8043 			return (error);
8044 	}
8045 
8046 	/* allocate new object */
8047 	object = kmem_zalloc(sizeof (dprov_object_t), KM_SLEEP);
8048 	if (object == NULL)
8049 		return (CRYPTO_HOST_MEMORY);
8050 
8051 	/* is it a token object? */
8052 	/* check CKA_TOKEN attribute value */
8053 	error = dprov_get_template_attr_boolean(template, nattr,
8054 	    DPROV_CKA_TOKEN, &is_token);
8055 	if (error == CRYPTO_SUCCESS && is_token) {
8056 		/* token object, add it to the per-instance object table */
8057 		for (i = 0; i < DPROV_MAX_OBJECTS; i++)
8058 			if (softc->ds_objects[i] == NULL)
8059 				break;
8060 		if (i == DPROV_MAX_OBJECTS)
8061 			/* no free slot */
8062 			return (CRYPTO_HOST_MEMORY);
8063 		softc->ds_objects[i] = object;
8064 		object->do_token_idx = i;
8065 		DPROV_OBJECT_REFHOLD(object);
8066 	}
8067 
8068 	/* add object to session object table */
8069 	for (i = 0; i < DPROV_MAX_OBJECTS; i++)
8070 		if (session->ds_objects[i] == NULL)
8071 			break;
8072 	if (i == DPROV_MAX_OBJECTS) {
8073 		/* no more session object slots */
8074 		DPROV_OBJECT_REFRELE(object);
8075 		return (CRYPTO_HOST_MEMORY);
8076 	}
8077 	session->ds_objects[i] = object;
8078 	DPROV_OBJECT_REFHOLD(object);
8079 	*object_id = i;
8080 
8081 	/* initialize object from template */
8082 	for (attr = 0, oattr = 0; attr < nattr; attr++) {
8083 		if (template[attr].oa_value == NULL)
8084 			continue;
8085 		type = template[attr].oa_type;
8086 		old_len = template[attr].oa_value_len;
8087 		new_len = attribute_size(type, old_len);
8088 
8089 		if (type == DPROV_CKA_EXTRACTABLE) {
8090 			extractable_attribute_present = B_TRUE;
8091 		} else if (type == DPROV_CKA_PRIVATE) {
8092 			private_attribute_present = B_TRUE;
8093 		}
8094 		object->do_attr[oattr].oa_type = type;
8095 		object->do_attr[oattr].oa_value_len = new_len;
8096 
8097 		object->do_attr[oattr].oa_value = kmem_zalloc(new_len,
8098 		    KM_SLEEP);
8099 
8100 		offset = 0;
8101 #ifdef _BIG_ENDIAN
8102 		if (fixed_size_attribute(type)) {
8103 			offset = old_len - new_len;
8104 		}
8105 #endif
8106 		bcopy(&template[attr].oa_value[offset],
8107 		    object->do_attr[oattr].oa_value, new_len);
8108 		oattr++;
8109 	}
8110 
8111 	/* add boolean attributes that must be present */
8112 	if (extractable_attribute_present == B_FALSE) {
8113 		object->do_attr[oattr].oa_type = DPROV_CKA_EXTRACTABLE;
8114 		object->do_attr[oattr].oa_value_len = 1;
8115 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
8116 		object->do_attr[oattr].oa_value[0] = B_TRUE;
8117 		oattr++;
8118 	}
8119 
8120 	if (private_attribute_present == B_FALSE) {
8121 		object->do_attr[oattr].oa_type = DPROV_CKA_PRIVATE;
8122 		object->do_attr[oattr].oa_value_len = 1;
8123 		object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
8124 		object->do_attr[oattr].oa_value[0] = B_FALSE;
8125 		oattr++;
8126 	}
8127 
8128 	return (CRYPTO_SUCCESS);
8129 }
8130 
8131 /*
8132  * Checks whether or not the object matches the specified attributes.
8133  *
8134  * PKCS#11 attributes which are longs are stored in uint32_t containers
8135  * so they can be matched by both 32 and 64-bit applications.
8136  */
8137 static boolean_t
8138 dprov_attributes_match(dprov_object_t *object,
8139     crypto_object_attribute_t *template, uint_t nattr)
8140 {
8141 	crypto_attr_type_t type;
8142 	size_t tlen, olen, diff;
8143 	int ta_idx;	/* template attribute index */
8144 	int oa_idx;	/* object attribute index */
8145 
8146 	for (ta_idx = 0; ta_idx < nattr; ta_idx++) {
8147 		/* no value for template attribute */
8148 		if (template[ta_idx].oa_value == NULL)
8149 			continue;
8150 
8151 		/* find attribute in object */
8152 		type = template[ta_idx].oa_type;
8153 		oa_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
8154 
8155 		if (oa_idx == -1)
8156 			/* attribute not found in object */
8157 			return (B_FALSE);
8158 
8159 		tlen = template[ta_idx].oa_value_len;
8160 		olen = object->do_attr[oa_idx].oa_value_len;
8161 		if (tlen < olen)
8162 			return (B_FALSE);
8163 
8164 		diff = 0;
8165 #ifdef _BIG_ENDIAN
8166 		/* application may think attribute is 8 bytes */
8167 		if (fixed_size_attribute(type))
8168 			diff = tlen - olen;
8169 #endif
8170 
8171 		if (bcmp(&template[ta_idx].oa_value[diff],
8172 		    object->do_attr[oa_idx].oa_value, olen) != 0)
8173 			/* value mismatch */
8174 			return (B_FALSE);
8175 	}
8176 
8177 	return (B_TRUE);
8178 }
8179 
8180 /*
8181  * Destroy the object specified by its session and object id.
8182  */
8183 static int
8184 dprov_destroy_object(dprov_state_t *softc, dprov_session_t *session,
8185     crypto_object_id_t object_id)
8186 {
8187 	dprov_object_t *object;
8188 
8189 	if ((object = session->ds_objects[object_id]) == NULL)
8190 		return (CRYPTO_OBJECT_HANDLE_INVALID);
8191 
8192 	if (dprov_object_is_token(object)) {
8193 		object->do_destroyed = B_TRUE;
8194 		/* it's a token object, remove from per-instance table */
8195 		softc->ds_objects[object->do_token_idx] = NULL;
8196 		DPROV_OBJECT_REFRELE(object);
8197 	}
8198 
8199 	/* remove from session table */
8200 	session->ds_objects[object_id] = NULL;
8201 	DPROV_OBJECT_REFRELE(object);
8202 	return (CRYPTO_SUCCESS);
8203 }
8204 
8205 static int
8206 dprov_object_can_modify(dprov_object_t *object,
8207     crypto_object_attribute_t *template, uint_t nattr)
8208 {
8209 	ulong_t object_class;
8210 
8211 	/* all objects should have an object class attribute */
8212 	if (dprov_get_object_attr_ulong(object, DPROV_CKA_CLASS,
8213 	    &object_class) != CRYPTO_SUCCESS) {
8214 		return (CRYPTO_SUCCESS);
8215 	}
8216 
8217 	if (object_class == DPROV_CKO_SECRET_KEY ||
8218 	    object_class == DPROV_CKO_PUBLIC_KEY ||
8219 	    object_class == DPROV_CKO_PRIVATE_KEY) {
8220 		if (dprov_template_attr_present(template, nattr,
8221 		    DPROV_CKA_CLASS) ||
8222 		    dprov_template_attr_present(template, nattr,
8223 		    DPROV_CKA_KEY_TYPE))
8224 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8225 	}
8226 
8227 	switch (object_class) {
8228 	case DPROV_CKO_SECRET_KEY:
8229 		if (dprov_template_attr_present(template, nattr,
8230 		    DPROV_CKA_VALUE))
8231 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8232 		break;
8233 
8234 	case DPROV_CKO_PUBLIC_KEY:
8235 		if (dprov_template_attr_present(template, nattr,
8236 		    DPROV_CKA_MODULUS) ||
8237 		    dprov_template_attr_present(template, nattr,
8238 		    DPROV_CKA_PUBLIC_EXPONENT))
8239 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8240 		break;
8241 
8242 	case DPROV_CKO_PRIVATE_KEY:
8243 		if (dprov_template_attr_present(template, nattr,
8244 		    DPROV_CKA_MODULUS) ||
8245 		    dprov_template_attr_present(template, nattr,
8246 		    DPROV_CKA_PRIVATE_EXPONENT))
8247 			return (CRYPTO_TEMPLATE_INCONSISTENT);
8248 		break;
8249 
8250 	default:
8251 		return (CRYPTO_SUCCESS);
8252 	}
8253 
8254 	return (CRYPTO_SUCCESS);
8255 }
8256 
8257 /*
8258  * Set the attributes specified by the template in the specified object,
8259  * replacing existing ones if needed.
8260  */
8261 static int
8262 dprov_object_set_attr(dprov_session_t *session, crypto_object_id_t object_id,
8263     crypto_object_attribute_t *template, uint_t nattr,
8264     boolean_t check_attributes)
8265 {
8266 	crypto_attr_type_t type;
8267 	dprov_object_t *object;
8268 	size_t old_len, new_len;
8269 	uint_t i, j;
8270 	int error;
8271 
8272 	if ((object = session->ds_objects[object_id]) == NULL)
8273 		return (CRYPTO_OBJECT_HANDLE_INVALID);
8274 
8275 	if (check_attributes) {
8276 		/* verify that attributes in the template can be modified */
8277 		if ((error = dprov_object_can_modify(object, template, nattr))
8278 		    != CRYPTO_SUCCESS)
8279 			return (error);
8280 	}
8281 
8282 	/* go through the attributes specified in the template */
8283 	for (i = 0; i < nattr; i++) {
8284 		if (template[i].oa_value == NULL)
8285 			continue;
8286 
8287 		/* find attribute in object */
8288 		type = template[i].oa_type;
8289 		j = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
8290 
8291 		if (j != -1) {
8292 			/* attribute already exists, free old value */
8293 			kmem_free(object->do_attr[j].oa_value,
8294 			    object->do_attr[j].oa_value_len);
8295 		} else {
8296 			/* attribute does not exist, create it */
8297 			for (j = 0; j < DPROV_MAX_ATTR; j++)
8298 				if (object->do_attr[j].oa_value == NULL)
8299 					break;
8300 			if (j == DPROV_MAX_ATTR)
8301 				/* ran out of attribute slots */
8302 				return (CRYPTO_HOST_MEMORY);
8303 		}
8304 
8305 		old_len = template[i].oa_value_len;
8306 		new_len = attribute_size(type, old_len);
8307 
8308 		/* set object attribute value */
8309 		object->do_attr[j].oa_value = kmem_alloc(new_len, KM_SLEEP);
8310 		bcopy(&template[i].oa_value[old_len - new_len],
8311 		    object->do_attr[j].oa_value, new_len);
8312 		object->do_attr[j].oa_value_len = new_len;
8313 
8314 		/* and the type */
8315 		object->do_attr[j].oa_type = type;
8316 	}
8317 
8318 	return (CRYPTO_SUCCESS);
8319 }
8320 
8321 
8322 /*
8323  * Free the specified object.
8324  */
8325 static void
8326 dprov_free_object(dprov_object_t *object)
8327 {
8328 	int i;
8329 
8330 	/* free the object attributes values */
8331 	for (i = 0; i < DPROV_MAX_ATTR; i++)
8332 		if (object->do_attr[i].oa_value != NULL)
8333 			kmem_free(object->do_attr[i].oa_value,
8334 			    object->do_attr[i].oa_value_len);
8335 
8336 	/* free the object */
8337 	kmem_free(object, sizeof (dprov_object_t));
8338 }
8339 
8340 /*
8341  * Checks whether the specified object is a private or public object.
8342  */
8343 static boolean_t
8344 dprov_object_is_private(dprov_object_t *object)
8345 {
8346 	boolean_t ret;
8347 	int err;
8348 
8349 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_PRIVATE, &ret);
8350 
8351 	if (err != CRYPTO_SUCCESS)
8352 		/* by default, CKA_PRIVATE is false */
8353 		ret = B_FALSE;
8354 
8355 	return (ret);
8356 }
8357 
8358 /*
8359  * Checks whether the specified object is a token or session object.
8360  */
8361 static boolean_t
8362 dprov_object_is_token(dprov_object_t *object)
8363 {
8364 	boolean_t ret;
8365 	int err;
8366 
8367 	err = dprov_get_object_attr_boolean(object, DPROV_CKA_TOKEN, &ret);
8368 
8369 	if (err != CRYPTO_SUCCESS)
8370 		/* by default, CKA_TOKEN is false */
8371 		ret = B_FALSE;
8372 
8373 	return (ret);
8374 }
8375 
8376 /*
8377  * Common function used by the dprov_get_object_attr_*() family of
8378  * functions. Returns the value of the specified attribute of specified
8379  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
8380  * if the length of the attribute does not match the specified length,
8381  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
8382  */
8383 static int
8384 dprov_get_object_attr_scalar_common(dprov_object_t *object, uint64_t attr_type,
8385 				    void *value, size_t value_len)
8386 {
8387 	int attr_idx;
8388 	size_t oa_value_len;
8389 	size_t offset = 0;
8390 
8391 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
8392 	    attr_type)) == -1)
8393 		return (CRYPTO_ARGUMENTS_BAD);
8394 
8395 	oa_value_len = object->do_attr[attr_idx].oa_value_len;
8396 	if (oa_value_len != value_len) {
8397 		/*
8398 		 * For some attributes, it's okay to copy the value
8399 		 * into a larger container, e.g. copy an unsigned
8400 		 * 32-bit integer into a 64-bit container.
8401 		 */
8402 		if (attr_type == DPROV_CKA_VALUE_LEN ||
8403 		    attr_type == DPROV_CKA_KEY_TYPE ||
8404 		    attr_type == DPROV_CKA_CLASS) {
8405 			if (oa_value_len < value_len) {
8406 #ifdef _BIG_ENDIAN
8407 				offset = value_len - oa_value_len;
8408 #endif
8409 				bzero(value, value_len);
8410 				goto do_copy;
8411 			}
8412 		}
8413 		/* incorrect attribute value length */
8414 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8415 	}
8416 
8417 do_copy:
8418 	bcopy(object->do_attr[attr_idx].oa_value, (uchar_t *)value + offset,
8419 	    oa_value_len);
8420 
8421 	return (CRYPTO_SUCCESS);
8422 }
8423 
8424 /*
8425  * Get the value of the a boolean attribute from the specified object.
8426  */
8427 static int
8428 dprov_get_object_attr_boolean(dprov_object_t *object, uint64_t attr_type,
8429     boolean_t *attr_value)
8430 {
8431 	uchar_t val;
8432 	int ret;
8433 
8434 	/* PKCS#11 defines a boolean as one byte */
8435 	ret = dprov_get_object_attr_scalar_common(object, attr_type, &val, 1);
8436 	if (ret == CRYPTO_SUCCESS) {
8437 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
8438 	}
8439 	return (ret);
8440 }
8441 
8442 /*
8443  * Get the value of a ulong_t attribute from the specified object.
8444  */
8445 static int
8446 dprov_get_object_attr_ulong(dprov_object_t *object, uint64_t attr_type,
8447     ulong_t *attr_value)
8448 {
8449 	return (dprov_get_object_attr_scalar_common(object, attr_type,
8450 	    attr_value, sizeof (ulong_t)));
8451 }
8452 
8453 /*
8454  * Find the specified byte array attribute of specified type in
8455  * the specified object. Returns CRYPTO_SUCCESS
8456  * on success or CRYPTO_ARGUMENTS_BAD if the specified
8457  * attribute cannot be found.
8458  */
8459 static int
8460 dprov_get_object_attr_array(dprov_object_t *object, uint64_t attr_type,
8461     void **array, size_t *len)
8462 {
8463 	int attr_idx;
8464 
8465 	if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
8466 	    attr_type)) == -1)
8467 		return (CRYPTO_ARGUMENTS_BAD);
8468 
8469 	*array = object->do_attr[attr_idx].oa_value;
8470 	*len = object->do_attr[attr_idx].oa_value_len;
8471 
8472 	return (CRYPTO_SUCCESS);
8473 }
8474 
8475 /*
8476  * Common function used by the dprov_get_template_attr_*() family of
8477  * functions. Returns the value of the specified attribute of specified
8478  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
8479  * if the length of the attribute does not match the specified length,
8480  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
8481  */
8482 static int
8483 dprov_get_template_attr_scalar_common(crypto_object_attribute_t *template,
8484     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
8485 {
8486 	size_t oa_value_len;
8487 	size_t offset = 0;
8488 	int attr_idx;
8489 
8490 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
8491 		return (CRYPTO_ARGUMENTS_BAD);
8492 
8493 	oa_value_len = template[attr_idx].oa_value_len;
8494 	if (oa_value_len != value_len) {
8495 		/*
8496 		 * For some attributes, it's okay to copy the value
8497 		 * into a larger container, e.g. copy an unsigned
8498 		 * 32-bit integer into a 64-bit container.
8499 		 */
8500 		if (attr_type == DPROV_CKA_VALUE_LEN ||
8501 		    attr_type == DPROV_CKA_KEY_TYPE ||
8502 		    attr_type == DPROV_CKA_CLASS) {
8503 			if (oa_value_len < value_len) {
8504 #ifdef _BIG_ENDIAN
8505 				offset = value_len - oa_value_len;
8506 #endif
8507 				bzero(value, value_len);
8508 				goto do_copy;
8509 			}
8510 		}
8511 		/* incorrect attribute value length */
8512 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8513 	}
8514 
8515 do_copy:
8516 	bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
8517 	    oa_value_len);
8518 
8519 	return (CRYPTO_SUCCESS);
8520 }
8521 
8522 /*
8523  * Get the value of the a boolean attribute from the specified template
8524  */
8525 static int
8526 dprov_get_template_attr_boolean(crypto_object_attribute_t *template,
8527     uint_t nattr, uint64_t attr_type, boolean_t *attr_value)
8528 {
8529 	uchar_t val;
8530 	int ret;
8531 
8532 	/* PKCS#11 defines a boolean as one byte */
8533 	ret = dprov_get_template_attr_scalar_common(template, nattr,
8534 	    attr_type, &val, 1);
8535 	if (ret == CRYPTO_SUCCESS) {
8536 		*attr_value = (val == '\0') ? B_FALSE : B_TRUE;
8537 	}
8538 	return (ret);
8539 }
8540 
8541 /*
8542  * Get the value of a ulong_t attribute from the specified template.
8543  */
8544 static int
8545 dprov_get_template_attr_ulong(crypto_object_attribute_t *template,
8546     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
8547 {
8548 	return (dprov_get_template_attr_scalar_common(template, nattr,
8549 	    attr_type, attr_value, sizeof (ulong_t)));
8550 }
8551 
8552 static int
8553 dprov_template_attr_present(crypto_object_attribute_t *template,
8554     uint_t nattr, uint64_t attr_type)
8555 {
8556 	return (dprov_find_attr(template, nattr,
8557 	    attr_type) == -1 ? B_FALSE : B_TRUE);
8558 }
8559 
8560 /*
8561  * Find the specified byte array attribute of specified type in
8562  * the specified template. Returns CRYPTO_SUCCESS on success or
8563  * CRYPTO_ARGUMENTS_BAD if the specified attribute cannot be found.
8564  */
8565 static int
8566 dprov_get_template_attr_array(crypto_object_attribute_t *template,
8567     uint_t nattr, uint64_t attr_type, void **array, size_t *len)
8568 {
8569 	int attr_idx;
8570 
8571 	if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
8572 		return (CRYPTO_ARGUMENTS_BAD);
8573 
8574 	*array = template[attr_idx].oa_value;
8575 	*len = template[attr_idx].oa_value_len;
8576 
8577 	return (CRYPTO_SUCCESS);
8578 }
8579 
8580 /*
8581  * Common function used by the dprov_get_key_attr_*() family of
8582  * functions. Returns the value of the specified attribute of specified
8583  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
8584  * if the length of the attribute does not match the specified length,
8585  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
8586  */
8587 static int
8588 dprov_get_key_attr_scalar_common(crypto_key_t *key, uint64_t attr_type,
8589     void *value, size_t value_len)
8590 {
8591 	int attr_idx;
8592 
8593 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
8594 
8595 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
8596 	    attr_type)) == -1)
8597 		return (CRYPTO_ARGUMENTS_BAD);
8598 
8599 	if (key->ck_attrs[attr_idx].oa_value_len != value_len)
8600 		/* incorrect attribute value length */
8601 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8602 
8603 	bcopy(key->ck_attrs[attr_idx].oa_value, value, value_len);
8604 
8605 	return (CRYPTO_SUCCESS);
8606 }
8607 
8608 /*
8609  * Get the value of a ulong_t attribute from the specified key.
8610  */
8611 static int
8612 dprov_get_key_attr_ulong(crypto_key_t *key, uint64_t attr_type,
8613     ulong_t *attr_value)
8614 {
8615 	return (dprov_get_key_attr_scalar_common(key, attr_type,
8616 	    attr_value, sizeof (ulong_t)));
8617 }
8618 
8619 /*
8620  * Find the specified byte array attribute of specified type in
8621  * the specified key by attributes. Returns CRYPTO_SUCCESS
8622  * on success or CRYPTO_ARGUMENTS_BAD if the specified
8623  * attribute cannot be found.
8624  */
8625 static int
8626 dprov_get_key_attr_array(crypto_key_t *key, uint64_t attr_type,
8627     void **array, size_t *len)
8628 {
8629 	int attr_idx;
8630 
8631 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
8632 
8633 	if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
8634 	    attr_type)) == -1)
8635 		return (CRYPTO_ARGUMENTS_BAD);
8636 
8637 	*array = key->ck_attrs[attr_idx].oa_value;
8638 	*len = key->ck_attrs[attr_idx].oa_value_len;
8639 
8640 	return (CRYPTO_SUCCESS);
8641 }
8642 
8643 static void
8644 dprov_release_session_objects(dprov_session_t *session)
8645 {
8646 	dprov_object_t *object;
8647 	int i;
8648 
8649 	for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
8650 		object = session->ds_objects[i];
8651 		if (object != NULL) {
8652 			DPROV_OBJECT_REFRELE(object);
8653 		}
8654 	}
8655 }
8656