This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate Digest-1.00 and Digest-MD5-2.13, from Gisle Aas.
[perl5.git] / ext / Digest / MD5 / MD5.xs
1 /* $Id: MD5.xs,v 1.26 2000/09/18 14:27:44 gisle Exp $ */
2
3 /* 
4  * This library is free software; you can redistribute it and/or
5  * modify it under the same terms as Perl itself.
6  * 
7  *  Copyright 1998-2000 Gisle Aas.
8  *  Copyright 1995-1996 Neil Winton.
9  *  Copyright 1991-1992 RSA Data Security, Inc.
10  *
11  * This code is derived from Neil Winton's MD5-1.7 Perl module, which in
12  * turn is derived from the reference implementation in RFC 1231 which
13  * comes with this message:
14  *
15  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
16  * rights reserved.
17  *
18  * License to copy and use this software is granted provided that it
19  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
20  * Algorithm" in all material mentioning or referencing this software
21  * or this function.
22  *
23  * License is also granted to make and use derivative works provided
24  * that such works are identified as "derived from the RSA Data
25  * Security, Inc. MD5 Message-Digest Algorithm" in all material
26  * mentioning or referencing the derived work.
27  *
28  * RSA Data Security, Inc. makes no representations concerning either
29  * the merchantability of this software or the suitability of this
30  * software for any particular purpose. It is provided "as is"
31  * without express or implied warranty of any kind.
32  *
33  * These notices must be retained in any copies of any part of this
34  * documentation and/or software.
35  */
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 #include "EXTERN.h"
41 #include "perl.h"
42 #include "XSUB.h"
43 #ifdef __cplusplus
44 }
45 #endif
46
47 /*#define MD5_DEBUG /**/
48
49 /* Perl does not guarantee that U32 is exactly 32 bits.  Some system
50  * has no integral type with exactly 32 bits.  For instance, A Cray has
51  * short, int and long all at 64 bits so we need to apply this macro
52  * to reduce U32 values to 32 bits at appropriate places. If U32
53  * really does have 32 bits then this is a no-op.
54  */
55 #if BYTEORDER > 0x4321 || defined(TRUNCATE_U32)
56   #define TO32(x)    ((x) &  0xFFFFffff)
57   #define TRUNC32(x) ((x) &= 0xFFFFffff)
58 #else
59   #define TO32(x)    (x)
60   #define TRUNC32(x) /*nothing*/
61 #endif
62
63 /* The MD5 algorithm is defined in terms of little endian 32-bit
64  * values.  The following macros (and functions) allow us to convert
65  * between native integers and such values.
66  */
67 #undef BYTESWAP
68 #ifndef U32_ALIGNMENT_REQUIRED
69  #if BYTEORDER == 0x1234      /* 32-bit little endian */
70   #define BYTESWAP(x) (x)     /* no-op */
71
72  #elif BYTEORDER == 0x4321    /* 32-bit big endian */
73   #define BYTESWAP(x)   ((((x)&0xFF)<<24)       \
74                         |(((x)>>24)&0xFF)       \
75                         |(((x)&0x0000FF00)<<8)  \
76                         |(((x)&0x00FF0000)>>8)  )
77  #endif
78 #endif
79
80 #ifndef BYTESWAP
81 static void u2s(U32 u, U8* s)
82 {
83     *s++ = u         & 0xFF;
84     *s++ = (u >>  8) & 0xFF;
85     *s++ = (u >> 16) & 0xFF;
86     *s   = (u >> 24) & 0xFF;
87 }
88
89 #define s2u(s,u) ((u) =  (U32)(*s)            |  \
90                         ((U32)(*(s+1)) << 8)  |  \
91                         ((U32)(*(s+2)) << 16) |  \
92                         ((U32)(*(s+3)) << 24))
93 #endif
94
95 #define MD5_CTX_SIGNATURE 200003165
96
97 /* This stucture keeps the current state of algorithm.
98  */
99 typedef struct {
100   U32 signature;   /* safer cast in get_md5_ctx() */
101   U32 A, B, C, D;  /* current digest */
102   U32 bytes_low;   /* counts bytes in message */
103   U32 bytes_high;  /* turn it into a 64-bit counter */
104   U8 buffer[128];  /* collect complete 64 byte blocks */
105 } MD5_CTX;
106
107
108 /* Padding is added at the end of the message in order to fill a
109  * complete 64 byte block (- 8 bytes for the message length).  The
110  * padding is also the reason the buffer in MD5_CTX have to be
111  * 128 bytes.
112  */
113 static unsigned char PADDING[64] = {
114   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
117 };
118
119 /* Constants for MD5Transform routine.
120  */
121 #define S11 7
122 #define S12 12
123 #define S13 17
124 #define S14 22
125 #define S21 5
126 #define S22 9
127 #define S23 14
128 #define S24 20
129 #define S31 4
130 #define S32 11
131 #define S33 16
132 #define S34 23
133 #define S41 6
134 #define S42 10
135 #define S43 15
136 #define S44 21
137
138 /* F, G, H and I are basic MD5 functions.
139  */
140 #define F(x, y, z) (((x) & ((y) ^ (z)) ^ (z)))
141 #define G(x, y, z) F(z, x, y)
142 #define H(x, y, z) ((x) ^ (y) ^ (z))
143 #define I(x, y, z) ((y) ^ ((x) | (~z)))
144
145 /* ROTATE_LEFT rotates x left n bits.
146  */
147 #define ROTATE_LEFT(x, n) (((x) << (n) | ((x) >> (32-(n)))))
148
149 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
150  * Rotation is separate from addition to prevent recomputation.
151  */
152 #define FF(a, b, c, d, s, ac)                    \
153  (a) += F ((b), (c), (d)) + (NEXTx) + (U32)(ac); \
154  TRUNC32((a));                                   \
155  (a) = ROTATE_LEFT ((a), (s));                   \
156  (a) += (b);                                     \
157  TRUNC32((a));
158
159 #define GG(a, b, c, d, x, s, ac)                 \
160  (a) += G ((b), (c), (d)) + X[x] + (U32)(ac);    \
161  TRUNC32((a));                                   \
162  (a) = ROTATE_LEFT ((a), (s));                   \
163  (a) += (b);                                     \
164  TRUNC32((a));
165
166 #define HH(a, b, c, d, x, s, ac)                 \
167  (a) += H ((b), (c), (d)) + X[x] + (U32)(ac);    \
168  TRUNC32((a));                                   \
169  (a) = ROTATE_LEFT ((a), (s));                   \
170  (a) += (b);                                     \
171  TRUNC32((a));
172
173 #define II(a, b, c, d, x, s, ac)                 \
174  (a) += I ((b), (c), (d)) + X[x] + (U32)(ac);    \
175  TRUNC32((a));                                   \
176  (a) = ROTATE_LEFT ((a), (s));                   \
177  (a) += (b);                                     \
178  TRUNC32((a));
179
180
181 static void
182 MD5Init(MD5_CTX *ctx)
183 {
184   /* Start state */
185   ctx->A = 0x67452301;
186   ctx->B = 0xefcdab89;
187   ctx->C = 0x98badcfe;
188   ctx->D = 0x10325476;
189
190   /* message length */
191   ctx->bytes_low = ctx->bytes_high = 0;
192 }
193
194
195 static void
196 MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
197 {
198     static int tcount = 0;
199
200     U32 A = ctx->A;
201     U32 B = ctx->B;
202     U32 C = ctx->C;
203     U32 D = ctx->D;
204
205 #ifndef U32_ALIGNMENT_REQUIRED
206     const U32 *x = (U32*)buf;  /* really just type casting */
207 #endif
208
209     do {
210         U32 a = A;
211         U32 b = B;
212         U32 c = C;
213         U32 d = D;
214
215 #if BYTEORDER == 0x1234 && !defined(U32_ALIGNMENT_REQUIRED)
216         const U32 *X = x;
217         #define NEXTx  (*x++)
218 #else
219         U32 X[16];      /* converted values, used in round 2-4 */
220         U32 *uptr = X;
221         U32 tmp;
222  #ifdef BYTESWAP
223         #define NEXTx  (tmp=*x++, *uptr++ = BYTESWAP(tmp))
224  #else
225         #define NEXTx  (s2u(buf,tmp), buf += 4, *uptr++ = tmp)
226  #endif
227 #endif
228
229 #ifdef MD5_DEBUG
230         if (buf == ctx->buffer)
231             fprintf(stderr,"%5d: Transform ctx->buffer", ++tcount);
232         else 
233             fprintf(stderr,"%5d: Transform %p (%d)", ++tcount, buf, blocks);
234
235         {
236             int i;
237             fprintf(stderr,"[");
238             for (i = 0; i < 16; i++) {
239                 fprintf(stderr,"%x,", x[i]);
240             }
241             fprintf(stderr,"]\n");
242         }
243 #endif
244
245         /* Round 1 */
246         FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
247         FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
248         FF (c, d, a, b, S13, 0x242070db); /* 3 */
249         FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
250         FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
251         FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
252         FF (c, d, a, b, S13, 0xa8304613); /* 7 */
253         FF (b, c, d, a, S14, 0xfd469501); /* 8 */
254         FF (a, b, c, d, S11, 0x698098d8); /* 9 */
255         FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
256         FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
257         FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
258         FF (a, b, c, d, S11, 0x6b901122); /* 13 */
259         FF (d, a, b, c, S12, 0xfd987193); /* 14 */
260         FF (c, d, a, b, S13, 0xa679438e); /* 15 */
261         FF (b, c, d, a, S14, 0x49b40821); /* 16 */
262
263         /* Round 2 */
264         GG (a, b, c, d,  1, S21, 0xf61e2562); /* 17 */
265         GG (d, a, b, c,  6, S22, 0xc040b340); /* 18 */
266         GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
267         GG (b, c, d, a,  0, S24, 0xe9b6c7aa); /* 20 */
268         GG (a, b, c, d,  5, S21, 0xd62f105d); /* 21 */
269         GG (d, a, b, c, 10, S22,  0x2441453); /* 22 */
270         GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
271         GG (b, c, d, a,  4, S24, 0xe7d3fbc8); /* 24 */
272         GG (a, b, c, d,  9, S21, 0x21e1cde6); /* 25 */
273         GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
274         GG (c, d, a, b,  3, S23, 0xf4d50d87); /* 27 */
275         GG (b, c, d, a,  8, S24, 0x455a14ed); /* 28 */
276         GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
277         GG (d, a, b, c,  2, S22, 0xfcefa3f8); /* 30 */
278         GG (c, d, a, b,  7, S23, 0x676f02d9); /* 31 */
279         GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
280
281         /* Round 3 */
282         HH (a, b, c, d,  5, S31, 0xfffa3942); /* 33 */
283         HH (d, a, b, c,  8, S32, 0x8771f681); /* 34 */
284         HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
285         HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
286         HH (a, b, c, d,  1, S31, 0xa4beea44); /* 37 */
287         HH (d, a, b, c,  4, S32, 0x4bdecfa9); /* 38 */
288         HH (c, d, a, b,  7, S33, 0xf6bb4b60); /* 39 */
289         HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
290         HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
291         HH (d, a, b, c,  0, S32, 0xeaa127fa); /* 42 */
292         HH (c, d, a, b,  3, S33, 0xd4ef3085); /* 43 */
293         HH (b, c, d, a,  6, S34,  0x4881d05); /* 44 */
294         HH (a, b, c, d,  9, S31, 0xd9d4d039); /* 45 */
295         HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
296         HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
297         HH (b, c, d, a,  2, S34, 0xc4ac5665); /* 48 */
298
299         /* Round 4 */
300         II (a, b, c, d,  0, S41, 0xf4292244); /* 49 */
301         II (d, a, b, c,  7, S42, 0x432aff97); /* 50 */
302         II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
303         II (b, c, d, a,  5, S44, 0xfc93a039); /* 52 */
304         II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
305         II (d, a, b, c,  3, S42, 0x8f0ccc92); /* 54 */
306         II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
307         II (b, c, d, a,  1, S44, 0x85845dd1); /* 56 */
308         II (a, b, c, d,  8, S41, 0x6fa87e4f); /* 57 */
309         II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
310         II (c, d, a, b,  6, S43, 0xa3014314); /* 59 */
311         II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
312         II (a, b, c, d,  4, S41, 0xf7537e82); /* 61 */
313         II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
314         II (c, d, a, b,  2, S43, 0x2ad7d2bb); /* 63 */
315         II (b, c, d, a,  9, S44, 0xeb86d391); /* 64 */
316
317         A += a;  TRUNC32(A);
318         B += b;  TRUNC32(B);
319         C += c;  TRUNC32(C);
320         D += d;  TRUNC32(D);
321
322     } while (--blocks);
323     ctx->A = A;
324     ctx->B = B;
325     ctx->C = C;
326     ctx->D = D;
327 }
328
329
330 #ifdef MD5_DEBUG
331 static char*
332 ctx_dump(MD5_CTX* ctx)
333 {
334     static char buf[1024];
335     sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}",
336             ctx->A, ctx->B, ctx->C, ctx->D,
337             ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F));
338     return buf;
339 }
340 #endif
341
342
343 static void
344 MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len)
345 {
346     STRLEN blocks;
347     STRLEN fill = ctx->bytes_low & 0x3F;
348
349 #ifdef MD5_DEBUG  
350     static int ucount = 0;
351     fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx),
352                                                 buf, len);
353 #endif
354
355     ctx->bytes_low += len;
356     if (ctx->bytes_low < len) /* wrap around */
357         ctx->bytes_high++;
358
359     if (fill) {
360         STRLEN missing = 64 - fill;
361         if (len < missing) {
362             Copy(buf, ctx->buffer + fill, len, U8);
363             return;
364         }
365         Copy(buf, ctx->buffer + fill, missing, U8);
366         MD5Transform(ctx, ctx->buffer, 1);
367         buf += missing;
368         len -= missing;
369     }
370
371     blocks = len >> 6;
372     if (blocks)
373         MD5Transform(ctx, buf, blocks);
374     if ( (len &= 0x3F)) {
375         Copy(buf + (blocks << 6), ctx->buffer, len, U8);
376     }
377 }
378
379
380 static void
381 MD5Final(U8* digest, MD5_CTX *ctx)
382 {
383     STRLEN fill = ctx->bytes_low & 0x3F;
384     STRLEN padlen = (fill < 56 ? 56 : 120) - fill;
385     U32 bits_low, bits_high;
386 #ifdef MD5_DEBUG
387     fprintf(stderr,"       Final:  %s\n", ctx_dump(ctx));
388 #endif
389     Copy(PADDING, ctx->buffer + fill, padlen, U8);
390     fill += padlen;
391
392     bits_low = ctx->bytes_low << 3;
393     bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low  >> 29);
394 #ifdef BYTESWAP
395     *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_low);    fill += 4;
396     *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_high);   fill += 4;
397 #else
398     u2s(bits_low,  ctx->buffer + fill);   fill += 4;
399     u2s(bits_high, ctx->buffer + fill);   fill += 4;
400 #endif
401
402     MD5Transform(ctx, ctx->buffer, fill >> 6);
403 #ifdef MD5_DEBUG
404     fprintf(stderr,"       Result: %s\n", ctx_dump(ctx));
405 #endif
406
407 #ifdef BYTESWAP
408     *(U32*)digest = BYTESWAP(ctx->A);  digest += 4;
409     *(U32*)digest = BYTESWAP(ctx->B);  digest += 4;
410     *(U32*)digest = BYTESWAP(ctx->C);  digest += 4;
411     *(U32*)digest = BYTESWAP(ctx->D);
412 #else
413     u2s(ctx->A, digest);
414     u2s(ctx->B, digest+4);
415     u2s(ctx->C, digest+8);
416     u2s(ctx->D, digest+12);
417 #endif
418 }
419
420 #ifndef INT2PTR
421 #define INT2PTR(any,d)  (any)(d)
422 #endif
423
424 static MD5_CTX* get_md5_ctx(SV* sv)
425 {
426     if (SvROK(sv)) {
427         sv = SvRV(sv);
428         if (SvIOK(sv)) {
429             MD5_CTX* ctx = INT2PTR(MD5_CTX*, SvIV(sv));
430             if (ctx && ctx->signature == MD5_CTX_SIGNATURE) {
431                 return ctx;
432             }
433         }
434     }
435     croak("Not a reference to a Digest::MD5 object");
436     return (MD5_CTX*)0; /* some compilers insist on a return value */
437 }
438
439
440 static char* hex_16(const unsigned char* from, char* to)
441 {
442     static char *hexdigits = "0123456789abcdef";
443     const unsigned char *end = from + 16;
444     char *d = to;
445
446     while (from < end) {
447         *d++ = hexdigits[(*from >> 4)];
448         *d++ = hexdigits[(*from & 0x0F)];
449         from++;
450     }
451     *d = '\0';
452     return to;
453 }
454
455 static char* base64_16(const unsigned char* from, char* to)
456 {
457     static char* base64 =
458         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
459     const unsigned char *end = from + 16;
460     unsigned char c1, c2, c3;
461     char *d = to;
462
463     while (1) {
464         c1 = *from++;
465         *d++ = base64[c1>>2];
466         if (from == end) {
467             *d++ = base64[(c1 & 0x3) << 4];
468             break;
469         }
470         c2 = *from++;
471         c3 = *from++;
472         *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
473         *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
474         *d++ = base64[c3 & 0x3F];
475     }
476     *d = '\0';
477     return to;
478 }
479
480 /* Formats */
481 #define F_BIN 0
482 #define F_HEX 1
483 #define F_B64 2
484
485 static SV* make_mortal_sv(const unsigned char *src, int type)
486 {
487     STRLEN len;
488     char result[33];
489     char *ret;
490     
491     switch (type) {
492     case F_BIN:
493         ret = (char*)src;
494         len = 16;
495         break;
496     case F_HEX:
497         ret = hex_16(src, result);
498         len = 32;
499         break;
500     case F_B64:
501         ret = base64_16(src, result);
502         len = 22;
503         break;
504     default:
505         croak("Bad convertion type (%d)", type);
506         break;
507     }
508     return sv_2mortal(newSVpv(ret,len));
509 }
510
511
512 /********************************************************************/
513
514 typedef PerlIO* InputStream;
515
516 MODULE = Digest::MD5            PACKAGE = Digest::MD5
517
518 PROTOTYPES: DISABLE
519
520 void
521 new(xclass)
522         SV* xclass
523     PREINIT:
524         MD5_CTX* context;
525     PPCODE:
526         if (!SvROK(xclass)) {
527             STRLEN my_na;
528             char *sclass = SvPV(xclass, my_na);
529             New(55, context, 1, MD5_CTX);
530             context->signature = MD5_CTX_SIGNATURE;
531             ST(0) = sv_newmortal();
532             sv_setref_pv(ST(0), sclass, (void*)context);
533             SvREADONLY_on(SvRV(ST(0)));
534         } else {
535             context = get_md5_ctx(xclass);
536         }
537         MD5Init(context);
538         XSRETURN(1);
539
540 void
541 DESTROY(context)
542         MD5_CTX* context
543     CODE:
544         Safefree(context);
545
546 void
547 add(self, ...)
548         SV* self
549     PREINIT:
550         MD5_CTX* context = get_md5_ctx(self);
551         int i;
552         unsigned char *data;
553         STRLEN len;
554     PPCODE:
555         for (i = 1; i < items; i++) {
556             data = (unsigned char *)(SvPV(ST(i), len));
557             MD5Update(context, data, len);
558         }
559         XSRETURN(1);  /* self */
560
561 void
562 addfile(self, fh)
563         SV* self
564         InputStream fh
565     PREINIT:
566         MD5_CTX* context = get_md5_ctx(self);
567         STRLEN fill = context->bytes_low & 0x3F;
568         unsigned char buffer[4096];
569         int  n;
570     CODE:
571         if (fh) {
572             if (fill) {
573                 /* The MD5Update() function is faster if it can work with
574                  * complete blocks.  This will fill up any buffered block
575                  * first.
576                  */
577                 STRLEN missing = 64 - fill;
578                 if ( (n = PerlIO_read(fh, buffer, missing)))
579                     MD5Update(context, buffer, n);
580                 else
581                     XSRETURN(1);  /* self */
582             }
583
584             /* Process blocks until EOF */
585             while ( (n = PerlIO_read(fh, buffer, sizeof(buffer)))) {
586                 MD5Update(context, buffer, n);
587             }
588         }
589         XSRETURN(1);  /* self */
590
591 void
592 digest(context)
593         MD5_CTX* context
594     ALIAS:
595         Digest::MD5::digest    = F_BIN
596         Digest::MD5::hexdigest = F_HEX
597         Digest::MD5::b64digest = F_B64
598     PREINIT:
599         unsigned char digeststr[16];
600     PPCODE:
601         MD5Final(digeststr, context);
602         MD5Init(context);  /* In case it is reused */
603         ST(0) = make_mortal_sv(digeststr, ix);
604         XSRETURN(1);
605
606 void
607 md5(...)
608     ALIAS:
609         Digest::MD5::md5        = F_BIN
610         Digest::MD5::md5_hex    = F_HEX
611         Digest::MD5::md5_base64 = F_B64
612     PREINIT:
613         MD5_CTX ctx;
614         int i;
615         unsigned char *data;
616         STRLEN len;
617         unsigned char digeststr[16];
618     PPCODE:
619         MD5Init(&ctx);
620         for (i = 0; i < items; i++) {
621             data = (unsigned char *)(SvPV(ST(i), len));
622             MD5Update(&ctx, data, len);
623         }
624         MD5Final(digeststr, &ctx);
625         ST(0) = make_mortal_sv(digeststr, ix);
626         XSRETURN(1);