Blame src/sha.c

Packit fa4fcc
/*
Packit fa4fcc
 * sha.c: routines to compute SHA-1/224/256/384/512 digests
Packit fa4fcc
 *
Packit fa4fcc
 * Ref: NIST FIPS PUB 180-4 Secure Hash Standard
Packit fa4fcc
 *
Packit fa4fcc
 * Copyright (C) 2003-2018 Mark Shelor, All Rights Reserved
Packit fa4fcc
 *
Packit fa4fcc
 * Version: 6.02
Packit fa4fcc
 * Fri Apr 20 16:25:30 MST 2018
Packit fa4fcc
 *
Packit fa4fcc
 */
Packit fa4fcc
Packit fa4fcc
#include <stdio.h>
Packit fa4fcc
#include <stdlib.h>
Packit fa4fcc
#include <stddef.h>
Packit fa4fcc
#include <string.h>
Packit fa4fcc
#include <ctype.h>
Packit fa4fcc
#include "sha.h"
Packit fa4fcc
#include "sha64bit.h"
Packit fa4fcc
Packit fa4fcc
#define W32	SHA32			/* useful abbreviations */
Packit fa4fcc
#define C32	SHA32_CONST
Packit fa4fcc
#define SR32	SHA32_SHR
Packit fa4fcc
#define SL32	SHA32_SHL
Packit fa4fcc
#define LO32	SHA_LO32
Packit fa4fcc
#define UCHR	unsigned char
Packit fa4fcc
#define UINT	unsigned int
Packit fa4fcc
#define ULNG	unsigned long
Packit fa4fcc
#define VP	void *
Packit fa4fcc
Packit fa4fcc
#define ROTR(x, n)	(SR32(x, n) | SL32(x, 32-(n)))
Packit fa4fcc
#define ROTL(x, n)	(SL32(x, n) | SR32(x, 32-(n)))
Packit fa4fcc
Packit fa4fcc
#define Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
Packit fa4fcc
#define Pa(x, y, z)	((x) ^ (y) ^ (z))
Packit fa4fcc
#define Ma(x, y, z)	(((x) & (y)) | ((z) & ((x) | (y))))
Packit fa4fcc
Packit fa4fcc
#define SIGMA0(x)	(ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
Packit fa4fcc
#define SIGMA1(x)	(ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
Packit fa4fcc
#define sigma0(x)	(ROTR(x,  7) ^ ROTR(x, 18) ^ SR32(x,  3))
Packit fa4fcc
#define sigma1(x)	(ROTR(x, 17) ^ ROTR(x, 19) ^ SR32(x, 10))
Packit fa4fcc
Packit fa4fcc
#define K1	C32(0x5a827999)		/* SHA-1 constants */
Packit fa4fcc
#define K2	C32(0x6ed9eba1)
Packit fa4fcc
#define K3	C32(0x8f1bbcdc)
Packit fa4fcc
#define K4	C32(0xca62c1d6)
Packit fa4fcc
Packit fa4fcc
static const W32 K256[64] =		/* SHA-224/256 constants */
Packit fa4fcc
{
Packit fa4fcc
	C32(0x428a2f98), C32(0x71374491), C32(0xb5c0fbcf), C32(0xe9b5dba5),
Packit fa4fcc
	C32(0x3956c25b), C32(0x59f111f1), C32(0x923f82a4), C32(0xab1c5ed5),
Packit fa4fcc
	C32(0xd807aa98), C32(0x12835b01), C32(0x243185be), C32(0x550c7dc3),
Packit fa4fcc
	C32(0x72be5d74), C32(0x80deb1fe), C32(0x9bdc06a7), C32(0xc19bf174),
Packit fa4fcc
	C32(0xe49b69c1), C32(0xefbe4786), C32(0x0fc19dc6), C32(0x240ca1cc),
Packit fa4fcc
	C32(0x2de92c6f), C32(0x4a7484aa), C32(0x5cb0a9dc), C32(0x76f988da),
Packit fa4fcc
	C32(0x983e5152), C32(0xa831c66d), C32(0xb00327c8), C32(0xbf597fc7),
Packit fa4fcc
	C32(0xc6e00bf3), C32(0xd5a79147), C32(0x06ca6351), C32(0x14292967),
Packit fa4fcc
	C32(0x27b70a85), C32(0x2e1b2138), C32(0x4d2c6dfc), C32(0x53380d13),
Packit fa4fcc
	C32(0x650a7354), C32(0x766a0abb), C32(0x81c2c92e), C32(0x92722c85),
Packit fa4fcc
	C32(0xa2bfe8a1), C32(0xa81a664b), C32(0xc24b8b70), C32(0xc76c51a3),
Packit fa4fcc
	C32(0xd192e819), C32(0xd6990624), C32(0xf40e3585), C32(0x106aa070),
Packit fa4fcc
	C32(0x19a4c116), C32(0x1e376c08), C32(0x2748774c), C32(0x34b0bcb5),
Packit fa4fcc
	C32(0x391c0cb3), C32(0x4ed8aa4a), C32(0x5b9cca4f), C32(0x682e6ff3),
Packit fa4fcc
	C32(0x748f82ee), C32(0x78a5636f), C32(0x84c87814), C32(0x8cc70208),
Packit fa4fcc
	C32(0x90befffa), C32(0xa4506ceb), C32(0xbef9a3f7), C32(0xc67178f2)
Packit fa4fcc
};
Packit fa4fcc
Packit fa4fcc
static const W32 H01[8] =		/* SHA-1 initial hash value */
Packit fa4fcc
{
Packit fa4fcc
	C32(0x67452301), C32(0xefcdab89), C32(0x98badcfe), C32(0x10325476),
Packit fa4fcc
	C32(0xc3d2e1f0), C32(0x00000000), C32(0x00000000), C32(0x00000000)
Packit fa4fcc
};
Packit fa4fcc
Packit fa4fcc
static const W32 H0224[8] =		/* SHA-224 initial hash value */
Packit fa4fcc
{
Packit fa4fcc
	C32(0xc1059ed8), C32(0x367cd507), C32(0x3070dd17), C32(0xf70e5939),
Packit fa4fcc
	C32(0xffc00b31), C32(0x68581511), C32(0x64f98fa7), C32(0xbefa4fa4)
Packit fa4fcc
};
Packit fa4fcc
Packit fa4fcc
static const W32 H0256[8] =		/* SHA-256 initial hash value */
Packit fa4fcc
{
Packit fa4fcc
	C32(0x6a09e667), C32(0xbb67ae85), C32(0x3c6ef372), C32(0xa54ff53a),
Packit fa4fcc
	C32(0x510e527f), C32(0x9b05688c), C32(0x1f83d9ab), C32(0x5be0cd19)
Packit fa4fcc
};
Packit fa4fcc
Packit fa4fcc
static void sha1(SHA *s, UCHR *block)		/* SHA-1 transform */
Packit fa4fcc
{
Packit fa4fcc
	W32 a, b, c, d, e;
Packit fa4fcc
	W32 W[16];
Packit fa4fcc
	W32 *wp = W;
Packit fa4fcc
	W32 *H = s->H32;
Packit fa4fcc
Packit fa4fcc
	SHA32_SCHED(W, block);
Packit fa4fcc
Packit fa4fcc
/*
Packit fa4fcc
 * Use SHA-1 alternate method from FIPS PUB 180-4 (ref. 6.1.3)
Packit fa4fcc
 *
Packit fa4fcc
 * To improve performance, unroll the loop and consolidate assignments
Packit fa4fcc
 * by changing the roles of variables "a" through "e" at each step.
Packit fa4fcc
 * Note that the variable "T" is no longer needed.
Packit fa4fcc
 */
Packit fa4fcc
Packit fa4fcc
#define M1(a, b, c, d, e, f, k, w)		\
Packit fa4fcc
	e += ROTL(a, 5) + f(b, c, d) + k + w;	\
Packit fa4fcc
	b =  ROTL(b, 30)
Packit fa4fcc
Packit fa4fcc
#define M11(f, k, w)	M1(a, b, c, d, e, f, k, w);
Packit fa4fcc
#define M12(f, k, w)	M1(e, a, b, c, d, f, k, w);
Packit fa4fcc
#define M13(f, k, w)	M1(d, e, a, b, c, f, k, w);
Packit fa4fcc
#define M14(f, k, w)	M1(c, d, e, a, b, f, k, w);
Packit fa4fcc
#define M15(f, k, w)	M1(b, c, d, e, a, f, k, w);
Packit fa4fcc
Packit fa4fcc
#define W11(s)	W[(s+ 0) & 0xf]
Packit fa4fcc
#define W12(s)	W[(s+13) & 0xf]
Packit fa4fcc
#define W13(s)	W[(s+ 8) & 0xf]
Packit fa4fcc
#define W14(s)	W[(s+ 2) & 0xf]
Packit fa4fcc
Packit fa4fcc
#define A1(s)	(W11(s) = ROTL(W11(s) ^ W12(s) ^ W13(s) ^ W14(s), 1))
Packit fa4fcc
Packit fa4fcc
	a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4];
Packit fa4fcc
Packit fa4fcc
	M11(Ch, K1,  *wp++); M12(Ch, K1,  *wp++); M13(Ch, K1,  *wp++);
Packit fa4fcc
	M14(Ch, K1,  *wp++); M15(Ch, K1,  *wp++); M11(Ch, K1,  *wp++);
Packit fa4fcc
	M12(Ch, K1,  *wp++); M13(Ch, K1,  *wp++); M14(Ch, K1,  *wp++);
Packit fa4fcc
	M15(Ch, K1,  *wp++); M11(Ch, K1,  *wp++); M12(Ch, K1,  *wp++);
Packit fa4fcc
	M13(Ch, K1,  *wp++); M14(Ch, K1,  *wp++); M15(Ch, K1,  *wp++);
Packit fa4fcc
	M11(Ch, K1,  *wp  ); M12(Ch, K1, A1( 0)); M13(Ch, K1, A1( 1));
Packit fa4fcc
	M14(Ch, K1, A1( 2)); M15(Ch, K1, A1( 3)); M11(Pa, K2, A1( 4));
Packit fa4fcc
	M12(Pa, K2, A1( 5)); M13(Pa, K2, A1( 6)); M14(Pa, K2, A1( 7));
Packit fa4fcc
	M15(Pa, K2, A1( 8)); M11(Pa, K2, A1( 9)); M12(Pa, K2, A1(10));
Packit fa4fcc
	M13(Pa, K2, A1(11)); M14(Pa, K2, A1(12)); M15(Pa, K2, A1(13));
Packit fa4fcc
	M11(Pa, K2, A1(14)); M12(Pa, K2, A1(15)); M13(Pa, K2, A1( 0));
Packit fa4fcc
	M14(Pa, K2, A1( 1)); M15(Pa, K2, A1( 2)); M11(Pa, K2, A1( 3));
Packit fa4fcc
	M12(Pa, K2, A1( 4)); M13(Pa, K2, A1( 5)); M14(Pa, K2, A1( 6));
Packit fa4fcc
	M15(Pa, K2, A1( 7)); M11(Ma, K3, A1( 8)); M12(Ma, K3, A1( 9));
Packit fa4fcc
	M13(Ma, K3, A1(10)); M14(Ma, K3, A1(11)); M15(Ma, K3, A1(12));
Packit fa4fcc
	M11(Ma, K3, A1(13)); M12(Ma, K3, A1(14)); M13(Ma, K3, A1(15));
Packit fa4fcc
	M14(Ma, K3, A1( 0)); M15(Ma, K3, A1( 1)); M11(Ma, K3, A1( 2));
Packit fa4fcc
	M12(Ma, K3, A1( 3)); M13(Ma, K3, A1( 4)); M14(Ma, K3, A1( 5));
Packit fa4fcc
	M15(Ma, K3, A1( 6)); M11(Ma, K3, A1( 7)); M12(Ma, K3, A1( 8));
Packit fa4fcc
	M13(Ma, K3, A1( 9)); M14(Ma, K3, A1(10)); M15(Ma, K3, A1(11));
Packit fa4fcc
	M11(Pa, K4, A1(12)); M12(Pa, K4, A1(13)); M13(Pa, K4, A1(14));
Packit fa4fcc
	M14(Pa, K4, A1(15)); M15(Pa, K4, A1( 0)); M11(Pa, K4, A1( 1));
Packit fa4fcc
	M12(Pa, K4, A1( 2)); M13(Pa, K4, A1( 3)); M14(Pa, K4, A1( 4));
Packit fa4fcc
	M15(Pa, K4, A1( 5)); M11(Pa, K4, A1( 6)); M12(Pa, K4, A1( 7));
Packit fa4fcc
	M13(Pa, K4, A1( 8)); M14(Pa, K4, A1( 9)); M15(Pa, K4, A1(10));
Packit fa4fcc
	M11(Pa, K4, A1(11)); M12(Pa, K4, A1(12)); M13(Pa, K4, A1(13));
Packit fa4fcc
	M14(Pa, K4, A1(14)); M15(Pa, K4, A1(15));
Packit fa4fcc
Packit fa4fcc
	H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e;
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
static void sha256(SHA *s, UCHR *block)		/* SHA-224/256 transform */
Packit fa4fcc
{
Packit fa4fcc
	W32 a, b, c, d, e, f, g, h, T1;
Packit fa4fcc
	W32 W[16];
Packit fa4fcc
	const W32 *kp = K256;
Packit fa4fcc
	W32 *wp = W;
Packit fa4fcc
	W32 *H = s->H32;
Packit fa4fcc
Packit fa4fcc
	SHA32_SCHED(W, block);
Packit fa4fcc
Packit fa4fcc
/*
Packit fa4fcc
 * Use same technique as in sha1()
Packit fa4fcc
 *
Packit fa4fcc
 * To improve performance, unroll the loop and consolidate assignments
Packit fa4fcc
 * by changing the roles of variables "a" through "h" at each step.
Packit fa4fcc
 * Note that the variable "T2" is no longer needed.
Packit fa4fcc
 */
Packit fa4fcc
Packit fa4fcc
#define M2(a, b, c, d, e, f, g, h, w)				\
Packit fa4fcc
	T1 = h  + SIGMA1(e) + Ch(e, f, g) + (*kp++) + w;	\
Packit fa4fcc
	h  = T1 + SIGMA0(a) + Ma(a, b, c); d += T1;
Packit fa4fcc
Packit fa4fcc
#define W21(s)	W[(s+ 0) & 0xf]
Packit fa4fcc
#define W22(s)	W[(s+14) & 0xf]
Packit fa4fcc
#define W23(s)	W[(s+ 9) & 0xf]
Packit fa4fcc
#define W24(s)	W[(s+ 1) & 0xf]
Packit fa4fcc
Packit fa4fcc
#define A2(s)	(W21(s) += sigma1(W22(s)) + W23(s) + sigma0(W24(s)))
Packit fa4fcc
Packit fa4fcc
#define M21(w)	M2(a, b, c, d, e, f, g, h, w)
Packit fa4fcc
#define M22(w)	M2(h, a, b, c, d, e, f, g, w)
Packit fa4fcc
#define M23(w)	M2(g, h, a, b, c, d, e, f, w)
Packit fa4fcc
#define M24(w)	M2(f, g, h, a, b, c, d, e, w)
Packit fa4fcc
#define M25(w)	M2(e, f, g, h, a, b, c, d, w)
Packit fa4fcc
#define M26(w)	M2(d, e, f, g, h, a, b, c, w)
Packit fa4fcc
#define M27(w)	M2(c, d, e, f, g, h, a, b, w)
Packit fa4fcc
#define M28(w)	M2(b, c, d, e, f, g, h, a, w)
Packit fa4fcc
Packit fa4fcc
	a = H[0]; b = H[1]; c = H[2]; d = H[3];
Packit fa4fcc
	e = H[4]; f = H[5]; g = H[6]; h = H[7];
Packit fa4fcc
Packit fa4fcc
	M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++);
Packit fa4fcc
	M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp++);
Packit fa4fcc
	M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++);
Packit fa4fcc
	M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp  );
Packit fa4fcc
	M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
Packit fa4fcc
	M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
Packit fa4fcc
	M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
Packit fa4fcc
	M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
Packit fa4fcc
	M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
Packit fa4fcc
	M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
Packit fa4fcc
	M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
Packit fa4fcc
	M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
Packit fa4fcc
	M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
Packit fa4fcc
	M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
Packit fa4fcc
	M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
Packit fa4fcc
	M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
Packit fa4fcc
Packit fa4fcc
	H[0] += a; H[1] += b; H[2] += c; H[3] += d;
Packit fa4fcc
	H[4] += e; H[5] += f; H[6] += g; H[7] += h;
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
#include "sha64bit.c"
Packit fa4fcc
Packit fa4fcc
#define BITSET(s, pos)	s[(pos) >> 3] &  (UCHR)  (0x01 << (7 - (pos) % 8))
Packit fa4fcc
#define SETBIT(s, pos)	s[(pos) >> 3] |= (UCHR)  (0x01 << (7 - (pos) % 8))
Packit fa4fcc
#define CLRBIT(s, pos)	s[(pos) >> 3] &= (UCHR) ~(0x01 << (7 - (pos) % 8))
Packit fa4fcc
#define NBYTES(nbits)	(((nbits) + 7) >> 3)
Packit fa4fcc
#define HEXLEN(nbytes)	((nbytes) << 1)
Packit fa4fcc
#define B64LEN(nbytes)	(((nbytes) % 3 == 0) ? ((nbytes) / 3) * 4 \
Packit fa4fcc
			: ((nbytes) / 3) * 4 + ((nbytes) % 3) + 1)
Packit fa4fcc
Packit fa4fcc
/* w32mem: writes 32-bit word to memory in big-endian order */
Packit fa4fcc
static UCHR *w32mem(UCHR *mem, W32 w32)
Packit fa4fcc
{
Packit fa4fcc
	int i;
Packit fa4fcc
Packit fa4fcc
	for (i = 0; i < 4; i++)
Packit fa4fcc
		*mem++ = (UCHR) (SR32(w32, 24-i*8) & 0xff);
Packit fa4fcc
	return(mem);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* memw32: returns 32-bit word from memory written in big-endian order */
Packit fa4fcc
static W32 memw32(UCHR *mem)
Packit fa4fcc
{
Packit fa4fcc
	int i;
Packit fa4fcc
	W32 w = 0;
Packit fa4fcc
Packit fa4fcc
	for (i = 0; i < 4; i++)
Packit fa4fcc
		w = (w << 8) + *mem++;
Packit fa4fcc
	return(w);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* digcpy: writes current state to digest buffer */
Packit fa4fcc
static UCHR *digcpy(SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	int i;
Packit fa4fcc
	UCHR *d = s->digest;
Packit fa4fcc
	W32 *p32 = s->H32;
Packit fa4fcc
	W64 *p64 = s->H64;
Packit fa4fcc
Packit fa4fcc
	if (s->alg <= SHA256)
Packit fa4fcc
		for (i = 0; i < 8; i++, d += 4)
Packit fa4fcc
			w32mem(d, *p32++);
Packit fa4fcc
	else
Packit fa4fcc
		for (i = 0; i < 8; i++, d += 8) {
Packit fa4fcc
			w32mem(d, (W32) ((*p64 >> 16) >> 16));
Packit fa4fcc
			w32mem(d+4, (W32) (*p64++ & SHA32_MAX));
Packit fa4fcc
		}
Packit fa4fcc
	return(s->digest);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* statecpy: writes buffer to current state (opposite of digcpy) */
Packit fa4fcc
static UCHR *statecpy(SHA *s, UCHR *buf)
Packit fa4fcc
{
Packit fa4fcc
	int i;
Packit fa4fcc
	W32 *p32 = s->H32;
Packit fa4fcc
	W64 *p64 = s->H64;
Packit fa4fcc
Packit fa4fcc
	if (s->alg <= SHA256)
Packit fa4fcc
		for (i = 0; i < 8; i++, buf += 4)
Packit fa4fcc
			*p32++ = memw32(buf);
Packit fa4fcc
	else
Packit fa4fcc
		for (i = 0; i < 8; i++, buf += 8)
Packit fa4fcc
			*p64++ = (((W64)memw32(buf) << 16) << 16) +
Packit fa4fcc
					memw32(buf+4);
Packit fa4fcc
	return(buf);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
#define SHA_INIT(s, algo, transform) 					\
Packit fa4fcc
	do {								\
Packit fa4fcc
		Zero(s, 1, SHA);					\
Packit fa4fcc
		s->alg = algo; s->sha = sha ## transform;		\
Packit fa4fcc
		if (s->alg <= SHA256)					\
Packit fa4fcc
			Copy(H0 ## algo, s->H32, 8, SHA32);		\
Packit fa4fcc
		else							\
Packit fa4fcc
			Copy(H0 ## algo, s->H64, 8, SHA64);		\
Packit fa4fcc
		s->blocksize = SHA ## algo ## _BLOCK_BITS;		\
Packit fa4fcc
		s->digestlen = SHA ## algo ## _DIGEST_BITS >> 3;	\
Packit fa4fcc
	} while (0)
Packit fa4fcc
Packit fa4fcc
/* sharewind: resets digest object */
Packit fa4fcc
static void sharewind(SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	if      (s->alg == SHA1)   SHA_INIT(s, 1, 1);
Packit fa4fcc
	else if (s->alg == SHA224) SHA_INIT(s, 224, 256);
Packit fa4fcc
	else if (s->alg == SHA256) SHA_INIT(s, 256, 256);
Packit fa4fcc
	else if (s->alg == SHA384) SHA_INIT(s, 384, 512);
Packit fa4fcc
	else if (s->alg == SHA512) SHA_INIT(s, 512, 512);
Packit fa4fcc
	else if (s->alg == SHA512224) SHA_INIT(s, 512224, 512);
Packit fa4fcc
	else if (s->alg == SHA512256) SHA_INIT(s, 512256, 512);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shainit: initializes digest object */
Packit fa4fcc
static int shainit(SHA *s, int alg)
Packit fa4fcc
{
Packit fa4fcc
	if (alg >= SHA384 && !sha_384_512)
Packit fa4fcc
		return 0;
Packit fa4fcc
	if (alg != SHA1 && alg != SHA224 && alg != SHA256 &&
Packit fa4fcc
		alg != SHA384    && alg != SHA512 &&
Packit fa4fcc
		alg != SHA512224 && alg != SHA512256)
Packit fa4fcc
		return 0;
Packit fa4fcc
	s->alg = alg;
Packit fa4fcc
	sharewind(s);
Packit fa4fcc
	return 1;
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shadirect: updates state directly (w/o going through s->block) */
Packit fa4fcc
static ULNG shadirect(UCHR *bitstr, ULNG bitcnt, SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	ULNG savecnt = bitcnt;
Packit fa4fcc
Packit fa4fcc
	while (bitcnt >= s->blocksize) {
Packit fa4fcc
		s->sha(s, bitstr);
Packit fa4fcc
		bitstr += (s->blocksize >> 3);
Packit fa4fcc
		bitcnt -= s->blocksize;
Packit fa4fcc
	}
Packit fa4fcc
	if (bitcnt > 0) {
Packit fa4fcc
		Copy(bitstr, s->block, NBYTES(bitcnt), char);
Packit fa4fcc
		s->blockcnt = bitcnt;
Packit fa4fcc
	}
Packit fa4fcc
	return(savecnt);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shabytes: updates state for byte-aligned data in s->block */
Packit fa4fcc
static ULNG shabytes(UCHR *bitstr, ULNG bitcnt, SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	UINT offset;
Packit fa4fcc
	UINT nbits;
Packit fa4fcc
	ULNG savecnt = bitcnt;
Packit fa4fcc
Packit fa4fcc
	offset = s->blockcnt >> 3;
Packit fa4fcc
	if (s->blockcnt + bitcnt >= s->blocksize) {
Packit fa4fcc
		nbits = s->blocksize - s->blockcnt;
Packit fa4fcc
		Copy(bitstr, s->block+offset, nbits>>3, char);
Packit fa4fcc
		bitcnt -= nbits;
Packit fa4fcc
		bitstr += (nbits >> 3);
Packit fa4fcc
		s->sha(s, s->block), s->blockcnt = 0;
Packit fa4fcc
		shadirect(bitstr, bitcnt, s);
Packit fa4fcc
	}
Packit fa4fcc
	else {
Packit fa4fcc
		Copy(bitstr, s->block+offset, NBYTES(bitcnt), char);
Packit fa4fcc
		s->blockcnt += bitcnt;
Packit fa4fcc
	}
Packit fa4fcc
	return(savecnt);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shabits: updates state for bit-aligned data in s->block */
Packit fa4fcc
static ULNG shabits(UCHR *bitstr, ULNG bitcnt, SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	ULNG i;
Packit fa4fcc
Packit fa4fcc
	for (i = 0UL; i < bitcnt; i++) {
Packit fa4fcc
		if (BITSET(bitstr, i))
Packit fa4fcc
			SETBIT(s->block, s->blockcnt);
Packit fa4fcc
		else
Packit fa4fcc
			CLRBIT(s->block, s->blockcnt);
Packit fa4fcc
		if (++s->blockcnt == s->blocksize)
Packit fa4fcc
			s->sha(s, s->block), s->blockcnt = 0;
Packit fa4fcc
	}
Packit fa4fcc
	return(bitcnt);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shawrite: triggers a state update using data in bitstr/bitcnt */
Packit fa4fcc
static ULNG shawrite(UCHR *bitstr, ULNG bitcnt, SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	if (!bitcnt)
Packit fa4fcc
		return(0);
Packit fa4fcc
	if (SHA_LO32(s->lenll += bitcnt) < bitcnt)
Packit fa4fcc
		if (SHA_LO32(++s->lenlh) == 0)
Packit fa4fcc
			if (SHA_LO32(++s->lenhl) == 0)
Packit fa4fcc
				s->lenhh++;
Packit fa4fcc
	if (s->blockcnt == 0)
Packit fa4fcc
		return(shadirect(bitstr, bitcnt, s));
Packit fa4fcc
	else if (s->blockcnt % 8 == 0)
Packit fa4fcc
		return(shabytes(bitstr, bitcnt, s));
Packit fa4fcc
	else
Packit fa4fcc
		return(shabits(bitstr, bitcnt, s));
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shafinish: pads remaining block(s) and computes final digest state */
Packit fa4fcc
static void shafinish(SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	UINT lenpos, lhpos, llpos;
Packit fa4fcc
Packit fa4fcc
	lenpos = s->blocksize == SHA1_BLOCK_BITS ? 448 : 896;
Packit fa4fcc
	lhpos  = s->blocksize == SHA1_BLOCK_BITS ?  56 : 120;
Packit fa4fcc
	llpos  = s->blocksize == SHA1_BLOCK_BITS ?  60 : 124;
Packit fa4fcc
	SETBIT(s->block, s->blockcnt), s->blockcnt++;
Packit fa4fcc
	while (s->blockcnt > lenpos)
Packit fa4fcc
		if (s->blockcnt < s->blocksize)
Packit fa4fcc
			CLRBIT(s->block, s->blockcnt), s->blockcnt++;
Packit fa4fcc
		else
Packit fa4fcc
			s->sha(s, s->block), s->blockcnt = 0;
Packit fa4fcc
	while (s->blockcnt < lenpos)
Packit fa4fcc
		CLRBIT(s->block, s->blockcnt), s->blockcnt++;
Packit fa4fcc
	if (s->blocksize > SHA1_BLOCK_BITS) {
Packit fa4fcc
		w32mem(s->block + 112, s->lenhh);
Packit fa4fcc
		w32mem(s->block + 116, s->lenhl);
Packit fa4fcc
	}
Packit fa4fcc
	w32mem(s->block + lhpos, s->lenlh);
Packit fa4fcc
	w32mem(s->block + llpos, s->lenll);
Packit fa4fcc
	s->sha(s, s->block);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
#define shadigest(state)	digcpy(state)
Packit fa4fcc
Packit fa4fcc
/* xmap: translation map for hexadecimal encoding */
Packit fa4fcc
static const char xmap[] =
Packit fa4fcc
	"0123456789abcdef";
Packit fa4fcc
Packit fa4fcc
/* shahex: returns pointer to current digest (hexadecimal) */
Packit fa4fcc
static char *shahex(SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	UINT i;
Packit fa4fcc
	char *h;
Packit fa4fcc
	UCHR *d;
Packit fa4fcc
Packit fa4fcc
	d = digcpy(s);
Packit fa4fcc
	s->hex[0] = '\0';
Packit fa4fcc
	if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex))
Packit fa4fcc
		return(s->hex);
Packit fa4fcc
	for (i = 0, h = s->hex; i < s->digestlen; i++) {
Packit fa4fcc
		*h++ = xmap[(*d >> 4) & 0x0f];
Packit fa4fcc
		*h++ = xmap[(*d++   ) & 0x0f];
Packit fa4fcc
	}
Packit fa4fcc
	*h = '\0';
Packit fa4fcc
	return(s->hex);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* bmap: translation map for Base 64 encoding */
Packit fa4fcc
static const char bmap[] =
Packit fa4fcc
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Packit fa4fcc
Packit fa4fcc
/* encbase64: encodes input (0 to 3 bytes) into Base 64 */
Packit fa4fcc
static void encbase64(UCHR *in, UINT n, char *out)
Packit fa4fcc
{
Packit fa4fcc
	UCHR byte[3] = {0, 0, 0};
Packit fa4fcc
Packit fa4fcc
	out[0] = '\0';
Packit fa4fcc
	if (n < 1 || n > 3)
Packit fa4fcc
		return;
Packit fa4fcc
	Copy(in, byte, n, UCHR);
Packit fa4fcc
	out[0] = bmap[byte[0] >> 2];
Packit fa4fcc
	out[1] = bmap[((byte[0] & 0x03) << 4) | (byte[1] >> 4)];
Packit fa4fcc
	out[2] = bmap[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)];
Packit fa4fcc
	out[3] = bmap[byte[2] & 0x3f];
Packit fa4fcc
	out[n+1] = '\0';
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* shabase64: returns pointer to current digest (Base 64) */
Packit fa4fcc
static char *shabase64(SHA *s)
Packit fa4fcc
{
Packit fa4fcc
	UINT n;
Packit fa4fcc
	UCHR *q;
Packit fa4fcc
	char out[5];
Packit fa4fcc
Packit fa4fcc
	q = digcpy(s);
Packit fa4fcc
	s->base64[0] = '\0';
Packit fa4fcc
	if (B64LEN((size_t) s->digestlen) >= sizeof(s->base64))
Packit fa4fcc
		return(s->base64);
Packit fa4fcc
	for (n = s->digestlen; n > 3; n -= 3, q += 3) {
Packit fa4fcc
		encbase64(q, 3, out);
Packit fa4fcc
		strcat(s->base64, out);
Packit fa4fcc
	}
Packit fa4fcc
	encbase64(q, n, out);
Packit fa4fcc
	strcat(s->base64, out);
Packit fa4fcc
	return(s->base64);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* hmacinit: initializes HMAC-SHA digest object */
Packit fa4fcc
static HMAC *hmacinit(HMAC *h, int alg, UCHR *key, UINT keylen)
Packit fa4fcc
{
Packit fa4fcc
	UINT i;
Packit fa4fcc
	SHA ksha;
Packit fa4fcc
Packit fa4fcc
	Zero(h, 1, HMAC);
Packit fa4fcc
	if (!shainit(&h->isha, alg))
Packit fa4fcc
		return(NULL);
Packit fa4fcc
	if (!shainit(&h->osha, alg))
Packit fa4fcc
		return(NULL);
Packit fa4fcc
	if (keylen <= h->osha.blocksize / 8)
Packit fa4fcc
		Copy(key, h->key, keylen, char);
Packit fa4fcc
	else {
Packit fa4fcc
		if (!shainit(&ksha, alg))
Packit fa4fcc
			return(NULL);
Packit fa4fcc
		shawrite(key, keylen * 8, &ksha);
Packit fa4fcc
		shafinish(&ksha);
Packit fa4fcc
		Copy(digcpy(&ksha), h->key, ksha.digestlen, char);
Packit fa4fcc
	}
Packit fa4fcc
	h->digestlen = h->osha.digestlen;
Packit fa4fcc
	for (i = 0; i < h->osha.blocksize / 8; i++)
Packit fa4fcc
		h->key[i] ^= 0x5c;
Packit fa4fcc
	shawrite(h->key, h->osha.blocksize, &h->osha);
Packit fa4fcc
	for (i = 0; i < h->isha.blocksize / 8; i++)
Packit fa4fcc
		h->key[i] ^= (0x5c ^ 0x36);
Packit fa4fcc
	shawrite(h->key, h->isha.blocksize, &h->isha);
Packit fa4fcc
	Zero(h->key, sizeof(h->key), char);
Packit fa4fcc
	return(h);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* hmacwrite: triggers a state update using data in bitstr/bitcnt */
Packit fa4fcc
static ULNG hmacwrite(UCHR *bitstr, ULNG bitcnt, HMAC *h)
Packit fa4fcc
{
Packit fa4fcc
	return(shawrite(bitstr, bitcnt, &h->isha));
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* hmacfinish: computes final digest state */
Packit fa4fcc
static void hmacfinish(HMAC *h)
Packit fa4fcc
{
Packit fa4fcc
	shafinish(&h->isha);
Packit fa4fcc
	shawrite(digcpy(&h->isha), h->isha.digestlen * 8, &h->osha);
Packit fa4fcc
	shafinish(&h->osha);
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
#define hmacdigest(h)	digcpy(&(h)->osha)
Packit fa4fcc
Packit fa4fcc
/* hmachex: returns pointer to digest (hexadecimal) */
Packit fa4fcc
static char *hmachex(HMAC *h)
Packit fa4fcc
{
Packit fa4fcc
	return(shahex(&h->osha));
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
/* hmacbase64: returns pointer to digest (Base 64) */
Packit fa4fcc
static char *hmacbase64(HMAC *h)
Packit fa4fcc
{
Packit fa4fcc
	return(shabase64(&h->osha));
Packit fa4fcc
}