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