Commit | Line | Data |
---|---|---|
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 | 37 | static 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 | 48 | static 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 |
55 | MODULE = Digest::SHA PACKAGE = Digest::SHA |
56 | ||
57 | PROTOTYPES: ENABLE | |
c2de4d02 | 58 | |
207902b1 CBW |
59 | int |
60 | shainit(s, alg) | |
61 | SHA * s | |
6bc89f92 SP |
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 | ||
207902b1 CBW |
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: | |
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); | |
106 | OUTPUT: | |
107 | RETVAL | |
108 | ||
6bc89f92 | 109 | void |
207902b1 CBW |
110 | DESTROY(s) |
111 | SHA * s | |
112 | CODE: | |
113 | Safefree(s); | |
114 | ||
115 | SV * | |
6bc89f92 SP |
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 | |
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 |
139 | PREINIT: |
140 | int i; | |
7123ec76 | 141 | UCHR *data; |
6bc89f92 | 142 | STRLEN len; |
207902b1 | 143 | SHA sha; |
6bc89f92 | 144 | char *result; |
207902b1 CBW |
145 | CODE: |
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); | |
168 | OUTPUT: | |
169 | RETVAL | |
6bc89f92 | 170 | |
207902b1 | 171 | SV * |
6bc89f92 SP |
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 | |
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 |
195 | PREINIT: |
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 |
202 | CODE: |
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); | |
228 | OUTPUT: | |
229 | RETVAL | |
6bc89f92 | 230 | |
207902b1 | 231 | int |
6bc89f92 SP |
232 | hashsize(self) |
233 | SV * self | |
234 | ALIAS: | |
235 | Digest::SHA::hashsize = 0 | |
236 | Digest::SHA::algorithm = 1 | |
237 | PREINIT: | |
238 | SHA *state; | |
207902b1 | 239 | CODE: |
24278fc4 | 240 | if ((state = getSHA(aTHX_ self)) == NULL) |
7123ec76 | 241 | XSRETURN_UNDEF; |
03c6205f | 242 | RETVAL = ix ? state->alg : (int) (state->digestlen << 3); |
207902b1 CBW |
243 | OUTPUT: |
244 | RETVAL | |
6bc89f92 SP |
245 | |
246 | void | |
247 | add(self, ...) | |
248 | SV * self | |
249 | PREINIT: | |
250 | int i; | |
7123ec76 | 251 | UCHR *data; |
6bc89f92 SP |
252 | STRLEN len; |
253 | SHA *state; | |
254 | PPCODE: | |
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 | 268 | SV * |
6bc89f92 SP |
269 | digest(self) |
270 | SV * self | |
271 | ALIAS: | |
272 | Digest::SHA::digest = 0 | |
207902b1 CBW |
273 | Digest::SHA::hexdigest = 1 |
274 | Digest::SHA::b64digest = 2 | |
6bc89f92 SP |
275 | PREINIT: |
276 | STRLEN len; | |
277 | SHA *state; | |
278 | char *result; | |
207902b1 | 279 | CODE: |
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 |
294 | OUTPUT: |
295 | RETVAL | |
7123ec76 | 296 | |
207902b1 | 297 | SV * |
7123ec76 SH |
298 | _getstate(self) |
299 | SV * self | |
300 | PREINIT: | |
301 | SHA *state; | |
302 | UCHR buf[256]; | |
303 | UCHR *ptr = buf; | |
207902b1 | 304 | CODE: |
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 |
317 | OUTPUT: |
318 | RETVAL | |
7123ec76 SH |
319 | |
320 | void | |
207902b1 | 321 | _putstate(self, packed_state) |
7123ec76 | 322 | SV * self |
207902b1 | 323 | SV * packed_state |
7123ec76 SH |
324 | PREINIT: |
325 | UINT bc; | |
326 | STRLEN len; | |
327 | SHA *state; | |
328 | UCHR *data; | |
329 | PPCODE: | |
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 | |
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: | |
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 | ||
363 | void | |
364 | _addfileuniv(self, f) | |
365 | SV * self | |
366 | PerlIO * f | |
367 | PREINIT: | |
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; | |
374 | PPCODE: | |
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); |