This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
locale.c: savepv() of getenv()
[perl5.git] / cpan / Digest-MD5 / MD5.xs
CommitLineData
3357b1b1
JH
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
6fb32e20 10 * turn is derived from the reference implementation in RFC 1321 which
3357b1b1
JH
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
36extern "C" {
37#endif
ee7ea0b1 38#define PERL_NO_GET_CONTEXT /* we want efficiency */
3357b1b1
JH
39#include "EXTERN.h"
40#include "perl.h"
41#include "XSUB.h"
42#ifdef __cplusplus
43}
44#endif
45
0a3486ef
CBW
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)
65static 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
3357b1b1
JH
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
123static void u2s(U32 u, U8* s)
124{
7c436af3
GS
125 *s++ = (U8)(u & 0xFF);
126 *s++ = (U8)((u >> 8) & 0xFF);
127 *s++ = (U8)((u >> 16) & 0xFF);
128 *s = (U8)((u >> 24) & 0xFF);
3357b1b1
JH
129}
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
0a3486ef 137/* This structure keeps the current state of algorithm.
3357b1b1
JH
138 */
139typedef struct {
3357b1b1
JH
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
0a3486ef 146#if defined(USE_ITHREADS) && defined(MGf_DUP)
62d37bf0
FR
147STATIC 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
38054f44
CBW
158#if defined(MGf_DUP) && defined(USE_ITHREADS)
159const STATIC MGVTBL vtbl_md5 = {
62d37bf0
FR
160 NULL, /* get */
161 NULL, /* set */
162 NULL, /* len */
163 NULL, /* clear */
164 NULL, /* free */
62d37bf0 165 NULL, /* copy */
38054f44 166 dup_md5_ctx, /* dup */
62d37bf0 167 NULL /* local */
62d37bf0 168};
38054f44
CBW
169#else
170/* declare as 5 member, not normal 8 to save image space*/
171const STATIC 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
62d37bf0 181
3357b1b1
JH
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 */
27da23d5 188static const unsigned char PADDING[64] = {
3357b1b1
JH
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 */
124f80e2 215#define F(x, y, z) ((((x) & ((y) ^ (z))) ^ (z)))
3357b1b1
JH
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
256static void
257MD5Init(MD5_CTX *ctx)
258{
259 /* Start state */
260 ctx->A = 0x67452301;
261 ctx->B = 0xefcdab89;
262 ctx->C = 0x98badcfe;
263 ctx->D = 0x10325476;
264
265 /* message length */
266 ctx->bytes_low = ctx->bytes_high = 0;
267}
268
269
270static void
271MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
272{
516a5887 273#ifdef MD5_DEBUG
3357b1b1 274 static int tcount = 0;
516a5887 275#endif
3357b1b1
JH
276
277 U32 A = ctx->A;
278 U32 B = ctx->B;
279 U32 C = ctx->C;
280 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 U32 a = A;
288 U32 b = B;
289 U32 c = C;
290 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 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 FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
324 FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
325 FF (c, d, a, b, S13, 0x242070db); /* 3 */
326 FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
327 FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
328 FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
329 FF (c, d, a, b, S13, 0xa8304613); /* 7 */
330 FF (b, c, d, a, S14, 0xfd469501); /* 8 */
331 FF (a, b, c, d, S11, 0x698098d8); /* 9 */
332 FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
333 FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
334 FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
335 FF (a, b, c, d, S11, 0x6b901122); /* 13 */
336 FF (d, a, b, c, S12, 0xfd987193); /* 14 */
337 FF (c, d, a, b, S13, 0xa679438e); /* 15 */
338 FF (b, c, d, a, S14, 0x49b40821); /* 16 */
339
340 /* Round 2 */
341 GG (a, b, c, d, 1, S21, 0xf61e2562); /* 17 */
342 GG (d, a, b, c, 6, S22, 0xc040b340); /* 18 */
343 GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
344 GG (b, c, d, a, 0, S24, 0xe9b6c7aa); /* 20 */
345 GG (a, b, c, d, 5, S21, 0xd62f105d); /* 21 */
346 GG (d, a, b, c, 10, S22, 0x2441453); /* 22 */
347 GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
348 GG (b, c, d, a, 4, S24, 0xe7d3fbc8); /* 24 */
349 GG (a, b, c, d, 9, S21, 0x21e1cde6); /* 25 */
350 GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
351 GG (c, d, a, b, 3, S23, 0xf4d50d87); /* 27 */
352 GG (b, c, d, a, 8, S24, 0x455a14ed); /* 28 */
353 GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
354 GG (d, a, b, c, 2, S22, 0xfcefa3f8); /* 30 */
355 GG (c, d, a, b, 7, S23, 0x676f02d9); /* 31 */
356 GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
357
358 /* Round 3 */
359 HH (a, b, c, d, 5, S31, 0xfffa3942); /* 33 */
360 HH (d, a, b, c, 8, S32, 0x8771f681); /* 34 */
361 HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
362 HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
363 HH (a, b, c, d, 1, S31, 0xa4beea44); /* 37 */
364 HH (d, a, b, c, 4, S32, 0x4bdecfa9); /* 38 */
365 HH (c, d, a, b, 7, S33, 0xf6bb4b60); /* 39 */
366 HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
367 HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
368 HH (d, a, b, c, 0, S32, 0xeaa127fa); /* 42 */
369 HH (c, d, a, b, 3, S33, 0xd4ef3085); /* 43 */
370 HH (b, c, d, a, 6, S34, 0x4881d05); /* 44 */
371 HH (a, b, c, d, 9, S31, 0xd9d4d039); /* 45 */
372 HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
373 HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
374 HH (b, c, d, a, 2, S34, 0xc4ac5665); /* 48 */
375
376 /* Round 4 */
377 II (a, b, c, d, 0, S41, 0xf4292244); /* 49 */
378 II (d, a, b, c, 7, S42, 0x432aff97); /* 50 */
379 II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
380 II (b, c, d, a, 5, S44, 0xfc93a039); /* 52 */
381 II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
382 II (d, a, b, c, 3, S42, 0x8f0ccc92); /* 54 */
383 II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
384 II (b, c, d, a, 1, S44, 0x85845dd1); /* 56 */
385 II (a, b, c, d, 8, S41, 0x6fa87e4f); /* 57 */
386 II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
387 II (c, d, a, b, 6, S43, 0xa3014314); /* 59 */
388 II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
389 II (a, b, c, d, 4, S41, 0xf7537e82); /* 61 */
390 II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
391 II (c, d, a, b, 2, S43, 0x2ad7d2bb); /* 63 */
392 II (b, c, d, a, 9, S44, 0xeb86d391); /* 64 */
393
394 A += a; TRUNC32(A);
395 B += b; TRUNC32(B);
396 C += c; TRUNC32(C);
397 D += d; TRUNC32(D);
398
399 } while (--blocks);
400 ctx->A = A;
401 ctx->B = B;
402 ctx->C = C;
403 ctx->D = D;
404}
405
406
407#ifdef MD5_DEBUG
408static char*
409ctx_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
420static void
421MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len)
422{
423 STRLEN blocks;
424 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 ctx->bytes_low += len;
433 if (ctx->bytes_low < len) /* wrap around */
434 ctx->bytes_high++;
435
436 if (fill) {
437 STRLEN missing = 64 - fill;
438 if (len < missing) {
439 Copy(buf, ctx->buffer + fill, len, U8);
440 return;
441 }
442 Copy(buf, ctx->buffer + fill, missing, U8);
443 MD5Transform(ctx, ctx->buffer, 1);
444 buf += missing;
445 len -= missing;
446 }
447
448 blocks = len >> 6;
449 if (blocks)
450 MD5Transform(ctx, buf, blocks);
451 if ( (len &= 0x3F)) {
452 Copy(buf + (blocks << 6), ctx->buffer, len, U8);
453 }
454}
455
456
457static void
458MD5Final(U8* digest, MD5_CTX *ctx)
459{
460 STRLEN fill = ctx->bytes_low & 0x3F;
461 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 Copy(PADDING, ctx->buffer + fill, padlen, U8);
467 fill += padlen;
468
469 bits_low = ctx->bytes_low << 3;
470 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 u2s(bits_low, ctx->buffer + fill); fill += 4;
476 u2s(bits_high, ctx->buffer + fill); fill += 4;
477#endif
478
479 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 u2s(ctx->A, digest);
491 u2s(ctx->B, digest+4);
492 u2s(ctx->C, digest+8);
493 u2s(ctx->D, digest+12);
494#endif
495}
496
497#ifndef INT2PTR
498#define INT2PTR(any,d) (any)(d)
499#endif
500
ee7ea0b1 501static MD5_CTX* get_md5_ctx(pTHX_ SV* sv)
3357b1b1 502{
62d37bf0
FR
503 MAGIC *mg;
504
505 if (!sv_derived_from(sv, "Digest::MD5"))
506 croak("Not a reference to a Digest::MD5 object");
507
508 for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
38054f44
CBW
509 if (mg->mg_type == PERL_MAGIC_ext
510 && mg->mg_virtual == (const MGVTBL * const)&vtbl_md5) {
62d37bf0
FR
511 return (MD5_CTX *)mg->mg_ptr;
512 }
3357b1b1 513 }
62d37bf0
FR
514
515 croak("Failed to get MD5_CTX pointer");
3357b1b1
JH
516 return (MD5_CTX*)0; /* some compilers insist on a return value */
517}
518
62d37bf0
FR
519static SV * new_md5_ctx(pTHX_ MD5_CTX *context, const char *klass)
520{
521 SV *sv = newSV(0);
522 SV *obj = newRV_noinc(sv);
523#ifdef USE_ITHREADS
524 MAGIC *mg;
525#endif
526
527 sv_bless(obj, gv_stashpv(klass, 0));
528
529#ifdef USE_ITHREADS
530 mg =
531#endif
38054f44 532 sv_magicext(sv, NULL, PERL_MAGIC_ext, (const MGVTBL * const)&vtbl_md5, (const char *)context, 0);
62d37bf0 533
0a3486ef 534#if defined(USE_ITHREADS) && defined(MGf_DUP)
62d37bf0
FR
535 mg->mg_flags |= MGf_DUP;
536#endif
537
538 return obj;
539}
540
3357b1b1
JH
541
542static char* hex_16(const unsigned char* from, char* to)
543{
27da23d5 544 static const char hexdigits[] = "0123456789abcdef";
3357b1b1
JH
545 const unsigned char *end = from + 16;
546 char *d = to;
547
548 while (from < end) {
549 *d++ = hexdigits[(*from >> 4)];
550 *d++ = hexdigits[(*from & 0x0F)];
551 from++;
552 }
553 *d = '\0';
554 return to;
555}
556
557static char* base64_16(const unsigned char* from, char* to)
558{
27da23d5 559 static const char base64[] =
3357b1b1
JH
560 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
561 const unsigned char *end = from + 16;
562 unsigned char c1, c2, c3;
563 char *d = to;
564
565 while (1) {
566 c1 = *from++;
567 *d++ = base64[c1>>2];
568 if (from == end) {
569 *d++ = base64[(c1 & 0x3) << 4];
570 break;
571 }
572 c2 = *from++;
573 c3 = *from++;
574 *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
575 *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
576 *d++ = base64[c3 & 0x3F];
577 }
578 *d = '\0';
579 return to;
580}
581
582/* Formats */
583#define F_BIN 0
584#define F_HEX 1
585#define F_B64 2
586
ee7ea0b1 587static SV* make_mortal_sv(pTHX_ const unsigned char *src, int type)
3357b1b1
JH
588{
589 STRLEN len;
590 char result[33];
591 char *ret;
592
593 switch (type) {
594 case F_BIN:
595 ret = (char*)src;
596 len = 16;
597 break;
598 case F_HEX:
599 ret = hex_16(src, result);
600 len = 32;
601 break;
602 case F_B64:
603 ret = base64_16(src, result);
604 len = 22;
605 break;
606 default:
0a3486ef 607 croak("Bad conversion type (%d)", type);
3357b1b1
JH
608 break;
609 }
610 return sv_2mortal(newSVpv(ret,len));
611}
612
613
614/********************************************************************/
615
616typedef PerlIO* InputStream;
617
618MODULE = Digest::MD5 PACKAGE = Digest::MD5
619
620PROTOTYPES: DISABLE
621
622void
623new(xclass)
624 SV* xclass
625 PREINIT:
626 MD5_CTX* context;
627 PPCODE:
628 if (!SvROK(xclass)) {
629 STRLEN my_na;
62d37bf0 630 const char *sclass = SvPV(xclass, my_na);
3357b1b1 631 New(55, context, 1, MD5_CTX);
62d37bf0 632 ST(0) = sv_2mortal(new_md5_ctx(aTHX_ context, sclass));
3357b1b1 633 } else {
ee7ea0b1 634 context = get_md5_ctx(aTHX_ xclass);
3357b1b1 635 }
62d37bf0 636 MD5Init(context);
3357b1b1
JH
637 XSRETURN(1);
638
639void
f62a1bde
JH
640clone(self)
641 SV* self
642 PREINIT:
ee7ea0b1 643 MD5_CTX* cont = get_md5_ctx(aTHX_ self);
b277e9c1 644 const char *myname = sv_reftype(SvRV(self),TRUE);
f62a1bde
JH
645 MD5_CTX* context;
646 PPCODE:
f62a1bde 647 New(55, context, 1, MD5_CTX);
62d37bf0 648 ST(0) = sv_2mortal(new_md5_ctx(aTHX_ context, myname));
f62a1bde
JH
649 memcpy(context,cont,sizeof(MD5_CTX));
650 XSRETURN(1);
651
652void
3357b1b1
JH
653DESTROY(context)
654 MD5_CTX* context
655 CODE:
656 Safefree(context);
657
658void
659add(self, ...)
660 SV* self
661 PREINIT:
ee7ea0b1 662 MD5_CTX* context = get_md5_ctx(aTHX_ self);
3357b1b1
JH
663 int i;
664 unsigned char *data;
665 STRLEN len;
666 PPCODE:
667 for (i = 1; i < items; i++) {
62d37bf0 668 U32 had_utf8 = SvUTF8(ST(i));
844f0213 669 data = (unsigned char *)(SvPVbyte(ST(i), len));
3357b1b1 670 MD5Update(context, data, len);
62d37bf0 671 if (had_utf8) sv_utf8_upgrade(ST(i));
3357b1b1
JH
672 }
673 XSRETURN(1); /* self */
674
675void
676addfile(self, fh)
677 SV* self
678 InputStream fh
679 PREINIT:
ee7ea0b1 680 MD5_CTX* context = get_md5_ctx(aTHX_ self);
3357b1b1 681 STRLEN fill = context->bytes_low & 0x3F;
27da23d5
JH
682#ifdef USE_HEAP_INSTEAD_OF_STACK
683 unsigned char* buffer;
684#else
3357b1b1 685 unsigned char buffer[4096];
27da23d5 686#endif
263df5f1 687 int n;
3357b1b1
JH
688 CODE:
689 if (fh) {
27da23d5
JH
690#ifdef USE_HEAP_INSTEAD_OF_STACK
691 New(0, buffer, 4096, unsigned char);
692 assert(buffer);
693#endif
3357b1b1
JH
694 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 STRLEN missing = 64 - fill;
1c9948bf 700 if ( (n = PerlIO_read(fh, buffer, missing)) > 0)
3357b1b1 701 MD5Update(context, buffer, n);
ef3aad62 702 else
3357b1b1
JH
703 XSRETURN(1); /* self */
704 }
705
ac70dec1 706 /* Process blocks until EOF or error */
1c9948bf 707 while ( (n = PerlIO_read(fh, buffer, sizeof(buffer))) > 0) {
3357b1b1
JH
708 MD5Update(context, buffer, n);
709 }
27da23d5
JH
710#ifdef USE_HEAP_INSTEAD_OF_STACK
711 Safefree(buffer);
712#endif
263df5f1 713 if (PerlIO_error(fh)) {
ac70dec1
JH
714 croak("Reading from filehandle failed");
715 }
716 }
717 else {
718 croak("No filehandle passed");
3357b1b1
JH
719 }
720 XSRETURN(1); /* self */
721
722void
723digest(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 MD5Final(digeststr, context);
733 MD5Init(context); /* In case it is reused */
ee7ea0b1 734 ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
3357b1b1
JH
735 XSRETURN(1);
736
737void
38054f44
CBW
738context(ctx, ...)
739 MD5_CTX* ctx
740 PREINIT:
741 char out[16];
742 U32 w;
743 PPCODE:
744 if (items > 2) {
745 STRLEN len;
746 unsigned long blocks = SvUV(ST(1));
747 unsigned char *buf = (unsigned char *)(SvPV(ST(2), len));
748 ctx->A = buf[ 0] | (buf[ 1]<<8) | (buf[ 2]<<16) | (buf[ 3]<<24);
749 ctx->B = buf[ 4] | (buf[ 5]<<8) | (buf[ 6]<<16) | (buf[ 7]<<24);
750 ctx->C = buf[ 8] | (buf[ 9]<<8) | (buf[10]<<16) | (buf[11]<<24);
751 ctx->D = buf[12] | (buf[13]<<8) | (buf[14]<<16) | (buf[15]<<24);
752 ctx->bytes_low = blocks << 6;
753 ctx->bytes_high = blocks >> 26;
754 if (items == 4) {
755 buf = (unsigned char *)(SvPV(ST(3), len));
756 MD5Update(ctx, buf, len);
757 }
758 XSRETURN(1); /* ctx */
759 } else if (items != 1) {
760 XSRETURN(0);
761 }
762
763 w=ctx->A; out[ 0]=w; out[ 1]=(w>>8); out[ 2]=(w>>16); out[ 3]=(w>>24);
764 w=ctx->B; out[ 4]=w; out[ 5]=(w>>8); out[ 6]=(w>>16); out[ 7]=(w>>24);
765 w=ctx->C; out[ 8]=w; out[ 9]=(w>>8); out[10]=(w>>16); out[11]=(w>>24);
766 w=ctx->D; out[12]=w; out[13]=(w>>8); out[14]=(w>>16); out[15]=(w>>24);
767
768 EXTEND(SP, 3);
769 ST(0) = sv_2mortal(newSVuv(ctx->bytes_high << 26 |
770 ctx->bytes_low >> 6));
771 ST(1) = sv_2mortal(newSVpv(out, 16));
772 ST(2) = sv_2mortal(newSVpv((char *)ctx->buffer,
773 ctx->bytes_low & 0x3F));
774 XSRETURN(3);
775
776void
3357b1b1
JH
777md5(...)
778 ALIAS:
779 Digest::MD5::md5 = F_BIN
780 Digest::MD5::md5_hex = F_HEX
781 Digest::MD5::md5_base64 = F_B64
782 PREINIT:
783 MD5_CTX ctx;
784 int i;
785 unsigned char *data;
786 STRLEN len;
787 unsigned char digeststr[16];
788 PPCODE:
789 MD5Init(&ctx);
5a046520 790
62d37bf0 791 if (PL_dowarn & G_WARN_ON) {
326fafaa 792 const char *msg = 0;
5a046520
JH
793 if (items == 1) {
794 if (SvROK(ST(0))) {
795 SV* sv = SvRV(ST(0));
38054f44
CBW
796 char *name;
797 if (SvOBJECT(sv) && (name = HvNAME(SvSTASH(sv)))
798 && strEQ(name, "Digest::MD5"))
5a046520
JH
799 msg = "probably called as method";
800 else
801 msg = "called with reference argument";
802 }
803 }
804 else if (items > 1) {
62d37bf0 805 data = (unsigned char *)SvPV(ST(0), len);
5a046520
JH
806 if (len == 11 && memEQ("Digest::MD5", data, 11)) {
807 msg = "probably called as class method";
808 }
47a7661d
GA
809 else if (SvROK(ST(0))) {
810 SV* sv = SvRV(ST(0));
38054f44
CBW
811 char *name;
812 if (SvOBJECT(sv) && (name = HvNAME(SvSTASH(sv)))
813 && strEQ(name, "Digest::MD5"))
47a7661d
GA
814 msg = "probably called as method";
815 }
5a046520
JH
816 }
817 if (msg) {
8a722a80
JH
818 const char *f = (ix == F_BIN) ? "md5" :
819 (ix == F_HEX) ? "md5_hex" : "md5_base64";
5a046520
JH
820 warn("&Digest::MD5::%s function %s", f, msg);
821 }
db2a39d5 822 }
5a046520 823
3357b1b1 824 for (i = 0; i < items; i++) {
62d37bf0 825 U32 had_utf8 = SvUTF8(ST(i));
844f0213 826 data = (unsigned char *)(SvPVbyte(ST(i), len));
3357b1b1 827 MD5Update(&ctx, data, len);
62d37bf0 828 if (had_utf8) sv_utf8_upgrade(ST(i));
3357b1b1
JH
829 }
830 MD5Final(digeststr, &ctx);
ee7ea0b1 831 ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
3357b1b1 832 XSRETURN(1);