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