1 /*
2 **  OSSP uuid - Universally Unique Identifier
3 **  Copyright (c) 2004-2008 Ralf S. Engelschall <rse@engelschall.com>
4 **  Copyright (c) 2004-2008 The OSSP Project <http://www.ossp.org/>
5 **
6 **  This file is part of OSSP uuid, a library for the generation
7 **  of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/
8 **
9 **  Permission to use, copy, modify, and distribute this software for
10 **  any purpose with or without fee is hereby granted, provided that
11 **  the above copyright notice and this permission notice appear in all
12 **  copies.
13 **
14 **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
15 **  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 **  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
18 **  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 **  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 **  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 **  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 **  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 **  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
24 **  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 **  SUCH DAMAGE.
26 **
27 **  uuid_md5.c: MD5 API implementation
28 */
29 
30 /* own headers (part 1/2) */
31 #include "uuid_ac.h"
32 
33 /* system headers */
34 #include <stdlib.h>
35 #include <string.h>
36 
37 /* own headers (part 2/2) */
38 #include "uuid_md5.h"
39 
40 /*
41  * This is a RFC 1321 compliant Message Digest 5 (MD5) algorithm
42  * implementation. It is directly derived from the RSA code published in
43  * RFC 1321 with just the following functionality preserving changes:
44  * - converted function definitions from K&R to ANSI C
45  * - included contents of the "global.h" and "md5.h" headers
46  * - moved the SXX defines into the MD5Transform function
47  * - replaced MD5_memcpy() with memcpy(3) and MD5_memset() with memset(3)
48  * - renamed "index" variables to "idx" to avoid namespace conflicts
49  * - reformatted C style to conform with OSSP C style
50  * - added own OSSP style frontend API
51  */
52 
53 /*
54 ** ==== BEGIN RFC 1321 CODE ====
55 */
56 
57 /*
58  * RSA Data Security, Inc., MD5 message-digest algorithm
59  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
60  * All rights reserved.
61  *
62  * License to copy and use this software is granted provided that it
63  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
64  * Algorithm" in all material mentioning or referencing this software
65  * or this function.
66  *
67  * License is also granted to make and use derivative works provided
68  * that such works are identified as "derived from the RSA Data
69  * Security, Inc. MD5 Message-Digest Algorithm" in all material
70  * mentioning or referencing the derived work.
71  *
72  * RSA Data Security, Inc. makes no representations concerning either
73  * the merchantability of this software or the suitability of this
74  * software for any particular purpose. It is provided "as is"
75  * without express or implied warranty of any kind.
76  *
77  * These notices must be retained in any copies of any part of this
78  * documentation and/or software.
79  */
80 
81 /* POINTER defines a generic pointer type */
82 typedef unsigned char *POINTER;
83 
84 /* UINT4 defines a four byte word */
85 #if SIZEOF_UNSIGNED_SHORT       == 4
86 typedef unsigned short int     UINT4;
87 #elif SIZEOF_UNSIGNED_INT       == 4
88 typedef unsigned int           UINT4;
89 #elif SIZEOF_UNSIGNED_LONG      == 4
90 typedef unsigned long int      UINT4;
91 #elif SIZEOF_UNSIGNED_LONG_LONG == 4
92 typedef unsigned long long int UINT4;
93 #else
94 #error ERROR: unable to determine UINT4 type (four byte word)
95 #endif
96 
97 /* MD5 context. */
98 typedef struct {
99   UINT4 state[4];                                   /* state (ABCD) */
100   UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
101   unsigned char buffer[64];                         /* input buffer */
102 } MD5_CTX;
103 
104 /* prototypes for internal functions */
105 static void MD5Init      (MD5_CTX *_ctx);
106 static void MD5Update    (MD5_CTX *_ctx, unsigned char *, unsigned int);
107 static void MD5Final     (unsigned char [], MD5_CTX *);
108 static void MD5Transform (UINT4 [], unsigned char []);
109 static void Encode       (unsigned char *, UINT4 *, unsigned int);
110 static void Decode       (UINT4 *, unsigned char *, unsigned int);
111 
112 /* finalization padding */
113 static unsigned char PADDING[64] = {
114   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
117 };
118 
119 /* F, G, H and I are basic MD5 functions. */
120 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
121 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
122 #define H(x, y, z) ((x) ^ (y) ^ (z))
123 #define I(x, y, z) ((y) ^ ((x) | (~z)))
124 
125 /* ROTATE_LEFT rotates x left n bits. */
126 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
127 
128 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
129    Rotation is separate from addition to prevent recomputation. */
130 #define FF(a, b, c, d, x, s, ac) { \
131  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
132  (a) = ROTATE_LEFT ((a), (s)); \
133  (a) += (b); \
134 }
135 #define GG(a, b, c, d, x, s, ac) { \
136  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
137  (a) = ROTATE_LEFT ((a), (s)); \
138  (a) += (b); \
139 }
140 #define HH(a, b, c, d, x, s, ac) { \
141  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
142  (a) = ROTATE_LEFT ((a), (s)); \
143  (a) += (b); \
144 }
145 #define II(a, b, c, d, x, s, ac) { \
146  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
147  (a) = ROTATE_LEFT ((a), (s)); \
148  (a) += (b); \
149 }
150 
151 /* MD5 initialization. Begins an MD5 operation, writing a new context. */
MD5Init(MD5_CTX * context)152 static void MD5Init(
153     MD5_CTX *context)
154 {
155     context->count[0] = context->count[1] = 0;
156 
157     /* Load magic initialization constants. */
158     context->state[0] = 0x67452301;
159     context->state[1] = 0xefcdab89;
160     context->state[2] = 0x98badcfe;
161     context->state[3] = 0x10325476;
162     return;
163 }
164 
165 /* MD5 block update operation. Continues an MD5 message-digest
166    operation, processing another message block, and updating the
167    context. */
MD5Update(MD5_CTX * context,unsigned char * input,unsigned int inputLen)168 static void MD5Update(
169     MD5_CTX *context,                                        /* context */
170     unsigned char *input,                                /* input block */
171     unsigned int inputLen)                     /* length of input block */
172 {
173     unsigned int i, idx, partLen;
174 
175     /* Compute number of bytes mod 64 */
176     idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
177 
178     /* Update number of bits */
179     if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
180         context->count[1]++;
181     context->count[1] += ((UINT4)inputLen >> 29);
182 
183     partLen = (unsigned int)64 - idx;
184 
185     /* Transform as many times as possible.  */
186     if (inputLen >= partLen) {
187         memcpy((POINTER)&context->buffer[idx], (POINTER)input, (size_t)partLen);
188         MD5Transform(context->state, context->buffer);
189         for (i = partLen; i + 63 < inputLen; i += 64)
190             MD5Transform(context->state, &input[i]);
191         idx = 0;
192     }
193     else
194         i = 0;
195 
196     /* Buffer remaining input */
197     memcpy((POINTER)&context->buffer[idx], (POINTER)&input[i], (size_t)(inputLen - i));
198 }
199 
200 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
201    the message digest and zeroizing the context. */
MD5Final(unsigned char digest[],MD5_CTX * context)202 static void MD5Final(
203     unsigned char digest[],                                 /* message digest */
204     MD5_CTX *context)                                       /* context */
205 {
206     unsigned char bits[8];
207     unsigned int idx, padLen;
208 
209     /* Save number of bits */
210     Encode(bits, context->count, 8);
211 
212     /* Pad out to 56 mod 64. */
213     idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
214     padLen = (idx < 56) ? ((unsigned int)56 - idx) : ((unsigned int)120 - idx);
215     MD5Update(context, PADDING, padLen);
216 
217     /* Append length (before padding) */
218     MD5Update(context, bits, 8);
219 
220     /* Store state in digest */
221     Encode(digest, context->state, 16);
222 
223     /* Zeroize sensitive information. */
224     memset((POINTER)context, 0, sizeof(*context));
225 }
226 
227 /* MD5 basic transformation. Transforms state based on block. */
MD5Transform(UINT4 state[],unsigned char block[])228 static void MD5Transform(
229     UINT4 state[],
230     unsigned char block[])
231 {
232     UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
233 
234     Decode(x, block, 64);
235 
236     /* Round 1 */
237 #define S11 7
238 #define S12 12
239 #define S13 17
240 #define S14 22
241     FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
242     FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
243     FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
244     FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
245     FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
246     FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
247     FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
248     FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
249     FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
250     FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
251     FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
252     FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
253     FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
254     FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
255     FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
256     FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
257 
258    /* Round 2 */
259 #define S21 5
260 #define S22 9
261 #define S23 14
262 #define S24 20
263     GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
264     GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
265     GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
266     GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
267     GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
268     GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
269     GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
270     GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
271     GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
272     GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
273     GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
274     GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
275     GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
276     GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
277     GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
278     GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
279 
280     /* Round 3 */
281 #define S31 4
282 #define S32 11
283 #define S33 16
284 #define S34 23
285     HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
286     HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
287     HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
288     HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
289     HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
290     HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
291     HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
292     HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
293     HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
294     HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
295     HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
296     HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
297     HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
298     HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
299     HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
300     HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
301 
302     /* Round 4 */
303 #define S41 6
304 #define S42 10
305 #define S43 15
306 #define S44 21
307     II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
308     II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
309     II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
310     II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
311     II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
312     II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
313     II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
314     II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
315     II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
316     II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
317     II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
318     II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
319     II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
320     II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
321     II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
322     II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
323 
324     state[0] += a;
325     state[1] += b;
326     state[2] += c;
327     state[3] += d;
328 
329     /* Zeroize sensitive information. */
330     memset((POINTER)x, 0, sizeof(x));
331 }
332 
333 /* Encodes input (UINT4) into output (unsigned char).
334    Assumes len is a multiple of 4. */
Encode(unsigned char * output,UINT4 * input,unsigned int len)335 static void Encode(
336     unsigned char *output,
337     UINT4 *input,
338     unsigned int len)
339 {
340     unsigned int i, j;
341 
342     for (i = 0, j = 0; j < len; i++, j += 4) {
343         output[j]   = (unsigned char)( input[i]        & 0xff);
344         output[j+1] = (unsigned char)((input[i] >> 8)  & 0xff);
345         output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
346         output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
347     }
348     return;
349 }
350 
351 /* Decodes input (unsigned char) into output (UINT4).
352    Assumes len is a multiple of 4. */
Decode(UINT4 * output,unsigned char * input,unsigned int len)353 static void Decode(
354     UINT4 *output,
355     unsigned char *input,
356     unsigned int len)
357 {
358     unsigned int i, j;
359 
360     for (i = 0, j = 0; j < len; i++, j += 4)
361         output[i] =   ( (UINT4)input[j])
362                     | (((UINT4)input[j+1]) << 8 )
363                     | (((UINT4)input[j+2]) << 16)
364                     | (((UINT4)input[j+3]) << 24);
365     return;
366 }
367 
368 /*
369 ** ==== END RFC 1321 CODE ====
370 */
371 
372 struct md5_st {
373     MD5_CTX ctx;
374 };
375 
md5_create(md5_t ** md5)376 md5_rc_t md5_create(md5_t **md5)
377 {
378     if (md5 == NULL)
379         return MD5_RC_ARG;
380     if ((*md5 = (md5_t *)malloc(sizeof(md5_t))) == NULL)
381         return MD5_RC_MEM;
382     MD5Init(&((*md5)->ctx));
383     return MD5_RC_OK;
384 }
385 
md5_init(md5_t * md5)386 md5_rc_t md5_init(md5_t *md5)
387 {
388     if (md5 == NULL)
389         return MD5_RC_ARG;
390     MD5Init(&(md5->ctx));
391     return MD5_RC_OK;
392 }
393 
md5_update(md5_t * md5,const void * data_ptr,size_t data_len)394 md5_rc_t md5_update(md5_t *md5, const void *data_ptr, size_t data_len)
395 {
396     if (md5 == NULL)
397         return MD5_RC_ARG;
398     MD5Update(&(md5->ctx), (unsigned char *)data_ptr, (unsigned int)data_len);
399     return MD5_RC_OK;
400 }
401 
md5_store(md5_t * md5,void ** data_ptr,size_t * data_len)402 md5_rc_t md5_store(md5_t *md5, void **data_ptr, size_t *data_len)
403 {
404     MD5_CTX ctx;
405 
406     if (md5 == NULL || data_ptr == NULL)
407         return MD5_RC_ARG;
408     if (*data_ptr == NULL) {
409         if ((*data_ptr = malloc(MD5_LEN_BIN)) == NULL)
410             return MD5_RC_MEM;
411         if (data_len != NULL)
412             *data_len = MD5_LEN_BIN;
413     }
414     else {
415         if (data_len != NULL) {
416             if (*data_len < MD5_LEN_BIN)
417                 return MD5_RC_MEM;
418             *data_len = MD5_LEN_BIN;
419         }
420     }
421     memcpy((void *)(&ctx), (void *)(&(md5->ctx)), sizeof(MD5_CTX));
422     MD5Final((unsigned char *)(*data_ptr), &(ctx));
423     return MD5_RC_OK;
424 }
425 
md5_format(md5_t * md5,char ** data_ptr,size_t * data_len)426 md5_rc_t md5_format(md5_t *md5, char **data_ptr, size_t *data_len)
427 {
428     static const char hex[] = "0123456789abcdef";
429     unsigned char buf[MD5_LEN_BIN];
430     unsigned char *bufptr;
431     size_t buflen;
432     md5_rc_t rc;
433     int i;
434 
435     if (md5 == NULL || data_ptr == NULL)
436         return MD5_RC_ARG;
437     if (*data_ptr == NULL) {
438         if ((*data_ptr = (char *)malloc(MD5_LEN_STR+1)) == NULL)
439             return MD5_RC_MEM;
440         if (data_len != NULL)
441             *data_len = MD5_LEN_STR+1;
442     }
443     else {
444         if (data_len != NULL) {
445             if (*data_len < MD5_LEN_STR+1)
446                 return MD5_RC_MEM;
447             *data_len = MD5_LEN_STR+1;
448         }
449     }
450 
451     bufptr = buf;
452     buflen = sizeof(buf);
453     if ((rc = md5_store(md5, (void **)((void *)&bufptr), &buflen)) != MD5_RC_OK)
454         return rc;
455 
456     for (i = 0; i < (int)buflen; i++) {
457 	    (*data_ptr)[(i*2)+0] = hex[(int)(bufptr[i] >> 4)];
458 	    (*data_ptr)[(i*2)+1] = hex[(int)(bufptr[i] & 0x0f)];
459     }
460     (*data_ptr)[(i*2)] = '\0';
461     return MD5_RC_OK;
462 }
463 
md5_destroy(md5_t * md5)464 md5_rc_t md5_destroy(md5_t *md5)
465 {
466     if (md5 == NULL)
467         return MD5_RC_ARG;
468     free(md5);
469     return MD5_RC_OK;
470 }
471 
472