xref: /freebsd-src/sys/contrib/openzfs/module/icp/io/sha2_mod.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy  * CDDL HEADER START
3*eda14cbcSMatt Macy  *
4*eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5*eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6*eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7*eda14cbcSMatt Macy  *
8*eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*eda14cbcSMatt Macy  * or http://www.opensolaris.org/os/licensing.
10*eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11*eda14cbcSMatt Macy  * and limitations under the License.
12*eda14cbcSMatt Macy  *
13*eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14*eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16*eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17*eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*eda14cbcSMatt Macy  *
19*eda14cbcSMatt Macy  * CDDL HEADER END
20*eda14cbcSMatt Macy  */
21*eda14cbcSMatt Macy 
22*eda14cbcSMatt Macy /*
23*eda14cbcSMatt Macy  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*eda14cbcSMatt Macy  * Use is subject to license terms.
25*eda14cbcSMatt Macy  */
26*eda14cbcSMatt Macy 
27*eda14cbcSMatt Macy #include <sys/zfs_context.h>
28*eda14cbcSMatt Macy #include <sys/modctl.h>
29*eda14cbcSMatt Macy #include <sys/crypto/common.h>
30*eda14cbcSMatt Macy #include <sys/crypto/spi.h>
31*eda14cbcSMatt Macy #include <sys/crypto/icp.h>
32*eda14cbcSMatt Macy #define	_SHA2_IMPL
33*eda14cbcSMatt Macy #include <sys/sha2.h>
34*eda14cbcSMatt Macy #include <sha2/sha2_impl.h>
35*eda14cbcSMatt Macy 
36*eda14cbcSMatt Macy /*
37*eda14cbcSMatt Macy  * The sha2 module is created with two modlinkages:
38*eda14cbcSMatt Macy  * - a modlmisc that allows consumers to directly call the entry points
39*eda14cbcSMatt Macy  *   SHA2Init, SHA2Update, and SHA2Final.
40*eda14cbcSMatt Macy  * - a modlcrypto that allows the module to register with the Kernel
41*eda14cbcSMatt Macy  *   Cryptographic Framework (KCF) as a software provider for the SHA2
42*eda14cbcSMatt Macy  *   mechanisms.
43*eda14cbcSMatt Macy  */
44*eda14cbcSMatt Macy 
45*eda14cbcSMatt Macy static struct modlcrypto modlcrypto = {
46*eda14cbcSMatt Macy 	&mod_cryptoops,
47*eda14cbcSMatt Macy 	"SHA2 Kernel SW Provider"
48*eda14cbcSMatt Macy };
49*eda14cbcSMatt Macy 
50*eda14cbcSMatt Macy static struct modlinkage modlinkage = {
51*eda14cbcSMatt Macy 	MODREV_1, {&modlcrypto, NULL}
52*eda14cbcSMatt Macy };
53*eda14cbcSMatt Macy 
54*eda14cbcSMatt Macy /*
55*eda14cbcSMatt Macy  * Macros to access the SHA2 or SHA2-HMAC contexts from a context passed
56*eda14cbcSMatt Macy  * by KCF to one of the entry points.
57*eda14cbcSMatt Macy  */
58*eda14cbcSMatt Macy 
59*eda14cbcSMatt Macy #define	PROV_SHA2_CTX(ctx)	((sha2_ctx_t *)(ctx)->cc_provider_private)
60*eda14cbcSMatt Macy #define	PROV_SHA2_HMAC_CTX(ctx)	((sha2_hmac_ctx_t *)(ctx)->cc_provider_private)
61*eda14cbcSMatt Macy 
62*eda14cbcSMatt Macy /* to extract the digest length passed as mechanism parameter */
63*eda14cbcSMatt Macy #define	PROV_SHA2_GET_DIGEST_LEN(m, len) {				\
64*eda14cbcSMatt Macy 	if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t)))		\
65*eda14cbcSMatt Macy 		(len) = (uint32_t)*((ulong_t *)(m)->cm_param);	\
66*eda14cbcSMatt Macy 	else {								\
67*eda14cbcSMatt Macy 		ulong_t tmp_ulong;					\
68*eda14cbcSMatt Macy 		bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t));	\
69*eda14cbcSMatt Macy 		(len) = (uint32_t)tmp_ulong;				\
70*eda14cbcSMatt Macy 	}								\
71*eda14cbcSMatt Macy }
72*eda14cbcSMatt Macy 
73*eda14cbcSMatt Macy #define	PROV_SHA2_DIGEST_KEY(mech, ctx, key, len, digest) {	\
74*eda14cbcSMatt Macy 	SHA2Init(mech, ctx);				\
75*eda14cbcSMatt Macy 	SHA2Update(ctx, key, len);			\
76*eda14cbcSMatt Macy 	SHA2Final(digest, ctx);				\
77*eda14cbcSMatt Macy }
78*eda14cbcSMatt Macy 
79*eda14cbcSMatt Macy /*
80*eda14cbcSMatt Macy  * Mechanism info structure passed to KCF during registration.
81*eda14cbcSMatt Macy  */
82*eda14cbcSMatt Macy static crypto_mech_info_t sha2_mech_info_tab[] = {
83*eda14cbcSMatt Macy 	/* SHA256 */
84*eda14cbcSMatt Macy 	{SUN_CKM_SHA256, SHA256_MECH_INFO_TYPE,
85*eda14cbcSMatt Macy 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
86*eda14cbcSMatt Macy 	    0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
87*eda14cbcSMatt Macy 	/* SHA256-HMAC */
88*eda14cbcSMatt Macy 	{SUN_CKM_SHA256_HMAC, SHA256_HMAC_MECH_INFO_TYPE,
89*eda14cbcSMatt Macy 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
90*eda14cbcSMatt Macy 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
91*eda14cbcSMatt Macy 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
92*eda14cbcSMatt Macy 	/* SHA256-HMAC GENERAL */
93*eda14cbcSMatt Macy 	{SUN_CKM_SHA256_HMAC_GENERAL, SHA256_HMAC_GEN_MECH_INFO_TYPE,
94*eda14cbcSMatt Macy 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
95*eda14cbcSMatt Macy 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
96*eda14cbcSMatt Macy 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
97*eda14cbcSMatt Macy 	/* SHA384 */
98*eda14cbcSMatt Macy 	{SUN_CKM_SHA384, SHA384_MECH_INFO_TYPE,
99*eda14cbcSMatt Macy 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
100*eda14cbcSMatt Macy 	    0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
101*eda14cbcSMatt Macy 	/* SHA384-HMAC */
102*eda14cbcSMatt Macy 	{SUN_CKM_SHA384_HMAC, SHA384_HMAC_MECH_INFO_TYPE,
103*eda14cbcSMatt Macy 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
104*eda14cbcSMatt Macy 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
105*eda14cbcSMatt Macy 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
106*eda14cbcSMatt Macy 	/* SHA384-HMAC GENERAL */
107*eda14cbcSMatt Macy 	{SUN_CKM_SHA384_HMAC_GENERAL, SHA384_HMAC_GEN_MECH_INFO_TYPE,
108*eda14cbcSMatt Macy 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
109*eda14cbcSMatt Macy 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
110*eda14cbcSMatt Macy 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
111*eda14cbcSMatt Macy 	/* SHA512 */
112*eda14cbcSMatt Macy 	{SUN_CKM_SHA512, SHA512_MECH_INFO_TYPE,
113*eda14cbcSMatt Macy 	    CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
114*eda14cbcSMatt Macy 	    0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
115*eda14cbcSMatt Macy 	/* SHA512-HMAC */
116*eda14cbcSMatt Macy 	{SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE,
117*eda14cbcSMatt Macy 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
118*eda14cbcSMatt Macy 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
119*eda14cbcSMatt Macy 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES},
120*eda14cbcSMatt Macy 	/* SHA512-HMAC GENERAL */
121*eda14cbcSMatt Macy 	{SUN_CKM_SHA512_HMAC_GENERAL, SHA512_HMAC_GEN_MECH_INFO_TYPE,
122*eda14cbcSMatt Macy 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
123*eda14cbcSMatt Macy 	    SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
124*eda14cbcSMatt Macy 	    CRYPTO_KEYSIZE_UNIT_IN_BYTES}
125*eda14cbcSMatt Macy };
126*eda14cbcSMatt Macy 
127*eda14cbcSMatt Macy static void sha2_provider_status(crypto_provider_handle_t, uint_t *);
128*eda14cbcSMatt Macy 
129*eda14cbcSMatt Macy static crypto_control_ops_t sha2_control_ops = {
130*eda14cbcSMatt Macy 	sha2_provider_status
131*eda14cbcSMatt Macy };
132*eda14cbcSMatt Macy 
133*eda14cbcSMatt Macy static int sha2_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
134*eda14cbcSMatt Macy     crypto_req_handle_t);
135*eda14cbcSMatt Macy static int sha2_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
136*eda14cbcSMatt Macy     crypto_req_handle_t);
137*eda14cbcSMatt Macy static int sha2_digest_update(crypto_ctx_t *, crypto_data_t *,
138*eda14cbcSMatt Macy     crypto_req_handle_t);
139*eda14cbcSMatt Macy static int sha2_digest_final(crypto_ctx_t *, crypto_data_t *,
140*eda14cbcSMatt Macy     crypto_req_handle_t);
141*eda14cbcSMatt Macy static int sha2_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
142*eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
143*eda14cbcSMatt Macy     crypto_req_handle_t);
144*eda14cbcSMatt Macy 
145*eda14cbcSMatt Macy static crypto_digest_ops_t sha2_digest_ops = {
146*eda14cbcSMatt Macy 	.digest_init = sha2_digest_init,
147*eda14cbcSMatt Macy 	.digest = sha2_digest,
148*eda14cbcSMatt Macy 	.digest_update = sha2_digest_update,
149*eda14cbcSMatt Macy 	.digest_key = NULL,
150*eda14cbcSMatt Macy 	.digest_final = sha2_digest_final,
151*eda14cbcSMatt Macy 	.digest_atomic = sha2_digest_atomic
152*eda14cbcSMatt Macy };
153*eda14cbcSMatt Macy 
154*eda14cbcSMatt Macy static int sha2_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
155*eda14cbcSMatt Macy     crypto_spi_ctx_template_t, crypto_req_handle_t);
156*eda14cbcSMatt Macy static int sha2_mac_update(crypto_ctx_t *, crypto_data_t *,
157*eda14cbcSMatt Macy     crypto_req_handle_t);
158*eda14cbcSMatt Macy static int sha2_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
159*eda14cbcSMatt Macy static int sha2_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
160*eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
161*eda14cbcSMatt Macy     crypto_spi_ctx_template_t, crypto_req_handle_t);
162*eda14cbcSMatt Macy static int sha2_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
163*eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
164*eda14cbcSMatt Macy     crypto_spi_ctx_template_t, crypto_req_handle_t);
165*eda14cbcSMatt Macy 
166*eda14cbcSMatt Macy static crypto_mac_ops_t sha2_mac_ops = {
167*eda14cbcSMatt Macy 	.mac_init = sha2_mac_init,
168*eda14cbcSMatt Macy 	.mac = NULL,
169*eda14cbcSMatt Macy 	.mac_update = sha2_mac_update,
170*eda14cbcSMatt Macy 	.mac_final = sha2_mac_final,
171*eda14cbcSMatt Macy 	.mac_atomic = sha2_mac_atomic,
172*eda14cbcSMatt Macy 	.mac_verify_atomic = sha2_mac_verify_atomic
173*eda14cbcSMatt Macy };
174*eda14cbcSMatt Macy 
175*eda14cbcSMatt Macy static int sha2_create_ctx_template(crypto_provider_handle_t,
176*eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
177*eda14cbcSMatt Macy     size_t *, crypto_req_handle_t);
178*eda14cbcSMatt Macy static int sha2_free_context(crypto_ctx_t *);
179*eda14cbcSMatt Macy 
180*eda14cbcSMatt Macy static crypto_ctx_ops_t sha2_ctx_ops = {
181*eda14cbcSMatt Macy 	.create_ctx_template = sha2_create_ctx_template,
182*eda14cbcSMatt Macy 	.free_context = sha2_free_context
183*eda14cbcSMatt Macy };
184*eda14cbcSMatt Macy 
185*eda14cbcSMatt Macy static crypto_ops_t sha2_crypto_ops = {{{{{
186*eda14cbcSMatt Macy 	&sha2_control_ops,
187*eda14cbcSMatt Macy 	&sha2_digest_ops,
188*eda14cbcSMatt Macy 	NULL,
189*eda14cbcSMatt Macy 	&sha2_mac_ops,
190*eda14cbcSMatt Macy 	NULL,
191*eda14cbcSMatt Macy 	NULL,
192*eda14cbcSMatt Macy 	NULL,
193*eda14cbcSMatt Macy 	NULL,
194*eda14cbcSMatt Macy 	NULL,
195*eda14cbcSMatt Macy 	NULL,
196*eda14cbcSMatt Macy 	NULL,
197*eda14cbcSMatt Macy 	NULL,
198*eda14cbcSMatt Macy 	NULL,
199*eda14cbcSMatt Macy 	&sha2_ctx_ops
200*eda14cbcSMatt Macy }}}}};
201*eda14cbcSMatt Macy 
202*eda14cbcSMatt Macy static crypto_provider_info_t sha2_prov_info = {{{{
203*eda14cbcSMatt Macy 	CRYPTO_SPI_VERSION_1,
204*eda14cbcSMatt Macy 	"SHA2 Software Provider",
205*eda14cbcSMatt Macy 	CRYPTO_SW_PROVIDER,
206*eda14cbcSMatt Macy 	NULL,
207*eda14cbcSMatt Macy 	&sha2_crypto_ops,
208*eda14cbcSMatt Macy 	sizeof (sha2_mech_info_tab)/sizeof (crypto_mech_info_t),
209*eda14cbcSMatt Macy 	sha2_mech_info_tab
210*eda14cbcSMatt Macy }}}};
211*eda14cbcSMatt Macy 
212*eda14cbcSMatt Macy static crypto_kcf_provider_handle_t sha2_prov_handle = 0;
213*eda14cbcSMatt Macy 
214*eda14cbcSMatt Macy int
215*eda14cbcSMatt Macy sha2_mod_init(void)
216*eda14cbcSMatt Macy {
217*eda14cbcSMatt Macy 	int ret;
218*eda14cbcSMatt Macy 
219*eda14cbcSMatt Macy 	if ((ret = mod_install(&modlinkage)) != 0)
220*eda14cbcSMatt Macy 		return (ret);
221*eda14cbcSMatt Macy 
222*eda14cbcSMatt Macy 	/*
223*eda14cbcSMatt Macy 	 * Register with KCF. If the registration fails, log an
224*eda14cbcSMatt Macy 	 * error but do not uninstall the module, since the functionality
225*eda14cbcSMatt Macy 	 * provided by misc/sha2 should still be available.
226*eda14cbcSMatt Macy 	 */
227*eda14cbcSMatt Macy 	if ((ret = crypto_register_provider(&sha2_prov_info,
228*eda14cbcSMatt Macy 	    &sha2_prov_handle)) != CRYPTO_SUCCESS)
229*eda14cbcSMatt Macy 		cmn_err(CE_WARN, "sha2 _init: "
230*eda14cbcSMatt Macy 		    "crypto_register_provider() failed (0x%x)", ret);
231*eda14cbcSMatt Macy 
232*eda14cbcSMatt Macy 	return (0);
233*eda14cbcSMatt Macy }
234*eda14cbcSMatt Macy 
235*eda14cbcSMatt Macy int
236*eda14cbcSMatt Macy sha2_mod_fini(void)
237*eda14cbcSMatt Macy {
238*eda14cbcSMatt Macy 	int ret;
239*eda14cbcSMatt Macy 
240*eda14cbcSMatt Macy 	if (sha2_prov_handle != 0) {
241*eda14cbcSMatt Macy 		if ((ret = crypto_unregister_provider(sha2_prov_handle)) !=
242*eda14cbcSMatt Macy 		    CRYPTO_SUCCESS) {
243*eda14cbcSMatt Macy 			cmn_err(CE_WARN,
244*eda14cbcSMatt Macy 			    "sha2 _fini: crypto_unregister_provider() "
245*eda14cbcSMatt Macy 			    "failed (0x%x)", ret);
246*eda14cbcSMatt Macy 			return (EBUSY);
247*eda14cbcSMatt Macy 		}
248*eda14cbcSMatt Macy 		sha2_prov_handle = 0;
249*eda14cbcSMatt Macy 	}
250*eda14cbcSMatt Macy 
251*eda14cbcSMatt Macy 	return (mod_remove(&modlinkage));
252*eda14cbcSMatt Macy }
253*eda14cbcSMatt Macy 
254*eda14cbcSMatt Macy /*
255*eda14cbcSMatt Macy  * KCF software provider control entry points.
256*eda14cbcSMatt Macy  */
257*eda14cbcSMatt Macy /* ARGSUSED */
258*eda14cbcSMatt Macy static void
259*eda14cbcSMatt Macy sha2_provider_status(crypto_provider_handle_t provider, uint_t *status)
260*eda14cbcSMatt Macy {
261*eda14cbcSMatt Macy 	*status = CRYPTO_PROVIDER_READY;
262*eda14cbcSMatt Macy }
263*eda14cbcSMatt Macy 
264*eda14cbcSMatt Macy /*
265*eda14cbcSMatt Macy  * KCF software provider digest entry points.
266*eda14cbcSMatt Macy  */
267*eda14cbcSMatt Macy 
268*eda14cbcSMatt Macy static int
269*eda14cbcSMatt Macy sha2_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
270*eda14cbcSMatt Macy     crypto_req_handle_t req)
271*eda14cbcSMatt Macy {
272*eda14cbcSMatt Macy 
273*eda14cbcSMatt Macy 	/*
274*eda14cbcSMatt Macy 	 * Allocate and initialize SHA2 context.
275*eda14cbcSMatt Macy 	 */
276*eda14cbcSMatt Macy 	ctx->cc_provider_private = kmem_alloc(sizeof (sha2_ctx_t),
277*eda14cbcSMatt Macy 	    crypto_kmflag(req));
278*eda14cbcSMatt Macy 	if (ctx->cc_provider_private == NULL)
279*eda14cbcSMatt Macy 		return (CRYPTO_HOST_MEMORY);
280*eda14cbcSMatt Macy 
281*eda14cbcSMatt Macy 	PROV_SHA2_CTX(ctx)->sc_mech_type = mechanism->cm_type;
282*eda14cbcSMatt Macy 	SHA2Init(mechanism->cm_type, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx);
283*eda14cbcSMatt Macy 
284*eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
285*eda14cbcSMatt Macy }
286*eda14cbcSMatt Macy 
287*eda14cbcSMatt Macy /*
288*eda14cbcSMatt Macy  * Helper SHA2 digest update function for uio data.
289*eda14cbcSMatt Macy  */
290*eda14cbcSMatt Macy static int
291*eda14cbcSMatt Macy sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data)
292*eda14cbcSMatt Macy {
293*eda14cbcSMatt Macy 	off_t offset = data->cd_offset;
294*eda14cbcSMatt Macy 	size_t length = data->cd_length;
295*eda14cbcSMatt Macy 	uint_t vec_idx = 0;
296*eda14cbcSMatt Macy 	size_t cur_len;
297*eda14cbcSMatt Macy 
298*eda14cbcSMatt Macy 	/* we support only kernel buffer */
299*eda14cbcSMatt Macy 	if (uio_segflg(data->cd_uio) != UIO_SYSSPACE)
300*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
301*eda14cbcSMatt Macy 
302*eda14cbcSMatt Macy 	/*
303*eda14cbcSMatt Macy 	 * Jump to the first iovec containing data to be
304*eda14cbcSMatt Macy 	 * digested.
305*eda14cbcSMatt Macy 	 */
306*eda14cbcSMatt Macy 	offset = uio_index_at_offset(data->cd_uio, offset, &vec_idx);
307*eda14cbcSMatt Macy 	if (vec_idx == uio_iovcnt(data->cd_uio)) {
308*eda14cbcSMatt Macy 		/*
309*eda14cbcSMatt Macy 		 * The caller specified an offset that is larger than the
310*eda14cbcSMatt Macy 		 * total size of the buffers it provided.
311*eda14cbcSMatt Macy 		 */
312*eda14cbcSMatt Macy 		return (CRYPTO_DATA_LEN_RANGE);
313*eda14cbcSMatt Macy 	}
314*eda14cbcSMatt Macy 
315*eda14cbcSMatt Macy 	/*
316*eda14cbcSMatt Macy 	 * Now do the digesting on the iovecs.
317*eda14cbcSMatt Macy 	 */
318*eda14cbcSMatt Macy 	while (vec_idx < uio_iovcnt(data->cd_uio) && length > 0) {
319*eda14cbcSMatt Macy 		cur_len = MIN(uio_iovlen(data->cd_uio, vec_idx) -
320*eda14cbcSMatt Macy 		    offset, length);
321*eda14cbcSMatt Macy 
322*eda14cbcSMatt Macy 		SHA2Update(sha2_ctx, (uint8_t *)uio_iovbase(data->cd_uio,
323*eda14cbcSMatt Macy 		    vec_idx) + offset, cur_len);
324*eda14cbcSMatt Macy 		length -= cur_len;
325*eda14cbcSMatt Macy 		vec_idx++;
326*eda14cbcSMatt Macy 		offset = 0;
327*eda14cbcSMatt Macy 	}
328*eda14cbcSMatt Macy 
329*eda14cbcSMatt Macy 	if (vec_idx == uio_iovcnt(data->cd_uio) && length > 0) {
330*eda14cbcSMatt Macy 		/*
331*eda14cbcSMatt Macy 		 * The end of the specified iovec's was reached but
332*eda14cbcSMatt Macy 		 * the length requested could not be processed, i.e.
333*eda14cbcSMatt Macy 		 * The caller requested to digest more data than it provided.
334*eda14cbcSMatt Macy 		 */
335*eda14cbcSMatt Macy 		return (CRYPTO_DATA_LEN_RANGE);
336*eda14cbcSMatt Macy 	}
337*eda14cbcSMatt Macy 
338*eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
339*eda14cbcSMatt Macy }
340*eda14cbcSMatt Macy 
341*eda14cbcSMatt Macy /*
342*eda14cbcSMatt Macy  * Helper SHA2 digest final function for uio data.
343*eda14cbcSMatt Macy  * digest_len is the length of the desired digest. If digest_len
344*eda14cbcSMatt Macy  * is smaller than the default SHA2 digest length, the caller
345*eda14cbcSMatt Macy  * must pass a scratch buffer, digest_scratch, which must
346*eda14cbcSMatt Macy  * be at least the algorithm's digest length bytes.
347*eda14cbcSMatt Macy  */
348*eda14cbcSMatt Macy static int
349*eda14cbcSMatt Macy sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest,
350*eda14cbcSMatt Macy     ulong_t digest_len, uchar_t *digest_scratch)
351*eda14cbcSMatt Macy {
352*eda14cbcSMatt Macy 	off_t offset = digest->cd_offset;
353*eda14cbcSMatt Macy 	uint_t vec_idx = 0;
354*eda14cbcSMatt Macy 
355*eda14cbcSMatt Macy 	/* we support only kernel buffer */
356*eda14cbcSMatt Macy 	if (uio_segflg(digest->cd_uio) != UIO_SYSSPACE)
357*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
358*eda14cbcSMatt Macy 
359*eda14cbcSMatt Macy 	/*
360*eda14cbcSMatt Macy 	 * Jump to the first iovec containing ptr to the digest to
361*eda14cbcSMatt Macy 	 * be returned.
362*eda14cbcSMatt Macy 	 */
363*eda14cbcSMatt Macy 	offset = uio_index_at_offset(digest->cd_uio, offset, &vec_idx);
364*eda14cbcSMatt Macy 	if (vec_idx == uio_iovcnt(digest->cd_uio)) {
365*eda14cbcSMatt Macy 		/*
366*eda14cbcSMatt Macy 		 * The caller specified an offset that is
367*eda14cbcSMatt Macy 		 * larger than the total size of the buffers
368*eda14cbcSMatt Macy 		 * it provided.
369*eda14cbcSMatt Macy 		 */
370*eda14cbcSMatt Macy 		return (CRYPTO_DATA_LEN_RANGE);
371*eda14cbcSMatt Macy 	}
372*eda14cbcSMatt Macy 
373*eda14cbcSMatt Macy 	if (offset + digest_len <=
374*eda14cbcSMatt Macy 	    uio_iovlen(digest->cd_uio, vec_idx)) {
375*eda14cbcSMatt Macy 		/*
376*eda14cbcSMatt Macy 		 * The computed SHA2 digest will fit in the current
377*eda14cbcSMatt Macy 		 * iovec.
378*eda14cbcSMatt Macy 		 */
379*eda14cbcSMatt Macy 		if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) &&
380*eda14cbcSMatt Macy 		    (digest_len != SHA256_DIGEST_LENGTH)) ||
381*eda14cbcSMatt Macy 		    ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) &&
382*eda14cbcSMatt Macy 		    (digest_len != SHA512_DIGEST_LENGTH))) {
383*eda14cbcSMatt Macy 			/*
384*eda14cbcSMatt Macy 			 * The caller requested a short digest. Digest
385*eda14cbcSMatt Macy 			 * into a scratch buffer and return to
386*eda14cbcSMatt Macy 			 * the user only what was requested.
387*eda14cbcSMatt Macy 			 */
388*eda14cbcSMatt Macy 			SHA2Final(digest_scratch, sha2_ctx);
389*eda14cbcSMatt Macy 
390*eda14cbcSMatt Macy 			bcopy(digest_scratch, (uchar_t *)uio_iovbase(digest->
391*eda14cbcSMatt Macy 			    cd_uio, vec_idx) + offset,
392*eda14cbcSMatt Macy 			    digest_len);
393*eda14cbcSMatt Macy 		} else {
394*eda14cbcSMatt Macy 			SHA2Final((uchar_t *)uio_iovbase(digest->
395*eda14cbcSMatt Macy 			    cd_uio, vec_idx) + offset,
396*eda14cbcSMatt Macy 			    sha2_ctx);
397*eda14cbcSMatt Macy 
398*eda14cbcSMatt Macy 		}
399*eda14cbcSMatt Macy 	} else {
400*eda14cbcSMatt Macy 		/*
401*eda14cbcSMatt Macy 		 * The computed digest will be crossing one or more iovec's.
402*eda14cbcSMatt Macy 		 * This is bad performance-wise but we need to support it.
403*eda14cbcSMatt Macy 		 * Allocate a small scratch buffer on the stack and
404*eda14cbcSMatt Macy 		 * copy it piece meal to the specified digest iovec's.
405*eda14cbcSMatt Macy 		 */
406*eda14cbcSMatt Macy 		uchar_t digest_tmp[SHA512_DIGEST_LENGTH];
407*eda14cbcSMatt Macy 		off_t scratch_offset = 0;
408*eda14cbcSMatt Macy 		size_t length = digest_len;
409*eda14cbcSMatt Macy 		size_t cur_len;
410*eda14cbcSMatt Macy 
411*eda14cbcSMatt Macy 		SHA2Final(digest_tmp, sha2_ctx);
412*eda14cbcSMatt Macy 
413*eda14cbcSMatt Macy 		while (vec_idx < uio_iovcnt(digest->cd_uio) && length > 0) {
414*eda14cbcSMatt Macy 			cur_len =
415*eda14cbcSMatt Macy 			    MIN(uio_iovlen(digest->cd_uio, vec_idx) -
416*eda14cbcSMatt Macy 			    offset, length);
417*eda14cbcSMatt Macy 			bcopy(digest_tmp + scratch_offset,
418*eda14cbcSMatt Macy 			    uio_iovbase(digest->cd_uio, vec_idx) + offset,
419*eda14cbcSMatt Macy 			    cur_len);
420*eda14cbcSMatt Macy 
421*eda14cbcSMatt Macy 			length -= cur_len;
422*eda14cbcSMatt Macy 			vec_idx++;
423*eda14cbcSMatt Macy 			scratch_offset += cur_len;
424*eda14cbcSMatt Macy 			offset = 0;
425*eda14cbcSMatt Macy 		}
426*eda14cbcSMatt Macy 
427*eda14cbcSMatt Macy 		if (vec_idx == uio_iovcnt(digest->cd_uio) && length > 0) {
428*eda14cbcSMatt Macy 			/*
429*eda14cbcSMatt Macy 			 * The end of the specified iovec's was reached but
430*eda14cbcSMatt Macy 			 * the length requested could not be processed, i.e.
431*eda14cbcSMatt Macy 			 * The caller requested to digest more data than it
432*eda14cbcSMatt Macy 			 * provided.
433*eda14cbcSMatt Macy 			 */
434*eda14cbcSMatt Macy 			return (CRYPTO_DATA_LEN_RANGE);
435*eda14cbcSMatt Macy 		}
436*eda14cbcSMatt Macy 	}
437*eda14cbcSMatt Macy 
438*eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
439*eda14cbcSMatt Macy }
440*eda14cbcSMatt Macy 
441*eda14cbcSMatt Macy /* ARGSUSED */
442*eda14cbcSMatt Macy static int
443*eda14cbcSMatt Macy sha2_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
444*eda14cbcSMatt Macy     crypto_req_handle_t req)
445*eda14cbcSMatt Macy {
446*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
447*eda14cbcSMatt Macy 	uint_t sha_digest_len;
448*eda14cbcSMatt Macy 
449*eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
450*eda14cbcSMatt Macy 
451*eda14cbcSMatt Macy 	switch (PROV_SHA2_CTX(ctx)->sc_mech_type) {
452*eda14cbcSMatt Macy 	case SHA256_MECH_INFO_TYPE:
453*eda14cbcSMatt Macy 		sha_digest_len = SHA256_DIGEST_LENGTH;
454*eda14cbcSMatt Macy 		break;
455*eda14cbcSMatt Macy 	case SHA384_MECH_INFO_TYPE:
456*eda14cbcSMatt Macy 		sha_digest_len = SHA384_DIGEST_LENGTH;
457*eda14cbcSMatt Macy 		break;
458*eda14cbcSMatt Macy 	case SHA512_MECH_INFO_TYPE:
459*eda14cbcSMatt Macy 		sha_digest_len = SHA512_DIGEST_LENGTH;
460*eda14cbcSMatt Macy 		break;
461*eda14cbcSMatt Macy 	default:
462*eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
463*eda14cbcSMatt Macy 	}
464*eda14cbcSMatt Macy 
465*eda14cbcSMatt Macy 	/*
466*eda14cbcSMatt Macy 	 * We need to just return the length needed to store the output.
467*eda14cbcSMatt Macy 	 * We should not destroy the context for the following cases.
468*eda14cbcSMatt Macy 	 */
469*eda14cbcSMatt Macy 	if ((digest->cd_length == 0) ||
470*eda14cbcSMatt Macy 	    (digest->cd_length < sha_digest_len)) {
471*eda14cbcSMatt Macy 		digest->cd_length = sha_digest_len;
472*eda14cbcSMatt Macy 		return (CRYPTO_BUFFER_TOO_SMALL);
473*eda14cbcSMatt Macy 	}
474*eda14cbcSMatt Macy 
475*eda14cbcSMatt Macy 	/*
476*eda14cbcSMatt Macy 	 * Do the SHA2 update on the specified input data.
477*eda14cbcSMatt Macy 	 */
478*eda14cbcSMatt Macy 	switch (data->cd_format) {
479*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
480*eda14cbcSMatt Macy 		SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
481*eda14cbcSMatt Macy 		    (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
482*eda14cbcSMatt Macy 		    data->cd_length);
483*eda14cbcSMatt Macy 		break;
484*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
485*eda14cbcSMatt Macy 		ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
486*eda14cbcSMatt Macy 		    data);
487*eda14cbcSMatt Macy 		break;
488*eda14cbcSMatt Macy 	default:
489*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
490*eda14cbcSMatt Macy 	}
491*eda14cbcSMatt Macy 
492*eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS) {
493*eda14cbcSMatt Macy 		/* the update failed, free context and bail */
494*eda14cbcSMatt Macy 		kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t));
495*eda14cbcSMatt Macy 		ctx->cc_provider_private = NULL;
496*eda14cbcSMatt Macy 		digest->cd_length = 0;
497*eda14cbcSMatt Macy 		return (ret);
498*eda14cbcSMatt Macy 	}
499*eda14cbcSMatt Macy 
500*eda14cbcSMatt Macy 	/*
501*eda14cbcSMatt Macy 	 * Do a SHA2 final, must be done separately since the digest
502*eda14cbcSMatt Macy 	 * type can be different than the input data type.
503*eda14cbcSMatt Macy 	 */
504*eda14cbcSMatt Macy 	switch (digest->cd_format) {
505*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
506*eda14cbcSMatt Macy 		SHA2Final((unsigned char *)digest->cd_raw.iov_base +
507*eda14cbcSMatt Macy 		    digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx);
508*eda14cbcSMatt Macy 		break;
509*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
510*eda14cbcSMatt Macy 		ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
511*eda14cbcSMatt Macy 		    digest, sha_digest_len, NULL);
512*eda14cbcSMatt Macy 		break;
513*eda14cbcSMatt Macy 	default:
514*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
515*eda14cbcSMatt Macy 	}
516*eda14cbcSMatt Macy 
517*eda14cbcSMatt Macy 	/* all done, free context and return */
518*eda14cbcSMatt Macy 
519*eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS)
520*eda14cbcSMatt Macy 		digest->cd_length = sha_digest_len;
521*eda14cbcSMatt Macy 	else
522*eda14cbcSMatt Macy 		digest->cd_length = 0;
523*eda14cbcSMatt Macy 
524*eda14cbcSMatt Macy 	kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t));
525*eda14cbcSMatt Macy 	ctx->cc_provider_private = NULL;
526*eda14cbcSMatt Macy 	return (ret);
527*eda14cbcSMatt Macy }
528*eda14cbcSMatt Macy 
529*eda14cbcSMatt Macy /* ARGSUSED */
530*eda14cbcSMatt Macy static int
531*eda14cbcSMatt Macy sha2_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
532*eda14cbcSMatt Macy     crypto_req_handle_t req)
533*eda14cbcSMatt Macy {
534*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
535*eda14cbcSMatt Macy 
536*eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
537*eda14cbcSMatt Macy 
538*eda14cbcSMatt Macy 	/*
539*eda14cbcSMatt Macy 	 * Do the SHA2 update on the specified input data.
540*eda14cbcSMatt Macy 	 */
541*eda14cbcSMatt Macy 	switch (data->cd_format) {
542*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
543*eda14cbcSMatt Macy 		SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
544*eda14cbcSMatt Macy 		    (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
545*eda14cbcSMatt Macy 		    data->cd_length);
546*eda14cbcSMatt Macy 		break;
547*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
548*eda14cbcSMatt Macy 		ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
549*eda14cbcSMatt Macy 		    data);
550*eda14cbcSMatt Macy 		break;
551*eda14cbcSMatt Macy 	default:
552*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
553*eda14cbcSMatt Macy 	}
554*eda14cbcSMatt Macy 
555*eda14cbcSMatt Macy 	return (ret);
556*eda14cbcSMatt Macy }
557*eda14cbcSMatt Macy 
558*eda14cbcSMatt Macy /* ARGSUSED */
559*eda14cbcSMatt Macy static int
560*eda14cbcSMatt Macy sha2_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
561*eda14cbcSMatt Macy     crypto_req_handle_t req)
562*eda14cbcSMatt Macy {
563*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
564*eda14cbcSMatt Macy 	uint_t sha_digest_len;
565*eda14cbcSMatt Macy 
566*eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
567*eda14cbcSMatt Macy 
568*eda14cbcSMatt Macy 	switch (PROV_SHA2_CTX(ctx)->sc_mech_type) {
569*eda14cbcSMatt Macy 	case SHA256_MECH_INFO_TYPE:
570*eda14cbcSMatt Macy 		sha_digest_len = SHA256_DIGEST_LENGTH;
571*eda14cbcSMatt Macy 		break;
572*eda14cbcSMatt Macy 	case SHA384_MECH_INFO_TYPE:
573*eda14cbcSMatt Macy 		sha_digest_len = SHA384_DIGEST_LENGTH;
574*eda14cbcSMatt Macy 		break;
575*eda14cbcSMatt Macy 	case SHA512_MECH_INFO_TYPE:
576*eda14cbcSMatt Macy 		sha_digest_len = SHA512_DIGEST_LENGTH;
577*eda14cbcSMatt Macy 		break;
578*eda14cbcSMatt Macy 	default:
579*eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
580*eda14cbcSMatt Macy 	}
581*eda14cbcSMatt Macy 
582*eda14cbcSMatt Macy 	/*
583*eda14cbcSMatt Macy 	 * We need to just return the length needed to store the output.
584*eda14cbcSMatt Macy 	 * We should not destroy the context for the following cases.
585*eda14cbcSMatt Macy 	 */
586*eda14cbcSMatt Macy 	if ((digest->cd_length == 0) ||
587*eda14cbcSMatt Macy 	    (digest->cd_length < sha_digest_len)) {
588*eda14cbcSMatt Macy 		digest->cd_length = sha_digest_len;
589*eda14cbcSMatt Macy 		return (CRYPTO_BUFFER_TOO_SMALL);
590*eda14cbcSMatt Macy 	}
591*eda14cbcSMatt Macy 
592*eda14cbcSMatt Macy 	/*
593*eda14cbcSMatt Macy 	 * Do a SHA2 final.
594*eda14cbcSMatt Macy 	 */
595*eda14cbcSMatt Macy 	switch (digest->cd_format) {
596*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
597*eda14cbcSMatt Macy 		SHA2Final((unsigned char *)digest->cd_raw.iov_base +
598*eda14cbcSMatt Macy 		    digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx);
599*eda14cbcSMatt Macy 		break;
600*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
601*eda14cbcSMatt Macy 		ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
602*eda14cbcSMatt Macy 		    digest, sha_digest_len, NULL);
603*eda14cbcSMatt Macy 		break;
604*eda14cbcSMatt Macy 	default:
605*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
606*eda14cbcSMatt Macy 	}
607*eda14cbcSMatt Macy 
608*eda14cbcSMatt Macy 	/* all done, free context and return */
609*eda14cbcSMatt Macy 
610*eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS)
611*eda14cbcSMatt Macy 		digest->cd_length = sha_digest_len;
612*eda14cbcSMatt Macy 	else
613*eda14cbcSMatt Macy 		digest->cd_length = 0;
614*eda14cbcSMatt Macy 
615*eda14cbcSMatt Macy 	kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t));
616*eda14cbcSMatt Macy 	ctx->cc_provider_private = NULL;
617*eda14cbcSMatt Macy 
618*eda14cbcSMatt Macy 	return (ret);
619*eda14cbcSMatt Macy }
620*eda14cbcSMatt Macy 
621*eda14cbcSMatt Macy /* ARGSUSED */
622*eda14cbcSMatt Macy static int
623*eda14cbcSMatt Macy sha2_digest_atomic(crypto_provider_handle_t provider,
624*eda14cbcSMatt Macy     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
625*eda14cbcSMatt Macy     crypto_data_t *data, crypto_data_t *digest,
626*eda14cbcSMatt Macy     crypto_req_handle_t req)
627*eda14cbcSMatt Macy {
628*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
629*eda14cbcSMatt Macy 	SHA2_CTX sha2_ctx;
630*eda14cbcSMatt Macy 	uint32_t sha_digest_len;
631*eda14cbcSMatt Macy 
632*eda14cbcSMatt Macy 	/*
633*eda14cbcSMatt Macy 	 * Do the SHA inits.
634*eda14cbcSMatt Macy 	 */
635*eda14cbcSMatt Macy 
636*eda14cbcSMatt Macy 	SHA2Init(mechanism->cm_type, &sha2_ctx);
637*eda14cbcSMatt Macy 
638*eda14cbcSMatt Macy 	switch (data->cd_format) {
639*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
640*eda14cbcSMatt Macy 		SHA2Update(&sha2_ctx, (uint8_t *)data->
641*eda14cbcSMatt Macy 		    cd_raw.iov_base + data->cd_offset, data->cd_length);
642*eda14cbcSMatt Macy 		break;
643*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
644*eda14cbcSMatt Macy 		ret = sha2_digest_update_uio(&sha2_ctx, data);
645*eda14cbcSMatt Macy 		break;
646*eda14cbcSMatt Macy 	default:
647*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
648*eda14cbcSMatt Macy 	}
649*eda14cbcSMatt Macy 
650*eda14cbcSMatt Macy 	/*
651*eda14cbcSMatt Macy 	 * Do the SHA updates on the specified input data.
652*eda14cbcSMatt Macy 	 */
653*eda14cbcSMatt Macy 
654*eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS) {
655*eda14cbcSMatt Macy 		/* the update failed, bail */
656*eda14cbcSMatt Macy 		digest->cd_length = 0;
657*eda14cbcSMatt Macy 		return (ret);
658*eda14cbcSMatt Macy 	}
659*eda14cbcSMatt Macy 
660*eda14cbcSMatt Macy 	if (mechanism->cm_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE)
661*eda14cbcSMatt Macy 		sha_digest_len = SHA256_DIGEST_LENGTH;
662*eda14cbcSMatt Macy 	else
663*eda14cbcSMatt Macy 		sha_digest_len = SHA512_DIGEST_LENGTH;
664*eda14cbcSMatt Macy 
665*eda14cbcSMatt Macy 	/*
666*eda14cbcSMatt Macy 	 * Do a SHA2 final, must be done separately since the digest
667*eda14cbcSMatt Macy 	 * type can be different than the input data type.
668*eda14cbcSMatt Macy 	 */
669*eda14cbcSMatt Macy 	switch (digest->cd_format) {
670*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
671*eda14cbcSMatt Macy 		SHA2Final((unsigned char *)digest->cd_raw.iov_base +
672*eda14cbcSMatt Macy 		    digest->cd_offset, &sha2_ctx);
673*eda14cbcSMatt Macy 		break;
674*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
675*eda14cbcSMatt Macy 		ret = sha2_digest_final_uio(&sha2_ctx, digest,
676*eda14cbcSMatt Macy 		    sha_digest_len, NULL);
677*eda14cbcSMatt Macy 		break;
678*eda14cbcSMatt Macy 	default:
679*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
680*eda14cbcSMatt Macy 	}
681*eda14cbcSMatt Macy 
682*eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS)
683*eda14cbcSMatt Macy 		digest->cd_length = sha_digest_len;
684*eda14cbcSMatt Macy 	else
685*eda14cbcSMatt Macy 		digest->cd_length = 0;
686*eda14cbcSMatt Macy 
687*eda14cbcSMatt Macy 	return (ret);
688*eda14cbcSMatt Macy }
689*eda14cbcSMatt Macy 
690*eda14cbcSMatt Macy /*
691*eda14cbcSMatt Macy  * KCF software provider mac entry points.
692*eda14cbcSMatt Macy  *
693*eda14cbcSMatt Macy  * SHA2 HMAC is: SHA2(key XOR opad, SHA2(key XOR ipad, text))
694*eda14cbcSMatt Macy  *
695*eda14cbcSMatt Macy  * Init:
696*eda14cbcSMatt Macy  * The initialization routine initializes what we denote
697*eda14cbcSMatt Macy  * as the inner and outer contexts by doing
698*eda14cbcSMatt Macy  * - for inner context: SHA2(key XOR ipad)
699*eda14cbcSMatt Macy  * - for outer context: SHA2(key XOR opad)
700*eda14cbcSMatt Macy  *
701*eda14cbcSMatt Macy  * Update:
702*eda14cbcSMatt Macy  * Each subsequent SHA2 HMAC update will result in an
703*eda14cbcSMatt Macy  * update of the inner context with the specified data.
704*eda14cbcSMatt Macy  *
705*eda14cbcSMatt Macy  * Final:
706*eda14cbcSMatt Macy  * The SHA2 HMAC final will do a SHA2 final operation on the
707*eda14cbcSMatt Macy  * inner context, and the resulting digest will be used
708*eda14cbcSMatt Macy  * as the data for an update on the outer context. Last
709*eda14cbcSMatt Macy  * but not least, a SHA2 final on the outer context will
710*eda14cbcSMatt Macy  * be performed to obtain the SHA2 HMAC digest to return
711*eda14cbcSMatt Macy  * to the user.
712*eda14cbcSMatt Macy  */
713*eda14cbcSMatt Macy 
714*eda14cbcSMatt Macy /*
715*eda14cbcSMatt Macy  * Initialize a SHA2-HMAC context.
716*eda14cbcSMatt Macy  */
717*eda14cbcSMatt Macy static void
718*eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
719*eda14cbcSMatt Macy {
720*eda14cbcSMatt Macy 	uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)];
721*eda14cbcSMatt Macy 	uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)];
722*eda14cbcSMatt Macy 	int i, block_size, blocks_per_int64;
723*eda14cbcSMatt Macy 
724*eda14cbcSMatt Macy 	/* Determine the block size */
725*eda14cbcSMatt Macy 	if (ctx->hc_mech_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
726*eda14cbcSMatt Macy 		block_size = SHA256_HMAC_BLOCK_SIZE;
727*eda14cbcSMatt Macy 		blocks_per_int64 = SHA256_HMAC_BLOCK_SIZE / sizeof (uint64_t);
728*eda14cbcSMatt Macy 	} else {
729*eda14cbcSMatt Macy 		block_size = SHA512_HMAC_BLOCK_SIZE;
730*eda14cbcSMatt Macy 		blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t);
731*eda14cbcSMatt Macy 	}
732*eda14cbcSMatt Macy 
733*eda14cbcSMatt Macy 	(void) bzero(ipad, block_size);
734*eda14cbcSMatt Macy 	(void) bzero(opad, block_size);
735*eda14cbcSMatt Macy 	(void) bcopy(keyval, ipad, length_in_bytes);
736*eda14cbcSMatt Macy 	(void) bcopy(keyval, opad, length_in_bytes);
737*eda14cbcSMatt Macy 
738*eda14cbcSMatt Macy 	/* XOR key with ipad (0x36) and opad (0x5c) */
739*eda14cbcSMatt Macy 	for (i = 0; i < blocks_per_int64; i ++) {
740*eda14cbcSMatt Macy 		ipad[i] ^= 0x3636363636363636;
741*eda14cbcSMatt Macy 		opad[i] ^= 0x5c5c5c5c5c5c5c5c;
742*eda14cbcSMatt Macy 	}
743*eda14cbcSMatt Macy 
744*eda14cbcSMatt Macy 	/* perform SHA2 on ipad */
745*eda14cbcSMatt Macy 	SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext);
746*eda14cbcSMatt Macy 	SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size);
747*eda14cbcSMatt Macy 
748*eda14cbcSMatt Macy 	/* perform SHA2 on opad */
749*eda14cbcSMatt Macy 	SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext);
750*eda14cbcSMatt Macy 	SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size);
751*eda14cbcSMatt Macy 
752*eda14cbcSMatt Macy }
753*eda14cbcSMatt Macy 
754*eda14cbcSMatt Macy /*
755*eda14cbcSMatt Macy  */
756*eda14cbcSMatt Macy static int
757*eda14cbcSMatt Macy sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
758*eda14cbcSMatt Macy     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
759*eda14cbcSMatt Macy     crypto_req_handle_t req)
760*eda14cbcSMatt Macy {
761*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
762*eda14cbcSMatt Macy 	uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
763*eda14cbcSMatt Macy 	uint_t sha_digest_len, sha_hmac_block_size;
764*eda14cbcSMatt Macy 
765*eda14cbcSMatt Macy 	/*
766*eda14cbcSMatt Macy 	 * Set the digest length and block size to values appropriate to the
767*eda14cbcSMatt Macy 	 * mechanism
768*eda14cbcSMatt Macy 	 */
769*eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
770*eda14cbcSMatt Macy 	case SHA256_HMAC_MECH_INFO_TYPE:
771*eda14cbcSMatt Macy 	case SHA256_HMAC_GEN_MECH_INFO_TYPE:
772*eda14cbcSMatt Macy 		sha_digest_len = SHA256_DIGEST_LENGTH;
773*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
774*eda14cbcSMatt Macy 		break;
775*eda14cbcSMatt Macy 	case SHA384_HMAC_MECH_INFO_TYPE:
776*eda14cbcSMatt Macy 	case SHA384_HMAC_GEN_MECH_INFO_TYPE:
777*eda14cbcSMatt Macy 	case SHA512_HMAC_MECH_INFO_TYPE:
778*eda14cbcSMatt Macy 	case SHA512_HMAC_GEN_MECH_INFO_TYPE:
779*eda14cbcSMatt Macy 		sha_digest_len = SHA512_DIGEST_LENGTH;
780*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
781*eda14cbcSMatt Macy 		break;
782*eda14cbcSMatt Macy 	default:
783*eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
784*eda14cbcSMatt Macy 	}
785*eda14cbcSMatt Macy 
786*eda14cbcSMatt Macy 	if (key->ck_format != CRYPTO_KEY_RAW)
787*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
788*eda14cbcSMatt Macy 
789*eda14cbcSMatt Macy 	ctx->cc_provider_private = kmem_alloc(sizeof (sha2_hmac_ctx_t),
790*eda14cbcSMatt Macy 	    crypto_kmflag(req));
791*eda14cbcSMatt Macy 	if (ctx->cc_provider_private == NULL)
792*eda14cbcSMatt Macy 		return (CRYPTO_HOST_MEMORY);
793*eda14cbcSMatt Macy 
794*eda14cbcSMatt Macy 	PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type;
795*eda14cbcSMatt Macy 	if (ctx_template != NULL) {
796*eda14cbcSMatt Macy 		/* reuse context template */
797*eda14cbcSMatt Macy 		bcopy(ctx_template, PROV_SHA2_HMAC_CTX(ctx),
798*eda14cbcSMatt Macy 		    sizeof (sha2_hmac_ctx_t));
799*eda14cbcSMatt Macy 	} else {
800*eda14cbcSMatt Macy 		/* no context template, compute context */
801*eda14cbcSMatt Macy 		if (keylen_in_bytes > sha_hmac_block_size) {
802*eda14cbcSMatt Macy 			uchar_t digested_key[SHA512_DIGEST_LENGTH];
803*eda14cbcSMatt Macy 			sha2_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private;
804*eda14cbcSMatt Macy 
805*eda14cbcSMatt Macy 			/*
806*eda14cbcSMatt Macy 			 * Hash the passed-in key to get a smaller key.
807*eda14cbcSMatt Macy 			 * The inner context is used since it hasn't been
808*eda14cbcSMatt Macy 			 * initialized yet.
809*eda14cbcSMatt Macy 			 */
810*eda14cbcSMatt Macy 			PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
811*eda14cbcSMatt Macy 			    &hmac_ctx->hc_icontext,
812*eda14cbcSMatt Macy 			    key->ck_data, keylen_in_bytes, digested_key);
813*eda14cbcSMatt Macy 			sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx),
814*eda14cbcSMatt Macy 			    digested_key, sha_digest_len);
815*eda14cbcSMatt Macy 		} else {
816*eda14cbcSMatt Macy 			sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx),
817*eda14cbcSMatt Macy 			    key->ck_data, keylen_in_bytes);
818*eda14cbcSMatt Macy 		}
819*eda14cbcSMatt Macy 	}
820*eda14cbcSMatt Macy 
821*eda14cbcSMatt Macy 	/*
822*eda14cbcSMatt Macy 	 * Get the mechanism parameters, if applicable.
823*eda14cbcSMatt Macy 	 */
824*eda14cbcSMatt Macy 	if (mechanism->cm_type % 3 == 2) {
825*eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
826*eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (ulong_t))
827*eda14cbcSMatt Macy 			ret = CRYPTO_MECHANISM_PARAM_INVALID;
828*eda14cbcSMatt Macy 		PROV_SHA2_GET_DIGEST_LEN(mechanism,
829*eda14cbcSMatt Macy 		    PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len);
830*eda14cbcSMatt Macy 		if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > sha_digest_len)
831*eda14cbcSMatt Macy 			ret = CRYPTO_MECHANISM_PARAM_INVALID;
832*eda14cbcSMatt Macy 	}
833*eda14cbcSMatt Macy 
834*eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS) {
835*eda14cbcSMatt Macy 		bzero(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
836*eda14cbcSMatt Macy 		kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
837*eda14cbcSMatt Macy 		ctx->cc_provider_private = NULL;
838*eda14cbcSMatt Macy 	}
839*eda14cbcSMatt Macy 
840*eda14cbcSMatt Macy 	return (ret);
841*eda14cbcSMatt Macy }
842*eda14cbcSMatt Macy 
843*eda14cbcSMatt Macy /* ARGSUSED */
844*eda14cbcSMatt Macy static int
845*eda14cbcSMatt Macy sha2_mac_update(crypto_ctx_t *ctx, crypto_data_t *data,
846*eda14cbcSMatt Macy     crypto_req_handle_t req)
847*eda14cbcSMatt Macy {
848*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
849*eda14cbcSMatt Macy 
850*eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
851*eda14cbcSMatt Macy 
852*eda14cbcSMatt Macy 	/*
853*eda14cbcSMatt Macy 	 * Do a SHA2 update of the inner context using the specified
854*eda14cbcSMatt Macy 	 * data.
855*eda14cbcSMatt Macy 	 */
856*eda14cbcSMatt Macy 	switch (data->cd_format) {
857*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
858*eda14cbcSMatt Macy 		SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_icontext,
859*eda14cbcSMatt Macy 		    (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
860*eda14cbcSMatt Macy 		    data->cd_length);
861*eda14cbcSMatt Macy 		break;
862*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
863*eda14cbcSMatt Macy 		ret = sha2_digest_update_uio(
864*eda14cbcSMatt Macy 		    &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data);
865*eda14cbcSMatt Macy 		break;
866*eda14cbcSMatt Macy 	default:
867*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
868*eda14cbcSMatt Macy 	}
869*eda14cbcSMatt Macy 
870*eda14cbcSMatt Macy 	return (ret);
871*eda14cbcSMatt Macy }
872*eda14cbcSMatt Macy 
873*eda14cbcSMatt Macy /* ARGSUSED */
874*eda14cbcSMatt Macy static int
875*eda14cbcSMatt Macy sha2_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
876*eda14cbcSMatt Macy {
877*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
878*eda14cbcSMatt Macy 	uchar_t digest[SHA512_DIGEST_LENGTH];
879*eda14cbcSMatt Macy 	uint32_t digest_len, sha_digest_len;
880*eda14cbcSMatt Macy 
881*eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
882*eda14cbcSMatt Macy 
883*eda14cbcSMatt Macy 	/* Set the digest lengths to values appropriate to the mechanism */
884*eda14cbcSMatt Macy 	switch (PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type) {
885*eda14cbcSMatt Macy 	case SHA256_HMAC_MECH_INFO_TYPE:
886*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA256_DIGEST_LENGTH;
887*eda14cbcSMatt Macy 		break;
888*eda14cbcSMatt Macy 	case SHA384_HMAC_MECH_INFO_TYPE:
889*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA384_DIGEST_LENGTH;
890*eda14cbcSMatt Macy 		break;
891*eda14cbcSMatt Macy 	case SHA512_HMAC_MECH_INFO_TYPE:
892*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
893*eda14cbcSMatt Macy 		break;
894*eda14cbcSMatt Macy 	case SHA256_HMAC_GEN_MECH_INFO_TYPE:
895*eda14cbcSMatt Macy 		sha_digest_len = SHA256_DIGEST_LENGTH;
896*eda14cbcSMatt Macy 		digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len;
897*eda14cbcSMatt Macy 		break;
898*eda14cbcSMatt Macy 	case SHA384_HMAC_GEN_MECH_INFO_TYPE:
899*eda14cbcSMatt Macy 	case SHA512_HMAC_GEN_MECH_INFO_TYPE:
900*eda14cbcSMatt Macy 		sha_digest_len = SHA512_DIGEST_LENGTH;
901*eda14cbcSMatt Macy 		digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len;
902*eda14cbcSMatt Macy 		break;
903*eda14cbcSMatt Macy 	default:
904*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
905*eda14cbcSMatt Macy 	}
906*eda14cbcSMatt Macy 
907*eda14cbcSMatt Macy 	/*
908*eda14cbcSMatt Macy 	 * We need to just return the length needed to store the output.
909*eda14cbcSMatt Macy 	 * We should not destroy the context for the following cases.
910*eda14cbcSMatt Macy 	 */
911*eda14cbcSMatt Macy 	if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) {
912*eda14cbcSMatt Macy 		mac->cd_length = digest_len;
913*eda14cbcSMatt Macy 		return (CRYPTO_BUFFER_TOO_SMALL);
914*eda14cbcSMatt Macy 	}
915*eda14cbcSMatt Macy 
916*eda14cbcSMatt Macy 	/*
917*eda14cbcSMatt Macy 	 * Do a SHA2 final on the inner context.
918*eda14cbcSMatt Macy 	 */
919*eda14cbcSMatt Macy 	SHA2Final(digest, &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext);
920*eda14cbcSMatt Macy 
921*eda14cbcSMatt Macy 	/*
922*eda14cbcSMatt Macy 	 * Do a SHA2 update on the outer context, feeding the inner
923*eda14cbcSMatt Macy 	 * digest as data.
924*eda14cbcSMatt Macy 	 */
925*eda14cbcSMatt Macy 	SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, digest,
926*eda14cbcSMatt Macy 	    sha_digest_len);
927*eda14cbcSMatt Macy 
928*eda14cbcSMatt Macy 	/*
929*eda14cbcSMatt Macy 	 * Do a SHA2 final on the outer context, storing the computing
930*eda14cbcSMatt Macy 	 * digest in the users buffer.
931*eda14cbcSMatt Macy 	 */
932*eda14cbcSMatt Macy 	switch (mac->cd_format) {
933*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
934*eda14cbcSMatt Macy 		if (digest_len != sha_digest_len) {
935*eda14cbcSMatt Macy 			/*
936*eda14cbcSMatt Macy 			 * The caller requested a short digest. Digest
937*eda14cbcSMatt Macy 			 * into a scratch buffer and return to
938*eda14cbcSMatt Macy 			 * the user only what was requested.
939*eda14cbcSMatt Macy 			 */
940*eda14cbcSMatt Macy 			SHA2Final(digest,
941*eda14cbcSMatt Macy 			    &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext);
942*eda14cbcSMatt Macy 			bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
943*eda14cbcSMatt Macy 			    mac->cd_offset, digest_len);
944*eda14cbcSMatt Macy 		} else {
945*eda14cbcSMatt Macy 			SHA2Final((unsigned char *)mac->cd_raw.iov_base +
946*eda14cbcSMatt Macy 			    mac->cd_offset,
947*eda14cbcSMatt Macy 			    &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext);
948*eda14cbcSMatt Macy 		}
949*eda14cbcSMatt Macy 		break;
950*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
951*eda14cbcSMatt Macy 		ret = sha2_digest_final_uio(
952*eda14cbcSMatt Macy 		    &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac,
953*eda14cbcSMatt Macy 		    digest_len, digest);
954*eda14cbcSMatt Macy 		break;
955*eda14cbcSMatt Macy 	default:
956*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
957*eda14cbcSMatt Macy 	}
958*eda14cbcSMatt Macy 
959*eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS)
960*eda14cbcSMatt Macy 		mac->cd_length = digest_len;
961*eda14cbcSMatt Macy 	else
962*eda14cbcSMatt Macy 		mac->cd_length = 0;
963*eda14cbcSMatt Macy 
964*eda14cbcSMatt Macy 	bzero(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
965*eda14cbcSMatt Macy 	kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
966*eda14cbcSMatt Macy 	ctx->cc_provider_private = NULL;
967*eda14cbcSMatt Macy 
968*eda14cbcSMatt Macy 	return (ret);
969*eda14cbcSMatt Macy }
970*eda14cbcSMatt Macy 
971*eda14cbcSMatt Macy #define	SHA2_MAC_UPDATE(data, ctx, ret) {				\
972*eda14cbcSMatt Macy 	switch (data->cd_format) {					\
973*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:						\
974*eda14cbcSMatt Macy 		SHA2Update(&(ctx).hc_icontext,				\
975*eda14cbcSMatt Macy 		    (uint8_t *)data->cd_raw.iov_base +			\
976*eda14cbcSMatt Macy 		    data->cd_offset, data->cd_length);			\
977*eda14cbcSMatt Macy 		break;							\
978*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:						\
979*eda14cbcSMatt Macy 		ret = sha2_digest_update_uio(&(ctx).hc_icontext, data);	\
980*eda14cbcSMatt Macy 		break;							\
981*eda14cbcSMatt Macy 	default:							\
982*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;				\
983*eda14cbcSMatt Macy 	}								\
984*eda14cbcSMatt Macy }
985*eda14cbcSMatt Macy 
986*eda14cbcSMatt Macy /* ARGSUSED */
987*eda14cbcSMatt Macy static int
988*eda14cbcSMatt Macy sha2_mac_atomic(crypto_provider_handle_t provider,
989*eda14cbcSMatt Macy     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
990*eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
991*eda14cbcSMatt Macy     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
992*eda14cbcSMatt Macy {
993*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
994*eda14cbcSMatt Macy 	uchar_t digest[SHA512_DIGEST_LENGTH];
995*eda14cbcSMatt Macy 	sha2_hmac_ctx_t sha2_hmac_ctx;
996*eda14cbcSMatt Macy 	uint32_t sha_digest_len, digest_len, sha_hmac_block_size;
997*eda14cbcSMatt Macy 	uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
998*eda14cbcSMatt Macy 
999*eda14cbcSMatt Macy 	/*
1000*eda14cbcSMatt Macy 	 * Set the digest length and block size to values appropriate to the
1001*eda14cbcSMatt Macy 	 * mechanism
1002*eda14cbcSMatt Macy 	 */
1003*eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
1004*eda14cbcSMatt Macy 	case SHA256_HMAC_MECH_INFO_TYPE:
1005*eda14cbcSMatt Macy 	case SHA256_HMAC_GEN_MECH_INFO_TYPE:
1006*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA256_DIGEST_LENGTH;
1007*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
1008*eda14cbcSMatt Macy 		break;
1009*eda14cbcSMatt Macy 	case SHA384_HMAC_MECH_INFO_TYPE:
1010*eda14cbcSMatt Macy 	case SHA384_HMAC_GEN_MECH_INFO_TYPE:
1011*eda14cbcSMatt Macy 	case SHA512_HMAC_MECH_INFO_TYPE:
1012*eda14cbcSMatt Macy 	case SHA512_HMAC_GEN_MECH_INFO_TYPE:
1013*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
1014*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
1015*eda14cbcSMatt Macy 		break;
1016*eda14cbcSMatt Macy 	default:
1017*eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
1018*eda14cbcSMatt Macy 	}
1019*eda14cbcSMatt Macy 
1020*eda14cbcSMatt Macy 	/* Add support for key by attributes (RFE 4706552) */
1021*eda14cbcSMatt Macy 	if (key->ck_format != CRYPTO_KEY_RAW)
1022*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
1023*eda14cbcSMatt Macy 
1024*eda14cbcSMatt Macy 	if (ctx_template != NULL) {
1025*eda14cbcSMatt Macy 		/* reuse context template */
1026*eda14cbcSMatt Macy 		bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
1027*eda14cbcSMatt Macy 	} else {
1028*eda14cbcSMatt Macy 		sha2_hmac_ctx.hc_mech_type = mechanism->cm_type;
1029*eda14cbcSMatt Macy 		/* no context template, initialize context */
1030*eda14cbcSMatt Macy 		if (keylen_in_bytes > sha_hmac_block_size) {
1031*eda14cbcSMatt Macy 			/*
1032*eda14cbcSMatt Macy 			 * Hash the passed-in key to get a smaller key.
1033*eda14cbcSMatt Macy 			 * The inner context is used since it hasn't been
1034*eda14cbcSMatt Macy 			 * initialized yet.
1035*eda14cbcSMatt Macy 			 */
1036*eda14cbcSMatt Macy 			PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
1037*eda14cbcSMatt Macy 			    &sha2_hmac_ctx.hc_icontext,
1038*eda14cbcSMatt Macy 			    key->ck_data, keylen_in_bytes, digest);
1039*eda14cbcSMatt Macy 			sha2_mac_init_ctx(&sha2_hmac_ctx, digest,
1040*eda14cbcSMatt Macy 			    sha_digest_len);
1041*eda14cbcSMatt Macy 		} else {
1042*eda14cbcSMatt Macy 			sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data,
1043*eda14cbcSMatt Macy 			    keylen_in_bytes);
1044*eda14cbcSMatt Macy 		}
1045*eda14cbcSMatt Macy 	}
1046*eda14cbcSMatt Macy 
1047*eda14cbcSMatt Macy 	/* get the mechanism parameters, if applicable */
1048*eda14cbcSMatt Macy 	if ((mechanism->cm_type % 3) == 2) {
1049*eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
1050*eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (ulong_t)) {
1051*eda14cbcSMatt Macy 			ret = CRYPTO_MECHANISM_PARAM_INVALID;
1052*eda14cbcSMatt Macy 			goto bail;
1053*eda14cbcSMatt Macy 		}
1054*eda14cbcSMatt Macy 		PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len);
1055*eda14cbcSMatt Macy 		if (digest_len > sha_digest_len) {
1056*eda14cbcSMatt Macy 			ret = CRYPTO_MECHANISM_PARAM_INVALID;
1057*eda14cbcSMatt Macy 			goto bail;
1058*eda14cbcSMatt Macy 		}
1059*eda14cbcSMatt Macy 	}
1060*eda14cbcSMatt Macy 
1061*eda14cbcSMatt Macy 	/* do a SHA2 update of the inner context using the specified data */
1062*eda14cbcSMatt Macy 	SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret);
1063*eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
1064*eda14cbcSMatt Macy 		/* the update failed, free context and bail */
1065*eda14cbcSMatt Macy 		goto bail;
1066*eda14cbcSMatt Macy 
1067*eda14cbcSMatt Macy 	/*
1068*eda14cbcSMatt Macy 	 * Do a SHA2 final on the inner context.
1069*eda14cbcSMatt Macy 	 */
1070*eda14cbcSMatt Macy 	SHA2Final(digest, &sha2_hmac_ctx.hc_icontext);
1071*eda14cbcSMatt Macy 
1072*eda14cbcSMatt Macy 	/*
1073*eda14cbcSMatt Macy 	 * Do an SHA2 update on the outer context, feeding the inner
1074*eda14cbcSMatt Macy 	 * digest as data.
1075*eda14cbcSMatt Macy 	 *
1076*eda14cbcSMatt Macy 	 * HMAC-SHA384 needs special handling as the outer hash needs only 48
1077*eda14cbcSMatt Macy 	 * bytes of the inner hash value.
1078*eda14cbcSMatt Macy 	 */
1079*eda14cbcSMatt Macy 	if (mechanism->cm_type == SHA384_HMAC_MECH_INFO_TYPE ||
1080*eda14cbcSMatt Macy 	    mechanism->cm_type == SHA384_HMAC_GEN_MECH_INFO_TYPE)
1081*eda14cbcSMatt Macy 		SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest,
1082*eda14cbcSMatt Macy 		    SHA384_DIGEST_LENGTH);
1083*eda14cbcSMatt Macy 	else
1084*eda14cbcSMatt Macy 		SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len);
1085*eda14cbcSMatt Macy 
1086*eda14cbcSMatt Macy 	/*
1087*eda14cbcSMatt Macy 	 * Do a SHA2 final on the outer context, storing the computed
1088*eda14cbcSMatt Macy 	 * digest in the users buffer.
1089*eda14cbcSMatt Macy 	 */
1090*eda14cbcSMatt Macy 	switch (mac->cd_format) {
1091*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
1092*eda14cbcSMatt Macy 		if (digest_len != sha_digest_len) {
1093*eda14cbcSMatt Macy 			/*
1094*eda14cbcSMatt Macy 			 * The caller requested a short digest. Digest
1095*eda14cbcSMatt Macy 			 * into a scratch buffer and return to
1096*eda14cbcSMatt Macy 			 * the user only what was requested.
1097*eda14cbcSMatt Macy 			 */
1098*eda14cbcSMatt Macy 			SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext);
1099*eda14cbcSMatt Macy 			bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
1100*eda14cbcSMatt Macy 			    mac->cd_offset, digest_len);
1101*eda14cbcSMatt Macy 		} else {
1102*eda14cbcSMatt Macy 			SHA2Final((unsigned char *)mac->cd_raw.iov_base +
1103*eda14cbcSMatt Macy 			    mac->cd_offset, &sha2_hmac_ctx.hc_ocontext);
1104*eda14cbcSMatt Macy 		}
1105*eda14cbcSMatt Macy 		break;
1106*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
1107*eda14cbcSMatt Macy 		ret = sha2_digest_final_uio(&sha2_hmac_ctx.hc_ocontext, mac,
1108*eda14cbcSMatt Macy 		    digest_len, digest);
1109*eda14cbcSMatt Macy 		break;
1110*eda14cbcSMatt Macy 	default:
1111*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
1112*eda14cbcSMatt Macy 	}
1113*eda14cbcSMatt Macy 
1114*eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
1115*eda14cbcSMatt Macy 		mac->cd_length = digest_len;
1116*eda14cbcSMatt Macy 		return (CRYPTO_SUCCESS);
1117*eda14cbcSMatt Macy 	}
1118*eda14cbcSMatt Macy bail:
1119*eda14cbcSMatt Macy 	bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
1120*eda14cbcSMatt Macy 	mac->cd_length = 0;
1121*eda14cbcSMatt Macy 	return (ret);
1122*eda14cbcSMatt Macy }
1123*eda14cbcSMatt Macy 
1124*eda14cbcSMatt Macy /* ARGSUSED */
1125*eda14cbcSMatt Macy static int
1126*eda14cbcSMatt Macy sha2_mac_verify_atomic(crypto_provider_handle_t provider,
1127*eda14cbcSMatt Macy     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1128*eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1129*eda14cbcSMatt Macy     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1130*eda14cbcSMatt Macy {
1131*eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
1132*eda14cbcSMatt Macy 	uchar_t digest[SHA512_DIGEST_LENGTH];
1133*eda14cbcSMatt Macy 	sha2_hmac_ctx_t sha2_hmac_ctx;
1134*eda14cbcSMatt Macy 	uint32_t sha_digest_len, digest_len, sha_hmac_block_size;
1135*eda14cbcSMatt Macy 	uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1136*eda14cbcSMatt Macy 
1137*eda14cbcSMatt Macy 	/*
1138*eda14cbcSMatt Macy 	 * Set the digest length and block size to values appropriate to the
1139*eda14cbcSMatt Macy 	 * mechanism
1140*eda14cbcSMatt Macy 	 */
1141*eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
1142*eda14cbcSMatt Macy 	case SHA256_HMAC_MECH_INFO_TYPE:
1143*eda14cbcSMatt Macy 	case SHA256_HMAC_GEN_MECH_INFO_TYPE:
1144*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA256_DIGEST_LENGTH;
1145*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
1146*eda14cbcSMatt Macy 		break;
1147*eda14cbcSMatt Macy 	case SHA384_HMAC_MECH_INFO_TYPE:
1148*eda14cbcSMatt Macy 	case SHA384_HMAC_GEN_MECH_INFO_TYPE:
1149*eda14cbcSMatt Macy 	case SHA512_HMAC_MECH_INFO_TYPE:
1150*eda14cbcSMatt Macy 	case SHA512_HMAC_GEN_MECH_INFO_TYPE:
1151*eda14cbcSMatt Macy 		sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
1152*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
1153*eda14cbcSMatt Macy 		break;
1154*eda14cbcSMatt Macy 	default:
1155*eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
1156*eda14cbcSMatt Macy 	}
1157*eda14cbcSMatt Macy 
1158*eda14cbcSMatt Macy 	/* Add support for key by attributes (RFE 4706552) */
1159*eda14cbcSMatt Macy 	if (key->ck_format != CRYPTO_KEY_RAW)
1160*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
1161*eda14cbcSMatt Macy 
1162*eda14cbcSMatt Macy 	if (ctx_template != NULL) {
1163*eda14cbcSMatt Macy 		/* reuse context template */
1164*eda14cbcSMatt Macy 		bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
1165*eda14cbcSMatt Macy 	} else {
1166*eda14cbcSMatt Macy 		sha2_hmac_ctx.hc_mech_type = mechanism->cm_type;
1167*eda14cbcSMatt Macy 		/* no context template, initialize context */
1168*eda14cbcSMatt Macy 		if (keylen_in_bytes > sha_hmac_block_size) {
1169*eda14cbcSMatt Macy 			/*
1170*eda14cbcSMatt Macy 			 * Hash the passed-in key to get a smaller key.
1171*eda14cbcSMatt Macy 			 * The inner context is used since it hasn't been
1172*eda14cbcSMatt Macy 			 * initialized yet.
1173*eda14cbcSMatt Macy 			 */
1174*eda14cbcSMatt Macy 			PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
1175*eda14cbcSMatt Macy 			    &sha2_hmac_ctx.hc_icontext,
1176*eda14cbcSMatt Macy 			    key->ck_data, keylen_in_bytes, digest);
1177*eda14cbcSMatt Macy 			sha2_mac_init_ctx(&sha2_hmac_ctx, digest,
1178*eda14cbcSMatt Macy 			    sha_digest_len);
1179*eda14cbcSMatt Macy 		} else {
1180*eda14cbcSMatt Macy 			sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data,
1181*eda14cbcSMatt Macy 			    keylen_in_bytes);
1182*eda14cbcSMatt Macy 		}
1183*eda14cbcSMatt Macy 	}
1184*eda14cbcSMatt Macy 
1185*eda14cbcSMatt Macy 	/* get the mechanism parameters, if applicable */
1186*eda14cbcSMatt Macy 	if (mechanism->cm_type % 3 == 2) {
1187*eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
1188*eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (ulong_t)) {
1189*eda14cbcSMatt Macy 			ret = CRYPTO_MECHANISM_PARAM_INVALID;
1190*eda14cbcSMatt Macy 			goto bail;
1191*eda14cbcSMatt Macy 		}
1192*eda14cbcSMatt Macy 		PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len);
1193*eda14cbcSMatt Macy 		if (digest_len > sha_digest_len) {
1194*eda14cbcSMatt Macy 			ret = CRYPTO_MECHANISM_PARAM_INVALID;
1195*eda14cbcSMatt Macy 			goto bail;
1196*eda14cbcSMatt Macy 		}
1197*eda14cbcSMatt Macy 	}
1198*eda14cbcSMatt Macy 
1199*eda14cbcSMatt Macy 	if (mac->cd_length != digest_len) {
1200*eda14cbcSMatt Macy 		ret = CRYPTO_INVALID_MAC;
1201*eda14cbcSMatt Macy 		goto bail;
1202*eda14cbcSMatt Macy 	}
1203*eda14cbcSMatt Macy 
1204*eda14cbcSMatt Macy 	/* do a SHA2 update of the inner context using the specified data */
1205*eda14cbcSMatt Macy 	SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret);
1206*eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
1207*eda14cbcSMatt Macy 		/* the update failed, free context and bail */
1208*eda14cbcSMatt Macy 		goto bail;
1209*eda14cbcSMatt Macy 
1210*eda14cbcSMatt Macy 	/* do a SHA2 final on the inner context */
1211*eda14cbcSMatt Macy 	SHA2Final(digest, &sha2_hmac_ctx.hc_icontext);
1212*eda14cbcSMatt Macy 
1213*eda14cbcSMatt Macy 	/*
1214*eda14cbcSMatt Macy 	 * Do an SHA2 update on the outer context, feeding the inner
1215*eda14cbcSMatt Macy 	 * digest as data.
1216*eda14cbcSMatt Macy 	 *
1217*eda14cbcSMatt Macy 	 * HMAC-SHA384 needs special handling as the outer hash needs only 48
1218*eda14cbcSMatt Macy 	 * bytes of the inner hash value.
1219*eda14cbcSMatt Macy 	 */
1220*eda14cbcSMatt Macy 	if (mechanism->cm_type == SHA384_HMAC_MECH_INFO_TYPE ||
1221*eda14cbcSMatt Macy 	    mechanism->cm_type == SHA384_HMAC_GEN_MECH_INFO_TYPE)
1222*eda14cbcSMatt Macy 		SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest,
1223*eda14cbcSMatt Macy 		    SHA384_DIGEST_LENGTH);
1224*eda14cbcSMatt Macy 	else
1225*eda14cbcSMatt Macy 		SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len);
1226*eda14cbcSMatt Macy 
1227*eda14cbcSMatt Macy 	/*
1228*eda14cbcSMatt Macy 	 * Do a SHA2 final on the outer context, storing the computed
1229*eda14cbcSMatt Macy 	 * digest in the users buffer.
1230*eda14cbcSMatt Macy 	 */
1231*eda14cbcSMatt Macy 	SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext);
1232*eda14cbcSMatt Macy 
1233*eda14cbcSMatt Macy 	/*
1234*eda14cbcSMatt Macy 	 * Compare the computed digest against the expected digest passed
1235*eda14cbcSMatt Macy 	 * as argument.
1236*eda14cbcSMatt Macy 	 */
1237*eda14cbcSMatt Macy 
1238*eda14cbcSMatt Macy 	switch (mac->cd_format) {
1239*eda14cbcSMatt Macy 
1240*eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
1241*eda14cbcSMatt Macy 		if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base +
1242*eda14cbcSMatt Macy 		    mac->cd_offset, digest_len) != 0)
1243*eda14cbcSMatt Macy 			ret = CRYPTO_INVALID_MAC;
1244*eda14cbcSMatt Macy 		break;
1245*eda14cbcSMatt Macy 
1246*eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO: {
1247*eda14cbcSMatt Macy 		off_t offset = mac->cd_offset;
1248*eda14cbcSMatt Macy 		uint_t vec_idx = 0;
1249*eda14cbcSMatt Macy 		off_t scratch_offset = 0;
1250*eda14cbcSMatt Macy 		size_t length = digest_len;
1251*eda14cbcSMatt Macy 		size_t cur_len;
1252*eda14cbcSMatt Macy 
1253*eda14cbcSMatt Macy 		/* we support only kernel buffer */
1254*eda14cbcSMatt Macy 		if (uio_segflg(mac->cd_uio) != UIO_SYSSPACE)
1255*eda14cbcSMatt Macy 			return (CRYPTO_ARGUMENTS_BAD);
1256*eda14cbcSMatt Macy 
1257*eda14cbcSMatt Macy 		/* jump to the first iovec containing the expected digest */
1258*eda14cbcSMatt Macy 		offset = uio_index_at_offset(mac->cd_uio, offset, &vec_idx);
1259*eda14cbcSMatt Macy 		if (vec_idx == uio_iovcnt(mac->cd_uio)) {
1260*eda14cbcSMatt Macy 			/*
1261*eda14cbcSMatt Macy 			 * The caller specified an offset that is
1262*eda14cbcSMatt Macy 			 * larger than the total size of the buffers
1263*eda14cbcSMatt Macy 			 * it provided.
1264*eda14cbcSMatt Macy 			 */
1265*eda14cbcSMatt Macy 			ret = CRYPTO_DATA_LEN_RANGE;
1266*eda14cbcSMatt Macy 			break;
1267*eda14cbcSMatt Macy 		}
1268*eda14cbcSMatt Macy 
1269*eda14cbcSMatt Macy 		/* do the comparison of computed digest vs specified one */
1270*eda14cbcSMatt Macy 		while (vec_idx < uio_iovcnt(mac->cd_uio) && length > 0) {
1271*eda14cbcSMatt Macy 			cur_len = MIN(uio_iovlen(mac->cd_uio, vec_idx) -
1272*eda14cbcSMatt Macy 			    offset, length);
1273*eda14cbcSMatt Macy 
1274*eda14cbcSMatt Macy 			if (bcmp(digest + scratch_offset,
1275*eda14cbcSMatt Macy 			    uio_iovbase(mac->cd_uio, vec_idx) + offset,
1276*eda14cbcSMatt Macy 			    cur_len) != 0) {
1277*eda14cbcSMatt Macy 				ret = CRYPTO_INVALID_MAC;
1278*eda14cbcSMatt Macy 				break;
1279*eda14cbcSMatt Macy 			}
1280*eda14cbcSMatt Macy 
1281*eda14cbcSMatt Macy 			length -= cur_len;
1282*eda14cbcSMatt Macy 			vec_idx++;
1283*eda14cbcSMatt Macy 			scratch_offset += cur_len;
1284*eda14cbcSMatt Macy 			offset = 0;
1285*eda14cbcSMatt Macy 		}
1286*eda14cbcSMatt Macy 		break;
1287*eda14cbcSMatt Macy 	}
1288*eda14cbcSMatt Macy 
1289*eda14cbcSMatt Macy 	default:
1290*eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
1291*eda14cbcSMatt Macy 	}
1292*eda14cbcSMatt Macy 
1293*eda14cbcSMatt Macy 	return (ret);
1294*eda14cbcSMatt Macy bail:
1295*eda14cbcSMatt Macy 	bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
1296*eda14cbcSMatt Macy 	mac->cd_length = 0;
1297*eda14cbcSMatt Macy 	return (ret);
1298*eda14cbcSMatt Macy }
1299*eda14cbcSMatt Macy 
1300*eda14cbcSMatt Macy /*
1301*eda14cbcSMatt Macy  * KCF software provider context management entry points.
1302*eda14cbcSMatt Macy  */
1303*eda14cbcSMatt Macy 
1304*eda14cbcSMatt Macy /* ARGSUSED */
1305*eda14cbcSMatt Macy static int
1306*eda14cbcSMatt Macy sha2_create_ctx_template(crypto_provider_handle_t provider,
1307*eda14cbcSMatt Macy     crypto_mechanism_t *mechanism, crypto_key_t *key,
1308*eda14cbcSMatt Macy     crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size,
1309*eda14cbcSMatt Macy     crypto_req_handle_t req)
1310*eda14cbcSMatt Macy {
1311*eda14cbcSMatt Macy 	sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl;
1312*eda14cbcSMatt Macy 	uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1313*eda14cbcSMatt Macy 	uint32_t sha_digest_len, sha_hmac_block_size;
1314*eda14cbcSMatt Macy 
1315*eda14cbcSMatt Macy 	/*
1316*eda14cbcSMatt Macy 	 * Set the digest length and block size to values appropriate to the
1317*eda14cbcSMatt Macy 	 * mechanism
1318*eda14cbcSMatt Macy 	 */
1319*eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
1320*eda14cbcSMatt Macy 	case SHA256_HMAC_MECH_INFO_TYPE:
1321*eda14cbcSMatt Macy 	case SHA256_HMAC_GEN_MECH_INFO_TYPE:
1322*eda14cbcSMatt Macy 		sha_digest_len = SHA256_DIGEST_LENGTH;
1323*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
1324*eda14cbcSMatt Macy 		break;
1325*eda14cbcSMatt Macy 	case SHA384_HMAC_MECH_INFO_TYPE:
1326*eda14cbcSMatt Macy 	case SHA384_HMAC_GEN_MECH_INFO_TYPE:
1327*eda14cbcSMatt Macy 	case SHA512_HMAC_MECH_INFO_TYPE:
1328*eda14cbcSMatt Macy 	case SHA512_HMAC_GEN_MECH_INFO_TYPE:
1329*eda14cbcSMatt Macy 		sha_digest_len = SHA512_DIGEST_LENGTH;
1330*eda14cbcSMatt Macy 		sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
1331*eda14cbcSMatt Macy 		break;
1332*eda14cbcSMatt Macy 	default:
1333*eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
1334*eda14cbcSMatt Macy 	}
1335*eda14cbcSMatt Macy 
1336*eda14cbcSMatt Macy 	/* Add support for key by attributes (RFE 4706552) */
1337*eda14cbcSMatt Macy 	if (key->ck_format != CRYPTO_KEY_RAW)
1338*eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
1339*eda14cbcSMatt Macy 
1340*eda14cbcSMatt Macy 	/*
1341*eda14cbcSMatt Macy 	 * Allocate and initialize SHA2 context.
1342*eda14cbcSMatt Macy 	 */
1343*eda14cbcSMatt Macy 	sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t),
1344*eda14cbcSMatt Macy 	    crypto_kmflag(req));
1345*eda14cbcSMatt Macy 	if (sha2_hmac_ctx_tmpl == NULL)
1346*eda14cbcSMatt Macy 		return (CRYPTO_HOST_MEMORY);
1347*eda14cbcSMatt Macy 
1348*eda14cbcSMatt Macy 	sha2_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type;
1349*eda14cbcSMatt Macy 
1350*eda14cbcSMatt Macy 	if (keylen_in_bytes > sha_hmac_block_size) {
1351*eda14cbcSMatt Macy 		uchar_t digested_key[SHA512_DIGEST_LENGTH];
1352*eda14cbcSMatt Macy 
1353*eda14cbcSMatt Macy 		/*
1354*eda14cbcSMatt Macy 		 * Hash the passed-in key to get a smaller key.
1355*eda14cbcSMatt Macy 		 * The inner context is used since it hasn't been
1356*eda14cbcSMatt Macy 		 * initialized yet.
1357*eda14cbcSMatt Macy 		 */
1358*eda14cbcSMatt Macy 		PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
1359*eda14cbcSMatt Macy 		    &sha2_hmac_ctx_tmpl->hc_icontext,
1360*eda14cbcSMatt Macy 		    key->ck_data, keylen_in_bytes, digested_key);
1361*eda14cbcSMatt Macy 		sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, digested_key,
1362*eda14cbcSMatt Macy 		    sha_digest_len);
1363*eda14cbcSMatt Macy 	} else {
1364*eda14cbcSMatt Macy 		sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, key->ck_data,
1365*eda14cbcSMatt Macy 		    keylen_in_bytes);
1366*eda14cbcSMatt Macy 	}
1367*eda14cbcSMatt Macy 
1368*eda14cbcSMatt Macy 	*ctx_template = (crypto_spi_ctx_template_t)sha2_hmac_ctx_tmpl;
1369*eda14cbcSMatt Macy 	*ctx_template_size = sizeof (sha2_hmac_ctx_t);
1370*eda14cbcSMatt Macy 
1371*eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
1372*eda14cbcSMatt Macy }
1373*eda14cbcSMatt Macy 
1374*eda14cbcSMatt Macy static int
1375*eda14cbcSMatt Macy sha2_free_context(crypto_ctx_t *ctx)
1376*eda14cbcSMatt Macy {
1377*eda14cbcSMatt Macy 	uint_t ctx_len;
1378*eda14cbcSMatt Macy 
1379*eda14cbcSMatt Macy 	if (ctx->cc_provider_private == NULL)
1380*eda14cbcSMatt Macy 		return (CRYPTO_SUCCESS);
1381*eda14cbcSMatt Macy 
1382*eda14cbcSMatt Macy 	/*
1383*eda14cbcSMatt Macy 	 * We have to free either SHA2 or SHA2-HMAC contexts, which
1384*eda14cbcSMatt Macy 	 * have different lengths.
1385*eda14cbcSMatt Macy 	 *
1386*eda14cbcSMatt Macy 	 * Note: Below is dependent on the mechanism ordering.
1387*eda14cbcSMatt Macy 	 */
1388*eda14cbcSMatt Macy 
1389*eda14cbcSMatt Macy 	if (PROV_SHA2_CTX(ctx)->sc_mech_type % 3 == 0)
1390*eda14cbcSMatt Macy 		ctx_len = sizeof (sha2_ctx_t);
1391*eda14cbcSMatt Macy 	else
1392*eda14cbcSMatt Macy 		ctx_len = sizeof (sha2_hmac_ctx_t);
1393*eda14cbcSMatt Macy 
1394*eda14cbcSMatt Macy 	bzero(ctx->cc_provider_private, ctx_len);
1395*eda14cbcSMatt Macy 	kmem_free(ctx->cc_provider_private, ctx_len);
1396*eda14cbcSMatt Macy 	ctx->cc_provider_private = NULL;
1397*eda14cbcSMatt Macy 
1398*eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
1399*eda14cbcSMatt Macy }
1400