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