UFO: Alien Invasion
Loading...
Searching...
No Matches
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 */
54static void Com_SHA1PadMessage (SHA1Context *);
55
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
139void 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
289static 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
330bool 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
358bool 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_Read(void *buffer, int len, qFILE *f)
Definition files.cpp:371
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition files.cpp:162
Filesystem header file.
@ FILE_READ
Definition filesys.h:111
const char * filename
Definition ioapi.h:41
voidpf void * buf
Definition ioapi.h:42
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
bool Com_SHA1File(const char *filename, char digest[41])
Definition sha1.cpp:330
void Com_SHA1Input(SHA1Context *context, const unsigned char *message_array, unsigned length)
Definition sha1.cpp:139
bool Com_SHA1Buffer(const unsigned char *buf, unsigned int len, char digest[41])
Definition sha1.cpp:358
static void Com_SHA1ProcessMessageBlock(SHA1Context *)
Definition sha1.cpp:192
bool Com_SHA1Result(SHA1Context *context)
Definition sha1.cpp:104
static void Com_SHA1PadMessage(SHA1Context *)
Definition sha1.cpp:289
void Com_SHA1Reset(SHA1Context *context)
Definition sha1.cpp:72
#define SHA1CircularShift(bits, word)
Definition sha1.cpp:48
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
unsigned Message_Digest[5]
Definition sha1.h:44
int Computed
Definition sha1.h:52
int Message_Block_Index
Definition sha1.h:50
unsigned Length_Low
Definition sha1.h:46
unsigned char Message_Block[64]
Definition sha1.h:49
int Corrupted
Definition sha1.h:53
unsigned Length_High
Definition sha1.h:47