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