File Coverage

inc/CryptX_Mode_CBC.xs.inc
Criterion Covered Total %
statement 141 163 86.5
branch 104 160 65.0
condition n/a
subroutine n/a
pod n/a
total 245 323 75.8


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::Mode::CBC
2              
3             PROTOTYPES: DISABLE
4              
5             ### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
6              
7             Crypt::Mode::CBC
8             new(Class, char * cipher_name, int padding=1, int rounds=0)
9             CODE:
10             {
11 130           Newz(0, RETVAL, 1, struct cbc_struct);
12 130 50         if (!RETVAL) croak("FATAL: Newz failed");
13 130           RETVAL->padding_mode = padding;
14 130           RETVAL->padlen = 0;
15 130           RETVAL->direction = 0;
16 130           RETVAL->cipher_rounds = rounds;
17 130           RETVAL->cipher_id = cryptx_internal_find_cipher(cipher_name);
18 130 50         if (RETVAL->cipher_id == -1) {
19 0           Safefree(RETVAL);
20 0           croak("FATAL: find_cipher failed for '%s'", cipher_name);
21             }
22             }
23             OUTPUT:
24             RETVAL
25              
26             void
27             DESTROY(Crypt::Mode::CBC self)
28             CODE:
29             {
30 130           zeromem(&self->state, sizeof(symmetric_CBC));
31 130           zeromem(self->pad, sizeof(self->pad));
32 130           Safefree(self);
33             }
34              
35             void
36             start_decrypt(Crypt::Mode::CBC self, SV * key, SV * iv)
37             ALIAS:
38             start_encrypt = 1
39             PPCODE:
40             {
41             int rv;
42 324           STRLEN k_len=0;
43 324           unsigned char *k=NULL;
44 324           STRLEN i_len=0;
45 324           unsigned char *i=NULL;
46              
47 324 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
48 324           k = (unsigned char *) SvPVbyte(key, k_len);
49              
50 324 50         if (!SvPOK_spec(iv)) croak("FATAL: iv must be string/buffer scalar");
    50          
    0          
    0          
    0          
51 324           i = (unsigned char *) SvPVbyte(iv, i_len);
52 324 50         if (i_len != (STRLEN)cipher_descriptor[self->cipher_id].block_length) {
53 0           croak ("FATAL: sizeof(iv) should be equal to blocksize (%d)", cipher_descriptor[self->cipher_id].block_length);
54             }
55 324           rv = cbc_start(self->cipher_id, i, k, (int)k_len, self->cipher_rounds, &self->state);
56 324 50         if (rv != CRYPT_OK) {
57 0           croak("FATAL: cbc_start failed: %s", error_to_string(rv));
58             }
59              
60 324 100         self->direction = ix == 1 ? 1 : -1;
61 324           self->padlen = 0;
62 324 50         XPUSHs(ST(0)); /* return self */
63             }
64              
65             SV *
66             add(Crypt::Mode::CBC self, ...)
67             CODE:
68             {
69             int rv, has_tmp_block, blen, j;
70             unsigned long i;
71 3491           STRLEN in_data_len, in_data_start, out_len = 0;
72             unsigned char *in_data, *out_data, tmp_block[MAXBLOCKSIZE];
73              
74 3491           RETVAL = newSVpvn("", 0);
75 6981 100         for (j = 1; j < items; j++) {
76 3491           in_data = (unsigned char *)SvPVbyte(ST(j), in_data_len);
77 3491           blen = (&self->state)->ecb.blocklen;
78 3491           in_data_start = 0;
79 3491           has_tmp_block = 0;
80 3491 100         if (in_data_len > 0) {
81 3488 100         if (self->direction == 1) {
82             /* handle non-empty self->pad buffer */
83 1688 100         if (self->padlen > 0) {
84 1360           i = (blen - self->padlen);
85 1360 100         if (in_data_len >= i) { /* enough data to fill pad */
86 585           Copy(in_data, self->pad+self->padlen, i, unsigned char);
87 585           in_data_len -= i;
88 585           in_data_start = i;
89 585           rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
90 585 50         if (rv != CRYPT_OK) {
91 0           SvREFCNT_dec(RETVAL);
92 0           croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
93             }
94 585           self->padlen = 0;
95 585           has_tmp_block = 1;
96             }
97             else { /* not enough data to fill pad */
98 775           Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
99 775           self->padlen += (int)in_data_len;
100 775           in_data_len = 0;
101             }
102             }
103              
104 1688           i = (unsigned long)(in_data_len % blen);
105 1688 100         if (in_data_len > 0 && i > 0) { /* save tail of data into pad */
    100          
106 678           Copy(in_data + in_data_start + in_data_len - i, self->pad, i, unsigned char);
107 678           self->padlen = i;
108 678           in_data_len -= i;
109             }
110              
111 1688 100         if (in_data_len > 0) {
112 246 100         i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
113 246 50         out_data = (unsigned char*)SvGROW(RETVAL, out_len + i + 1) + out_len;
    50          
114 246           out_len += i;
115 246 100         if (has_tmp_block) {
116 96           Copy(tmp_block, out_data, blen, unsigned char);
117 96           out_data += blen;
118             }
119 246           rv = cbc_encrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
120 246 50         if (rv != CRYPT_OK) {
121 0           SvREFCNT_dec(RETVAL);
122 0           croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
123             }
124             } /* in_data_len > 0 */
125 1442 100         else if (has_tmp_block) {
126 489 50         out_data = (unsigned char*)SvGROW(RETVAL, out_len + blen + 1) + out_len;
    50          
127 489           out_len += blen;
128 489           Copy(tmp_block, out_data, blen, unsigned char);
129             }
130             }
131 1800 100         else if (self->direction == -1) {
132 1799 100         if (self->padlen == blen) {
133 116           rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
134 116 50         if (rv != CRYPT_OK) {
135 0           SvREFCNT_dec(RETVAL);
136 0           croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
137             }
138 116           self->padlen = 0;
139 116           has_tmp_block = 1;
140             } /* padlen == blen */
141 1683 100         else if (self->padlen > 0) {
142 1470           i = (blen - self->padlen); /* remaining bytes in padding buffer */
143 1470 100         if (in_data_len >= i) { /* enough data to fill pad */
144 633           Copy(in_data, self->pad+self->padlen, i, unsigned char);
145 633           self->padlen += i;
146 633           in_data_len -= i;
147 633           in_data_start = i;
148 633 100         if (in_data_len>0 || self->padding_mode == 0) {
    100          
149 501           rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
150 501 50         if (rv != CRYPT_OK) {
151 0           SvREFCNT_dec(RETVAL);
152 0           croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
153             }
154 501           self->padlen = 0;
155 501           has_tmp_block = 1;
156             }
157             }
158             else { /* not enough data to fill pad */
159 837           Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
160 837           self->padlen += (int)in_data_len;
161 837           in_data_len = 0;
162             }
163             } /* padlen > 0 */
164              
165             /* here: a/ padlen == 1..16 && in_data_len == 0; b/ padlen == 0 && in_data_len > 0 */
166 1799 100         if (in_data_len>0) {
167 766           i = (unsigned long)(in_data_len % blen);
168 766 100         if (i>0) { /* save tail of data into pad */
169 633           Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
170 633           self->padlen = i;
171 633           in_data_len -= i;
172             }
173             }
174              
175 1799 100         if (in_data_len>0) {
176 272 100         if (self->padlen == 0 && self->padding_mode !=0) {
    100          
177             /* in case of padding keep full pad if no more data */
178 82           Copy(in_data+in_data_start+in_data_len-blen, self->pad, blen, unsigned char);
179 82           self->padlen = blen;
180 82           in_data_len -= blen;
181             }
182 272 100         i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
183 272 100         if (i > 0) {
184 263 50         out_data = (unsigned char*)SvGROW(RETVAL, out_len + i + 1) + out_len;
    50          
185 263           out_len += i;
186 263 100         if (has_tmp_block) {
187 142           Copy(tmp_block, out_data, blen, unsigned char);
188 142           out_data += blen;
189             }
190 263           rv = cbc_decrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
191 263 50         if (rv != CRYPT_OK) {
192 0           SvREFCNT_dec(RETVAL);
193 0           croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
194             }
195             }
196             } /* in_data_len>0 */
197 1527 100         else if (has_tmp_block) {
198 475 50         out_data = (unsigned char*)SvGROW(RETVAL, out_len + blen + 1) + out_len;
    50          
199 475           out_len += blen;
200 475           Copy(tmp_block, out_data, blen, unsigned char);
201             }
202             }
203             else {
204 1           SvREFCNT_dec(RETVAL);
205 1           croak("FATAL: call start_decrypt or start_encrypt first (%d)", self->direction);
206             }
207             }
208             }
209 3490 100         if (out_len > 0) SvCUR_set(RETVAL, out_len);
210             }
211             OUTPUT:
212             RETVAL
213              
214             SV *
215             finish(Crypt::Mode::CBC self)
216             CODE:
217             {
218             unsigned char tmp_block[MAXBLOCKSIZE];
219             int rv;
220 325           unsigned long blen = (&self->state)->ecb.blocklen;
221             unsigned long padmode;
222              
223 325 100         if (self->direction == 1) {
224 161 50         if (self->padlen < 0 || self->padlen >= (int)blen) croak("FATAL: invalid padlen");
    50          
225 161 100         if (self->padding_mode != 0) {
226 98 100         if (self->padding_mode == 1) { padmode = LTC_PAD_PKCS7 | (&self->state)->ecb.blocklen; }
227 45 50         else if (self->padding_mode == 2) { padmode = LTC_PAD_ONE_AND_ZERO | (&self->state)->ecb.blocklen; }
228 0 0         else if (self->padding_mode == 3) { padmode = LTC_PAD_ANSI_X923 | (&self->state)->ecb.blocklen; }
229 0 0         else if (self->padding_mode == 4) { padmode = LTC_PAD_ZERO | (&self->state)->ecb.blocklen; }
230 0 0         else if (self->padding_mode == 5) { padmode = LTC_PAD_ZERO_ALWAYS | (&self->state)->ecb.blocklen; }
231 0           else { croak("FATAL: unknown padding"); }
232 98           blen = sizeof(self->pad);
233 98           rv = padding_pad(self->pad, self->padlen, &blen, padmode);
234 98 50         if (rv != CRYPT_OK) croak("FATAL: padding_pad failed: %s", error_to_string(rv));
235 98           rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
236 98 50         if (rv != CRYPT_OK) croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
237             }
238             else {
239 63 50         if (self->padlen > 0) croak("FATAL: cbc_encrypt, input data length not multiple of %d", (int)blen);
240 63           blen = 0;
241             }
242             }
243 164 100         else if (self->direction == -1) {
244 163 100         if (self->padlen > 0) {
245 98 50         if (self->padlen != (int)blen) croak("FATAL: cipher text length has to be multiple of %d (%d)", (int)blen, self->padlen);
246 98           rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
247 98 50         if (rv != CRYPT_OK) croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
248 98 50         if (self->padding_mode != 0) {
249 98 100         if (self->padding_mode == 1) { padmode = LTC_PAD_PKCS7 | (&self->state)->ecb.blocklen; }
250 45 50         else if (self->padding_mode == 2) { padmode = LTC_PAD_ONE_AND_ZERO | (&self->state)->ecb.blocklen; }
251 0 0         else if (self->padding_mode == 3) { padmode = LTC_PAD_ANSI_X923 | (&self->state)->ecb.blocklen; }
252 0 0         else if (self->padding_mode == 4) { padmode = LTC_PAD_ZERO | (&self->state)->ecb.blocklen; }
253 0 0         else if (self->padding_mode == 5) { padmode = LTC_PAD_ZERO_ALWAYS | (&self->state)->ecb.blocklen; }
254 0           else { croak("FATAL: unknown padding"); }
255 98           rv = padding_depad(tmp_block, &blen, padmode);
256 98 100         if (rv != CRYPT_OK) croak("FATAL: padding_depad failed: %s", error_to_string(rv));
257             }
258             else {
259             /* "no padding" == there is no need to do anything */
260             }
261             }
262             else {
263 65 100         if (self->padding_mode != 0) croak("FATAL: cipher text length has to be at least one block with padding");
264 64           blen = 0;
265             }
266             }
267             else {
268 1           croak("FATAL: mode not active; call start_decrypt or start_encrypt first");
269             }
270              
271 322           self->direction = 0;
272 322           RETVAL = newSVpvn((char*)tmp_block, blen);
273             }
274             OUTPUT:
275             RETVAL