1 : /* -*- mode: C -*-
2 : *
3 : * File: pdf-crypt.c
4 : * Date: Fri Feb 22 21:05:05 2008
5 : *
6 : * GNU PDF Library - Header file for encryption module
7 : *
8 : */
9 :
10 : /* Copyright (C) 2008 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 : #ifndef PDF_CRYPT_H
27 : #define PDF_CRYPT_H
28 :
29 : #include <config.h>
30 :
31 : #include <string.h>
32 :
33 : #include <pdf-types.h>
34 : #include <pdf-error.h>
35 : #include <pdf-alloc.h>
36 : #include <pdf-crypt-c-aesv2.h>
37 : #include <pdf-crypt-c-v2.h>
38 :
39 : /* BEGIN PUBLIC */
40 :
41 : enum pdf_crypt_md_algo_e
42 : {
43 : PDF_CRYPT_MD_MD5
44 : };
45 :
46 : enum pdf_crypt_cipher_algo_e
47 : {
48 : PDF_CRYPT_CIPHER_ALGO_AESV2,
49 : PDF_CRYPT_CIPHER_ALGO_V2
50 : };
51 :
52 : typedef struct pdf_crypt_cipher_s *pdf_crypt_cipher_t;
53 : typedef struct pdf_crypt_md_s *pdf_crypt_md_t;
54 :
55 : /* END PUBLIC */
56 :
57 :
58 : struct pdf_crypt_cipher_algo_s
59 : {
60 : pdf_status_t (*new) (void ** cipher);
61 :
62 : pdf_status_t (*setkey) (void * cipher, pdf_char_t *key, pdf_size_t size);
63 :
64 : pdf_status_t (*encrypt) (void * cipher,
65 : pdf_char_t *out, pdf_size_t out_size,
66 : pdf_char_t *in, pdf_size_t in_size,
67 : pdf_size_t *result_size);
68 :
69 : pdf_status_t (*decrypt) (void * cipher,
70 : pdf_char_t *out, pdf_size_t out_size,
71 : pdf_char_t *in, pdf_size_t in_sizem,
72 : pdf_size_t *result_size);
73 :
74 : pdf_status_t (*destroy) (void * cipher);
75 : };
76 :
77 : typedef struct pdf_crypt_cipher_algo_s *pdf_crypt_cipher_algo_t;
78 :
79 : struct pdf_crypt_cipher_s
80 : {
81 : pdf_crypt_cipher_algo_t algo;
82 : void * raw;
83 : };
84 :
85 : struct pdf_crypt_md_s
86 : {
87 : void * raw;
88 : };
89 :
90 :
91 : #if !defined HAVE_INLINE && !defined COMPILING_PDF_CRYPT
92 :
93 :
94 : pdf_status_t pdf_crypt_init (void);
95 :
96 :
97 : /* BEGIN PUBLIC */
98 :
99 : pdf_status_t pdf_crypt_nonce (pdf_char_t * buffer, pdf_size_t size);
100 :
101 : pdf_status_t pdf_crypt_cipher_new (enum pdf_crypt_cipher_algo_e algorithm,
102 : pdf_crypt_cipher_t *cipher);
103 :
104 : pdf_status_t pdf_crypt_cipher_setkey (pdf_crypt_cipher_t cipher,
105 : pdf_char_t *key,
106 : pdf_size_t size);
107 :
108 : pdf_status_t pdf_crypt_cipher_encrypt (pdf_crypt_cipher_t cipher,
109 : pdf_char_t *out,
110 : pdf_size_t out_size,
111 : pdf_char_t *in,
112 : pdf_size_t in_size,
113 : pdf_size_t *result_size);
114 :
115 : pdf_status_t pdf_crypt_cipher_decrypt (pdf_crypt_cipher_t cipher,
116 : pdf_char_t *out,
117 : pdf_size_t out_size,
118 : pdf_char_t *in,
119 : pdf_size_t in_size,
120 : pdf_size_t *result_size);
121 :
122 : pdf_status_t pdf_crypt_cipher_destroy (pdf_crypt_cipher_t cipher);
123 :
124 :
125 : pdf_status_t pdf_crypt_md_new (enum pdf_crypt_md_algo_e algo, pdf_crypt_md_t *md);
126 :
127 : pdf_status_t pdf_crypt_md_write (pdf_crypt_md_t md,
128 : pdf_char_t *in, pdf_size_t in_size);
129 :
130 : pdf_status_t pdf_crypt_md_read (pdf_crypt_md_t md,
131 : pdf_char_t *out, pdf_size_t out_size);
132 :
133 :
134 : pdf_status_t pdf_crypt_md_destroy (pdf_crypt_md_t hd);
135 :
136 :
137 :
138 : /* END PUBLIC */
139 :
140 : #else
141 :
142 : #if defined COMPILING_PDF_CRYPT
143 : # define STATIC_INLINE
144 : #else
145 : # define STATIC_INLINE static inline
146 : #endif /* COMPILING_PDF_CRYPT */
147 :
148 :
149 : #include <gcrypt.h>
150 :
151 :
152 : STATIC_INLINE pdf_status_t
153 : pdf_crypt_init (void)
154 0 : {
155 749 : gcry_check_version (GCRYPT_VERSION);
156 749 : return PDF_OK;
157 : }
158 :
159 :
160 : STATIC_INLINE pdf_status_t
161 : pdf_crypt_nonce (pdf_char_t * buffer, pdf_size_t size)
162 1 : {
163 1 : gcry_create_nonce (buffer, size);
164 1 : return PDF_OK;
165 : }
166 :
167 :
168 :
169 : STATIC_INLINE pdf_status_t
170 : pdf_crypt_cipher_new (enum pdf_crypt_cipher_algo_e algorithm,
171 : pdf_crypt_cipher_t *cipher)
172 14 : {
173 : pdf_status_t status;
174 : pdf_crypt_cipher_algo_t cipher_algo;
175 :
176 54 : *cipher = pdf_alloc (sizeof(struct pdf_crypt_cipher_s));
177 54 : cipher_algo = pdf_alloc (sizeof(struct pdf_crypt_cipher_algo_s));
178 :
179 54 : switch (algorithm)
180 : {
181 : case PDF_CRYPT_CIPHER_ALGO_AESV2:
182 : {
183 29 : cipher_algo->new = pdf_crypt_cipher_aesv2_new;
184 29 : cipher_algo->setkey = pdf_crypt_cipher_aesv2_setkey;
185 29 : cipher_algo->encrypt = pdf_crypt_cipher_aesv2_encrypt;
186 29 : cipher_algo->decrypt = pdf_crypt_cipher_aesv2_decrypt;
187 29 : cipher_algo->destroy = pdf_crypt_cipher_aesv2_destroy;
188 9 : break;
189 : }
190 : case PDF_CRYPT_CIPHER_ALGO_V2:
191 : {
192 25 : cipher_algo->new = pdf_crypt_cipher_v2_new;
193 25 : cipher_algo->setkey = pdf_crypt_cipher_v2_setkey;
194 25 : cipher_algo->encrypt = pdf_crypt_cipher_v2_encrypt;
195 25 : cipher_algo->decrypt = pdf_crypt_cipher_v2_decrypt;
196 25 : cipher_algo->destroy = pdf_crypt_cipher_v2_destroy;
197 5 : break;
198 : }
199 : default:
200 : {
201 : /* Not reached, but makes stupid compilers happy */
202 0 : return PDF_ERROR;
203 : break;
204 : }
205 : }
206 :
207 54 : if (cipher_algo->new (&(*cipher)->raw) == PDF_OK)
208 : {
209 54 : (*cipher)->algo = cipher_algo;
210 54 : status = PDF_OK;
211 : }
212 : else
213 0 : status = PDF_ERROR;
214 :
215 54 : return status;
216 : }
217 :
218 :
219 : STATIC_INLINE pdf_status_t
220 : pdf_crypt_cipher_setkey (pdf_crypt_cipher_t cipher,
221 : pdf_char_t *key, pdf_size_t size)
222 10 : {
223 50 : return cipher->algo->setkey (cipher->raw, key, size);
224 : }
225 :
226 :
227 : STATIC_INLINE pdf_status_t
228 : pdf_crypt_cipher_encrypt (pdf_crypt_cipher_t cipher,
229 : pdf_char_t *out, pdf_size_t out_size,
230 : pdf_char_t *in, pdf_size_t in_size,
231 : pdf_size_t *result_size)
232 7 : {
233 57 : return cipher->algo->encrypt (cipher->raw, out, out_size, in, in_size, result_size);
234 : }
235 :
236 :
237 : STATIC_INLINE pdf_status_t
238 : pdf_crypt_cipher_decrypt (pdf_crypt_cipher_t cipher,
239 : pdf_char_t *out, pdf_size_t out_size,
240 : pdf_char_t *in, pdf_size_t in_size,
241 : pdf_size_t *result_size)
242 8 : {
243 38 : return cipher->algo->decrypt (cipher->raw, out, out_size, in, in_size, result_size);
244 : }
245 :
246 :
247 : STATIC_INLINE pdf_status_t
248 : pdf_crypt_cipher_destroy (pdf_crypt_cipher_t cipher)
249 14 : {
250 : pdf_status_t ret;
251 :
252 54 : ret = cipher->algo->destroy (cipher->raw);
253 54 : pdf_dealloc (cipher->algo);
254 54 : pdf_dealloc (cipher);
255 54 : return ret;
256 : }
257 :
258 :
259 : /* Hashing functions */
260 :
261 :
262 : STATIC_INLINE pdf_status_t
263 : pdf_crypt_md_new (enum pdf_crypt_md_algo_e algo, pdf_crypt_md_t *_md)
264 8 : {
265 : pdf_crypt_md_t md;
266 : gcry_md_hd_t * raw;
267 : pdf_status_t ret;
268 :
269 8 : md = pdf_alloc (sizeof(struct pdf_crypt_md_s));
270 :
271 8 : if (algo == PDF_CRYPT_MD_MD5)
272 : {
273 7 : raw = pdf_alloc (sizeof(gcry_md_hd_t));
274 :
275 7 : if (gcry_md_open (raw, GCRY_MD_MD5, 0) == GPG_ERR_NO_ERROR)
276 : {
277 7 : md->raw = raw;
278 7 : *_md = md;
279 7 : ret = PDF_OK;
280 : }
281 : else
282 : {
283 0 : gcry_md_close (*raw);
284 0 : ret = PDF_ERROR;
285 : }
286 : }
287 : else
288 : {
289 1 : ret = PDF_EBADDATA;
290 : }
291 :
292 8 : return ret;
293 : }
294 :
295 :
296 :
297 : STATIC_INLINE pdf_status_t
298 : pdf_crypt_md_write (pdf_crypt_md_t md,
299 : pdf_char_t *in, pdf_size_t in_size)
300 5 : {
301 5 : gcry_md_hd_t * gcry_md = md->raw;
302 5 : gcry_md_write (*gcry_md, in, in_size);
303 5 : return PDF_OK;
304 : }
305 :
306 :
307 : STATIC_INLINE pdf_status_t
308 : pdf_crypt_md_read (pdf_crypt_md_t md,
309 : pdf_char_t *out, pdf_size_t out_size)
310 4 : {
311 4 : gcry_md_hd_t * gcry_md = md->raw;
312 4 : pdf_size_t required_size = gcry_md_get_algo_dlen (GCRY_MD_MD5);
313 :
314 4 : if (out_size < required_size)
315 1 : return PDF_EBADDATA;
316 :
317 3 : if (gcry_md_final (*gcry_md) != GPG_ERR_NO_ERROR)
318 : {
319 0 : return PDF_ERROR;
320 : }
321 : else
322 : {
323 : void * hash;
324 :
325 3 : hash = gcry_md_read (*gcry_md, GCRY_MD_MD5);
326 :
327 3 : if (hash == NULL)
328 0 : return PDF_ERROR;
329 : else
330 : {
331 3 : memcpy (out, hash, required_size);
332 : }
333 :
334 3 : gcry_md_reset (*gcry_md);
335 3 : return PDF_OK;
336 : }
337 : }
338 :
339 :
340 :
341 : STATIC_INLINE pdf_status_t
342 : pdf_crypt_md_destroy (pdf_crypt_md_t md)
343 7 : {
344 7 : pdf_dealloc (md->raw);
345 7 : pdf_dealloc (md);
346 7 : return PDF_OK;
347 : }
348 :
349 :
350 :
351 : #endif /* COMPILING_PDF_CRYPT */
352 : #endif /* PDF_CRYPT_H */
353 :
354 : /* End of pdf-crypt.h */
|