1 /* 2 * Copyright 2004 Filip Navara 3 * Based on public domain SHA code by Steve Reid <steve@edmweb.com> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "sha1.h" 21 22 /* SHA1 Helper Macros */ 23 24 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 25 /* FIXME: This definition of DWORD2BE is little endian specific! */ 26 #define DWORD2BE(x) (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000); 27 /* FIXME: This definition of blk0 is little endian specific! */ 28 #define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF)) 29 #define blk1(i) (Block[i&15] = rol(Block[(i+13)&15]^Block[(i+8)&15]^Block[(i+2)&15]^Block[i&15],1)) 30 #define f1(x,y,z) (z^(x&(y^z))) 31 #define f2(x,y,z) (x^y^z) 32 #define f3(x,y,z) ((x&y)|(z&(x|y))) 33 #define f4(x,y,z) (x^y^z) 34 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 35 #define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 36 #define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30); 37 #define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 38 #define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 39 #define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 40 41 /* Hash a single 512-bit block. This is the core of the algorithm. */ 42 static void SHA1Transform(ULONG State[5], UCHAR Buffer[64]) 43 { 44 ULONG a, b, c, d, e; 45 ULONG *Block; 46 47 Block = (ULONG*)Buffer; 48 49 /* Copy Context->State[] to working variables */ 50 a = State[0]; 51 b = State[1]; 52 c = State[2]; 53 d = State[3]; 54 e = State[4]; 55 56 /* 4 rounds of 20 operations each. Loop unrolled. */ 57 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 58 R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 59 R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 60 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 61 R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 62 R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 63 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 64 R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 65 R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 66 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 67 R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 68 R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 69 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 70 R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 71 R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 72 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 73 R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 74 R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 75 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 76 R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 77 78 /* Add the working variables back into Context->State[] */ 79 State[0] += a; 80 State[1] += b; 81 State[2] += c; 82 State[3] += d; 83 State[4] += e; 84 85 /* Wipe variables */ 86 a = b = c = d = e = 0; 87 } 88 89 90 /****************************************************************************** 91 * A_SHAInit [ADVAPI32.@] 92 * 93 * Initialize a SHA context structure. 94 * 95 * PARAMS 96 * Context [O] SHA context 97 * 98 * RETURNS 99 * Nothing 100 */ 101 VOID NTAPI 102 A_SHAInit(PSHA_CTX Context) 103 { 104 /* SHA1 initialization constants */ 105 Context->State[0] = 0x67452301; 106 Context->State[1] = 0xEFCDAB89; 107 Context->State[2] = 0x98BADCFE; 108 Context->State[3] = 0x10325476; 109 Context->State[4] = 0xC3D2E1F0; 110 Context->Count[0] = 111 Context->Count[1] = 0; 112 } 113 114 /****************************************************************************** 115 * A_SHAUpdate [ADVAPI32.@] 116 * 117 * Update a SHA context with a hashed data from supplied buffer. 118 * 119 * PARAMS 120 * Context [O] SHA context 121 * Buffer [I] hashed data 122 * BufferSize [I] hashed data size 123 * 124 * RETURNS 125 * Nothing 126 */ 127 VOID NTAPI 128 A_SHAUpdate(PSHA_CTX Context, const unsigned char *Buffer, ULONG BufferSize) 129 { 130 ULONG BufferContentSize; 131 132 BufferContentSize = Context->Count[1] & 63; 133 Context->Count[1] += BufferSize; 134 if (Context->Count[1] < BufferSize) 135 Context->Count[0]++; 136 Context->Count[0] += (BufferSize >> 29); 137 138 if (BufferContentSize + BufferSize < 64) 139 { 140 memcpy(&Context->Buffer[BufferContentSize], Buffer, 141 BufferSize); 142 } 143 else 144 { 145 while (BufferContentSize + BufferSize >= 64) 146 { 147 memcpy(Context->Buffer + BufferContentSize, Buffer, 148 64 - BufferContentSize); 149 Buffer += 64 - BufferContentSize; 150 BufferSize -= 64 - BufferContentSize; 151 SHA1Transform(Context->State, Context->Buffer); 152 BufferContentSize = 0; 153 } 154 memcpy(Context->Buffer + BufferContentSize, Buffer, BufferSize); 155 } 156 } 157 158 /****************************************************************************** 159 * A_SHAFinal [ADVAPI32.@] 160 * 161 * Finalize SHA context and return the resulting hash. 162 * 163 * PARAMS 164 * Context [I/O] SHA context 165 * Result [O] resulting hash 166 * 167 * RETURNS 168 * Nothing 169 */ 170 VOID NTAPI 171 A_SHAFinal(PSHA_CTX Context, PULONG Result) 172 { 173 INT Pad, Index; 174 UCHAR Buffer[72]; 175 ULONG *Count; 176 ULONG BufferContentSize, LengthHi, LengthLo; 177 178 BufferContentSize = Context->Count[1] & 63; 179 if (BufferContentSize >= 56) 180 Pad = 56 + 64 - BufferContentSize; 181 else 182 Pad = 56 - BufferContentSize; 183 184 LengthHi = (Context->Count[0] << 3) | (Context->Count[1] >> (32 - 3)); 185 LengthLo = (Context->Count[1] << 3); 186 187 memset(Buffer + 1, 0, Pad - 1); 188 Buffer[0] = 0x80; 189 Count = (ULONG*)(Buffer + Pad); 190 Count[0] = DWORD2BE(LengthHi); 191 Count[1] = DWORD2BE(LengthLo); 192 A_SHAUpdate(Context, Buffer, Pad + 8); 193 194 for (Index = 0; Index < 5; Index++) 195 Result[Index] = DWORD2BE(Context->State[Index]); 196 197 A_SHAInit(Context); 198 } 199