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
T2tot2SpecialValuesTestT2tot2SpecialValuesTest34 
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 
testIdT2tot2SpecialValuesTest48 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 
testIdxIdT2tot2SpecialValuesTest59 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:
testKT2tot2SpecialValuesTest81 	Newxz(state, 1, SHA);
82 	if (!shainit(state, alg)) {
83 		Safefree(state);
84 		XSRETURN_UNDEF;
85 	}
86 	RETVAL = newSV(0);
__anon4ba8a3a90102() 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;
testK2T2tot2SpecialValuesTest97 	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
main()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