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