Branch data Line data Source code
1 : : /* -*- mode: C -*-
2 : : *
3 : : * File: pdf-stm-f-v2.c
4 : : * Date: Tue Jul 10 23:44:00 2007
5 : : *
6 : : * GNU PDF Library - V2 stream filter
7 : : *
8 : : */
9 : :
10 : : /* Copyright (C) 2008-2011 Free Software Foundation, Inc. */
11 : :
12 : : /* This program is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU General Public License as published by
14 : : * the Free Software Foundation, either version 3 of the License, or
15 : : * (at your option) any later version.
16 : : *
17 : : * This program is distributed in the hope that it will be useful,
18 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : : * GNU General Public License for more details.
21 : : *
22 : : * You should have received a copy of the GNU General Public License
23 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : : */
25 : :
26 : : #include <config.h>
27 : :
28 : : #include <pdf-types.h>
29 : : #include <pdf-types-buffer.h>
30 : : #include <pdf-hash.h>
31 : : #include <pdf-alloc.h>
32 : : #include <pdf-crypt.h>
33 : : #include <pdf-stm-f-v2.h>
34 : : #include <pdf-hash-helper.h>
35 : :
36 : : /* Define V2 encoder */
37 : 20 : PDF_STM_FILTER_DEFINE (pdf_stm_f_v2enc_get,
38 : : stm_f_v2_init,
39 : : stm_f_v2enc_apply,
40 : : stm_f_v2_deinit);
41 : :
42 : : /* Define V2 decoder */
43 : 0 : PDF_STM_FILTER_DEFINE (pdf_stm_f_v2dec_get,
44 : : stm_f_v2_init,
45 : : stm_f_v2dec_apply,
46 : : stm_f_v2_deinit);
47 : :
48 : : #define V2_PARAM_KEY "Key"
49 : : #define V2_PARAM_KEY_SIZE "KeySize"
50 : :
51 : : /* Encryption and decryption */
52 : : typedef enum {
53 : : PDF_STM_F_V2_MODE_ENCODE,
54 : : PDF_STM_F_V2_MODE_DECODE
55 : : } pdf_stm_f_v2_mode_e;
56 : :
57 : : /* Internal state */
58 : : struct pdf_stm_f_v2_s
59 : : {
60 : : pdf_crypt_cipher_t *cipher;
61 : :
62 : : pdf_char_t *key;
63 : : pdf_size_t keysize;
64 : : };
65 : :
66 : : /* Common implementation */
67 : :
68 : : static pdf_bool_t
69 : 20 : stm_f_v2_init (const pdf_hash_t *params,
70 : : void **state,
71 : : pdf_error_t **error)
72 : : {
73 : : struct pdf_stm_f_v2_s *filter_state;
74 : : const pdf_char_t *key;
75 : : pdf_size_t keysize;
76 : :
77 : : /* We demand all parameters are present */
78 [ + - ][ + - ]: 20 : if (!params ||
[ - + ]
79 : : !pdf_hash_key_p (params, V2_PARAM_KEY) ||
80 : : !pdf_hash_key_p (params, V2_PARAM_KEY_SIZE))
81 : : {
82 [ # # ][ # # ]: 0 : pdf_set_error (error,
[ # # ][ # # ]
83 : : PDF_EDOMAIN_BASE_STM,
84 : : PDF_EBADDATA,
85 : : "cannot initialize V2 encoder/decoder: "
86 : : "parameters missing ('Key': %s, 'KeySize': %s)",
87 : : ((params && pdf_hash_key_p (params, V2_PARAM_KEY)) ?
88 : : "available" : "missing"),
89 : : ((params && pdf_hash_key_p (params, V2_PARAM_KEY_SIZE)) ?
90 : : "available" : "missing"));
91 : 0 : return PDF_FALSE;
92 : : }
93 : :
94 : 20 : filter_state = pdf_alloc (sizeof (struct pdf_stm_f_v2_s));
95 [ - + ]: 20 : if (!filter_state)
96 : : {
97 : 0 : pdf_set_error (error,
98 : : PDF_EDOMAIN_BASE_STM,
99 : : PDF_ENOMEM,
100 : : "cannot create V2 encoder/decoder internal state: "
101 : : "couldn't allocate %lu bytes",
102 : : (unsigned long)sizeof (struct pdf_stm_f_v2_s));
103 : 0 : return PDF_FALSE;
104 : : }
105 : :
106 : 20 : filter_state->cipher = NULL;
107 : :
108 : : /* Note that Key may NOT be NUL-terminated */
109 : 20 : key = pdf_hash_get_value (params, V2_PARAM_KEY);
110 : 20 : keysize = pdf_hash_get_size (params, V2_PARAM_KEY_SIZE);
111 : :
112 : : /* Keep a copy of the key in the filter */
113 : 20 : filter_state->key = (pdf_char_t *)pdf_alloc (keysize);
114 [ - + ]: 20 : if (!filter_state->key)
115 : : {
116 : 0 : pdf_set_error (error,
117 : : PDF_EDOMAIN_BASE_STM,
118 : : PDF_ENOMEM,
119 : : "cannot copy V2 key: "
120 : : "couldn't allocate %lu bytes",
121 : : (unsigned long)keysize);
122 : 0 : stm_f_v2_deinit (filter_state);
123 : 0 : return PDF_FALSE;
124 : : }
125 : 20 : filter_state->keysize = keysize;
126 : 20 : memcpy (filter_state->key, key, keysize);
127 : :
128 : 20 : filter_state->cipher = pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, error);
129 [ - + ]: 20 : if (!filter_state->cipher)
130 : : {
131 : 0 : stm_f_v2_deinit (filter_state);
132 : 0 : return PDF_FALSE;
133 : : }
134 : :
135 [ - + ]: 20 : if (!pdf_crypt_cipher_set_key (filter_state->cipher,
136 : : filter_state->key,
137 : : filter_state->keysize,
138 : : error))
139 : : {
140 : 0 : stm_f_v2_deinit (filter_state);
141 : 0 : return PDF_FALSE;
142 : : }
143 : :
144 : 20 : *state = filter_state;
145 : 20 : return PDF_TRUE;
146 : : }
147 : :
148 : : static void
149 : 20 : stm_f_v2_deinit (void *state)
150 : : {
151 : 20 : struct pdf_stm_f_v2_s *filter_state = state;
152 : :
153 [ + - ]: 20 : if (filter_state->cipher)
154 : 20 : pdf_crypt_cipher_destroy (filter_state->cipher);
155 [ + - ]: 20 : if (filter_state->key)
156 : 20 : pdf_dealloc (filter_state->key);
157 : 20 : pdf_dealloc (state);
158 : 20 : }
159 : :
160 : : static enum pdf_stm_filter_apply_status_e
161 : 88 : stm_f_v2_apply (pdf_stm_f_v2_mode_e mode,
162 : : void *state,
163 : : pdf_buffer_t *in,
164 : : pdf_buffer_t *out,
165 : : pdf_bool_t finish,
166 : : pdf_error_t **error)
167 : : {
168 : 88 : struct pdf_stm_f_v2_s *filter_state = state;
169 : : pdf_size_t in_size;
170 : : pdf_size_t out_size;
171 : : pdf_size_t bytes_to_copy;
172 : : pdf_size_t written;
173 : :
174 [ - + ]: 88 : PDF_ASSERT (in->wp >= in->rp);
175 [ - + ]: 88 : PDF_ASSERT (out->size >= out->wp);
176 : :
177 : 88 : in_size = in->wp - in->rp;
178 : 88 : out_size = out->size - out->wp;
179 : :
180 : 88 : bytes_to_copy = PDF_MIN (out_size, in_size);
181 : :
182 [ + + ]: 88 : if (bytes_to_copy != 0)
183 : : {
184 [ + - - ]: 20 : switch (mode)
185 : : {
186 : : case PDF_STM_F_V2_MODE_ENCODE:
187 : : {
188 [ - + ]: 20 : if (!pdf_crypt_cipher_encrypt (filter_state->cipher,
189 : : (pdf_char_t *)out->data,
190 : : out_size,
191 : : (const pdf_char_t *)in->data,
192 : : in_size,
193 : : &written,
194 : : error))
195 : 0 : return PDF_STM_FILTER_APPLY_STATUS_ERROR;
196 : : break;
197 : : }
198 : : case PDF_STM_F_V2_MODE_DECODE:
199 : : {
200 [ # # ]: 0 : if (!pdf_crypt_cipher_decrypt (filter_state->cipher,
201 : : (pdf_char_t *)out->data,
202 : : out_size,
203 : : (const pdf_char_t *)in->data,
204 : : in_size,
205 : : &written,
206 : : error))
207 : 0 : return PDF_STM_FILTER_APPLY_STATUS_ERROR;
208 : : break;
209 : : }
210 : : }
211 : :
212 : 20 : in->rp += bytes_to_copy;
213 : 20 : out->wp += written;
214 : : }
215 : :
216 [ - + ]: 88 : return (in_size > out_size ?
217 : : PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT :
218 : : PDF_STM_FILTER_APPLY_STATUS_NO_INPUT);
219 : : }
220 : :
221 : : /* Encode filter */
222 : :
223 : : static enum pdf_stm_filter_apply_status_e
224 : 88 : stm_f_v2enc_apply (void *state,
225 : : pdf_buffer_t *in,
226 : : pdf_buffer_t *out,
227 : : pdf_bool_t finish,
228 : : pdf_error_t **error)
229 : : {
230 : 88 : return stm_f_v2_apply (PDF_STM_F_V2_MODE_ENCODE,
231 : : state,
232 : : in,
233 : : out,
234 : : finish,
235 : : error);
236 : : }
237 : :
238 : : /* Decode filter */
239 : :
240 : : static enum pdf_stm_filter_apply_status_e
241 : 0 : stm_f_v2dec_apply (void *state,
242 : : pdf_buffer_t *in,
243 : : pdf_buffer_t *out,
244 : : pdf_bool_t finish,
245 : : pdf_error_t **error)
246 : : {
247 : 0 : return stm_f_v2_apply (PDF_STM_F_V2_MODE_DECODE,
248 : : state,
249 : : in,
250 : : out,
251 : : finish,
252 : : error);
253 : : }
254 : :
255 : : /* End of pdf_stm_f_v2.c */
|