UFO: Alien Invasion
Loading...
Searching...
No Matches
md5.cpp
Go to the documentation of this file.
1
5
6/*
7 * This code implements the MD5 message-digest algorithm.
8 * The algorithm is due to Ron Rivest. This code was
9 * written by Colin Plumb in 1993, no copyright is claimed.
10 * This code is in the public domain; do with it what you wish.
11 *
12 * Equivalent code is available from RSA Data Security, Inc.
13 * This code has been tested against that, and is equivalent,
14 * except that you don't need to include two pages of legalese
15 * with every copy.
16 *
17 * To compute the message digest of a chunk of bytes, declare an
18 * MD5Context structure, pass it to MD5Init, call MD5Update as
19 * needed on buffers full of bytes, and then call MD5Final, which
20 * will fill a supplied 16-byte array with the digest.
21 */
22
23#include "common.h"
24#include <SDL_endian.h>
25
26typedef struct MD5Context {
27 uint32_t buf[4];
28 uint32_t bits[2];
29 unsigned char in[64];
30} MD5_CTX;
31
32#if SDL_BYTEORDER == SDL_LIL_ENDIAN
33#define byteReverse(buf, len) {} /* Nothing */
34#else
38static void byteReverse (unsigned char* buf, unsigned longs)
39{
40 do {
41 const uint32_t t = SDL_SwapLE32(*(uint32_t*)buf);
42 *(uint32_t*) buf = t;
43 buf += 4;
44 } while (--longs);
45}
46#endif
47
52static void MD5Init (struct MD5Context *ctx)
53{
54 ctx->buf[0] = 0x67452301;
55 ctx->buf[1] = 0xefcdab89;
56 ctx->buf[2] = 0x98badcfe;
57 ctx->buf[3] = 0x10325476;
58
59 ctx->bits[0] = 0;
60 ctx->bits[1] = 0;
61}
62/* The four core functions - F1 is optimized somewhat */
63
64/* #define F1(x, y, z) (x & y | ~x & z) */
65#define F1(x, y, z) (z ^ (x & (y ^ z)))
66#define F2(x, y, z) F1(z, x, y)
67#define F3(x, y, z) (x ^ y ^ z)
68#define F4(x, y, z) (y ^ (x | ~z))
69
70/* This is the central step in the MD5 algorithm. */
71#define MD5STEP(f, w, x, y, z, data, s) \
72 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
73
79static void MD5Transform (uint32_t buf[4], uint32_t const in[16])
80{
81
82 register uint32_t a = buf[0];
83 register uint32_t b = buf[1];
84 register uint32_t c = buf[2];
85 register uint32_t d = buf[3];
86
87 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
88 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
89 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
90 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
91 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
92 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
93 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
94 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
95 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
96 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
97 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
98 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
99 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
100 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
101 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
102 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
103
104 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
105 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
106 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
107 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
108 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
109 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
110 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
111 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
112 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
113 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
114 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
115 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
116 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
117 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
118 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
119 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
120
121 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
122 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
123 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
124 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
125 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
126 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
127 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
128 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
129 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
130 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
131 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
132 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
133 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
134 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
135 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
136 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
137
138 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
139 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
140 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
141 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
142 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
143 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
144 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
145 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
146 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
147 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
148 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
149 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
150 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
151 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
152 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
153 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
154
155 buf[0] += a;
156 buf[1] += b;
157 buf[2] += c;
158 buf[3] += d;
159}
160
165static void MD5Update (struct MD5Context *ctx, unsigned char const* buf, unsigned len)
166{
167 /* Update bitcount */
168
169 uint32_t t = ctx->bits[0];
170 if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
171 ctx->bits[1]++; /* Carry from low to high */
172 ctx->bits[1] += len >> 29;
173
174 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
175
176 /* Handle any leading odd-sized chunks */
177
178 if (t) {
179 unsigned char* p = (unsigned char*) ctx->in + t;
180
181 t = 64 - t;
182 if (len < t) {
183 memcpy(p, buf, len);
184 return;
185 }
186 memcpy(p, buf, t);
187 byteReverse(ctx->in, 16);
188 MD5Transform(ctx->buf, (uint32_t*) ctx->in);
189 buf += t;
190 len -= t;
191 }
192 /* Process data in 64-byte chunks */
193
194 while (len >= 64) {
195 memcpy(ctx->in, buf, 64);
196 byteReverse(ctx->in, 16);
197 MD5Transform(ctx->buf, (uint32_t*) ctx->in);
198 buf += 64;
199 len -= 64;
200 }
201
202 /* Handle any remaining bytes of data. */
203
204 memcpy(ctx->in, buf, len);
205}
206
211static void MD5Final (struct MD5Context *ctx, unsigned char* digest)
212{
213 /* Compute number of bytes mod 64 */
214 unsigned count = (ctx->bits[0] >> 3) & 0x3F;
215
216 /* Set the first char of padding to 0x80. This is safe since there is
217 always at least one byte free */
218 unsigned char* p = ctx->in + count;
219 *p++ = 0x80;
220
221 /* Bytes of padding needed to make 64 bytes */
222 count = 64 - 1 - count;
223
224 /* Pad out to 56 mod 64 */
225 if (count < 8) {
226 /* Two lots of padding: Pad the first block to 64 bytes */
227 memset(p, 0, count);
228 byteReverse(ctx->in, 16);
229 MD5Transform(ctx->buf, (uint32_t*) ctx->in);
230
231 /* Now fill the next block with 56 bytes */
232 memset(ctx->in, 0, 56);
233 } else {
234 /* Pad block to 56 bytes */
235 memset(p, 0, count - 8);
236 }
237 byteReverse(ctx->in, 14);
238
239 /* Append length in bits and transform */
240 ((uint32_t*) ctx->in)[14] = ctx->bits[0];
241 ((uint32_t*) ctx->in)[15] = ctx->bits[1];
242
243 MD5Transform(ctx->buf, (uint32_t*) ctx->in);
244 byteReverse((unsigned char*) ctx->buf, 4);
245
246 if (digest != nullptr)
247 memcpy(digest, ctx->buf, 16);
248 OBJZERO(*ctx); /* In case it's sensitive */
249}
250
257const char* Com_MD5File (const char* fn, int length)
258{
260 const int filelen = FS_OpenFile(fn, &f, FILE_READ);
261 if (filelen < 1)
262 return "unknown";
263
264 if (filelen < length || !length)
265 length = filelen;
266
267 MD5_CTX md5;
268 MD5Init(&md5);
269
270 char buffer[2048];
271 int total = 0;
272 for (;;) {
273 int r = FS_Read(buffer, sizeof(buffer), &f);
274 if (r < 1)
275 break;
276 if (r + total > length)
277 r = length - total;
278 total += r;
279 MD5Update(&md5, (const unsigned char*) buffer, r);
280 if (r < sizeof(buffer) || total >= length)
281 break;
282 }
283 unsigned char digest[16] = { "" };
284 MD5Final(&md5, digest);
285
286 static char final[33];
287 final[0] = '\0';
288 for (int i = 0; i < 16; i++)
289 Q_strcat(final, sizeof(final), "%02x", digest[i]);
290
291 return final;
292}
293
300const char* Com_MD5Buffer (const byte* buf, size_t len)
301{
302 if (len < 1)
303 return "unknown";
304
305 MD5_CTX md5;
306 MD5Init(&md5);
307 MD5Update(&md5, buf, len);
308
309 unsigned char digest[16] = { "" };
310 MD5Final(&md5, digest);
311
312 static char final[33];
313 final[0] = '\0';
314 for (int i = 0; i < 16; i++)
315 Q_strcat(final, sizeof(final), "%02x", digest[i]);
316
317 return final;
318}
definitions common between client and server, but not game lib
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
@ FILE_READ
Definition filesys.h:111
voidpf void * buf
Definition ioapi.h:42
static void MD5Final(struct MD5Context *ctx, unsigned char *digest)
Final wrapup - pad to 64-byte boundary with the bit pattern 1 0* (64-bit count of bits processed,...
Definition md5.cpp:211
#define MD5STEP(f, w, x, y, z, data, s)
Definition md5.cpp:71
static void MD5Init(struct MD5Context *ctx)
Start MD5 accumulation. Set bit count to 0 and buffer to mysterious initialization constants.
Definition md5.cpp:52
#define byteReverse(buf, len)
Definition md5.cpp:33
static void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
Update context to reflect the concatenation of another buffer full of bytes.
Definition md5.cpp:165
#define F1(x, y, z)
Definition md5.cpp:65
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
The core of the MD5 algorithm, this alters an existing MD5 hash to reflect the addition of 16 longwor...
Definition md5.cpp:79
#define F4(x, y, z)
Definition md5.cpp:68
const char * Com_MD5Buffer(const byte *buf, size_t len)
Compute the md5sum of the given buffer.
Definition md5.cpp:300
#define F3(x, y, z)
Definition md5.cpp:67
#define F2(x, y, z)
Definition md5.cpp:66
const char * Com_MD5File(const char *fn, int length)
Compute the md5sum of a given file.
Definition md5.cpp:257
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN GLuint count
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
#define OBJZERO(obj)
Definition shared.h:178
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
uint32_t bits[2]
Definition md5.cpp:28
unsigned char in[64]
Definition md5.cpp:29
uint32_t buf[4]
Definition md5.cpp:27