"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 #define PERL_NO_GET_CONTEXT /* we want efficiency */
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8 #ifdef __cplusplus
9 }
10 #endif
11
12 #ifndef PERL_VERSION
13 # include <patchlevel.h>
14 # if !(defined(PERL_VERSION) || (SUBVERSION > 0 && defined(PATCHLEVEL)))
15 # include <could_not_find_Perl_patchlevel.h>
16 # endif
17 # define PERL_REVISION 5
18 # define PERL_VERSION PATCHLEVEL
19 # define PERL_SUBVERSION SUBVERSION
20 #endif
21
22 #if PERL_VERSION <= 4 && !defined(PL_dowarn)
23 #define PL_dowarn dowarn
24 #endif
25
26 #ifdef G_WARN_ON
27 #define DOWARN (PL_dowarn & G_WARN_ON)
28 #else
29 #define DOWARN PL_dowarn
30 #endif
31
32 #ifdef SvPVbyte
33 #if PERL_REVISION == 5 && PERL_VERSION < 7
34 /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */
35 #undef SvPVbyte
36 #define SvPVbyte(sv, lp) \
37 ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
38 ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp))
39
40 static char *
41 my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
42 {
43 sv_utf8_downgrade(sv,0);
44 return SvPV(sv,*lp);
45 }
46 #endif
47 #else
48 #define SvPVbyte SvPV
49 #endif
50
51 #ifndef dTHX
52 #define pTHX_
53 #define aTHX_
54 #endif
55
56 /* NIST Secure Hash Algorithm */
57 /* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
58 /* from Peter C. Gutmann's implementation as found in */
59 /* Applied Cryptography by Bruce Schneier */
60 /* Further modifications to include the "UNRAVEL" stuff, below */
61
62 /* This code is in the public domain */
63
64 /* Useful defines & typedefs */
65
66 #if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321)))
67 typedef U64TYPE ULONGx;
68 # if BYTEORDER == 0x1234
69 # undef BYTEORDER
70 # define BYTEORDER 0x12345678
71 # elif BYTEORDER == 0x4321
72 # undef BYTEORDER
73 # define BYTEORDER 0x87654321
74 # endif
75 #else
76 typedef unsigned long ULONGx; /* 32-or-more-bit quantity */
77 #endif
78
79 #define SHA_BLOCKSIZE 64
80 #define SHA_DIGESTSIZE 20
81
82 typedef struct {
83 ULONGx digest[5]; /* message digest */
84 ULONGx count_lo, count_hi; /* 64-bit bit count */
85 U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */
86 int local; /* unprocessed amount in data */
87 } SHA_INFO;
88
89
90 /* UNRAVEL should be fastest & biggest */
91 /* UNROLL_LOOPS should be just as big, but slightly slower */
92 /* both undefined should be smallest and slowest */
93
94 #define SHA_VERSION 1
95 #define UNRAVEL
96 /* #define UNROLL_LOOPS */
97
98 /* SHA f()-functions */
99 #define f1(x,y,z) ((x & y) | (~x & z))
100 #define f2(x,y,z) (x ^ y ^ z)
101 #define f3(x,y,z) ((x & y) | (x & z) | (y & z))
102 #define f4(x,y,z) (x ^ y ^ z)
103
104 /* SHA constants */
105 #define CONST1 0x5a827999L
106 #define CONST2 0x6ed9eba1L
107 #define CONST3 0x8f1bbcdcL
108 #define CONST4 0xca62c1d6L
109
110 /* truncate to 32 bits -- should be a null op on 32-bit machines */
111 #define T32(x) ((x) & 0xffffffffL)
112
113 /* 32-bit rotate */
114 #define R32(x,n) T32(((x << n) | (x >> (32 - n))))
115
116 /* the generic case, for when the overall rotation is not unraveled */
117 #define FG(n) \
118 T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
119 E = D; D = C; C = R32(B,30); B = A; A = T
120
121 /* specific cases, for when the overall rotation is unraveled */
122 #define FA(n) \
123 T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
124
125 #define FB(n) \
126 E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
127
128 #define FC(n) \
129 D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
130
131 #define FD(n) \
132 C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
133
134 #define FE(n) \
135 B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
136
137 #define FT(n) \
138 A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
139
140
141 static void sha_transform(SHA_INFO *sha_info)
142 {
143 int i;
144 U8 *dp;
145 ULONGx T, A, B, C, D, E, W[80], *WP;
146
147 dp = sha_info->data;
148
149 /*
150 the following makes sure that at least one code block below is
151 traversed or an error is reported, without the necessity for nested
152 preprocessor if/else/endif blocks, which are a great pain in the
153 nether regions of the anatomy...
154 */
155 #undef SWAP_DONE
156
157 #if BYTEORDER == 0x1234
158 #define SWAP_DONE
159 /* assert(sizeof(ULONGx) == 4); */
160 for (i = 0; i < 16; ++i) {
161 T = *((ULONGx *) dp);
162 dp += 4;
163 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
164 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
165 }
166 #endif
167
168 #if BYTEORDER == 0x4321
169 #define SWAP_DONE
170 /* assert(sizeof(ULONGx) == 4); */
171 for (i = 0; i < 16; ++i) {
172 T = *((ULONGx *) dp);
173 dp += 4;
174 W[i] = T32(T);
175 }
176 #endif
177
178 #if BYTEORDER == 0x12345678
179 #define SWAP_DONE
180 /* assert(sizeof(ULONGx) == 8); */
181 for (i = 0; i < 16; i += 2) {
182 T = *((ULONGx *) dp);
183 dp += 8;
184 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
185 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
186 T >>= 32;
187 W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
188 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
189 }
190 #endif
191
192 #if BYTEORDER == 0x87654321
193 #define SWAP_DONE
194 /* assert(sizeof(ULONGx) == 8); */
195 for (i = 0; i < 16; i += 2) {
196 T = *((ULONGx *) dp);
197 dp += 8;
198 W[i] = T32(T >> 32);
199 W[i+1] = T32(T);
200 }
201 #endif
202
203 #ifndef SWAP_DONE
204 #error Unknown byte order -- you need to add code here
205 #endif /* SWAP_DONE */
206
207 for (i = 16; i < 80; ++i) {
208 W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
209 #if (SHA_VERSION == 1)
210 W[i] = R32(W[i], 1);
211 #endif /* SHA_VERSION */
212 }
213 A = sha_info->digest[0];
214 B = sha_info->digest[1];
215 C = sha_info->digest[2];
216 D = sha_info->digest[3];
217 E = sha_info->digest[4];
218 WP = W;
219 #ifdef UNRAVEL
220 FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
221 FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
222 FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
223 FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
224 FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
225 FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
226 FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
227 FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
228 sha_info->digest[0] = T32(sha_info->digest[0] + E);
229 sha_info->digest[1] = T32(sha_info->digest[1] + T);
230 sha_info->digest[2] = T32(sha_info->digest[2] + A);
231 sha_info->digest[3] = T32(sha_info->digest[3] + B);
232 sha_info->digest[4] = T32(sha_info->digest[4] + C);
233 #else /* !UNRAVEL */
234 #ifdef UNROLL_LOOPS
235 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
236 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
237 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
238 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
239 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
240 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
241 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
242 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
243 #else /* !UNROLL_LOOPS */
244 for (i = 0; i < 20; ++i) { FG(1); }
245 for (i = 20; i < 40; ++i) { FG(2); }
246 for (i = 40; i < 60; ++i) { FG(3); }
247 for (i = 60; i < 80; ++i) { FG(4); }
248 #endif /* !UNROLL_LOOPS */
249 sha_info->digest[0] = T32(sha_info->digest[0] + A);
250 sha_info->digest[1] = T32(sha_info->digest[1] + B);
251 sha_info->digest[2] = T32(sha_info->digest[2] + C);
252 sha_info->digest[3] = T32(sha_info->digest[3] + D);
253 sha_info->digest[4] = T32(sha_info->digest[4] + E);
254 #endif /* !UNRAVEL */
255 }
256
257 /* initialize the SHA digest */
258
259 static void sha_init(SHA_INFO *sha_info)
260 {
261 sha_info->digest[0] = 0x67452301L;
262 sha_info->digest[1] = 0xefcdab89L;
263 sha_info->digest[2] = 0x98badcfeL;
264 sha_info->digest[3] = 0x10325476L;
265 sha_info->digest[4] = 0xc3d2e1f0L;
266 sha_info->count_lo = 0L;
267 sha_info->count_hi = 0L;
268 sha_info->local = 0;
269 }
270
271 /* update the SHA digest */
272
273 static void sha_update(SHA_INFO *sha_info, U8 *buffer, int count)
274 {
275 int i;
276 ULONGx clo;
277
278 clo = T32(sha_info->count_lo + ((ULONGx) count << 3));
279 if (clo < sha_info->count_lo) {
280 ++sha_info->count_hi;
281 }
282 sha_info->count_lo = clo;
283 sha_info->count_hi += (ULONGx) count >> 29;
284 if (sha_info->local) {
285 i = SHA_BLOCKSIZE - sha_info->local;
286 if (i > count) {
287 i = count;
288 }
289 memcpy(((U8 *) sha_info->data) + sha_info->local, buffer, i);
290 count -= i;
291 buffer += i;
292 sha_info->local += i;
293 if (sha_info->local == SHA_BLOCKSIZE) {
294 sha_transform(sha_info);
295 } else {
296 return;
297 }
298 }
299 while (count >= SHA_BLOCKSIZE) {
300 memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
301 buffer += SHA_BLOCKSIZE;
302 count -= SHA_BLOCKSIZE;
303 sha_transform(sha_info);
304 }
305 memcpy(sha_info->data, buffer, count);
306 sha_info->local = count;
307 }
308
309
310 static void sha_transform_and_copy(unsigned char digest[20], SHA_INFO *sha_info)
311 {
312 sha_transform(sha_info);
313 digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
314 digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
315 digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
316 digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
317 digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
318 digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
319 digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
320 digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
321 digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
322 digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
323 digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
324 digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
325 digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
326 digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
327 digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
328 digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
329 digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
330 digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
331 digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
332 digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
333 }
334
335 /* finish computing the SHA digest */
336 static void sha_final(unsigned char digest[20], SHA_INFO *sha_info)
337 {
338 int count;
339 ULONGx lo_bit_count, hi_bit_count;
340
341 lo_bit_count = sha_info->count_lo;
342 hi_bit_count = sha_info->count_hi;
343 count = (int) ((lo_bit_count >> 3) & 0x3f);
344 ((U8 *) sha_info->data)[count++] = 0x80;
345 if (count > SHA_BLOCKSIZE - 8) {
346 memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
347 sha_transform(sha_info);
348 memset((U8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
349 } else {
350 memset(((U8 *) sha_info->data) + count, 0,
351 SHA_BLOCKSIZE - 8 - count);
352 }
353 sha_info->data[56] = (U8)((hi_bit_count >> 24) & 0xff);
354 sha_info->data[57] = (U8)((hi_bit_count >> 16) & 0xff);
355 sha_info->data[58] = (U8)((hi_bit_count >> 8) & 0xff);
356 sha_info->data[59] = (U8)((hi_bit_count >> 0) & 0xff);
357 sha_info->data[60] = (U8)((lo_bit_count >> 24) & 0xff);
358 sha_info->data[61] = (U8)((lo_bit_count >> 16) & 0xff);
359 sha_info->data[62] = (U8)((lo_bit_count >> 8) & 0xff);
360 sha_info->data[63] = (U8)((lo_bit_count >> 0) & 0xff);
361 sha_transform_and_copy(digest, sha_info);
362 }
363
364
365
366
367
368 /*----------------------------------------------------------------*/
369 #ifndef INT2PTR
370 #define INT2PTR(any,d) (any)(d)
371 #endif
372
373 static SHA_INFO* get_sha_info(pTHX_ SV* sv)
374 {
375 if (sv_derived_from(sv, "Digest::SHA1"))
376 return INT2PTR(SHA_INFO*, SvIV(SvRV(sv)));
377 croak("Not a reference to a Digest::SHA1 object");
378 return (SHA_INFO*)0; /* some compilers insist on a return value */
379 }
380
381
382 static char* hex_20(const unsigned char* from, char* to)
383 {
384 static const char *hexdigits = "0123456789abcdef";
385 const unsigned char *end = from + 20;
386 char *d = to;
387
388 while (from < end) {
389 *d++ = hexdigits[(*from >> 4)];
390 *d++ = hexdigits[(*from & 0x0F)];
391 from++;
392 }
393 *d = '\0';
394 return to;
395 }
396
397 static char* base64_20(const unsigned char* from, char* to)
398 {
399 static const char* base64 =
400 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
401 const unsigned char *end = from + 20;
402 unsigned char c1, c2, c3;
403 char *d = to;
404
405 while (1) {
406 c1 = *from++;
407 c2 = *from++;
408 *d++ = base64[c1>>2];
409 *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
410 if (from == end) {
411 *d++ = base64[(c2 & 0xF) << 2];
412 break;
413 }
414 c3 = *from++;
415 *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
416 *d++ = base64[c3 & 0x3F];
417 }
418 *d = '\0';
419 return to;
420 }
421
422 /* Formats */
423 #define F_BIN 0
424 #define F_HEX 1
425 #define F_B64 2
426
427 static SV* make_mortal_sv(pTHX_ const unsigned char *src, int type)
428 {
429 STRLEN len;
430 char result[41];
431 char *ret;
432
433 switch (type) {
434 case F_BIN:
435 ret = (char*)src;
436 len = 20;
437 break;
438 case F_HEX:
439 ret = hex_20(src, result);
440 len = 40;
441 break;
442 case F_B64:
443 ret = base64_20(src, result);
444 len = 27;
445 break;
446 default:
447 croak("Bad convertion type (%d)", type);
448 break;
449 }
450 return sv_2mortal(newSVpv(ret,len));
451 }
452
453
454 /********************************************************************/
455
456 typedef PerlIO* InputStream;
457
458 MODULE = Digest::SHA1 PACKAGE = Digest::SHA1
459
460 PROTOTYPES: DISABLE
461
462 void
463 new(xclass)
464 SV* xclass
465 PREINIT:
466 SHA_INFO* context;
467 PPCODE:
468 if (!SvROK(xclass)) {
469 STRLEN my_na;
470 char *sclass = SvPV(xclass, my_na);
471 New(55, context, 1, SHA_INFO);
472 ST(0) = sv_newmortal();
473 sv_setref_pv(ST(0), sclass, (void*)context);
474 SvREADONLY_on(SvRV(ST(0)));
475 } else {
476 context = get_sha_info(aTHX_ xclass);
477 }
478 sha_init(context);
479 XSRETURN(1);
480
481 void
482 clone(self)
483 SV* self
484 PREINIT:
485 SHA_INFO* cont = get_sha_info(aTHX_ self);
486 const char *myname = sv_reftype(SvRV(self),TRUE);
487 SHA_INFO* context;
488 PPCODE:
489 New(55, context, 1, SHA_INFO);
490 ST(0) = sv_newmortal();
491 sv_setref_pv(ST(0), myname , (void*)context);
492 SvREADONLY_on(SvRV(ST(0)));
493 memcpy(context,cont,sizeof(SHA_INFO));
494 XSRETURN(1);
495
496 void
497 DESTROY(context)
498 SHA_INFO* context
499 CODE:
500 Safefree(context);
501
502 void
503 add(self, ...)
504 SV* self
505 PREINIT:
506 SHA_INFO* context = get_sha_info(aTHX_ self);
507 int i;
508 unsigned char *data;
509 STRLEN len;
510 PPCODE:
511 for (i = 1; i < items; i++) {
512 data = (unsigned char *)(SvPVbyte(ST(i), len));
513 sha_update(context, data, len);
514 }
515 XSRETURN(1); /* self */
516
517 void
518 addfile(self, fh)
519 SV* self
520 InputStream fh
521 PREINIT:
522 SHA_INFO* context = get_sha_info(aTHX_ self);
523 unsigned char buffer[4096];
524 int n;
525 CODE:
526 if (fh) {
527 /* Process blocks until EOF or error */
528 while ( (n = PerlIO_read(fh, buffer, sizeof(buffer))) > 0) {
529 sha_update(context, buffer, n);
530 }
531 if (PerlIO_error(fh)) {
532 croak("Reading from filehandle failed");
533 }
534 }
535 else {
536 croak("No filehandle passed");
537 }
538
539 XSRETURN(1); /* self */
540
541 void
542 digest(context)
543 SHA_INFO* context
544 ALIAS:
545 Digest::SHA1::digest = F_BIN
546 Digest::SHA1::hexdigest = F_HEX
547 Digest::SHA1::b64digest = F_B64
548 PREINIT:
549 unsigned char digeststr[20];
550 PPCODE:
551 sha_final(digeststr, context);
552 sha_init(context); /* In case it is reused */
553 ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
554 XSRETURN(1);
555
556 void
557 sha1(...)
558 ALIAS:
559 Digest::SHA1::sha1 = F_BIN
560 Digest::SHA1::sha1_hex = F_HEX
561 Digest::SHA1::sha1_base64 = F_B64
562 PREINIT:
563 SHA_INFO ctx;
564 int i;
565 unsigned char *data;
566 STRLEN len;
567 unsigned char digeststr[20];
568 PPCODE:
569 sha_init(&ctx);
570
571 if (DOWARN) {
572 const char *msg = 0;
573 if (items == 1) {
574 if (SvROK(ST(0))) {
575 SV* sv = SvRV(ST(0));
576 if (SvOBJECT(sv) && strEQ(HvNAME(SvSTASH(sv)), "Digest::SHA1"))
577 msg = "probably called as method";
578 else
579 msg = "called with reference argument";
580 }
581 }
582 else if (items > 1) {
583 data = (unsigned char *)SvPVbyte(ST(0), len);
584 if (len == 12 && memEQ("Digest::SHA1", data, 12)) {
585 msg = "probably called as class method";
586 }
587 }
588 if (msg) {
589 const char *f = (ix == F_BIN) ? "sha1" :
590 (ix == F_HEX) ? "sha1_hex" : "sha1_base64";
591 warn("&Digest::SHA1::%s function %s", f, msg);
592 }
593 }
594
595 for (i = 0; i < items; i++) {
596 data = (unsigned char *)(SvPVbyte(ST(i), len));
597 sha_update(&ctx, data, len);
598 }
599 sha_final(digeststr, &ctx);
600 ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
601 XSRETURN(1);
602
603 void
604 sha1_transform(data)
605 SV* data
606 PREINIT:
607 SHA_INFO ctx;
608 unsigned char *data_pv;
609 unsigned char test[64];
610 STRLEN len;
611 unsigned char digeststr[20];
612 PPCODE:
613 sha_init(&ctx);
614
615 memset (test, 0, 64);
616 data_pv = (unsigned char *)(SvPVbyte(data, len));
617 memcpy (test, data_pv, len);
618 memcpy ((&ctx)->data, test, 64);
619 sha_transform_and_copy(digeststr, &ctx);
620 ST(0) = sv_2mortal(newSVpv((char*)digeststr, 20));
621 XSRETURN(1);
622