1 /*
2 * sha1.c
3 *
4 * Copyright (C) 1998, 2009
5 * Paul E. Jones <paulej@packetizer.com>
6 * All Rights Reserved
7 *
8 *****************************************************************************
9 * $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $
10 *****************************************************************************
11 *
12 * Description:
13 * This file implements the Secure Hashing Standard as defined
14 * in FIPS PUB 180-1 published April 17, 1995.
15 *
16 * The Secure Hashing Standard, which uses the Secure Hashing
17 * Algorithm (SHA), produces a 160-bit message digest for a
18 * given data stream. In theory, it is highly improbable that
19 * two messages will produce the same message digest. Therefore,
20 * this algorithm can serve as a means of providing a "fingerprint"
21 * for a message.
22 *
23 * Portability Issues:
24 * SHA-1 is defined in terms of 32-bit "words". This code was
25 * written with the expectation that the processor has at least
26 * a 32-bit machine word size. If the machine word size is larger,
27 * the code should still function properly. One caveat to that
28 * is that the input functions taking characters and character
29 * arrays assume that only 8 bits of information are stored in each
30 * character.
31 *
32 * Caveats:
33 * SHA-1 is designed to work with messages less than 2^64 bits
34 * long. Although SHA-1 allows a message digest to be generated for
35 * messages of any number of bits less than 2^64, this
36 * implementation only works with messages with a length that is a
37 * multiple of the size of an 8-bit character.
38 *
39 */
40
41 #include "sha1.h"
42 #include "filesys.h"
43 #include "../shared/shared.h"
44
45 /*
46 * Define the circular shift macro
47 */
48 #define SHA1CircularShift(bits,word) \
49 ((((word) << (bits)) & 0xFFFFFFFF) | \
50 ((word) >> (32-(bits))))
51
52 /* Function prototypes */
53 static void Com_SHA1ProcessMessageBlock (SHA1Context *);
54 static void Com_SHA1PadMessage (SHA1Context *);
55
56 /**
57 * SHA1Reset
58 *
59 * Description:
60 * This function will initialize the SHA1Context in preparation
61 * for computing a new message digest.
62 *
63 * Parameters:
64 * context: [in/out]
65 * The context to reset.
66 *
67 * Returns:
68 * Nothing.
69 *
70 * Comments:
71 */
Com_SHA1Reset(SHA1Context * context)72 void Com_SHA1Reset (SHA1Context *context)
73 {
74 context->Length_Low = 0;
75 context->Length_High = 0;
76 context->Message_Block_Index = 0;
77
78 context->Message_Digest[0] = 0x67452301;
79 context->Message_Digest[1] = 0xEFCDAB89;
80 context->Message_Digest[2] = 0x98BADCFE;
81 context->Message_Digest[3] = 0x10325476;
82 context->Message_Digest[4] = 0xC3D2E1F0;
83
84 context->Computed = 0;
85 context->Corrupted = 0;
86 }
87
88 /**
89 * SHA1Result
90 *
91 * Description:
92 * This function will return the 160-bit message digest into the
93 * Message_Digest array within the SHA1Context provided
94 *
95 * Parameters:
96 * context: [in/out]
97 * The context to use to calculate the SHA-1 hash.
98 *
99 * Returns:
100 * true if successful, false if it failed.
101 *
102 * Comments:
103 */
Com_SHA1Result(SHA1Context * context)104 bool Com_SHA1Result (SHA1Context *context)
105 {
106 if (context->Corrupted) {
107 return false;
108 }
109
110 if (!context->Computed) {
111 Com_SHA1PadMessage(context);
112 context->Computed = 1;
113 }
114
115 return true;
116 }
117
118 /**
119 * SHA1Input
120 *
121 * Description:
122 * This function accepts an array of octets as the next portion of
123 * the message.
124 *
125 * Parameters:
126 * context: [in/out]
127 * The SHA-1 context to update
128 * message_array: [in]
129 * An array of characters representing the next portion of the
130 * message.
131 * length: [in]
132 * The length of the message in message_array
133 *
134 * Returns:
135 * Nothing.
136 *
137 * Comments:
138 */
Com_SHA1Input(SHA1Context * context,const unsigned char * message_array,unsigned length)139 void Com_SHA1Input (SHA1Context *context, const unsigned char* message_array, unsigned length)
140 {
141 if (!length) {
142 return;
143 }
144
145 if (context->Computed || context->Corrupted) {
146 context->Corrupted = 1;
147 return;
148 }
149
150 while (length-- && !context->Corrupted) {
151 context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
152
153 context->Length_Low += 8;
154 /* Force it to 32 bits */
155 context->Length_Low &= 0xFFFFFFFF;
156 if (context->Length_Low == 0) {
157 context->Length_High++;
158 /* Force it to 32 bits */
159 context->Length_High &= 0xFFFFFFFF;
160 if (context->Length_High == 0) {
161 /* Message is too long */
162 context->Corrupted = 1;
163 }
164 }
165
166 if (context->Message_Block_Index == 64) {
167 Com_SHA1ProcessMessageBlock(context);
168 }
169
170 message_array++;
171 }
172 }
173
174 /**
175 * SHA1ProcessMessageBlock
176 *
177 * Description:
178 * This function will process the next 512 bits of the message
179 * stored in the Message_Block array.
180 *
181 * Parameters:
182 * None.
183 *
184 * Returns:
185 * Nothing.
186 *
187 * Comments:
188 * Many of the variable names in the SHAContext, especially the
189 * single character names, were used because those were the names
190 * used in the publication.
191 */
Com_SHA1ProcessMessageBlock(SHA1Context * context)192 static void Com_SHA1ProcessMessageBlock (SHA1Context *context)
193 {
194 const unsigned K[] = /* Constants defined in SHA-1 */
195 { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
196 int t; /* Loop counter */
197 unsigned temp; /* Temporary word value */
198 unsigned W[80]; /* Word sequence*/
199 unsigned A, B, C, D, E; /* Word buffers */
200
201 /*
202 * Initialize the first 16 words in the array W
203 */
204 for (t = 0; t < 16; t++) {
205 W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
206 W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
207 W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
208 W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
209 }
210
211 for (t = 16; t < 80; t++) {
212 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
213 }
214
215 A = context->Message_Digest[0];
216 B = context->Message_Digest[1];
217 C = context->Message_Digest[2];
218 D = context->Message_Digest[3];
219 E = context->Message_Digest[4];
220
221 for (t = 0; t < 20; t++) {
222 temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
223 temp &= 0xFFFFFFFF;
224 E = D;
225 D = C;
226 C = SHA1CircularShift(30,B);
227 B = A;
228 A = temp;
229 }
230
231 for (t = 20; t < 40; t++) {
232 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
233 temp &= 0xFFFFFFFF;
234 E = D;
235 D = C;
236 C = SHA1CircularShift(30,B);
237 B = A;
238 A = temp;
239 }
240
241 for (t = 40; t < 60; t++) {
242 temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
243 temp &= 0xFFFFFFFF;
244 E = D;
245 D = C;
246 C = SHA1CircularShift(30,B);
247 B = A;
248 A = temp;
249 }
250
251 for (t = 60; t < 80; t++) {
252 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
253 temp &= 0xFFFFFFFF;
254 E = D;
255 D = C;
256 C = SHA1CircularShift(30,B);
257 B = A;
258 A = temp;
259 }
260
261 context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;
262 context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;
263 context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;
264 context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;
265 context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;
266
267 context->Message_Block_Index = 0;
268 }
269
270 /**
271 * SHA1PadMessage
272 *
273 * Description:
274 * According to the standard, the message must be padded to an even
275 * 512 bits. The first padding bit must be a '1'. The last 64
276 * bits represent the length of the original message. All bits in
277 * between should be 0. This function will pad the message
278 * according to those rules by filling the Message_Block array
279 * accordingly. It will also call SHA1ProcessMessageBlock()
280 * appropriately. When it returns, it can be assumed that the
281 * message digest has been computed.
282 *
283 * Parameters:
284 * context: [in/out]
285 * The context to pad
286 *
287 * Returns:
288 * Nothing.
289 *
290 * Comments:
291 */
Com_SHA1PadMessage(SHA1Context * context)292 static void Com_SHA1PadMessage (SHA1Context *context)
293 {
294 /*
295 * Check to see if the current message block is too small to hold
296 * the initial padding bits and length. If so, we will pad the
297 * block, process it, and then continue padding into a second
298 * block.
299 */
300 if (context->Message_Block_Index > 55) {
301 context->Message_Block[context->Message_Block_Index++] = 0x80;
302 while (context->Message_Block_Index < 64) {
303 context->Message_Block[context->Message_Block_Index++] = 0;
304 }
305
306 Com_SHA1ProcessMessageBlock(context);
307
308 while (context->Message_Block_Index < 56) {
309 context->Message_Block[context->Message_Block_Index++] = 0;
310 }
311 } else {
312 context->Message_Block[context->Message_Block_Index++] = 0x80;
313 while (context->Message_Block_Index < 56) {
314 context->Message_Block[context->Message_Block_Index++] = 0;
315 }
316 }
317
318 /*
319 * Store the message length as the last 8 octets
320 */
321 context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
322 context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
323 context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
324 context->Message_Block[59] = (context->Length_High) & 0xFF;
325 context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
326 context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
327 context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
328 context->Message_Block[63] = (context->Length_Low) & 0xFF;
329
330 Com_SHA1ProcessMessageBlock(context);
331 }
332
Com_SHA1File(const char * filename,char digest[41])333 bool Com_SHA1File (const char* filename, char digest[41])
334 {
335 qFILE f;
336 const int filelen = FS_OpenFile(filename, &f, FILE_READ);
337 if (filelen < 1)
338 return false;
339
340 SHA1Context sha;
341 Com_SHA1Reset(&sha);
342
343 byte buf[1024];
344 for (;;) {
345 const int n = FS_Read(buf, sizeof(buf), &f);
346 if (n < 1)
347 break;
348 Com_SHA1Input(&sha, buf, n);
349 }
350
351 if (!Com_SHA1Result(&sha)) {
352 return false;
353 }
354 digest[0] = '\0';
355 for (int i = 0; i < 5; i++) {
356 Q_strcat(digest, 41, "%02x", sha.Message_Digest[i]);
357 }
358 return true;
359 }
360
Com_SHA1Buffer(const unsigned char * buf,unsigned int len,char digest[41])361 bool Com_SHA1Buffer (const unsigned char* buf, unsigned int len, char digest[41])
362 {
363 if (len < 1)
364 return false;
365
366 SHA1Context sha;
367 Com_SHA1Reset(&sha);
368 Com_SHA1Input(&sha, buf, len);
369
370 if (!Com_SHA1Result(&sha)) {
371 return false;
372 }
373 digest[0] = '\0';
374 for (int i = 0; i < 5; i++) {
375 Q_strcat(digest, 41, "%02x", sha.Message_Digest[i]);
376 }
377 return true;
378 }
379