File Coverage

xs/crypt.xs
Criterion Covered Total %
statement 58 97 59.7
branch 28 90 31.1
condition n/a
subroutine n/a
pod n/a
total 86 187 45.9


line stmt bran cond sub pod time code
1             MODULE = PDF::Make::Crypt PACKAGE = PDF::Make::Crypt PREFIX = crypt_
2              
3             PROTOTYPES: DISABLE
4              
5             #===============================================================================
6             # Constructor / Destructor
7             #===============================================================================
8              
9             pdfmake_crypt_xs_t *
10             crypt_new(class)
11             SV *class
12             CODE:
13             PERL_UNUSED_VAR(class);
14 18           Newxz(RETVAL, 1, pdfmake_crypt_xs_t);
15 18           pdfmake_crypt_init(&RETVAL->ctx);
16             OUTPUT:
17             RETVAL
18              
19             void
20             crypt_DESTROY(self)
21             pdfmake_crypt_xs_t *self
22             CODE:
23 18           Safefree(self);
24              
25             #===============================================================================
26             # Setup for encryption
27             #===============================================================================
28              
29             int
30             crypt_setup(self, algorithm, user_passwd, owner_passwd, permissions, doc_id)
31             pdfmake_crypt_xs_t *self
32             const char *algorithm
33             const char *user_passwd
34             SV *owner_passwd
35             int32_t permissions
36             SV *doc_id
37             PREINIT:
38             pdfmake_crypt_algo_t algo;
39 17           const char *owner_str = NULL;
40 17           const uint8_t *id_bytes = NULL;
41 17 50         STRLEN id_len = 0;
42             CODE:
43             /* Parse algorithm string */
44 17 100         if (strEQ(algorithm, "RC4-40") || strEQ(algorithm, "rc4-40")) {
    50          
45 3           algo = PDFMAKE_CRYPT_RC4_40;
46 14 100         } else if (strEQ(algorithm, "RC4-128") || strEQ(algorithm, "rc4-128")) {
    50          
47 6           algo = PDFMAKE_CRYPT_RC4_128;
48 8 100         } else if (strEQ(algorithm, "AES-128") || strEQ(algorithm, "aes-128")) {
    50          
49 4           algo = PDFMAKE_CRYPT_AES_128;
50 4 50         } else if (strEQ(algorithm, "AES-256") || strEQ(algorithm, "aes-256")) {
    0          
51 4           algo = PDFMAKE_CRYPT_AES_256;
52             } else {
53 0           croak("Unknown encryption algorithm: %s", algorithm);
54             }
55            
56             /* Get owner password (may be undef) */
57 17 50         if (SvOK(owner_passwd)) {
58 17           owner_str = SvPV_nolen(owner_passwd);
59             }
60            
61             /* Get document ID */
62 17 50         if (SvOK(doc_id)) {
63 17           id_bytes = (const uint8_t *)SvPV(doc_id, id_len);
64             }
65            
66 17           RETVAL = pdfmake_crypt_setup(&self->ctx, algo,
67             user_passwd, owner_str,
68             permissions,
69 17 100         id_bytes, id_len) == 0 ? 1 : 0;
70             OUTPUT:
71             RETVAL
72              
73             #===============================================================================
74             # Load encryption parameters from parsed PDF
75             #===============================================================================
76              
77             int
78             crypt_load(self, V, R, key_length, O, U, OE, UE, Perms, P, doc_id, encrypt_metadata)
79             pdfmake_crypt_xs_t *self
80             int V
81             int R
82             int key_length
83             SV *O
84             SV *U
85             SV *OE
86             SV *UE
87             SV *Perms
88             int32_t P
89             SV *doc_id
90             int encrypt_metadata
91             PREINIT:
92 0           const uint8_t *O_bytes = NULL, *U_bytes = NULL;
93 0           const uint8_t *OE_bytes = NULL, *UE_bytes = NULL;
94 0           const uint8_t *Perms_bytes = NULL, *id_bytes = NULL;
95 0 0         STRLEN O_len = 0, U_len = 0, OE_len = 0, UE_len = 0, Perms_len = 0, id_len = 0;
96             CODE:
97 0 0         if (SvOK(O)) O_bytes = (const uint8_t *)SvPV(O, O_len);
98 0 0         if (SvOK(U)) U_bytes = (const uint8_t *)SvPV(U, U_len);
99 0 0         if (SvOK(OE)) OE_bytes = (const uint8_t *)SvPV(OE, OE_len);
100 0 0         if (SvOK(UE)) UE_bytes = (const uint8_t *)SvPV(UE, UE_len);
101 0 0         if (SvOK(Perms)) Perms_bytes = (const uint8_t *)SvPV(Perms, Perms_len);
102 0 0         if (SvOK(doc_id)) id_bytes = (const uint8_t *)SvPV(doc_id, id_len);
103            
104 0           RETVAL = pdfmake_crypt_load(&self->ctx, V, R, key_length,
105             O_bytes, O_len, U_bytes, U_len,
106             OE_bytes, OE_len, UE_bytes, UE_len,
107             Perms_bytes, Perms_len,
108             P, id_bytes, id_len, encrypt_metadata);
109             OUTPUT:
110             RETVAL
111              
112             #===============================================================================
113             # Authentication
114             #===============================================================================
115              
116             int
117             crypt_authenticate(self, password)
118             pdfmake_crypt_xs_t *self
119             const char *password
120             CODE:
121 0           RETVAL = pdfmake_crypt_authenticate(&self->ctx, password);
122             OUTPUT:
123             RETVAL
124              
125             int
126             crypt_is_authenticated(self)
127             pdfmake_crypt_xs_t *self
128             CODE:
129 9           RETVAL = pdfmake_crypt_is_authenticated(&self->ctx);
130             OUTPUT:
131             RETVAL
132              
133             int
134             crypt_is_owner(self)
135             pdfmake_crypt_xs_t *self
136             CODE:
137 2           RETVAL = pdfmake_crypt_is_owner(&self->ctx);
138             OUTPUT:
139             RETVAL
140              
141             #===============================================================================
142             # Encryption / Decryption
143             #===============================================================================
144              
145             SV *
146             crypt_encrypt_string(self, obj_num, gen_num, data)
147             pdfmake_crypt_xs_t *self
148             int obj_num
149             int gen_num
150             SV *data
151             PREINIT:
152             const uint8_t *in;
153             STRLEN in_len;
154             uint8_t *out;
155             int out_len;
156             CODE:
157 3           in = (const uint8_t *)SvPV(data, in_len);
158            
159             /* Allocate output buffer (max size for AES: 16 + in_len + 16) */
160 3           Newx(out, in_len + 32, uint8_t);
161            
162 3           out_len = pdfmake_crypt_encrypt_string(&self->ctx, obj_num, gen_num,
163             in, in_len, out);
164            
165 3 50         if (out_len < 0) {
166 0           Safefree(out);
167 0           RETVAL = &PL_sv_undef;
168             } else {
169 3           RETVAL = newSVpvn((char *)out, out_len);
170 3           Safefree(out);
171             }
172             OUTPUT:
173             RETVAL
174              
175             SV *
176             crypt_decrypt_string(self, obj_num, gen_num, data)
177             pdfmake_crypt_xs_t *self
178             int obj_num
179             int gen_num
180             SV *data
181             PREINIT:
182             const uint8_t *in;
183             STRLEN in_len;
184             uint8_t *out;
185             int out_len;
186             CODE:
187 3           in = (const uint8_t *)SvPV(data, in_len);
188            
189             /* Output is at most input length */
190 3           Newx(out, in_len, uint8_t);
191            
192 3           out_len = pdfmake_crypt_decrypt_string(&self->ctx, obj_num, gen_num,
193             in, in_len, out);
194            
195 3 50         if (out_len < 0) {
196 0           Safefree(out);
197 0           RETVAL = &PL_sv_undef;
198             } else {
199 3           RETVAL = newSVpvn((char *)out, out_len);
200 3           Safefree(out);
201             }
202             OUTPUT:
203             RETVAL
204              
205             SV *
206             crypt_encrypt_stream(self, data, obj_num, gen_num)
207             pdfmake_crypt_xs_t *self
208             SV *data
209             int obj_num
210             int gen_num
211             PREINIT:
212             const uint8_t *in;
213             STRLEN in_len;
214 2           uint8_t *out = NULL;
215 2           size_t out_len = 0;
216             int rc;
217             CODE:
218 2           in = (const uint8_t *)SvPV(data, in_len);
219            
220 2           rc = pdfmake_crypt_encrypt_stream(&self->ctx, obj_num, gen_num,
221             in, in_len, &out, &out_len);
222            
223 2 50         if (rc != 0 || out == NULL) {
    50          
224 0 0         if (out) free(out);
225 0           RETVAL = &PL_sv_undef;
226             } else {
227 2           RETVAL = newSVpvn((char *)out, out_len);
228 2           free(out);
229             }
230             OUTPUT:
231             RETVAL
232              
233             SV *
234             crypt_decrypt_stream(self, data, obj_num, gen_num)
235             pdfmake_crypt_xs_t *self
236             SV *data
237             int obj_num
238             int gen_num
239             PREINIT:
240             const uint8_t *in;
241             STRLEN in_len;
242 2           uint8_t *out = NULL;
243 2           size_t out_len = 0;
244             int rc;
245             CODE:
246 2           in = (const uint8_t *)SvPV(data, in_len);
247            
248 2           rc = pdfmake_crypt_decrypt_stream(&self->ctx, obj_num, gen_num,
249             in, in_len, &out, &out_len);
250            
251 2 50         if (rc != 0 || out == NULL) {
    50          
252 0 0         if (out) free(out);
253 0           RETVAL = &PL_sv_undef;
254             } else {
255 2           RETVAL = newSVpvn((char *)out, out_len);
256 2           free(out);
257             }
258             OUTPUT:
259             RETVAL
260              
261             #===============================================================================
262             # Permission checking
263             #===============================================================================
264              
265             int
266             crypt_has_permission(self, perm)
267             pdfmake_crypt_xs_t *self
268             int32_t perm
269             CODE:
270 3           RETVAL = pdfmake_crypt_has_permission(&self->ctx, perm);
271             OUTPUT:
272             RETVAL
273              
274             int32_t
275             crypt_get_permissions(self)
276             pdfmake_crypt_xs_t *self
277             CODE:
278 2           RETVAL = pdfmake_crypt_get_permissions(&self->ctx);
279             OUTPUT:
280             RETVAL
281              
282             #===============================================================================
283             # Getters for encryption parameters (for writing /Encrypt dict)
284             #===============================================================================
285              
286             int
287             crypt_get_V(self)
288             pdfmake_crypt_xs_t *self
289             CODE:
290 0 0         RETVAL = self->ctx.V;
291             OUTPUT:
292             RETVAL
293              
294             int
295             crypt_get_R(self)
296             pdfmake_crypt_xs_t *self
297             CODE:
298 0 0         RETVAL = self->ctx.R;
299             OUTPUT:
300             RETVAL
301              
302             int
303             crypt_get_key_length(self)
304             pdfmake_crypt_xs_t *self
305             CODE:
306 7 100         RETVAL = self->ctx.key_length * 8; /* Return in bits */
307             OUTPUT:
308             RETVAL
309              
310             SV *
311             crypt_get_O(self)
312             pdfmake_crypt_xs_t *self
313             CODE:
314 0 0         if (self->ctx.R >= 6) {
315 0           RETVAL = newSVpvn((char *)self->ctx.O, 48);
316             } else {
317 0           RETVAL = newSVpvn((char *)self->ctx.O, 32);
318             }
319             OUTPUT:
320             RETVAL
321              
322             SV *
323             crypt_get_U(self)
324             pdfmake_crypt_xs_t *self
325             CODE:
326 0 0         if (self->ctx.R >= 6) {
327 0           RETVAL = newSVpvn((char *)self->ctx.U, 48);
328             } else {
329 0           RETVAL = newSVpvn((char *)self->ctx.U, 32);
330             }
331             OUTPUT:
332             RETVAL
333              
334             SV *
335             crypt_get_OE(self)
336             pdfmake_crypt_xs_t *self
337             CODE:
338 0 0         if (self->ctx.R >= 6) {
339 0           RETVAL = newSVpvn((char *)self->ctx.OE, 32);
340             } else {
341 0           RETVAL = &PL_sv_undef;
342             }
343             OUTPUT:
344             RETVAL
345              
346             SV *
347             crypt_get_UE(self)
348             pdfmake_crypt_xs_t *self
349             CODE:
350 0 0         if (self->ctx.R >= 6) {
351 0           RETVAL = newSVpvn((char *)self->ctx.UE, 32);
352             } else {
353 0           RETVAL = &PL_sv_undef;
354             }
355             OUTPUT:
356             RETVAL
357              
358             SV *
359             crypt_get_Perms(self)
360             pdfmake_crypt_xs_t *self
361             CODE:
362 0 0         if (self->ctx.R >= 6) {
363 0           RETVAL = newSVpvn((char *)self->ctx.Perms, 16);
364             } else {
365 0           RETVAL = &PL_sv_undef;
366             }
367             OUTPUT:
368             RETVAL
369              
370             int32_t
371             crypt_get_P(self)
372             pdfmake_crypt_xs_t *self
373             CODE:
374 0 0         RETVAL = self->ctx.P;
375             OUTPUT:
376             RETVAL
377              
378             int
379             crypt_get_encrypt_metadata(self)
380             pdfmake_crypt_xs_t *self
381             CODE:
382 4 50         RETVAL = self->ctx.encrypt_metadata;
383             OUTPUT:
384             RETVAL
385              
386             void
387             crypt_set_encrypt_metadata(self, value)
388             pdfmake_crypt_xs_t *self
389             int value
390             CODE:
391 2           self->ctx.encrypt_metadata = value;
392              
393             BOOT:
394             {
395 90           HV *stash = gv_stashpv("PDF::Make::Crypt", GV_ADD);
396 90 50         PDFMAKE_REGISTER_GETTER(stash, "version", pdfmake_crypt_xs_t, ctx.V, PDFMAKE_FIELD_INT);
    0          
397 90 50         PDFMAKE_REGISTER_GETTER(stash, "revision", pdfmake_crypt_xs_t, ctx.R, PDFMAKE_FIELD_INT);
    0          
398 90 50         PDFMAKE_REGISTER_GETTER(stash, "permissions", pdfmake_crypt_xs_t, ctx.P, PDFMAKE_FIELD_INT);
    0          
399 90 50         PDFMAKE_REGISTER_GETTER(stash, "encrypt_metadata", pdfmake_crypt_xs_t, ctx.encrypt_metadata, PDFMAKE_FIELD_INT);
    0          
400             }