17c478bd9Sstevel@tonic-gate /*
28de5c4f4SDan OpenSolaris Anderson * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate * The basic framework for this code came from the reference
87c478bd9Sstevel@tonic-gate * implementation for MD5. That implementation is Copyright (C)
97c478bd9Sstevel@tonic-gate * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
107c478bd9Sstevel@tonic-gate *
117c478bd9Sstevel@tonic-gate * License to copy and use this software is granted provided that it
127c478bd9Sstevel@tonic-gate * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
137c478bd9Sstevel@tonic-gate * Algorithm" in all material mentioning or referencing this software
147c478bd9Sstevel@tonic-gate * or this function.
157c478bd9Sstevel@tonic-gate *
167c478bd9Sstevel@tonic-gate * License is also granted to make and use derivative works provided
177c478bd9Sstevel@tonic-gate * that such works are identified as "derived from the RSA Data
187c478bd9Sstevel@tonic-gate * Security, Inc. MD5 Message-Digest Algorithm" in all material
197c478bd9Sstevel@tonic-gate * mentioning or referencing the derived work.
207c478bd9Sstevel@tonic-gate *
217c478bd9Sstevel@tonic-gate * RSA Data Security, Inc. makes no representations concerning either
227c478bd9Sstevel@tonic-gate * the merchantability of this software or the suitability of this
237c478bd9Sstevel@tonic-gate * software for any particular purpose. It is provided "as is"
247c478bd9Sstevel@tonic-gate * without express or implied warranty of any kind.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate * These notices must be retained in any copies of any part of this
277c478bd9Sstevel@tonic-gate * documentation and/or software.
287c478bd9Sstevel@tonic-gate *
297c478bd9Sstevel@tonic-gate * NOTE: Cleaned-up and optimized, version of SHA1, based on the FIPS 180-1
304b56a003SDaniel Anderson * standard, available at http://www.itl.nist.gov/fipspubs/fip180-1.htm
317c478bd9Sstevel@tonic-gate * Not as fast as one would like -- further optimizations are encouraged
327c478bd9Sstevel@tonic-gate * and appreciated.
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate
3503fe8edeSToomas Soome #if defined(_STANDALONE)
3603fe8edeSToomas Soome #include <sys/cdefs.h>
3703fe8edeSToomas Soome #define _RESTRICT_KYWD restrict
3803fe8edeSToomas Soome #else
39e65d07eeSKeith Wesolowski #if !defined(_KERNEL) && !defined(_BOOT)
408de5c4f4SDan OpenSolaris Anderson #include <stdint.h>
418de5c4f4SDan OpenSolaris Anderson #include <strings.h>
428de5c4f4SDan OpenSolaris Anderson #include <stdlib.h>
438de5c4f4SDan OpenSolaris Anderson #include <errno.h>
448de5c4f4SDan OpenSolaris Anderson #include <sys/systeminfo.h>
45e65d07eeSKeith Wesolowski #endif /* !_KERNEL && !_BOOT */
4603fe8edeSToomas Soome #endif /* _STANDALONE */
478de5c4f4SDan OpenSolaris Anderson
487c478bd9Sstevel@tonic-gate #include <sys/types.h>
497c478bd9Sstevel@tonic-gate #include <sys/param.h>
507c478bd9Sstevel@tonic-gate #include <sys/systm.h>
517c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
527c478bd9Sstevel@tonic-gate #include <sys/sha1.h>
537c478bd9Sstevel@tonic-gate #include <sys/sha1_consts.h>
547c478bd9Sstevel@tonic-gate
5503fe8edeSToomas Soome #if defined(_STANDALONE)
5603fe8edeSToomas Soome #include <sys/endian.h>
5703fe8edeSToomas Soome #define HAVE_HTONL
5803fe8edeSToomas Soome #if _BYTE_ORDER == _LITTLE_ENDIAN
5903fe8edeSToomas Soome #undef _BIG_ENDIAN
6003fe8edeSToomas Soome #else
6103fe8edeSToomas Soome #undef _LITTLE_ENDIAN
6203fe8edeSToomas Soome #endif
6303fe8edeSToomas Soome #else
644b56a003SDaniel Anderson #ifdef _LITTLE_ENDIAN
654b56a003SDaniel Anderson #include <sys/byteorder.h>
664b56a003SDaniel Anderson #define HAVE_HTONL
674b56a003SDaniel Anderson #endif
6803fe8edeSToomas Soome #endif /* _STANDALONE */
694b56a003SDaniel Anderson
70e65d07eeSKeith Wesolowski #ifdef _BOOT
71e65d07eeSKeith Wesolowski #define bcopy(_s, _d, _l) ((void) memcpy((_d), (_s), (_l)))
72e65d07eeSKeith Wesolowski #define bzero(_m, _l) ((void) memset((_m), 0, (_l)))
73e65d07eeSKeith Wesolowski #endif
74e65d07eeSKeith Wesolowski
75734b6a94Sdarrenm static void Encode(uint8_t *, const uint32_t *, size_t);
767c478bd9Sstevel@tonic-gate
77734b6a94Sdarrenm #if defined(__sparc)
787c478bd9Sstevel@tonic-gate
79734b6a94Sdarrenm #define SHA1_TRANSFORM(ctx, in) \
80734b6a94Sdarrenm SHA1Transform((ctx)->state[0], (ctx)->state[1], (ctx)->state[2], \
81734b6a94Sdarrenm (ctx)->state[3], (ctx)->state[4], (ctx), (in))
827c478bd9Sstevel@tonic-gate
83734b6a94Sdarrenm static void SHA1Transform(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
845aaf65b1SToomas Soome SHA1_CTX *, const uint8_t [64]);
857c478bd9Sstevel@tonic-gate
86321502cdSda #elif defined(__amd64)
87321502cdSda
88321502cdSda #define SHA1_TRANSFORM(ctx, in) sha1_block_data_order((ctx), (in), 1)
89321502cdSda #define SHA1_TRANSFORM_BLOCKS(ctx, in, num) sha1_block_data_order((ctx), \
90321502cdSda (in), (num))
91321502cdSda
92321502cdSda void sha1_block_data_order(SHA1_CTX *ctx, const void *inpp, size_t num_blocks);
93321502cdSda
94734b6a94Sdarrenm #else
957c478bd9Sstevel@tonic-gate
96734b6a94Sdarrenm #define SHA1_TRANSFORM(ctx, in) SHA1Transform((ctx), (in))
977c478bd9Sstevel@tonic-gate
985aaf65b1SToomas Soome static void SHA1Transform(SHA1_CTX *, const uint8_t [64]);
997c478bd9Sstevel@tonic-gate
100734b6a94Sdarrenm #endif
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate
103734b6a94Sdarrenm static uint8_t PADDING[64] = { 0x80, /* all zeros */ };
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate /*
106734b6a94Sdarrenm * F, G, and H are the basic SHA1 functions.
1077c478bd9Sstevel@tonic-gate */
108734b6a94Sdarrenm #define F(b, c, d) (((b) & (c)) | ((~b) & (d)))
109734b6a94Sdarrenm #define G(b, c, d) ((b) ^ (c) ^ (d))
110734b6a94Sdarrenm #define H(b, c, d) (((b) & (c)) | (((b)|(c)) & (d)))
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate * SHA1Init()
1147c478bd9Sstevel@tonic-gate *
1157c478bd9Sstevel@tonic-gate * purpose: initializes the sha1 context and begins and sha1 digest operation
1167c478bd9Sstevel@tonic-gate * input: SHA1_CTX * : the context to initializes.
1177c478bd9Sstevel@tonic-gate * output: void
1187c478bd9Sstevel@tonic-gate */
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate void
SHA1Init(SHA1_CTX * ctx)1217c478bd9Sstevel@tonic-gate SHA1Init(SHA1_CTX *ctx)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate ctx->count[0] = ctx->count[1] = 0;
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate * load magic initialization constants. Tell lint
1277c478bd9Sstevel@tonic-gate * that these constants are unsigned by using U.
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate ctx->state[0] = 0x67452301U;
1317c478bd9Sstevel@tonic-gate ctx->state[1] = 0xefcdab89U;
1327c478bd9Sstevel@tonic-gate ctx->state[2] = 0x98badcfeU;
1337c478bd9Sstevel@tonic-gate ctx->state[3] = 0x10325476U;
1347c478bd9Sstevel@tonic-gate ctx->state[4] = 0xc3d2e1f0U;
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate #ifdef VIS_SHA1
1387c478bd9Sstevel@tonic-gate #ifdef _KERNEL
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate #include <sys/regset.h>
1417c478bd9Sstevel@tonic-gate #include <sys/vis.h>
14215b9cbbcSkrishna #include <sys/fpu/fpusystm.h>
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate /* the alignment for block stores to save fp registers */
1457c478bd9Sstevel@tonic-gate #define VIS_ALIGN (64)
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate extern int sha1_savefp(kfpu_t *, int);
1487c478bd9Sstevel@tonic-gate extern void sha1_restorefp(kfpu_t *);
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate uint32_t vis_sha1_svfp_threshold = 128;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate * VIS SHA-1 consts.
1567c478bd9Sstevel@tonic-gate */
1577c478bd9Sstevel@tonic-gate static uint64_t VIS[] = {
1584cc1ac68Skrishna 0x8000000080000000ULL,
1594cc1ac68Skrishna 0x0002000200020002ULL,
1604cc1ac68Skrishna 0x5a8279996ed9eba1ULL,
1614cc1ac68Skrishna 0x8f1bbcdcca62c1d6ULL,
1624cc1ac68Skrishna 0x012389ab456789abULL};
1637c478bd9Sstevel@tonic-gate
164734b6a94Sdarrenm extern void SHA1TransformVIS(uint64_t *, uint32_t *, uint32_t *, uint64_t *);
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * SHA1Update()
1697c478bd9Sstevel@tonic-gate *
1707c478bd9Sstevel@tonic-gate * purpose: continues an sha1 digest operation, using the message block
1717c478bd9Sstevel@tonic-gate * to update the context.
1727c478bd9Sstevel@tonic-gate * input: SHA1_CTX * : the context to update
173734b6a94Sdarrenm * void * : the message block
174734b6a94Sdarrenm * size_t : the length of the message block in bytes
1757c478bd9Sstevel@tonic-gate * output: void
1767c478bd9Sstevel@tonic-gate */
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate void
SHA1Update(SHA1_CTX * ctx,const void * inptr,size_t input_len)179734b6a94Sdarrenm SHA1Update(SHA1_CTX *ctx, const void *inptr, size_t input_len)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate uint32_t i, buf_index, buf_len;
1827c478bd9Sstevel@tonic-gate uint64_t X0[40], input64[8];
183734b6a94Sdarrenm const uint8_t *input = inptr;
18415b9cbbcSkrishna #ifdef _KERNEL
18515b9cbbcSkrishna int usevis = 0;
186734b6a94Sdarrenm #else
187734b6a94Sdarrenm int usevis = 1;
18815b9cbbcSkrishna #endif /* _KERNEL */
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate /* check for noop */
1917c478bd9Sstevel@tonic-gate if (input_len == 0)
1927c478bd9Sstevel@tonic-gate return;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate /* compute number of bytes mod 64 */
1957c478bd9Sstevel@tonic-gate buf_index = (ctx->count[1] >> 3) & 0x3F;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /* update number of bits */
1987c478bd9Sstevel@tonic-gate if ((ctx->count[1] += (input_len << 3)) < (input_len << 3))
1997c478bd9Sstevel@tonic-gate ctx->count[0]++;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate ctx->count[0] += (input_len >> 29);
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate buf_len = 64 - buf_index;
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate /* transform as many times as possible */
2067c478bd9Sstevel@tonic-gate i = 0;
2077c478bd9Sstevel@tonic-gate if (input_len >= buf_len) {
2087c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2097c478bd9Sstevel@tonic-gate kfpu_t *fpu;
210734b6a94Sdarrenm if (fpu_exists) {
211734b6a94Sdarrenm uint8_t fpua[sizeof (kfpu_t) + GSR_SIZE + VIS_ALIGN];
212734b6a94Sdarrenm uint32_t len = (input_len + buf_index) & ~0x3f;
213734b6a94Sdarrenm int svfp_ok;
214734b6a94Sdarrenm
215734b6a94Sdarrenm fpu = (kfpu_t *)P2ROUNDUP((uintptr_t)fpua, 64);
216734b6a94Sdarrenm svfp_ok = ((len >= vis_sha1_svfp_threshold) ? 1 : 0);
217734b6a94Sdarrenm usevis = fpu_exists && sha1_savefp(fpu, svfp_ok);
218734b6a94Sdarrenm } else {
219734b6a94Sdarrenm usevis = 0;
220734b6a94Sdarrenm }
2217c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate * general optimization:
2257c478bd9Sstevel@tonic-gate *
2267c478bd9Sstevel@tonic-gate * only do initial bcopy() and SHA1Transform() if
2277c478bd9Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just
2287c478bd9Sstevel@tonic-gate * wasting our time doing the bcopy() since there
2297c478bd9Sstevel@tonic-gate * wasn't any data left over from a previous call to
2307c478bd9Sstevel@tonic-gate * SHA1Update().
2317c478bd9Sstevel@tonic-gate */
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if (buf_index) {
2347c478bd9Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len);
2357c478bd9Sstevel@tonic-gate if (usevis) {
2367c478bd9Sstevel@tonic-gate SHA1TransformVIS(X0,
237734b6a94Sdarrenm ctx->buf_un.buf32,
2387c478bd9Sstevel@tonic-gate &ctx->state[0], VIS);
2397c478bd9Sstevel@tonic-gate } else {
240734b6a94Sdarrenm SHA1_TRANSFORM(ctx, ctx->buf_un.buf8);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate i = buf_len;
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * VIS SHA-1: uses the VIS 1.0 instructions to accelerate
2477c478bd9Sstevel@tonic-gate * SHA-1 processing. This is achieved by "offloading" the
2487c478bd9Sstevel@tonic-gate * computation of the message schedule (MS) to the VIS units.
2497c478bd9Sstevel@tonic-gate * This allows the VIS computation of the message schedule
2507c478bd9Sstevel@tonic-gate * to be performed in parallel with the standard integer
2517c478bd9Sstevel@tonic-gate * processing of the remainder of the SHA-1 computation.
2527c478bd9Sstevel@tonic-gate * performance by up to around 1.37X, compared to an optimized
2537c478bd9Sstevel@tonic-gate * integer-only implementation.
2547c478bd9Sstevel@tonic-gate *
2557c478bd9Sstevel@tonic-gate * The VIS implementation of SHA1Transform has a different API
2567c478bd9Sstevel@tonic-gate * to the standard integer version:
2577c478bd9Sstevel@tonic-gate *
2587c478bd9Sstevel@tonic-gate * void SHA1TransformVIS(
2597c478bd9Sstevel@tonic-gate * uint64_t *, // Pointer to MS for ith block
260734b6a94Sdarrenm * uint32_t *, // Pointer to ith block of message data
2617c478bd9Sstevel@tonic-gate * uint32_t *, // Pointer to SHA state i.e ctx->state
2627c478bd9Sstevel@tonic-gate * uint64_t *, // Pointer to various VIS constants
2637c478bd9Sstevel@tonic-gate * )
2647c478bd9Sstevel@tonic-gate *
2657c478bd9Sstevel@tonic-gate * Note: the message data must by 4-byte aligned.
2667c478bd9Sstevel@tonic-gate *
2677c478bd9Sstevel@tonic-gate * Function requires VIS 1.0 support.
2687c478bd9Sstevel@tonic-gate *
2697c478bd9Sstevel@tonic-gate * Handling is provided to deal with arbitrary byte alingment
2707c478bd9Sstevel@tonic-gate * of the input data but the performance gains are reduced
2717c478bd9Sstevel@tonic-gate * for alignments other than 4-bytes.
2727c478bd9Sstevel@tonic-gate */
2737c478bd9Sstevel@tonic-gate if (usevis) {
274734b6a94Sdarrenm if (!IS_P2ALIGNED(&input[i], sizeof (uint32_t))) {
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * Main processing loop - input misaligned
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) {
279321502cdSda bcopy(&input[i], input64, 64);
280321502cdSda SHA1TransformVIS(X0,
281321502cdSda (uint32_t *)input64,
282321502cdSda &ctx->state[0], VIS);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate } else {
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * Main processing loop - input 8-byte aligned
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) {
2897c478bd9Sstevel@tonic-gate SHA1TransformVIS(X0,
2904b56a003SDaniel Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
2914b56a003SDaniel Anderson (uint32_t *)&input[i], /* CSTYLED */
2927c478bd9Sstevel@tonic-gate &ctx->state[0], VIS);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2977c478bd9Sstevel@tonic-gate sha1_restorefp(fpu);
2987c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2997c478bd9Sstevel@tonic-gate } else {
3007c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) {
301321502cdSda SHA1_TRANSFORM(ctx, &input[i]);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate /*
3067c478bd9Sstevel@tonic-gate * general optimization:
3077c478bd9Sstevel@tonic-gate *
3087c478bd9Sstevel@tonic-gate * if i and input_len are the same, return now instead
3097c478bd9Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case
3107c478bd9Sstevel@tonic-gate * will be an expensive nop.
3117c478bd9Sstevel@tonic-gate */
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate if (input_len == i)
3147c478bd9Sstevel@tonic-gate return;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate buf_index = 0;
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /* buffer remaining input */
3207c478bd9Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate #else /* VIS_SHA1 */
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate void
SHA1Update(SHA1_CTX * ctx,const void * inptr,size_t input_len)326734b6a94Sdarrenm SHA1Update(SHA1_CTX *ctx, const void *inptr, size_t input_len)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate uint32_t i, buf_index, buf_len;
329734b6a94Sdarrenm const uint8_t *input = inptr;
330321502cdSda #if defined(__amd64)
331321502cdSda uint32_t block_count;
332321502cdSda #endif /* __amd64 */
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate /* check for noop */
3357c478bd9Sstevel@tonic-gate if (input_len == 0)
3367c478bd9Sstevel@tonic-gate return;
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate /* compute number of bytes mod 64 */
3397c478bd9Sstevel@tonic-gate buf_index = (ctx->count[1] >> 3) & 0x3F;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate /* update number of bits */
3427c478bd9Sstevel@tonic-gate if ((ctx->count[1] += (input_len << 3)) < (input_len << 3))
3437c478bd9Sstevel@tonic-gate ctx->count[0]++;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate ctx->count[0] += (input_len >> 29);
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate buf_len = 64 - buf_index;
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /* transform as many times as possible */
3507c478bd9Sstevel@tonic-gate i = 0;
3517c478bd9Sstevel@tonic-gate if (input_len >= buf_len) {
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate * general optimization:
3557c478bd9Sstevel@tonic-gate *
3567c478bd9Sstevel@tonic-gate * only do initial bcopy() and SHA1Transform() if
3577c478bd9Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just
3587c478bd9Sstevel@tonic-gate * wasting our time doing the bcopy() since there
3597c478bd9Sstevel@tonic-gate * wasn't any data left over from a previous call to
3607c478bd9Sstevel@tonic-gate * SHA1Update().
3617c478bd9Sstevel@tonic-gate */
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate if (buf_index) {
3647c478bd9Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len);
365734b6a94Sdarrenm SHA1_TRANSFORM(ctx, ctx->buf_un.buf8);
3667c478bd9Sstevel@tonic-gate i = buf_len;
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
369321502cdSda #if !defined(__amd64)
3707c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64)
371734b6a94Sdarrenm SHA1_TRANSFORM(ctx, &input[i]);
372321502cdSda #else
373321502cdSda block_count = (input_len - i) >> 6;
374321502cdSda if (block_count > 0) {
375321502cdSda SHA1_TRANSFORM_BLOCKS(ctx, &input[i], block_count);
376321502cdSda i += block_count << 6;
377321502cdSda }
378321502cdSda #endif /* !__amd64 */
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate /*
3817c478bd9Sstevel@tonic-gate * general optimization:
3827c478bd9Sstevel@tonic-gate *
3837c478bd9Sstevel@tonic-gate * if i and input_len are the same, return now instead
3847c478bd9Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case
3857c478bd9Sstevel@tonic-gate * will be an expensive nop.
3867c478bd9Sstevel@tonic-gate */
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate if (input_len == i)
3897c478bd9Sstevel@tonic-gate return;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate buf_index = 0;
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate /* buffer remaining input */
3957c478bd9Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate #endif /* VIS_SHA1 */
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate /*
4017c478bd9Sstevel@tonic-gate * SHA1Final()
4027c478bd9Sstevel@tonic-gate *
4037c478bd9Sstevel@tonic-gate * purpose: ends an sha1 digest operation, finalizing the message digest and
4047c478bd9Sstevel@tonic-gate * zeroing the context.
405321502cdSda * input: uchar_t * : A buffer to store the digest.
4065151fb12Sdarrenm * : The function actually uses void* because many
4075151fb12Sdarrenm * : callers pass things other than uchar_t here.
4087c478bd9Sstevel@tonic-gate * SHA1_CTX * : the context to finalize, save, and zero
4097c478bd9Sstevel@tonic-gate * output: void
4107c478bd9Sstevel@tonic-gate */
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate void
SHA1Final(void * digest,SHA1_CTX * ctx)413734b6a94Sdarrenm SHA1Final(void *digest, SHA1_CTX *ctx)
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate uint8_t bitcount_be[sizeof (ctx->count)];
4167c478bd9Sstevel@tonic-gate uint32_t index = (ctx->count[1] >> 3) & 0x3f;
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate /* store bit count, big endian */
4197c478bd9Sstevel@tonic-gate Encode(bitcount_be, ctx->count, sizeof (bitcount_be));
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate /* pad out to 56 mod 64 */
4227c478bd9Sstevel@tonic-gate SHA1Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index);
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate /* append length (before padding) */
4257c478bd9Sstevel@tonic-gate SHA1Update(ctx, bitcount_be, sizeof (bitcount_be));
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate /* store state in digest */
4287c478bd9Sstevel@tonic-gate Encode(digest, ctx->state, sizeof (ctx->state));
429673007c6Sdarrenm
430673007c6Sdarrenm /* zeroize sensitive information */
431673007c6Sdarrenm bzero(ctx, sizeof (*ctx));
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate
434321502cdSda
435321502cdSda #if !defined(__amd64)
436321502cdSda
437*067afcb3SToomas Soome /*
438*067afcb3SToomas Soome * ROTATE_LEFT rotates x left n bits.
439*067afcb3SToomas Soome */
440*067afcb3SToomas Soome
441*067afcb3SToomas Soome #if defined(__GNUC__) && defined(_LP64)
442*067afcb3SToomas Soome static __inline__ uint64_t
ROTATE_LEFT(uint64_t value,uint32_t n)443*067afcb3SToomas Soome ROTATE_LEFT(uint64_t value, uint32_t n)
444*067afcb3SToomas Soome {
445*067afcb3SToomas Soome uint32_t t32;
446*067afcb3SToomas Soome
447*067afcb3SToomas Soome t32 = (uint32_t)value;
448*067afcb3SToomas Soome return ((t32 << n) | (t32 >> (32 - n)));
449*067afcb3SToomas Soome }
450*067afcb3SToomas Soome
451*067afcb3SToomas Soome #else
452*067afcb3SToomas Soome #define ROTATE_LEFT(x, n) \
453*067afcb3SToomas Soome (((x) << (n)) | ((x) >> ((sizeof (x) * NBBY)-(n))))
454*067afcb3SToomas Soome #endif
455*067afcb3SToomas Soome
456734b6a94Sdarrenm typedef uint32_t sha1word;
457734b6a94Sdarrenm
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate * sparc optimization:
4607c478bd9Sstevel@tonic-gate *
4617c478bd9Sstevel@tonic-gate * on the sparc, we can load big endian 32-bit data easily. note that
4627c478bd9Sstevel@tonic-gate * special care must be taken to ensure the address is 32-bit aligned.
4637c478bd9Sstevel@tonic-gate * in the interest of speed, we don't check to make sure, since
4647c478bd9Sstevel@tonic-gate * careful programming can guarantee this for us.
4657c478bd9Sstevel@tonic-gate */
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate #if defined(_BIG_ENDIAN)
4687c478bd9Sstevel@tonic-gate #define LOAD_BIG_32(addr) (*(uint32_t *)(addr))
4697c478bd9Sstevel@tonic-gate
4704b56a003SDaniel Anderson #elif defined(HAVE_HTONL)
4714b56a003SDaniel Anderson #define LOAD_BIG_32(addr) htonl(*((uint32_t *)(addr)))
472734b6a94Sdarrenm
4734b56a003SDaniel Anderson #else
474734b6a94Sdarrenm /* little endian -- will work on big endian, but slowly */
4757c478bd9Sstevel@tonic-gate #define LOAD_BIG_32(addr) \
4767c478bd9Sstevel@tonic-gate (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3])
4774b56a003SDaniel Anderson #endif /* _BIG_ENDIAN */
478734b6a94Sdarrenm
479734b6a94Sdarrenm /*
480734b6a94Sdarrenm * SHA1Transform()
481734b6a94Sdarrenm */
482734b6a94Sdarrenm #if defined(W_ARRAY)
483734b6a94Sdarrenm #define W(n) w[n]
484734b6a94Sdarrenm #else /* !defined(W_ARRAY) */
485734b6a94Sdarrenm #define W(n) w_ ## n
486734b6a94Sdarrenm #endif /* !defined(W_ARRAY) */
487734b6a94Sdarrenm
488734b6a94Sdarrenm
489734b6a94Sdarrenm #if defined(__sparc)
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate * sparc register window optimization:
4937c478bd9Sstevel@tonic-gate *
4947c478bd9Sstevel@tonic-gate * `a', `b', `c', `d', and `e' are passed into SHA1Transform
4957c478bd9Sstevel@tonic-gate * explicitly since it increases the number of registers available to
4967c478bd9Sstevel@tonic-gate * the compiler. under this scheme, these variables can be held in
4977c478bd9Sstevel@tonic-gate * %i0 - %i4, which leaves more local and out registers available.
4987c478bd9Sstevel@tonic-gate *
4997c478bd9Sstevel@tonic-gate * purpose: sha1 transformation -- updates the digest based on `block'
5007c478bd9Sstevel@tonic-gate * input: uint32_t : bytes 1 - 4 of the digest
5017c478bd9Sstevel@tonic-gate * uint32_t : bytes 5 - 8 of the digest
5027c478bd9Sstevel@tonic-gate * uint32_t : bytes 9 - 12 of the digest
5037c478bd9Sstevel@tonic-gate * uint32_t : bytes 12 - 16 of the digest
5047c478bd9Sstevel@tonic-gate * uint32_t : bytes 16 - 20 of the digest
5057c478bd9Sstevel@tonic-gate * SHA1_CTX * : the context to update
5067c478bd9Sstevel@tonic-gate * uint8_t [64]: the block to use to update the digest
5077c478bd9Sstevel@tonic-gate * output: void
5087c478bd9Sstevel@tonic-gate */
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate void
SHA1Transform(uint32_t a,uint32_t b,uint32_t c,uint32_t d,uint32_t e,SHA1_CTX * ctx,const uint8_t blk[64])5117c478bd9Sstevel@tonic-gate SHA1Transform(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e,
5127c478bd9Sstevel@tonic-gate SHA1_CTX *ctx, const uint8_t blk[64])
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate /*
5157c478bd9Sstevel@tonic-gate * sparc optimization:
5167c478bd9Sstevel@tonic-gate *
5177c478bd9Sstevel@tonic-gate * while it is somewhat counter-intuitive, on sparc, it is
5187c478bd9Sstevel@tonic-gate * more efficient to place all the constants used in this
5197c478bd9Sstevel@tonic-gate * function in an array and load the values out of the array
5207c478bd9Sstevel@tonic-gate * than to manually load the constants. this is because
5217c478bd9Sstevel@tonic-gate * setting a register to a 32-bit value takes two ops in most
5227c478bd9Sstevel@tonic-gate * cases: a `sethi' and an `or', but loading a 32-bit value
5237c478bd9Sstevel@tonic-gate * from memory only takes one `ld' (or `lduw' on v9). while
5247c478bd9Sstevel@tonic-gate * this increases memory usage, the compiler can find enough
5257c478bd9Sstevel@tonic-gate * other things to do while waiting to keep the pipeline does
5267c478bd9Sstevel@tonic-gate * not stall. additionally, it is likely that many of these
5277c478bd9Sstevel@tonic-gate * constants are cached so that later accesses do not even go
5287c478bd9Sstevel@tonic-gate * out to the bus.
5297c478bd9Sstevel@tonic-gate *
5307c478bd9Sstevel@tonic-gate * this array is declared `static' to keep the compiler from
5317c478bd9Sstevel@tonic-gate * having to bcopy() this array onto the stack frame of
5327c478bd9Sstevel@tonic-gate * SHA1Transform() each time it is called -- which is
5337c478bd9Sstevel@tonic-gate * unacceptably expensive.
5347c478bd9Sstevel@tonic-gate *
5357c478bd9Sstevel@tonic-gate * the `const' is to ensure that callers are good citizens and
5367c478bd9Sstevel@tonic-gate * do not try to munge the array. since these routines are
5377c478bd9Sstevel@tonic-gate * going to be called from inside multithreaded kernelland,
5387c478bd9Sstevel@tonic-gate * this is a good safety check. -- `sha1_consts' will end up in
5397c478bd9Sstevel@tonic-gate * .rodata.
5407c478bd9Sstevel@tonic-gate *
5417c478bd9Sstevel@tonic-gate * unfortunately, loading from an array in this manner hurts
5424b56a003SDaniel Anderson * performance under Intel. So, there is a macro,
5437c478bd9Sstevel@tonic-gate * SHA1_CONST(), used in SHA1Transform(), that either expands to
5447c478bd9Sstevel@tonic-gate * a reference to this array, or to the actual constant,
5457c478bd9Sstevel@tonic-gate * depending on what platform this code is compiled for.
5467c478bd9Sstevel@tonic-gate */
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate static const uint32_t sha1_consts[] = {
5494b56a003SDaniel Anderson SHA1_CONST_0, SHA1_CONST_1, SHA1_CONST_2, SHA1_CONST_3
5507c478bd9Sstevel@tonic-gate };
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate * general optimization:
5547c478bd9Sstevel@tonic-gate *
5557c478bd9Sstevel@tonic-gate * use individual integers instead of using an array. this is a
5567c478bd9Sstevel@tonic-gate * win, although the amount it wins by seems to vary quite a bit.
5577c478bd9Sstevel@tonic-gate */
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate uint32_t w_0, w_1, w_2, w_3, w_4, w_5, w_6, w_7;
5607c478bd9Sstevel@tonic-gate uint32_t w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15;
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate * sparc optimization:
5647c478bd9Sstevel@tonic-gate *
5657c478bd9Sstevel@tonic-gate * if `block' is already aligned on a 4-byte boundary, use
5667c478bd9Sstevel@tonic-gate * LOAD_BIG_32() directly. otherwise, bcopy() into a
5677c478bd9Sstevel@tonic-gate * buffer that *is* aligned on a 4-byte boundary and then do
5687c478bd9Sstevel@tonic-gate * the LOAD_BIG_32() on that buffer. benchmarks have shown
5697c478bd9Sstevel@tonic-gate * that using the bcopy() is better than loading the bytes
5707c478bd9Sstevel@tonic-gate * individually and doing the endian-swap by hand.
5717c478bd9Sstevel@tonic-gate *
5727c478bd9Sstevel@tonic-gate * even though it's quite tempting to assign to do:
5737c478bd9Sstevel@tonic-gate *
5747c478bd9Sstevel@tonic-gate * blk = bcopy(ctx->buf_un.buf32, blk, sizeof (ctx->buf_un.buf32));
5757c478bd9Sstevel@tonic-gate *
5767c478bd9Sstevel@tonic-gate * and only have one set of LOAD_BIG_32()'s, the compiler
5777c478bd9Sstevel@tonic-gate * *does not* like that, so please resist the urge.
5787c478bd9Sstevel@tonic-gate */
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate if ((uintptr_t)blk & 0x3) { /* not 4-byte aligned? */
5817c478bd9Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32));
5827c478bd9Sstevel@tonic-gate w_15 = LOAD_BIG_32(ctx->buf_un.buf32 + 15);
5837c478bd9Sstevel@tonic-gate w_14 = LOAD_BIG_32(ctx->buf_un.buf32 + 14);
5847c478bd9Sstevel@tonic-gate w_13 = LOAD_BIG_32(ctx->buf_un.buf32 + 13);
5857c478bd9Sstevel@tonic-gate w_12 = LOAD_BIG_32(ctx->buf_un.buf32 + 12);
5867c478bd9Sstevel@tonic-gate w_11 = LOAD_BIG_32(ctx->buf_un.buf32 + 11);
5877c478bd9Sstevel@tonic-gate w_10 = LOAD_BIG_32(ctx->buf_un.buf32 + 10);
5887c478bd9Sstevel@tonic-gate w_9 = LOAD_BIG_32(ctx->buf_un.buf32 + 9);
5897c478bd9Sstevel@tonic-gate w_8 = LOAD_BIG_32(ctx->buf_un.buf32 + 8);
5907c478bd9Sstevel@tonic-gate w_7 = LOAD_BIG_32(ctx->buf_un.buf32 + 7);
5917c478bd9Sstevel@tonic-gate w_6 = LOAD_BIG_32(ctx->buf_un.buf32 + 6);
5927c478bd9Sstevel@tonic-gate w_5 = LOAD_BIG_32(ctx->buf_un.buf32 + 5);
5937c478bd9Sstevel@tonic-gate w_4 = LOAD_BIG_32(ctx->buf_un.buf32 + 4);
5947c478bd9Sstevel@tonic-gate w_3 = LOAD_BIG_32(ctx->buf_un.buf32 + 3);
5957c478bd9Sstevel@tonic-gate w_2 = LOAD_BIG_32(ctx->buf_un.buf32 + 2);
5967c478bd9Sstevel@tonic-gate w_1 = LOAD_BIG_32(ctx->buf_un.buf32 + 1);
5977c478bd9Sstevel@tonic-gate w_0 = LOAD_BIG_32(ctx->buf_un.buf32 + 0);
5987c478bd9Sstevel@tonic-gate } else {
5998de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6007c478bd9Sstevel@tonic-gate w_15 = LOAD_BIG_32(blk + 60);
6018de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6027c478bd9Sstevel@tonic-gate w_14 = LOAD_BIG_32(blk + 56);
6038de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6047c478bd9Sstevel@tonic-gate w_13 = LOAD_BIG_32(blk + 52);
6058de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6067c478bd9Sstevel@tonic-gate w_12 = LOAD_BIG_32(blk + 48);
6078de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6087c478bd9Sstevel@tonic-gate w_11 = LOAD_BIG_32(blk + 44);
6098de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6107c478bd9Sstevel@tonic-gate w_10 = LOAD_BIG_32(blk + 40);
6118de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6127c478bd9Sstevel@tonic-gate w_9 = LOAD_BIG_32(blk + 36);
6138de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6147c478bd9Sstevel@tonic-gate w_8 = LOAD_BIG_32(blk + 32);
6158de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6167c478bd9Sstevel@tonic-gate w_7 = LOAD_BIG_32(blk + 28);
6178de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6187c478bd9Sstevel@tonic-gate w_6 = LOAD_BIG_32(blk + 24);
6198de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6207c478bd9Sstevel@tonic-gate w_5 = LOAD_BIG_32(blk + 20);
6218de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6227c478bd9Sstevel@tonic-gate w_4 = LOAD_BIG_32(blk + 16);
6238de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6247c478bd9Sstevel@tonic-gate w_3 = LOAD_BIG_32(blk + 12);
6258de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6267c478bd9Sstevel@tonic-gate w_2 = LOAD_BIG_32(blk + 8);
6278de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6287c478bd9Sstevel@tonic-gate w_1 = LOAD_BIG_32(blk + 4);
6298de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
6307c478bd9Sstevel@tonic-gate w_0 = LOAD_BIG_32(blk + 0);
6317c478bd9Sstevel@tonic-gate }
632734b6a94Sdarrenm #else /* !defined(__sparc) */
633734b6a94Sdarrenm
6344b56a003SDaniel Anderson void /* CSTYLED */
635734b6a94Sdarrenm SHA1Transform(SHA1_CTX *ctx, const uint8_t blk[64])
636734b6a94Sdarrenm {
6374b56a003SDaniel Anderson /* CSTYLED */
638734b6a94Sdarrenm sha1word a = ctx->state[0];
639734b6a94Sdarrenm sha1word b = ctx->state[1];
640734b6a94Sdarrenm sha1word c = ctx->state[2];
641734b6a94Sdarrenm sha1word d = ctx->state[3];
642734b6a94Sdarrenm sha1word e = ctx->state[4];
643734b6a94Sdarrenm
644734b6a94Sdarrenm #if defined(W_ARRAY)
645734b6a94Sdarrenm sha1word w[16];
646734b6a94Sdarrenm #else /* !defined(W_ARRAY) */
647734b6a94Sdarrenm sha1word w_0, w_1, w_2, w_3, w_4, w_5, w_6, w_7;
648734b6a94Sdarrenm sha1word w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15;
649734b6a94Sdarrenm #endif /* !defined(W_ARRAY) */
650734b6a94Sdarrenm
65125cc6a40SDaniel Anderson W(0) = LOAD_BIG_32((void *)(blk + 0));
65225cc6a40SDaniel Anderson W(1) = LOAD_BIG_32((void *)(blk + 4));
65325cc6a40SDaniel Anderson W(2) = LOAD_BIG_32((void *)(blk + 8));
65425cc6a40SDaniel Anderson W(3) = LOAD_BIG_32((void *)(blk + 12));
65525cc6a40SDaniel Anderson W(4) = LOAD_BIG_32((void *)(blk + 16));
65625cc6a40SDaniel Anderson W(5) = LOAD_BIG_32((void *)(blk + 20));
65725cc6a40SDaniel Anderson W(6) = LOAD_BIG_32((void *)(blk + 24));
65825cc6a40SDaniel Anderson W(7) = LOAD_BIG_32((void *)(blk + 28));
65925cc6a40SDaniel Anderson W(8) = LOAD_BIG_32((void *)(blk + 32));
66025cc6a40SDaniel Anderson W(9) = LOAD_BIG_32((void *)(blk + 36));
66125cc6a40SDaniel Anderson W(10) = LOAD_BIG_32((void *)(blk + 40));
66225cc6a40SDaniel Anderson W(11) = LOAD_BIG_32((void *)(blk + 44));
66325cc6a40SDaniel Anderson W(12) = LOAD_BIG_32((void *)(blk + 48));
66425cc6a40SDaniel Anderson W(13) = LOAD_BIG_32((void *)(blk + 52));
66525cc6a40SDaniel Anderson W(14) = LOAD_BIG_32((void *)(blk + 56));
66625cc6a40SDaniel Anderson W(15) = LOAD_BIG_32((void *)(blk + 60));
667734b6a94Sdarrenm
668734b6a94Sdarrenm #endif /* !defined(__sparc) */
669734b6a94Sdarrenm
6707c478bd9Sstevel@tonic-gate /*
6717c478bd9Sstevel@tonic-gate * general optimization:
6727c478bd9Sstevel@tonic-gate *
6737c478bd9Sstevel@tonic-gate * even though this approach is described in the standard as
6747c478bd9Sstevel@tonic-gate * being slower algorithmically, it is 30-40% faster than the
6757c478bd9Sstevel@tonic-gate * "faster" version under SPARC, because this version has more
6767c478bd9Sstevel@tonic-gate * of the constraints specified at compile-time and uses fewer
6777c478bd9Sstevel@tonic-gate * variables (and therefore has better register utilization)
6787c478bd9Sstevel@tonic-gate * than its "speedier" brother. (i've tried both, trust me)
6797c478bd9Sstevel@tonic-gate *
6807c478bd9Sstevel@tonic-gate * for either method given in the spec, there is an "assignment"
6817c478bd9Sstevel@tonic-gate * phase where the following takes place:
6827c478bd9Sstevel@tonic-gate *
6837c478bd9Sstevel@tonic-gate * tmp = (main_computation);
6847c478bd9Sstevel@tonic-gate * e = d; d = c; c = rotate_left(b, 30); b = a; a = tmp;
6857c478bd9Sstevel@tonic-gate *
6867c478bd9Sstevel@tonic-gate * we can make the algorithm go faster by not doing this work,
6877c478bd9Sstevel@tonic-gate * but just pretending that `d' is now `e', etc. this works
6887c478bd9Sstevel@tonic-gate * really well and obviates the need for a temporary variable.
689321502cdSda * however, we still explicitly perform the rotate action,
6907c478bd9Sstevel@tonic-gate * since it is cheaper on SPARC to do it once than to have to
6917c478bd9Sstevel@tonic-gate * do it over and over again.
6927c478bd9Sstevel@tonic-gate */
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate /* round 1 */
695734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(0) + SHA1_CONST(0); /* 0 */
6967c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
6977c478bd9Sstevel@tonic-gate
698734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(1) + SHA1_CONST(0); /* 1 */
6997c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
7007c478bd9Sstevel@tonic-gate
701734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(2) + SHA1_CONST(0); /* 2 */
7027c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
7037c478bd9Sstevel@tonic-gate
704734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(3) + SHA1_CONST(0); /* 3 */
7057c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
7067c478bd9Sstevel@tonic-gate
707734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(4) + SHA1_CONST(0); /* 4 */
7087c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
7097c478bd9Sstevel@tonic-gate
710734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(5) + SHA1_CONST(0); /* 5 */
7117c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
7127c478bd9Sstevel@tonic-gate
713734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(6) + SHA1_CONST(0); /* 6 */
7147c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
7157c478bd9Sstevel@tonic-gate
716734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(7) + SHA1_CONST(0); /* 7 */
7177c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
7187c478bd9Sstevel@tonic-gate
719734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(8) + SHA1_CONST(0); /* 8 */
7207c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
7217c478bd9Sstevel@tonic-gate
722734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(9) + SHA1_CONST(0); /* 9 */
7237c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
7247c478bd9Sstevel@tonic-gate
725734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(10) + SHA1_CONST(0); /* 10 */
7267c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
7277c478bd9Sstevel@tonic-gate
728734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(11) + SHA1_CONST(0); /* 11 */
7297c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
7307c478bd9Sstevel@tonic-gate
731734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(12) + SHA1_CONST(0); /* 12 */
7327c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
7337c478bd9Sstevel@tonic-gate
734734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(13) + SHA1_CONST(0); /* 13 */
7357c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
7367c478bd9Sstevel@tonic-gate
737734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(14) + SHA1_CONST(0); /* 14 */
7387c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
7397c478bd9Sstevel@tonic-gate
740734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + W(15) + SHA1_CONST(0); /* 15 */
7417c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
7427c478bd9Sstevel@tonic-gate
743734b6a94Sdarrenm W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1); /* 16 */
744734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + W(0) + SHA1_CONST(0);
7457c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
7467c478bd9Sstevel@tonic-gate
747734b6a94Sdarrenm W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1); /* 17 */
748734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + W(1) + SHA1_CONST(0);
7497c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
7507c478bd9Sstevel@tonic-gate
751734b6a94Sdarrenm W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1); /* 18 */
752734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + W(2) + SHA1_CONST(0);
7537c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
7547c478bd9Sstevel@tonic-gate
755734b6a94Sdarrenm W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1); /* 19 */
756734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + W(3) + SHA1_CONST(0);
7577c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate /* round 2 */
760734b6a94Sdarrenm W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1); /* 20 */
761734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(4) + SHA1_CONST(1);
7627c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
7637c478bd9Sstevel@tonic-gate
764734b6a94Sdarrenm W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1); /* 21 */
765734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(5) + SHA1_CONST(1);
7667c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
7677c478bd9Sstevel@tonic-gate
768734b6a94Sdarrenm W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1); /* 22 */
769734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(6) + SHA1_CONST(1);
7707c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
7717c478bd9Sstevel@tonic-gate
772734b6a94Sdarrenm W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1); /* 23 */
773734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(7) + SHA1_CONST(1);
7747c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
7757c478bd9Sstevel@tonic-gate
776734b6a94Sdarrenm W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1); /* 24 */
777734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(8) + SHA1_CONST(1);
7787c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
7797c478bd9Sstevel@tonic-gate
780734b6a94Sdarrenm W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1); /* 25 */
781734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(9) + SHA1_CONST(1);
7827c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
7837c478bd9Sstevel@tonic-gate
784734b6a94Sdarrenm W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1); /* 26 */
785734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(10) + SHA1_CONST(1);
7867c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
7877c478bd9Sstevel@tonic-gate
788734b6a94Sdarrenm W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1); /* 27 */
789734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(11) + SHA1_CONST(1);
7907c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
7917c478bd9Sstevel@tonic-gate
792734b6a94Sdarrenm W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1); /* 28 */
793734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(12) + SHA1_CONST(1);
7947c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
7957c478bd9Sstevel@tonic-gate
796734b6a94Sdarrenm W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1); /* 29 */
797734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(13) + SHA1_CONST(1);
7987c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
7997c478bd9Sstevel@tonic-gate
800734b6a94Sdarrenm W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1); /* 30 */
801734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(14) + SHA1_CONST(1);
8027c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
8037c478bd9Sstevel@tonic-gate
804734b6a94Sdarrenm W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1); /* 31 */
805734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(15) + SHA1_CONST(1);
8067c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
8077c478bd9Sstevel@tonic-gate
808734b6a94Sdarrenm W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1); /* 32 */
809734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(0) + SHA1_CONST(1);
8107c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
8117c478bd9Sstevel@tonic-gate
812734b6a94Sdarrenm W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1); /* 33 */
813734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(1) + SHA1_CONST(1);
8147c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
8157c478bd9Sstevel@tonic-gate
816734b6a94Sdarrenm W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1); /* 34 */
817734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(2) + SHA1_CONST(1);
8187c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
8197c478bd9Sstevel@tonic-gate
820734b6a94Sdarrenm W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1); /* 35 */
821734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(3) + SHA1_CONST(1);
8227c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
8237c478bd9Sstevel@tonic-gate
824734b6a94Sdarrenm W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1); /* 36 */
825734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(4) + SHA1_CONST(1);
8267c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
8277c478bd9Sstevel@tonic-gate
828734b6a94Sdarrenm W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1); /* 37 */
829734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(5) + SHA1_CONST(1);
8307c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
8317c478bd9Sstevel@tonic-gate
832734b6a94Sdarrenm W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1); /* 38 */
833734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(6) + SHA1_CONST(1);
8347c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
8357c478bd9Sstevel@tonic-gate
836734b6a94Sdarrenm W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1); /* 39 */
837734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(7) + SHA1_CONST(1);
8387c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate /* round 3 */
841734b6a94Sdarrenm W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1); /* 40 */
842734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(8) + SHA1_CONST(2);
8437c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
8447c478bd9Sstevel@tonic-gate
845734b6a94Sdarrenm W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1); /* 41 */
846734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(9) + SHA1_CONST(2);
8477c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
8487c478bd9Sstevel@tonic-gate
849734b6a94Sdarrenm W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1); /* 42 */
850734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(10) + SHA1_CONST(2);
8517c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
8527c478bd9Sstevel@tonic-gate
853734b6a94Sdarrenm W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1); /* 43 */
854734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(11) + SHA1_CONST(2);
8557c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
8567c478bd9Sstevel@tonic-gate
857734b6a94Sdarrenm W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1); /* 44 */
858734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(12) + SHA1_CONST(2);
8597c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
8607c478bd9Sstevel@tonic-gate
861734b6a94Sdarrenm W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1); /* 45 */
862734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(13) + SHA1_CONST(2);
8637c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
8647c478bd9Sstevel@tonic-gate
865734b6a94Sdarrenm W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1); /* 46 */
866734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(14) + SHA1_CONST(2);
8677c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
8687c478bd9Sstevel@tonic-gate
869734b6a94Sdarrenm W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1); /* 47 */
870734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(15) + SHA1_CONST(2);
8717c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
8727c478bd9Sstevel@tonic-gate
873734b6a94Sdarrenm W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1); /* 48 */
874734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(0) + SHA1_CONST(2);
8757c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
8767c478bd9Sstevel@tonic-gate
877734b6a94Sdarrenm W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1); /* 49 */
878734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(1) + SHA1_CONST(2);
8797c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
8807c478bd9Sstevel@tonic-gate
881734b6a94Sdarrenm W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1); /* 50 */
882734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(2) + SHA1_CONST(2);
8837c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
8847c478bd9Sstevel@tonic-gate
885734b6a94Sdarrenm W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1); /* 51 */
886734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(3) + SHA1_CONST(2);
8877c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
8887c478bd9Sstevel@tonic-gate
889734b6a94Sdarrenm W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1); /* 52 */
890734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(4) + SHA1_CONST(2);
8917c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
8927c478bd9Sstevel@tonic-gate
893734b6a94Sdarrenm W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1); /* 53 */
894734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(5) + SHA1_CONST(2);
8957c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
8967c478bd9Sstevel@tonic-gate
897734b6a94Sdarrenm W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1); /* 54 */
898734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(6) + SHA1_CONST(2);
8997c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
9007c478bd9Sstevel@tonic-gate
901734b6a94Sdarrenm W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1); /* 55 */
902734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + W(7) + SHA1_CONST(2);
9037c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
9047c478bd9Sstevel@tonic-gate
905734b6a94Sdarrenm W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1); /* 56 */
906734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + W(8) + SHA1_CONST(2);
9077c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
9087c478bd9Sstevel@tonic-gate
909734b6a94Sdarrenm W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1); /* 57 */
910734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + W(9) + SHA1_CONST(2);
9117c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
9127c478bd9Sstevel@tonic-gate
913734b6a94Sdarrenm W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1); /* 58 */
914734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + W(10) + SHA1_CONST(2);
9157c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
9167c478bd9Sstevel@tonic-gate
917734b6a94Sdarrenm W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1); /* 59 */
918734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + W(11) + SHA1_CONST(2);
9197c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate /* round 4 */
922734b6a94Sdarrenm W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1); /* 60 */
923734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(12) + SHA1_CONST(3);
9247c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
9257c478bd9Sstevel@tonic-gate
926734b6a94Sdarrenm W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1); /* 61 */
927734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(13) + SHA1_CONST(3);
9287c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
9297c478bd9Sstevel@tonic-gate
930734b6a94Sdarrenm W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1); /* 62 */
931734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(14) + SHA1_CONST(3);
9327c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
9337c478bd9Sstevel@tonic-gate
934734b6a94Sdarrenm W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1); /* 63 */
935734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(15) + SHA1_CONST(3);
9367c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
9377c478bd9Sstevel@tonic-gate
938734b6a94Sdarrenm W(0) = ROTATE_LEFT((W(13) ^ W(8) ^ W(2) ^ W(0)), 1); /* 64 */
939734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(0) + SHA1_CONST(3);
9407c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
9417c478bd9Sstevel@tonic-gate
942734b6a94Sdarrenm W(1) = ROTATE_LEFT((W(14) ^ W(9) ^ W(3) ^ W(1)), 1); /* 65 */
943734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(1) + SHA1_CONST(3);
9447c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
9457c478bd9Sstevel@tonic-gate
946734b6a94Sdarrenm W(2) = ROTATE_LEFT((W(15) ^ W(10) ^ W(4) ^ W(2)), 1); /* 66 */
947734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(2) + SHA1_CONST(3);
9487c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
9497c478bd9Sstevel@tonic-gate
950734b6a94Sdarrenm W(3) = ROTATE_LEFT((W(0) ^ W(11) ^ W(5) ^ W(3)), 1); /* 67 */
951734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(3) + SHA1_CONST(3);
9527c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
9537c478bd9Sstevel@tonic-gate
954734b6a94Sdarrenm W(4) = ROTATE_LEFT((W(1) ^ W(12) ^ W(6) ^ W(4)), 1); /* 68 */
955734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(4) + SHA1_CONST(3);
9567c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
9577c478bd9Sstevel@tonic-gate
958734b6a94Sdarrenm W(5) = ROTATE_LEFT((W(2) ^ W(13) ^ W(7) ^ W(5)), 1); /* 69 */
959734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(5) + SHA1_CONST(3);
9607c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
9617c478bd9Sstevel@tonic-gate
962734b6a94Sdarrenm W(6) = ROTATE_LEFT((W(3) ^ W(14) ^ W(8) ^ W(6)), 1); /* 70 */
963734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(6) + SHA1_CONST(3);
9647c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
9657c478bd9Sstevel@tonic-gate
966734b6a94Sdarrenm W(7) = ROTATE_LEFT((W(4) ^ W(15) ^ W(9) ^ W(7)), 1); /* 71 */
967734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(7) + SHA1_CONST(3);
9687c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
9697c478bd9Sstevel@tonic-gate
970734b6a94Sdarrenm W(8) = ROTATE_LEFT((W(5) ^ W(0) ^ W(10) ^ W(8)), 1); /* 72 */
971734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(8) + SHA1_CONST(3);
9727c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
9737c478bd9Sstevel@tonic-gate
974734b6a94Sdarrenm W(9) = ROTATE_LEFT((W(6) ^ W(1) ^ W(11) ^ W(9)), 1); /* 73 */
975734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(9) + SHA1_CONST(3);
9767c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
9777c478bd9Sstevel@tonic-gate
978734b6a94Sdarrenm W(10) = ROTATE_LEFT((W(7) ^ W(2) ^ W(12) ^ W(10)), 1); /* 74 */
979734b6a94Sdarrenm a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(10) + SHA1_CONST(3);
9807c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30);
9817c478bd9Sstevel@tonic-gate
982734b6a94Sdarrenm W(11) = ROTATE_LEFT((W(8) ^ W(3) ^ W(13) ^ W(11)), 1); /* 75 */
983734b6a94Sdarrenm e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + W(11) + SHA1_CONST(3);
9847c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30);
9857c478bd9Sstevel@tonic-gate
986734b6a94Sdarrenm W(12) = ROTATE_LEFT((W(9) ^ W(4) ^ W(14) ^ W(12)), 1); /* 76 */
987734b6a94Sdarrenm d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + W(12) + SHA1_CONST(3);
9887c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30);
9897c478bd9Sstevel@tonic-gate
990734b6a94Sdarrenm W(13) = ROTATE_LEFT((W(10) ^ W(5) ^ W(15) ^ W(13)), 1); /* 77 */
991734b6a94Sdarrenm c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + W(13) + SHA1_CONST(3);
9927c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30);
9937c478bd9Sstevel@tonic-gate
994734b6a94Sdarrenm W(14) = ROTATE_LEFT((W(11) ^ W(6) ^ W(0) ^ W(14)), 1); /* 78 */
995734b6a94Sdarrenm b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + W(14) + SHA1_CONST(3);
9967c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30);
9977c478bd9Sstevel@tonic-gate
998734b6a94Sdarrenm W(15) = ROTATE_LEFT((W(12) ^ W(7) ^ W(1) ^ W(15)), 1); /* 79 */
9997c478bd9Sstevel@tonic-gate
1000734b6a94Sdarrenm ctx->state[0] += ROTATE_LEFT(b, 5) + G(c, d, e) + a + W(15) +
10017c478bd9Sstevel@tonic-gate SHA1_CONST(3);
10027c478bd9Sstevel@tonic-gate ctx->state[1] += b;
10037c478bd9Sstevel@tonic-gate ctx->state[2] += ROTATE_LEFT(c, 30);
10047c478bd9Sstevel@tonic-gate ctx->state[3] += d;
10057c478bd9Sstevel@tonic-gate ctx->state[4] += e;
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate /* zeroize sensitive information */
1008734b6a94Sdarrenm W(0) = W(1) = W(2) = W(3) = W(4) = W(5) = W(6) = W(7) = W(8) = 0;
1009734b6a94Sdarrenm W(9) = W(10) = W(11) = W(12) = W(13) = W(14) = W(15) = 0;
10107c478bd9Sstevel@tonic-gate }
1011321502cdSda #endif /* !__amd64 */
1012321502cdSda
10137c478bd9Sstevel@tonic-gate
10147c478bd9Sstevel@tonic-gate /*
10157c478bd9Sstevel@tonic-gate * Encode()
10167c478bd9Sstevel@tonic-gate *
10177c478bd9Sstevel@tonic-gate * purpose: to convert a list of numbers from little endian to big endian
10187c478bd9Sstevel@tonic-gate * input: uint8_t * : place to store the converted big endian numbers
10197c478bd9Sstevel@tonic-gate * uint32_t * : place to get numbers to convert from
10207c478bd9Sstevel@tonic-gate * size_t : the length of the input in bytes
10217c478bd9Sstevel@tonic-gate * output: void
10227c478bd9Sstevel@tonic-gate */
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate static void
1025734b6a94Sdarrenm Encode(uint8_t *_RESTRICT_KYWD output, const uint32_t *_RESTRICT_KYWD input,
1026734b6a94Sdarrenm size_t len)
10277c478bd9Sstevel@tonic-gate {
10287c478bd9Sstevel@tonic-gate size_t i, j;
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate #if defined(__sparc)
10317c478bd9Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint32_t))) {
10327c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) {
10338de5c4f4SDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */
10347c478bd9Sstevel@tonic-gate *((uint32_t *)(output + j)) = input[i];
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate } else {
10377c478bd9Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */
10387c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) {
10397c478bd9Sstevel@tonic-gate output[j] = (input[i] >> 24) & 0xff;
10407c478bd9Sstevel@tonic-gate output[j + 1] = (input[i] >> 16) & 0xff;
10417c478bd9Sstevel@tonic-gate output[j + 2] = (input[i] >> 8) & 0xff;
10427c478bd9Sstevel@tonic-gate output[j + 3] = input[i] & 0xff;
10437c478bd9Sstevel@tonic-gate }
10447c478bd9Sstevel@tonic-gate #if defined(__sparc)
10457c478bd9Sstevel@tonic-gate }
10467c478bd9Sstevel@tonic-gate #endif
10477c478bd9Sstevel@tonic-gate }
1048