1 /*        $NetBSD: md5.c,v 1.8 2021/08/14 16:14:58 christos Exp $     */
2 
3 /* md5.c -- MD5 message-digest algorithm */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* This work was adapted for inclusion in OpenLDAP Software by
19  * Kurt D. Zeilenga based upon code developed by Colin Plumb
20  * and subsequently modified by Jim Kingdon.
21  */
22 
23 /*
24  * This code implements the MD5 message-digest algorithm.
25  * The algorithm is due to Ron Rivest.  This code was
26  * written by Colin Plumb in 1993, no copyright is claimed.
27  * This code is in the public domain; do with it what you wish.
28  *
29  * Equivalent code is available from RSA Data Security, Inc.
30  * This code has been tested against that, and is equivalent,
31  * except that you don't need to include two pages of legalese
32  * with every copy.
33  *
34  * To compute the message digest of a chunk of bytes, declare an
35  * MD5Context structure, pass it to MD5Init, call MD5Update as
36  * needed on buffers full of bytes, and then call MD5Final, which
37  * will fill a supplied 16-byte array with the digest.
38  */
39 
40 /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
41    not require an integer type which is exactly 32 bits.  This work
42    draws on the changes for the same purpose by Tatu Ylonen
43    <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
44    that code, there is no copyright issue.  I hereby disclaim
45    copyright in any changes I have made; this code remains in the
46    public domain.  */
47 
48 #include <sys/cdefs.h>
49 __RCSID("$NetBSD: md5.c,v 1.8 2021/08/14 16:14:58 christos Exp $");
50 
51 #include "portable.h"
52 
53 #include <ac/string.h>
54 
55 /* include socket.h to get sys/types.h and/or winsock2.h */
56 #include <ac/socket.h>
57 
58 #include <lutil_md5.h>
59 
60 /* Little-endian byte-swapping routines.  Note that these do not
61    depend on the size of datatypes such as ber_uint_t, nor do they require
62    us to detect the endianness of the machine we are running on.  It
63    is possible they should be macros for speed, but I would be
64    surprised if they were a performance bottleneck for MD5.  */
65 
66 static ber_uint_t
getu32(const unsigned char * addr)67 getu32( const unsigned char *addr )
68 {
69           return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
70                     | addr[1]) << 8 | addr[0];
71 }
72 
73 static void
putu32(ber_uint_t data,unsigned char * addr)74 putu32( ber_uint_t data, unsigned char *addr )
75 {
76           addr[0] = (unsigned char)data;
77           addr[1] = (unsigned char)(data >> 8);
78           addr[2] = (unsigned char)(data >> 16);
79           addr[3] = (unsigned char)(data >> 24);
80 }
81 
82 /*
83  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
84  * initialization constants.
85  */
86 void
lutil_MD5Init(struct lutil_MD5Context * ctx)87 lutil_MD5Init( struct lutil_MD5Context *ctx )
88 {
89           ctx->buf[0] = 0x67452301;
90           ctx->buf[1] = 0xefcdab89;
91           ctx->buf[2] = 0x98badcfe;
92           ctx->buf[3] = 0x10325476;
93 
94           ctx->bits[0] = 0;
95           ctx->bits[1] = 0;
96 }
97 
98 /*
99  * Update context to reflect the concatenation of another buffer full
100  * of bytes.
101  */
102 void
lutil_MD5Update(struct lutil_MD5Context * ctx,const unsigned char * buf,ber_len_t len)103 lutil_MD5Update(
104     struct lutil_MD5Context   *ctx,
105     const unsigned char                 *buf,
106     ber_len_t                 len
107 )
108 {
109           ber_uint_t t;
110 
111           /* Update bitcount */
112 
113           t = ctx->bits[0];
114           if ((ctx->bits[0] = (t + ((ber_uint_t)len << 3)) & 0xffffffff) < t)
115                     ctx->bits[1]++;     /* Carry from low to high */
116           ctx->bits[1] += len >> 29;
117 
118           t = (t >> 3) & 0x3f;          /* Bytes already in shsInfo->data */
119 
120           /* Handle any leading odd-sized chunks */
121 
122           if ( t ) {
123                     unsigned char *p = ctx->in + t;
124 
125                     t = 64-t;
126                     if (len < t) {
127                               AC_MEMCPY(p, buf, len);
128                               return;
129                     }
130                     AC_MEMCPY(p, buf, t);
131                     lutil_MD5Transform(ctx->buf, ctx->in);
132                     buf += t;
133                     len -= t;
134           }
135 
136           /* Process data in 64-byte chunks */
137 
138           while (len >= 64) {
139                     AC_MEMCPY(ctx->in, buf, 64);
140                     lutil_MD5Transform(ctx->buf, ctx->in);
141                     buf += 64;
142                     len -= 64;
143           }
144 
145           /* Handle any remaining bytes of data. */
146 
147           AC_MEMCPY(ctx->in, buf, len);
148 }
149 
150 /*
151  * Final wrapup - pad to 64-byte boundary with the bit pattern
152  * 1 0* (64-bit count of bits processed, MSB-first)
153  */
154 void
lutil_MD5Final(unsigned char * digest,struct lutil_MD5Context * ctx)155 lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx )
156 {
157           unsigned count;
158           unsigned char *p;
159 
160           /* Compute number of bytes mod 64 */
161           count = (ctx->bits[0] >> 3) & 0x3F;
162 
163           /* Set the first char of padding to 0x80.  This is safe since there is
164              always at least one byte free */
165           p = ctx->in + count;
166           *p++ = 0x80;
167 
168           /* Bytes of padding needed to make 64 bytes */
169           count = 64 - 1 - count;
170 
171           /* Pad out to 56 mod 64 */
172           if (count < 8) {
173                     /* Two lots of padding:  Pad the first block to 64 bytes */
174                     memset(p, '\0', count);
175                     lutil_MD5Transform(ctx->buf, ctx->in);
176 
177                     /* Now fill the next block with 56 bytes */
178                     memset(ctx->in, '\0', 56);
179           } else {
180                     /* Pad block to 56 bytes */
181                     memset(p, '\0', count-8);
182           }
183 
184           /* Append length in bits and transform */
185           putu32(ctx->bits[0], ctx->in + 56);
186           putu32(ctx->bits[1], ctx->in + 60);
187 
188           lutil_MD5Transform(ctx->buf, ctx->in);
189           putu32(ctx->buf[0], digest);
190           putu32(ctx->buf[1], digest + 4);
191           putu32(ctx->buf[2], digest + 8);
192           putu32(ctx->buf[3], digest + 12);
193           memset(ctx, '\0', sizeof(*ctx));        /* In case it's sensitive */
194 }
195 
196 #ifndef ASM_MD5
197 
198 /* The four core functions - F1 is optimized somewhat */
199 
200 /* #define F1(x, y, z) (x & y | ~x & z) */
201 #define F1(x, y, z) (z ^ (x & (y ^ z)))
202 #define F2(x, y, z) F1(z, x, y)
203 #define F3(x, y, z) (x ^ y ^ z)
204 #define F4(x, y, z) (y ^ (x | ~z))
205 
206 /* This is the central step in the MD5 algorithm. */
207 #define MD5STEP(f, w, x, y, z, data, s) \
208           ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
209 
210 /*
211  * The core of the MD5 algorithm, this alters an existing MD5 hash to
212  * reflect the addition of 16 longwords of new data.  MD5Update blocks
213  * the data and converts bytes into longwords for this routine.
214  */
215 void
lutil_MD5Transform(ber_uint_t * buf,const unsigned char * inraw)216 lutil_MD5Transform( ber_uint_t *buf, const unsigned char *inraw )
217 {
218           register ber_uint_t a, b, c, d;
219           ber_uint_t in[16];
220           int i;
221 
222           for (i = 0; i < 16; ++i)
223                     in[i] = getu32 (inraw + 4 * i);
224 
225           a = buf[0];
226           b = buf[1];
227           c = buf[2];
228           d = buf[3];
229 
230           MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
231           MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
232           MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
233           MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
234           MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
235           MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
236           MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
237           MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
238           MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
239           MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
240           MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
241           MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
242           MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
243           MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
244           MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
245           MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
246 
247           MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
248           MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
249           MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
250           MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
251           MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
252           MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
253           MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
254           MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
255           MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
256           MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
257           MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
258           MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
259           MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
260           MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
261           MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
262           MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
263 
264           MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
265           MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
266           MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
267           MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
268           MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
269           MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
270           MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
271           MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
272           MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
273           MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
274           MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
275           MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
276           MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
277           MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
278           MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
279           MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
280 
281           MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
282           MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
283           MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
284           MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
285           MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
286           MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
287           MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
288           MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
289           MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
290           MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
291           MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
292           MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
293           MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
294           MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
295           MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
296           MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
297 
298           buf[0] += a;
299           buf[1] += b;
300           buf[2] += c;
301           buf[3] += d;
302 }
303 #endif
304 
305 #ifdef TEST
306 /* Simple test program.  Can use it to manually run the tests from
307    RFC1321 for example.  */
308 #include <stdio.h>
309 
310 int
main(int argc,char ** argv)311 main (int  argc, char **argv )
312 {
313           struct lutil_MD5Context context;
314           unsigned char checksum[LUTIL_MD5_BYTES];
315           int i;
316           int j;
317 
318           if (argc < 2)
319           {
320                     fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
321                     return EXIT_FAILURE;
322           }
323           for (j = 1; j < argc; ++j)
324           {
325                     printf ("MD5 (\"%s\") = ", argv[j]);
326                     lutil_MD5Init (&context);
327                     lutil_MD5Update (&context, argv[j], strlen (argv[j]));
328                     lutil_MD5Final (checksum, &context);
329                     for (i = 0; i < LUTIL_MD5_BYTES; i++)
330                     {
331                               printf ("%02x", (unsigned int) checksum[i]);
332                     }
333                     printf ("\n");
334           }
335           return EXIT_SUCCESS;
336 }
337 #endif /* TEST */
338