Add help strings for all commands.
[gnupg.git] / sm / decrypt.c
blob8fb9f2dfde363f68dde687766c6a984b20af930a
1 /* decrypt.c - Decrypt a message
2 * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <time.h>
27 #include <assert.h>
29 #include "gpgsm.h"
30 #include <gcrypt.h>
31 #include <ksba.h>
33 #include "keydb.h"
34 #include "i18n.h"
36 struct decrypt_filter_parm_s {
37 int algo;
38 int mode;
39 int blklen;
40 gcry_cipher_hd_t hd;
41 char iv[16];
42 size_t ivlen;
43 int any_data; /* dod we push anything through the filter at all? */
44 unsigned char lastblock[16]; /* to strip the padding we have to
45 keep this one */
46 char helpblock[16]; /* needed because there is no block buffering in
47 libgcrypt (yet) */
48 int helpblocklen;
53 /* Decrypt the session key and fill in the parm structure. The
54 algo and the IV is expected to be already in PARM. */
55 static int
56 prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
57 ksba_const_sexp_t enc_val,
58 struct decrypt_filter_parm_s *parm)
60 char *seskey = NULL;
61 size_t n, seskeylen;
62 int rc;
64 rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
65 &seskey, &seskeylen);
66 if (rc)
68 log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
69 goto leave;
72 if (DBG_CRYPTO)
73 log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
75 n=0;
76 if (seskeylen == 24)
78 /* Smells like a 3-des key. This might happen because a SC has
79 already done the unpacking. */
81 else
83 if (n + 7 > seskeylen )
85 rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
86 goto leave;
89 /* FIXME: Actually the leading zero is required but due to the way
90 we encode the output in libgcrypt as an MPI we are not able to
91 encode that leading zero. However, when using a Smartcard we are
92 doing it the right way and therefore we have to skip the zero. This
93 should be fixed in gpg-agent of course. */
94 if (!seskey[n])
95 n++;
97 if (seskey[n] != 2 ) /* Wrong block type version. */
99 rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
100 goto leave;
103 for (n++; n < seskeylen && seskey[n]; n++) /* Skip the random bytes. */
105 n++; /* and the zero byte */
106 if (n >= seskeylen )
108 rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
109 goto leave;
113 if (DBG_CRYPTO)
114 log_printhex ("session key:", seskey+n, seskeylen-n);
116 rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
117 if (rc)
119 log_error ("error creating decryptor: %s\n", gpg_strerror (rc));
120 goto leave;
123 rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
124 if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
126 log_info (_("WARNING: message was encrypted with "
127 "a weak key in the symmetric cipher.\n"));
128 rc = 0;
130 if (rc)
132 log_error("key setup failed: %s\n", gpg_strerror(rc) );
133 goto leave;
136 gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
138 leave:
139 xfree (seskey);
140 return rc;
144 /* This function is called by the KSBA writer just before the actual
145 write is done. The function must take INLEN bytes from INBUF,
146 decrypt it and store it inoutbuf which has a maximum size of
147 maxoutlen. The valid bytes in outbuf should be return in outlen.
148 Due to different buffer sizes or different length of input and
149 output, it may happen that fewer bytes are processed or fewer bytes
150 are written. */
151 static gpg_error_t
152 decrypt_filter (void *arg,
153 const void *inbuf, size_t inlen, size_t *inused,
154 void *outbuf, size_t maxoutlen, size_t *outlen)
156 struct decrypt_filter_parm_s *parm = arg;
157 int blklen = parm->blklen;
158 size_t orig_inlen = inlen;
160 /* fixme: Should we issue an error when we have not seen one full block? */
161 if (!inlen)
162 return gpg_error (GPG_ERR_BUG);
164 if (maxoutlen < 2*parm->blklen)
165 return gpg_error (GPG_ERR_BUG);
166 /* Make some space because we will later need an extra block at the end. */
167 maxoutlen -= blklen;
169 if (parm->helpblocklen)
171 int i, j;
173 for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
174 parm->helpblock[i] = ((const char*)inbuf)[j];
175 inlen -= j;
176 if (blklen > maxoutlen)
177 return gpg_error (GPG_ERR_BUG);
178 if (i < blklen)
180 parm->helpblocklen = i;
181 *outlen = 0;
183 else
185 parm->helpblocklen = 0;
186 if (parm->any_data)
188 memcpy (outbuf, parm->lastblock, blklen);
189 *outlen =blklen;
191 else
192 *outlen = 0;
193 gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
194 parm->helpblock, blklen);
195 parm->any_data = 1;
197 *inused = orig_inlen - inlen;
198 return 0;
202 if (inlen > maxoutlen)
203 inlen = maxoutlen;
204 if (inlen % blklen)
205 { /* store the remainder away */
206 parm->helpblocklen = inlen%blklen;
207 inlen = inlen/blklen*blklen;
208 memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
211 *inused = inlen + parm->helpblocklen;
212 if (inlen)
214 assert (inlen >= blklen);
215 if (parm->any_data)
217 gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
218 inbuf, inlen);
219 memcpy (outbuf, parm->lastblock, blklen);
220 memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
221 *outlen = inlen;
223 else
225 gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
226 memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
227 *outlen = inlen - blklen;
228 parm->any_data = 1;
231 else
232 *outlen = 0;
233 return 0;
238 /* Perform a decrypt operation. */
240 gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
242 int rc;
243 Base64Context b64reader = NULL;
244 Base64Context b64writer = NULL;
245 ksba_reader_t reader;
246 ksba_writer_t writer;
247 ksba_cms_t cms = NULL;
248 ksba_stop_reason_t stopreason;
249 KEYDB_HANDLE kh;
250 int recp;
251 FILE *in_fp = NULL;
252 struct decrypt_filter_parm_s dfparm;
254 memset (&dfparm, 0, sizeof dfparm);
256 kh = keydb_new (0);
257 if (!kh)
259 log_error (_("failed to allocated keyDB handle\n"));
260 rc = gpg_error (GPG_ERR_GENERAL);
261 goto leave;
265 in_fp = fdopen ( dup (in_fd), "rb");
266 if (!in_fp)
268 rc = gpg_error (gpg_err_code_from_errno (errno));
269 log_error ("fdopen() failed: %s\n", strerror (errno));
270 goto leave;
273 rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, 0, &reader);
274 if (rc)
276 log_error ("can't create reader: %s\n", gpg_strerror (rc));
277 goto leave;
280 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
281 if (rc)
283 log_error ("can't create writer: %s\n", gpg_strerror (rc));
284 goto leave;
287 rc = ksba_cms_new (&cms);
288 if (rc)
289 goto leave;
291 rc = ksba_cms_set_reader_writer (cms, reader, writer);
292 if (rc)
294 log_debug ("ksba_cms_set_reader_writer failed: %s\n",
295 gpg_strerror (rc));
296 goto leave;
299 /* Parser loop. */
302 rc = ksba_cms_parse (cms, &stopreason);
303 if (rc)
305 log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
306 goto leave;
309 if (stopreason == KSBA_SR_BEGIN_DATA
310 || stopreason == KSBA_SR_DETACHED_DATA)
312 int algo, mode;
313 const char *algoid;
314 int any_key = 0;
316 algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
317 algo = gcry_cipher_map_name (algoid);
318 mode = gcry_cipher_mode_from_oid (algoid);
319 if (!algo || !mode)
321 rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
322 log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
323 if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
324 log_info (_("(this is the RC2 algorithm)\n"));
325 else if (!algoid)
326 log_info (_("(this does not seem to be an encrypted"
327 " message)\n"));
329 char numbuf[50];
330 sprintf (numbuf, "%d", rc);
331 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
332 numbuf, algoid?algoid:"?", NULL);
335 /* If it seems that this is not an encrypted message we
336 return a more sensible error code. */
337 if (!algoid)
338 rc = gpg_error (GPG_ERR_NO_DATA);
340 goto leave;
342 dfparm.algo = algo;
343 dfparm.mode = mode;
344 dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
345 if (dfparm.blklen > sizeof (dfparm.helpblock))
346 return gpg_error (GPG_ERR_BUG);
348 rc = ksba_cms_get_content_enc_iv (cms,
349 dfparm.iv,
350 sizeof (dfparm.iv),
351 &dfparm.ivlen);
352 if (rc)
354 log_error ("error getting IV: %s\n", gpg_strerror (rc));
355 goto leave;
358 for (recp=0; !any_key; recp++)
360 char *issuer;
361 ksba_sexp_t serial;
362 ksba_sexp_t enc_val;
363 char *hexkeygrip = NULL;
364 char *desc = NULL;
365 char kidbuf[16+1];
367 *kidbuf = 0;
369 rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
370 if (rc == -1 && recp)
371 break; /* no more recipients */
372 if (rc)
373 log_error ("recp %d - error getting info: %s\n",
374 recp, gpg_strerror (rc));
375 else
377 ksba_cert_t cert = NULL;
379 log_debug ("recp %d - issuer: `%s'\n",
380 recp, issuer? issuer:"[NONE]");
381 log_debug ("recp %d - serial: ", recp);
382 gpgsm_dump_serial (serial);
383 log_printf ("\n");
385 keydb_search_reset (kh);
386 rc = keydb_search_issuer_sn (kh, issuer, serial);
387 if (rc)
389 log_error ("failed to find the certificate: %s\n",
390 gpg_strerror(rc));
391 goto oops;
394 rc = keydb_get_cert (kh, &cert);
395 if (rc)
397 log_error ("failed to get cert: %s\n", gpg_strerror (rc));
398 goto oops;
401 /* Print the ENC_TO status line. Note that we can
402 do so only if we have the certificate. This is
403 in contrast to gpg where the keyID is commonly
404 included in the encrypted messages. It is too
405 cumbersome to retrieve the used algorithm, thus
406 we don't print it for now. We also record the
407 keyid for later use. */
409 unsigned long kid[2];
411 kid[0] = gpgsm_get_short_fingerprint (cert, kid+1);
412 snprintf (kidbuf, sizeof kidbuf, "%08lX%08lX",
413 kid[1], kid[0]);
414 gpgsm_status2 (ctrl, STATUS_ENC_TO,
415 kidbuf, "0", "0", NULL);
419 /* Just in case there is a problem with the own
420 certificate we print this message - should never
421 happen of course */
422 rc = gpgsm_cert_use_decrypt_p (cert);
423 if (rc)
425 char numbuf[50];
426 sprintf (numbuf, "%d", rc);
427 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
428 numbuf, NULL);
429 rc = 0;
432 hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
433 desc = gpgsm_format_keydesc (cert);
435 oops:
436 xfree (issuer);
437 xfree (serial);
438 ksba_cert_release (cert);
441 if (!hexkeygrip)
443 else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
444 log_error ("recp %d - error getting encrypted session key\n",
445 recp);
446 else
448 rc = prepare_decryption (ctrl,
449 hexkeygrip, desc, enc_val, &dfparm);
450 xfree (enc_val);
451 if (rc)
453 log_info ("decrypting session key failed: %s\n",
454 gpg_strerror (rc));
455 if (gpg_err_code (rc) == GPG_ERR_NO_SECKEY && *kidbuf)
456 gpgsm_status2 (ctrl, STATUS_NO_SECKEY, kidbuf, NULL);
458 else
459 { /* setup the bulk decrypter */
460 any_key = 1;
461 ksba_writer_set_filter (writer,
462 decrypt_filter,
463 &dfparm);
466 xfree (hexkeygrip);
467 xfree (desc);
469 if (!any_key)
471 rc = gpg_error (GPG_ERR_NO_SECKEY);
472 goto leave;
475 else if (stopreason == KSBA_SR_END_DATA)
477 ksba_writer_set_filter (writer, NULL, NULL);
478 if (dfparm.any_data)
479 { /* write the last block with padding removed */
480 int i, npadding = dfparm.lastblock[dfparm.blklen-1];
481 if (!npadding || npadding > dfparm.blklen)
483 log_error ("invalid padding with value %d\n", npadding);
484 rc = gpg_error (GPG_ERR_INV_DATA);
485 goto leave;
487 rc = ksba_writer_write (writer,
488 dfparm.lastblock,
489 dfparm.blklen - npadding);
490 if (rc)
491 goto leave;
493 for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
495 if (dfparm.lastblock[i] != npadding)
497 log_error ("inconsistent padding\n");
498 rc = gpg_error (GPG_ERR_INV_DATA);
499 goto leave;
506 while (stopreason != KSBA_SR_READY);
508 rc = gpgsm_finish_writer (b64writer);
509 if (rc)
511 log_error ("write failed: %s\n", gpg_strerror (rc));
512 goto leave;
514 gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
517 leave:
518 if (rc)
520 gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
521 log_error ("message decryption failed: %s <%s>\n",
522 gpg_strerror (rc), gpg_strsource (rc));
524 ksba_cms_release (cms);
525 gpgsm_destroy_reader (b64reader);
526 gpgsm_destroy_writer (b64writer);
527 keydb_release (kh);
528 if (in_fp)
529 fclose (in_fp);
530 if (dfparm.hd)
531 gcry_cipher_close (dfparm.hd);
532 return rc;