This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade Test-Simple from version 1.302073 to 1.302096
[perl5.git] / cpan / Digest-SHA / SHA.xs
CommitLineData
24278fc4 1#define PERL_NO_GET_CONTEXT
6bc89f92
SP
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
7720cfb2
CBW
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
ab2aaaf4
CBW
14#endif
15
24278fc4
CBW
16#ifndef dTHX
17 #define pTHX_
18 #define aTHX_
19#endif
20
207902b1
CBW
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
4eb6bdb8 35#include "src/sha.c"
6bc89f92 36
24278fc4 37static const int ix2alg[] =
65484cb9
CBW
38 {1,1,1,224,224,224,256,256,256,384,384,384,512,512,512,
39 512224,512224,512224,512256,512256,512256};
6bc89f92 40
747da336
RGS
41#ifndef INT2PTR
42#define INT2PTR(p, i) (p) (i)
43#endif
44
a0780036 45#define MAX_WRITE_SIZE 16384
207902b1 46#define IO_BUFFER_SIZE 4096
6bc89f92 47
24278fc4 48static SHA *getSHA(pTHX_ SV *self)
207902b1
CBW
49{
50 if (!sv_isobject(self) || !sv_derived_from(self, "Digest::SHA"))
51 return(NULL);
52 return INT2PTR(SHA *, SvIV(SvRV(self)));
53}
c2de4d02 54
207902b1
CBW
55MODULE = Digest::SHA PACKAGE = Digest::SHA
56
57PROTOTYPES: ENABLE
c2de4d02 58
207902b1
CBW
59int
60shainit(s, alg)
61 SHA * s
6bc89f92
SP
62 int alg
63
64void
65sharewind(s)
66 SHA * s
67
68unsigned long
69shawrite(bitstr, bitcnt, s)
70 unsigned char * bitstr
71 unsigned long bitcnt
72 SHA * s
73
207902b1
CBW
74SV *
75newSHA(classname, alg)
76 char * classname
77 int alg
78PREINIT:
79 SHA *state;
80CODE:
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));
89OUTPUT:
90 RETVAL
91
92SV *
93clone(self)
94 SV * self
95PREINIT:
96 SHA *state;
97 SHA *clone;
98CODE:
24278fc4 99 if ((state = getSHA(aTHX_ self)) == NULL)
207902b1
CBW
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);
106OUTPUT:
107 RETVAL
108
6bc89f92 109void
207902b1
CBW
110DESTROY(s)
111 SHA * s
112CODE:
113 Safefree(s);
114
115SV *
6bc89f92
SP
116sha1(...)
117ALIAS:
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
65484cb9
CBW
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
6bc89f92
SP
139PREINIT:
140 int i;
7123ec76 141 UCHR *data;
6bc89f92 142 STRLEN len;
207902b1 143 SHA sha;
6bc89f92 144 char *result;
207902b1
CBW
145CODE:
146 if (!shainit(&sha, ix2alg[ix]))
6bc89f92
SP
147 XSRETURN_UNDEF;
148 for (i = 0; i < items; i++) {
7123ec76 149 data = (UCHR *) (SvPVbyte(ST(i), len));
a0780036 150 while (len > MAX_WRITE_SIZE) {
207902b1 151 shawrite(data, MAX_WRITE_SIZE << 3, &sha);
a0780036
CBW
152 data += MAX_WRITE_SIZE;
153 len -= MAX_WRITE_SIZE;
154 }
207902b1 155 shawrite(data, len << 3, &sha);
6bc89f92 156 }
207902b1 157 shafinish(&sha);
6bc89f92
SP
158 len = 0;
159 if (ix % 3 == 0) {
207902b1
CBW
160 result = (char *) shadigest(&sha);
161 len = sha.digestlen;
6bc89f92
SP
162 }
163 else if (ix % 3 == 1)
207902b1 164 result = shahex(&sha);
6bc89f92 165 else
207902b1
CBW
166 result = shabase64(&sha);
167 RETVAL = newSVpv(result, len);
168OUTPUT:
169 RETVAL
6bc89f92 170
207902b1 171SV *
6bc89f92
SP
172hmac_sha1(...)
173ALIAS:
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
65484cb9
CBW
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
6bc89f92
SP
195PREINIT:
196 int i;
207902b1 197 UCHR *key = (UCHR *) "";
7123ec76 198 UCHR *data;
207902b1
CBW
199 STRLEN len = 0;
200 HMAC hmac;
6bc89f92 201 char *result;
207902b1
CBW
202CODE:
203 if (items > 0) {
204 key = (UCHR *) (SvPVbyte(ST(items-1), len));
205 }
206 if (hmacinit(&hmac, ix2alg[ix], key, len) == NULL)
6bc89f92
SP
207 XSRETURN_UNDEF;
208 for (i = 0; i < items - 1; i++) {
7123ec76 209 data = (UCHR *) (SvPVbyte(ST(i), len));
a0780036 210 while (len > MAX_WRITE_SIZE) {
207902b1 211 hmacwrite(data, MAX_WRITE_SIZE << 3, &hmac);
a0780036
CBW
212 data += MAX_WRITE_SIZE;
213 len -= MAX_WRITE_SIZE;
214 }
207902b1 215 hmacwrite(data, len << 3, &hmac);
6bc89f92 216 }
207902b1 217 hmacfinish(&hmac);
6bc89f92
SP
218 len = 0;
219 if (ix % 3 == 0) {
207902b1
CBW
220 result = (char *) hmacdigest(&hmac);
221 len = hmac.digestlen;
6bc89f92
SP
222 }
223 else if (ix % 3 == 1)
207902b1 224 result = hmachex(&hmac);
6bc89f92 225 else
207902b1
CBW
226 result = hmacbase64(&hmac);
227 RETVAL = newSVpv(result, len);
228OUTPUT:
229 RETVAL
6bc89f92 230
207902b1 231int
6bc89f92
SP
232hashsize(self)
233 SV * self
234ALIAS:
235 Digest::SHA::hashsize = 0
236 Digest::SHA::algorithm = 1
237PREINIT:
238 SHA *state;
207902b1 239CODE:
24278fc4 240 if ((state = getSHA(aTHX_ self)) == NULL)
7123ec76 241 XSRETURN_UNDEF;
03c6205f 242 RETVAL = ix ? state->alg : (int) (state->digestlen << 3);
207902b1
CBW
243OUTPUT:
244 RETVAL
6bc89f92
SP
245
246void
247add(self, ...)
248 SV * self
249PREINIT:
250 int i;
7123ec76 251 UCHR *data;
6bc89f92
SP
252 STRLEN len;
253 SHA *state;
254PPCODE:
24278fc4 255 if ((state = getSHA(aTHX_ self)) == NULL)
7123ec76 256 XSRETURN_UNDEF;
6bc89f92 257 for (i = 1; i < items; i++) {
7123ec76 258 data = (UCHR *) (SvPVbyte(ST(i), len));
a0780036
CBW
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 }
6bc89f92
SP
264 shawrite(data, len << 3, state);
265 }
266 XSRETURN(1);
267
207902b1 268SV *
6bc89f92
SP
269digest(self)
270 SV * self
271ALIAS:
272 Digest::SHA::digest = 0
207902b1
CBW
273 Digest::SHA::hexdigest = 1
274 Digest::SHA::b64digest = 2
6bc89f92
SP
275PREINIT:
276 STRLEN len;
277 SHA *state;
278 char *result;
207902b1 279CODE:
24278fc4 280 if ((state = getSHA(aTHX_ self)) == NULL)
7123ec76 281 XSRETURN_UNDEF;
6bc89f92
SP
282 shafinish(state);
283 len = 0;
284 if (ix == 0) {
207902b1 285 result = (char *) shadigest(state);
7123ec76 286 len = state->digestlen;
6bc89f92
SP
287 }
288 else if (ix == 1)
289 result = shahex(state);
290 else
291 result = shabase64(state);
207902b1 292 RETVAL = newSVpv(result, len);
6bc89f92 293 sharewind(state);
207902b1
CBW
294OUTPUT:
295 RETVAL
7123ec76 296
207902b1 297SV *
7123ec76
SH
298_getstate(self)
299 SV * self
300PREINIT:
301 SHA *state;
302 UCHR buf[256];
303 UCHR *ptr = buf;
207902b1 304CODE:
24278fc4 305 if ((state = getSHA(aTHX_ self)) == NULL)
7123ec76 306 XSRETURN_UNDEF;
207902b1 307 Copy(digcpy(state), ptr, state->alg <= SHA256 ? 32 : 64, UCHR);
7123ec76 308 ptr += state->alg <= SHA256 ? 32 : 64;
207902b1 309 Copy(state->block, ptr, state->alg <= SHA256 ? 64 : 128, UCHR);
7123ec76
SH
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);
03c6205f 316 RETVAL = newSVpv((char *) buf, (STRLEN) (ptr - buf));
207902b1
CBW
317OUTPUT:
318 RETVAL
7123ec76
SH
319
320void
207902b1 321_putstate(self, packed_state)
7123ec76 322 SV * self
207902b1 323 SV * packed_state
7123ec76
SH
324PREINIT:
325 UINT bc;
326 STRLEN len;
327 SHA *state;
328 UCHR *data;
329PPCODE:
24278fc4 330 if ((state = getSHA(aTHX_ self)) == NULL)
7123ec76 331 XSRETURN_UNDEF;
207902b1 332 data = (UCHR *) SvPV(packed_state, len);
03c6205f 333 if (len != (state->alg <= SHA256 ? 116U : 212U))
7123ec76
SH
334 XSRETURN_UNDEF;
335 data = statecpy(state, data);
207902b1 336 Copy(data, state->block, state->blocksize >> 3, UCHR);
7123ec76
SH
337 data += (state->blocksize >> 3);
338 bc = memw32(data), data += 4;
207902b1 339 if (bc >= (state->alg <= SHA256 ? 512U : 1024U))
7123ec76
SH
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);
207902b1
CBW
347
348void
349_addfilebin(self, f)
350 SV * self
351 PerlIO * f
352PREINIT:
353 SHA *state;
354 int n;
355 UCHR in[IO_BUFFER_SIZE];
356PPCODE:
24278fc4 357 if (!f || (state = getSHA(aTHX_ self)) == NULL)
207902b1
CBW
358 XSRETURN_UNDEF;
359 while ((n = PerlIO_read(f, in, sizeof(in))) > 0)
03c6205f 360 shawrite(in, (ULNG) n << 3, state);
207902b1
CBW
361 XSRETURN(1);
362
363void
364_addfileuniv(self, f)
365 SV * self
366 PerlIO * f
367PREINIT:
03c6205f 368 UCHR c;
207902b1
CBW
369 int n;
370 int cr = 0;
371 UCHR *src, *dst;
372 UCHR in[IO_BUFFER_SIZE+1];
373 SHA *state;
374PPCODE:
24278fc4 375 if (!f || (state = getSHA(aTHX_ self)) == NULL)
207902b1
CBW
376 XSRETURN_UNDEF;
377 while ((n = 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 }
03c6205f 400 shawrite(in, (ULNG) (dst - in) << 3, state);
207902b1
CBW
401 }
402 if (cr) {
403 in[0] = '\012';
404 shawrite(in, 1 << 3, state);
405 }
406 XSRETURN(1);