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