1 : /* -*- mode: C -*-
2 : *
3 : * File: pdf-crypt.c
4 : * Date: Fri Feb 22 21:05:05 2008
5 : *
6 : * GNU PDF Library - AESV2 backend 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 : #include <config.h>
27 :
28 : #include <stdlib.h>
29 : #include <string.h>
30 : #include <gcrypt.h>
31 :
32 : #include <pdf-alloc.h>
33 : #include <pdf-types.h>
34 : #include <pdf-error.h>
35 : #include <pdf-crypt-c-aesv2.h>
36 : #include <pdf-hash-helper.h>
37 :
38 : #define AESV2_BLKSIZE 16 /* Size of a block in AES128 */
39 :
40 :
41 : struct aesv2_state_s
42 : {
43 : gcry_cipher_hd_t cipher;
44 : pdf_bool_t first_block;
45 : };
46 :
47 : typedef struct aesv2_state_s * aesv2_state_t;
48 :
49 :
50 : /* Creation and destruction of aesv2 ciphers */
51 :
52 : pdf_status_t
53 : pdf_crypt_cipher_aesv2_new (void ** out)
54 12 : {
55 : aesv2_state_t state;
56 :
57 12 : state = pdf_alloc (sizeof(struct aesv2_state_s));
58 :
59 12 : if (state != NULL)
60 : {
61 : gcry_error_t err;
62 :
63 12 : err = gcry_cipher_open (&state->cipher, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
64 12 : state->first_block = PDF_TRUE;
65 :
66 12 : if (err == GPG_ERR_NO_ERROR)
67 : {
68 12 : *out = state;
69 12 : return PDF_OK;
70 : }
71 : else
72 : {
73 0 : pdf_dealloc (state);
74 0 : return PDF_ERROR;
75 : }
76 : }
77 : else
78 : {
79 0 : pdf_dealloc (state);
80 0 : return PDF_ENOMEM;
81 : }
82 :
83 : return PDF_OK;
84 : }
85 :
86 :
87 :
88 : pdf_status_t
89 : pdf_crypt_cipher_aesv2_destroy (void * _state)
90 12 : {
91 12 : aesv2_state_t state = _state;
92 12 : gcry_cipher_close (state->cipher);
93 12 : pdf_dealloc (state);
94 12 : return PDF_OK;
95 : }
96 :
97 :
98 :
99 : /* Encryption and decryption functions */
100 :
101 : pdf_status_t
102 : pdf_crypt_cipher_aesv2_setkey (void * _state,
103 : pdf_char_t *key, pdf_size_t size)
104 10 : {
105 10 : aesv2_state_t state = _state;
106 :
107 10 : if (gcry_cipher_setkey (state->cipher, key, size) == GPG_ERR_NO_ERROR)
108 : {
109 9 : return PDF_OK;
110 : }
111 : else
112 : {
113 1 : return PDF_EBADAESKEY;
114 : }
115 : }
116 :
117 :
118 :
119 : pdf_status_t
120 : pdf_crypt_cipher_aesv2_encrypt (void * _state,
121 : pdf_char_t *out, pdf_size_t out_size,
122 : pdf_char_t *in, pdf_size_t in_size,
123 : pdf_size_t *result_size)
124 15 : {
125 15 : aesv2_state_t state = _state;
126 : pdf_char_t * output;
127 : pdf_size_t output_size;
128 : pdf_char_t * input;
129 : pdf_size_t input_size;
130 :
131 15 : if (in_size < AESV2_BLKSIZE || in_size % AESV2_BLKSIZE != 0)
132 0 : return PDF_EBADDATA;
133 :
134 15 : if (out_size < in_size)
135 0 : return PDF_EBADDATA;
136 :
137 : /* If we are at first block, then we have found the IV vector */
138 15 : if (state->first_block == PDF_TRUE)
139 : {
140 4 : pdf_char_t * iv = in;
141 4 : gcry_cipher_setiv (state->cipher, iv, AESV2_BLKSIZE);
142 4 : input = in + AESV2_BLKSIZE;
143 4 : input_size = in_size - AESV2_BLKSIZE;
144 :
145 4 : memcpy (out, iv, AESV2_BLKSIZE);
146 :
147 4 : output = out + AESV2_BLKSIZE;
148 4 : output_size = out_size - AESV2_BLKSIZE;
149 :
150 4 : state->first_block = PDF_FALSE;
151 : }
152 : else
153 : {
154 11 : output = out;
155 11 : output_size = out_size;
156 11 : input = in;
157 11 : input_size = in_size;
158 : }
159 :
160 15 : if (gcry_cipher_encrypt (state->cipher, output, output_size, input, input_size) != GPG_ERR_NO_ERROR)
161 : {
162 0 : return PDF_ERROR;
163 : }
164 :
165 15 : if (result_size != NULL)
166 0 : *result_size = in_size;
167 :
168 15 : return PDF_OK;
169 : }
170 :
171 :
172 :
173 :
174 : pdf_status_t
175 : pdf_crypt_cipher_aesv2_decrypt (void * _state,
176 : pdf_char_t *out, pdf_size_t out_size,
177 : pdf_char_t *in, pdf_size_t in_size,
178 : pdf_size_t *result_size)
179 10 : {
180 10 : aesv2_state_t state = _state;
181 : pdf_char_t * output;
182 : pdf_size_t output_size;
183 : pdf_char_t * input;
184 : pdf_size_t input_size;
185 :
186 10 : if (in_size < AESV2_BLKSIZE || in_size % AESV2_BLKSIZE != 0)
187 0 : return PDF_EBADDATA;
188 :
189 10 : if (out_size < in_size)
190 0 : return PDF_EBADDATA;
191 :
192 : /* If we are at first block, then we have found the IV vector */
193 10 : if (state->first_block == PDF_TRUE)
194 : {
195 4 : pdf_char_t * iv = in;
196 4 : gcry_cipher_setiv (state->cipher, iv, AESV2_BLKSIZE);
197 4 : input = in + AESV2_BLKSIZE;
198 4 : input_size = in_size - AESV2_BLKSIZE;
199 :
200 4 : memcpy (out, iv, AESV2_BLKSIZE);
201 :
202 4 : output = out + AESV2_BLKSIZE;
203 4 : output_size = out_size - AESV2_BLKSIZE;
204 :
205 4 : state->first_block = PDF_FALSE;
206 : }
207 : else
208 : {
209 6 : output = out;
210 6 : output_size = out_size;
211 6 : input = in;
212 6 : input_size = in_size;
213 : }
214 :
215 10 : if (gcry_cipher_decrypt (state->cipher, output, output_size, input, input_size) != GPG_ERR_NO_ERROR)
216 : {
217 0 : return PDF_ERROR;
218 : }
219 :
220 10 : if (result_size != NULL)
221 0 : *result_size = in_size;
222 :
223 10 : return PDF_OK;
224 : }
225 :
226 :
227 :
228 :
229 :
230 : /* End of pdf-crypt-c-aesv2.c */
|