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