1 /***********************************************************
2 *       libsrs_alt - A simple SRS implementation           *
3 ***********************************************************/
4 
5 /* (C)2004 Miles Wilton <miles@mirtol.com> */
6 
7 /* License: GPL */
8 
9 /* This file:
10 
11    sha1.c
12 
13    Perform SHA1
14 */
15 
16 #include <string.h>
17 
18 #include "sha1.h"
19 
20 
21 /* mHMAC Structure */
22 
23 mHMAC_DIGEST mHMACD_SHA1 = {
24     64,
25     20,
26     sizeof(mSHA1),
27     mSHA1_start,
28     mSHA1_block,
29     mSHA1_process,
30     mSHA1_end
31 };
32 
33 
34 /***********************************************************
35     mSHA1_start - Init SHA1 structure
36 
37 */
38 
mSHA1_start(mSHA1 * sha1)39 int mSHA1_start(mSHA1 *sha1)
40 {
41     sha1->len = 0;
42     sha1->blen = 0;
43     sha1->H[0] = 0x67452301;
44     sha1->H[1] = 0xEFCDAB89;
45     sha1->H[2] = 0x98BADCFE;
46     sha1->H[3] = 0x10325476;
47     sha1->H[4] = 0xC3D2E1F0;
48 
49     return 0;
50 }
51 
52 
53 /***********************************************************
54     mSHA1_block - Process 512-bit block
55 
56 */
57 
mSHA1_block(mSHA1 * sha1,unsigned char * block)58 int mSHA1_block(mSHA1 *sha1, unsigned char *block)
59 {
60     u_int32_t A, B, C, D, E;
61     u_int32_t W[80];
62     int t;
63 
64     // Compute Ws
65     for(t = 0; t < 16; t++)
66     {
67         W[t] = (block[0] << 24) | (block[1] << 16) | (block[2] << 8) | block[3]; // Ensure byte order
68         block += 4;
69     }
70     for(t = 16; t < 80; t++)
71     {
72         register u_int32_t X = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
73         W[t] = (X << 1) | (X >> 31);
74     }
75 
76     A = sha1->H[0];
77     B = sha1->H[1];
78     C = sha1->H[2];
79     D = sha1->H[3];
80     E = sha1->H[4];
81 
82     // Digest (in 4 runs for different f-functions/K-values)
83     for(t = 0; t < 20; t++)
84     {
85         register u_int32_t TEMP = ((A << 5) | (A >> 27)) + ((B & C) | ((~B) & D)) + E + W[t] + 0x5A827999;
86         E = D;
87         D = C;
88         C = (B << 30) | (B >> 2);
89         B = A;
90         A = TEMP;
91     }
92     for(; t < 40; t++)
93     {
94         register u_int32_t TEMP = ((A << 5) | (A >> 27)) + (B ^ C ^ D) + E + W[t] + 0x6ED9EBA1;
95         E = D;
96         D = C;
97         C = (B << 30) | (B >> 2);
98         B = A;
99         A = TEMP;
100     }
101     for(; t < 60; t++)
102     {
103         register u_int32_t TEMP = ((A << 5) | (A >> 27)) + ((B & C) | (B & D) | (C & D)) + E + W[t] + 0x8F1BBCDC;
104         E = D;
105         D = C;
106         C = (B << 30) | (B >> 2);
107         B = A;
108         A = TEMP;
109     }
110     for(; t < 80; t++)
111     {
112         register u_int32_t TEMP = ((A << 5) | (A >> 27)) + (B ^ C ^ D) + E + W[t] + 0xCA62C1D6;
113         E = D;
114         D = C;
115         C = (B << 30) | (B >> 2);
116         B = A;
117         A = TEMP;
118     }
119 
120     // Update hash
121     sha1->H[0] += A;
122     sha1->H[1] += B;
123     sha1->H[2] += C;
124     sha1->H[3] += D;
125     sha1->H[4] += E;
126 
127     return 0;
128 }
129 
130 
131 /***********************************************************
132     mSHA1_process - Add a string to hash
133 
134 */
mSHA1_process(mSHA1 * sha1,unsigned char * data,int data_len)135 int mSHA1_process(mSHA1 *sha1, unsigned char *data, int data_len)
136 {
137     int b, n = 0;
138 
139     // Fulfill buffered data obligations
140     if(sha1->blen)
141     {
142         b = 64 - sha1->blen;
143         if(b > data_len)
144         {
145             // Just add data to buffer and return
146             memcpy(&sha1->b[sha1->blen], data, data_len);
147             sha1->blen += data_len;
148             return 0;
149         }
150         else
151         {
152             // Fill buffer and process block
153             memcpy(&sha1->b[sha1->blen], data, b);
154             n += b;
155             mSHA1_block(sha1, sha1->b);
156         }
157     }
158 
159     // Go until we don't have a full block
160     while(data_len - n >= 64)
161     {
162         mSHA1_block(sha1, &data[n]);
163         sha1->len += 512;
164         n += 64;
165     }
166 
167     // copy remaining data to buffer
168     sha1->blen = data_len - n;
169     memcpy(sha1->b, &data[n], sha1->blen);
170 
171     return 0;
172 }
173 
174 
175 /***********************************************************
176     mSHA1_end - Finalise hash
177 
178 */
mSHA1_end(mSHA1 * sha1,unsigned char * hash_buffer)179 int mSHA1_end(mSHA1 *sha1, unsigned char *hash_buffer)
180 {
181     // sha1->blen should _NEVER_ be 64
182     sha1->b[sha1->blen] = 0x80;
183 
184     // Calculate final length
185     sha1->len += sha1->blen << 3;
186 
187     // Pad remaining data
188     if(sha1->blen > 55)
189     {
190         memset(&sha1->b[sha1->blen+1], 0, 63 - sha1->blen);
191         mSHA1_block(sha1, sha1->b);
192 
193         memset(sha1->b, 0, 56);
194     }
195     else
196         memset(&sha1->b[sha1->blen+1], 0, 55 - sha1->blen);
197 
198     // Add length (ensuring byte order)
199     sha1->b[56] = (sha1->len >> 56) & 0xFF;
200     sha1->b[57] = (sha1->len >> 48) & 0xFF;
201     sha1->b[58] = (sha1->len >> 40) & 0xFF;
202     sha1->b[59] = (sha1->len >> 32) & 0xFF;
203     sha1->b[60] = (sha1->len >> 24) & 0xFF;
204     sha1->b[61] = (sha1->len >> 16) & 0xFF;
205     sha1->b[62] = (sha1->len >> 8) & 0xFF;
206     sha1->b[63] = sha1->len & 0xFF;
207 
208     // Process final block
209     mSHA1_block(sha1, sha1->b);
210 
211     // Get hash
212     if(hash_buffer)
213         mSHA1_gethash(sha1, hash_buffer);
214 
215     return 0;
216 }
217 
218 
219 /***********************************************************
220     mSHA1_gethash - Get hash string (fills 20 bytes)
221 
222 */
mSHA1_gethash(mSHA1 * sha1,unsigned char * hash_buffer)223 int mSHA1_gethash(mSHA1 *sha1, unsigned char *hash_buffer)
224 {
225     int n;
226 
227     for(n = 0; n < 5; n++)
228     {
229         *hash_buffer++ = (sha1->H[n] >> 24) & 0xFF;
230         *hash_buffer++ = (sha1->H[n] >> 16) & 0xFF;
231         *hash_buffer++ = (sha1->H[n] >> 8) & 0xFF;
232         *hash_buffer++ = sha1->H[n] & 0xFF;
233     }
234 
235     return 0;
236 }
237 
238 
239