UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
sha1.cpp
Go to the documentation of this file.
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 */
54 static void Com_SHA1PadMessage (SHA1Context *);
55 
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 
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 
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) {
168  }
169 
170  message_array++;
171  }
172 }
173 
193 {
194  const unsigned K[] = /* Constants defined in SHA-1 */
195  { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
196  unsigned W[80]; /* Word sequence*/
197 
198  /*
199  * Initialize the first 16 words in the array W
200  */
201  for (int t = 0; t < 16; t++) {
202  W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
203  W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
204  W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
205  W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
206  }
207 
208  for (int t = 16; t < 80; t++) {
209  W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
210  }
211 
212  unsigned A = context->Message_Digest[0];
213  unsigned B = context->Message_Digest[1];
214  unsigned C = context->Message_Digest[2];
215  unsigned D = context->Message_Digest[3];
216  unsigned E = context->Message_Digest[4];
217 
218  for (int t = 0; t < 20; t++) {
219  unsigned temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
220  temp &= 0xFFFFFFFF;
221  E = D;
222  D = C;
223  C = SHA1CircularShift(30,B);
224  B = A;
225  A = temp;
226  }
227 
228  for (int t = 20; t < 40; t++) {
229  unsigned temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
230  temp &= 0xFFFFFFFF;
231  E = D;
232  D = C;
233  C = SHA1CircularShift(30,B);
234  B = A;
235  A = temp;
236  }
237 
238  for (int t = 40; t < 60; t++) {
239  unsigned temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
240  temp &= 0xFFFFFFFF;
241  E = D;
242  D = C;
243  C = SHA1CircularShift(30,B);
244  B = A;
245  A = temp;
246  }
247 
248  for (int t = 60; t < 80; t++) {
249  unsigned temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
250  temp &= 0xFFFFFFFF;
251  E = D;
252  D = C;
253  C = SHA1CircularShift(30,B);
254  B = A;
255  A = temp;
256  }
257 
258  context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;
259  context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;
260  context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;
261  context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;
262  context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;
263 
264  context->Message_Block_Index = 0;
265 }
266 
289 static void Com_SHA1PadMessage (SHA1Context *context)
290 {
291  /*
292  * Check to see if the current message block is too small to hold
293  * the initial padding bits and length. If so, we will pad the
294  * block, process it, and then continue padding into a second
295  * block.
296  */
297  if (context->Message_Block_Index > 55) {
298  context->Message_Block[context->Message_Block_Index++] = 0x80;
299  while (context->Message_Block_Index < 64) {
300  context->Message_Block[context->Message_Block_Index++] = 0;
301  }
302 
304 
305  while (context->Message_Block_Index < 56) {
306  context->Message_Block[context->Message_Block_Index++] = 0;
307  }
308  } else {
309  context->Message_Block[context->Message_Block_Index++] = 0x80;
310  while (context->Message_Block_Index < 56) {
311  context->Message_Block[context->Message_Block_Index++] = 0;
312  }
313  }
314 
315  /*
316  * Store the message length as the last 8 octets
317  */
318  context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
319  context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
320  context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
321  context->Message_Block[59] = (context->Length_High) & 0xFF;
322  context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
323  context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
324  context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
325  context->Message_Block[63] = (context->Length_Low) & 0xFF;
326 
328 }
329 
330 bool Com_SHA1File (const char* filename, char digest[41])
331 {
332  qFILE f;
333  const int filelen = FS_OpenFile(filename, &f, FILE_READ);
334  if (filelen < 1)
335  return false;
336 
337  SHA1Context sha;
338  Com_SHA1Reset(&sha);
339 
340  byte buf[1024];
341  for (;;) {
342  const int n = FS_Read(buf, sizeof(buf), &f);
343  if (n < 1)
344  break;
345  Com_SHA1Input(&sha, buf, n);
346  }
347 
348  if (!Com_SHA1Result(&sha)) {
349  return false;
350  }
351  digest[0] = '\0';
352  for (int i = 0; i < 5; i++) {
353  Q_strcat(digest, 41, "%02x", sha.Message_Digest[i]);
354  }
355  return true;
356 }
357 
358 bool Com_SHA1Buffer (const unsigned char* buf, unsigned int len, char digest[41])
359 {
360  if (len < 1)
361  return false;
362 
363  SHA1Context sha;
364  Com_SHA1Reset(&sha);
365  Com_SHA1Input(&sha, buf, len);
366 
367  if (!Com_SHA1Result(&sha)) {
368  return false;
369  }
370  digest[0] = '\0';
371  for (int i = 0; i < 5; i++) {
372  Q_strcat(digest, 41, "%02x", sha.Message_Digest[i]);
373  }
374  return true;
375 }
#define E(x)
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition: files.cpp:162
bool Com_SHA1Buffer(const unsigned char *buf, unsigned int len, char digest[41])
Definition: sha1.cpp:358
int Corrupted
Definition: sha1.h:53
const char * filename
Definition: ioapi.h:41
static void Com_SHA1PadMessage(SHA1Context *)
Definition: sha1.cpp:289
voidpf void * buf
Definition: ioapi.h:42
unsigned Message_Digest[5]
Definition: sha1.h:44
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition: r_gl.h:110
unsigned Length_Low
Definition: sha1.h:46
bool Com_SHA1Result(SHA1Context *context)
Definition: sha1.cpp:104
unsigned char Message_Block[64]
Definition: sha1.h:49
static void Com_SHA1ProcessMessageBlock(SHA1Context *)
Definition: sha1.cpp:192
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
int FS_Read(void *buffer, int len, qFILE *f)
Definition: files.cpp:371
unsigned Length_High
Definition: sha1.h:47
void Com_SHA1Input(SHA1Context *context, const unsigned char *message_array, unsigned length)
Definition: sha1.cpp:139
QGL_EXTERN GLint i
Definition: r_gl.h:113
QGL_EXTERN GLuint GLchar GLuint * len
Definition: r_gl.h:99
bool Com_SHA1File(const char *filename, char digest[41])
Definition: sha1.cpp:330
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
Filesystem header file.
int Computed
Definition: sha1.h:52
void Com_SHA1Reset(SHA1Context *context)
Definition: sha1.cpp:72
uint8_t byte
Definition: ufotypes.h:34
#define SHA1CircularShift(bits, word)
Definition: sha1.cpp:48
int Message_Block_Index
Definition: sha1.h:50