1/* NIST Secure Hash Algorithm */ 2/* heavily modified by Uwe Hollerbach uh@alumni.caltech edu */ 3/* from Peter C. Gutmann's implementation as found in */ 4/* Applied Cryptography by Bruce Schneier */ 5 6/* NIST's proposed modification to SHA of 7/11/94 may be */ 7/* activated by defining USE_MODIFIED_SHA */ 8 9#ifdef HAVE_STDLIB_H 10#include <stdlib.h> 11#else 12#include "../../compat/stdlib.h" 13#endif 14 15#include <stdio.h> 16#include <string.h> 17#include "sha.h" 18 19/* SHA f()-functions */ 20 21#define f1(x,y,z) ((x & y) | (~x & z)) 22#define f2(x,y,z) (x ^ y ^ z) 23#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) 24#define f4(x,y,z) (x ^ y ^ z) 25 26/* SHA constants */ 27 28#define CONST1 0x5a827999L 29#define CONST2 0x6ed9eba1L 30#define CONST3 0x8f1bbcdcL 31#define CONST4 0xca62c1d6L 32 33/* 32-bit rotate */ 34 35#define ROT32(x,n) ((x << n) | (x >> (32 - n))) 36 37#define FUNC(n,i) \ 38 temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \ 39 E = D; D = C; C = ROT32(B,30); B = A; A = temp 40 41#define FUNC1(i) \ 42 temp = ROT32(A,5) + f1(B,C,D) + E + W[i] + CONST1; \ 43 E = D; D = C; C = ROT32(B,30); B = A; A = temp 44#define FUNC2(i) \ 45 temp = ROT32(A,5) + f2(B,C,D) + E + W[i] + CONST2; \ 46 E = D; D = C; C = ROT32(B,30); B = A; A = temp 47#define FUNC3(i) \ 48 temp = ROT32(A,5) + f3(B,C,D) + E + W[i] + CONST3; \ 49 E = D; D = C; C = ROT32(B,30); B = A; A = temp 50#define FUNC4(i) \ 51 temp = ROT32(A,5) + f4(B,C,D) + E + W[i] + CONST4; \ 52 E = D; D = C; C = ROT32(B,30); B = A; A = temp 53 54/* do SHA transformation */ 55 56static void sha_transform(sha_info) 57SHA_INFO *sha_info; 58{ 59 int i; 60 UINT32 temp, A, B, C, D, E, W[80]; 61 62 for (i = 0; i < 16; ++i) { 63 W[i] = sha_info->data[i]; 64 } 65 for (i = 16; i < 80; ++i) { 66 W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; 67#ifdef USE_MODIFIED_SHA 68 W[i] = ROT32(W[i], 1); 69#endif /* USE_MODIFIED_SHA */ 70 } 71 A = sha_info->digest[0]; 72 B = sha_info->digest[1]; 73 C = sha_info->digest[2]; 74 D = sha_info->digest[3]; 75 E = sha_info->digest[4]; 76#ifdef UNROLL_LOOPS 77 FUNC1( 0); FUNC1( 1); FUNC1( 2); FUNC1( 3); FUNC1( 4); 78 FUNC1( 5); FUNC1( 6); FUNC1( 7); FUNC1( 8); FUNC1( 9); 79 FUNC1(10); FUNC1(11); FUNC1(12); FUNC1(13); FUNC1(14); 80 FUNC1(15); FUNC1(16); FUNC1(17); FUNC1(18); FUNC1(19); 81 82 FUNC2(20); FUNC2(21); FUNC2(22); FUNC2(23); FUNC2(24); 83 FUNC2(25); FUNC2(26); FUNC2(27); FUNC2(28); FUNC2(29); 84 FUNC2(30); FUNC2(31); FUNC2(32); FUNC2(33); FUNC2(34); 85 FUNC2(35); FUNC2(36); FUNC2(37); FUNC2(38); FUNC2(39); 86 87 FUNC3(40); FUNC3(41); FUNC3(42); FUNC3(43); FUNC3(44); 88 FUNC3(45); FUNC3(46); FUNC3(47); FUNC3(48); FUNC3(49); 89 FUNC3(50); FUNC3(51); FUNC3(52); FUNC3(53); FUNC3(54); 90 FUNC3(55); FUNC3(56); FUNC3(57); FUNC3(58); FUNC3(59); 91 92 FUNC4(60); FUNC4(61); FUNC4(62); FUNC4(63); FUNC4(64); 93 FUNC4(65); FUNC4(66); FUNC4(67); FUNC4(68); FUNC4(69); 94 FUNC4(70); FUNC4(71); FUNC4(72); FUNC4(73); FUNC4(74); 95 FUNC4(75); FUNC4(76); FUNC4(77); FUNC4(78); FUNC4(79); 96#else /* !UNROLL_LOOPS */ 97 for (i = 0; i < 20; ++i) { 98 FUNC1(i); 99 } 100 for (i = 20; i < 40; ++i) { 101 FUNC2(i); 102 } 103 for (i = 40; i < 60; ++i) { 104 FUNC3(i); 105 } 106 for (i = 60; i < 80; ++i) { 107 FUNC4(i); 108 } 109#endif /* !UNROLL_LOOPS */ 110 sha_info->digest[0] += A; 111 sha_info->digest[1] += B; 112 sha_info->digest[2] += C; 113 sha_info->digest[3] += D; 114 sha_info->digest[4] += E; 115} 116 117#ifdef LITTLE_ENDIAN 118 119/* change endianness of data */ 120 121static void byte_reverse(buffer, count) 122UINT32 *buffer; int count; 123{ 124 int i; 125 BYTE ct[4], *cp; 126 127 count /= sizeof(UINT32); 128 cp = (BYTE *) buffer; 129 for (i = 0; i < count; ++i) { 130 ct[0] = cp[0]; 131 ct[1] = cp[1]; 132 ct[2] = cp[2]; 133 ct[3] = cp[3]; 134 cp[0] = ct[3]; 135 cp[1] = ct[2]; 136 cp[2] = ct[1]; 137 cp[3] = ct[0]; 138 cp += sizeof(UINT32); 139 } 140} 141 142#endif /* LITTLE_ENDIAN */ 143 144/* initialize the SHA digest */ 145 146void sha_init(sha_info) 147SHA_INFO *sha_info; 148{ 149 sha_info->digest[0] = 0x67452301L; 150 sha_info->digest[1] = 0xefcdab89L; 151 sha_info->digest[2] = 0x98badcfeL; 152 sha_info->digest[3] = 0x10325476L; 153 sha_info->digest[4] = 0xc3d2e1f0L; 154 sha_info->count_lo = 0L; 155 sha_info->count_hi = 0L; 156} 157 158/* update the SHA digest */ 159 160void sha_update(sha_info, buffer, count) 161SHA_INFO *sha_info; BYTE *buffer; int count; 162{ 163 if ((sha_info->count_lo + ((UINT32) count << 3)) < sha_info->count_lo) { 164 ++sha_info->count_hi; 165 } 166 sha_info->count_lo += (UINT32) count << 3; 167 sha_info->count_hi += (UINT32) count >> 29; 168 while (count >= SHA_BLOCKSIZE) { 169 memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); 170#ifdef LITTLE_ENDIAN 171 byte_reverse(sha_info->data, SHA_BLOCKSIZE); 172#endif /* LITTLE_ENDIAN */ 173 sha_transform(sha_info); 174 buffer += SHA_BLOCKSIZE; 175 count -= SHA_BLOCKSIZE; 176 } 177 memcpy(sha_info->data, buffer, count); 178} 179 180/* finish computing the SHA digest */ 181 182void sha_final(sha_info) 183SHA_INFO *sha_info; 184{ 185 int count; 186 UINT32 lo_bit_count, hi_bit_count; 187 188 lo_bit_count = sha_info->count_lo; 189 hi_bit_count = sha_info->count_hi; 190 count = (int) ((lo_bit_count >> 3) & 0x3f); 191 ((BYTE *) sha_info->data)[count++] = 0x80; 192 if (count > 56) { 193 memset((BYTE *) sha_info->data + count, 0, 64 - count); 194#ifdef LITTLE_ENDIAN 195 byte_reverse(sha_info->data, SHA_BLOCKSIZE); 196#endif /* LITTLE_ENDIAN */ 197 sha_transform(sha_info); 198 memset(sha_info->data, 0, 56); 199 } else { 200 memset((BYTE *) sha_info->data + count, 0, 56 - count); 201 } 202#ifdef LITTLE_ENDIAN 203 byte_reverse(sha_info->data, SHA_BLOCKSIZE); 204#endif /* LITTLE_ENDIAN */ 205 sha_info->data[14] = hi_bit_count; 206 sha_info->data[15] = lo_bit_count; 207 sha_transform(sha_info); 208} 209 210/* compute the SHA digest of a FILE stream */ 211 212#define BLOCK_SIZE 8192 213 214void sha_stream(sha_info, fin) 215SHA_INFO *sha_info; FILE *fin; 216{ 217 int i; 218 BYTE data[BLOCK_SIZE]; 219 220 sha_init(sha_info); 221 while ((i = fread(data, 1, BLOCK_SIZE, fin)) > 0) { 222 sha_update(sha_info, data, i); 223 } 224 sha_final(sha_info); 225} 226 227/* print a SHA digest */ 228 229void sha_print(sha_info) 230SHA_INFO *sha_info; 231{ 232 printf("%08lx %08lx %08lx %08lx %08lx\n", 233 sha_info->digest[0], sha_info->digest[1], sha_info->digest[2], 234 sha_info->digest[3], sha_info->digest[4]); 235} 236