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