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