Rizin
unix-like reverse engineering framework and cli tools
md5.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 1999 Alan DeKok <aland@ox.org>
2 // SPDX-License-Identifier: LGPL-2.1-or-later
3 
4 /* MD5 message-digest algorithm */
5 
6 /* This file is licensed under the LGPL, but is largely derived from
7  * public domain source code
8  */
9 
10 /*
11  * FORCE MD5 TO USE OUR MD5 HEADER FILE!
12  *
13  * If we don't do this, it might pick up the systems broken MD5.
14  * - Alan DeKok <aland@ox.org>
15  */
16 #include "md5.h"
17 #include <rz_util/rz_mem.h>
18 
19 /* The below was retrieved from
20  * http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.c?rev=1.1
21  * with the following changes:
22  * #includes commented out.
23  * Support context->count as ut32[2] instead of uint64_t
24  * u_int* to uint*
25  */
26 
27 /*
28  * This code implements the MD5 message-digest algorithm.
29  * The algorithm is due to Ron Rivest. This code was
30  * written by Colin Plumb in 1993, no copyright is claimed.
31  * This code is in the public domain; do with it what you wish.
32  *
33  * Equivalent code is available from RSA Data Security, Inc.
34  * This code has been tested against that, and is equivalent,
35  * except that you don't need to include two pages of legalese
36  * with every copy.
37  *
38  * To compute the message digest of a chunk of bytes, declare an
39  * MD5Context structure, pass it to MD5Init, call MD5Update as
40  * needed on buffers full of bytes, and then call MD5Final, which
41  * will fill a supplied 16-byte array with the digest.
42  */
43 
44 #define PUT_64BIT_LE(cp, value) \
45  do { \
46  rz_write_le32(cp, value[0]); \
47  rz_write_at_le32(cp, value[1], sizeof(ut32)); \
48  } while (0)
49 
51  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
54 };
55 
56 /* The four core functions - F1 is optimized somewhat */
57 
58 /* #define F1(x, y, z) (x & y | ~x & z) */
59 #define F1(x, y, z) (z ^ (x & (y ^ z)))
60 #define F2(x, y, z) F1(z, x, y)
61 #define F3(x, y, z) (x ^ y ^ z)
62 #define F4(x, y, z) (y ^ (x | ~z))
63 
64 /* This is the central step in the MD5 algorithm. */
65 #define MD5STEP(f, w, x, y, z, data, s) \
66  (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
67 
68 /*
69  * The core of the MD5 algorithm, this alters an existing MD5 hash to
70  * reflect the addition of 16 longwords of new data. MD5Update blocks
71  * the data and converts bytes into longwords for this routine.
72  */
73 static void MD5Transform(ut32 state[4], const ut8 block[MD5_BLOCK_LENGTH]) {
74  ut32 a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
75 
76  for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
77  in[a] = rz_read_at_le32(block, a * 4);
78  }
79 
80  a = state[0];
81  b = state[1];
82  c = state[2];
83  d = state[3];
84 
85  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
86  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
87  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
88  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
89  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
90  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
91  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
92  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
93  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
94  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
95  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
96  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
97  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
98  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
99  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
100  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
101 
102  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
103  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
104  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
105  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
106  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
107  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
108  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
109  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
110  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
111  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
112  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
113  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
114  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
115  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
116  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
117  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
118 
119  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
120  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
121  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
122  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
123  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
124  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
125  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
126  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
127  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
128  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
129  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
130  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
131  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
132  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
133  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
134  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
135 
136  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
137  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
138  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
139  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
140  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
141  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
142  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
143  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
144  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
145  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
146  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
147  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
148  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
149  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
150  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
151  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
152 
153  state[0] += a;
154  state[1] += b;
155  state[2] += c;
156  state[3] += d;
157 }
158 
159 /*
160  * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
161  * initialization constants.
162  */
164  ctx->count[0] = 0;
165  ctx->count[1] = 0;
166  ctx->state[0] = 0x67452301;
167  ctx->state[1] = 0xefcdab89;
168  ctx->state[2] = 0x98badcfe;
169  ctx->state[3] = 0x10325476;
170 }
171 
172 /*
173  * Update context to reflect the concatenation of another buffer full
174  * of bytes.
175  */
176 RZ_IPI void rz_MD5Update(rz_MD5_CTX *ctx, const unsigned char *input, size_t len) {
177  size_t have, need;
178 
179  /* Check how many bytes we already have and how many more we need. */
180  have = (size_t)((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
181  need = MD5_BLOCK_LENGTH - have;
182 
183  /* Update bitcount */
184  /* ctx->count += (uint64_t)len << 3;*/
185  if ((ctx->count[0] += ((ut32)len << 3)) < (ut32)len) {
186  /* Overflowed ctx->count[0] */
187  ctx->count[1]++;
188  }
189  ctx->count[1] += ((ut32)len >> 29);
190 
191  if (len >= need) {
192  if (have != 0) {
193  memcpy(ctx->buffer + have, input, need);
194  MD5Transform(ctx->state, ctx->buffer);
195  input += need;
196  len -= need;
197  have = 0;
198  }
199 
200  /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
201  while (len >= MD5_BLOCK_LENGTH) {
202  MD5Transform(ctx->state, input);
205  }
206  }
207 
208  /* Handle any remaining bytes of data. */
209  if (len != 0) {
210  memcpy(ctx->buffer + have, input, len);
211  }
212 }
213 
214 /*
215  * Final wrapup - pad to 64-byte boundary with the bit pattern
216  * 1 0* (64-bit count of bits processed, MSB-first)
217  */
218 RZ_IPI void rz_MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], rz_MD5_CTX *ctx) {
219  ut8 count[8];
220  size_t padlen;
221  int i;
222 
223  /* Convert count to 8 bytes in little endian order. */
224  PUT_64BIT_LE(count, ctx->count);
225 
226  /* Pad out to 56 mod 64. */
227  padlen = MD5_BLOCK_LENGTH -
228  ((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
229  if (padlen < 1 + 8) {
230  padlen += MD5_BLOCK_LENGTH;
231  }
232  rz_MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
233  rz_MD5Update(ctx, count, 8);
234 
235  if (digest != NULL) {
236  for (i = 0; i < 4; i++) {
237  rz_write_le32(digest + i * 4, ctx->state[i]);
238  }
239  }
240  rz_mem_memzero(ctx, sizeof(*ctx)); /* in case it's sensitive */
241 }
size_t len
Definition: 6502dis.c:15
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t * in
Definition: block.h:527
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint32_t ut32
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define MD5STEP(f, w, x, y, z, data, s)
Definition: md5.c:65
RZ_IPI void rz_MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], rz_MD5_CTX *ctx)
Definition: md5.c:218
#define F1(x, y, z)
Definition: md5.c:59
static ut8 PADDING[MD5_BLOCK_LENGTH]
Definition: md5.c:50
#define F4(x, y, z)
Definition: md5.c:62
#define PUT_64BIT_LE(cp, value)
Definition: md5.c:44
#define F3(x, y, z)
Definition: md5.c:61
static void MD5Transform(ut32 state[4], const ut8 block[MD5_BLOCK_LENGTH])
Definition: md5.c:73
RZ_IPI void rz_MD5Init(rz_MD5_CTX *ctx)
Definition: md5.c:163
RZ_IPI void rz_MD5Update(rz_MD5_CTX *ctx, const unsigned char *input, size_t len)
Definition: md5.c:176
#define F2(x, y, z)
Definition: md5.c:60
#define MD5_DIGEST_LENGTH
Definition: md5.h:34
#define MD5_BLOCK_LENGTH
Definition: md5.h:33
static void rz_write_le32(void *dest, ut32 val)
Definition: rz_endian.h:256
static ut32 rz_read_at_le32(const void *src, size_t offset)
Definition: rz_endian.h:248
RZ_API void rz_mem_memzero(void *, size_t)
Definition: mem.c:365
int size_t
Definition: sftypes.h:40
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
Definition: md5.h:36
Definition: dis.h:43
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)