1#include "EXTERN.h"
2#include "perl.h"
3#include "XSUB.h"
4
5#include <src/sha.c>
6#include <src/hmac.c>
7
8static int ix2alg[] =
9	{1,1,1,224,224,224,256,256,256,384,384,384,512,512,512};
10
11MODULE = Digest::SHA		PACKAGE = Digest::SHA
12
13PROTOTYPES: ENABLE
14
15#include <src/sha.h>
16#include <src/hmac.h>
17
18#ifndef INT2PTR
19#define INT2PTR(p, i) (p) (i)
20#endif
21
22int
23shaclose(s)
24	SHA *	s
25
26int
27shadump(file, s)
28	char *	file
29	SHA *	s
30
31SHA *
32shadup(s)
33	SHA *	s
34
35SHA *
36shaload(file)
37	char *	file
38
39SHA *
40shaopen(alg)
41	int	alg
42
43void
44sharewind(s)
45	SHA *	s
46
47unsigned long
48shawrite(bitstr, bitcnt, s)
49	unsigned char *	bitstr
50	unsigned long	bitcnt
51	SHA *	s
52
53void
54sha1(...)
55ALIAS:
56	Digest::SHA::sha1 = 0
57	Digest::SHA::sha1_hex = 1
58	Digest::SHA::sha1_base64 = 2
59	Digest::SHA::sha224 = 3
60	Digest::SHA::sha224_hex = 4
61	Digest::SHA::sha224_base64 = 5
62	Digest::SHA::sha256 = 6
63	Digest::SHA::sha256_hex = 7
64	Digest::SHA::sha256_base64 = 8
65	Digest::SHA::sha384 = 9
66	Digest::SHA::sha384_hex = 10
67	Digest::SHA::sha384_base64 = 11
68	Digest::SHA::sha512 = 12
69	Digest::SHA::sha512_hex = 13
70	Digest::SHA::sha512_base64 = 14
71PREINIT:
72	int i;
73	unsigned char *data;
74	STRLEN len;
75	SHA *state;
76	char *result;
77PPCODE:
78	if ((state = shaopen(ix2alg[ix])) == NULL)
79		XSRETURN_UNDEF;
80	for (i = 0; i < items; i++) {
81		data = (unsigned char *) (SvPV(ST(i), len));
82		shawrite(data, len << 3, state);
83	}
84	shafinish(state);
85	len = 0;
86	if (ix % 3 == 0) {
87		result = (char *) shadigest(state);
88		len = shadsize(state);
89	}
90	else if (ix % 3 == 1)
91		result = shahex(state);
92	else
93		result = shabase64(state);
94	ST(0) = sv_2mortal(newSVpv(result, len));
95	shaclose(state);
96	XSRETURN(1);
97
98void
99hmac_sha1(...)
100ALIAS:
101	Digest::SHA::hmac_sha1 = 0
102	Digest::SHA::hmac_sha1_hex = 1
103	Digest::SHA::hmac_sha1_base64 = 2
104	Digest::SHA::hmac_sha224 = 3
105	Digest::SHA::hmac_sha224_hex = 4
106	Digest::SHA::hmac_sha224_base64 = 5
107	Digest::SHA::hmac_sha256 = 6
108	Digest::SHA::hmac_sha256_hex = 7
109	Digest::SHA::hmac_sha256_base64 = 8
110	Digest::SHA::hmac_sha384 = 9
111	Digest::SHA::hmac_sha384_hex = 10
112	Digest::SHA::hmac_sha384_base64 = 11
113	Digest::SHA::hmac_sha512 = 12
114	Digest::SHA::hmac_sha512_hex = 13
115	Digest::SHA::hmac_sha512_base64 = 14
116PREINIT:
117	int i;
118	unsigned char *key;
119	unsigned char *data;
120	STRLEN len;
121	HMAC *state;
122	char *result;
123PPCODE:
124	key = (unsigned char *) (SvPV(ST(items-1), len));
125	if ((state = hmacopen(ix2alg[ix], key, len)) == NULL)
126		XSRETURN_UNDEF;
127	for (i = 0; i < items - 1; i++) {
128		data = (unsigned char *) (SvPV(ST(i), len));
129		hmacwrite(data, len << 3, state);
130	}
131	hmacfinish(state);
132	len = 0;
133	if (ix % 3 == 0) {
134		result = (char *) hmacdigest(state);
135		len = shadsize(state->osha);
136	}
137	else if (ix % 3 == 1)
138		result = hmachex(state);
139	else
140		result = hmacbase64(state);
141	ST(0) = sv_2mortal(newSVpv(result, len));
142	hmacclose(state);
143	XSRETURN(1);
144
145void
146hashsize(self)
147	SV *	self
148ALIAS:
149	Digest::SHA::hashsize = 0
150	Digest::SHA::algorithm = 1
151PREINIT:
152	SHA *state;
153	int result;
154PPCODE:
155	state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
156	result = shadsize(state) << 3;
157	if (ix == 1 && result == 160)
158		result = 1;
159	ST(0) = sv_2mortal(newSViv(result));
160	XSRETURN(1);
161
162void
163add(self, ...)
164	SV *	self
165PREINIT:
166	int i;
167	unsigned char *data;
168	STRLEN len;
169	SHA *state;
170PPCODE:
171	state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
172	for (i = 1; i < items; i++) {
173		data = (unsigned char *) (SvPV(ST(i), len));
174		shawrite(data, len << 3, state);
175	}
176	XSRETURN(1);
177
178void
179digest(self)
180	SV *	self
181ALIAS:
182	Digest::SHA::digest = 0
183	Digest::SHA::Hexdigest = 1
184	Digest::SHA::B64digest = 2
185PREINIT:
186	STRLEN len;
187	SHA *state;
188	char *result;
189PPCODE:
190	state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
191	shafinish(state);
192	len = 0;
193	if (ix == 0) {
194		result = (char *) shadigest(state);
195		len = shadsize(state);
196	}
197	else if (ix == 1)
198		result = shahex(state);
199	else
200		result = shabase64(state);
201	ST(0) = sv_2mortal(newSVpv(result, len));
202	sharewind(state);
203	XSRETURN(1);
204