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 912           static void u2s(U32 u, U8* s)
81             {
82 912           *s++ = (U8)(u & 0xFF);
83 912           *s++ = (U8)((u >> 8) & 0xFF);
84 912           *s++ = (U8)((u >> 16) & 0xFF);
85 912           *s = (U8)((u >> 24) & 0xFF);
86 912           }
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 152           static void MD5Init(MD5_CTX *ctx) {
173             /* Start state */
174 152           ctx->A = 0x67452301;
175 152           ctx->B = 0xefcdab89;
176 152           ctx->C = 0x98badcfe;
177 152           ctx->D = 0x10325476;
178              
179             /* message length */
180 152           ctx->bytes_low = ctx->bytes_high = 0;
181 152           }
182              
183 152           static void MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks) {
184             #ifdef MD5_DEBUG
185             static int tcount = 0;
186             #endif
187              
188 152           U32 A = ctx->A;
189 152           U32 B = ctx->B;
190 152           U32 C = ctx->C;
191 152           U32 D = ctx->D;
192              
193             do {
194 152           U32 a = A;
195 152           U32 b = B;
196 152           U32 c = C;
197 152           U32 d = D;
198              
199             U32 X[16]; /* little-endian values, used in round 2-4 */
200 152           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 152           FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
222 152           FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
223 152           FF (c, d, a, b, S13, 0x242070db); /* 3 */
224 152           FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
225 152           FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
226 152           FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
227 152           FF (c, d, a, b, S13, 0xa8304613); /* 7 */
228 152           FF (b, c, d, a, S14, 0xfd469501); /* 8 */
229 152           FF (a, b, c, d, S11, 0x698098d8); /* 9 */
230 152           FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
231 152           FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
232 152           FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
233 152           FF (a, b, c, d, S11, 0x6b901122); /* 13 */
234 152           FF (d, a, b, c, S12, 0xfd987193); /* 14 */
235 152           FF (c, d, a, b, S13, 0xa679438e); /* 15 */
236 152           FF (b, c, d, a, S14, 0x49b40821); /* 16 */
237              
238             /* Round 2 */
239 152           GG (a, b, c, d, 1, S21, 0xf61e2562); /* 17 */
240 152           GG (d, a, b, c, 6, S22, 0xc040b340); /* 18 */
241 152           GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
242 152           GG (b, c, d, a, 0, S24, 0xe9b6c7aa); /* 20 */
243 152           GG (a, b, c, d, 5, S21, 0xd62f105d); /* 21 */
244 152           GG (d, a, b, c, 10, S22, 0x2441453); /* 22 */
245 152           GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
246 152           GG (b, c, d, a, 4, S24, 0xe7d3fbc8); /* 24 */
247 152           GG (a, b, c, d, 9, S21, 0x21e1cde6); /* 25 */
248 152           GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
249 152           GG (c, d, a, b, 3, S23, 0xf4d50d87); /* 27 */
250 152           GG (b, c, d, a, 8, S24, 0x455a14ed); /* 28 */
251 152           GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
252 152           GG (d, a, b, c, 2, S22, 0xfcefa3f8); /* 30 */
253 152           GG (c, d, a, b, 7, S23, 0x676f02d9); /* 31 */
254 152           GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
255              
256             /* Round 3 */
257 152           HH (a, b, c, d, 5, S31, 0xfffa3942); /* 33 */
258 152           HH (d, a, b, c, 8, S32, 0x8771f681); /* 34 */
259 152           HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
260 152           HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
261 152           HH (a, b, c, d, 1, S31, 0xa4beea44); /* 37 */
262 152           HH (d, a, b, c, 4, S32, 0x4bdecfa9); /* 38 */
263 152           HH (c, d, a, b, 7, S33, 0xf6bb4b60); /* 39 */
264 152           HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
265 152           HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
266 152           HH (d, a, b, c, 0, S32, 0xeaa127fa); /* 42 */
267 152           HH (c, d, a, b, 3, S33, 0xd4ef3085); /* 43 */
268 152           HH (b, c, d, a, 6, S34, 0x4881d05); /* 44 */
269 152           HH (a, b, c, d, 9, S31, 0xd9d4d039); /* 45 */
270 152           HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
271 152           HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
272 152           HH (b, c, d, a, 2, S34, 0xc4ac5665); /* 48 */
273              
274             /* Round 4 */
275 152           II (a, b, c, d, 0, S41, 0xf4292244); /* 49 */
276 152           II (d, a, b, c, 7, S42, 0x432aff97); /* 50 */
277 152           II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
278 152           II (b, c, d, a, 5, S44, 0xfc93a039); /* 52 */
279 152           II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
280 152           II (d, a, b, c, 3, S42, 0x8f0ccc92); /* 54 */
281 152           II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
282 152           II (b, c, d, a, 1, S44, 0x85845dd1); /* 56 */
283 152           II (a, b, c, d, 8, S41, 0x6fa87e4f); /* 57 */
284 152           II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
285 152           II (c, d, a, b, 6, S43, 0xa3014314); /* 59 */
286 152           II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
287 152           II (a, b, c, d, 4, S41, 0xf7537e82); /* 61 */
288 152           II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
289 152           II (c, d, a, b, 2, S43, 0x2ad7d2bb); /* 63 */
290 152           II (b, c, d, a, 9, S44, 0xeb86d391); /* 64 */
291              
292 152           A += a; TRUNC32(A);
293 152           B += b; TRUNC32(B);
294 152           C += c; TRUNC32(C);
295 152           D += d; TRUNC32(D);
296              
297 152 50         } while (--blocks);
298 152           ctx->A = A;
299 152           ctx->B = B;
300 152           ctx->C = C;
301 152           ctx->D = D;
302 152           }
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 304           static void MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len) {
317             STRLEN blocks;
318 304           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 304           ctx->bytes_low += len;
326 304 50         if (ctx->bytes_low < len) /* wrap around */
327 0           ctx->bytes_high++;
328              
329 304 100         if (fill) {
330 152           STRLEN missing = 64 - fill;
331 152 50         if (len < missing) {
332 152           Copy(buf, ctx->buffer + fill, len, U8);
333 152           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 152           blocks = len >> 6;
342 152 50         if (blocks)
343 0           MD5Transform(ctx, buf, blocks);
344 152 50         if ( (len &= 0x3F)) {
345 152           Copy(buf + (blocks << 6), ctx->buffer, len, U8);
346             }
347             }
348              
349 152           static void MD5Final(U8* digest, MD5_CTX *ctx) {
350 152           STRLEN fill = ctx->bytes_low & 0x3F;
351 152 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 152           Copy(PADDING, ctx->buffer + fill, padlen, U8);
357 152           fill += padlen;
358              
359 152           bits_low = ctx->bytes_low << 3;
360 152           bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29);
361 152           u2s(bits_low, ctx->buffer + fill); fill += 4;
362 152           u2s(bits_high, ctx->buffer + fill); fill += 4;
363              
364 152           MD5Transform(ctx, ctx->buffer, fill >> 6);
365             #ifdef MD5_DEBUG
366             fprintf(stderr," Result: %s\n", ctx_dump(ctx));
367             #endif
368              
369 152           u2s(ctx->A, digest);
370 152           u2s(ctx->B, digest+4);
371 152           u2s(ctx->C, digest+8);
372 152           u2s(ctx->D, digest+12);
373 152           }
374             /*----------------------------------------------------------------*/
375              
376             static const char *hexdigits = "0123456789abcdef";
377              
378 152           static void hex_16(const unsigned char* from, char* to) {
379 152           const unsigned char *end = from + 16;
380 152           char *d = to;
381              
382 2584 100         while (from < end) {
383 2432           *d++ = hexdigits[(*from >> 4)];
384 2432           *d++ = hexdigits[(*from & 0x0F)];
385 2432           from++;
386             }
387 152           *d = '\0';
388 152           }
389              
390 152           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 152           uu_pack1(io, (U8*)&packed);
401              
402 152           MD5Init(&context);
403              
404 152           MD5Update(&context, (U8*)&packed, sizeof(packed));
405 152 50         if (name)
406 152           MD5Update(&context, (U8*)name, strlen(name));
407              
408 152           MD5Final((U8*)digeststr, &context);
409 152           digeststr[20] = '\0';
410              
411 152           hex_16(digeststr, tmp);
412 152           tmp[32] = '\0';
413              
414             /* hyphenate */
415 152           Move(&tmp[20], &tmp[21], 12, char); tmp[20] = '-';
416 152           Move(&tmp[16], &tmp[17], 17, char); tmp[16] = '-';
417 152           Move(&tmp[12], &tmp[13], 22, char); tmp[12] = '-';
418 152           Move(&tmp[ 8], &tmp[ 9], 27, char); tmp[ 8] = '-';
419 152           tmp[36] = '\0';
420              
421             /* version */
422 152           tmp[14] = '3';
423              
424             /* variant */
425 152           vardig = tmp[19] - 48;
426 152 100         if (vardig > 9) vardig -= 7;
427 152 100         if (vardig > 15) vardig -= 32;
428 152           vardig = vardig & 0x3 | 0x8;
429 152 100         if (vardig > 9) vardig += 87;
430 145           else vardig += 48;
431 152           tmp[19] = vardig;
432              
433 152           uu_parse(tmp, io);
434 152           }
435              
436             /* ex:set ts=2 sw=2 itab=spaces: */