File Coverage

inc/CryptX_AuthEnc_OCB.xs.inc
Criterion Covered Total %
statement 123 159 77.3
branch 73 228 32.0
condition n/a
subroutine n/a
pod n/a
total 196 387 50.6


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::AuthEnc::OCB
2              
3             PROTOTYPES: DISABLE
4              
5             Crypt::AuthEnc::OCB
6             new(Class, char * cipher_name, SV * key, SV * nonce, unsigned long taglen)
7             CODE:
8             {
9 37           STRLEN k_len=0;
10 37           unsigned char *k=NULL;
11 37           unsigned char *n=NULL;
12 37           STRLEN n_len=0;
13             int rv, id;
14              
15 37 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
16 37           k = (unsigned char *) SvPVbyte(key, k_len);
17 37 50         if (!SvPOK_spec(nonce)) croak("FATAL: nonce must be string/buffer scalar");
    50          
    0          
    0          
    0          
18 37           n = (unsigned char *) SvPVbyte(nonce, n_len);
19              
20 37           id = cryptx_internal_find_cipher(cipher_name);
21 37 50         if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
22              
23 37           Newz(0, RETVAL, 1, struct cryptx_authenc_ocb_struct);
24 37 50         if (!RETVAL) croak("FATAL: Newz failed");
25              
26 37           rv = ocb3_init(&RETVAL->state, id, k, (unsigned long)k_len, n, (unsigned long)n_len, taglen);
27 37 50         if (rv != CRYPT_OK) {
28 0           zeromem(RETVAL, sizeof(*RETVAL));
29 0           Safefree(RETVAL);
30 0           croak("FATAL: ocb setup failed: %s", error_to_string(rv));
31             }
32             }
33             OUTPUT:
34             RETVAL
35              
36             void
37             DESTROY(Crypt::AuthEnc::OCB self)
38             CODE:
39 38 50         if (self) {
40 38           zeromem(self, sizeof(*self));
41 38           Safefree(self);
42             }
43              
44             Crypt::AuthEnc::OCB
45             clone(Crypt::AuthEnc::OCB self)
46             CODE:
47 1           Newz(0, RETVAL, 1, struct cryptx_authenc_ocb_struct);
48 1 50         if (!RETVAL) croak("FATAL: Newz failed");
49 1           Copy(self, RETVAL, 1, struct cryptx_authenc_ocb_struct);
50             OUTPUT:
51             RETVAL
52              
53             void
54             adata_add(Crypt::AuthEnc::OCB self, SV * data)
55             PPCODE:
56             {
57             int rv;
58             STRLEN in_data_len;
59             unsigned char *in_data;
60              
61 37 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
62 37           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
63              
64 37 100         if (in_data_len>0) {
65 25           rv = ocb3_add_aad(&self->state, in_data, (unsigned long)in_data_len);
66 25 50         if (rv != CRYPT_OK) croak("FATAL: ocb3_add_aad failed: %s", error_to_string(rv));
67             }
68 37 50         XPUSHs(ST(0)); /* return self */
69             }
70              
71             SV *
72             encrypt_add(Crypt::AuthEnc::OCB self, SV * data)
73             CODE:
74             {
75             int rv;
76             STRLEN in_data_len;
77             unsigned char *in_data, *out_data;
78              
79 3 100         if (self->finalized) croak("FATAL: AEAD object already finalized");
80 2           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
81 2 50         if (in_data_len == 0) {
82 0           RETVAL = newSVpvn("", 0);
83             }
84             else {
85 2 50         if (in_data_len % 16) {
86 0           croak ("FATAL: sizeof(data) should be multiple of 16");
87             }
88 2           RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
89 2           SvPOK_only(RETVAL);
90 2           SvCUR_set(RETVAL, in_data_len);
91 2           out_data = (unsigned char *)SvPVX(RETVAL);
92 2           rv = ocb3_encrypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
93 2 50         if (rv != CRYPT_OK) {
94 0           SvREFCNT_dec(RETVAL);
95 0           croak("FATAL: ocb3_encrypt failed: %s", error_to_string(rv));
96             }
97             }
98             }
99             OUTPUT:
100             RETVAL
101              
102             SV *
103             encrypt_last(Crypt::AuthEnc::OCB self, SV * data)
104             CODE:
105             {
106             int rv;
107             STRLEN in_data_len;
108             unsigned char *in_data, *out_data;
109              
110 18 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
111 18           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
112 18 100         if (in_data_len == 0) {
113 6           rv = ocb3_encrypt_last(&self->state, in_data, 0, NULL);
114 6 50         if (rv != CRYPT_OK) {
115 0           croak("FATAL: ocb3_encrypt_last failed: %s", error_to_string(rv));
116             }
117 6           RETVAL = newSVpvn("", 0);
118             }
119             else {
120 12           RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
121 12           SvPOK_only(RETVAL);
122 12           SvCUR_set(RETVAL, in_data_len);
123 12           out_data = (unsigned char *)SvPVX(RETVAL);
124 12           rv = ocb3_encrypt_last(&self->state, in_data, (unsigned long)in_data_len, out_data);
125 12 50         if (rv != CRYPT_OK) {
126 0           SvREFCNT_dec(RETVAL);
127 0           croak("FATAL: ocb3_encrypt_last failed: %s", error_to_string(rv));
128             }
129             }
130             }
131             OUTPUT:
132             RETVAL
133              
134             SV *
135             decrypt_add(Crypt::AuthEnc::OCB self, SV * data)
136             CODE:
137             {
138             int rv;
139             STRLEN in_data_len;
140             unsigned char *in_data, *out_data;
141              
142 0 0         if (self->finalized) croak("FATAL: AEAD object already finalized");
143 0           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
144 0 0         if (in_data_len == 0) {
145 0           RETVAL = newSVpvn("", 0);
146             }
147             else {
148 0 0         if (in_data_len % 16) {
149 0           croak ("FATAL: sizeof(data) should be multiple of 16");
150             }
151 0           RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
152 0           SvPOK_only(RETVAL);
153 0           SvCUR_set(RETVAL, in_data_len);
154 0           out_data = (unsigned char *)SvPVX(RETVAL);
155 0           rv = ocb3_decrypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
156 0 0         if (rv != CRYPT_OK) {
157 0           SvREFCNT_dec(RETVAL);
158 0           croak("FATAL: ocb3_decrypt failed: %s", error_to_string(rv));
159             }
160             }
161             }
162             OUTPUT:
163             RETVAL
164              
165             SV *
166             decrypt_last(Crypt::AuthEnc::OCB self, SV * data)
167             CODE:
168             {
169             int rv;
170             STRLEN in_data_len;
171             unsigned char *in_data, *out_data;
172              
173 18 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
174 18           in_data = (unsigned char *)SvPVbyte(data, in_data_len);
175 18 100         if (in_data_len == 0) {
176 6           rv = ocb3_decrypt_last(&self->state, in_data, 0, NULL);
177 6 50         if (rv != CRYPT_OK) {
178 0           croak("FATAL: ocb3_decrypt_last failed: %s", error_to_string(rv));
179             }
180 6           RETVAL = newSVpvn("", 0);
181             }
182             else {
183 12           RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
184 12           SvPOK_only(RETVAL);
185 12           SvCUR_set(RETVAL, in_data_len);
186 12           out_data = (unsigned char *)SvPVX(RETVAL);
187 12           rv = ocb3_decrypt_last(&self->state, in_data, (unsigned long)in_data_len, out_data);
188 12 50         if (rv != CRYPT_OK) {
189 0           SvREFCNT_dec(RETVAL);
190 0           croak("FATAL: ocb3_decrypt_last failed: %s", error_to_string(rv));
191             }
192             }
193             }
194             OUTPUT:
195             RETVAL
196              
197             void
198             encrypt_done(Crypt::AuthEnc::OCB self)
199             PPCODE:
200             {
201             int rv;
202             unsigned char tag[MAXBLOCKSIZE];
203 21           unsigned long tag_len = sizeof(tag);
204              
205 21 100         if (self->finalized) croak("FATAL: AEAD object already finalized");
206 20           rv = ocb3_done(&self->state, tag, &tag_len);
207 20 50         if (rv != CRYPT_OK) croak("FATAL: ocb3_done_encrypt failed: %s", error_to_string(rv));
208 20           self->finalized = 1;
209              
210 20 50         XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
211 20           zeromem(tag, sizeof(tag));
212             }
213              
214             void
215             decrypt_done(Crypt::AuthEnc::OCB self, ...)
216             PPCODE:
217             {
218             int rv;
219             unsigned char tag[MAXBLOCKSIZE];
220 18           unsigned long tag_len = sizeof(tag);
221             STRLEN expected_tag_len;
222             unsigned char *expected_tag;
223              
224 18 50         if (self->finalized) croak("FATAL: AEAD object already finalized");
225 18           rv = ocb3_done(&self->state, tag, &tag_len);
226 18 50         if (rv != CRYPT_OK) croak("FATAL: ocb3_done_decrypt failed: %s", error_to_string(rv));
227 18           self->finalized = 1;
228 18 50         if (items == 1) {
229 18 50         XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
230 18           zeromem(tag, sizeof(tag));
231             }
232             else {
233 0 0         if (!SvPOK_spec(ST(1))) croak("FATAL: expected_tag must be string/buffer scalar");
    0          
    0          
    0          
    0          
234 0           expected_tag = (unsigned char *) SvPVbyte(ST(1), expected_tag_len);
235 0 0         if (expected_tag_len!=tag_len) {
236 0 0         XPUSHs(sv_2mortal(newSViv(0))); /* false */
237             }
238 0 0         else if (mem_neq(expected_tag, tag, tag_len)) {
239 0 0         XPUSHs(sv_2mortal(newSViv(0))); /* false */
240             }
241             else {
242 0 0         XPUSHs(sv_2mortal(newSViv(1))); /* true */
243             }
244             }
245             }
246              
247             void
248             ocb_encrypt_authenticate(char *cipher_name, SV *key, SV *nonce, SV *header, unsigned long tag_len, SV *plaintext)
249             PPCODE:
250             {
251 2           STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
252 2           unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
253             int rv, id;
254             unsigned char tag[MAXBLOCKSIZE];
255             SV *output;
256              
257 2 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
258 2           k = (unsigned char *) SvPVbyte(key, k_len);
259 2 50         if (!SvPOK_spec(nonce)) croak("FATAL: nonce must be string/buffer scalar");
    50          
    0          
    0          
    0          
260 2           n = (unsigned char *) SvPVbyte(nonce, n_len);
261 2 50         if (!SvPOK_spec(plaintext)) croak("FATAL: plaintext must be string/buffer scalar");
    50          
    0          
    0          
    0          
262 2           pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
263 2 50         if (header && SvOK(header)) {
    50          
264 2 50         if (!SvPOK_spec(header)) croak("FATAL: header must be string/buffer scalar");
    50          
    0          
    0          
    0          
265 2           h = (unsigned char *) SvPVbyte(header, h_len);
266 2           zeromem(tag, sizeof(tag));
267             }
268              
269 2           id = cryptx_internal_find_cipher(cipher_name);
270 2 50         if(id==-1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
271 2 50         output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
272 2           SvPOK_only(output);
273 2           SvCUR_set(output, pt_len);
274 2 50         if(tag_len < 4 || tag_len > 16) tag_len = 16;
    50          
275              
276 2           rv = ocb3_encrypt_authenticate_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len,
277             h, (unsigned long)h_len, pt, (unsigned long)pt_len,
278 2           (unsigned char *)SvPVX(output), tag, &tag_len);
279              
280 2 50         if (rv != CRYPT_OK) {
281 0           SvREFCNT_dec(output);
282 0           croak("FATAL: ocb3_encrypt_authenticate_memory failed: %s", error_to_string(rv));
283             }
284 2 50         XPUSHs(sv_2mortal(output));
285 2 50         XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
286             }
287              
288             void
289             ocb_decrypt_verify(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
290             PPCODE:
291             {
292 4           STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
293 4           unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
294 4           int rv, id, stat = 0;
295             SV *output;
296              
297 4 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
298 4           k = (unsigned char *) SvPVbyte(key, k_len);
299 4 50         if (!SvPOK_spec(nonce)) croak("FATAL: nonce must be string/buffer scalar");
    50          
    0          
    0          
    0          
300 4           n = (unsigned char *) SvPVbyte(nonce, n_len);
301 4 50         if (!SvPOK_spec(ciphertext)) croak("FATAL: ciphertext must be string/buffer scalar");
    50          
    0          
    0          
    0          
302 4           ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
303 4 50         if (!SvPOK_spec(tagsv)) croak("FATAL: tag must be string/buffer scalar");
    50          
    0          
    0          
    0          
304 4           t = (unsigned char *) SvPVbyte(tagsv, t_len);
305 4 50         if (header && SvOK(header)) {
    50          
306 4 50         if (!SvPOK_spec(header)) croak("FATAL: header must be string/buffer scalar");
    50          
    0          
    0          
    0          
307 4           h = (unsigned char *) SvPVbyte(header, h_len);
308             }
309              
310 4           id = cryptx_internal_find_cipher(cipher_name);
311 4 50         if(id==-1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
312 4 50         output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
313 4           SvPOK_only(output);
314 4           SvCUR_set(output, ct_len);
315              
316 4           rv = ocb3_decrypt_verify_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len,
317             h, (unsigned long)h_len, ct, (unsigned long)ct_len,
318 4           (unsigned char *)SvPVX(output), t, (unsigned long)t_len, &stat);
319              
320 4 50         if (rv != CRYPT_OK || stat != 1) {
    100          
321 2           SvREFCNT_dec(output);
322 2 50         XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
323             }
324             else {
325 2 50         XPUSHs(sv_2mortal(output));
326             }
327             }