File Coverage

MD5.xs
Criterion Covered Total %
statement 234 278 84.1
branch 57 128 44.5
condition n/a
subroutine n/a
pod n/a
total 291 406 71.6


line stmt bran cond sub pod time code
1             /*
2             * This library is free software; you can redistribute it and/or
3             * modify it under the same terms as Perl itself.
4             *
5             * Copyright 1998-2000 Gisle Aas.
6             * Copyright 1995-1996 Neil Winton.
7             * Copyright 1991-1992 RSA Data Security, Inc.
8             *
9             * This code is derived from Neil Winton's MD5-1.7 Perl module, which in
10             * turn is derived from the reference implementation in RFC 1321 which
11             * comes with this message:
12             *
13             * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
14             * rights reserved.
15             *
16             * License to copy and use this software is granted provided that it
17             * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
18             * Algorithm" in all material mentioning or referencing this software
19             * or this function.
20             *
21             * License is also granted to make and use derivative works provided
22             * that such works are identified as "derived from the RSA Data
23             * Security, Inc. MD5 Message-Digest Algorithm" in all material
24             * mentioning or referencing the derived work.
25             *
26             * RSA Data Security, Inc. makes no representations concerning either
27             * the merchantability of this software or the suitability of this
28             * software for any particular purpose. It is provided "as is"
29             * without express or implied warranty of any kind.
30             *
31             * These notices must be retained in any copies of any part of this
32             * documentation and/or software.
33             */
34              
35             #ifdef __cplusplus
36             extern "C" {
37             #endif
38             #define PERL_NO_GET_CONTEXT /* we want efficiency */
39             #include "EXTERN.h"
40             #include "perl.h"
41             #include "XSUB.h"
42             #ifdef __cplusplus
43             }
44             #endif
45              
46             #ifndef PERL_UNUSED_VAR
47             # define PERL_UNUSED_VAR(x) ((void)x)
48             #endif
49              
50             #ifndef PERL_MAGIC_ext
51             # define PERL_MAGIC_ext '~'
52             #endif
53              
54             #ifndef Newxz
55             # define Newxz(v,n,t) Newz(0,v,n,t)
56             #endif
57              
58             #ifndef SvMAGIC_set
59             # define SvMAGIC_set(sv, mg) (SvMAGIC(sv) = (mg))
60             #endif
61              
62             #ifndef sv_magicext
63             # define sv_magicext(sv, obj, type, vtbl, name, namlen) \
64             THX_sv_magicext(aTHX_ sv, obj, type, vtbl, name, namlen)
65             static MAGIC *THX_sv_magicext(pTHX_ SV *sv, SV *obj, int type,
66             MGVTBL const *vtbl, char const *name, I32 namlen)
67             {
68             MAGIC *mg;
69             if (obj || namlen)
70             /* exceeded intended usage of this reserve implementation */
71             return NULL;
72             Newxz(mg, 1, MAGIC);
73             mg->mg_virtual = (MGVTBL*)vtbl;
74             mg->mg_type = type;
75             mg->mg_ptr = (char *)name;
76             mg->mg_len = -1;
77             (void) SvUPGRADE(sv, SVt_PVMG);
78             mg->mg_moremagic = SvMAGIC(sv);
79             SvMAGIC_set(sv, mg);
80             SvMAGICAL_off(sv);
81             mg_magical(sv);
82             return mg;
83             }
84             #endif
85              
86             #if PERL_VERSION < 8
87             # undef SvPVbyte
88             # define SvPVbyte(sv, lp) (sv_utf8_downgrade((sv), 0), SvPV((sv), (lp)))
89             #endif
90              
91             /* Perl does not guarantee that U32 is exactly 32 bits. Some system
92             * has no integral type with exactly 32 bits. For instance, A Cray has
93             * short, int and long all at 64 bits so we need to apply this macro
94             * to reduce U32 values to 32 bits at appropriate places. If U32
95             * really does have 32 bits then this is a no-op.
96             */
97             #if BYTEORDER > 0x4321 || defined(TRUNCATE_U32)
98             #define TO32(x) ((x) & 0xFFFFffff)
99             #define TRUNC32(x) ((x) &= 0xFFFFffff)
100             #else
101             #define TO32(x) (x)
102             #define TRUNC32(x) /*nothing*/
103             #endif
104              
105             /* The MD5 algorithm is defined in terms of little endian 32-bit
106             * values. The following macros (and functions) allow us to convert
107             * between native integers and such values.
108             */
109             #undef BYTESWAP
110             #ifndef U32_ALIGNMENT_REQUIRED
111             #if BYTEORDER == 0x1234 /* 32-bit little endian */
112             #define BYTESWAP(x) (x) /* no-op */
113              
114             #elif BYTEORDER == 0x4321 /* 32-bit big endian */
115             #define BYTESWAP(x) ((((x)&0xFF)<<24) \
116             |(((x)>>24)&0xFF) \
117             |(((x)&0x0000FF00)<<8) \
118             |(((x)&0x00FF0000)>>8) )
119             #endif
120             #endif
121              
122             #ifndef BYTESWAP
123 8766           static void u2s(U32 u, U8* s)
124             {
125 8766           *s++ = (U8)(u & 0xFF);
126 8766           *s++ = (U8)((u >> 8) & 0xFF);
127 8766           *s++ = (U8)((u >> 16) & 0xFF);
128 8766           *s = (U8)((u >> 24) & 0xFF);
129 8766           }
130              
131             #define s2u(s,u) ((u) = (U32)(*s) | \
132             ((U32)(*(s+1)) << 8) | \
133             ((U32)(*(s+2)) << 16) | \
134             ((U32)(*(s+3)) << 24))
135             #endif
136              
137             /* This structure keeps the current state of algorithm.
138             */
139             typedef struct {
140             U32 A, B, C, D; /* current digest */
141             U32 bytes_low; /* counts bytes in message */
142             U32 bytes_high; /* turn it into a 64-bit counter */
143             U8 buffer[128]; /* collect complete 64 byte blocks */
144             } MD5_CTX;
145              
146             #if defined(USE_ITHREADS) && defined(MGf_DUP)
147             STATIC int dup_md5_ctx(pTHX_ MAGIC *mg, CLONE_PARAMS *params)
148             {
149             MD5_CTX *new_ctx;
150             PERL_UNUSED_VAR(params);
151             New(55, new_ctx, 1, MD5_CTX);
152             memcpy(new_ctx, mg->mg_ptr, sizeof(MD5_CTX));
153             mg->mg_ptr = (char *)new_ctx;
154             return 0;
155             }
156             #endif
157              
158             #if defined(MGf_DUP) && defined(USE_ITHREADS)
159             STATIC const MGVTBL vtbl_md5 = {
160             NULL, /* get */
161             NULL, /* set */
162             NULL, /* len */
163             NULL, /* clear */
164             NULL, /* free */
165             NULL, /* copy */
166             dup_md5_ctx, /* dup */
167             NULL /* local */
168             };
169             #else
170             /* declare as 5 member, not normal 8 to save image space*/
171             STATIC const struct {
172             int (*svt_get)(SV* sv, MAGIC* mg);
173             int (*svt_set)(SV* sv, MAGIC* mg);
174             U32 (*svt_len)(SV* sv, MAGIC* mg);
175             int (*svt_clear)(SV* sv, MAGIC* mg);
176             int (*svt_free)(SV* sv, MAGIC* mg);
177             } vtbl_md5 = {
178             NULL, NULL, NULL, NULL, NULL
179             };
180             #endif
181              
182              
183             /* Padding is added at the end of the message in order to fill a
184             * complete 64 byte block (- 8 bytes for the message length). The
185             * padding is also the reason the buffer in MD5_CTX have to be
186             * 128 bytes.
187             */
188             static const unsigned char PADDING[64] = {
189             0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
192             };
193              
194             /* Constants for MD5Transform routine.
195             */
196             #define S11 7
197             #define S12 12
198             #define S13 17
199             #define S14 22
200             #define S21 5
201             #define S22 9
202             #define S23 14
203             #define S24 20
204             #define S31 4
205             #define S32 11
206             #define S33 16
207             #define S34 23
208             #define S41 6
209             #define S42 10
210             #define S43 15
211             #define S44 21
212              
213             /* F, G, H and I are basic MD5 functions.
214             */
215             #define F(x, y, z) ((((x) & ((y) ^ (z))) ^ (z)))
216             #define G(x, y, z) F(z, x, y)
217             #define H(x, y, z) ((x) ^ (y) ^ (z))
218             #define I(x, y, z) ((y) ^ ((x) | (~z)))
219              
220             /* ROTATE_LEFT rotates x left n bits.
221             */
222             #define ROTATE_LEFT(x, n) (((x) << (n) | ((x) >> (32-(n)))))
223              
224             /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
225             * Rotation is separate from addition to prevent recomputation.
226             */
227             #define FF(a, b, c, d, s, ac) \
228             (a) += F ((b), (c), (d)) + (NEXTx) + (U32)(ac); \
229             TRUNC32((a)); \
230             (a) = ROTATE_LEFT ((a), (s)); \
231             (a) += (b); \
232             TRUNC32((a));
233              
234             #define GG(a, b, c, d, x, s, ac) \
235             (a) += G ((b), (c), (d)) + X[x] + (U32)(ac); \
236             TRUNC32((a)); \
237             (a) = ROTATE_LEFT ((a), (s)); \
238             (a) += (b); \
239             TRUNC32((a));
240              
241             #define HH(a, b, c, d, x, s, ac) \
242             (a) += H ((b), (c), (d)) + X[x] + (U32)(ac); \
243             TRUNC32((a)); \
244             (a) = ROTATE_LEFT ((a), (s)); \
245             (a) += (b); \
246             TRUNC32((a));
247              
248             #define II(a, b, c, d, x, s, ac) \
249             (a) += I ((b), (c), (d)) + X[x] + (U32)(ac); \
250             TRUNC32((a)); \
251             (a) = ROTATE_LEFT ((a), (s)); \
252             (a) += (b); \
253             TRUNC32((a));
254              
255              
256             static void
257 2636           MD5Init(MD5_CTX *ctx)
258             {
259             /* Start state */
260 2636           ctx->A = 0x67452301;
261 2636           ctx->B = 0xefcdab89;
262 2636           ctx->C = 0x98badcfe;
263 2636           ctx->D = 0x10325476;
264              
265             /* message length */
266 2636           ctx->bytes_low = ctx->bytes_high = 0;
267 2636           }
268              
269              
270             static void
271 8448           MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
272             {
273             #ifdef MD5_DEBUG
274             static int tcount = 0;
275             #endif
276              
277 8448           U32 A = ctx->A;
278 8448           U32 B = ctx->B;
279 8448           U32 C = ctx->C;
280 8448           U32 D = ctx->D;
281              
282             #ifndef U32_ALIGNMENT_REQUIRED
283             const U32 *x = (U32*)buf; /* really just type casting */
284             #endif
285              
286             do {
287 212974           U32 a = A;
288 212974           U32 b = B;
289 212974           U32 c = C;
290 212974           U32 d = D;
291              
292             #if BYTEORDER == 0x1234 && !defined(U32_ALIGNMENT_REQUIRED)
293             const U32 *X = x;
294             #define NEXTx (*x++)
295             #else
296             U32 X[16]; /* converted values, used in round 2-4 */
297 212974           U32 *uptr = X;
298             U32 tmp;
299             #ifdef BYTESWAP
300             #define NEXTx (tmp=*x++, *uptr++ = BYTESWAP(tmp))
301             #else
302             #define NEXTx (s2u(buf,tmp), buf += 4, *uptr++ = tmp)
303             #endif
304             #endif
305              
306             #ifdef MD5_DEBUG
307             if (buf == ctx->buffer)
308             fprintf(stderr,"%5d: Transform ctx->buffer", ++tcount);
309             else
310             fprintf(stderr,"%5d: Transform %p (%d)", ++tcount, buf, blocks);
311              
312             {
313             int i;
314             fprintf(stderr,"[");
315             for (i = 0; i < 16; i++) {
316             fprintf(stderr,"%x,", x[i]);
317             }
318             fprintf(stderr,"]\n");
319             }
320             #endif
321              
322             /* Round 1 */
323 212974           FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
324 212974           FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
325 212974           FF (c, d, a, b, S13, 0x242070db); /* 3 */
326 212974           FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
327 212974           FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
328 212974           FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
329 212974           FF (c, d, a, b, S13, 0xa8304613); /* 7 */
330 212974           FF (b, c, d, a, S14, 0xfd469501); /* 8 */
331 212974           FF (a, b, c, d, S11, 0x698098d8); /* 9 */
332 212974           FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
333 212974           FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
334 212974           FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
335 212974           FF (a, b, c, d, S11, 0x6b901122); /* 13 */
336 212974           FF (d, a, b, c, S12, 0xfd987193); /* 14 */
337 212974           FF (c, d, a, b, S13, 0xa679438e); /* 15 */
338 212974           FF (b, c, d, a, S14, 0x49b40821); /* 16 */
339              
340             /* Round 2 */
341 212974           GG (a, b, c, d, 1, S21, 0xf61e2562); /* 17 */
342 212974           GG (d, a, b, c, 6, S22, 0xc040b340); /* 18 */
343 212974           GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
344 212974           GG (b, c, d, a, 0, S24, 0xe9b6c7aa); /* 20 */
345 212974           GG (a, b, c, d, 5, S21, 0xd62f105d); /* 21 */
346 212974           GG (d, a, b, c, 10, S22, 0x2441453); /* 22 */
347 212974           GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
348 212974           GG (b, c, d, a, 4, S24, 0xe7d3fbc8); /* 24 */
349 212974           GG (a, b, c, d, 9, S21, 0x21e1cde6); /* 25 */
350 212974           GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
351 212974           GG (c, d, a, b, 3, S23, 0xf4d50d87); /* 27 */
352 212974           GG (b, c, d, a, 8, S24, 0x455a14ed); /* 28 */
353 212974           GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
354 212974           GG (d, a, b, c, 2, S22, 0xfcefa3f8); /* 30 */
355 212974           GG (c, d, a, b, 7, S23, 0x676f02d9); /* 31 */
356 212974           GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
357              
358             /* Round 3 */
359 212974           HH (a, b, c, d, 5, S31, 0xfffa3942); /* 33 */
360 212974           HH (d, a, b, c, 8, S32, 0x8771f681); /* 34 */
361 212974           HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
362 212974           HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
363 212974           HH (a, b, c, d, 1, S31, 0xa4beea44); /* 37 */
364 212974           HH (d, a, b, c, 4, S32, 0x4bdecfa9); /* 38 */
365 212974           HH (c, d, a, b, 7, S33, 0xf6bb4b60); /* 39 */
366 212974           HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
367 212974           HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
368 212974           HH (d, a, b, c, 0, S32, 0xeaa127fa); /* 42 */
369 212974           HH (c, d, a, b, 3, S33, 0xd4ef3085); /* 43 */
370 212974           HH (b, c, d, a, 6, S34, 0x4881d05); /* 44 */
371 212974           HH (a, b, c, d, 9, S31, 0xd9d4d039); /* 45 */
372 212974           HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
373 212974           HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
374 212974           HH (b, c, d, a, 2, S34, 0xc4ac5665); /* 48 */
375              
376             /* Round 4 */
377 212974           II (a, b, c, d, 0, S41, 0xf4292244); /* 49 */
378 212974           II (d, a, b, c, 7, S42, 0x432aff97); /* 50 */
379 212974           II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
380 212974           II (b, c, d, a, 5, S44, 0xfc93a039); /* 52 */
381 212974           II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
382 212974           II (d, a, b, c, 3, S42, 0x8f0ccc92); /* 54 */
383 212974           II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
384 212974           II (b, c, d, a, 1, S44, 0x85845dd1); /* 56 */
385 212974           II (a, b, c, d, 8, S41, 0x6fa87e4f); /* 57 */
386 212974           II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
387 212974           II (c, d, a, b, 6, S43, 0xa3014314); /* 59 */
388 212974           II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
389 212974           II (a, b, c, d, 4, S41, 0xf7537e82); /* 61 */
390 212974           II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
391 212974           II (c, d, a, b, 2, S43, 0x2ad7d2bb); /* 63 */
392 212974           II (b, c, d, a, 9, S44, 0xeb86d391); /* 64 */
393              
394 212974           A += a; TRUNC32(A);
395 212974           B += b; TRUNC32(B);
396 212974           C += c; TRUNC32(C);
397 212974           D += d; TRUNC32(D);
398              
399 212974 100         } while (--blocks);
400 8448           ctx->A = A;
401 8448           ctx->B = B;
402 8448           ctx->C = C;
403 8448           ctx->D = D;
404 8448           }
405              
406              
407             #ifdef MD5_DEBUG
408             static char*
409             ctx_dump(MD5_CTX* ctx)
410             {
411             static char buf[1024];
412             sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}",
413             ctx->A, ctx->B, ctx->C, ctx->D,
414             ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F));
415             return buf;
416             }
417             #endif
418              
419              
420             static void
421 211568           MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len)
422             {
423             STRLEN blocks;
424 211568           STRLEN fill = ctx->bytes_low & 0x3F;
425              
426             #ifdef MD5_DEBUG
427             static int ucount = 0;
428             fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx),
429             buf, len);
430             #endif
431              
432 211568           ctx->bytes_low += len;
433 211568 50         if (ctx->bytes_low < len) /* wrap around */
434 0           ctx->bytes_high++;
435              
436 211568 100         if (fill) {
437 204239           STRLEN missing = 64 - fill;
438 204239 100         if (len < missing) {
439 201124           Copy(buf, ctx->buffer + fill, len, U8);
440 201124           return;
441             }
442 3115           Copy(buf, ctx->buffer + fill, missing, U8);
443 3115           MD5Transform(ctx, ctx->buffer, 1);
444 3115           buf += missing;
445 3115           len -= missing;
446             }
447              
448 10444           blocks = len >> 6;
449 10444 100         if (blocks)
450 3872           MD5Transform(ctx, buf, blocks);
451 10444 100         if ( (len &= 0x3F)) {
452 4561           Copy(buf + (blocks << 6), ctx->buffer, len, U8);
453             }
454             }
455              
456              
457             static void
458 1461           MD5Final(U8* digest, MD5_CTX *ctx)
459             {
460 1461           STRLEN fill = ctx->bytes_low & 0x3F;
461 1461 100         STRLEN padlen = (fill < 56 ? 56 : 120) - fill;
462             U32 bits_low, bits_high;
463             #ifdef MD5_DEBUG
464             fprintf(stderr," Final: %s\n", ctx_dump(ctx));
465             #endif
466 1461           Copy(PADDING, ctx->buffer + fill, padlen, U8);
467 1461           fill += padlen;
468              
469 1461           bits_low = ctx->bytes_low << 3;
470 1461           bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29);
471             #ifdef BYTESWAP
472             *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_low); fill += 4;
473             *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_high); fill += 4;
474             #else
475 1461           u2s(bits_low, ctx->buffer + fill); fill += 4;
476 1461           u2s(bits_high, ctx->buffer + fill); fill += 4;
477             #endif
478              
479 1461           MD5Transform(ctx, ctx->buffer, fill >> 6);
480             #ifdef MD5_DEBUG
481             fprintf(stderr," Result: %s\n", ctx_dump(ctx));
482             #endif
483              
484             #ifdef BYTESWAP
485             *(U32*)digest = BYTESWAP(ctx->A); digest += 4;
486             *(U32*)digest = BYTESWAP(ctx->B); digest += 4;
487             *(U32*)digest = BYTESWAP(ctx->C); digest += 4;
488             *(U32*)digest = BYTESWAP(ctx->D);
489             #else
490 1461           u2s(ctx->A, digest);
491 1461           u2s(ctx->B, digest+4);
492 1461           u2s(ctx->C, digest+8);
493 1461           u2s(ctx->D, digest+12);
494             #endif
495 1461           }
496              
497             #ifndef INT2PTR
498             #define INT2PTR(any,d) (any)(d)
499             #endif
500              
501 61772           static MD5_CTX* get_md5_ctx(pTHX_ SV* sv)
502             {
503             MAGIC *mg;
504              
505 61772 50         if (!sv_derived_from(sv, "Digest::MD5"))
506 0           croak("Not a reference to a Digest::MD5 object");
507              
508 61772 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
509 61772 50         if (mg->mg_type == PERL_MAGIC_ext
510 61772 50         && mg->mg_virtual == (const MGVTBL * const)&vtbl_md5) {
511 61772           return (MD5_CTX *)mg->mg_ptr;
512             }
513             }
514              
515 0           croak("Failed to get MD5_CTX pointer");
516             return (MD5_CTX*)0; /* some compilers insist on a return value */
517             }
518              
519 1179           static SV * new_md5_ctx(pTHX_ MD5_CTX *context, const char *klass)
520             {
521 1179           SV *sv = newSV(0);
522 1179           SV *obj = newRV_noinc(sv);
523             #ifdef USE_ITHREADS
524             MAGIC *mg;
525             #endif
526              
527 1179           sv_bless(obj, gv_stashpv(klass, 0));
528              
529             #ifdef USE_ITHREADS
530             mg =
531             #endif
532 1179           sv_magicext(sv, NULL, PERL_MAGIC_ext, (const MGVTBL * const)&vtbl_md5, (const char *)context, 0);
533              
534             #if defined(USE_ITHREADS) && defined(MGf_DUP)
535             mg->mg_flags |= MGf_DUP;
536             #endif
537              
538 1179           return obj;
539             }
540              
541              
542 1178           static char* hex_16(const unsigned char* from, char* to)
543             {
544             static const char hexdigits[] = "0123456789abcdef";
545 1178           const unsigned char *end = from + 16;
546 1178           char *d = to;
547              
548 20026 100         while (from < end) {
549 18848           *d++ = hexdigits[(*from >> 4)];
550 18848           *d++ = hexdigits[(*from & 0x0F)];
551 18848           from++;
552             }
553 1178           *d = '\0';
554 1178           return to;
555             }
556              
557 9           static char* base64_16(const unsigned char* from, char* to)
558             {
559             static const char base64[] =
560             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
561 9           const unsigned char *end = from + 16;
562             unsigned char c1, c2, c3;
563 9           char *d = to;
564              
565             while (1) {
566 54           c1 = *from++;
567 54           *d++ = base64[c1>>2];
568 54 100         if (from == end) {
569 9           *d++ = base64[(c1 & 0x3) << 4];
570 9           break;
571             }
572 45           c2 = *from++;
573 45           c3 = *from++;
574 45           *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
575 45           *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
576 45           *d++ = base64[c3 & 0x3F];
577 45           }
578 9           *d = '\0';
579 9           return to;
580             }
581              
582             /* Formats */
583             #define F_BIN 0
584             #define F_HEX 1
585             #define F_B64 2
586              
587 1461           static SV* make_mortal_sv(pTHX_ const unsigned char *src, int type)
588             {
589             STRLEN len;
590             char result[33];
591             char *ret;
592            
593 1461           switch (type) {
594             case F_BIN:
595 274           ret = (char*)src;
596 274           len = 16;
597 274           break;
598             case F_HEX:
599 1178           ret = hex_16(src, result);
600 1178           len = 32;
601 1178           break;
602             case F_B64:
603 9           ret = base64_16(src, result);
604 9           len = 22;
605 9           break;
606             default:
607 0           croak("Bad conversion type (%d)", type);
608             break;
609             }
610 1461           return sv_2mortal(newSVpv(ret,len));
611             }
612              
613              
614             /********************************************************************/
615              
616             typedef PerlIO* InputStream;
617              
618             MODULE = Digest::MD5 PACKAGE = Digest::MD5
619              
620             PROTOTYPES: DISABLE
621              
622             void
623             new(xclass)
624             SV* xclass
625             PREINIT:
626             MD5_CTX* context;
627             PPCODE:
628 1174 50         if (!SvROK(xclass)) {
629             STRLEN my_na;
630 1174 50         const char *sclass = SvPV(xclass, my_na);
631 1174           New(55, context, 1, MD5_CTX);
632 1174           ST(0) = sv_2mortal(new_md5_ctx(aTHX_ context, sclass));
633             } else {
634 0           context = get_md5_ctx(aTHX_ xclass);
635             }
636 1174           MD5Init(context);
637 1174           XSRETURN(1);
638              
639             void
640             clone(self)
641             SV* self
642             PREINIT:
643 5           MD5_CTX* cont = get_md5_ctx(aTHX_ self);
644 5           const char *myname = sv_reftype(SvRV(self),TRUE);
645             MD5_CTX* context;
646             PPCODE:
647 5           New(55, context, 1, MD5_CTX);
648 5           ST(0) = sv_2mortal(new_md5_ctx(aTHX_ context, myname));
649 5           memcpy(context,cont,sizeof(MD5_CTX));
650 5           XSRETURN(1);
651              
652             void
653             DESTROY(context)
654             MD5_CTX* context
655             CODE:
656 1179           Safefree(context);
657              
658             void
659             add(self, ...)
660             SV* self
661             PREINIT:
662 58511           MD5_CTX* context = get_md5_ctx(aTHX_ self);
663             int i;
664             unsigned char *data;
665             STRLEN len;
666             PPCODE:
667 207895 100         for (i = 1; i < items; i++) {
668 149384           U32 had_utf8 = SvUTF8(ST(i));
669 149384 100         data = (unsigned char *)(SvPVbyte(ST(i), len));
670 149384           MD5Update(context, data, len);
671 149384 50         if (had_utf8) sv_utf8_upgrade(ST(i));
672             }
673 58511           XSRETURN(1); /* self */
674              
675             void
676             addfile(self, fh)
677             SV* self
678             InputStream fh
679             PREINIT:
680 900           MD5_CTX* context = get_md5_ctx(aTHX_ self);
681 900           STRLEN fill = context->bytes_low & 0x3F;
682             #ifdef USE_HEAP_INSTEAD_OF_STACK
683             unsigned char* buffer;
684             #else
685             unsigned char buffer[4096];
686             #endif
687             int n;
688             CODE:
689 900 100         if (fh) {
690             #ifdef USE_HEAP_INSTEAD_OF_STACK
691             New(0, buffer, 4096, unsigned char);
692             assert(buffer);
693             #endif
694 899 50         if (fill) {
695             /* The MD5Update() function is faster if it can work with
696             * complete blocks. This will fill up any buffered block
697             * first.
698             */
699 0           STRLEN missing = 64 - fill;
700 0 0         if ( (n = PerlIO_read(fh, buffer, missing)) > 0)
701 0           MD5Update(context, buffer, n);
702             else
703 0           XSRETURN(1); /* self */
704             }
705              
706             /* Process blocks until EOF or error */
707 4559 100         while ( (n = PerlIO_read(fh, buffer, sizeof(buffer))) > 0) {
708 3660           MD5Update(context, buffer, n);
709             }
710             #ifdef USE_HEAP_INSTEAD_OF_STACK
711             Safefree(buffer);
712             #endif
713 899 50         if (PerlIO_error(fh)) {
714 0           croak("Reading from filehandle failed");
715             }
716             }
717             else {
718 1           croak("No filehandle passed");
719             }
720 899           XSRETURN(1); /* self */
721              
722             void
723             digest(context)
724             MD5_CTX* context
725             ALIAS:
726             Digest::MD5::digest = F_BIN
727             Digest::MD5::hexdigest = F_HEX
728             Digest::MD5::b64digest = F_B64
729             PREINIT:
730             unsigned char digeststr[16];
731             PPCODE:
732 1177           MD5Final(digeststr, context);
733 1177           MD5Init(context); /* In case it is reused */
734 1177           ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
735 1177           XSRETURN(1);
736              
737             void
738             context(ctx, ...)
739             MD5_CTX* ctx
740             PREINIT:
741             char out[16];
742             U32 w;
743             PPCODE:
744 0 0         if (items > 2) {
745             STRLEN len;
746 0 0         unsigned long blocks = SvUV(ST(1));
747 0 0         unsigned char *buf = (unsigned char *)(SvPV(ST(2), len));
748 0           ctx->A = buf[ 0] | (buf[ 1]<<8) | (buf[ 2]<<16) | (buf[ 3]<<24);
749 0           ctx->B = buf[ 4] | (buf[ 5]<<8) | (buf[ 6]<<16) | (buf[ 7]<<24);
750 0           ctx->C = buf[ 8] | (buf[ 9]<<8) | (buf[10]<<16) | (buf[11]<<24);
751 0           ctx->D = buf[12] | (buf[13]<<8) | (buf[14]<<16) | (buf[15]<<24);
752 0           ctx->bytes_low = blocks << 6;
753 0           ctx->bytes_high = blocks >> 26;
754 0 0         if (items == 4) {
755 0 0         buf = (unsigned char *)(SvPV(ST(3), len));
756 0           MD5Update(ctx, buf, len);
757             }
758 0           XSRETURN(1); /* ctx */
759 0 0         } else if (items != 1) {
760 0           XSRETURN(0);
761             }
762              
763 0           w=ctx->A; out[ 0]=(char)w; out[ 1]=(char)(w>>8); out[ 2]=(char)(w>>16); out[ 3]=(char)(w>>24);
764 0           w=ctx->B; out[ 4]=(char)w; out[ 5]=(char)(w>>8); out[ 6]=(char)(w>>16); out[ 7]=(char)(w>>24);
765 0           w=ctx->C; out[ 8]=(char)w; out[ 9]=(char)(w>>8); out[10]=(char)(w>>16); out[11]=(char)(w>>24);
766 0           w=ctx->D; out[12]=(char)w; out[13]=(char)(w>>8); out[14]=(char)(w>>16); out[15]=(char)(w>>24);
767              
768 0 0         EXTEND(SP, 3);
769 0           ST(0) = sv_2mortal(newSVuv(ctx->bytes_high << 26 |
770             ctx->bytes_low >> 6));
771 0           ST(1) = sv_2mortal(newSVpv(out, 16));
772              
773 0 0         if ((ctx->bytes_low & 0x3F) == 0)
774 0           XSRETURN(2);
775              
776 0           ST(2) = sv_2mortal(newSVpv((char *)ctx->buffer,
777             ctx->bytes_low & 0x3F));
778 0           XSRETURN(3);
779              
780             void
781             md5(...)
782             ALIAS:
783             Digest::MD5::md5 = F_BIN
784             Digest::MD5::md5_hex = F_HEX
785             Digest::MD5::md5_base64 = F_B64
786             PREINIT:
787             MD5_CTX ctx;
788             int i;
789             unsigned char *data;
790             STRLEN len;
791             unsigned char digeststr[16];
792             PPCODE:
793 285           MD5Init(&ctx);
794              
795 285 100         if ((PL_dowarn & G_WARN_ON) || ckWARN(WARN_SYNTAX)) {
    100          
796 282           const char *msg = 0;
797 282 100         if (items == 1) {
798 275 50         if (SvROK(ST(0))) {
799 0           SV* sv = SvRV(ST(0));
800             char *name;
801 0 0         if (SvOBJECT(sv) && (name = HvNAME(SvSTASH(sv)))
    0          
    0          
    0          
    0          
    0          
    0          
    0          
802 0 0         && strEQ(name, "Digest::MD5"))
803 0           msg = "probably called as method";
804             else
805 275           msg = "called with reference argument";
806             }
807             }
808 7 50         else if (items > 1) {
809 7 50         data = (unsigned char *)SvPV(ST(0), len);
810 7 100         if (len == 11 && memEQ("Digest::MD5", data, 11)) {
    50          
811 3           msg = "probably called as class method";
812             }
813 4 50         else if (SvROK(ST(0))) {
814 0           SV* sv = SvRV(ST(0));
815             char *name;
816 0 0         if (SvOBJECT(sv) && (name = HvNAME(SvSTASH(sv)))
    0          
    0          
    0          
    0          
    0          
    0          
    0          
817 0 0         && strEQ(name, "Digest::MD5"))
818 0           msg = "probably called as method";
819             }
820             }
821 282 100         if (msg) {
822 3 50         const char *f = (ix == F_BIN) ? "md5" :
    50          
823             (ix == F_HEX) ? "md5_hex" : "md5_base64";
824 3           warn("&Digest::MD5::%s function %s", f, msg);
825             }
826             }
827              
828 58809 100         for (i = 0; i < items; i++) {
829 58525           U32 had_utf8 = SvUTF8(ST(i));
830 58525 100         data = (unsigned char *)(SvPVbyte(ST(i), len));
831 58524           MD5Update(&ctx, data, len);
832 58524 100         if (had_utf8) sv_utf8_upgrade(ST(i));
833             }
834 284           MD5Final(digeststr, &ctx);
835 284           ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
836 284           XSRETURN(1);