File Coverage

SHA.xs
Criterion Covered Total %
statement 120 142 84.5
branch 75 102 73.5
condition n/a
subroutine n/a
pod n/a
total 195 244 79.9


line stmt bran cond sub pod time code
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              
48 868           static SHA *getSHA(pTHX_ SV *self)
49             {
50 868 50         if (!sv_isobject(self) || !sv_derived_from(self, "Digest::SHA"))
    50          
51 0           return(NULL);
52 868 50         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 18           Newxz(state, 1, SHA);
82 18 100         if (!shainit(state, alg)) {
83 1           Safefree(state);
84 1           XSRETURN_UNDEF;
85             }
86 17           RETVAL = newSV(0);
87 17           sv_setref_pv(RETVAL, classname, (void *) state);
88 17           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 11 50         if ((state = getSHA(aTHX_ self)) == NULL)
100 0           XSRETURN_UNDEF;
101 11           Newx(clone, 1, SHA);
102 11           RETVAL = newSV(0);
103 11           sv_setref_pv(RETVAL, sv_reftype(SvRV(self), 1), (void *) clone);
104 11           SvREADONLY_on(SvRV(RETVAL));
105 11           Copy(state, clone, 1, SHA);
106             OUTPUT:
107             RETVAL
108              
109             void
110             DESTROY(s)
111             SHA * s
112             CODE:
113 28           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 38 50         if (!shainit(&sha, ix2alg[ix]))
147 0           XSRETURN_UNDEF;
148 75 100         for (i = 0; i < items; i++) {
149 38 100         data = (UCHR *) (SvPVbyte(ST(i), len));
150 342 100         while (len > MAX_WRITE_SIZE) {
151 305           shawrite(data, MAX_WRITE_SIZE << 3, &sha);
152 305           data += MAX_WRITE_SIZE;
153 305           len -= MAX_WRITE_SIZE;
154             }
155 37           shawrite(data, (ULNG) len << 3, &sha);
156             }
157 37           shafinish(&sha);
158 37           len = 0;
159 37 100         if (ix % 3 == 0) {
160 1           result = (char *) shadigest(&sha);
161 1           len = sha.digestlen;
162             }
163 36 100         else if (ix % 3 == 1)
164 26           result = shahex(&sha);
165             else
166 10           result = shabase64(&sha);
167 37           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 43           UCHR *key = (UCHR *) "";
198             UCHR *data;
199 43           STRLEN len = 0;
200             HMAC hmac;
201             char *result;
202             CODE:
203 43 50         if (items > 0) {
204 43 50         key = (UCHR *) (SvPVbyte(ST(items-1), len));
205             }
206 43 50         if (hmacinit(&hmac, ix2alg[ix], key, (UINT) len) == NULL)
207 0           XSRETURN_UNDEF;
208 88 100         for (i = 0; i < items - 1; i++) {
209 45 50         data = (UCHR *) (SvPVbyte(ST(i), len));
210 45 50         while (len > MAX_WRITE_SIZE) {
211 0           hmacwrite(data, MAX_WRITE_SIZE << 3, &hmac);
212 0           data += MAX_WRITE_SIZE;
213 0           len -= MAX_WRITE_SIZE;
214             }
215 45           hmacwrite(data, (ULNG) len << 3, &hmac);
216             }
217 43           hmacfinish(&hmac);
218 43           len = 0;
219 43 100         if (ix % 3 == 0) {
220 23           result = (char *) hmacdigest(&hmac);
221 23           len = hmac.digestlen;
222             }
223 20 50         else if (ix % 3 == 1)
224 20           result = hmachex(&hmac);
225             else
226 0           result = hmacbase64(&hmac);
227 43           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 12 50         if ((state = getSHA(aTHX_ self)) == NULL)
241 0           XSRETURN_UNDEF;
242 12 50         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 15 50         if ((state = getSHA(aTHX_ self)) == NULL)
256 0           XSRETURN_UNDEF;
257 31 100         for (i = 1; i < items; i++) {
258 16 50         data = (UCHR *) (SvPVbyte(ST(i), len));
259 16 50         while (len > MAX_WRITE_SIZE) {
260 0           shawrite(data, MAX_WRITE_SIZE << 3, state);
261 0           data += MAX_WRITE_SIZE;
262 0           len -= MAX_WRITE_SIZE;
263             }
264 16           shawrite(data, (ULNG) len << 3, state);
265             }
266 15           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 61 50         if ((state = getSHA(aTHX_ self)) == NULL)
281 0           XSRETURN_UNDEF;
282 61           shafinish(state);
283 61           len = 0;
284 61 100         if (ix == 0) {
285 1           result = (char *) shadigest(state);
286 1           len = state->digestlen;
287             }
288 60 100         else if (ix == 1)
289 59           result = shahex(state);
290             else
291 1           result = shabase64(state);
292 61           RETVAL = newSVpv(result, len);
293 61           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 4           UCHR *ptr = buf;
304             CODE:
305 4 50         if ((state = getSHA(aTHX_ self)) == NULL)
306 0           XSRETURN_UNDEF;
307 4 100         Copy(digcpy(state), ptr, state->alg <= SHA256 ? 32 : 64, UCHR);
308 4 100         ptr += state->alg <= SHA256 ? 32 : 64;
309 4 100         Copy(state->block, ptr, state->alg <= SHA256 ? 64 : 128, UCHR);
310 4 100         ptr += state->alg <= SHA256 ? 64 : 128;
311 4           ptr = w32mem(ptr, state->blockcnt);
312 4           ptr = w32mem(ptr, state->lenhh);
313 4           ptr = w32mem(ptr, state->lenhl);
314 4           ptr = w32mem(ptr, state->lenlh);
315 4           ptr = w32mem(ptr, state->lenll);
316 4           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 11 50         if ((state = getSHA(aTHX_ self)) == NULL)
331 0           XSRETURN_UNDEF;
332 11 50         data = (UCHR *) SvPV(packed_state, len);
333 11 100         if (len != (state->alg <= SHA256 ? 116U : 212U))
    50          
334 0           XSRETURN_UNDEF;
335 11           data = statecpy(state, data);
336 11           Copy(data, state->block, state->blocksize >> 3, UCHR);
337 11           data += (state->blocksize >> 3);
338 11           bc = memw32(data), data += 4;
339 11 100         if (bc >= (state->alg <= SHA256 ? 512U : 1024U))
    50          
340 0           XSRETURN_UNDEF;
341 11           state->blockcnt = bc;
342 11           state->lenhh = memw32(data), data += 4;
343 11           state->lenhl = memw32(data), data += 4;
344 11           state->lenlh = memw32(data), data += 4;
345 11           state->lenll = memw32(data);
346 11           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 1 50         if (!f || (state = getSHA(aTHX_ self)) == NULL)
    50          
358 0           XSRETURN_UNDEF;
359 2 100         while ((n = (int) PerlIO_read(f, in, sizeof(in))) > 0)
360 1           shawrite(in, (ULNG) n << 3, state);
361 1           XSRETURN(1);
362              
363             void
364             _addfileuniv(self, f)
365             SV * self
366             PerlIO * f
367             PREINIT:
368             UCHR c;
369             int n;
370 1           int cr = 0;
371             UCHR *src, *dst;
372             UCHR in[IO_BUFFER_SIZE+1];
373             SHA *state;
374             PPCODE:
375 1 50         if (!f || (state = getSHA(aTHX_ self)) == NULL)
    50          
376 0           XSRETURN_UNDEF;
377 2 100         while ((n = (int) PerlIO_read(f, in+1, IO_BUFFER_SIZE)) > 0) {
378 28 100         for (dst = in, src = in + 1; n; n--) {
379 27           c = *src++;
380 27 100         if (!cr) {
381 23 100         if (c == '\015')
382 3           cr = 1;
383             else
384 23           *dst++ = c;
385             }
386             else {
387 4 100         if (c == '\015')
388 1           *dst++ = '\012';
389 3 100         else if (c == '\012') {
390 2           *dst++ = '\012';
391 2           cr = 0;
392             }
393             else {
394 1           *dst++ = '\012';
395 1           *dst++ = c;
396 1           cr = 0;
397             }
398             }
399             }
400 1           shawrite(in, (ULNG) (dst - in) << 3, state);
401             }
402 1 50         if (cr) {
403 0           in[0] = '\012';
404 0           shawrite(in, 1UL << 3, state);
405             }
406 1           XSRETURN(1);