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