1 #define PERL_NO_GET_CONTEXT
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5
6 #ifdef SvPVbyte
7 #if PERL_REVISION == 5 && PERL_VERSION < 8
8 #undef SvPVbyte
9 #define SvPVbyte(sv, lp) \
10 (sv_utf8_downgrade((sv), 0), SvPV((sv), (lp)))
11 #endif
12 #else
13 #define SvPVbyte SvPV
14 #endif
15
16 #ifndef dTHX
17 #define pTHX_
18 #define aTHX_
19 #endif
20
21 #ifndef PerlIO
22 #define PerlIO FILE
23 #define PerlIO_read(f, buf, count) fread(buf, 1, count, f)
24 #endif
25
26 #ifndef sv_derived_from
27 #include "src/sdf.c"
28 #endif
29
30 #ifndef Newx
31 #define Newx(ptr, num, type) New(0, ptr, num, type)
32 #define Newxz(ptr, num, type) Newz(0, ptr, num, type)
33 #endif
34
35 #include "src/sha.c"
36
37 static const int ix2alg[] =
38 {1,1,1,224,224,224,256,256,256,384,384,384,512,512,512,
39 512224,512224,512224,512256,512256,512256};
40
41 #ifndef INT2PTR
42 #define INT2PTR(p, i) (p) (i)
43 #endif
44
45 #define MAX_WRITE_SIZE 16384
46 #define IO_BUFFER_SIZE 4096
47
getSHA(pTHX_ SV * self)48 static SHA *getSHA(pTHX_ SV *self)
49 {
50 if (!sv_isobject(self) || !sv_derived_from(self, "Digest::SHA"))
51 return(NULL);
52 return INT2PTR(SHA *, SvIV(SvRV(self)));
53 }
54
55 MODULE = Digest::SHA PACKAGE = Digest::SHA
56
57 PROTOTYPES: ENABLE
58
59 int
60 shainit(s, alg)
61 SHA * s
62 int alg
63
64 void
65 sharewind(s)
66 SHA * s
67
68 unsigned long
69 shawrite(bitstr, bitcnt, s)
70 unsigned char * bitstr
71 unsigned long bitcnt
72 SHA * s
73
74 SV *
75 newSHA(classname, alg)
76 char * classname
77 int alg
78 PREINIT:
79 SHA *state;
80 CODE:
81 Newxz(state, 1, SHA);
82 if (!shainit(state, alg)) {
83 Safefree(state);
84 XSRETURN_UNDEF;
85 }
86 RETVAL = newSV(0);
87 sv_setref_pv(RETVAL, classname, (void *) state);
88 SvREADONLY_on(SvRV(RETVAL));
89 OUTPUT:
90 RETVAL
91
92 SV *
93 clone(self)
94 SV * self
95 PREINIT:
96 SHA *state;
97 SHA *clone;
98 CODE:
99 if ((state = getSHA(aTHX_ self)) == NULL)
100 XSRETURN_UNDEF;
101 Newx(clone, 1, SHA);
102 RETVAL = newSV(0);
103 sv_setref_pv(RETVAL, sv_reftype(SvRV(self), 1), (void *) clone);
104 SvREADONLY_on(SvRV(RETVAL));
105 Copy(state, clone, 1, SHA);
106 OUTPUT:
107 RETVAL
108
109 void
110 DESTROY(s)
111 SHA * s
112 CODE:
113 Safefree(s);
114
115 SV *
116 sha1(...)
117 ALIAS:
118 Digest::SHA::sha1 = 0
119 Digest::SHA::sha1_hex = 1
120 Digest::SHA::sha1_base64 = 2
121 Digest::SHA::sha224 = 3
122 Digest::SHA::sha224_hex = 4
123 Digest::SHA::sha224_base64 = 5
124 Digest::SHA::sha256 = 6
125 Digest::SHA::sha256_hex = 7
126 Digest::SHA::sha256_base64 = 8
127 Digest::SHA::sha384 = 9
128 Digest::SHA::sha384_hex = 10
129 Digest::SHA::sha384_base64 = 11
130 Digest::SHA::sha512 = 12
131 Digest::SHA::sha512_hex = 13
132 Digest::SHA::sha512_base64 = 14
133 Digest::SHA::sha512224 = 15
134 Digest::SHA::sha512224_hex = 16
135 Digest::SHA::sha512224_base64 = 17
136 Digest::SHA::sha512256 = 18
137 Digest::SHA::sha512256_hex = 19
138 Digest::SHA::sha512256_base64 = 20
139 PREINIT:
140 int i;
141 UCHR *data;
142 STRLEN len;
143 SHA sha;
144 char *result;
145 CODE:
146 if (!shainit(&sha, ix2alg[ix]))
147 XSRETURN_UNDEF;
148 for (i = 0; i < items; i++) {
149 data = (UCHR *) (SvPVbyte(ST(i), len));
150 while (len > MAX_WRITE_SIZE) {
151 shawrite(data, MAX_WRITE_SIZE << 3, &sha);
152 data += MAX_WRITE_SIZE;
153 len -= MAX_WRITE_SIZE;
154 }
155 shawrite(data, (ULNG) len << 3, &sha);
156 }
157 shafinish(&sha);
158 len = 0;
159 if (ix % 3 == 0) {
160 result = (char *) shadigest(&sha);
161 len = sha.digestlen;
162 }
163 else if (ix % 3 == 1)
164 result = shahex(&sha);
165 else
166 result = shabase64(&sha);
167 RETVAL = newSVpv(result, len);
168 OUTPUT:
169 RETVAL
170
171 SV *
172 hmac_sha1(...)
173 ALIAS:
174 Digest::SHA::hmac_sha1 = 0
175 Digest::SHA::hmac_sha1_hex = 1
176 Digest::SHA::hmac_sha1_base64 = 2
177 Digest::SHA::hmac_sha224 = 3
178 Digest::SHA::hmac_sha224_hex = 4
179 Digest::SHA::hmac_sha224_base64 = 5
180 Digest::SHA::hmac_sha256 = 6
181 Digest::SHA::hmac_sha256_hex = 7
182 Digest::SHA::hmac_sha256_base64 = 8
183 Digest::SHA::hmac_sha384 = 9
184 Digest::SHA::hmac_sha384_hex = 10
185 Digest::SHA::hmac_sha384_base64 = 11
186 Digest::SHA::hmac_sha512 = 12
187 Digest::SHA::hmac_sha512_hex = 13
188 Digest::SHA::hmac_sha512_base64 = 14
189 Digest::SHA::hmac_sha512224 = 15
190 Digest::SHA::hmac_sha512224_hex = 16
191 Digest::SHA::hmac_sha512224_base64 = 17
192 Digest::SHA::hmac_sha512256 = 18
193 Digest::SHA::hmac_sha512256_hex = 19
194 Digest::SHA::hmac_sha512256_base64 = 20
195 PREINIT:
196 int i;
197 UCHR *key = (UCHR *) "";
198 UCHR *data;
199 STRLEN len = 0;
200 HMAC hmac;
201 char *result;
202 CODE:
203 if (items > 0) {
204 key = (UCHR *) (SvPVbyte(ST(items-1), len));
205 }
206 if (hmacinit(&hmac, ix2alg[ix], key, (UINT) len) == NULL)
207 XSRETURN_UNDEF;
208 for (i = 0; i < items - 1; i++) {
209 data = (UCHR *) (SvPVbyte(ST(i), len));
210 while (len > MAX_WRITE_SIZE) {
211 hmacwrite(data, MAX_WRITE_SIZE << 3, &hmac);
212 data += MAX_WRITE_SIZE;
213 len -= MAX_WRITE_SIZE;
214 }
215 hmacwrite(data, (ULNG) len << 3, &hmac);
216 }
217 hmacfinish(&hmac);
218 len = 0;
219 if (ix % 3 == 0) {
220 result = (char *) hmacdigest(&hmac);
221 len = hmac.digestlen;
222 }
223 else if (ix % 3 == 1)
224 result = hmachex(&hmac);
225 else
226 result = hmacbase64(&hmac);
227 RETVAL = newSVpv(result, len);
228 OUTPUT:
229 RETVAL
230
231 int
232 hashsize(self)
233 SV * self
234 ALIAS:
235 Digest::SHA::hashsize = 0
236 Digest::SHA::algorithm = 1
237 PREINIT:
238 SHA *state;
239 CODE:
240 if ((state = getSHA(aTHX_ self)) == NULL)
241 XSRETURN_UNDEF;
242 RETVAL = ix ? state->alg : (int) (state->digestlen << 3);
243 OUTPUT:
244 RETVAL
245
246 void
247 add(self, ...)
248 SV * self
249 PREINIT:
250 int i;
251 UCHR *data;
252 STRLEN len;
253 SHA *state;
254 PPCODE:
255 if ((state = getSHA(aTHX_ self)) == NULL)
256 XSRETURN_UNDEF;
257 for (i = 1; i < items; i++) {
258 data = (UCHR *) (SvPVbyte(ST(i), len));
259 while (len > MAX_WRITE_SIZE) {
260 shawrite(data, MAX_WRITE_SIZE << 3, state);
261 data += MAX_WRITE_SIZE;
262 len -= MAX_WRITE_SIZE;
263 }
264 shawrite(data, (ULNG) len << 3, state);
265 }
266 XSRETURN(1);
267
268 SV *
269 digest(self)
270 SV * self
271 ALIAS:
272 Digest::SHA::digest = 0
273 Digest::SHA::hexdigest = 1
274 Digest::SHA::b64digest = 2
275 PREINIT:
276 STRLEN len;
277 SHA *state;
278 char *result;
279 CODE:
280 if ((state = getSHA(aTHX_ self)) == NULL)
281 XSRETURN_UNDEF;
282 shafinish(state);
283 len = 0;
284 if (ix == 0) {
285 result = (char *) shadigest(state);
286 len = state->digestlen;
287 }
288 else if (ix == 1)
289 result = shahex(state);
290 else
291 result = shabase64(state);
292 RETVAL = newSVpv(result, len);
293 sharewind(state);
294 OUTPUT:
295 RETVAL
296
297 SV *
298 _getstate(self)
299 SV * self
300 PREINIT:
301 SHA *state;
302 UCHR buf[256];
303 UCHR *ptr = buf;
304 CODE:
305 if ((state = getSHA(aTHX_ self)) == NULL)
306 XSRETURN_UNDEF;
307 Copy(digcpy(state), ptr, state->alg <= SHA256 ? 32 : 64, UCHR);
308 ptr += state->alg <= SHA256 ? 32 : 64;
309 Copy(state->block, ptr, state->alg <= SHA256 ? 64 : 128, UCHR);
310 ptr += state->alg <= SHA256 ? 64 : 128;
311 ptr = w32mem(ptr, state->blockcnt);
312 ptr = w32mem(ptr, state->lenhh);
313 ptr = w32mem(ptr, state->lenhl);
314 ptr = w32mem(ptr, state->lenlh);
315 ptr = w32mem(ptr, state->lenll);
316 RETVAL = newSVpv((char *) buf, (STRLEN) (ptr - buf));
317 OUTPUT:
318 RETVAL
319
320 void
321 _putstate(self, packed_state)
322 SV * self
323 SV * packed_state
324 PREINIT:
325 UINT bc;
326 STRLEN len;
327 SHA *state;
328 UCHR *data;
329 PPCODE:
330 if ((state = getSHA(aTHX_ self)) == NULL)
331 XSRETURN_UNDEF;
332 data = (UCHR *) SvPV(packed_state, len);
333 if (len != (state->alg <= SHA256 ? 116U : 212U))
334 XSRETURN_UNDEF;
335 data = statecpy(state, data);
336 Copy(data, state->block, state->blocksize >> 3, UCHR);
337 data += (state->blocksize >> 3);
338 bc = memw32(data), data += 4;
339 if (bc >= (state->alg <= SHA256 ? 512U : 1024U))
340 XSRETURN_UNDEF;
341 state->blockcnt = bc;
342 state->lenhh = memw32(data), data += 4;
343 state->lenhl = memw32(data), data += 4;
344 state->lenlh = memw32(data), data += 4;
345 state->lenll = memw32(data);
346 XSRETURN(1);
347
348 void
349 _addfilebin(self, f)
350 SV * self
351 PerlIO * f
352 PREINIT:
353 SHA *state;
354 int n;
355 UCHR in[IO_BUFFER_SIZE];
356 PPCODE:
357 if (!f || (state = getSHA(aTHX_ self)) == NULL)
358 XSRETURN_UNDEF;
359 while ((n = (int) PerlIO_read(f, in, sizeof(in))) > 0)
360 shawrite(in, (ULNG) n << 3, state);
361 XSRETURN(1);
362
363 void
364 _addfileuniv(self, f)
365 SV * self
366 PerlIO * f
367 PREINIT:
368 UCHR c;
369 int n;
370 int cr = 0;
371 UCHR *src, *dst;
372 UCHR in[IO_BUFFER_SIZE+1];
373 SHA *state;
374 PPCODE:
375 if (!f || (state = getSHA(aTHX_ self)) == NULL)
376 XSRETURN_UNDEF;
377 while ((n = (int) PerlIO_read(f, in+1, IO_BUFFER_SIZE)) > 0) {
378 for (dst = in, src = in + 1; n; n--) {
379 c = *src++;
380 if (!cr) {
381 if (c == '\015')
382 cr = 1;
383 else
384 *dst++ = c;
385 }
386 else {
387 if (c == '\015')
388 *dst++ = '\012';
389 else if (c == '\012') {
390 *dst++ = '\012';
391 cr = 0;
392 }
393 else {
394 *dst++ = '\012';
395 *dst++ = c;
396 cr = 0;
397 }
398 }
399 }
400 shawrite(in, (ULNG) (dst - in) << 3, state);
401 }
402 if (cr) {
403 in[0] = '\012';
404 shawrite(in, 1UL << 3, state);
405 }
406 XSRETURN(1);
407