Blame SHA.xs

Packit fa4fcc
#define PERL_NO_GET_CONTEXT
Packit fa4fcc
#include "EXTERN.h"
Packit fa4fcc
#include "perl.h"
Packit fa4fcc
#include "XSUB.h"
Packit fa4fcc
Packit fa4fcc
#ifdef SvPVbyte
Packit fa4fcc
	#if PERL_REVISION == 5 && PERL_VERSION < 8
Packit fa4fcc
		#undef SvPVbyte
Packit fa4fcc
		#define SvPVbyte(sv, lp) \
Packit fa4fcc
			(sv_utf8_downgrade((sv), 0), SvPV((sv), (lp)))
Packit fa4fcc
	#endif
Packit fa4fcc
#else
Packit fa4fcc
	#define SvPVbyte SvPV
Packit fa4fcc
#endif
Packit fa4fcc
Packit fa4fcc
#ifndef dTHX
Packit fa4fcc
	#define pTHX_
Packit fa4fcc
	#define aTHX_
Packit fa4fcc
#endif
Packit fa4fcc
Packit fa4fcc
#ifndef PerlIO
Packit fa4fcc
	#define PerlIO				FILE
Packit fa4fcc
	#define PerlIO_read(f, buf, count)	fread(buf, 1, count, f)
Packit fa4fcc
#endif
Packit fa4fcc
Packit fa4fcc
#ifndef sv_derived_from
Packit fa4fcc
	#include "src/sdf.c"
Packit fa4fcc
#endif
Packit fa4fcc
Packit fa4fcc
#ifndef Newx
Packit fa4fcc
	#define Newx(ptr, num, type)	New(0, ptr, num, type)
Packit fa4fcc
	#define Newxz(ptr, num, type)	Newz(0, ptr, num, type)
Packit fa4fcc
#endif
Packit fa4fcc
Packit fa4fcc
#include "src/sha.c"
Packit fa4fcc
Packit fa4fcc
static const int ix2alg[] =
Packit fa4fcc
	{1,1,1,224,224,224,256,256,256,384,384,384,512,512,512,
Packit fa4fcc
	512224,512224,512224,512256,512256,512256};
Packit fa4fcc
Packit fa4fcc
#ifndef INT2PTR
Packit fa4fcc
#define INT2PTR(p, i) (p) (i)
Packit fa4fcc
#endif
Packit fa4fcc
Packit fa4fcc
#define MAX_WRITE_SIZE 16384
Packit fa4fcc
#define IO_BUFFER_SIZE 4096
Packit fa4fcc
Packit fa4fcc
static SHA *getSHA(pTHX_ SV *self)
Packit fa4fcc
{
Packit fa4fcc
	if (!sv_isobject(self) || !sv_derived_from(self, "Digest::SHA"))
Packit fa4fcc
		return(NULL);
Packit fa4fcc
	return INT2PTR(SHA *, SvIV(SvRV(self)));
Packit fa4fcc
}
Packit fa4fcc
Packit fa4fcc
MODULE = Digest::SHA		PACKAGE = Digest::SHA
Packit fa4fcc
Packit fa4fcc
PROTOTYPES: ENABLE
Packit fa4fcc
Packit fa4fcc
int
Packit fa4fcc
shainit(s, alg)
Packit fa4fcc
	SHA *	s
Packit fa4fcc
	int	alg
Packit fa4fcc
Packit fa4fcc
void
Packit fa4fcc
sharewind(s)
Packit fa4fcc
	SHA *	s
Packit fa4fcc
Packit fa4fcc
unsigned long
Packit fa4fcc
shawrite(bitstr, bitcnt, s)
Packit fa4fcc
	unsigned char *	bitstr
Packit fa4fcc
	unsigned long	bitcnt
Packit fa4fcc
	SHA *	s
Packit fa4fcc
Packit fa4fcc
SV *
Packit fa4fcc
newSHA(classname, alg)
Packit fa4fcc
	char *	classname
Packit fa4fcc
	int 	alg
Packit fa4fcc
PREINIT:
Packit fa4fcc
	SHA *state;
Packit fa4fcc
CODE:
Packit fa4fcc
	Newxz(state, 1, SHA);
Packit fa4fcc
	if (!shainit(state, alg)) {
Packit fa4fcc
		Safefree(state);
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	}
Packit fa4fcc
	RETVAL = newSV(0);
Packit fa4fcc
	sv_setref_pv(RETVAL, classname, (void *) state);
Packit fa4fcc
	SvREADONLY_on(SvRV(RETVAL));
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
SV *
Packit fa4fcc
clone(self)
Packit fa4fcc
	SV *	self
Packit fa4fcc
PREINIT:
Packit fa4fcc
	SHA *state;
Packit fa4fcc
	SHA *clone;
Packit fa4fcc
CODE:
Packit fa4fcc
	if ((state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	Newx(clone, 1, SHA);
Packit fa4fcc
	RETVAL = newSV(0);
Packit fa4fcc
	sv_setref_pv(RETVAL, sv_reftype(SvRV(self), 1), (void *) clone);
Packit fa4fcc
	SvREADONLY_on(SvRV(RETVAL));
Packit fa4fcc
	Copy(state, clone, 1, SHA);
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
void
Packit fa4fcc
DESTROY(s)
Packit fa4fcc
	SHA *	s
Packit fa4fcc
CODE:
Packit fa4fcc
	Safefree(s);
Packit fa4fcc
Packit fa4fcc
SV *
Packit fa4fcc
sha1(...)
Packit fa4fcc
ALIAS:
Packit fa4fcc
	Digest::SHA::sha1 = 0
Packit fa4fcc
	Digest::SHA::sha1_hex = 1
Packit fa4fcc
	Digest::SHA::sha1_base64 = 2
Packit fa4fcc
	Digest::SHA::sha224 = 3
Packit fa4fcc
	Digest::SHA::sha224_hex = 4
Packit fa4fcc
	Digest::SHA::sha224_base64 = 5
Packit fa4fcc
	Digest::SHA::sha256 = 6
Packit fa4fcc
	Digest::SHA::sha256_hex = 7
Packit fa4fcc
	Digest::SHA::sha256_base64 = 8
Packit fa4fcc
	Digest::SHA::sha384 = 9
Packit fa4fcc
	Digest::SHA::sha384_hex = 10
Packit fa4fcc
	Digest::SHA::sha384_base64 = 11
Packit fa4fcc
	Digest::SHA::sha512 = 12
Packit fa4fcc
	Digest::SHA::sha512_hex = 13
Packit fa4fcc
	Digest::SHA::sha512_base64 = 14
Packit fa4fcc
	Digest::SHA::sha512224 = 15
Packit fa4fcc
	Digest::SHA::sha512224_hex = 16
Packit fa4fcc
	Digest::SHA::sha512224_base64 = 17
Packit fa4fcc
	Digest::SHA::sha512256 = 18
Packit fa4fcc
	Digest::SHA::sha512256_hex = 19
Packit fa4fcc
	Digest::SHA::sha512256_base64 = 20
Packit fa4fcc
PREINIT:
Packit fa4fcc
	int i;
Packit fa4fcc
	UCHR *data;
Packit fa4fcc
	STRLEN len;
Packit fa4fcc
	SHA sha;
Packit fa4fcc
	char *result;
Packit fa4fcc
CODE:
Packit fa4fcc
	if (!shainit(&sha, ix2alg[ix]))
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	for (i = 0; i < items; i++) {
Packit fa4fcc
		data = (UCHR *) (SvPVbyte(ST(i), len));
Packit fa4fcc
		while (len > MAX_WRITE_SIZE) {
Packit fa4fcc
			shawrite(data, MAX_WRITE_SIZE << 3, &sha);
Packit fa4fcc
			data += MAX_WRITE_SIZE;
Packit fa4fcc
			len  -= MAX_WRITE_SIZE;
Packit fa4fcc
		}
Packit fa4fcc
		shawrite(data, (ULNG) len << 3, &sha);
Packit fa4fcc
	}
Packit fa4fcc
	shafinish(&sha);
Packit fa4fcc
	len = 0;
Packit fa4fcc
	if (ix % 3 == 0) {
Packit fa4fcc
		result = (char *) shadigest(&sha);
Packit fa4fcc
		len = sha.digestlen;
Packit fa4fcc
	}
Packit fa4fcc
	else if (ix % 3 == 1)
Packit fa4fcc
		result = shahex(&sha);
Packit fa4fcc
	else
Packit fa4fcc
		result = shabase64(&sha);
Packit fa4fcc
	RETVAL = newSVpv(result, len);
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
SV *
Packit fa4fcc
hmac_sha1(...)
Packit fa4fcc
ALIAS:
Packit fa4fcc
	Digest::SHA::hmac_sha1 = 0
Packit fa4fcc
	Digest::SHA::hmac_sha1_hex = 1
Packit fa4fcc
	Digest::SHA::hmac_sha1_base64 = 2
Packit fa4fcc
	Digest::SHA::hmac_sha224 = 3
Packit fa4fcc
	Digest::SHA::hmac_sha224_hex = 4
Packit fa4fcc
	Digest::SHA::hmac_sha224_base64 = 5
Packit fa4fcc
	Digest::SHA::hmac_sha256 = 6
Packit fa4fcc
	Digest::SHA::hmac_sha256_hex = 7
Packit fa4fcc
	Digest::SHA::hmac_sha256_base64 = 8
Packit fa4fcc
	Digest::SHA::hmac_sha384 = 9
Packit fa4fcc
	Digest::SHA::hmac_sha384_hex = 10
Packit fa4fcc
	Digest::SHA::hmac_sha384_base64 = 11
Packit fa4fcc
	Digest::SHA::hmac_sha512 = 12
Packit fa4fcc
	Digest::SHA::hmac_sha512_hex = 13
Packit fa4fcc
	Digest::SHA::hmac_sha512_base64 = 14
Packit fa4fcc
	Digest::SHA::hmac_sha512224 = 15
Packit fa4fcc
	Digest::SHA::hmac_sha512224_hex = 16
Packit fa4fcc
	Digest::SHA::hmac_sha512224_base64 = 17
Packit fa4fcc
	Digest::SHA::hmac_sha512256 = 18
Packit fa4fcc
	Digest::SHA::hmac_sha512256_hex = 19
Packit fa4fcc
	Digest::SHA::hmac_sha512256_base64 = 20
Packit fa4fcc
PREINIT:
Packit fa4fcc
	int i;
Packit fa4fcc
	UCHR *key = (UCHR *) "";
Packit fa4fcc
	UCHR *data;
Packit fa4fcc
	STRLEN len = 0;
Packit fa4fcc
	HMAC hmac;
Packit fa4fcc
	char *result;
Packit fa4fcc
CODE:
Packit fa4fcc
	if (items > 0) {
Packit fa4fcc
		key = (UCHR *) (SvPVbyte(ST(items-1), len));
Packit fa4fcc
	}
Packit fa4fcc
	if (hmacinit(&hmac, ix2alg[ix], key, (UINT) len) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	for (i = 0; i < items - 1; i++) {
Packit fa4fcc
		data = (UCHR *) (SvPVbyte(ST(i), len));
Packit fa4fcc
		while (len > MAX_WRITE_SIZE) {
Packit fa4fcc
			hmacwrite(data, MAX_WRITE_SIZE << 3, &hmac);
Packit fa4fcc
			data += MAX_WRITE_SIZE;
Packit fa4fcc
			len  -= MAX_WRITE_SIZE;
Packit fa4fcc
		}
Packit fa4fcc
		hmacwrite(data, (ULNG) len << 3, &hmac);
Packit fa4fcc
	}
Packit fa4fcc
	hmacfinish(&hmac);
Packit fa4fcc
	len = 0;
Packit fa4fcc
	if (ix % 3 == 0) {
Packit fa4fcc
		result = (char *) hmacdigest(&hmac);
Packit fa4fcc
		len = hmac.digestlen;
Packit fa4fcc
	}
Packit fa4fcc
	else if (ix % 3 == 1)
Packit fa4fcc
		result = hmachex(&hmac);
Packit fa4fcc
	else
Packit fa4fcc
		result = hmacbase64(&hmac);
Packit fa4fcc
	RETVAL = newSVpv(result, len);
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
int
Packit fa4fcc
hashsize(self)
Packit fa4fcc
	SV *	self
Packit fa4fcc
ALIAS:
Packit fa4fcc
	Digest::SHA::hashsize = 0
Packit fa4fcc
	Digest::SHA::algorithm = 1
Packit fa4fcc
PREINIT:
Packit fa4fcc
	SHA *state;
Packit fa4fcc
CODE:
Packit fa4fcc
	if ((state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	RETVAL = ix ? state->alg : (int) (state->digestlen << 3);
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
void
Packit fa4fcc
add(self, ...)
Packit fa4fcc
	SV *	self
Packit fa4fcc
PREINIT:
Packit fa4fcc
	int i;
Packit fa4fcc
	UCHR *data;
Packit fa4fcc
	STRLEN len;
Packit fa4fcc
	SHA *state;
Packit fa4fcc
PPCODE:
Packit fa4fcc
	if ((state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	for (i = 1; i < items; i++) {
Packit fa4fcc
		data = (UCHR *) (SvPVbyte(ST(i), len));
Packit fa4fcc
		while (len > MAX_WRITE_SIZE) {
Packit fa4fcc
			shawrite(data, MAX_WRITE_SIZE << 3, state);
Packit fa4fcc
			data += MAX_WRITE_SIZE;
Packit fa4fcc
			len  -= MAX_WRITE_SIZE;
Packit fa4fcc
		}
Packit fa4fcc
		shawrite(data, (ULNG) len << 3, state);
Packit fa4fcc
	}
Packit fa4fcc
	XSRETURN(1);
Packit fa4fcc
Packit fa4fcc
SV *
Packit fa4fcc
digest(self)
Packit fa4fcc
	SV *	self
Packit fa4fcc
ALIAS:
Packit fa4fcc
	Digest::SHA::digest = 0
Packit fa4fcc
	Digest::SHA::hexdigest = 1
Packit fa4fcc
	Digest::SHA::b64digest = 2
Packit fa4fcc
PREINIT:
Packit fa4fcc
	STRLEN len;
Packit fa4fcc
	SHA *state;
Packit fa4fcc
	char *result;
Packit fa4fcc
CODE:
Packit fa4fcc
	if ((state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	shafinish(state);
Packit fa4fcc
	len = 0;
Packit fa4fcc
	if (ix == 0) {
Packit fa4fcc
		result = (char *) shadigest(state);
Packit fa4fcc
		len = state->digestlen;
Packit fa4fcc
	}
Packit fa4fcc
	else if (ix == 1)
Packit fa4fcc
		result = shahex(state);
Packit fa4fcc
	else
Packit fa4fcc
		result = shabase64(state);
Packit fa4fcc
	RETVAL = newSVpv(result, len);
Packit fa4fcc
	sharewind(state);
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
SV *
Packit fa4fcc
_getstate(self)
Packit fa4fcc
	SV *	self
Packit fa4fcc
PREINIT:
Packit fa4fcc
	SHA *state;
Packit fa4fcc
	UCHR buf[256];
Packit fa4fcc
	UCHR *ptr = buf;
Packit fa4fcc
CODE:
Packit fa4fcc
	if ((state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	Copy(digcpy(state), ptr, state->alg <= SHA256 ? 32 : 64, UCHR);
Packit fa4fcc
	ptr += state->alg <= SHA256 ? 32 : 64;
Packit fa4fcc
	Copy(state->block, ptr, state->alg <= SHA256 ? 64 : 128, UCHR);
Packit fa4fcc
	ptr += state->alg <= SHA256 ? 64 : 128;
Packit fa4fcc
	ptr = w32mem(ptr, state->blockcnt);
Packit fa4fcc
	ptr = w32mem(ptr, state->lenhh);
Packit fa4fcc
	ptr = w32mem(ptr, state->lenhl);
Packit fa4fcc
	ptr = w32mem(ptr, state->lenlh);
Packit fa4fcc
	ptr = w32mem(ptr, state->lenll);
Packit fa4fcc
	RETVAL = newSVpv((char *) buf, (STRLEN) (ptr - buf));
Packit fa4fcc
OUTPUT:
Packit fa4fcc
	RETVAL
Packit fa4fcc
Packit fa4fcc
void
Packit fa4fcc
_putstate(self, packed_state)
Packit fa4fcc
	SV *	self
Packit fa4fcc
	SV *	packed_state
Packit fa4fcc
PREINIT:
Packit fa4fcc
	UINT bc;
Packit fa4fcc
	STRLEN len;
Packit fa4fcc
	SHA *state;
Packit fa4fcc
	UCHR *data;
Packit fa4fcc
PPCODE:
Packit fa4fcc
	if ((state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	data = (UCHR *) SvPV(packed_state, len);
Packit fa4fcc
	if (len != (state->alg <= SHA256 ? 116U : 212U))
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	data = statecpy(state, data);
Packit fa4fcc
	Copy(data, state->block, state->blocksize >> 3, UCHR);
Packit fa4fcc
	data += (state->blocksize >> 3);
Packit fa4fcc
	bc = memw32(data), data += 4;
Packit fa4fcc
	if (bc >= (state->alg <= SHA256 ? 512U : 1024U))
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	state->blockcnt = bc;
Packit fa4fcc
	state->lenhh = memw32(data), data += 4;
Packit fa4fcc
	state->lenhl = memw32(data), data += 4;
Packit fa4fcc
	state->lenlh = memw32(data), data += 4;
Packit fa4fcc
	state->lenll = memw32(data);
Packit fa4fcc
	XSRETURN(1);
Packit fa4fcc
Packit fa4fcc
void
Packit fa4fcc
_addfilebin(self, f)
Packit fa4fcc
	SV *		self
Packit fa4fcc
	PerlIO *	f
Packit fa4fcc
PREINIT:
Packit fa4fcc
	SHA *state;
Packit fa4fcc
	int n;
Packit fa4fcc
	UCHR in[IO_BUFFER_SIZE];
Packit fa4fcc
PPCODE:
Packit fa4fcc
	if (!f || (state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	while ((n = (int) PerlIO_read(f, in, sizeof(in))) > 0)
Packit fa4fcc
		shawrite(in, (ULNG) n << 3, state);
Packit fa4fcc
	XSRETURN(1);
Packit fa4fcc
Packit fa4fcc
void
Packit fa4fcc
_addfileuniv(self, f)
Packit fa4fcc
	SV *		self
Packit fa4fcc
	PerlIO *	f
Packit fa4fcc
PREINIT:
Packit fa4fcc
	UCHR c;
Packit fa4fcc
	int n;
Packit fa4fcc
	int cr = 0;
Packit fa4fcc
	UCHR *src, *dst;
Packit fa4fcc
	UCHR in[IO_BUFFER_SIZE+1];
Packit fa4fcc
	SHA *state;
Packit fa4fcc
PPCODE:
Packit fa4fcc
	if (!f || (state = getSHA(aTHX_ self)) == NULL)
Packit fa4fcc
		XSRETURN_UNDEF;
Packit fa4fcc
	while ((n = (int) PerlIO_read(f, in+1, IO_BUFFER_SIZE)) > 0) {
Packit fa4fcc
		for (dst = in, src = in + 1; n; n--) {
Packit fa4fcc
			c = *src++;
Packit fa4fcc
			if (!cr) {
Packit fa4fcc
				if (c == '\015')
Packit fa4fcc
					cr = 1;
Packit fa4fcc
				else
Packit fa4fcc
					*dst++ = c;
Packit fa4fcc
			}
Packit fa4fcc
			else {
Packit fa4fcc
				if (c == '\015')
Packit fa4fcc
					*dst++ = '\012';
Packit fa4fcc
				else if (c == '\012') {
Packit fa4fcc
					*dst++ = '\012';
Packit fa4fcc
					cr = 0;
Packit fa4fcc
				}
Packit fa4fcc
				else {
Packit fa4fcc
					*dst++ = '\012';
Packit fa4fcc
					*dst++ = c;
Packit fa4fcc
					cr = 0;
Packit fa4fcc
				}
Packit fa4fcc
			}
Packit fa4fcc
		}
Packit fa4fcc
		shawrite(in, (ULNG) (dst - in) << 3, state);
Packit fa4fcc
	}
Packit fa4fcc
	if (cr) {
Packit fa4fcc
		in[0] = '\012';
Packit fa4fcc
		shawrite(in, 1UL << 3, state);
Packit fa4fcc
	}
Packit fa4fcc
	XSRETURN(1);