File Coverage

inc/CryptX_AuthEnc_EAX.xs.inc
Criterion Covered Total %
statement 115 133 86.4
branch 67 216 31.0
condition n/a
subroutine n/a
pod n/a
total 182 349 52.1


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::AuthEnc::EAX
2              
3             PROTOTYPES: DISABLE
4              
5             Crypt::AuthEnc::EAX
6             new(Class, char * cipher_name, SV * key, SV * nonce, SV * adata=&PL_sv_undef)
7             CODE:
8             {
9 20           STRLEN k_len=0;
10 20           unsigned char *k=NULL;
11 20           unsigned char *n=NULL;
12 20           STRLEN n_len=0;
13 20           unsigned char *h=NULL;
14 20           STRLEN h_len=0;
15             int rv, id;
16              
17 20 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
18 20           k = (unsigned char *) SvPVbyte(key, k_len);
19 20 50         if (!SvPOK_spec(nonce)) croak("FATAL: nonce must be string/buffer scalar");
    50          
    0          
    0          
    0          
20 20           n = (unsigned char *) SvPVbyte(nonce, n_len);
21 20 50         if (SvOK(adata)) { /* adata is optional param */
22 0 0         if (!SvPOK_spec(adata)) croak("FATAL: adata must be string/buffer scalar");
    0          
    0          
    0          
    0          
23 0           h = (unsigned char *) SvPVbyte(adata, h_len);
24             }
25              
26 20           id = cryptx_internal_find_cipher(cipher_name);
27 20 50         if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
28              
29 20           Newz(0, RETVAL, 1, struct cryptx_authenc_eax_struct);
30 20 50         if (!RETVAL) croak("FATAL: Newz failed");
31              
32 20           rv = eax_init(&RETVAL->state, id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len);
33 20 50         if (rv != CRYPT_OK) {
34 0           zeromem(RETVAL, sizeof(*RETVAL));
35 0           Safefree(RETVAL);
36 0           croak("FATAL: eax setup failed: %s", error_to_string(rv));
37             }
38             }
39             OUTPUT:
40             RETVAL
41              
42             void
43             DESTROY(Crypt::AuthEnc::EAX self)
44             CODE:
45 21 50         if (self) {
46 21           zeromem(self, sizeof(*self));
47 21           Safefree(self);
48             }
49              
50             Crypt::AuthEnc::EAX
51             clone(Crypt::AuthEnc::EAX self)
52             CODE:
53 1           Newz(0, RETVAL, 1, struct cryptx_authenc_eax_struct);
54 1 50         if (!RETVAL) croak("FATAL: Newz failed");
55 1           Copy(self, RETVAL, 1, struct cryptx_authenc_eax_struct);
56             OUTPUT:
57             RETVAL
58              
59             SV *
60             encrypt_add(Crypt::AuthEnc::EAX self, SV * data)
61             CODE:
62             {
63             int rv;
64             STRLEN in_data_len;
65             unsigned char *in_data, *out_data;
66              
67 12 100         if (self->finalized) croak("FATAL: AEAD object already finalized");
68 11           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
69 11 100         if (in_data_len == 0) {
70 4           RETVAL = newSVpvn("", 0);
71             }
72             else {
73 7           RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
74 7           SvPOK_only(RETVAL);
75 7           SvCUR_set(RETVAL, in_data_len);
76 7           out_data = (unsigned char *)SvPVX(RETVAL);
77 7           rv = eax_encrypt(&self->state, in_data, out_data, (unsigned long)in_data_len);
78 7 50         if (rv != CRYPT_OK) {
79 0           SvREFCNT_dec(RETVAL);
80 0           croak("FATAL: eax_encrypt failed: %s", error_to_string(rv));
81             }
82             }
83             }
84             OUTPUT:
85             RETVAL
86              
87             SV *
88             decrypt_add(Crypt::AuthEnc::EAX self, SV * data)
89             CODE:
90             {
91             int rv;
92             STRLEN in_data_len;
93             unsigned char *in_data, *out_data;
94              
95 29 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
96 29           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
97 29 100         if (in_data_len == 0) {
98 4           RETVAL = newSVpvn("", 0);
99             }
100             else {
101 25           RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
102 25           SvPOK_only(RETVAL);
103 25           SvCUR_set(RETVAL, in_data_len);
104 25           out_data = (unsigned char *)SvPVX(RETVAL);
105 25           rv = eax_decrypt(&self->state, in_data, out_data, (unsigned long)in_data_len);
106 25 50         if (rv != CRYPT_OK) {
107 0           SvREFCNT_dec(RETVAL);
108 0           croak("FATAL: eax_decrypt failed: %s", error_to_string(rv));
109             }
110             }
111             }
112             OUTPUT:
113             RETVAL
114              
115             void
116             encrypt_done(Crypt::AuthEnc::EAX self)
117             PPCODE:
118             {
119             int rv;
120             unsigned char tag[MAXBLOCKSIZE];
121 12           unsigned long tag_len = sizeof(tag);
122              
123 12 100         if (self->finalized) croak("FATAL: AEAD object already finalized");
124 11           rv = eax_done(&self->state, tag, &tag_len);
125 11 50         if (rv != CRYPT_OK) croak("FATAL: eax_done failed: %s", error_to_string(rv));
126 11           self->finalized = 1;
127 11 50         XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
128 11           zeromem(tag, sizeof(tag));
129             }
130              
131             void
132             decrypt_done(Crypt::AuthEnc::EAX self, ...)
133             PPCODE:
134             {
135             int rv;
136             unsigned char tag[MAXBLOCKSIZE];
137 10           unsigned long tag_len = sizeof(tag);
138             STRLEN expected_tag_len;
139             unsigned char *expected_tag;
140              
141 10 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
142 10           rv = eax_done(&self->state, tag, &tag_len);
143 10 50         if (rv != CRYPT_OK) croak("FATAL: eax_done failed: %s", error_to_string(rv));
144 10           self->finalized = 1;
145 10 50         if (items == 1) {
146 10 50         XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
147 10           zeromem(tag, sizeof(tag));
148             }
149             else {
150 0 0         if (!SvPOK_spec(ST(1))) croak("FATAL: expected_tag must be string/buffer scalar");
    0          
    0          
    0          
    0          
151 0           expected_tag = (unsigned char *) SvPVbyte(ST(1), expected_tag_len);
152 0 0         if (expected_tag_len!=tag_len) {
153 0 0         XPUSHs(sv_2mortal(newSViv(0))); /* false */
154             }
155 0 0         else if (mem_neq(expected_tag, tag, tag_len)) {
156 0 0         XPUSHs(sv_2mortal(newSViv(0))); /* false */
157             }
158             else {
159 0 0         XPUSHs(sv_2mortal(newSViv(1))); /* true */
160             }
161             }
162             }
163              
164             void
165             adata_add(Crypt::AuthEnc::EAX self, SV * adata)
166             PPCODE:
167             {
168             STRLEN h_len;
169             int rv;
170             unsigned char *h;
171 24 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
172 24           h = (unsigned char *)SvPVbyte(adata, h_len);
173 24           rv = eax_addheader(&self->state, h, (unsigned long)h_len);
174 24 50         if (rv != CRYPT_OK) croak("FATAL: eax_addheader failed: %s", error_to_string(rv));
175 24 50         XPUSHs(ST(0)); /* return self */
176             }
177              
178             void
179             eax_encrypt_authenticate(char *cipher_name, SV *key, SV *nonce, SV *header, SV *plaintext)
180             PPCODE:
181             {
182 10           STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
183 10           unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
184             int rv, id;
185             unsigned char tag[MAXBLOCKSIZE];
186 10           unsigned long tag_len = sizeof(tag);
187             SV *output;
188              
189 10 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
190 10           k = (unsigned char *) SvPVbyte(key, k_len);
191 10 50         if (!SvPOK_spec(nonce)) croak("FATAL: nonce must be string/buffer scalar");
    50          
    0          
    0          
    0          
192 10           n = (unsigned char *) SvPVbyte(nonce, n_len);
193 10 50         if (!SvPOK_spec(plaintext)) croak("FATAL: plaintext must be string/buffer scalar");
    50          
    0          
    0          
    0          
194 10           pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
195 10 50         if (header && SvOK(header)) {
    50          
196 10 50         if (!SvPOK_spec(header)) croak("FATAL: header must be string/buffer scalar");
    50          
    0          
    0          
    0          
197 10           h = (unsigned char *) SvPVbyte(header, h_len);
198 10           zeromem(tag, sizeof(tag));
199             }
200              
201 10           id = cryptx_internal_find_cipher(cipher_name);
202 10 50         if(id==-1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
203 10 100         output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
204 10           SvPOK_only(output);
205 10           SvCUR_set(output, pt_len);
206              
207 10           rv = eax_encrypt_authenticate_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len,
208             h, (unsigned long)h_len, pt, (unsigned long)pt_len,
209 10           (unsigned char *)SvPVX(output), tag, &tag_len);
210              
211 10 50         if (rv != CRYPT_OK) {
212 0           SvREFCNT_dec(output);
213 0           croak("FATAL: eax_encrypt_authenticate_memory failed: %s", error_to_string(rv));
214             }
215 10 50         XPUSHs(sv_2mortal(output));
216 10 50         XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
217             }
218              
219             void
220             eax_decrypt_verify(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
221             PPCODE:
222             {
223 14           STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
224 14           unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
225 14           int rv, id, stat = 0;
226             unsigned char tag[MAXBLOCKSIZE];
227             unsigned long tag_len;
228             SV *output;
229              
230 14 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
231 14           k = (unsigned char *) SvPVbyte(key, k_len);
232 14 50         if (!SvPOK_spec(nonce)) croak("FATAL: nonce must be string/buffer scalar");
    50          
    0          
    0          
    0          
233 14           n = (unsigned char *) SvPVbyte(nonce, n_len);
234 14 50         if (!SvPOK_spec(ciphertext)) croak("FATAL: ciphertext must be string/buffer scalar");
    50          
    0          
    0          
    0          
235 14           ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
236 14 50         if (!SvPOK_spec(tagsv)) croak("FATAL: tag must be string/buffer scalar");
    50          
    0          
    0          
    0          
237 14           t = (unsigned char *) SvPVbyte(tagsv, t_len);
238 14 50         if (header && SvOK(header)) {
    50          
239 14 50         if (!SvPOK_spec(header)) croak("FATAL: header must be string/buffer scalar");
    50          
    0          
    0          
    0          
240 14           h = (unsigned char *) SvPVbyte(header, h_len);
241 14           zeromem(tag, sizeof(tag));
242             }
243              
244 14           id = cryptx_internal_find_cipher(cipher_name);
245 14 50         if(id==-1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
246 14 100         output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
247 14           SvPOK_only(output);
248 14           SvCUR_set(output, ct_len);
249             /* Clamp malformed tags to the stack buffer size before copying. */
250 14           tag_len = (unsigned long)(t_len > sizeof(tag) ? sizeof(tag) : t_len);
251 14 50         if (tag_len > 0) {
252 14           Copy(t, tag, tag_len, unsigned char);
253             }
254              
255 14           rv = eax_decrypt_verify_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len,
256 14           ct, (unsigned long)ct_len, (unsigned char *)SvPVX(output), tag, tag_len, &stat);
257              
258 14 50         if (rv != CRYPT_OK || stat != 1) {
    100          
259 4           SvREFCNT_dec(output);
260 4 50         XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
261             }
262             else {
263 10 50         XPUSHs(sv_2mortal(output));
264             }
265             }