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