File Coverage

ulib/md5.c
Criterion Covered Total %
statement 159 165 96.3
branch 17 24 70.8
condition n/a
subroutine n/a
pod n/a
total 176 189 93.1


line stmt bran cond sub pod time code
1             #ifdef __cplusplus
2             extern "C" {
3             #endif
4              
5             #include "ulib/md5.h"
6             #include "ulib/pack.h"
7             #include "ulib/parse.h"
8              
9             #ifdef __cplusplus
10             }
11             #endif
12              
13             #ifdef MD5_DEBUG
14             #undef MD5_DEBUG
15             #endif
16              
17             /* borrowed from Digest::MD5 with gentle mangling */
18             /*----------------------------------------------------------------*/
19             /*
20             * This library is free software; you can redistribute it and/or
21             * modify it under the same terms as Perl itself.
22             *
23             * Copyright 1998-2000 Gisle Aas.
24             * Copyright 1995-1996 Neil Winton.
25             * Copyright 1991-1992 RSA Data Security, Inc.
26             *
27             * This code is derived from Neil Winton's MD5-1.7 Perl module, which in
28             * turn is derived from the reference implementation in RFC 1321 which
29             * comes with this message:
30             *
31             * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
32             * rights reserved.
33             *
34             * License to copy and use this software is granted provided that it
35             * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
36             * Algorithm" in all material mentioning or referencing this software
37             * or this function.
38             *
39             * License is also granted to make and use derivative works provided
40             * that such works are identified as "derived from the RSA Data
41             * Security, Inc. MD5 Message-Digest Algorithm" in all material
42             * mentioning or referencing the derived work.
43             *
44             * RSA Data Security, Inc. makes no representations concerning either
45             * the merchantability of this software or the suitability of this
46             * software for any particular purpose. It is provided "as is"
47             * without express or implied warranty of any kind.
48             *
49             * These notices must be retained in any copies of any part of this
50             * documentation and/or software.
51             */
52              
53             #ifndef PERL_UNUSED_VAR
54             # define PERL_UNUSED_VAR(x) ((void)x)
55             #endif
56              
57             #if PERL_VERSION < 8
58             # undef SvPVbyte
59             # define SvPVbyte(sv, lp) (sv_utf8_downgrade((sv), 0), SvPV((sv), (lp)))
60             #endif
61              
62             /* Perl does not guarantee that U32 is exactly 32 bits. Some system
63             * has no integral type with exactly 32 bits. For instance, A Cray has
64             * short, int and long all at 64 bits so we need to apply this macro
65             * to reduce U32 values to 32 bits at appropriate places. If U32
66             * really does have 32 bits then this is a no-op.
67             */
68             #if BYTEORDER > 0x4321 || defined(TRUNCATE_U32)
69             #define TO32(x) ((x) & 0xFFFFffff)
70             #define TRUNC32(x) ((x) &= 0xFFFFffff)
71             #else
72             #define TO32(x) (x)
73             #define TRUNC32(x) /*nothing*/
74             #endif
75              
76             /* The MD5 algorithm is defined in terms of little endian 32-bit
77             * values. The following macros (and functions) allow us to convert
78             * between native integers and such values.
79             */
80 84912           static void u2s(U32 u, U8* s)
81             {
82 84912           *s++ = (U8)(u & 0xFF);
83 84912           *s++ = (U8)((u >> 8) & 0xFF);
84 84912           *s++ = (U8)((u >> 16) & 0xFF);
85 84912           *s = (U8)((u >> 24) & 0xFF);
86 84912           }
87              
88             #define s2u(s,u) ((u) = (U32)(*s) | \
89             ((U32)(*(s+1)) << 8) | \
90             ((U32)(*(s+2)) << 16) | \
91             ((U32)(*(s+3)) << 24))
92              
93             typedef struct {
94             U32 A, B, C, D; /* current digest */
95             U32 bytes_low; /* counts bytes in message */
96             U32 bytes_high; /* turn it into a 64-bit counter */
97             U8 buffer[128]; /* collect complete 64 byte blocks */
98             } MD5_CTX;
99              
100             /* Padding is added at the end of the message in order to fill a
101             * complete 64 byte block (- 8 bytes for the message length). The
102             * padding is also the reason the buffer in MD5_CTX have to be
103             * 128 bytes.
104             */
105             static const unsigned char PADDING[64] = {
106             0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
109             };
110              
111             /* Constants for MD5Transform routine.
112             */
113             #define S11 7
114             #define S12 12
115             #define S13 17
116             #define S14 22
117             #define S21 5
118             #define S22 9
119             #define S23 14
120             #define S24 20
121             #define S31 4
122             #define S32 11
123             #define S33 16
124             #define S34 23
125             #define S41 6
126             #define S42 10
127             #define S43 15
128             #define S44 21
129              
130             /* F, G, H and I are basic MD5 functions.
131             */
132             #define F(x, y, z) ((((x) & ((y) ^ (z))) ^ (z)))
133             #define G(x, y, z) F(z, x, y)
134             #define H(x, y, z) ((x) ^ (y) ^ (z))
135             #define I(x, y, z) ((y) ^ ((x) | (~z)))
136              
137             /* ROTATE_LEFT rotates x left n bits.
138             */
139             #define ROTATE_LEFT(x, n) (((x) << (n) | ((x) >> (32-(n)))))
140              
141             /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
142             * Rotation is separate from addition to prevent recomputation.
143             */
144             #define FF(a, b, c, d, s, ac) \
145             (a) += F ((b), (c), (d)) + (NEXTx) + (U32)(ac); \
146             TRUNC32((a)); \
147             (a) = ROTATE_LEFT ((a), (s)); \
148             (a) += (b); \
149             TRUNC32((a));
150              
151             #define GG(a, b, c, d, x, s, ac) \
152             (a) += G ((b), (c), (d)) + X[x] + (U32)(ac); \
153             TRUNC32((a)); \
154             (a) = ROTATE_LEFT ((a), (s)); \
155             (a) += (b); \
156             TRUNC32((a));
157              
158             #define HH(a, b, c, d, x, s, ac) \
159             (a) += H ((b), (c), (d)) + X[x] + (U32)(ac); \
160             TRUNC32((a)); \
161             (a) = ROTATE_LEFT ((a), (s)); \
162             (a) += (b); \
163             TRUNC32((a));
164              
165             #define II(a, b, c, d, x, s, ac) \
166             (a) += I ((b), (c), (d)) + X[x] + (U32)(ac); \
167             TRUNC32((a)); \
168             (a) = ROTATE_LEFT ((a), (s)); \
169             (a) += (b); \
170             TRUNC32((a));
171              
172 14152           static void MD5Init(MD5_CTX *ctx) {
173             /* Start state */
174 14152           ctx->A = 0x67452301;
175 14152           ctx->B = 0xefcdab89;
176 14152           ctx->C = 0x98badcfe;
177 14152           ctx->D = 0x10325476;
178              
179             /* message length */
180 14152           ctx->bytes_low = ctx->bytes_high = 0;
181 14152           }
182              
183 14152           static void MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks) {
184             #ifdef MD5_DEBUG
185             static int tcount = 0;
186             #endif
187              
188 14152           U32 A = ctx->A;
189 14152           U32 B = ctx->B;
190 14152           U32 C = ctx->C;
191 14152           U32 D = ctx->D;
192              
193             do {
194 14152           U32 a = A;
195 14152           U32 b = B;
196 14152           U32 c = C;
197 14152           U32 d = D;
198              
199             U32 X[16]; /* little-endian values, used in round 2-4 */
200 14152           U32 *uptr = X;
201             U32 tmp;
202             #define NEXTx (s2u(buf,tmp), buf += 4, *uptr++ = tmp)
203              
204             #ifdef MD5_DEBUG
205             if (buf == ctx->buffer)
206             fprintf(stderr,"%5d: Transform ctx->buffer", ++tcount);
207             else
208             fprintf(stderr,"%5d: Transform %p (%d)", ++tcount, buf, blocks);
209              
210             {
211             int i;
212             fprintf(stderr,"[");
213             for (i = 0; i < 16; i++) {
214             fprintf(stderr,"%x,", X[i]); /* FIXME */
215             }
216             fprintf(stderr,"]\n");
217             }
218             #endif
219              
220             /* Round 1 */
221 14152           FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
222 14152           FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
223 14152           FF (c, d, a, b, S13, 0x242070db); /* 3 */
224 14152           FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
225 14152           FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
226 14152           FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
227 14152           FF (c, d, a, b, S13, 0xa8304613); /* 7 */
228 14152           FF (b, c, d, a, S14, 0xfd469501); /* 8 */
229 14152           FF (a, b, c, d, S11, 0x698098d8); /* 9 */
230 14152           FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
231 14152           FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
232 14152           FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
233 14152           FF (a, b, c, d, S11, 0x6b901122); /* 13 */
234 14152           FF (d, a, b, c, S12, 0xfd987193); /* 14 */
235 14152           FF (c, d, a, b, S13, 0xa679438e); /* 15 */
236 14152           FF (b, c, d, a, S14, 0x49b40821); /* 16 */
237              
238             /* Round 2 */
239 14152           GG (a, b, c, d, 1, S21, 0xf61e2562); /* 17 */
240 14152           GG (d, a, b, c, 6, S22, 0xc040b340); /* 18 */
241 14152           GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
242 14152           GG (b, c, d, a, 0, S24, 0xe9b6c7aa); /* 20 */
243 14152           GG (a, b, c, d, 5, S21, 0xd62f105d); /* 21 */
244 14152           GG (d, a, b, c, 10, S22, 0x2441453); /* 22 */
245 14152           GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
246 14152           GG (b, c, d, a, 4, S24, 0xe7d3fbc8); /* 24 */
247 14152           GG (a, b, c, d, 9, S21, 0x21e1cde6); /* 25 */
248 14152           GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
249 14152           GG (c, d, a, b, 3, S23, 0xf4d50d87); /* 27 */
250 14152           GG (b, c, d, a, 8, S24, 0x455a14ed); /* 28 */
251 14152           GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
252 14152           GG (d, a, b, c, 2, S22, 0xfcefa3f8); /* 30 */
253 14152           GG (c, d, a, b, 7, S23, 0x676f02d9); /* 31 */
254 14152           GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
255              
256             /* Round 3 */
257 14152           HH (a, b, c, d, 5, S31, 0xfffa3942); /* 33 */
258 14152           HH (d, a, b, c, 8, S32, 0x8771f681); /* 34 */
259 14152           HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
260 14152           HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
261 14152           HH (a, b, c, d, 1, S31, 0xa4beea44); /* 37 */
262 14152           HH (d, a, b, c, 4, S32, 0x4bdecfa9); /* 38 */
263 14152           HH (c, d, a, b, 7, S33, 0xf6bb4b60); /* 39 */
264 14152           HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
265 14152           HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
266 14152           HH (d, a, b, c, 0, S32, 0xeaa127fa); /* 42 */
267 14152           HH (c, d, a, b, 3, S33, 0xd4ef3085); /* 43 */
268 14152           HH (b, c, d, a, 6, S34, 0x4881d05); /* 44 */
269 14152           HH (a, b, c, d, 9, S31, 0xd9d4d039); /* 45 */
270 14152           HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
271 14152           HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
272 14152           HH (b, c, d, a, 2, S34, 0xc4ac5665); /* 48 */
273              
274             /* Round 4 */
275 14152           II (a, b, c, d, 0, S41, 0xf4292244); /* 49 */
276 14152           II (d, a, b, c, 7, S42, 0x432aff97); /* 50 */
277 14152           II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
278 14152           II (b, c, d, a, 5, S44, 0xfc93a039); /* 52 */
279 14152           II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
280 14152           II (d, a, b, c, 3, S42, 0x8f0ccc92); /* 54 */
281 14152           II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
282 14152           II (b, c, d, a, 1, S44, 0x85845dd1); /* 56 */
283 14152           II (a, b, c, d, 8, S41, 0x6fa87e4f); /* 57 */
284 14152           II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
285 14152           II (c, d, a, b, 6, S43, 0xa3014314); /* 59 */
286 14152           II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
287 14152           II (a, b, c, d, 4, S41, 0xf7537e82); /* 61 */
288 14152           II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
289 14152           II (c, d, a, b, 2, S43, 0x2ad7d2bb); /* 63 */
290 14152           II (b, c, d, a, 9, S44, 0xeb86d391); /* 64 */
291              
292 14152           A += a; TRUNC32(A);
293 14152           B += b; TRUNC32(B);
294 14152           C += c; TRUNC32(C);
295 14152           D += d; TRUNC32(D);
296              
297 14152 50         } while (--blocks);
298 14152           ctx->A = A;
299 14152           ctx->B = B;
300 14152           ctx->C = C;
301 14152           ctx->D = D;
302 14152           }
303              
304             #ifdef MD5_DEBUG
305             static char*
306             ctx_dump(MD5_CTX* ctx)
307             {
308             static char buf[1024];
309             sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}",
310             ctx->A, ctx->B, ctx->C, ctx->D,
311             ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F));
312             return buf;
313             }
314             #endif
315              
316 28304           static void MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len) {
317             STRLEN blocks;
318 28304           STRLEN fill = ctx->bytes_low & 0x3F;
319              
320             #ifdef MD5_DEBUG
321             static int ucount = 0;
322             fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx), buf, len);
323             #endif
324              
325 28304           ctx->bytes_low += len;
326 28304 50         if (ctx->bytes_low < len) /* wrap around */
327 0           ctx->bytes_high++;
328              
329 28304 100         if (fill) {
330 14152           STRLEN missing = 64 - fill;
331 14152 50         if (len < missing) {
332 14152           Copy(buf, ctx->buffer + fill, len, U8);
333 14152           return;
334             }
335 0           Copy(buf, ctx->buffer + fill, missing, U8);
336 0           MD5Transform(ctx, ctx->buffer, 1);
337 0           buf += missing;
338 0           len -= missing;
339             }
340              
341 14152           blocks = len >> 6;
342 14152 50         if (blocks)
343 0           MD5Transform(ctx, buf, blocks);
344 14152 50         if ( (len &= 0x3F)) {
345 14152           Copy(buf + (blocks << 6), ctx->buffer, len, U8);
346             }
347             }
348              
349 14152           static void MD5Final(U8* digest, MD5_CTX *ctx) {
350 14152           STRLEN fill = ctx->bytes_low & 0x3F;
351 14152 50         STRLEN padlen = (fill < 56 ? 56 : 120) - fill;
352             U32 bits_low, bits_high;
353             #ifdef MD5_DEBUG
354             fprintf(stderr," Final: %s\n", ctx_dump(ctx));
355             #endif
356 14152           Copy(PADDING, ctx->buffer + fill, padlen, U8);
357 14152           fill += padlen;
358              
359 14152           bits_low = ctx->bytes_low << 3;
360 14152           bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29);
361 14152           u2s(bits_low, ctx->buffer + fill); fill += 4;
362 14152           u2s(bits_high, ctx->buffer + fill); fill += 4;
363              
364 14152           MD5Transform(ctx, ctx->buffer, fill >> 6);
365             #ifdef MD5_DEBUG
366             fprintf(stderr," Result: %s\n", ctx_dump(ctx));
367             #endif
368              
369 14152           u2s(ctx->A, digest);
370 14152           u2s(ctx->B, digest+4);
371 14152           u2s(ctx->C, digest+8);
372 14152           u2s(ctx->D, digest+12);
373 14152           }
374             /*----------------------------------------------------------------*/
375              
376             static const char *hexdigits = "0123456789abcdef";
377              
378 14152           static void hex_16(const unsigned char* from, char* to) {
379 14152           const unsigned char *end = from + 16;
380 14152           char *d = to;
381              
382 240584 100         while (from < end) {
383 226432           *d++ = hexdigits[(*from >> 4)];
384 226432           *d++ = hexdigits[(*from & 0x0F)];
385 226432           from++;
386             }
387 14152           *d = '\0';
388 14152           }
389              
390 14152           void uu_md5_hash(pUCXT, struct_uu_t *io, char *name) {
391             /* io is assumed to be a v1 namespace uuid coming in. */
392             /* name is... a name. */
393             MD5_CTX context;
394             struct_uu_t ns;
395             char tmp[37];
396             char vardig;
397             unsigned char digeststr[21];
398             uu_t packed;
399              
400 14152           uu_pack1(io, (U8*)&packed);
401              
402 14152           MD5Init(&context);
403              
404 14152           MD5Update(&context, (U8*)&packed, sizeof(packed));
405 14152 50         if (name)
406 14152           MD5Update(&context, (U8*)name, strlen(name));
407              
408 14152           MD5Final((U8*)digeststr, &context);
409 14152           digeststr[20] = '\0';
410              
411 14152           hex_16(digeststr, tmp);
412 14152           tmp[32] = '\0';
413              
414             /* hyphenate */
415 14152           Move(&tmp[20], &tmp[21], 12, char); tmp[20] = '-';
416 14152           Move(&tmp[16], &tmp[17], 17, char); tmp[16] = '-';
417 14152           Move(&tmp[12], &tmp[13], 22, char); tmp[12] = '-';
418 14152           Move(&tmp[ 8], &tmp[ 9], 27, char); tmp[ 8] = '-';
419 14152           tmp[36] = '\0';
420              
421             /* version */
422 14152           tmp[14] = '3';
423              
424             /* variant */
425 14152           vardig = tmp[19] - 48;
426 14152 100         if (vardig > 9) vardig -= 7;
427 14152 100         if (vardig > 15) vardig -= 32;
428 14152           vardig = vardig & 0x3 | 0x8;
429 14152 100         if (vardig > 9) vardig += 87;
430 145           else vardig += 48;
431 14152           tmp[19] = vardig;
432              
433 14152           uu_parse(tmp, io);
434 14152           }
435              
436             /* ex:set ts=2 sw=2 itab=spaces: */