1 /* Functions to compute MD5 message digest of memory blocks according to the
2    definition of MD5 in RFC 1321 from April 1992.
3    Copyright (C) 2020, 2021 Antonio Diaz Diaz.
4 
5    This library is free software. Redistribution and use in source and
6    binary forms, with or without modification, are permitted provided
7    that the following conditions are met:
8 
9    1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions, and the following disclaimer.
11 
12    2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions, and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15 
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 */
20 
21 #define _FILE_OFFSET_BITS 64
22 
23 #include <cstring>
24 #include <stdint.h>
25 
26 #include "md5.h"
27 
28 
29 namespace {
30 
31 /* These are the four functions used in the four steps of the MD5 algorithm
32    as defined in RFC 1321. */
33 #define F(x, y, z) ((x & y) | (~x & z))
34 #define G(x, y, z) ((x & z) | (y & ~z))
35 #define H(x, y, z) (x ^ y ^ z)
36 #define I(x, y, z) (y ^ (x | ~z))
37 
38 /* Rotate x left n bits.
39    It is unfortunate that C++ does not provide an operator for rotation.
40    Hope the compiler is smart enough. */
41 #define ROTATE_LEFT(x, n) (x = (x << n) | (x >> (32 - n)))
42 
43 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
44 #define FF(a, b, c, d, x, s, ac) \
45   { a += F(b, c, d) + x + ac; ROTATE_LEFT(a, s); a += b; }
46 #define GG(a, b, c, d, x, s, ac) \
47   { a += G(b, c, d) + x + ac; ROTATE_LEFT(a, s); a += b; }
48 #define HH(a, b, c, d, x, s, ac) \
49   { a += H(b, c, d) + x + ac; ROTATE_LEFT(a, s); a += b; }
50 #define II(a, b, c, d, x, s, ac) \
51   { a += I(b, c, d) + x + ac; ROTATE_LEFT(a, s); a += b; }
52 
53 } // end namespace
54 
55 
md5_process_block(const uint8_t block[64])56 void MD5SUM::md5_process_block( const uint8_t block[64] )
57   {
58   uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
59 
60   for( int i = 0, j = 0; i < 16; ++i, j += 4 )	// fill x in little endian
61     x[i] = block[j] | (block[j+1] << 8) | (block[j+2] << 16) | (block[j+3] << 24);
62 
63   /* Round 1 */
64   FF (a, b, c, d, x[ 0],  7, 0xD76AA478);	//  1
65   FF (d, a, b, c, x[ 1], 12, 0xE8C7B756);	//  2
66   FF (c, d, a, b, x[ 2], 17, 0x242070DB);	//  3
67   FF (b, c, d, a, x[ 3], 22, 0xC1BDCEEE);	//  4
68   FF (a, b, c, d, x[ 4],  7, 0xF57C0FAF);	//  5
69   FF (d, a, b, c, x[ 5], 12, 0x4787C62A);	//  6
70   FF (c, d, a, b, x[ 6], 17, 0xA8304613);	//  7
71   FF (b, c, d, a, x[ 7], 22, 0xFD469501);	//  8
72   FF (a, b, c, d, x[ 8],  7, 0x698098D8);	//  9
73   FF (d, a, b, c, x[ 9], 12, 0x8B44F7AF);	// 10
74   FF (c, d, a, b, x[10], 17, 0xFFFF5BB1);	// 11
75   FF (b, c, d, a, x[11], 22, 0x895CD7BE);	// 12
76   FF (a, b, c, d, x[12],  7, 0x6B901122);	// 13
77   FF (d, a, b, c, x[13], 12, 0xFD987193);	// 14
78   FF (c, d, a, b, x[14], 17, 0xA679438E);	// 15
79   FF (b, c, d, a, x[15], 22, 0x49B40821);	// 16
80 
81   /* Round 2 */
82   GG (a, b, c, d, x[ 1],  5, 0xF61E2562);	// 17
83   GG (d, a, b, c, x[ 6],  9, 0xC040B340);	// 18
84   GG (c, d, a, b, x[11], 14, 0x265E5A51);	// 19
85   GG (b, c, d, a, x[ 0], 20, 0xE9B6C7AA);	// 20
86   GG (a, b, c, d, x[ 5],  5, 0xD62F105D);	// 21
87   GG (d, a, b, c, x[10],  9, 0x02441453);	// 22
88   GG (c, d, a, b, x[15], 14, 0xD8A1E681);	// 23
89   GG (b, c, d, a, x[ 4], 20, 0xE7D3FBC8);	// 24
90   GG (a, b, c, d, x[ 9],  5, 0x21E1CDE6);	// 25
91   GG (d, a, b, c, x[14],  9, 0xC33707D6);	// 26
92   GG (c, d, a, b, x[ 3], 14, 0xF4D50D87);	// 27
93   GG (b, c, d, a, x[ 8], 20, 0x455A14ED);	// 28
94   GG (a, b, c, d, x[13],  5, 0xA9E3E905);	// 29
95   GG (d, a, b, c, x[ 2],  9, 0xFCEFA3F8);	// 30
96   GG (c, d, a, b, x[ 7], 14, 0x676F02D9);	// 31
97   GG (b, c, d, a, x[12], 20, 0x8D2A4C8A);	// 32
98 
99   /* Round 3 */
100   HH (a, b, c, d, x[ 5],  4, 0xFFFA3942);	// 33
101   HH (d, a, b, c, x[ 8], 11, 0x8771F681);	// 34
102   HH (c, d, a, b, x[11], 16, 0x6D9D6122);	// 35
103   HH (b, c, d, a, x[14], 23, 0xFDE5380C);	// 36
104   HH (a, b, c, d, x[ 1],  4, 0xA4BEEA44);	// 37
105   HH (d, a, b, c, x[ 4], 11, 0x4BDECFA9);	// 38
106   HH (c, d, a, b, x[ 7], 16, 0xF6BB4B60);	// 39
107   HH (b, c, d, a, x[10], 23, 0xBEBFBC70);	// 40
108   HH (a, b, c, d, x[13],  4, 0x289B7EC6);	// 41
109   HH (d, a, b, c, x[ 0], 11, 0xEAA127FA);	// 42
110   HH (c, d, a, b, x[ 3], 16, 0xD4EF3085);	// 43
111   HH (b, c, d, a, x[ 6], 23, 0x04881D05);	// 44
112   HH (a, b, c, d, x[ 9],  4, 0xD9D4D039);	// 45
113   HH (d, a, b, c, x[12], 11, 0xE6DB99E5);	// 46
114   HH (c, d, a, b, x[15], 16, 0x1FA27CF8);	// 47
115   HH (b, c, d, a, x[ 2], 23, 0xC4AC5665);	// 48
116 
117   /* Round 4 */
118   II (a, b, c, d, x[ 0],  6, 0xF4292244);	// 49
119   II (d, a, b, c, x[ 7], 10, 0x432AFF97);	// 50
120   II (c, d, a, b, x[14], 15, 0xAB9423A7);	// 51
121   II (b, c, d, a, x[ 5], 21, 0xFC93A039);	// 52
122   II (a, b, c, d, x[12],  6, 0x655B59C3);	// 53
123   II (d, a, b, c, x[ 3], 10, 0x8F0CCC92);	// 54
124   II (c, d, a, b, x[10], 15, 0xFFEFF47D);	// 55
125   II (b, c, d, a, x[ 1], 21, 0x85845DD1);	// 56
126   II (a, b, c, d, x[ 8],  6, 0x6FA87E4F);	// 57
127   II (d, a, b, c, x[15], 10, 0xFE2CE6E0);	// 58
128   II (c, d, a, b, x[ 6], 15, 0xA3014314);	// 59
129   II (b, c, d, a, x[13], 21, 0x4E0811A1);	// 60
130   II (a, b, c, d, x[ 4],  6, 0xF7537E82);	// 61
131   II (d, a, b, c, x[11], 10, 0xBD3AF235);	// 62
132   II (c, d, a, b, x[ 2], 15, 0x2AD7D2BB);	// 63
133   II (b, c, d, a, x[ 9], 21, 0xEB86D391);	// 64
134 
135   // add the processed values to the context
136   state[0] += a; state[1] += b; state[2] += c; state[3] += d;
137   }
138 
139 
140 /* Update the context for the next 'len' bytes of 'buffer'.
141    'len' does not need to be a multiple of 64.
142 */
md5_update(const uint8_t * const buffer,const unsigned long len)143 void MD5SUM::md5_update( const uint8_t * const buffer, const unsigned long len )
144   {
145   unsigned index = count & 0x3F;	// data length in bytes mod 64
146   count += len;				// update data length
147   const unsigned rest = 64 - index;
148   unsigned long i;
149 
150   if( len >= rest )			// process as many bytes as possible
151     {
152     std::memcpy( ibuf + index, buffer, rest );
153     md5_process_block( ibuf );
154     for( i = rest; i + 63 < len; i += 64 )
155       md5_process_block( buffer + i );
156     index = 0;
157     }
158   else i = 0;
159 
160   std::memcpy( ibuf + index, buffer + i, len - i );	// save remaining input
161   }
162 
163 
164 // finish computation and return the digest
md5_finish(uint8_t digest[16])165 void MD5SUM::md5_finish( uint8_t digest[16] )
166   {
167   uint8_t padding[64] = {
168     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
171     };
172   uint8_t bits[8];
173   uint64_t c = count << 3;		// save data length in bits
174   for( int i = 0; i <= 7; ++i ) { bits[i] = (uint8_t)c; c >>= 8; }
175 
176   const unsigned index = count & 0x3F;	// data length in bytes mod 64
177   const unsigned len = (index < 56) ? (56 - index) : (120 - index);
178   md5_update( padding, len );		// pad to 56 mod 64
179   md5_update( bits, 8 );		// append data length in bits
180 
181   for( int i = 0, j = 0; i < 4; i++, j += 4 )	// store state in digest
182     {
183     digest[j  ] = (uint8_t)state[i];
184     digest[j+1] = (uint8_t)(state[i] >>  8);
185     digest[j+2] = (uint8_t)(state[i] >> 16);
186     digest[j+3] = (uint8_t)(state[i] >> 24);
187     }
188   }
189 
190 
compute_md5(const uint8_t * const buffer,const unsigned long len,uint8_t digest[16])191 void compute_md5( const uint8_t * const buffer, const unsigned long len,
192                   uint8_t digest[16] )
193   {
194   MD5SUM md5sum;
195   if( len > 0 ) md5sum.md5_update( buffer, len );
196   md5sum.md5_finish( digest );
197   }
198 
199 
check_md5(const uint8_t * const buffer,const unsigned long len,const uint8_t digest[16])200 bool check_md5( const uint8_t * const buffer, const unsigned long len,
201                 const uint8_t digest[16] )
202   {
203   uint8_t new_digest[16];
204   compute_md5( buffer, len, new_digest );
205   return ( std::memcmp( digest, new_digest, 16 ) == 0 );
206   }
207