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