1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// Because MD5 may not be implemented (at least, with the same interface) on all systems,
19// we have our own implementation.
20// Implementation
21
22#include "ourMD5.hh"
23#include <NetCommon.h> // for u_int32_t, u_int64_t
24#include <string.h>
25
26#define DIGEST_SIZE_IN_BYTES 16
27#define DIGEST_SIZE_IN_HEX_DIGITS (2*DIGEST_SIZE_IN_BYTES)
28#define DIGEST_SIZE_AS_STRING (DIGEST_SIZE_IN_HEX_DIGITS+1)
29
30// The state of a MD5 computation in progress:
31
32class MD5Context {
33public:
34 MD5Context();
35 ~MD5Context();
36
37 void addData(unsigned char const* inputData, unsigned inputDataSize);
38 void end(char* outputDigest /*must point to an array of size DIGEST_SIZE_AS_STRING*/);
39 void finalize(unsigned char* outputDigestInBytes);
40 // Like "end()", except that the argument is a byte array, of size DIGEST_SIZE_IN_BYTES.
41 // This function is used to implement "end()".
42
43private:
44 void zeroize(); // to remove potentially sensitive information
45 void transform64Bytes(unsigned char const block[64]); // does the actual MD5 transform
46
47private:
48 u_int32_t fState[4]; // ABCD
49 u_int64_t fBitCount; // number of bits, modulo 2^64
50 unsigned char fWorkingBuffer[64];
51};
52
53char* our_MD5Data(unsigned char const* data, unsigned dataSize, char* outputDigest) {
54 MD5Context ctx;
55
56 ctx.addData(data, dataSize);
57
58 if (outputDigest == NULL) outputDigest = new char[DIGEST_SIZE_AS_STRING];
59 ctx.end(outputDigest);
60
61 return outputDigest;
62}
63
64unsigned char* our_MD5DataRaw(unsigned char const* data, unsigned dataSize,
65 unsigned char* outputDigest) {
66 MD5Context ctx;
67
68 ctx.addData(data, dataSize);
69
70 if (outputDigest == NULL) outputDigest = new unsigned char[DIGEST_SIZE_IN_BYTES];
71 ctx.finalize(outputDigest);
72
73 return outputDigest;
74}
75
76
77////////// MD5Context implementation //////////
78
79MD5Context::MD5Context()
80 : fBitCount(0) {
81 // Initialize with magic constants:
82 fState[0] = 0x67452301;
83 fState[1] = 0xefcdab89;
84 fState[2] = 0x98badcfe;
85 fState[3] = 0x10325476;
86}
87
88MD5Context::~MD5Context() {
89 zeroize();
90}
91
92void MD5Context::addData(unsigned char const* inputData, unsigned inputDataSize) {
93 // Begin by noting how much of our 64-byte working buffer remains unfilled:
94 u_int64_t const byteCount = fBitCount>>3;
95 unsigned bufferBytesInUse = (unsigned)(byteCount&0x3F);
96 unsigned bufferBytesRemaining = 64 - bufferBytesInUse;
97
98 // Then update our bit count:
99 fBitCount += inputDataSize<<3;
100
101 unsigned i = 0;
102 if (inputDataSize >= bufferBytesRemaining) {
103 // We have enough input data to do (64-byte) MD5 transforms.
104 // Do this now, starting with a transform on our working buffer, then with
105 // (as many as possible) transforms on rest of the input data.
106
107 memcpy((unsigned char*)&fWorkingBuffer[bufferBytesInUse], (unsigned char*)inputData, bufferBytesRemaining);
108 transform64Bytes(fWorkingBuffer);
109 bufferBytesInUse = 0;
110
111 for (i = bufferBytesRemaining; i + 63 < inputDataSize; i += 64) {
112 transform64Bytes(&inputData[i]);
113 }
114 }
115
116 // Copy any remaining (and currently un-transformed) input data into our working buffer:
117 if (i < inputDataSize) {
118 memcpy((unsigned char*)&fWorkingBuffer[bufferBytesInUse], (unsigned char*)&inputData[i], inputDataSize - i);
119 }
120}
121
122void MD5Context::end(char* outputDigest) {
123 unsigned char digestInBytes[DIGEST_SIZE_IN_BYTES];
124 finalize(digestInBytes);
125
126 // Convert the digest from bytes (binary) to hex digits:
127 static char const hex[]="0123456789abcdef";
128 unsigned i;
129 for (i = 0; i < DIGEST_SIZE_IN_BYTES; ++i) {
130 outputDigest[2*i] = hex[digestInBytes[i] >> 4];
131 outputDigest[2*i+1] = hex[digestInBytes[i] & 0x0F];
132 }
133 outputDigest[2*i] = '\0';
134}
135
136// Routines that unpack 32 and 64-bit values into arrays of bytes (in little-endian order).
137// (These are used to implement "finalize()".)
138
139static void unpack32(unsigned char out[4], u_int32_t in) {
140 for (unsigned i = 0; i < 4; ++i) {
141 out[i] = (unsigned char)((in>>(8*i))&0xFF);
142 }
143}
144
145static void unpack64(unsigned char out[8], u_int64_t in) {
146 for (unsigned i = 0; i < 8; ++i) {
147 out[i] = (unsigned char)((in>>(8*i))&0xFF);
148 }
149}
150
151static unsigned char const PADDING[64] = {
152 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
155};
156
157void MD5Context::finalize(unsigned char* outputDigestInBytes) {
158 // Unpack our bit count:
159 unsigned char bitCountInBytes[8];
160 unpack64(bitCountInBytes, fBitCount);
161
162 // Before 'finalizing', make sure that we transform any remaining bytes in our working buffer:
163 u_int64_t const byteCount = fBitCount>>3;
164 unsigned bufferBytesInUse = (unsigned)(byteCount&0x3F);
165 unsigned numPaddingBytes
166 = (bufferBytesInUse < 56) ? (56 - bufferBytesInUse) : (64 + 56 - bufferBytesInUse);
167 addData(PADDING, numPaddingBytes);
168
169 addData(bitCountInBytes, 8);
170
171 // Unpack our 'state' into the output digest:
172 unpack32(&outputDigestInBytes[0], fState[0]);
173 unpack32(&outputDigestInBytes[4], fState[1]);
174 unpack32(&outputDigestInBytes[8], fState[2]);
175 unpack32(&outputDigestInBytes[12], fState[3]);
176
177 zeroize();
178}
179
180void MD5Context::zeroize() {
181 fState[0] = fState[1] = fState[2] = fState[3] = 0;
182 fBitCount = 0;
183 for (unsigned i = 0; i < 64; ++i) fWorkingBuffer[i] = 0;
184}
185
186
187////////// Implementation of the MD5 transform ("MD5Context::transform64Bytes()") //////////
188
189// Constants for the transform:
190#define S11 7
191#define S12 12
192#define S13 17
193#define S14 22
194#define S21 5
195#define S22 9
196#define S23 14
197#define S24 20
198#define S31 4
199#define S32 11
200#define S33 16
201#define S34 23
202#define S41 6
203#define S42 10
204#define S43 15
205#define S44 21
206
207// Basic MD5 functions:
208#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
209#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
210#define H(x, y, z) ((x) ^ (y) ^ (z))
211#define I(x, y, z) ((y) ^ ((x) | (~z)))
212
213// Rotate "x" left "n" bits:
214#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
215
216// Other transforms:
217#define FF(a, b, c, d, x, s, ac) { \
218 (a) += F((b), (c), (d)) + (x) + (u_int32_t)(ac); \
219 (a) = ROTATE_LEFT((a), (s)); \
220 (a) += (b); \
221}
222#define GG(a, b, c, d, x, s, ac) { \
223 (a) += G((b), (c), (d)) + (x) + (u_int32_t)(ac); \
224 (a) = ROTATE_LEFT((a), (s)); \
225 (a) += (b); \
226}
227#define HH(a, b, c, d, x, s, ac) { \
228 (a) += H((b), (c), (d)) + (x) + (u_int32_t)(ac); \
229 (a) = ROTATE_LEFT((a), (s)); \
230 (a) += (b); \
231}
232#define II(a, b, c, d, x, s, ac) { \
233 (a) += I((b), (c), (d)) + (x) + (u_int32_t)(ac); \
234 (a) = ROTATE_LEFT((a), (s)); \
235 (a) += (b); \
236}
237
238void MD5Context::transform64Bytes(unsigned char const block[64]) {
239 u_int32_t a = fState[0], b = fState[1], c = fState[2], d = fState[3];
240
241 // Begin by packing "block" into an array ("x") of 16 32-bit values (in little-endian order):
242 u_int32_t x[16];
243 for (unsigned i = 0, j = 0; i < 16; ++i, j += 4) {
244 x[i] = ((u_int32_t)block[j]) | (((u_int32_t)block[j+1]) << 8) | (((u_int32_t)block[j+2]) << 16) | (((u_int32_t)block[j+3]) << 24);
245 }
246
247 // Now, perform the transform on the array "x":
248
249 // Round 1
250 FF(a, b, c, d, x[0], S11, 0xd76aa478); // 1
251 FF(d, a, b, c, x[1], S12, 0xe8c7b756); // 2
252 FF(c, d, a, b, x[2], S13, 0x242070db); // 3
253 FF(b, c, d, a, x[3], S14, 0xc1bdceee); // 4
254 FF(a, b, c, d, x[4], S11, 0xf57c0faf); // 5
255 FF(d, a, b, c, x[5], S12, 0x4787c62a); // 6
256 FF(c, d, a, b, x[6], S13, 0xa8304613); // 7
257 FF(b, c, d, a, x[7], S14, 0xfd469501); // 8
258 FF(a, b, c, d, x[8], S11, 0x698098d8); // 9
259 FF(d, a, b, c, x[9], S12, 0x8b44f7af); // 10
260 FF(c, d, a, b, x[10], S13, 0xffff5bb1); // 11
261 FF(b, c, d, a, x[11], S14, 0x895cd7be); // 12
262 FF(a, b, c, d, x[12], S11, 0x6b901122); // 13
263 FF(d, a, b, c, x[13], S12, 0xfd987193); // 14
264 FF(c, d, a, b, x[14], S13, 0xa679438e); // 15
265 FF(b, c, d, a, x[15], S14, 0x49b40821); // 16
266
267 // Round 2
268 GG(a, b, c, d, x[1], S21, 0xf61e2562); // 17
269 GG(d, a, b, c, x[6], S22, 0xc040b340); // 18
270 GG(c, d, a, b, x[11], S23, 0x265e5a51); // 19
271 GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); // 20
272 GG(a, b, c, d, x[5], S21, 0xd62f105d); // 21
273 GG(d, a, b, c, x[10], S22, 0x2441453); // 22
274 GG(c, d, a, b, x[15], S23, 0xd8a1e681); // 23
275 GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); // 24
276 GG(a, b, c, d, x[9], S21, 0x21e1cde6); // 25
277 GG(d, a, b, c, x[14], S22, 0xc33707d6); // 26
278 GG(c, d, a, b, x[3], S23, 0xf4d50d87); // 27
279 GG(b, c, d, a, x[8], S24, 0x455a14ed); // 28
280 GG(a, b, c, d, x[13], S21, 0xa9e3e905); // 29
281 GG(d, a, b, c, x[2], S22, 0xfcefa3f8); // 30
282 GG(c, d, a, b, x[7], S23, 0x676f02d9); // 31
283 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32
284
285 // Round 3
286 HH(a, b, c, d, x[5], S31, 0xfffa3942); // 33
287 HH(d, a, b, c, x[8], S32, 0x8771f681); // 34
288 HH(c, d, a, b, x[11], S33, 0x6d9d6122); // 35
289 HH(b, c, d, a, x[14], S34, 0xfde5380c); // 36
290 HH(a, b, c, d, x[1], S31, 0xa4beea44); // 37
291 HH(d, a, b, c, x[4], S32, 0x4bdecfa9); // 38
292 HH(c, d, a, b, x[7], S33, 0xf6bb4b60); // 39
293 HH(b, c, d, a, x[10], S34, 0xbebfbc70); // 40
294 HH(a, b, c, d, x[13], S31, 0x289b7ec6); // 41
295 HH(d, a, b, c, x[0], S32, 0xeaa127fa); // 42
296 HH(c, d, a, b, x[3], S33, 0xd4ef3085); // 43
297 HH(b, c, d, a, x[6], S34, 0x4881d05); // 44
298 HH(a, b, c, d, x[9], S31, 0xd9d4d039); // 45
299 HH(d, a, b, c, x[12], S32, 0xe6db99e5); // 46
300 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); // 47
301 HH(b, c, d, a, x[2], S34, 0xc4ac5665); // 48
302
303 // Round 4
304 II(a, b, c, d, x[0], S41, 0xf4292244); // 49
305 II(d, a, b, c, x[7], S42, 0x432aff97); // 50
306 II(c, d, a, b, x[14], S43, 0xab9423a7); // 51
307 II(b, c, d, a, x[5], S44, 0xfc93a039); // 52
308 II(a, b, c, d, x[12], S41, 0x655b59c3); // 53
309 II(d, a, b, c, x[3], S42, 0x8f0ccc92); // 54
310 II(c, d, a, b, x[10], S43, 0xffeff47d); // 55
311 II(b, c, d, a, x[1], S44, 0x85845dd1); // 56
312 II(a, b, c, d, x[8], S41, 0x6fa87e4f); // 57
313 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58
314 II(c, d, a, b, x[6], S43, 0xa3014314); // 59
315 II(b, c, d, a, x[13], S44, 0x4e0811a1); // 60
316 II(a, b, c, d, x[4], S41, 0xf7537e82); // 61
317 II(d, a, b, c, x[11], S42, 0xbd3af235); // 62
318 II(c, d, a, b, x[2], S43, 0x2ad7d2bb); // 63
319 II(b, c, d, a, x[9], S44, 0xeb86d391); // 64
320
321 fState[0] += a; fState[1] += b; fState[2] += c; fState[3] += d;
322
323 // Zeroize sensitive information.
324 for (unsigned k = 0; k < 16; ++k) x[k] = 0;
325}
326