xref: /titanic_51/usr/src/common/crypto/sha1/sha1.c (revision 321502cd0930b1eb6d4805e17f16234f3e3ff4b2)
17c478bd9Sstevel@tonic-gate /*
2*321502cdSda73024  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate  * The basic framework for this code came from the reference
107c478bd9Sstevel@tonic-gate  * implementation for MD5.  That implementation is Copyright (C)
117c478bd9Sstevel@tonic-gate  * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * License to copy and use this software is granted provided that it
147c478bd9Sstevel@tonic-gate  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
157c478bd9Sstevel@tonic-gate  * Algorithm" in all material mentioning or referencing this software
167c478bd9Sstevel@tonic-gate  * or this function.
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * License is also granted to make and use derivative works provided
197c478bd9Sstevel@tonic-gate  * that such works are identified as "derived from the RSA Data
207c478bd9Sstevel@tonic-gate  * Security, Inc. MD5 Message-Digest Algorithm" in all material
217c478bd9Sstevel@tonic-gate  * mentioning or referencing the derived work.
227c478bd9Sstevel@tonic-gate  *
237c478bd9Sstevel@tonic-gate  * RSA Data Security, Inc. makes no representations concerning either
247c478bd9Sstevel@tonic-gate  * the merchantability of this software or the suitability of this
257c478bd9Sstevel@tonic-gate  * software for any particular purpose. It is provided "as is"
267c478bd9Sstevel@tonic-gate  * without express or implied warranty of any kind.
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * These notices must be retained in any copies of any part of this
297c478bd9Sstevel@tonic-gate  * documentation and/or software.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * NOTE: Cleaned-up and optimized, version of SHA1, based on the FIPS 180-1
327c478bd9Sstevel@tonic-gate  * standard, available at http://www.itl.nist.gov/div897/pubs/fip180-1.htm
337c478bd9Sstevel@tonic-gate  * Not as fast as one would like -- further optimizations are encouraged
347c478bd9Sstevel@tonic-gate  * and appreciated.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/param.h>
397c478bd9Sstevel@tonic-gate #include <sys/systm.h>
407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate #include <sys/sha1.h>
427c478bd9Sstevel@tonic-gate #include <sys/sha1_consts.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #ifndef	_KERNEL
457c478bd9Sstevel@tonic-gate #include <strings.h>
467c478bd9Sstevel@tonic-gate #include <stdlib.h>
477c478bd9Sstevel@tonic-gate #include <errno.h>
487c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
497c478bd9Sstevel@tonic-gate #endif  /* !_KERNEL */
507c478bd9Sstevel@tonic-gate 
51734b6a94Sdarrenm static void Encode(uint8_t *, const uint32_t *, size_t);
52734b6a94Sdarrenm 
53734b6a94Sdarrenm #if	defined(__sparc)
54734b6a94Sdarrenm 
55734b6a94Sdarrenm #define	SHA1_TRANSFORM(ctx, in) \
56734b6a94Sdarrenm 	SHA1Transform((ctx)->state[0], (ctx)->state[1], (ctx)->state[2], \
57734b6a94Sdarrenm 		(ctx)->state[3], (ctx)->state[4], (ctx), (in))
58734b6a94Sdarrenm 
597c478bd9Sstevel@tonic-gate static void SHA1Transform(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
607c478bd9Sstevel@tonic-gate     SHA1_CTX *, const uint8_t *);
617c478bd9Sstevel@tonic-gate 
62*321502cdSda73024 #elif	defined(__amd64)
63*321502cdSda73024 
64*321502cdSda73024 #define	SHA1_TRANSFORM(ctx, in) sha1_block_data_order((ctx), (in), 1)
65*321502cdSda73024 #define	SHA1_TRANSFORM_BLOCKS(ctx, in, num) sha1_block_data_order((ctx), \
66*321502cdSda73024 		(in), (num))
67*321502cdSda73024 
68*321502cdSda73024 void sha1_block_data_order(SHA1_CTX *ctx, const void *inpp, size_t num_blocks);
69*321502cdSda73024 
70734b6a94Sdarrenm #else
71734b6a94Sdarrenm 
72734b6a94Sdarrenm #define	SHA1_TRANSFORM(ctx, in) SHA1Transform((ctx), (in))
73734b6a94Sdarrenm 
74734b6a94Sdarrenm static void SHA1Transform(SHA1_CTX *, const uint8_t *);
75734b6a94Sdarrenm 
76734b6a94Sdarrenm #endif
77734b6a94Sdarrenm 
78734b6a94Sdarrenm 
797c478bd9Sstevel@tonic-gate static uint8_t PADDING[64] = { 0x80, /* all zeros */ };
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * F, G, and H are the basic SHA1 functions.
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate #define	F(b, c, d)	(((b) & (c)) | ((~b) & (d)))
857c478bd9Sstevel@tonic-gate #define	G(b, c, d)	((b) ^ (c) ^ (d))
86734b6a94Sdarrenm #define	H(b, c, d)	(((b) & (c)) | (((b)|(c)) & (d)))
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * ROTATE_LEFT rotates x left n bits.
907c478bd9Sstevel@tonic-gate  */
91734b6a94Sdarrenm 
92734b6a94Sdarrenm #if	defined(__GNUC__) && defined(_LP64)
93734b6a94Sdarrenm static __inline__ uint64_t
94734b6a94Sdarrenm ROTATE_LEFT(uint64_t value, uint32_t n)
95734b6a94Sdarrenm {
96734b6a94Sdarrenm 	uint32_t t32;
97734b6a94Sdarrenm 
98734b6a94Sdarrenm 	t32 = (uint32_t)value;
99734b6a94Sdarrenm 	return ((t32 << n) | (t32 >> (32 - n)));
100734b6a94Sdarrenm }
101734b6a94Sdarrenm 
102734b6a94Sdarrenm #else
103734b6a94Sdarrenm 
1047c478bd9Sstevel@tonic-gate #define	ROTATE_LEFT(x, n)	\
1057c478bd9Sstevel@tonic-gate 	(((x) << (n)) | ((x) >> ((sizeof (x) * NBBY)-(n))))
1067c478bd9Sstevel@tonic-gate 
107734b6a94Sdarrenm #endif
1087c478bd9Sstevel@tonic-gate 
109734b6a94Sdarrenm #if	defined(__GNUC__) && (defined(__i386) || defined(__amd64))
1107c478bd9Sstevel@tonic-gate 
111734b6a94Sdarrenm #define	HAVE_BSWAP
1127c478bd9Sstevel@tonic-gate 
113734b6a94Sdarrenm extern __inline__ uint32_t bswap(uint32_t value)
1147c478bd9Sstevel@tonic-gate {
115734b6a94Sdarrenm 	__asm__("bswap %0" : "+r" (value));
116734b6a94Sdarrenm 	return (value);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
119734b6a94Sdarrenm #endif
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate  * SHA1Init()
1237c478bd9Sstevel@tonic-gate  *
1247c478bd9Sstevel@tonic-gate  * purpose: initializes the sha1 context and begins and sha1 digest operation
1257c478bd9Sstevel@tonic-gate  *   input: SHA1_CTX *	: the context to initializes.
1267c478bd9Sstevel@tonic-gate  *  output: void
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate void
1307c478bd9Sstevel@tonic-gate SHA1Init(SHA1_CTX *ctx)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	ctx->count[0] = ctx->count[1] = 0;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/*
1357c478bd9Sstevel@tonic-gate 	 * load magic initialization constants. Tell lint
1367c478bd9Sstevel@tonic-gate 	 * that these constants are unsigned by using U.
1377c478bd9Sstevel@tonic-gate 	 */
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	ctx->state[0] = 0x67452301U;
1407c478bd9Sstevel@tonic-gate 	ctx->state[1] = 0xefcdab89U;
1417c478bd9Sstevel@tonic-gate 	ctx->state[2] = 0x98badcfeU;
1427c478bd9Sstevel@tonic-gate 	ctx->state[3] = 0x10325476U;
1437c478bd9Sstevel@tonic-gate 	ctx->state[4] = 0xc3d2e1f0U;
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate #ifdef VIS_SHA1
1477c478bd9Sstevel@tonic-gate #ifdef _KERNEL
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate #include <sys/regset.h>
1507c478bd9Sstevel@tonic-gate #include <sys/vis.h>
15115b9cbbcSkrishna #include <sys/fpu/fpusystm.h>
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /* the alignment for block stores to save fp registers */
1547c478bd9Sstevel@tonic-gate #define	VIS_ALIGN	(64)
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate extern int sha1_savefp(kfpu_t *, int);
1577c478bd9Sstevel@tonic-gate extern void sha1_restorefp(kfpu_t *);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate uint32_t	vis_sha1_svfp_threshold = 128;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * VIS SHA-1 consts.
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate static uint64_t VIS[] = {
1674cc1ac68Skrishna 	0x8000000080000000ULL,
1684cc1ac68Skrishna 	0x0002000200020002ULL,
1694cc1ac68Skrishna 	0x5a8279996ed9eba1ULL,
1704cc1ac68Skrishna 	0x8f1bbcdcca62c1d6ULL,
1714cc1ac68Skrishna 	0x012389ab456789abULL};
1727c478bd9Sstevel@tonic-gate 
173734b6a94Sdarrenm extern void SHA1TransformVIS(uint64_t *, uint32_t *, uint32_t *, uint64_t *);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate  * SHA1Update()
1787c478bd9Sstevel@tonic-gate  *
1797c478bd9Sstevel@tonic-gate  * purpose: continues an sha1 digest operation, using the message block
1807c478bd9Sstevel@tonic-gate  *          to update the context.
1817c478bd9Sstevel@tonic-gate  *   input: SHA1_CTX *	: the context to update
182734b6a94Sdarrenm  *          void *	: the message block
183734b6a94Sdarrenm  *          size_t    : the length of the message block in bytes
1847c478bd9Sstevel@tonic-gate  *  output: void
1857c478bd9Sstevel@tonic-gate  */
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate void
188734b6a94Sdarrenm SHA1Update(SHA1_CTX *ctx, const void *inptr, size_t input_len)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	uint32_t i, buf_index, buf_len;
1917c478bd9Sstevel@tonic-gate 	uint64_t X0[40], input64[8];
192734b6a94Sdarrenm 	const uint8_t *input = inptr;
19315b9cbbcSkrishna #ifdef _KERNEL
19415b9cbbcSkrishna 	int usevis = 0;
195734b6a94Sdarrenm #else
196734b6a94Sdarrenm 	int usevis = 1;
19715b9cbbcSkrishna #endif /* _KERNEL */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	/* check for noop */
2007c478bd9Sstevel@tonic-gate 	if (input_len == 0)
2017c478bd9Sstevel@tonic-gate 		return;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/* compute number of bytes mod 64 */
2047c478bd9Sstevel@tonic-gate 	buf_index = (ctx->count[1] >> 3) & 0x3F;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* update number of bits */
2077c478bd9Sstevel@tonic-gate 	if ((ctx->count[1] += (input_len << 3)) < (input_len << 3))
2087c478bd9Sstevel@tonic-gate 		ctx->count[0]++;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	ctx->count[0] += (input_len >> 29);
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	buf_len = 64 - buf_index;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/* transform as many times as possible */
2157c478bd9Sstevel@tonic-gate 	i = 0;
2167c478bd9Sstevel@tonic-gate 	if (input_len >= buf_len) {
2177c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2187c478bd9Sstevel@tonic-gate 		kfpu_t *fpu;
219734b6a94Sdarrenm 		if (fpu_exists) {
220734b6a94Sdarrenm 			uint8_t fpua[sizeof (kfpu_t) + GSR_SIZE + VIS_ALIGN];
2217c478bd9Sstevel@tonic-gate 			uint32_t len = (input_len + buf_index) & ~0x3f;
2227c478bd9Sstevel@tonic-gate 			int svfp_ok;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 			fpu = (kfpu_t *)P2ROUNDUP((uintptr_t)fpua, 64);
2257c478bd9Sstevel@tonic-gate 			svfp_ok = ((len >= vis_sha1_svfp_threshold) ? 1 : 0);
22615b9cbbcSkrishna 			usevis = fpu_exists && sha1_savefp(fpu, svfp_ok);
227734b6a94Sdarrenm 		} else {
228734b6a94Sdarrenm 			usevis = 0;
229734b6a94Sdarrenm 		}
2307c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 		/*
2337c478bd9Sstevel@tonic-gate 		 * general optimization:
2347c478bd9Sstevel@tonic-gate 		 *
2357c478bd9Sstevel@tonic-gate 		 * only do initial bcopy() and SHA1Transform() if
2367c478bd9Sstevel@tonic-gate 		 * buf_index != 0.  if buf_index == 0, we're just
2377c478bd9Sstevel@tonic-gate 		 * wasting our time doing the bcopy() since there
2387c478bd9Sstevel@tonic-gate 		 * wasn't any data left over from a previous call to
2397c478bd9Sstevel@tonic-gate 		 * SHA1Update().
2407c478bd9Sstevel@tonic-gate 		 */
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		if (buf_index) {
2437c478bd9Sstevel@tonic-gate 			bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len);
2447c478bd9Sstevel@tonic-gate 			if (usevis) {
2457c478bd9Sstevel@tonic-gate 				SHA1TransformVIS(X0,
246734b6a94Sdarrenm 				    ctx->buf_un.buf32,
2477c478bd9Sstevel@tonic-gate 				    &ctx->state[0], VIS);
2487c478bd9Sstevel@tonic-gate 			} else {
249734b6a94Sdarrenm 				SHA1_TRANSFORM(ctx, ctx->buf_un.buf8);
2507c478bd9Sstevel@tonic-gate 			}
2517c478bd9Sstevel@tonic-gate 			i = buf_len;
2527c478bd9Sstevel@tonic-gate 		}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 		/*
2557c478bd9Sstevel@tonic-gate 		 * VIS SHA-1: uses the VIS 1.0 instructions to accelerate
2567c478bd9Sstevel@tonic-gate 		 * SHA-1 processing. This is achieved by "offloading" the
2577c478bd9Sstevel@tonic-gate 		 * computation of the message schedule (MS) to the VIS units.
2587c478bd9Sstevel@tonic-gate 		 * This allows the VIS computation of the message schedule
2597c478bd9Sstevel@tonic-gate 		 * to be performed in parallel with the standard integer
2607c478bd9Sstevel@tonic-gate 		 * processing of the remainder of the SHA-1 computation.
2617c478bd9Sstevel@tonic-gate 		 * performance by up to around 1.37X, compared to an optimized
2627c478bd9Sstevel@tonic-gate 		 * integer-only implementation.
2637c478bd9Sstevel@tonic-gate 		 *
2647c478bd9Sstevel@tonic-gate 		 * The VIS implementation of SHA1Transform has a different API
2657c478bd9Sstevel@tonic-gate 		 * to the standard integer version:
2667c478bd9Sstevel@tonic-gate 		 *
2677c478bd9Sstevel@tonic-gate 		 * void SHA1TransformVIS(
2687c478bd9Sstevel@tonic-gate 		 *	 uint64_t *, // Pointer to MS for ith block
269734b6a94Sdarrenm 		 *	 uint32_t *, // Pointer to ith block of message data
2707c478bd9Sstevel@tonic-gate 		 *	 uint32_t *, // Pointer to SHA state i.e ctx->state
2717c478bd9Sstevel@tonic-gate 		 *	 uint64_t *, // Pointer to various VIS constants
2727c478bd9Sstevel@tonic-gate 		 * )
2737c478bd9Sstevel@tonic-gate 		 *
2747c478bd9Sstevel@tonic-gate 		 * Note: the message data must by 4-byte aligned.
2757c478bd9Sstevel@tonic-gate 		 *
2767c478bd9Sstevel@tonic-gate 		 * Function requires VIS 1.0 support.
2777c478bd9Sstevel@tonic-gate 		 *
2787c478bd9Sstevel@tonic-gate 		 * Handling is provided to deal with arbitrary byte alingment
2797c478bd9Sstevel@tonic-gate 		 * of the input data but the performance gains are reduced
2807c478bd9Sstevel@tonic-gate 		 * for alignments other than 4-bytes.
2817c478bd9Sstevel@tonic-gate 		 */
2827c478bd9Sstevel@tonic-gate 		if (usevis) {
283734b6a94Sdarrenm 			if (!IS_P2ALIGNED(&input[i], sizeof (uint32_t))) {
2847c478bd9Sstevel@tonic-gate 				/*
2857c478bd9Sstevel@tonic-gate 				 * Main processing loop - input misaligned
2867c478bd9Sstevel@tonic-gate 				 */
2877c478bd9Sstevel@tonic-gate 				for (; i + 63 < input_len; i += 64) {
2887c478bd9Sstevel@tonic-gate 					bcopy(&input[i], input64, 64);
289*321502cdSda73024 					SHA1TransformVIS(X0,
290*321502cdSda73024 					    (uint32_t *)input64,
2917c478bd9Sstevel@tonic-gate 					    &ctx->state[0], VIS);
2927c478bd9Sstevel@tonic-gate 				}
2937c478bd9Sstevel@tonic-gate 			} else {
2947c478bd9Sstevel@tonic-gate 				/*
2957c478bd9Sstevel@tonic-gate 				 * Main processing loop - input 8-byte aligned
2967c478bd9Sstevel@tonic-gate 				 */
2977c478bd9Sstevel@tonic-gate 				for (; i + 63 < input_len; i += 64) {
2987c478bd9Sstevel@tonic-gate 					SHA1TransformVIS(X0,
299734b6a94Sdarrenm 					/* LINTED E_BAD_PTR_CAST_ALIGN */
300734b6a94Sdarrenm 					    (uint32_t *)&input[i],
3017c478bd9Sstevel@tonic-gate 					    &ctx->state[0], VIS);
3027c478bd9Sstevel@tonic-gate 				}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 			}
3057c478bd9Sstevel@tonic-gate #ifdef _KERNEL
3067c478bd9Sstevel@tonic-gate 			sha1_restorefp(fpu);
3077c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
3087c478bd9Sstevel@tonic-gate 		} else {
3097c478bd9Sstevel@tonic-gate 			for (; i + 63 < input_len; i += 64) {
310734b6a94Sdarrenm 				SHA1_TRANSFORM(ctx, &input[i]);
3117c478bd9Sstevel@tonic-gate 			}
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 		/*
3157c478bd9Sstevel@tonic-gate 		 * general optimization:
3167c478bd9Sstevel@tonic-gate 		 *
3177c478bd9Sstevel@tonic-gate 		 * if i and input_len are the same, return now instead
3187c478bd9Sstevel@tonic-gate 		 * of calling bcopy(), since the bcopy() in this case
3197c478bd9Sstevel@tonic-gate 		 * will be an expensive nop.
3207c478bd9Sstevel@tonic-gate 		 */
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 		if (input_len == i)
3237c478bd9Sstevel@tonic-gate 			return;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 		buf_index = 0;
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	/* buffer remaining input */
3297c478bd9Sstevel@tonic-gate 	bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i);
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate #else /* VIS_SHA1 */
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate void
335734b6a94Sdarrenm SHA1Update(SHA1_CTX *ctx, const void *inptr, size_t input_len)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate 	uint32_t i, buf_index, buf_len;
338734b6a94Sdarrenm 	const uint8_t *input = inptr;
339*321502cdSda73024 #if defined(__amd64)
340*321502cdSda73024 	uint32_t	block_count;
341*321502cdSda73024 #endif	/* __amd64 */
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	/* check for noop */
3447c478bd9Sstevel@tonic-gate 	if (input_len == 0)
3457c478bd9Sstevel@tonic-gate 		return;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/* compute number of bytes mod 64 */
3487c478bd9Sstevel@tonic-gate 	buf_index = (ctx->count[1] >> 3) & 0x3F;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	/* update number of bits */
3517c478bd9Sstevel@tonic-gate 	if ((ctx->count[1] += (input_len << 3)) < (input_len << 3))
3527c478bd9Sstevel@tonic-gate 		ctx->count[0]++;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	ctx->count[0] += (input_len >> 29);
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	buf_len = 64 - buf_index;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	/* transform as many times as possible */
3597c478bd9Sstevel@tonic-gate 	i = 0;
3607c478bd9Sstevel@tonic-gate 	if (input_len >= buf_len) {
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 		/*
3637c478bd9Sstevel@tonic-gate 		 * general optimization:
3647c478bd9Sstevel@tonic-gate 		 *
3657c478bd9Sstevel@tonic-gate 		 * only do initial bcopy() and SHA1Transform() if
3667c478bd9Sstevel@tonic-gate 		 * buf_index != 0.  if buf_index == 0, we're just
3677c478bd9Sstevel@tonic-gate 		 * wasting our time doing the bcopy() since there
3687c478bd9Sstevel@tonic-gate 		 * wasn't any data left over from a previous call to
3697c478bd9Sstevel@tonic-gate 		 * SHA1Update().
3707c478bd9Sstevel@tonic-gate 		 */
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 		if (buf_index) {
3737c478bd9Sstevel@tonic-gate 			bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len);
374734b6a94Sdarrenm 			SHA1_TRANSFORM(ctx, ctx->buf_un.buf8);
3757c478bd9Sstevel@tonic-gate 			i = buf_len;
3767c478bd9Sstevel@tonic-gate 		}
3777c478bd9Sstevel@tonic-gate 
378*321502cdSda73024 #if !defined(__amd64)
3797c478bd9Sstevel@tonic-gate 		for (; i + 63 < input_len; i += 64)
380734b6a94Sdarrenm 			SHA1_TRANSFORM(ctx, &input[i]);
381*321502cdSda73024 #else
382*321502cdSda73024 		block_count = (input_len - i) >> 6;
383*321502cdSda73024 		if (block_count > 0) {
384*321502cdSda73024 			SHA1_TRANSFORM_BLOCKS(ctx, &input[i], block_count);
385*321502cdSda73024 			i += block_count << 6;
386*321502cdSda73024 		}
387*321502cdSda73024 #endif	/* !__amd64 */
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		/*
3907c478bd9Sstevel@tonic-gate 		 * general optimization:
3917c478bd9Sstevel@tonic-gate 		 *
3927c478bd9Sstevel@tonic-gate 		 * if i and input_len are the same, return now instead
3937c478bd9Sstevel@tonic-gate 		 * of calling bcopy(), since the bcopy() in this case
3947c478bd9Sstevel@tonic-gate 		 * will be an expensive nop.
3957c478bd9Sstevel@tonic-gate 		 */
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		if (input_len == i)
3987c478bd9Sstevel@tonic-gate 			return;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 		buf_index = 0;
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	/* buffer remaining input */
4047c478bd9Sstevel@tonic-gate 	bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i);
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate #endif /* VIS_SHA1 */
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate  * SHA1Final()
4117c478bd9Sstevel@tonic-gate  *
4127c478bd9Sstevel@tonic-gate  * purpose: ends an sha1 digest operation, finalizing the message digest and
4137c478bd9Sstevel@tonic-gate  *          zeroing the context.
414*321502cdSda73024  *   input: uchar_t *	: A buffer to store the digest.
4155151fb12Sdarrenm  *			: The function actually uses void* because many
4165151fb12Sdarrenm  *			: callers pass things other than uchar_t here.
4177c478bd9Sstevel@tonic-gate  *          SHA1_CTX *  : the context to finalize, save, and zero
4187c478bd9Sstevel@tonic-gate  *  output: void
4197c478bd9Sstevel@tonic-gate  */
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate void
422734b6a94Sdarrenm SHA1Final(void *digest, SHA1_CTX *ctx)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	uint8_t		bitcount_be[sizeof (ctx->count)];
4257c478bd9Sstevel@tonic-gate 	uint32_t	index = (ctx->count[1] >> 3) & 0x3f;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	/* store bit count, big endian */
4287c478bd9Sstevel@tonic-gate 	Encode(bitcount_be, ctx->count, sizeof (bitcount_be));
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	/* pad out to 56 mod 64 */
4317c478bd9Sstevel@tonic-gate 	SHA1Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	/* append length (before padding) */
4347c478bd9Sstevel@tonic-gate 	SHA1Update(ctx, bitcount_be, sizeof (bitcount_be));
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	/* store state in digest */
4377c478bd9Sstevel@tonic-gate 	Encode(digest, ctx->state, sizeof (ctx->state));
438673007c6Sdarrenm 
439673007c6Sdarrenm 	/* zeroize sensitive information */
440673007c6Sdarrenm 	bzero(ctx, sizeof (*ctx));
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
443*321502cdSda73024 
444*321502cdSda73024 #if !defined(__amd64)
445*321502cdSda73024 
446734b6a94Sdarrenm typedef uint32_t sha1word;
447734b6a94Sdarrenm 
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate  * sparc optimization:
4507c478bd9Sstevel@tonic-gate  *
4517c478bd9Sstevel@tonic-gate  * on the sparc, we can load big endian 32-bit data easily.  note that
4527c478bd9Sstevel@tonic-gate  * special care must be taken to ensure the address is 32-bit aligned.
4537c478bd9Sstevel@tonic-gate  * in the interest of speed, we don't check to make sure, since
4547c478bd9Sstevel@tonic-gate  * careful programming can guarantee this for us.
4557c478bd9Sstevel@tonic-gate  */
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate #if	defined(_BIG_ENDIAN)
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate #define	LOAD_BIG_32(addr)	(*(uint32_t *)(addr))
4607c478bd9Sstevel@tonic-gate 
461734b6a94Sdarrenm #else	/* !defined(_BIG_ENDIAN) */
4627c478bd9Sstevel@tonic-gate 
463734b6a94Sdarrenm #if	defined(HAVE_BSWAP)
464734b6a94Sdarrenm 
465734b6a94Sdarrenm #define	LOAD_BIG_32(addr) bswap(*((uint32_t *)(addr)))
466734b6a94Sdarrenm 
467734b6a94Sdarrenm #else	/* !defined(HAVE_BSWAP) */
468734b6a94Sdarrenm 
469734b6a94Sdarrenm /* little endian -- will work on big endian, but slowly */
4707c478bd9Sstevel@tonic-gate #define	LOAD_BIG_32(addr)	\
4717c478bd9Sstevel@tonic-gate 	(((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3])
472734b6a94Sdarrenm 
473734b6a94Sdarrenm #endif	/* !defined(HAVE_BSWAP) */
474734b6a94Sdarrenm 
475734b6a94Sdarrenm #endif	/* !defined(_BIG_ENDIAN) */
476734b6a94Sdarrenm 
477734b6a94Sdarrenm /*
478734b6a94Sdarrenm  * SHA1Transform()
479734b6a94Sdarrenm  */
480734b6a94Sdarrenm #if	defined(W_ARRAY)
481734b6a94Sdarrenm #define	W(n) w[n]
482734b6a94Sdarrenm #else	/* !defined(W_ARRAY) */
483734b6a94Sdarrenm #define	W(n) w_ ## n
484734b6a94Sdarrenm #endif	/* !defined(W_ARRAY) */
485734b6a94Sdarrenm 
486734b6a94Sdarrenm 
487734b6a94Sdarrenm #if	defined(__sparc)
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate  * sparc register window optimization:
4917c478bd9Sstevel@tonic-gate  *
4927c478bd9Sstevel@tonic-gate  * `a', `b', `c', `d', and `e' are passed into SHA1Transform
4937c478bd9Sstevel@tonic-gate  * explicitly since it increases the number of registers available to
4947c478bd9Sstevel@tonic-gate  * the compiler.  under this scheme, these variables can be held in
4957c478bd9Sstevel@tonic-gate  * %i0 - %i4, which leaves more local and out registers available.
4967c478bd9Sstevel@tonic-gate  *
4977c478bd9Sstevel@tonic-gate  * purpose: sha1 transformation -- updates the digest based on `block'
4987c478bd9Sstevel@tonic-gate  *   input: uint32_t	: bytes  1 -  4 of the digest
4997c478bd9Sstevel@tonic-gate  *          uint32_t	: bytes  5 -  8 of the digest
5007c478bd9Sstevel@tonic-gate  *          uint32_t	: bytes  9 - 12 of the digest
5017c478bd9Sstevel@tonic-gate  *          uint32_t	: bytes 12 - 16 of the digest
5027c478bd9Sstevel@tonic-gate  *          uint32_t	: bytes 16 - 20 of the digest
5037c478bd9Sstevel@tonic-gate  *          SHA1_CTX *	: the context to update
5047c478bd9Sstevel@tonic-gate  *          uint8_t [64]: the block to use to update the digest
5057c478bd9Sstevel@tonic-gate  *  output: void
5067c478bd9Sstevel@tonic-gate  */
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate void
5097c478bd9Sstevel@tonic-gate SHA1Transform(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e,
5107c478bd9Sstevel@tonic-gate     SHA1_CTX *ctx, const uint8_t blk[64])
5117c478bd9Sstevel@tonic-gate {
5127c478bd9Sstevel@tonic-gate 	/*
5137c478bd9Sstevel@tonic-gate 	 * sparc optimization:
5147c478bd9Sstevel@tonic-gate 	 *
5157c478bd9Sstevel@tonic-gate 	 * while it is somewhat counter-intuitive, on sparc, it is
5167c478bd9Sstevel@tonic-gate 	 * more efficient to place all the constants used in this
5177c478bd9Sstevel@tonic-gate 	 * function in an array and load the values out of the array
5187c478bd9Sstevel@tonic-gate 	 * than to manually load the constants.  this is because
5197c478bd9Sstevel@tonic-gate 	 * setting a register to a 32-bit value takes two ops in most
5207c478bd9Sstevel@tonic-gate 	 * cases: a `sethi' and an `or', but loading a 32-bit value
5217c478bd9Sstevel@tonic-gate 	 * from memory only takes one `ld' (or `lduw' on v9).  while
5227c478bd9Sstevel@tonic-gate 	 * this increases memory usage, the compiler can find enough
5237c478bd9Sstevel@tonic-gate 	 * other things to do while waiting to keep the pipeline does
5247c478bd9Sstevel@tonic-gate 	 * not stall.  additionally, it is likely that many of these
5257c478bd9Sstevel@tonic-gate 	 * constants are cached so that later accesses do not even go
5267c478bd9Sstevel@tonic-gate 	 * out to the bus.
5277c478bd9Sstevel@tonic-gate 	 *
5287c478bd9Sstevel@tonic-gate 	 * this array is declared `static' to keep the compiler from
5297c478bd9Sstevel@tonic-gate 	 * having to bcopy() this array onto the stack frame of
5307c478bd9Sstevel@tonic-gate 	 * SHA1Transform() each time it is called -- which is
5317c478bd9Sstevel@tonic-gate 	 * unacceptably expensive.
5327c478bd9Sstevel@tonic-gate 	 *
5337c478bd9Sstevel@tonic-gate 	 * the `const' is to ensure that callers are good citizens and
5347c478bd9Sstevel@tonic-gate 	 * do not try to munge the array.  since these routines are
5357c478bd9Sstevel@tonic-gate 	 * going to be called from inside multithreaded kernelland,
5367c478bd9Sstevel@tonic-gate 	 * this is a good safety check. -- `sha1_consts' will end up in
5377c478bd9Sstevel@tonic-gate 	 * .rodata.
5387c478bd9Sstevel@tonic-gate 	 *
5397c478bd9Sstevel@tonic-gate 	 * unfortunately, loading from an array in this manner hurts
5407c478bd9Sstevel@tonic-gate 	 * performance under intel.  so, there is a macro,
5417c478bd9Sstevel@tonic-gate 	 * SHA1_CONST(), used in SHA1Transform(), that either expands to
5427c478bd9Sstevel@tonic-gate 	 * a reference to this array, or to the actual constant,
5437c478bd9Sstevel@tonic-gate 	 * depending on what platform this code is compiled for.
5447c478bd9Sstevel@tonic-gate 	 */
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	static const uint32_t sha1_consts[] = {
5477c478bd9Sstevel@tonic-gate 		SHA1_CONST_0,	SHA1_CONST_1,	SHA1_CONST_2,	SHA1_CONST_3,
5487c478bd9Sstevel@tonic-gate 	};
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	/*
5517c478bd9Sstevel@tonic-gate 	 * general optimization:
5527c478bd9Sstevel@tonic-gate 	 *
5537c478bd9Sstevel@tonic-gate 	 * use individual integers instead of using an array.  this is a
5547c478bd9Sstevel@tonic-gate 	 * win, although the amount it wins by seems to vary quite a bit.
5557c478bd9Sstevel@tonic-gate 	 */
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	uint32_t	w_0, w_1, w_2,  w_3,  w_4,  w_5,  w_6,  w_7;
5587c478bd9Sstevel@tonic-gate 	uint32_t	w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	/*
5617c478bd9Sstevel@tonic-gate 	 * sparc optimization:
5627c478bd9Sstevel@tonic-gate 	 *
5637c478bd9Sstevel@tonic-gate 	 * if `block' is already aligned on a 4-byte boundary, use
5647c478bd9Sstevel@tonic-gate 	 * LOAD_BIG_32() directly.  otherwise, bcopy() into a
5657c478bd9Sstevel@tonic-gate 	 * buffer that *is* aligned on a 4-byte boundary and then do
5667c478bd9Sstevel@tonic-gate 	 * the LOAD_BIG_32() on that buffer.  benchmarks have shown
5677c478bd9Sstevel@tonic-gate 	 * that using the bcopy() is better than loading the bytes
5687c478bd9Sstevel@tonic-gate 	 * individually and doing the endian-swap by hand.
5697c478bd9Sstevel@tonic-gate 	 *
5707c478bd9Sstevel@tonic-gate 	 * even though it's quite tempting to assign to do:
5717c478bd9Sstevel@tonic-gate 	 *
5727c478bd9Sstevel@tonic-gate 	 * blk = bcopy(ctx->buf_un.buf32, blk, sizeof (ctx->buf_un.buf32));
5737c478bd9Sstevel@tonic-gate 	 *
5747c478bd9Sstevel@tonic-gate 	 * and only have one set of LOAD_BIG_32()'s, the compiler
5757c478bd9Sstevel@tonic-gate 	 * *does not* like that, so please resist the urge.
5767c478bd9Sstevel@tonic-gate 	 */
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	if ((uintptr_t)blk & 0x3) {		/* not 4-byte aligned? */
5797c478bd9Sstevel@tonic-gate 		bcopy(blk, ctx->buf_un.buf32,  sizeof (ctx->buf_un.buf32));
5807c478bd9Sstevel@tonic-gate 		w_15 = LOAD_BIG_32(ctx->buf_un.buf32 + 15);
5817c478bd9Sstevel@tonic-gate 		w_14 = LOAD_BIG_32(ctx->buf_un.buf32 + 14);
5827c478bd9Sstevel@tonic-gate 		w_13 = LOAD_BIG_32(ctx->buf_un.buf32 + 13);
5837c478bd9Sstevel@tonic-gate 		w_12 = LOAD_BIG_32(ctx->buf_un.buf32 + 12);
5847c478bd9Sstevel@tonic-gate 		w_11 = LOAD_BIG_32(ctx->buf_un.buf32 + 11);
5857c478bd9Sstevel@tonic-gate 		w_10 = LOAD_BIG_32(ctx->buf_un.buf32 + 10);
5867c478bd9Sstevel@tonic-gate 		w_9  = LOAD_BIG_32(ctx->buf_un.buf32 +  9);
5877c478bd9Sstevel@tonic-gate 		w_8  = LOAD_BIG_32(ctx->buf_un.buf32 +  8);
5887c478bd9Sstevel@tonic-gate 		w_7  = LOAD_BIG_32(ctx->buf_un.buf32 +  7);
5897c478bd9Sstevel@tonic-gate 		w_6  = LOAD_BIG_32(ctx->buf_un.buf32 +  6);
5907c478bd9Sstevel@tonic-gate 		w_5  = LOAD_BIG_32(ctx->buf_un.buf32 +  5);
5917c478bd9Sstevel@tonic-gate 		w_4  = LOAD_BIG_32(ctx->buf_un.buf32 +  4);
5927c478bd9Sstevel@tonic-gate 		w_3  = LOAD_BIG_32(ctx->buf_un.buf32 +  3);
5937c478bd9Sstevel@tonic-gate 		w_2  = LOAD_BIG_32(ctx->buf_un.buf32 +  2);
5947c478bd9Sstevel@tonic-gate 		w_1  = LOAD_BIG_32(ctx->buf_un.buf32 +  1);
5957c478bd9Sstevel@tonic-gate 		w_0  = LOAD_BIG_32(ctx->buf_un.buf32 +  0);
5967c478bd9Sstevel@tonic-gate 	} else {
5977c478bd9Sstevel@tonic-gate 		/*LINTED*/
5987c478bd9Sstevel@tonic-gate 		w_15 = LOAD_BIG_32(blk + 60);
5997c478bd9Sstevel@tonic-gate 		/*LINTED*/
6007c478bd9Sstevel@tonic-gate 		w_14 = LOAD_BIG_32(blk + 56);
6017c478bd9Sstevel@tonic-gate 		/*LINTED*/
6027c478bd9Sstevel@tonic-gate 		w_13 = LOAD_BIG_32(blk + 52);
6037c478bd9Sstevel@tonic-gate 		/*LINTED*/
6047c478bd9Sstevel@tonic-gate 		w_12 = LOAD_BIG_32(blk + 48);
6057c478bd9Sstevel@tonic-gate 		/*LINTED*/
6067c478bd9Sstevel@tonic-gate 		w_11 = LOAD_BIG_32(blk + 44);
6077c478bd9Sstevel@tonic-gate 		/*LINTED*/
6087c478bd9Sstevel@tonic-gate 		w_10 = LOAD_BIG_32(blk + 40);
6097c478bd9Sstevel@tonic-gate 		/*LINTED*/
6107c478bd9Sstevel@tonic-gate 		w_9  = LOAD_BIG_32(blk + 36);
6117c478bd9Sstevel@tonic-gate 		/*LINTED*/
6127c478bd9Sstevel@tonic-gate 		w_8  = LOAD_BIG_32(blk + 32);
6137c478bd9Sstevel@tonic-gate 		/*LINTED*/
6147c478bd9Sstevel@tonic-gate 		w_7  = LOAD_BIG_32(blk + 28);
6157c478bd9Sstevel@tonic-gate 		/*LINTED*/
6167c478bd9Sstevel@tonic-gate 		w_6  = LOAD_BIG_32(blk + 24);
6177c478bd9Sstevel@tonic-gate 		/*LINTED*/
6187c478bd9Sstevel@tonic-gate 		w_5  = LOAD_BIG_32(blk + 20);
6197c478bd9Sstevel@tonic-gate 		/*LINTED*/
6207c478bd9Sstevel@tonic-gate 		w_4  = LOAD_BIG_32(blk + 16);
6217c478bd9Sstevel@tonic-gate 		/*LINTED*/
6227c478bd9Sstevel@tonic-gate 		w_3  = LOAD_BIG_32(blk + 12);
6237c478bd9Sstevel@tonic-gate 		/*LINTED*/
6247c478bd9Sstevel@tonic-gate 		w_2  = LOAD_BIG_32(blk +  8);
6257c478bd9Sstevel@tonic-gate 		/*LINTED*/
6267c478bd9Sstevel@tonic-gate 		w_1  = LOAD_BIG_32(blk +  4);
6277c478bd9Sstevel@tonic-gate 		/*LINTED*/
6287c478bd9Sstevel@tonic-gate 		w_0  = LOAD_BIG_32(blk +  0);
6297c478bd9Sstevel@tonic-gate 	}
630734b6a94Sdarrenm #else	/* !defined(__sparc) */
631734b6a94Sdarrenm 
632734b6a94Sdarrenm void
633734b6a94Sdarrenm SHA1Transform(SHA1_CTX *ctx, const uint8_t blk[64])
634734b6a94Sdarrenm {
635734b6a94Sdarrenm 	sha1word a = ctx->state[0];
636734b6a94Sdarrenm 	sha1word b = ctx->state[1];
637734b6a94Sdarrenm 	sha1word c = ctx->state[2];
638734b6a94Sdarrenm 	sha1word d = ctx->state[3];
639734b6a94Sdarrenm 	sha1word e = ctx->state[4];
640734b6a94Sdarrenm 
641734b6a94Sdarrenm #if	defined(W_ARRAY)
642734b6a94Sdarrenm 	sha1word	w[16];
643734b6a94Sdarrenm #else	/* !defined(W_ARRAY) */
644734b6a94Sdarrenm 	sha1word	w_0, w_1, w_2,  w_3,  w_4,  w_5,  w_6,  w_7;
645734b6a94Sdarrenm 	sha1word	w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15;
646734b6a94Sdarrenm #endif	/* !defined(W_ARRAY) */
647734b6a94Sdarrenm 
648734b6a94Sdarrenm 	W(0)  = LOAD_BIG_32(blk +  0);
649734b6a94Sdarrenm 	W(1)  = LOAD_BIG_32(blk +  4);
650734b6a94Sdarrenm 	W(2)  = LOAD_BIG_32(blk +  8);
651734b6a94Sdarrenm 	W(3)  = LOAD_BIG_32(blk + 12);
652734b6a94Sdarrenm 	W(4)  = LOAD_BIG_32(blk + 16);
653734b6a94Sdarrenm 	W(5)  = LOAD_BIG_32(blk + 20);
654734b6a94Sdarrenm 	W(6)  = LOAD_BIG_32(blk + 24);
655734b6a94Sdarrenm 	W(7)  = LOAD_BIG_32(blk + 28);
656734b6a94Sdarrenm 	W(8)  = LOAD_BIG_32(blk + 32);
657734b6a94Sdarrenm 	W(9)  = LOAD_BIG_32(blk + 36);
658734b6a94Sdarrenm 	W(10) = LOAD_BIG_32(blk + 40);
659734b6a94Sdarrenm 	W(11) = LOAD_BIG_32(blk + 44);
660734b6a94Sdarrenm 	W(12) = LOAD_BIG_32(blk + 48);
661734b6a94Sdarrenm 	W(13) = LOAD_BIG_32(blk + 52);
662734b6a94Sdarrenm 	W(14) = LOAD_BIG_32(blk + 56);
663734b6a94Sdarrenm 	W(15) = LOAD_BIG_32(blk + 60);
664734b6a94Sdarrenm 
665734b6a94Sdarrenm #endif	/* !defined(__sparc) */
666734b6a94Sdarrenm 
6677c478bd9Sstevel@tonic-gate 	/*
6687c478bd9Sstevel@tonic-gate 	 * general optimization:
6697c478bd9Sstevel@tonic-gate 	 *
6707c478bd9Sstevel@tonic-gate 	 * even though this approach is described in the standard as
6717c478bd9Sstevel@tonic-gate 	 * being slower algorithmically, it is 30-40% faster than the
6727c478bd9Sstevel@tonic-gate 	 * "faster" version under SPARC, because this version has more
6737c478bd9Sstevel@tonic-gate 	 * of the constraints specified at compile-time and uses fewer
6747c478bd9Sstevel@tonic-gate 	 * variables (and therefore has better register utilization)
6757c478bd9Sstevel@tonic-gate 	 * than its "speedier" brother.  (i've tried both, trust me)
6767c478bd9Sstevel@tonic-gate 	 *
6777c478bd9Sstevel@tonic-gate 	 * for either method given in the spec, there is an "assignment"
6787c478bd9Sstevel@tonic-gate 	 * phase where the following takes place:
6797c478bd9Sstevel@tonic-gate 	 *
6807c478bd9Sstevel@tonic-gate 	 *	tmp = (main_computation);
6817c478bd9Sstevel@tonic-gate 	 *	e = d; d = c; c = rotate_left(b, 30); b = a; a = tmp;
6827c478bd9Sstevel@tonic-gate 	 *
6837c478bd9Sstevel@tonic-gate 	 * we can make the algorithm go faster by not doing this work,
6847c478bd9Sstevel@tonic-gate 	 * but just pretending that `d' is now `e', etc. this works
6857c478bd9Sstevel@tonic-gate 	 * really well and obviates the need for a temporary variable.
686*321502cdSda73024 	 * however, we still explicitly perform the rotate action,
6877c478bd9Sstevel@tonic-gate 	 * since it is cheaper on SPARC to do it once than to have to
6887c478bd9Sstevel@tonic-gate 	 * do it over and over again.
6897c478bd9Sstevel@tonic-gate 	 */
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	/* round 1 */
692734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(0) + SHA1_CONST(0); /* 0 */
6937c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
6947c478bd9Sstevel@tonic-gate 
695734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(1) + SHA1_CONST(0); /* 1 */
6967c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
6977c478bd9Sstevel@tonic-gate 
698734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(2) + SHA1_CONST(0); /* 2 */
6997c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
7007c478bd9Sstevel@tonic-gate 
701734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(3) + SHA1_CONST(0); /* 3 */
7027c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
7037c478bd9Sstevel@tonic-gate 
704734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(4) + SHA1_CONST(0); /* 4 */
7057c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
7067c478bd9Sstevel@tonic-gate 
707734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(5) + SHA1_CONST(0); /* 5 */
7087c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
7097c478bd9Sstevel@tonic-gate 
710734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(6) + SHA1_CONST(0); /* 6 */
7117c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
7127c478bd9Sstevel@tonic-gate 
713734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(7) + SHA1_CONST(0); /* 7 */
7147c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
7157c478bd9Sstevel@tonic-gate 
716734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(8) + SHA1_CONST(0); /* 8 */
7177c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
7187c478bd9Sstevel@tonic-gate 
719734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(9) + SHA1_CONST(0); /* 9 */
7207c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
7217c478bd9Sstevel@tonic-gate 
722734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(10) + SHA1_CONST(0); /* 10 */
7237c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
7247c478bd9Sstevel@tonic-gate 
725734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(11) + SHA1_CONST(0); /* 11 */
7267c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
7277c478bd9Sstevel@tonic-gate 
728734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(12) + SHA1_CONST(0); /* 12 */
7297c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
7307c478bd9Sstevel@tonic-gate 
731734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(13) + SHA1_CONST(0); /* 13 */
7327c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
7337c478bd9Sstevel@tonic-gate 
734734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(14) + SHA1_CONST(0); /* 14 */
7357c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
7367c478bd9Sstevel@tonic-gate 
737734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(15) + SHA1_CONST(0); /* 15 */
7387c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
7397c478bd9Sstevel@tonic-gate 
740734b6a94Sdarrenm 	W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1);		/* 16 */
741734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(0) + SHA1_CONST(0);
7427c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
7437c478bd9Sstevel@tonic-gate 
744734b6a94Sdarrenm 	W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1);		/* 17 */
745734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(1) + SHA1_CONST(0);
7467c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
7477c478bd9Sstevel@tonic-gate 
748734b6a94Sdarrenm 	W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1);	/* 18 */
749734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(2) + SHA1_CONST(0);
7507c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
7517c478bd9Sstevel@tonic-gate 
752734b6a94Sdarrenm 	W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1);		/* 19 */
753734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(3) + SHA1_CONST(0);
7547c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/* round 2 */
757734b6a94Sdarrenm 	W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1);		/* 20 */
758734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(4) + SHA1_CONST(1);
7597c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
7607c478bd9Sstevel@tonic-gate 
761734b6a94Sdarrenm 	W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1);		/* 21 */
762734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(5) + SHA1_CONST(1);
7637c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
7647c478bd9Sstevel@tonic-gate 
765734b6a94Sdarrenm 	W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1);		/* 22 */
766734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(6) + SHA1_CONST(1);
7677c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
7687c478bd9Sstevel@tonic-gate 
769734b6a94Sdarrenm 	W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1);		/* 23 */
770734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(7) + SHA1_CONST(1);
7717c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
7727c478bd9Sstevel@tonic-gate 
773734b6a94Sdarrenm 	W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1);		/* 24 */
774734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(8) + SHA1_CONST(1);
7757c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
7767c478bd9Sstevel@tonic-gate 
777734b6a94Sdarrenm 	W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1);		/* 25 */
778734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(9) + SHA1_CONST(1);
7797c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
7807c478bd9Sstevel@tonic-gate 
781734b6a94Sdarrenm 	W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1);	/* 26 */
782734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(10) + SHA1_CONST(1);
7837c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
7847c478bd9Sstevel@tonic-gate 
785734b6a94Sdarrenm 	W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1);	/* 27 */
786734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(11) + SHA1_CONST(1);
7877c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
7887c478bd9Sstevel@tonic-gate 
789734b6a94Sdarrenm 	W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1);	/* 28 */
790734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(12) + SHA1_CONST(1);
7917c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
7927c478bd9Sstevel@tonic-gate 
793734b6a94Sdarrenm 	W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1);	/* 29 */
794734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(13) + SHA1_CONST(1);
7957c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
7967c478bd9Sstevel@tonic-gate 
797734b6a94Sdarrenm 	W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1);	/* 30 */
798734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(14) + SHA1_CONST(1);
7997c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
8007c478bd9Sstevel@tonic-gate 
801734b6a94Sdarrenm 	W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1);	/* 31 */
802734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(15) + SHA1_CONST(1);
8037c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
8047c478bd9Sstevel@tonic-gate 
805734b6a94Sdarrenm 	W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1);		/* 32 */
806734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(0) + SHA1_CONST(1);
8077c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
8087c478bd9Sstevel@tonic-gate 
809734b6a94Sdarrenm 	W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1);		/* 33 */
810734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(1) + SHA1_CONST(1);
8117c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
8127c478bd9Sstevel@tonic-gate 
813734b6a94Sdarrenm 	W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1);	/* 34 */
814734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(2) + SHA1_CONST(1);
8157c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
8167c478bd9Sstevel@tonic-gate 
817734b6a94Sdarrenm 	W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1);		/* 35 */
818734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(3) + SHA1_CONST(1);
8197c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
8207c478bd9Sstevel@tonic-gate 
821734b6a94Sdarrenm 	W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1);		/* 36 */
822734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(4) + SHA1_CONST(1);
8237c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
8247c478bd9Sstevel@tonic-gate 
825734b6a94Sdarrenm 	W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1);		/* 37 */
826734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(5) + SHA1_CONST(1);
8277c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
8287c478bd9Sstevel@tonic-gate 
829734b6a94Sdarrenm 	W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1);		/* 38 */
830734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(6) + SHA1_CONST(1);
8317c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
8327c478bd9Sstevel@tonic-gate 
833734b6a94Sdarrenm 	W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1);		/* 39 */
834734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(7) + SHA1_CONST(1);
8357c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 	/* round 3 */
838734b6a94Sdarrenm 	W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1);		/* 40 */
839734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(8) + SHA1_CONST(2);
8407c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
8417c478bd9Sstevel@tonic-gate 
842734b6a94Sdarrenm 	W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1);		/* 41 */
843734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(9) + SHA1_CONST(2);
8447c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
8457c478bd9Sstevel@tonic-gate 
846734b6a94Sdarrenm 	W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1);	/* 42 */
847734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(10) + SHA1_CONST(2);
8487c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
8497c478bd9Sstevel@tonic-gate 
850734b6a94Sdarrenm 	W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1);	/* 43 */
851734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(11) + SHA1_CONST(2);
8527c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
8537c478bd9Sstevel@tonic-gate 
854734b6a94Sdarrenm 	W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1);	/* 44 */
855734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(12) + SHA1_CONST(2);
8567c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
8577c478bd9Sstevel@tonic-gate 
858734b6a94Sdarrenm 	W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1);	/* 45 */
859734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(13) + SHA1_CONST(2);
8607c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
8617c478bd9Sstevel@tonic-gate 
862734b6a94Sdarrenm 	W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1);	/* 46 */
863734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(14) + SHA1_CONST(2);
8647c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
8657c478bd9Sstevel@tonic-gate 
866734b6a94Sdarrenm 	W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1);	/* 47 */
867734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(15) + SHA1_CONST(2);
8687c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
8697c478bd9Sstevel@tonic-gate 
870734b6a94Sdarrenm 	W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1);		/* 48 */
871734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(0) + SHA1_CONST(2);
8727c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
8737c478bd9Sstevel@tonic-gate 
874734b6a94Sdarrenm 	W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1);		/* 49 */
875734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(1) + SHA1_CONST(2);
8767c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
8777c478bd9Sstevel@tonic-gate 
878734b6a94Sdarrenm 	W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1);	/* 50 */
879734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(2) + SHA1_CONST(2);
8807c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
8817c478bd9Sstevel@tonic-gate 
882734b6a94Sdarrenm 	W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1);		/* 51 */
883734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(3) + SHA1_CONST(2);
8847c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
8857c478bd9Sstevel@tonic-gate 
886734b6a94Sdarrenm 	W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1);		/* 52 */
887734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(4) + SHA1_CONST(2);
8887c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
8897c478bd9Sstevel@tonic-gate 
890734b6a94Sdarrenm 	W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1);		/* 53 */
891734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(5) + SHA1_CONST(2);
8927c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
8937c478bd9Sstevel@tonic-gate 
894734b6a94Sdarrenm 	W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1);		/* 54 */
895734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(6) + SHA1_CONST(2);
8967c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
8977c478bd9Sstevel@tonic-gate 
898734b6a94Sdarrenm 	W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1);		/* 55 */
899734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(7) + SHA1_CONST(2);
9007c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
9017c478bd9Sstevel@tonic-gate 
902734b6a94Sdarrenm 	W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1);		/* 56 */
903734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(8) + SHA1_CONST(2);
9047c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
9057c478bd9Sstevel@tonic-gate 
906734b6a94Sdarrenm 	W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1);		/* 57 */
907734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(9) + SHA1_CONST(2);
9087c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
9097c478bd9Sstevel@tonic-gate 
910734b6a94Sdarrenm 	W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1);	/* 58 */
911734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(10) + SHA1_CONST(2);
9127c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
9137c478bd9Sstevel@tonic-gate 
914734b6a94Sdarrenm 	W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1);	/* 59 */
915734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(11) + SHA1_CONST(2);
9167c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 	/* round 4 */
919734b6a94Sdarrenm 	W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1);	/* 60 */
920734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(12) + SHA1_CONST(3);
9217c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
9227c478bd9Sstevel@tonic-gate 
923734b6a94Sdarrenm 	W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1);	/* 61 */
924734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(13) + SHA1_CONST(3);
9257c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
9267c478bd9Sstevel@tonic-gate 
927734b6a94Sdarrenm 	W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1);	/* 62 */
928734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(14) + SHA1_CONST(3);
9297c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
9307c478bd9Sstevel@tonic-gate 
931734b6a94Sdarrenm 	W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1);	/* 63 */
932734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(15) + SHA1_CONST(3);
9337c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
9347c478bd9Sstevel@tonic-gate 
935734b6a94Sdarrenm 	W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1);		/* 64 */
936734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(0) + SHA1_CONST(3);
9377c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
9387c478bd9Sstevel@tonic-gate 
939734b6a94Sdarrenm 	W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1);		/* 65 */
940734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(1) + SHA1_CONST(3);
9417c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
9427c478bd9Sstevel@tonic-gate 
943734b6a94Sdarrenm 	W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1);	/* 66 */
944734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(2) + SHA1_CONST(3);
9457c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
9467c478bd9Sstevel@tonic-gate 
947734b6a94Sdarrenm 	W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1);		/* 67 */
948734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(3) + SHA1_CONST(3);
9497c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
9507c478bd9Sstevel@tonic-gate 
951734b6a94Sdarrenm 	W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1);		/* 68 */
952734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(4) + SHA1_CONST(3);
9537c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
9547c478bd9Sstevel@tonic-gate 
955734b6a94Sdarrenm 	W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1);		/* 69 */
956734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(5) + SHA1_CONST(3);
9577c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
9587c478bd9Sstevel@tonic-gate 
959734b6a94Sdarrenm 	W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1);		/* 70 */
960734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(6) + SHA1_CONST(3);
9617c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
9627c478bd9Sstevel@tonic-gate 
963734b6a94Sdarrenm 	W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1);		/* 71 */
964734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(7) + SHA1_CONST(3);
9657c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
9667c478bd9Sstevel@tonic-gate 
967734b6a94Sdarrenm 	W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1);		/* 72 */
968734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(8) + SHA1_CONST(3);
9697c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
9707c478bd9Sstevel@tonic-gate 
971734b6a94Sdarrenm 	W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1);		/* 73 */
972734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(9) + SHA1_CONST(3);
9737c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
9747c478bd9Sstevel@tonic-gate 
975734b6a94Sdarrenm 	W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1);	/* 74 */
976734b6a94Sdarrenm 	a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(10) + SHA1_CONST(3);
9777c478bd9Sstevel@tonic-gate 	c = ROTATE_LEFT(c, 30);
9787c478bd9Sstevel@tonic-gate 
979734b6a94Sdarrenm 	W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1);	/* 75 */
980734b6a94Sdarrenm 	e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(11) + SHA1_CONST(3);
9817c478bd9Sstevel@tonic-gate 	b = ROTATE_LEFT(b, 30);
9827c478bd9Sstevel@tonic-gate 
983734b6a94Sdarrenm 	W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1);	/* 76 */
984734b6a94Sdarrenm 	d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(12) + SHA1_CONST(3);
9857c478bd9Sstevel@tonic-gate 	a = ROTATE_LEFT(a, 30);
9867c478bd9Sstevel@tonic-gate 
987734b6a94Sdarrenm 	W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1);	/* 77 */
988734b6a94Sdarrenm 	c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(13) + SHA1_CONST(3);
9897c478bd9Sstevel@tonic-gate 	e = ROTATE_LEFT(e, 30);
9907c478bd9Sstevel@tonic-gate 
991734b6a94Sdarrenm 	W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1);	/* 78 */
992734b6a94Sdarrenm 	b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(14) + SHA1_CONST(3);
9937c478bd9Sstevel@tonic-gate 	d = ROTATE_LEFT(d, 30);
9947c478bd9Sstevel@tonic-gate 
995734b6a94Sdarrenm 	W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1);	/* 79 */
9967c478bd9Sstevel@tonic-gate 
997734b6a94Sdarrenm 	ctx->state[0] += ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(15) +
9987c478bd9Sstevel@tonic-gate 	    SHA1_CONST(3);
9997c478bd9Sstevel@tonic-gate 	ctx->state[1] += b;
10007c478bd9Sstevel@tonic-gate 	ctx->state[2] += ROTATE_LEFT(c, 30);
10017c478bd9Sstevel@tonic-gate 	ctx->state[3] += d;
10027c478bd9Sstevel@tonic-gate 	ctx->state[4] += e;
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	/* zeroize sensitive information */
1005734b6a94Sdarrenm 	W(0) = W(1) = W(2) = W(3) = W(4) = W(5) = W(6) = W(7) = W(8) = 0;
1006734b6a94Sdarrenm 	W(9) = W(10) = W(11) = W(12) = W(13) = W(14) = W(15) = 0;
10077c478bd9Sstevel@tonic-gate }
1008*321502cdSda73024 #endif	/* !__amd64 */
1009*321502cdSda73024 
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate /*
10127c478bd9Sstevel@tonic-gate  * Encode()
10137c478bd9Sstevel@tonic-gate  *
10147c478bd9Sstevel@tonic-gate  * purpose: to convert a list of numbers from little endian to big endian
10157c478bd9Sstevel@tonic-gate  *   input: uint8_t *	: place to store the converted big endian numbers
10167c478bd9Sstevel@tonic-gate  *	    uint32_t *	: place to get numbers to convert from
10177c478bd9Sstevel@tonic-gate  *          size_t	: the length of the input in bytes
10187c478bd9Sstevel@tonic-gate  *  output: void
10197c478bd9Sstevel@tonic-gate  */
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate static void
1022734b6a94Sdarrenm Encode(uint8_t *_RESTRICT_KYWD output, const uint32_t *_RESTRICT_KYWD input,
1023734b6a94Sdarrenm     size_t len)
10247c478bd9Sstevel@tonic-gate {
10257c478bd9Sstevel@tonic-gate 	size_t		i, j;
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate #if	defined(__sparc)
10287c478bd9Sstevel@tonic-gate 	if (IS_P2ALIGNED(output, sizeof (uint32_t))) {
10297c478bd9Sstevel@tonic-gate 		for (i = 0, j = 0; j < len; i++, j += 4) {
10307c478bd9Sstevel@tonic-gate 			/* LINTED: pointer alignment */
10317c478bd9Sstevel@tonic-gate 			*((uint32_t *)(output + j)) = input[i];
10327c478bd9Sstevel@tonic-gate 		}
10337c478bd9Sstevel@tonic-gate 	} else {
10347c478bd9Sstevel@tonic-gate #endif	/* little endian -- will work on big endian, but slowly */
10357c478bd9Sstevel@tonic-gate 		for (i = 0, j = 0; j < len; i++, j += 4) {
10367c478bd9Sstevel@tonic-gate 			output[j]	= (input[i] >> 24) & 0xff;
10377c478bd9Sstevel@tonic-gate 			output[j + 1]	= (input[i] >> 16) & 0xff;
10387c478bd9Sstevel@tonic-gate 			output[j + 2]	= (input[i] >>  8) & 0xff;
10397c478bd9Sstevel@tonic-gate 			output[j + 3]	= input[i] & 0xff;
10407c478bd9Sstevel@tonic-gate 		}
10417c478bd9Sstevel@tonic-gate #if	defined(__sparc)
10427c478bd9Sstevel@tonic-gate 	}
10437c478bd9Sstevel@tonic-gate #endif
10447c478bd9Sstevel@tonic-gate }
1045