Version 3.0.12.
[pwmd.git] / src / convert.c
blob6794879411a7c3c082259489e681f2a4fe4e310c
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <fcntl.h>
25 #include <sys/stat.h>
26 #include <zlib.h>
27 #include <errno.h>
29 #include "pwmd-error.h"
30 #include <gcrypt.h>
31 #include "convert.h"
32 #include "xml.h"
33 #include "mem.h"
34 #include "util-misc.h"
35 #include "cache.h"
36 #include "crypto.h"
37 #include "pinentry.h"
39 #ifndef _
40 #include "gettext.h"
41 #define _(msgid) gettext(msgid)
42 #endif
44 #define KEYSIZE 32
46 typedef struct
48 uint8_t magic[5];
49 uint16_t version;
50 uint64_t iter;
51 uint64_t flags;
52 uint8_t iv[16];
53 uint8_t salt[8];
54 } v2_file_header_t;
56 struct gz_s
58 z_stream z;
59 void *out;
60 int done;
63 static unsigned char crypto_magic[5] = "\177PWMD";
65 static void
66 gz_cleanup (void *arg)
68 struct gz_s **gz = (struct gz_s **) arg;
70 if (!gz)
71 return;
73 if (!(*gz)->done && (*gz)->out)
74 gcry_free ((*gz)->out);
76 if ((*gz)->z.zalloc)
77 inflateEnd (&(*gz)->z);
79 xfree (*gz);
80 *gz = NULL;
83 static void *
84 z_alloc (void *data, unsigned items, unsigned size)
86 return gcry_calloc (items, size);
89 static void
90 z_free (void *data, void *p)
92 gcry_free (p);
95 #define ZLIB_BUFSIZE 65536
97 static gpg_error_t
98 decompress (void *in, unsigned long insize, void * *out,
99 unsigned long *outsize)
101 struct gz_s *gz;
102 gz_header h;
103 char buf[17];
104 gpg_error_t rc;
105 int zrc;
107 gz = xcalloc (1, sizeof (struct gz_s));
108 if (!gz)
109 return GPG_ERR_ENOMEM;
111 gz->z.zalloc = z_alloc;
112 gz->z.zfree = z_free;
113 gz->z.next_in = in;
114 gz->z.avail_in = (uInt) insize;
115 gz->z.avail_out = ZLIB_BUFSIZE;
116 gz->z.next_out = gz->out = gcry_malloc (ZLIB_BUFSIZE);
117 if (!gz->out)
119 gz_cleanup (&gz);
120 return GPG_ERR_ENOMEM;
123 zrc = inflateInit2 (&gz->z, 47);
124 if (zrc != Z_OK)
126 gz_cleanup (&gz);
127 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
130 memset (&h, 0, sizeof (gz_header));
131 h.comment = (unsigned char *) buf;
132 h.comm_max = sizeof (buf);
133 zrc = inflateGetHeader (&gz->z, &h);
134 if (zrc != Z_OK)
136 gz_cleanup (&gz);
137 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
140 zrc = inflate (&gz->z, Z_BLOCK);
141 if (zrc != Z_OK)
143 gz_cleanup (&gz);
144 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
147 if (h.comment)
148 insize = strtoul ((char *) h.comment, NULL, 10);
152 void *p;
154 zrc = inflate (&gz->z, Z_FINISH);
155 switch (zrc)
157 case Z_OK:
158 break;
159 case Z_BUF_ERROR:
160 if (!gz->z.avail_out)
162 p = gcry_realloc (gz->out, gz->z.total_out + ZLIB_BUFSIZE);
163 if (!p)
165 rc = GPG_ERR_ENOMEM;
166 goto fail;
169 gz->out = p;
170 gz->z.next_out = (unsigned char *) gz->out + gz->z.total_out;
171 gz->z.avail_out = ZLIB_BUFSIZE;
173 else
175 rc = GPG_ERR_COMPR_ALGO;
176 goto fail;
179 break;
180 case Z_STREAM_END:
181 break;
182 default:
183 rc = GPG_ERR_COMPR_ALGO;
184 goto fail;
185 break;
188 while (zrc != Z_STREAM_END);
190 *out = gz->out;
191 *outsize = gz->z.total_out;
192 gz->done = 1;
193 gz_cleanup (&gz);
194 return 0;
196 fail:
197 gz_cleanup (&gz);
198 return rc;
201 static gpg_error_t
202 decrypt (v2_file_header_t * fh, unsigned char *key,
203 unsigned char **ciphertext, size_t datalen, void * *result,
204 size_t * result_len)
206 gpg_error_t rc;
207 size_t blocksize, keysize, len;
208 int algo = cipher_to_gcrypt (fh->flags);
209 gcry_cipher_hd_t gh = NULL;
210 uint64_t iter = 0ULL;
211 unsigned char *data = *ciphertext;
213 *result = NULL;
214 *result_len = 0;
216 /* No encryption iterations. This is a plain (gzipped) file. */
217 if (!fh->iter)
218 goto decompress;
220 if (algo == -1)
221 return GPG_ERR_CIPHER_ALGO;
223 rc = gcry_cipher_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, NULL);
224 if (rc)
225 return rc;
227 rc = gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
228 if (rc)
229 return rc;
231 rc = gcry_cipher_algo_info (algo, GCRYCTL_GET_BLKLEN, NULL, &blocksize);
232 if (rc)
233 return rc;
235 rc = gcry_cipher_open (&gh, algo, GCRY_CIPHER_MODE_CBC, 0);
236 if (rc)
237 return rc;
239 if ((rc = gcry_cipher_setiv (gh, fh->iv, blocksize)))
240 goto fail;
242 if ((rc = gcry_cipher_setkey (gh, key, keysize)))
243 goto fail;
245 rc = gcry_cipher_decrypt (gh, data, datalen, NULL, 0);
246 if (rc)
247 goto fail;
249 key[0] ^= 1;
250 if ((rc = gcry_cipher_setkey (gh, key, keysize)))
251 goto fail;
253 while (++iter < fh->iter)
255 if ((rc = gcry_cipher_setiv (gh, fh->iv, blocksize)))
256 goto fail;
258 rc = gcry_cipher_decrypt (gh, data, datalen, NULL, 0);
259 if (rc)
260 goto fail;
263 decompress:
264 len = 0;
265 if (fh->version >= 0x218 && fh->iter > 0ULL)
267 if (memcmp (data, crypto_magic, sizeof (crypto_magic)))
269 rc = GPG_ERR_BAD_PASSPHRASE;
270 goto fail;
273 len = sizeof (crypto_magic);
276 rc =
277 decompress (data + len, datalen - len, result,
278 (unsigned long *) result_len);
279 if (rc)
281 if (fh->version < 0x218 && rc == GPG_ERR_COMPR_ALGO)
282 rc = GPG_ERR_BAD_PASSPHRASE;
283 goto fail;
286 if (strncasecmp ((char *) *result, "<?xml ", 6) != 0)
288 gcry_free (*result);
289 *result = NULL;
290 *result_len = 0;
291 rc = GPG_ERR_BAD_PASSPHRASE;
292 goto fail;
295 fail:
296 if (gh)
297 gcry_cipher_close (gh);
299 return rc;
302 gpg_error_t
303 read_v2_datafile (const char *filename, const char *keyfile,
304 void * *result, size_t * result_len, uint16_t * ver,
305 int *algo)
307 gpg_error_t rc;
308 int fd;
309 v2_file_header_t fh;
310 size_t len, passphraselen, datalen;
311 #ifdef WITH_AGENT
312 struct agent_s *agent = NULL;
313 #endif
314 char *passphrase = NULL;
315 unsigned char *data = NULL;
316 struct stat st;
317 unsigned char *key = NULL;
318 FILE *fp;
320 if (stat (filename, &st) == -1)
321 return gpg_error_from_errno (errno);
323 fd = open (filename, O_RDONLY);
324 if (fd == -1)
325 return gpg_error_from_errno (errno);
327 len = read (fd, &fh, sizeof (fh) - 8);
328 if (len != sizeof (fh) - 8)
330 rc = GPG_ERR_INV_LENGTH;
331 goto fail;
334 if (fh.version >= 0x221)
336 len = read (fd, &fh.salt, 8);
337 if (len != 8)
339 rc = GPG_ERR_INV_LENGTH;
340 goto fail;
344 *ver = fh.version;
345 *algo = cipher_to_gcrypt (fh.flags);
347 #ifdef WITH_AGENT
348 if (use_agent && !keyfile && fh.iter > 0)
350 char *desc;
352 rc = agent_init (&agent);
353 if (rc)
354 goto fail;
356 desc = plus_escape (_
357 ("A passphrase is required to decrypt the file for "
358 "converting. Please enter the passphrase below."));
359 rc = agent_set_pinentry_options (agent);
360 if (rc)
361 goto fail;
363 assuan_begin_confidential (agent->ctx);
364 rc = send_to_agent (agent, &passphrase, &passphraselen,
365 "GET_PASSPHRASE --data pwmd:convert + %s %s",
366 _("Passphrase:"), desc);
367 assuan_end_confidential (agent->ctx);
368 xfree (desc);
369 if (rc)
370 goto fail;
372 passphraselen--; // null byte
373 send_to_agent (agent, NULL, NULL, "CLEAR_PASSPHRASE pwmd:convert");
374 cleanup_agent (agent);
375 agent = NULL;
377 else if (keyfile && fh.iter > 0)
378 #else
379 if (keyfile && fh.iter > 0)
380 #endif
382 struct stat pst;
383 int pfd = open (keyfile, O_RDONLY);
385 if (pfd == -1)
387 rc = gpg_error_from_errno (errno);
388 goto fail;
391 if (stat (keyfile, &pst) == -1)
393 rc = gpg_error_from_errno (errno);
394 close (pfd);
395 goto fail;
398 passphrase = xmalloc (pst.st_size);
399 if (!passphrase)
401 rc = GPG_ERR_ENOMEM;
402 close (pfd);
403 goto fail;
406 passphraselen = read (pfd, passphrase, pst.st_size);
407 close (pfd);
408 if (passphraselen != pst.st_size)
410 rc = GPG_ERR_INV_LENGTH;
411 goto fail;
414 else if (fh.iter > 0)
416 rc = getpin_common (NULL, filename, PINENTRY_OPEN, &passphrase,
417 &passphraselen);
418 if (rc)
419 goto fail;
422 key = gcry_malloc (KEYSIZE);
423 if (!key)
425 rc = GPG_ERR_ENOMEM;
426 goto fail;
429 fp = fdopen (fd, "r");
430 len = st.st_size - ftell (fp);
432 if (fh.version >= 0x221 && fh.version < 0x0300)
434 rc = gcry_kdf_derive (passphrase, passphraselen, GCRY_KDF_ITERSALTED_S2K,
435 GCRY_MD_SHA1, fh.salt, 8, 1000, KEYSIZE, key);
436 if (rc)
437 goto fail;
439 else
440 gcry_md_hash_buffer (GCRY_MD_SHA256, key, passphrase, passphraselen);
442 data = gcry_malloc (len);
443 if (!data)
445 rc = GPG_ERR_ENOMEM;
446 goto fail;
449 datalen = read (fd, data, len);
450 if (datalen != len)
452 rc = GPG_ERR_INV_LENGTH;
453 goto fail;
456 fprintf (stderr, _("Decrypting ...\n"));
457 rc = decrypt (&fh, key, &data, datalen, result, result_len);
459 fail:
460 gcry_free (key);
461 gcry_free (data);
462 xfree (passphrase);
464 #ifdef WITH_AGENT
465 if (agent)
466 cleanup_agent (agent);
467 #endif
469 if (fd != -1)
470 close (fd);
471 return rc;