Add missing files in ext/Digest/SHA/src that somehow escaped the net.
Nicholas Clark [Sun, 8 Jan 2006 08:28:29 +0000 (08:28 +0000)]
p4raw-id: //depot/perl@26705

ext/Digest/SHA/src/hmac.c [new file with mode: 0644]
ext/Digest/SHA/src/hmac.h [new file with mode: 0644]
ext/Digest/SHA/src/hmacxtra.c [new file with mode: 0644]
ext/Digest/SHA/src/sha.c [new file with mode: 0644]
ext/Digest/SHA/src/sha.h [new file with mode: 0644]
ext/Digest/SHA/src/sha64bit.c [new file with mode: 0644]
ext/Digest/SHA/src/sha64bit.h [new file with mode: 0644]
ext/Digest/SHA/src/shaxtra.c [new file with mode: 0644]

diff --git a/ext/Digest/SHA/src/hmac.c b/ext/Digest/SHA/src/hmac.c
new file mode 100644 (file)
index 0000000..19d999b
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * hmac.c: routines to compute HMAC-SHA-1/224/256/384/512 digests
+ *
+ * Ref: FIPS PUB 198 The Keyed-Hash Message Authentication Code
+ *
+ * Copyright (C) 2003-2005 Mark Shelor, All Rights Reserved
+ *
+ * Version: 5.32
+ * Fri Dec  2 02:32:20 MST 2005
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hmac.h"
+#include "sha.h"
+
+/* hmacopen: creates a new HMAC-SHA digest object */
+HMAC *hmacopen(alg, key, keylen)
+int alg;
+unsigned char *key;
+unsigned int keylen;
+{
+       unsigned int i;
+       HMAC *h;
+
+       SHA_newz(0, h, 1, HMAC);
+       if (h == NULL)
+               return(NULL);
+       if ((h->isha = shaopen(alg)) == NULL) {
+               SHA_free(h);
+               return(NULL);
+       }
+       if ((h->osha = shaopen(alg)) == NULL) {
+               shaclose(h->isha);
+               SHA_free(h);
+               return(NULL);
+       }
+       if (keylen <= h->osha->blocksize / 8)
+               memcpy(h->key, key, keylen);
+       else {
+               if ((h->ksha = shaopen(alg)) == NULL) {
+                       shaclose(h->isha);
+                       shaclose(h->osha);
+                       SHA_free(h);
+                       return(NULL);
+               }
+               shawrite(key, keylen * 8, h->ksha);
+               shafinish(h->ksha);
+               memcpy(h->key, shadigest(h->ksha), h->ksha->digestlen);
+               shaclose(h->ksha);
+       }
+       for (i = 0; i < h->osha->blocksize / 8; i++)
+               h->key[i] ^= 0x5c;
+       shawrite(h->key, h->osha->blocksize, h->osha);
+       for (i = 0; i < h->isha->blocksize / 8; i++)
+               h->key[i] ^= (0x5c ^ 0x36);
+       shawrite(h->key, h->isha->blocksize, h->isha);
+       memset(h->key, 0, sizeof(h->key));
+       return(h);
+}
+
+/* hmacwrite: triggers a state update using data in bitstr/bitcnt */
+unsigned long hmacwrite(bitstr, bitcnt, h)
+unsigned char *bitstr;
+unsigned long bitcnt;
+HMAC *h;
+{
+       return(shawrite(bitstr, bitcnt, h->isha));
+}
+
+/* hmacfinish: computes final digest state */
+void hmacfinish(h)
+HMAC *h;
+{
+       shafinish(h->isha);
+       shawrite(shadigest(h->isha), h->isha->digestlen * 8, h->osha);
+       shaclose(h->isha);
+       shafinish(h->osha);
+}
+
+/* hmacdigest: returns pointer to digest (binary) */
+unsigned char *hmacdigest(h)
+HMAC *h;
+{
+       return(shadigest(h->osha));
+}
+
+/* hmachex: returns pointer to digest (hexadecimal) */
+char *hmachex(h)
+HMAC *h;
+{
+       return(shahex(h->osha));
+}
+
+/* hmacbase64: returns pointer to digest (Base 64) */
+char *hmacbase64(h)
+HMAC *h;
+{
+       return(shabase64(h->osha));
+}
+
+/* hmacclose: de-allocates digest object */
+int hmacclose(h)
+HMAC *h;
+{
+       shaclose(h->osha);
+       if (h != NULL) {
+               memset(h, 0, sizeof(HMAC));
+               SHA_free(h);
+       }
+       return(0);
+}
diff --git a/ext/Digest/SHA/src/hmac.h b/ext/Digest/SHA/src/hmac.h
new file mode 100644 (file)
index 0000000..639c46f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * hmac.h: header file for HMAC-SHA-1/224/256/384/512 routines
+ *
+ * Ref: FIPS PUB 198 The Keyed-Hash Message Authentication Code
+ *
+ * Copyright (C) 2003-2005 Mark Shelor, All Rights Reserved
+ *
+ * Version: 5.32
+ * Fri Dec  2 02:32:20 MST 2005
+ *
+ */
+
+#ifndef _INCLUDE_HMAC_H_
+#define _INCLUDE_HMAC_H_
+
+#include "sha.h"
+
+typedef struct {
+       SHA *ksha;
+       SHA *isha;
+       SHA *osha;
+       unsigned char key[SHA_MAX_BLOCK_BITS/8];
+} HMAC;
+
+#if defined(__STDC__) && __STDC__ != 0
+       #define _HMAC_P(protos) protos
+#else
+       #define _HMAC_P(protos) ()
+#endif
+
+#define _HMAC_STATE    HMAC *h
+#define _HMAC_ALG      int alg
+#define _HMAC_DATA     unsigned char *bitstr, unsigned long bitcnt
+#define _HMAC_KEY      unsigned char *key, unsigned int keylen
+
+HMAC           *hmacopen       _HMAC_P((_HMAC_ALG, _HMAC_KEY));
+unsigned long   hmacwrite      _HMAC_P((_HMAC_DATA, _HMAC_STATE));
+void            hmacfinish     _HMAC_P((_HMAC_STATE));
+unsigned char  *hmacdigest     _HMAC_P((_HMAC_STATE));
+char           *hmachex        _HMAC_P((_HMAC_STATE));
+char           *hmacbase64     _HMAC_P((_HMAC_STATE));
+int             hmacclose      _HMAC_P((_HMAC_STATE));
+
+unsigned char  *hmac1digest    _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac1hex       _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac1base64    _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+unsigned char  *hmac224digest  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac224hex     _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac224base64  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+unsigned char  *hmac256digest  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac256hex     _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac256base64  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+unsigned char  *hmac384digest  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac384hex     _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac384base64  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+unsigned char  *hmac512digest  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac512hex     _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+char           *hmac512base64  _HMAC_P((_HMAC_DATA, _HMAC_KEY));
+
+#endif /* _INCLUDE_HMAC_H_ */
diff --git a/ext/Digest/SHA/src/hmacxtra.c b/ext/Digest/SHA/src/hmacxtra.c
new file mode 100644 (file)
index 0000000..35a36ed
--- /dev/null
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include <string.h>
+#include "hmac.h"
+
+static unsigned char *hmaccomp(alg, fmt, bitstr, bitcnt, key, keylen)
+int alg;
+int fmt;
+unsigned char *bitstr;
+unsigned long bitcnt;
+unsigned char *key;
+unsigned int keylen;
+{
+       HMAC *h;
+       static unsigned char digest[SHA_MAX_HEX_LEN+1];
+       unsigned char *ret = digest;
+
+       if ((h = hmacopen(alg, key, keylen)) == NULL)
+               return(NULL);
+       hmacwrite(bitstr, bitcnt, h);
+       hmacfinish(h);
+       if (fmt == SHA_FMT_RAW)
+               memcpy(digest, hmacdigest(h), h->osha->digestlen); 
+       else if (fmt == SHA_FMT_HEX)
+               strcpy((char *) digest, hmachex(h)); 
+       else if (fmt == SHA_FMT_BASE64)
+               strcpy((char *) digest, hmacbase64(h)); 
+       else
+               ret = NULL;
+       hmacclose(h);
+       return(ret);
+}
+
+#define HMAC_DIRECT(type, name, alg, fmt)                      \
+type name(bitstr, bitcnt, key, keylen)                         \
+unsigned char *bitstr;                                         \
+unsigned long bitcnt;                                          \
+unsigned char *key;                                            \
+unsigned int keylen;                                           \
+{                                                              \
+       return((type) hmaccomp(alg, fmt, bitstr, bitcnt,        \
+                                       key, keylen));          \
+}
+
+HMAC_DIRECT(unsigned char *, hmac1digest, SHA1, SHA_FMT_RAW)
+HMAC_DIRECT(char *, hmac1hex, SHA1, SHA_FMT_HEX)
+HMAC_DIRECT(char *, hmac1base64, SHA1, SHA_FMT_BASE64)
+
+HMAC_DIRECT(unsigned char *, hmac224digest, SHA224, SHA_FMT_RAW)
+HMAC_DIRECT(char *, hmac224hex, SHA224, SHA_FMT_HEX)
+HMAC_DIRECT(char *, hmac224base64, SHA224, SHA_FMT_BASE64)
+
+HMAC_DIRECT(unsigned char *, hmac256digest, SHA256, SHA_FMT_RAW)
+HMAC_DIRECT(char *, hmac256hex, SHA256, SHA_FMT_HEX)
+HMAC_DIRECT(char *, hmac256base64, SHA256, SHA_FMT_BASE64)
+
+HMAC_DIRECT(unsigned char *, hmac384digest, SHA384, SHA_FMT_RAW)
+HMAC_DIRECT(char *, hmac384hex, SHA384, SHA_FMT_HEX)
+HMAC_DIRECT(char *, hmac384base64, SHA384, SHA_FMT_BASE64)
+
+HMAC_DIRECT(unsigned char *, hmac512digest, SHA512, SHA_FMT_RAW)
+HMAC_DIRECT(char *, hmac512hex, SHA512, SHA_FMT_HEX)
+HMAC_DIRECT(char *, hmac512base64, SHA512, SHA_FMT_BASE64)
diff --git a/ext/Digest/SHA/src/sha.c b/ext/Digest/SHA/src/sha.c
new file mode 100644 (file)
index 0000000..9fb7775
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * sha.c: routines to compute SHA-1/224/256/384/512 digests
+ *
+ * Ref: NIST FIPS PUB 180-2 Secure Hash Standard
+ *
+ * Copyright (C) 2003-2005 Mark Shelor, All Rights Reserved
+ *
+ * Version: 5.32
+ * Fri Dec  2 02:32:20 MST 2005
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include "sha.h"
+#include "sha64bit.h"
+
+#define W32    SHA32                   /* useful abbreviations */
+#define C32    SHA32_CONST
+#define SR32   SHA32_SHR
+#define SL32   SHA32_SHL
+#define LO32   SHA_LO32
+#define UCHR   unsigned char
+#define UINT   unsigned int
+#define ULNG   unsigned long
+#define VP     void *
+
+#define ROTR(x, n)     (SR32(x, n) | SL32(x, 32-(n)))
+#define ROTL(x, n)     (SL32(x, n) | SR32(x, 32-(n)))
+
+#define Ch(x, y, z)    ((z) ^ ((x) & ((y) ^ (z))))
+#define Pa(x, y, z)    ((x) ^ (y) ^ (z))
+#define Ma(x, y, z)    (((x) & (y)) | ((z) & ((x) | (y))))
+
+#define SIGMA0(x)      (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SIGMA1(x)      (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define sigma0(x)      (ROTR(x,  7) ^ ROTR(x, 18) ^ SR32(x,  3))
+#define sigma1(x)      (ROTR(x, 17) ^ ROTR(x, 19) ^ SR32(x, 10))
+
+#define K1     C32(0x5a827999)         /* SHA-1 constants */
+#define K2     C32(0x6ed9eba1)
+#define K3     C32(0x8f1bbcdc)
+#define K4     C32(0xca62c1d6)
+
+static W32 K256[64] =                  /* SHA-224/256 constants */
+{
+       C32(0x428a2f98), C32(0x71374491), C32(0xb5c0fbcf), C32(0xe9b5dba5),
+       C32(0x3956c25b), C32(0x59f111f1), C32(0x923f82a4), C32(0xab1c5ed5),
+       C32(0xd807aa98), C32(0x12835b01), C32(0x243185be), C32(0x550c7dc3),
+       C32(0x72be5d74), C32(0x80deb1fe), C32(0x9bdc06a7), C32(0xc19bf174),
+       C32(0xe49b69c1), C32(0xefbe4786), C32(0x0fc19dc6), C32(0x240ca1cc),
+       C32(0x2de92c6f), C32(0x4a7484aa), C32(0x5cb0a9dc), C32(0x76f988da),
+       C32(0x983e5152), C32(0xa831c66d), C32(0xb00327c8), C32(0xbf597fc7),
+       C32(0xc6e00bf3), C32(0xd5a79147), C32(0x06ca6351), C32(0x14292967),
+       C32(0x27b70a85), C32(0x2e1b2138), C32(0x4d2c6dfc), C32(0x53380d13),
+       C32(0x650a7354), C32(0x766a0abb), C32(0x81c2c92e), C32(0x92722c85),
+       C32(0xa2bfe8a1), C32(0xa81a664b), C32(0xc24b8b70), C32(0xc76c51a3),
+       C32(0xd192e819), C32(0xd6990624), C32(0xf40e3585), C32(0x106aa070),
+       C32(0x19a4c116), C32(0x1e376c08), C32(0x2748774c), C32(0x34b0bcb5),
+       C32(0x391c0cb3), C32(0x4ed8aa4a), C32(0x5b9cca4f), C32(0x682e6ff3),
+       C32(0x748f82ee), C32(0x78a5636f), C32(0x84c87814), C32(0x8cc70208),
+       C32(0x90befffa), C32(0xa4506ceb), C32(0xbef9a3f7), C32(0xc67178f2)
+};
+
+static W32 H01[5] =                    /* SHA-1 initial hash value */
+{
+       C32(0x67452301), C32(0xefcdab89), C32(0x98badcfe),
+       C32(0x10325476), C32(0xc3d2e1f0)
+};
+
+static W32 H0224[8] =                  /* SHA-224 initial hash value */
+{
+       C32(0xc1059ed8), C32(0x367cd507), C32(0x3070dd17), C32(0xf70e5939),
+       C32(0xffc00b31), C32(0x68581511), C32(0x64f98fa7), C32(0xbefa4fa4)
+};
+
+static W32 H0256[8] =                  /* SHA-256 initial hash value */
+{
+       C32(0x6a09e667), C32(0xbb67ae85), C32(0x3c6ef372), C32(0xa54ff53a),
+       C32(0x510e527f), C32(0x9b05688c), C32(0x1f83d9ab), C32(0x5be0cd19)
+};
+
+static void sha1(s, block)             /* SHA-1 transform */
+SHA *s;
+UCHR *block;
+{
+       W32 a, b, c, d, e;
+       SHA_STO_CLASS W32 W[16];
+       W32 *wp = W;
+       W32 *H = (W32 *) s->H;
+
+       SHA32_SCHED(W, block);
+
+/*
+ * Use SHA-1 alternate method from FIPS PUB 180-2 (ref. 6.1.3)
+ *
+ * To improve performance, unroll the loop and consolidate assignments
+ * by changing the roles of variables "a" through "e" at each step.
+ * Note that the variable "T" is no longer needed.
+ */
+
+#define M1(a, b, c, d, e, f, k, w)             \
+       e += ROTL(a, 5) + f(b, c, d) + k + w;   \
+       b =  ROTL(b, 30)
+
+#define M11(f, k, w)   M1(a, b, c, d, e, f, k, w);
+#define M12(f, k, w)   M1(e, a, b, c, d, f, k, w);
+#define M13(f, k, w)   M1(d, e, a, b, c, f, k, w);
+#define M14(f, k, w)   M1(c, d, e, a, b, f, k, w);
+#define M15(f, k, w)   M1(b, c, d, e, a, f, k, w);
+
+#define W11(s) W[(s+ 0) & 0xf]
+#define W12(s) W[(s+13) & 0xf]
+#define W13(s) W[(s+ 8) & 0xf]
+#define W14(s) W[(s+ 2) & 0xf]
+
+#define A1(s)  (W11(s) = ROTL(W11(s) ^ W12(s) ^ W13(s) ^ W14(s), 1))
+
+       a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4];
+
+       M11(Ch, K1,  *wp++); M12(Ch, K1,  *wp++); M13(Ch, K1,  *wp++);
+       M14(Ch, K1,  *wp++); M15(Ch, K1,  *wp++); M11(Ch, K1,  *wp++);
+       M12(Ch, K1,  *wp++); M13(Ch, K1,  *wp++); M14(Ch, K1,  *wp++);
+       M15(Ch, K1,  *wp++); M11(Ch, K1,  *wp++); M12(Ch, K1,  *wp++);
+       M13(Ch, K1,  *wp++); M14(Ch, K1,  *wp++); M15(Ch, K1,  *wp++);
+       M11(Ch, K1,  *wp  ); M12(Ch, K1, A1( 0)); M13(Ch, K1, A1( 1));
+       M14(Ch, K1, A1( 2)); M15(Ch, K1, A1( 3)); M11(Pa, K2, A1( 4));
+       M12(Pa, K2, A1( 5)); M13(Pa, K2, A1( 6)); M14(Pa, K2, A1( 7));
+       M15(Pa, K2, A1( 8)); M11(Pa, K2, A1( 9)); M12(Pa, K2, A1(10));
+       M13(Pa, K2, A1(11)); M14(Pa, K2, A1(12)); M15(Pa, K2, A1(13));
+       M11(Pa, K2, A1(14)); M12(Pa, K2, A1(15)); M13(Pa, K2, A1( 0));
+       M14(Pa, K2, A1( 1)); M15(Pa, K2, A1( 2)); M11(Pa, K2, A1( 3));
+       M12(Pa, K2, A1( 4)); M13(Pa, K2, A1( 5)); M14(Pa, K2, A1( 6));
+       M15(Pa, K2, A1( 7)); M11(Ma, K3, A1( 8)); M12(Ma, K3, A1( 9));
+       M13(Ma, K3, A1(10)); M14(Ma, K3, A1(11)); M15(Ma, K3, A1(12));
+       M11(Ma, K3, A1(13)); M12(Ma, K3, A1(14)); M13(Ma, K3, A1(15));
+       M14(Ma, K3, A1( 0)); M15(Ma, K3, A1( 1)); M11(Ma, K3, A1( 2));
+       M12(Ma, K3, A1( 3)); M13(Ma, K3, A1( 4)); M14(Ma, K3, A1( 5));
+       M15(Ma, K3, A1( 6)); M11(Ma, K3, A1( 7)); M12(Ma, K3, A1( 8));
+       M13(Ma, K3, A1( 9)); M14(Ma, K3, A1(10)); M15(Ma, K3, A1(11));
+       M11(Pa, K4, A1(12)); M12(Pa, K4, A1(13)); M13(Pa, K4, A1(14));
+       M14(Pa, K4, A1(15)); M15(Pa, K4, A1( 0)); M11(Pa, K4, A1( 1));
+       M12(Pa, K4, A1( 2)); M13(Pa, K4, A1( 3)); M14(Pa, K4, A1( 4));
+       M15(Pa, K4, A1( 5)); M11(Pa, K4, A1( 6)); M12(Pa, K4, A1( 7));
+       M13(Pa, K4, A1( 8)); M14(Pa, K4, A1( 9)); M15(Pa, K4, A1(10));
+       M11(Pa, K4, A1(11)); M12(Pa, K4, A1(12)); M13(Pa, K4, A1(13));
+       M14(Pa, K4, A1(14)); M15(Pa, K4, A1(15));
+
+       H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e;
+}
+
+static void sha256(s, block)           /* SHA-224/256 transform */
+SHA *s;
+UCHR *block;
+{
+       W32 a, b, c, d, e, f, g, h, T1;
+       SHA_STO_CLASS W32 W[16];
+       W32 *kp = K256;
+       W32 *wp = W;
+       W32 *H = (W32 *) s->H;
+
+       SHA32_SCHED(W, block);
+
+/*
+ * Use same technique as in sha1()
+ *
+ * To improve performance, unroll the loop and consolidate assignments
+ * by changing the roles of variables "a" through "h" at each step.
+ * Note that the variable "T2" is no longer needed.
+ */
+
+#define M2(a, b, c, d, e, f, g, h, w)                          \
+       T1 = h  + SIGMA1(e) + Ch(e, f, g) + (*kp++) + w;        \
+       h  = T1 + SIGMA0(a) + Ma(a, b, c); d += T1;
+
+#define W21(s) W[(s+ 0) & 0xf]
+#define W22(s) W[(s+14) & 0xf]
+#define W23(s) W[(s+ 9) & 0xf]
+#define W24(s) W[(s+ 1) & 0xf]
+
+#define A2(s)  (W21(s) += sigma1(W22(s)) + W23(s) + sigma0(W24(s)))
+
+#define M21(w) M2(a, b, c, d, e, f, g, h, w)
+#define M22(w) M2(h, a, b, c, d, e, f, g, w)
+#define M23(w) M2(g, h, a, b, c, d, e, f, w)
+#define M24(w) M2(f, g, h, a, b, c, d, e, w)
+#define M25(w) M2(e, f, g, h, a, b, c, d, w)
+#define M26(w) M2(d, e, f, g, h, a, b, c, w)
+#define M27(w) M2(c, d, e, f, g, h, a, b, w)
+#define M28(w) M2(b, c, d, e, f, g, h, a, w)
+
+       a = H[0]; b = H[1]; c = H[2]; d = H[3];
+       e = H[4]; f = H[5]; g = H[6]; h = H[7];
+
+       M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++);
+       M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp++);
+       M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++);
+       M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp  );
+       M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
+       M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
+       M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
+       M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
+       M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
+       M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
+       M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
+       M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
+       M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
+       M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
+       M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
+       M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
+
+       H[0] += a; H[1] += b; H[2] += c; H[3] += d;
+       H[4] += e; H[5] += f; H[6] += g; H[7] += h;
+}
+
+#include "sha64bit.c"
+
+#define SETBIT(s, pos) s[(pos) >> 3] |=  (0x01 << (7 - (pos) % 8))
+#define CLRBIT(s, pos) s[(pos) >> 3] &= ~(0x01 << (7 - (pos) % 8))
+#define NBYTES(nbits)  ((nbits) > 0 ? 1 + (((nbits) - 1) >> 3) : 0)
+#define HEXLEN(nbytes) ((nbytes) << 1)
+#define B64LEN(nbytes) (((nbytes) % 3 == 0) ? ((nbytes) / 3) * 4 \
+                       : ((nbytes) / 3) * 4 + ((nbytes) % 3) + 1)
+
+/* w32mem: writes 32-bit word to memory in big-endian order */
+static void w32mem(mem, w32)
+UCHR *mem;
+W32 w32;
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               *mem++ = (UCHR) (SR32(w32, 24-i*8) & 0xff);
+}
+
+/* digcpy: writes current state to digest buffer */
+static void digcpy(s)
+SHA *s;
+{
+       UINT i;
+       UCHR *d = s->digest;
+       W32 *p32 = (W32 *) s->H;
+       W64 *p64 = (W64 *) s->H;
+
+       if (s->alg <= SHA256)
+               for (i = 0; i < 8; i++, d += 4)
+                       w32mem(d, *p32++);
+       else
+               for (i = 0; i < 8; i++, d += 8) {
+                       w32mem(d, (W32) ((*p64 >> 16) >> 16));
+                       w32mem(d+4, (W32) (*p64++ & SHA32_MAX));
+               }
+}
+
+#define SHA_INIT(algo, transform)                                      \
+       do {                                                            \
+               memset(s, 0, sizeof(SHA));                              \
+               s->alg = algo; s->sha = sha ## transform;               \
+               memcpy(s->H, H0 ## algo, sizeof(H0 ## algo));           \
+               s->blocksize = SHA ## algo ## _BLOCK_BITS;              \
+               s->digestlen = SHA ## algo ## _DIGEST_BITS >> 3;        \
+       } while (0)
+
+/* sharewind: re-initializes the digest object */
+void sharewind(s)
+SHA *s;
+{
+       if      (s->alg == SHA1)   SHA_INIT(1, 1);
+       else if (s->alg == SHA224) SHA_INIT(224, 256);
+       else if (s->alg == SHA256) SHA_INIT(256, 256);
+       else if (s->alg == SHA384) SHA_INIT(384, 512);
+       else if (s->alg == SHA512) SHA_INIT(512, 512);
+}
+
+/* shaopen: creates a new digest object */
+SHA *shaopen(alg)
+int alg;
+{
+       SHA *s;
+
+       if (alg != SHA1 && alg != SHA224 && alg != SHA256 &&
+               alg != SHA384 && alg != SHA512)
+               return(NULL);
+       if (alg >= SHA384 && !sha_384_512)
+               return(NULL);
+       SHA_newz(0, s, 1, SHA);
+       if (s == NULL)
+               return(NULL);
+       s->alg = alg;
+       sharewind(s);
+       return(s);
+}
+
+/* shadirect: updates state directly (w/o going through s->block) */
+static ULNG shadirect(bitstr, bitcnt, s)
+UCHR *bitstr;
+ULNG bitcnt;
+SHA *s;
+{
+       ULNG savecnt = bitcnt;
+
+       while (bitcnt >= s->blocksize) {
+               s->sha(s, bitstr);
+               bitstr += (s->blocksize >> 3);
+               bitcnt -= s->blocksize;
+       }
+       if (bitcnt > 0) {
+               memcpy(s->block, bitstr, NBYTES(bitcnt));
+               s->blockcnt = bitcnt;
+       }
+       return(savecnt);
+}
+
+/* shabytes: updates state for byte-aligned input data */
+static ULNG shabytes(bitstr, bitcnt, s)
+UCHR *bitstr;
+ULNG bitcnt;
+SHA *s;
+{
+       UINT offset;
+       UINT nbits;
+       ULNG savecnt = bitcnt;
+
+       offset = s->blockcnt >> 3;
+       if (s->blockcnt + bitcnt >= s->blocksize) {
+               nbits = s->blocksize - s->blockcnt;
+               memcpy(s->block+offset, bitstr, nbits>>3);
+               bitcnt -= nbits;
+               bitstr += (nbits >> 3);
+               s->sha(s, s->block), s->blockcnt = 0;
+               shadirect(bitstr, bitcnt, s);
+       }
+       else {
+               memcpy(s->block+offset, bitstr, NBYTES(bitcnt));
+               s->blockcnt += bitcnt;
+       }
+       return(savecnt);
+}
+
+/* shabits: updates state for bit-aligned input data */
+static ULNG shabits(bitstr, bitcnt, s)
+UCHR *bitstr;
+ULNG bitcnt;
+SHA *s;
+{
+       UINT i;
+       UINT gap;
+       ULNG nbits;
+       UCHR buf[1<<9];
+       UINT bufsize = sizeof(buf);
+       ULNG bufbits = (ULNG) bufsize << 3;
+       UINT nbytes = NBYTES(bitcnt);
+       ULNG savecnt = bitcnt;
+
+       gap = 8 - s->blockcnt % 8;
+       s->block[s->blockcnt>>3] &= ~0 << gap;
+       s->block[s->blockcnt>>3] |= *bitstr >> (8 - gap);
+       s->blockcnt += bitcnt < gap ? bitcnt : gap;
+       if (bitcnt < gap)
+               return(savecnt);
+       if (s->blockcnt == s->blocksize)
+               s->sha(s, s->block), s->blockcnt = 0;
+       if ((bitcnt -= gap) == 0)
+               return(savecnt);
+       while (nbytes > bufsize) {
+               for (i = 0; i < bufsize; i++)
+                       buf[i] = bitstr[i] << gap | bitstr[i+1] >> (8-gap);
+               nbits = bitcnt < bufbits ? bitcnt : bufbits;
+               shabytes(buf, nbits, s);
+               bitcnt -= nbits, bitstr += bufsize, nbytes -= bufsize;
+       }
+       for (i = 0; i < nbytes - 1; i++)
+               buf[i] = bitstr[i] << gap | bitstr[i+1] >> (8-gap);
+       buf[nbytes-1] = bitstr[nbytes-1] << gap;
+       shabytes(buf, bitcnt, s);
+       return(savecnt);
+}
+
+/* shawrite: triggers a state update using data in bitstr/bitcnt */
+ULNG shawrite(bitstr, bitcnt, s)
+UCHR *bitstr;
+ULNG bitcnt;
+SHA *s;
+{
+       if (bitcnt < 1)
+               return(0);
+       if (SHA_LO32(s->lenll += bitcnt) < bitcnt)
+               if (SHA_LO32(++s->lenlh) == 0)
+                       if (SHA_LO32(++s->lenhl) == 0)
+                               s->lenhh++;
+       if (s->blockcnt == 0)
+               return(shadirect(bitstr, bitcnt, s));
+       else if (s->blockcnt % 8 == 0)
+               return(shabytes(bitstr, bitcnt, s));
+       else
+               return(shabits(bitstr, bitcnt, s));
+}
+
+/* shafinish: pads remaining block(s) and computes final digest state */
+void shafinish(s)
+SHA *s;
+{
+       UINT lenpos, lhpos, llpos;
+
+       lenpos = s->blocksize == SHA1_BLOCK_BITS ? 448 : 896;
+       lhpos  = s->blocksize == SHA1_BLOCK_BITS ?  56 : 120;
+       llpos  = s->blocksize == SHA1_BLOCK_BITS ?  60 : 124;
+       SETBIT(s->block, s->blockcnt), s->blockcnt++;
+       while (s->blockcnt > lenpos)
+               if (s->blockcnt < s->blocksize)
+                       CLRBIT(s->block, s->blockcnt), s->blockcnt++;
+               else
+                       s->sha(s, s->block), s->blockcnt = 0;
+       while (s->blockcnt < lenpos)
+               CLRBIT(s->block, s->blockcnt), s->blockcnt++;
+       if (s->blocksize > SHA1_BLOCK_BITS) {
+               w32mem(s->block + 112, s->lenhh);
+               w32mem(s->block + 116, s->lenhl);
+       }
+       w32mem(s->block + lhpos, s->lenlh);
+       w32mem(s->block + llpos, s->lenll);
+       s->sha(s, s->block);
+}
+
+/* shadigest: returns pointer to current digest (binary) */
+UCHR *shadigest(s)
+SHA *s;
+{
+       digcpy(s);
+       return(s->digest);
+}
+
+/* shahex: returns pointer to current digest (hexadecimal) */
+char *shahex(s)
+SHA *s;
+{
+       int i;
+
+       digcpy(s);
+       s->hex[0] = '\0';
+       if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex))
+               return(s->hex);
+       for (i = 0; i < s->digestlen; i++)
+               sprintf(s->hex+i*2, "%02x", s->digest[i]);
+       return(s->hex);
+}
+
+/* map: translation map for Base 64 encoding */
+static char map[] =            
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* encbase64: encodes input (0 to 3 bytes) into Base 64 */
+static void encbase64(in, n, out)
+UCHR *in;
+int n;
+char *out;
+{
+       UCHR byte[3] = {0, 0, 0};
+
+       out[0] = '\0';
+       if (n < 1 || n > 3)
+               return;
+       memcpy(byte, in, n);
+       out[0] = map[byte[0] >> 2];
+       out[1] = map[((byte[0] & 0x03) << 4) | (byte[1] >> 4)];
+       out[2] = map[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)];
+       out[3] = map[byte[2] & 0x3f];
+       out[n+1] = '\0';
+}
+
+/* shabase64: returns pointer to current digest (Base 64) */
+char *shabase64(s)
+SHA *s;
+{
+       int n;
+       UCHR *q;
+       char out[5];
+
+       digcpy(s);
+       s->base64[0] = '\0';
+       if (B64LEN(s->digestlen) >= sizeof(s->base64))
+               return(s->base64);
+       for (n = s->digestlen, q = s->digest; n > 3; n -= 3, q += 3) {
+               encbase64(q, 3, out);
+               strcat(s->base64, out);
+       }
+       encbase64(q, n, out);
+       strcat(s->base64, out);
+       return(s->base64);
+}
+
+/* shadsize: returns length of digest in bytes */
+int shadsize(s)
+SHA *s;
+{
+       return(s->digestlen);
+}
+
+/* shadup: duplicates current digest object */
+SHA *shadup(s)
+SHA *s;
+{
+       SHA *p;
+
+       SHA_new(0, p, 1, SHA);
+       if (p == NULL)
+               return(NULL);
+       memcpy(p, s, sizeof(SHA));
+       return(p);
+}
+
+/* shadump: dumps digest object to a human-readable ASCII file */
+int shadump(file, s)
+char *file;
+SHA *s;
+{
+       unsigned int i, j;
+       SHA_FILE *f;
+       UCHR *p = shadigest(s);
+
+       if (file == NULL || strlen(file) == 0)
+               f = SHA_stdout();
+       else if ((f = SHA_open(file, "w")) == NULL)
+               return(0);
+       SHA_fprintf(f, "alg:%d\nH", s->alg);
+       for (i = 0; i < 8; i++)
+               for (j = 0; j < (s->alg <= 256 ? 4 : 8); j++)
+                       SHA_fprintf(f, "%s%02x", j==0 ? ":" : "", *p++);
+       SHA_fprintf(f, "\nblock");
+       for (i = 0; i < s->blocksize>>3; i++)
+               SHA_fprintf(f, ":%02x", s->block[i]);
+       SHA_fprintf(f, "\nblockcnt:%u\n", s->blockcnt);
+       SHA_fprintf(f, "lenhh:%lu\nlenhl:%lu\nlenlh:%lu\nlenll:%lu\n",
+               (ULNG) LO32(s->lenhh), (ULNG) LO32(s->lenhl),
+               (ULNG) LO32(s->lenlh), (ULNG) LO32(s->lenll));
+       if (f != SHA_stdout())
+               SHA_close(f);
+       return(1);
+}
+
+/* fgetstr: reads (and returns pointer to) next line of file */
+static char *fgetstr(line, maxsize, f)
+char *line;
+UINT maxsize;
+SHA_FILE *f;
+{
+       char *p;
+
+       if (SHA_feof(f) || maxsize == 0)
+               return(NULL);
+       for (p = line; !SHA_feof(f) && maxsize > 1; maxsize--)
+               if ((*p++ = SHA_getc(f)) == '\n')
+                       break;
+       *p = '\0';
+       return(line);
+}
+
+/* empty: returns true if line contains only whitespace characters */
+static int empty(line)
+char *line;
+{
+       char *p;
+
+       for (p = line; *p; p++)
+               if (!isspace(*p))
+                       return(0);
+       return(1);
+}
+
+/* getval: null-terminates field value, and sets pointer to rest of line */
+static char *getval(line, pprest)
+char *line;
+char **pprest;
+{
+       char *p, *v;
+
+       for (v = line; *v == ':' || isspace(*v); v++)
+               ;
+       for (p = v; *p; p++) {
+               if (*p == ':' || isspace(*p)) {
+                       *p++ = '\0';
+                       break;
+               }
+       }
+       *pprest = p;
+       return(p == v ? NULL : v);
+}
+
+/* types of values present in dump file */
+#define T_C 1                  /* character */
+#define T_I 2                  /* normal integer */
+#define T_L 3                  /* 32-bit value */
+#define T_Q 4                  /* 64-bit value */
+
+/* ldvals: checks next line in dump file against tag, and loads values */
+static int ldvals(f, tag, type, pval, reps, base)
+SHA_FILE *f;
+char *tag;
+int type;
+void *pval;
+int reps;
+int base;
+{
+       char *p, *pr, line[512];
+       UCHR *pc = (UCHR *) pval; UINT *pi = (UINT *) pval;
+       W32  *pl = (W32  *) pval; W64  *pq = (W64  *) pval;
+
+       while ((p = fgetstr(line, sizeof(line), f)) != NULL)
+               if (line[0] != '#' && !empty(line))
+                       break;
+       if (p == NULL || strcmp(getval(line, &pr), tag) != 0)
+               return(0);
+       while (reps-- > 0) {
+               if ((p = getval(pr, &pr)) == NULL)
+                       return(1);
+               switch (type) {
+               case T_C: *pc++ = (UCHR) strtoul(p, NULL, base); break;
+               case T_I: *pi++ = (UINT) strtoul(p, NULL, base); break;
+               case T_L: *pl++ = (W32 ) strtoul(p, NULL, base); break;
+               case T_Q: *pq++ = (W64 ) strto64(p            ); break;
+               }
+       }
+       return(1);
+}
+
+/* closeall: closes dump file and de-allocates digest object */
+static SHA *closeall(f, s)
+SHA_FILE *f;
+SHA *s;
+{
+       if (f != NULL && f != SHA_stdin())
+               SHA_close(f);
+       if (s != NULL)
+               shaclose(s);
+       return(NULL);
+}
+
+/* shaload: creates digest object corresponding to contents of dump file */
+SHA *shaload(file)
+char *file;
+{
+       int alg;
+       SHA *s = NULL;
+       SHA_FILE *f;
+
+       if (file == NULL || strlen(file) == 0)
+               f = SHA_stdin();
+       else if ((f = SHA_open(file, "r")) == NULL)
+               return(NULL);
+       if (
+               /* avoid parens by exploiting precedence of (type)&-> */
+               !ldvals(f,"alg",T_I,(VP)&alg,1,10)                      ||
+               ((s = shaopen(alg)) == NULL)                            ||
+               !ldvals(f,"H",alg<=SHA256?T_L:T_Q,(VP)s->H,8,16)        ||
+               !ldvals(f,"block",T_C,(VP)s->block,s->blocksize/8,16)   ||
+               !ldvals(f,"blockcnt",T_I,(VP)&s->blockcnt,1,10)         ||
+               (alg <= SHA256 && s->blockcnt >= SHA1_BLOCK_BITS)       ||
+               (alg >= SHA384 && s->blockcnt >= SHA384_BLOCK_BITS)     ||
+               !ldvals(f,"lenhh",T_L,(VP)&s->lenhh,1,10)               ||
+               !ldvals(f,"lenhl",T_L,(VP)&s->lenhl,1,10)               ||
+               !ldvals(f,"lenlh",T_L,(VP)&s->lenlh,1,10)               ||
+               !ldvals(f,"lenll",T_L,(VP)&s->lenll,1,10)
+       )
+               return(closeall(f, s));
+       if (f != SHA_stdin())
+               SHA_close(f);
+       return(s);
+}
+
+/* shaclose: de-allocates digest object */
+int shaclose(s)
+SHA *s;
+{
+       if (s != NULL) {
+               memset(s, 0, sizeof(SHA));
+               SHA_free(s);
+       }
+       return(0);
+}
diff --git a/ext/Digest/SHA/src/sha.h b/ext/Digest/SHA/src/sha.h
new file mode 100644 (file)
index 0000000..0cbc9c3
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * sha.h: header file for SHA-1/224/256/384/512 routines
+ *
+ * Ref: NIST FIPS PUB 180-2 Secure Hash Standard
+ *
+ * Copyright (C) 2003-2005 Mark Shelor, All Rights Reserved
+ *
+ * Version: 5.32
+ * Fri Dec  2 02:32:20 MST 2005
+ *
+ */
+
+#ifndef _INCLUDE_SHA_H_
+#define _INCLUDE_SHA_H_
+
+#include <limits.h>
+
+#define SHA32_MAX      4294967295U
+#define SHA64_MAX      18446744073709551615U
+
+#define SHA32_SHR(x, n)        ((x) >> (n))
+#define SHA32_SHL(x, n)        ((x) << (n))
+
+#define SHA64_SHR(x, n)        ((x) >> (n))
+#define SHA64_SHL(x, n)        ((x) << (n))
+
+#define SHA32_ALIGNED
+#define SHA64_ALIGNED
+
+#define SHA_LO32(x)    (x)
+
+#if USHRT_MAX == SHA32_MAX
+       #define SHA32   unsigned short
+       #define SHA32_CONST(c)  c ## U
+#elif UINT_MAX == SHA32_MAX
+       #define SHA32   unsigned int
+       #define SHA32_CONST(c)  c ## U
+#elif ULONG_MAX == SHA32_MAX
+       #define SHA32   unsigned long
+       #define SHA32_CONST(c)  c ## UL
+#else
+       #undef  SHA32_ALIGNED
+       #undef  SHA_LO32
+       #define SHA_LO32(x)     ((x) & SHA32_MAX)
+       #undef  SHA32_SHR
+       #define SHA32_SHR(x, n) (SHA_LO32(x) >> (n))
+       #define SHA32   unsigned long
+       #define SHA32_CONST(c)  c ## UL
+#endif
+
+#if defined(ULONG_LONG_MAX) || defined(ULLONG_MAX) || defined(HAS_LONG_LONG)
+       #define SHA_ULL_EXISTS
+#endif
+
+#if (((ULONG_MAX >> 16) >> 16) >> 16) >> 15 == 1UL
+       #define SHA64   unsigned long
+       #define SHA64_CONST(c)  c ## UL
+#elif defined(SHA_ULL_EXISTS) && defined(LONGLONGSIZE) && LONGLONGSIZE == 8
+       #define SHA64   unsigned long long
+       #define SHA64_CONST(c)  c ## ULL
+#elif defined(SHA_ULL_EXISTS)
+       #undef  SHA64_ALIGNED
+       #undef  SHA64_SHR
+       #define SHA64_SHR(x, n) (((x) & SHA64_MAX) >> (n))
+       #define SHA64   unsigned long long
+       #define SHA64_CONST(c)  c ## ULL
+
+       /* The following cases detect compilers that
+        * support 64-bit types in a non-standard way */
+
+#elif defined(_MSC_VER)                                        /* Microsoft C */
+       #define SHA64   unsigned __int64
+       #define SHA64_CONST(c)  (SHA64) c
+#endif
+
+#if defined(SHA64) && !defined(NO_SHA_384_512)
+       #define SHA_384_512
+#endif
+
+#if defined(BYTEORDER) && (BYTEORDER & 0xffff) == 0x4321
+       #if defined(SHA32_ALIGNED)
+               #define SHA32_SCHED(W, b)       memcpy(W, b, 64)
+       #endif
+       #if defined(SHA64) && defined(SHA64_ALIGNED)
+               #define SHA64_SCHED(W, b)       memcpy(W, b, 128)
+       #endif
+#endif
+
+#if !defined(SHA32_SCHED)
+       #define SHA32_SCHED(W, b) { int t; SHA32 *q = W;                \
+               for (t = 0; t < 16; t++, b += 4) *q++ =                 \
+                       (SHA32) b[0] << 24 | (SHA32) b[1] << 16 |       \
+                       (SHA32) b[2] <<  8 | (SHA32) b[3]; }
+#endif
+
+#if defined(SHA64) && !defined(SHA64_SCHED)
+       #define SHA64_SCHED(W, b) { int t; SHA64 *q = W;                \
+               for (t = 0; t < 16; t++, b += 8) *q++ =                 \
+                       (SHA64) b[0] << 56 | (SHA64) b[1] << 48 |       \
+                       (SHA64) b[2] << 40 | (SHA64) b[3] << 32 |       \
+                       (SHA64) b[4] << 24 | (SHA64) b[5] << 16 |       \
+                       (SHA64) b[6] <<  8 | (SHA64) b[7]; }
+#endif
+
+/*
+ * SHA_STO_CLASS: default to auto storage class for message schedule
+ * arrays inside transform routines.  Note that redefining this to
+ * static might improve performance on some platforms (e.g. Intel).
+ */
+
+#if !defined(SHA_STO_CLASS)
+       #define SHA_STO_CLASS   auto
+#endif
+
+/* Override use of static arrays if compiling for thread-safety */
+#ifdef SHA_THREAD_SAFE
+       #undef  SHA_STO_CLASS
+       #define SHA_STO_CLASS   auto
+#endif
+
+/* Configure memory management and I/O for Perl or standalone C */
+#ifdef SHA_PERL_MODULE
+       #define SHA_new                 New
+       #define SHA_newz                Newz
+       #define SHA_free                Safefree
+       #define SHA_FILE                PerlIO
+       #define SHA_stdin()             PerlIO_stdin()
+       #define SHA_stdout()            PerlIO_stdout()
+       #define SHA_open                PerlIO_open
+       #define SHA_close               PerlIO_close
+       #define SHA_fprintf             PerlIO_printf
+       #define SHA_feof                PerlIO_eof
+       #define SHA_getc                PerlIO_getc
+#else
+       #define SHA_new(id, p, n, t)    p = (t *) malloc(sizeof(t))
+       #define SHA_newz(id, p, n, t)   p = (t *) calloc(n, sizeof(t))
+       #define SHA_free                free
+       #define SHA_FILE                FILE
+       #define SHA_stdin()             stdin
+       #define SHA_stdout()            stdout
+       #define SHA_open                fopen
+       #define SHA_close               fclose
+       #define SHA_fprintf             fprintf
+       #define SHA_feof                feof
+       #define SHA_getc                fgetc
+#endif
+
+#define SHA1   1
+#define SHA224 224
+#define SHA256 256
+#define SHA384 384
+#define SHA512 512
+
+#define SHA1_BLOCK_BITS                512
+#define SHA224_BLOCK_BITS      SHA1_BLOCK_BITS
+#define SHA256_BLOCK_BITS      SHA1_BLOCK_BITS
+#define SHA384_BLOCK_BITS      1024
+#define SHA512_BLOCK_BITS      SHA384_BLOCK_BITS
+
+#define SHA1_DIGEST_BITS       160
+#define SHA224_DIGEST_BITS     224
+#define SHA256_DIGEST_BITS     256
+#define SHA384_DIGEST_BITS     384
+#define SHA512_DIGEST_BITS     512
+
+#define SHA_MAX_BLOCK_BITS     SHA512_BLOCK_BITS
+#define SHA_MAX_DIGEST_BITS    SHA512_DIGEST_BITS
+#define SHA_MAX_HEX_LEN                (SHA_MAX_DIGEST_BITS / 4)
+#define SHA_MAX_BASE64_LEN     (1 + (SHA_MAX_DIGEST_BITS / 6))
+
+#if defined(SHA64)
+       #define SHA_H_SIZE      sizeof(SHA64) * 8
+#else
+       #define SHA_H_SIZE      sizeof(SHA32) * 8
+#endif
+
+typedef struct {
+       int alg;
+       void (*sha)();
+       unsigned char H[SHA_H_SIZE];
+       unsigned char block[SHA_MAX_BLOCK_BITS/8];
+       unsigned int blockcnt;
+       unsigned int blocksize;
+       SHA32 lenhh, lenhl, lenlh, lenll;
+       unsigned char digest[SHA_MAX_DIGEST_BITS/8];
+       int digestlen;
+       char hex[SHA_MAX_HEX_LEN+1];
+       char base64[SHA_MAX_BASE64_LEN+1];
+} SHA;
+
+#define SHA_FMT_RAW 1
+#define SHA_FMT_HEX 2
+#define SHA_FMT_BASE64 3
+
+#if defined(__STDC__) && __STDC__ != 0
+       #define _SHA_P(protos)  protos
+#else
+       #define _SHA_P(protos)  ()
+#endif
+
+#define _SHA_STATE     SHA *s
+#define _SHA_ALG       int alg
+#define _SHA_DATA      unsigned char *bitstr, unsigned long bitcnt
+#define _SHA_FNAME     char *filename
+
+SHA            *shaopen        _SHA_P((_SHA_ALG));
+unsigned long   shawrite       _SHA_P((_SHA_DATA, _SHA_STATE));
+void            shafinish      _SHA_P((_SHA_STATE));
+void            sharewind      _SHA_P((_SHA_STATE));
+unsigned char  *shadigest      _SHA_P((_SHA_STATE));
+char           *shahex         _SHA_P((_SHA_STATE));
+char           *shabase64      _SHA_P((_SHA_STATE));
+int             shadsize       _SHA_P((_SHA_STATE));
+SHA            *shadup         _SHA_P((_SHA_STATE));
+int             shadump        _SHA_P((_SHA_FNAME, _SHA_STATE));
+SHA            *shaload        _SHA_P((_SHA_FNAME));
+int             shaclose       _SHA_P((_SHA_STATE));
+
+unsigned char  *sha1digest     _SHA_P((_SHA_DATA));
+char           *sha1hex        _SHA_P((_SHA_DATA));
+char           *sha1base64     _SHA_P((_SHA_DATA));
+unsigned char  *sha224digest   _SHA_P((_SHA_DATA));
+char           *sha224hex      _SHA_P((_SHA_DATA));
+char           *sha224base64   _SHA_P((_SHA_DATA));
+unsigned char  *sha256digest   _SHA_P((_SHA_DATA));
+char           *sha256hex      _SHA_P((_SHA_DATA));
+char           *sha256base64   _SHA_P((_SHA_DATA));
+unsigned char  *sha384digest   _SHA_P((_SHA_DATA));
+char           *sha384hex      _SHA_P((_SHA_DATA));
+char           *sha384base64   _SHA_P((_SHA_DATA));
+unsigned char  *sha512digest   _SHA_P((_SHA_DATA));
+char           *sha512hex      _SHA_P((_SHA_DATA));
+char           *sha512base64   _SHA_P((_SHA_DATA));
+
+#endif /* _INCLUDE_SHA_H_ */
diff --git a/ext/Digest/SHA/src/sha64bit.c b/ext/Digest/SHA/src/sha64bit.c
new file mode 100644 (file)
index 0000000..0e499a6
--- /dev/null
@@ -0,0 +1,104 @@
+#ifdef SHA_384_512
+
+#undef sha_384_512
+#undef W64
+#undef strto64
+#undef sha512
+#undef H0384
+#undef H0512
+
+#define sha_384_512    1
+
+#define W64            SHA64           /* useful abbreviations */
+#define C64            SHA64_CONST
+#define SR64           SHA64_SHR
+#define SL64           SHA64_SHL
+
+#define ROTRQ(x, n)    (SR64(x, n) | SL64(x, 64-(n)))
+#define SIGMAQ0(x)     (ROTRQ(x, 28) ^ ROTRQ(x, 34) ^ ROTRQ(x, 39))
+#define SIGMAQ1(x)     (ROTRQ(x, 14) ^ ROTRQ(x, 18) ^ ROTRQ(x, 41))
+#define sigmaQ0(x)     (ROTRQ(x,  1) ^ ROTRQ(x,  8) ^ SR64(x,  7))
+#define sigmaQ1(x)     (ROTRQ(x, 19) ^ ROTRQ(x, 61) ^ SR64(x,  6))
+
+static W64 K512[80] =                  /* SHA-384/512 constants */
+{
+C64(0x428a2f98d728ae22), C64(0x7137449123ef65cd), C64(0xb5c0fbcfec4d3b2f),
+C64(0xe9b5dba58189dbbc), C64(0x3956c25bf348b538), C64(0x59f111f1b605d019),
+C64(0x923f82a4af194f9b), C64(0xab1c5ed5da6d8118), C64(0xd807aa98a3030242),
+C64(0x12835b0145706fbe), C64(0x243185be4ee4b28c), C64(0x550c7dc3d5ffb4e2),
+C64(0x72be5d74f27b896f), C64(0x80deb1fe3b1696b1), C64(0x9bdc06a725c71235),
+C64(0xc19bf174cf692694), C64(0xe49b69c19ef14ad2), C64(0xefbe4786384f25e3),
+C64(0x0fc19dc68b8cd5b5), C64(0x240ca1cc77ac9c65), C64(0x2de92c6f592b0275),
+C64(0x4a7484aa6ea6e483), C64(0x5cb0a9dcbd41fbd4), C64(0x76f988da831153b5),
+C64(0x983e5152ee66dfab), C64(0xa831c66d2db43210), C64(0xb00327c898fb213f),
+C64(0xbf597fc7beef0ee4), C64(0xc6e00bf33da88fc2), C64(0xd5a79147930aa725),
+C64(0x06ca6351e003826f), C64(0x142929670a0e6e70), C64(0x27b70a8546d22ffc),
+C64(0x2e1b21385c26c926), C64(0x4d2c6dfc5ac42aed), C64(0x53380d139d95b3df),
+C64(0x650a73548baf63de), C64(0x766a0abb3c77b2a8), C64(0x81c2c92e47edaee6),
+C64(0x92722c851482353b), C64(0xa2bfe8a14cf10364), C64(0xa81a664bbc423001),
+C64(0xc24b8b70d0f89791), C64(0xc76c51a30654be30), C64(0xd192e819d6ef5218),
+C64(0xd69906245565a910), C64(0xf40e35855771202a), C64(0x106aa07032bbd1b8),
+C64(0x19a4c116b8d2d0c8), C64(0x1e376c085141ab53), C64(0x2748774cdf8eeb99),
+C64(0x34b0bcb5e19b48a8), C64(0x391c0cb3c5c95a63), C64(0x4ed8aa4ae3418acb),
+C64(0x5b9cca4f7763e373), C64(0x682e6ff3d6b2b8a3), C64(0x748f82ee5defb2fc),
+C64(0x78a5636f43172f60), C64(0x84c87814a1f0ab72), C64(0x8cc702081a6439ec),
+C64(0x90befffa23631e28), C64(0xa4506cebde82bde9), C64(0xbef9a3f7b2c67915),
+C64(0xc67178f2e372532b), C64(0xca273eceea26619c), C64(0xd186b8c721c0c207),
+C64(0xeada7dd6cde0eb1e), C64(0xf57d4f7fee6ed178), C64(0x06f067aa72176fba),
+C64(0x0a637dc5a2c898a6), C64(0x113f9804bef90dae), C64(0x1b710b35131c471b),
+C64(0x28db77f523047d84), C64(0x32caab7b40c72493), C64(0x3c9ebe0a15c9bebc),
+C64(0x431d67c49c100d4c), C64(0x4cc5d4becb3e42b6), C64(0x597f299cfc657e2a),
+C64(0x5fcb6fab3ad6faec), C64(0x6c44198c4a475817)
+};
+
+static W64 H0384[8] =          /* SHA-384 initial hash value */
+{
+C64(0xcbbb9d5dc1059ed8), C64(0x629a292a367cd507), C64(0x9159015a3070dd17),
+C64(0x152fecd8f70e5939), C64(0x67332667ffc00b31), C64(0x8eb44a8768581511),
+C64(0xdb0c2e0d64f98fa7), C64(0x47b5481dbefa4fa4)
+};
+
+static W64 H0512[8] =          /* SHA-512 initial hash value */
+{
+C64(0x6a09e667f3bcc908), C64(0xbb67ae8584caa73b), C64(0x3c6ef372fe94f82b),
+C64(0xa54ff53a5f1d36f1), C64(0x510e527fade682d1), C64(0x9b05688c2b3e6c1f),
+C64(0x1f83d9abfb41bd6b), C64(0x5be0cd19137e2179)
+};
+
+/* strto64: converts hex string to a 64-bit word */
+static W64 strto64(s)
+char *s;
+{
+       char str[2] = {0, 0};
+       W64 u = C64(0);
+
+       while (isxdigit(str[0] = *s++))
+               u = (u << 4) + strtoul(str, NULL, 16);
+       return(u);
+}
+
+static void sha512(s, block)   /* SHA-384/512 transform */
+SHA *s;
+unsigned char *block;
+{
+       W64 a, b, c, d, e, f, g, h, T1, T2;
+       SHA_STO_CLASS W64 W[80];
+       W64 *H = (W64 *) s->H;
+       int t;
+
+       SHA64_SCHED(W, block);
+       for (t = 16; t < 80; t++)
+               W[t] = sigmaQ1(W[t-2]) + W[t-7] + sigmaQ0(W[t-15]) + W[t-16];
+       a = H[0]; b = H[1]; c = H[2]; d = H[3];
+       e = H[4]; f = H[5]; g = H[6]; h = H[7];
+       for (t = 0; t < 80; t++) {
+               T1 = h + SIGMAQ1(e) + Ch(e, f, g) + K512[t] + W[t];
+               T2 = SIGMAQ0(a) + Ma(a, b, c);
+               h = g; g = f; f = e; e = d + T1;
+               d = c; c = b; b = a; a = T1 + T2;
+       }
+       H[0] += a; H[1] += b; H[2] += c; H[3] += d;
+       H[4] += e; H[5] += f; H[6] += g; H[7] += h;
+}
+
+#endif /* #ifdef SHA_384_512 */
diff --git a/ext/Digest/SHA/src/sha64bit.h b/ext/Digest/SHA/src/sha64bit.h
new file mode 100644 (file)
index 0000000..5a02c92
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * The following macros supply placeholder values that enable the
+ * `sha.c' module to successfully compile when 64-bit integer types
+ * aren't present.
+ *
+ * They are appropriately redefined in `sha64bit.c` if the compiler
+ * provides a 64-bit type (i.e. when SHA_384_512 is defined).
+ */
+
+#define sha_384_512            0
+#define W64                    unsigned long
+#define strto64(p)             0
+#define sha512                 NULL
+#define H0384                  H01
+#define H0512                  H01
diff --git a/ext/Digest/SHA/src/shaxtra.c b/ext/Digest/SHA/src/shaxtra.c
new file mode 100644 (file)
index 0000000..7301fc7
--- /dev/null
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <string.h>
+#include "sha.h"
+
+static unsigned char *shacomp(alg, fmt, bitstr, bitcnt)
+int alg;
+int fmt;
+unsigned char *bitstr;
+unsigned long bitcnt;
+{
+       SHA *s;
+       static unsigned char digest[SHA_MAX_HEX_LEN+1];
+       unsigned char *ret = digest;
+
+       if ((s = shaopen(alg)) == NULL)
+               return(NULL);
+       shawrite(bitstr, bitcnt, s);
+       shafinish(s);
+       if (fmt == SHA_FMT_RAW)
+               memcpy(digest, shadigest(s), s->digestlen);
+       else if (fmt == SHA_FMT_HEX)
+               strcpy((char *) digest, shahex(s));
+       else if (fmt == SHA_FMT_BASE64)
+               strcpy((char *) digest, shabase64(s));
+       else
+               ret = NULL;
+       shaclose(s);
+       return(ret);
+}
+
+#define SHA_DIRECT(type, name, alg, fmt)                       \
+type name(bitstr, bitcnt)                                      \
+unsigned char *bitstr;                                         \
+unsigned long bitcnt;                                          \
+{                                                              \
+       return((type) shacomp(alg, fmt, bitstr, bitcnt));       \
+}
+
+SHA_DIRECT(unsigned char *, sha1digest, SHA1, SHA_FMT_RAW)
+SHA_DIRECT(char *, sha1hex, SHA1, SHA_FMT_HEX)
+SHA_DIRECT(char *, sha1base64, SHA1, SHA_FMT_BASE64)
+
+SHA_DIRECT(unsigned char *, sha224digest, SHA224, SHA_FMT_RAW)
+SHA_DIRECT(char *, sha224hex, SHA224, SHA_FMT_HEX)
+SHA_DIRECT(char *, sha224base64, SHA224, SHA_FMT_BASE64)
+
+SHA_DIRECT(unsigned char *, sha256digest, SHA256, SHA_FMT_RAW)
+SHA_DIRECT(char *, sha256hex, SHA256, SHA_FMT_HEX)
+SHA_DIRECT(char *, sha256base64, SHA256, SHA_FMT_BASE64)
+
+SHA_DIRECT(unsigned char *, sha384digest, SHA384, SHA_FMT_RAW)
+SHA_DIRECT(char *, sha384hex, SHA384, SHA_FMT_HEX)
+SHA_DIRECT(char *, sha384base64, SHA384, SHA_FMT_BASE64)
+
+SHA_DIRECT(unsigned char *, sha512digest, SHA512, SHA_FMT_RAW)
+SHA_DIRECT(char *, sha512hex, SHA512, SHA_FMT_HEX)
+SHA_DIRECT(char *, sha512base64, SHA512, SHA_FMT_BASE64)