HEVC Test Model (HM)  HM-16.18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
libmd5.c
Go to the documentation of this file.
1 /*
2  * This code implements the MD5 message-digest algorithm. The algorithm was
3  * written by Ron Rivest. This code was written by Colin Plumb in 1993, our
4  * understanding is that no copyright is claimed and that this code is in the
5  * public domain.
6  *
7  * Equivalent code is available from RSA Data Security, Inc.
8  * This code has been tested against that, and is functionally equivalent,
9  *
10  * To compute the message digest of a chunk of bytes, declare an MD5Context
11  * structure, pass it to MD5Init, call MD5Update as needed on buffers full of
12  * bytes, and then call MD5Final, which will fill a supplied 16-byte array with
13  * the digest.
14  */
15 
16 #include <stdint.h>
17 #include <string.h>
18 #include "libmd5.h"
19 
22 
23 static void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
24 
25 #ifndef __BIG_ENDIAN__
26 # define byteReverse(buf, len) /* Nothing */
27 #else
28 void byteReverse(uint32_t *buf, unsigned len);
29 /*
30  * Note: this code is harmless on little-endian machines.
31  */
32 void byteReverse(uint32_t *buf, unsigned len)
33 {
34  uint32_t t;
35  do {
36  char* bytes = (char *) buf;
37  t = ((unsigned) bytes[3] << 8 | bytes[2]) << 16 |
38  ((unsigned) bytes[1] << 8 | bytes[0]);
39  *buf = t;
40  buf++;
41  } while (--len);
42 }
43 #endif
44 
45 /*
46  * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
47  * initialization constants.
48  */
50 {
51  ctx->buf[0] = 0x67452301;
52  ctx->buf[1] = 0xefcdab89;
53  ctx->buf[2] = 0x98badcfe;
54  ctx->buf[3] = 0x10325476;
55 
56  ctx->bits[0] = 0;
57  ctx->bits[1] = 0;
58 }
59 
60 /*
61  * Update context to reflect the concatenation of another buffer full
62  * of bytes.
63  */
64 void MD5Update(context_md5_t *ctx, unsigned char *buf, unsigned len)
65 {
66  uint32_t t;
67 
68  /* Update bitcount */
69 
70  t = ctx->bits[0];
71  if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
72  ctx->bits[1]++; /* Carry from low to high */
73  ctx->bits[1] += len >> 29;
74 
75  t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
76 
77  /* Handle any leading odd-sized chunks */
78 
79  if (t) {
80  unsigned char *p = ctx->in.b8 + t;
81 
82  t = 64 - t;
83  if (len < t) {
84  memcpy(p, buf, len);
85  return;
86  }
87  memcpy(p, buf, t);
88  byteReverse(ctx->in.b32, 16);
89  MD5Transform(ctx->buf, ctx->in.b32);
90  buf += t;
91  len -= t;
92  }
93  /* Process data in 64-byte chunks */
94 
95  while (len >= 64) {
96  memcpy(ctx->in.b8, buf, 64);
97  byteReverse(ctx->in.b32, 16);
98  MD5Transform(ctx->buf, ctx->in.b32);
99  buf += 64;
100  len -= 64;
101  }
102 
103  /* Handle any remaining bytes of data. */
104 
105  memcpy(ctx->in.b8, buf, len);
106 }
107 
108 /*
109  * Final wrapup - pad to 64-byte boundary with the bit pattern
110  * 1 0* (64-bit count of bits processed, MSB-first)
111  */
112 void MD5Final(unsigned char digest[16], context_md5_t *ctx)
113 {
114  unsigned count;
115  unsigned char *p;
116 
117  /* Compute number of bytes mod 64 */
118  count = (ctx->bits[0] >> 3) & 0x3F;
119 
120  /* Set the first char of padding to 0x80. This is safe since there is
121  always at least one byte free */
122  p = ctx->in.b8 + count;
123  *p++ = 0x80;
124 
125  /* Bytes of padding needed to make 64 bytes */
126  count = 64 - 1 - count;
127 
128  /* Pad out to 56 mod 64 */
129  if (count < 8) {
130  /* Two lots of padding: Pad the first block to 64 bytes */
131  memset(p, 0, count);
132  byteReverse(ctx->in.b32, 16);
133  MD5Transform(ctx->buf, ctx->in.b32);
134 
135  /* Now fill the next block with 56 bytes */
136  memset(ctx->in.b8, 0, 56);
137  } else {
138  /* Pad block to 56 bytes */
139  memset(p, 0, count - 8);
140  }
141  byteReverse(ctx->in.b32, 14);
142 
143  /* Append length in bits and transform */
144  ctx->in.b32[14] = ctx->bits[0];
145  ctx->in.b32[15] = ctx->bits[1];
146 
147  MD5Transform(ctx->buf, ctx->in.b32);
148  byteReverse((uint32_t *) ctx->buf, 4);
149  memcpy(digest, ctx->buf, 16);
150 
151  memset(ctx, 0, sizeof(* ctx)); /* In case it's sensitive */
152  /* The original version of this code omitted the asterisk. In
153  effect, only the first part of ctx was wiped with zeros, not
154  the whole thing. Bug found by Derek Jones. Original line: */
155  // memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
156 }
157 
158 /* The four core functions - F1 is optimized somewhat */
159 
160 /* #define F1(x, y, z) (x & y | ~x & z) */
161 #define F1(x, y, z) (z ^ (x & (y ^ z)))
162 #define F2(x, y, z) F1(z, x, y)
163 #define F3(x, y, z) (x ^ y ^ z)
164 #define F4(x, y, z) (y ^ (x | ~z))
165 
166 /* This is the central step in the MD5 algorithm. */
167 #define MD5STEP(f, w, x, y, z, data, s) \
168  ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
169 
170 /*
171  * The core of the MD5 algorithm, this alters an existing MD5 hash to
172  * reflect the addition of 16 longwords of new data. MD5Update blocks
173  * the data and converts bytes into longwords for this routine.
174  */
175 static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
176 {
177  register uint32_t a, b, c, d;
178 
179  a = buf[0];
180  b = buf[1];
181  c = buf[2];
182  d = buf[3];
183 
184  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
185  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
186  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
187  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
188  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
189  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
190  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
191  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
192  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
193  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
194  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
195  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
196  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
197  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
198  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
199  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
200 
201  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
202  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
203  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
204  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
205  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
206  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
207  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
208  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
209  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
210  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
211  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
212  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
213  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
214  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
215  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
216  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
217 
218  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
219  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
220  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
221  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
222  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
223  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
224  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
225  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
226  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
227  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
228  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
229  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
230  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
231  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
232  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
233  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
234 
235  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
236  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
237  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
238  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
239  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
240  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
241  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
242  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
243  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
244  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
245  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
246  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
247  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
248  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
249  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
250  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
251 
252  buf[0] += a;
253  buf[1] += b;
254  buf[2] += c;
255  buf[3] += d;
256 }
#define F1(x, y, z)
Definition: libmd5.c:161
unsigned char b8[64]
Definition: libmd5.h:43
uint32_t bits[2]
Definition: libmd5.h:41
void MD5Init(context_md5_t *ctx)
Definition: libmd5.c:49
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
Definition: libmd5.c:175
uint32_t b32[16]
Definition: libmd5.h:44
#define F3(x, y, z)
Definition: libmd5.c:163
union _context_md5_t::@1 in
void MD5Final(unsigned char digest[16], context_md5_t *ctx)
Definition: libmd5.c:112
#define F4(x, y, z)
Definition: libmd5.c:164
uint32_t buf[4]
Definition: libmd5.h:40
#define byteReverse(buf, len)
Definition: libmd5.c:26
#define MD5STEP(f, w, x, y, z, data, s)
Definition: libmd5.c:167
void MD5Update(context_md5_t *ctx, unsigned char *buf, unsigned len)
Definition: libmd5.c:64
#define F2(x, y, z)
Definition: libmd5.c:162