core: Remove cruft from the engine-gpg code.
[gpgme.git] / src / decrypt.c
1 /* decrypt.c - Decrypt function.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2017 g10 Code GmbH
4
5    This file is part of GPGME.
6
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (at your option) any later version.
11
12    GPGME is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
29
30 #include "debug.h"
31 #include "gpgme.h"
32 #include "util.h"
33 #include "context.h"
34 #include "ops.h"
35
36
37 \f
38 typedef struct
39 {
40   struct _gpgme_op_decrypt_result result;
41
42   /* The error code from a FAILURE status line or 0.  */
43   gpg_error_t failure_code;
44
45   int okay;
46
47   /* A flag telling that the a decryption failed and an optional error
48    * code to further specify the failure.  */
49   int failed;
50   gpg_error_t pkdecrypt_failed;
51
52   /* At least one secret key is not available.  gpg issues NO_SECKEY
53    * status lines for each key the message has been encrypted to but
54    * that secret key is not available.  This can't be done for hidden
55    * recipients, though.  We track it here to allow for a better error
56    * message that the general DECRYPTION_FAILED. */
57   int any_no_seckey;
58
59   /* If the engine emits a DECRYPTION_INFO status and that does not
60    * indicate that an integrity proetction mode is active, this flag
61    * is set.  */
62   int not_integrity_protected;
63
64   /* A pointer to the next pointer of the last recipient in the list.
65      This makes appending new invalid signers painless while
66      preserving the order.  */
67   gpgme_recipient_t *last_recipient_p;
68 } *op_data_t;
69
70
71 static void
72 release_op_data (void *hook)
73 {
74   op_data_t opd = (op_data_t) hook;
75   gpgme_recipient_t recipient = opd->result.recipients;
76
77   free (opd->result.unsupported_algorithm);
78   free (opd->result.file_name);
79   free (opd->result.session_key);
80   free (opd->result.symkey_algo);
81
82   while (recipient)
83     {
84       gpgme_recipient_t next = recipient->next;
85       free (recipient);
86       recipient = next;
87     }
88 }
89
90
91 gpgme_decrypt_result_t
92 gpgme_op_decrypt_result (gpgme_ctx_t ctx)
93 {
94   void *hook;
95   op_data_t opd;
96   gpgme_error_t err;
97
98   TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);
99
100   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
101   opd = hook;
102   if (err || !opd)
103     {
104       TRACE_SUC0 ("result=(null)");
105       return NULL;
106     }
107
108   /* Make sure that SYMKEY_ALGO has a value.  */
109   if (!opd->result.symkey_algo)
110     {
111       opd->result.symkey_algo = strdup ("?.?");
112       if (!opd->result.symkey_algo)
113         {
114           TRACE_SUC0 ("result=(null)");
115           return NULL;
116         }
117     }
118
119   if (_gpgme_debug_trace ())
120     {
121       gpgme_recipient_t rcp;
122
123       if (opd->result.unsupported_algorithm)
124         {
125           TRACE_LOG1 ("result: unsupported_algorithm: %s",
126                       opd->result.unsupported_algorithm);
127         }
128       if (opd->result.wrong_key_usage)
129         {
130           TRACE_LOG ("result: wrong key usage");
131         }
132       rcp = opd->result.recipients;
133       while (rcp)
134         {
135           TRACE_LOG3 ("result: recipient: keyid=%s, pubkey_algo=%i, "
136                       "status=%s", rcp->keyid, rcp->pubkey_algo,
137                       gpg_strerror (rcp->status));
138           rcp = rcp->next;
139         }
140       if (opd->result.file_name)
141         {
142           TRACE_LOG1 ("result: original file name: %s", opd->result.file_name);
143         }
144     }
145
146   TRACE_SUC1 ("result=%p", &opd->result);
147   return &opd->result;
148 }
149
150
151 \f
152 /* Parse the ARGS of an error status line and record some error
153  * conditions at OPD.  Returns 0 on success.  */
154 static gpgme_error_t
155 parse_status_error (char *args, op_data_t opd)
156 {
157   gpgme_error_t err;
158   char *field[3];
159   int nfields;
160   char *args2;
161
162   if (!args)
163     return trace_gpg_error (GPG_ERR_INV_ENGINE);
164
165   args2 = strdup (args); /* Split modifies the input string. */
166   nfields = _gpgme_split_fields (args2, field, DIM (field));
167   if (nfields < 1)
168     {
169       free (args2);
170       return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing.  */
171     }
172   err = nfields < 2 ? 0 : atoi (field[1]);
173
174   if (!strcmp (field[0], "decrypt.algorithm"))
175     {
176       if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM
177           && nfields > 2
178           && strcmp (field[2], "?"))
179         {
180           opd->result.unsupported_algorithm = strdup (field[2]);
181           if (!opd->result.unsupported_algorithm)
182             {
183               free (args2);
184               return gpg_error_from_syserror ();
185             }
186         }
187     }
188   else if (!strcmp (field[0], "decrypt.keyusage"))
189     {
190       if (gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
191         opd->result.wrong_key_usage = 1;
192     }
193   else if (!strcmp (field[0], "pkdecrypt_failed"))
194     {
195       switch (gpg_err_code (err))
196         {
197         case GPG_ERR_CANCELED:
198         case GPG_ERR_FULLY_CANCELED:
199           /* It is better to return with a cancel error code than the
200            * general decryption failed error code.  */
201           opd->pkdecrypt_failed = gpg_err_make (gpg_err_source (err),
202                                                 GPG_ERR_CANCELED);
203           break;
204
205         case GPG_ERR_BAD_PASSPHRASE:
206           /* A bad passphrase is severe enough that we return this
207            * error code.  */
208           opd->pkdecrypt_failed = err;
209           break;
210
211         default:
212           /* For now all other error codes are ignored and the
213            * standard DECRYPT_FAILED is returned.  */
214           break;
215         }
216     }
217
218
219   free (args2);
220   return 0;
221 }
222
223
224 static gpgme_error_t
225 parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
226 {
227   gpgme_recipient_t rec;
228   char *tail;
229   int i;
230
231   rec = malloc (sizeof (*rec));
232   if (!rec)
233     return gpg_error_from_syserror ();
234
235   rec->next = NULL;
236   rec->keyid = rec->_keyid;
237   rec->status = 0;
238
239   for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
240     {
241       if (args[i] == '\0' || args[i] == ' ')
242         break;
243
244       rec->_keyid[i] = args[i];
245     }
246   rec->_keyid[i] = '\0';
247
248   args = &args[i];
249   if (*args != '\0' && *args != ' ')
250     {
251       free (rec);
252       return trace_gpg_error (GPG_ERR_INV_ENGINE);
253     }
254
255   while (*args == ' ')
256     args++;
257
258   if (*args)
259     {
260       gpg_err_set_errno (0);
261       rec->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol);
262       if (errno || args == tail || *tail != ' ')
263         {
264           /* The crypto backend does not behave.  */
265           free (rec);
266           return trace_gpg_error (GPG_ERR_INV_ENGINE);
267         }
268     }
269
270   /* FIXME: The key length is always 0 right now, so no need to parse
271      it.  */
272
273   *recp = rec;
274   return 0;
275 }
276
277
278 /* Parse the ARGS of a
279  *   DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
280  * status.  Returns 0 on success and updates the OPD.
281  */
282 static gpgme_error_t
283 parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
284 {
285   char *field[3];
286   int nfields;
287   char *args2;
288   int mdc, aead_algo;
289   const char *algostr, *modestr;
290
291   if (!args)
292     return trace_gpg_error (GPG_ERR_INV_ENGINE);
293
294   args2 = strdup (args); /* Split modifies the input string. */
295   nfields = _gpgme_split_fields (args2, field, DIM (field));
296   if (nfields < 2)
297     {
298       free (args2);
299       return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing.  */
300     }
301
302   mdc     = atoi (field[0]);
303   algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
304   aead_algo    = nfields < 3? 0 : atoi (field[2]);
305   modestr = _gpgme_cipher_mode_name (aead_algo, protocol);
306
307   free (args2);
308
309   free (opd->result.symkey_algo);
310   if (!aead_algo && mdc != 2)
311     opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
312   else
313     opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
314   if (!opd->result.symkey_algo)
315     return gpg_error_from_syserror ();
316
317   if (!mdc && !aead_algo)
318     opd->not_integrity_protected = 1;
319
320   return 0;
321 }
322
323
324 gpgme_error_t
325 _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
326                                char *args)
327 {
328   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
329   gpgme_error_t err;
330   void *hook;
331   op_data_t opd;
332
333   err = _gpgme_passphrase_status_handler (priv, code, args);
334   if (err)
335     return err;
336
337   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
338   opd = hook;
339   if (err)
340     return err;
341
342   switch (code)
343     {
344     case GPGME_STATUS_FAILURE:
345       opd->failure_code = _gpgme_parse_failure (args);
346       break;
347
348     case GPGME_STATUS_EOF:
349       /* We force an encryption failure if we know that integrity
350        * protection is missing.  For modern version of gpg using
351        * modern cipher algorithms this is not required because gpg
352        * will issue a failure anyway.  However older gpg versions emit
353        * only a warning.
354        * Fixme: These error values should probably be attributed to
355        * the underlying crypto engine (as error source).  */
356       if (opd->failed && opd->pkdecrypt_failed)
357         return opd->pkdecrypt_failed;
358       else if (opd->failed && opd->any_no_seckey)
359         return gpg_error (GPG_ERR_NO_SECKEY);
360       else if (opd->failed || opd->not_integrity_protected)
361         return gpg_error (GPG_ERR_DECRYPT_FAILED);
362       else if (!opd->okay)
363         return gpg_error (GPG_ERR_NO_DATA);
364       else if (opd->failure_code)
365         return opd->failure_code;
366       break;
367
368     case GPGME_STATUS_DECRYPTION_INFO:
369       err = parse_decryption_info (args, opd, ctx->protocol);
370       if (err)
371         return err;
372       break;
373
374     case GPGME_STATUS_DECRYPTION_OKAY:
375       opd->okay = 1;
376       break;
377
378     case GPGME_STATUS_DECRYPTION_FAILED:
379       opd->failed = 1;
380       break;
381
382     case GPGME_STATUS_ERROR:
383       /* Note that this is an informational status code which should
384          not lead to an error return unless it is something not
385          related to the backend.  */
386       err = parse_status_error (args, opd);
387       if (err)
388         return err;
389       break;
390
391     case GPGME_STATUS_ENC_TO:
392       err = parse_enc_to (args, opd->last_recipient_p, ctx->protocol);
393       if (err)
394         return err;
395
396       opd->last_recipient_p = &(*opd->last_recipient_p)->next;
397       break;
398
399     case GPGME_STATUS_SESSION_KEY:
400       if (opd->result.session_key)
401         free (opd->result.session_key);
402       opd->result.session_key = strdup(args);
403       break;
404
405     case GPGME_STATUS_NO_SECKEY:
406       {
407         gpgme_recipient_t rec = opd->result.recipients;
408         while (rec)
409           {
410             if (!strcmp (rec->keyid, args))
411               {
412                 rec->status = gpg_error (GPG_ERR_NO_SECKEY);
413                 break;
414               }
415             rec = rec->next;
416           }
417         /* FIXME: Is this ok?  */
418         if (!rec)
419           return trace_gpg_error (GPG_ERR_INV_ENGINE);
420         opd->any_no_seckey = 1;
421       }
422       break;
423
424     case GPGME_STATUS_PLAINTEXT:
425       {
426         int mime = 0;
427         err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime);
428         if (err)
429           return err;
430         opd->result.is_mime = !!mime;
431       }
432       break;
433
434     case GPGME_STATUS_INQUIRE_MAXLEN:
435       if (ctx->status_cb && !ctx->full_status)
436         {
437           err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
438           if (err)
439             return err;
440         }
441       break;
442
443     case GPGME_STATUS_DECRYPTION_COMPLIANCE_MODE:
444       PARSE_COMPLIANCE_FLAGS (args, &opd->result);
445       break;
446
447     default:
448       break;
449     }
450
451   return 0;
452 }
453
454
455 static gpgme_error_t
456 decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
457 {
458   gpgme_error_t err;
459
460   err = _gpgme_progress_status_handler (priv, code, args);
461   if (!err)
462     err = _gpgme_decrypt_status_handler (priv, code, args);
463   return err;
464 }
465
466
467 gpgme_error_t
468 _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
469 {
470   gpgme_error_t err;
471   void *hook;
472   op_data_t opd;
473
474   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
475                                sizeof (*opd), release_op_data);
476   opd = hook;
477   if (err)
478     return err;
479
480   opd->last_recipient_p = &opd->result.recipients;
481   return 0;
482 }
483
484
485 gpgme_error_t
486 _gpgme_decrypt_start (gpgme_ctx_t ctx, int synchronous,
487                       gpgme_decrypt_flags_t flags,
488                       gpgme_data_t cipher, gpgme_data_t plain)
489 {
490   gpgme_error_t err;
491
492   assert (!(flags & GPGME_DECRYPT_VERIFY));
493
494   err = _gpgme_op_reset (ctx, synchronous);
495   if (err)
496     return err;
497
498   err = _gpgme_op_decrypt_init_result (ctx);
499   if (err)
500     return err;
501
502   if (!cipher)
503     return gpg_error (GPG_ERR_NO_DATA);
504   if (!plain)
505     return gpg_error (GPG_ERR_INV_VALUE);
506
507   if (err)
508     return err;
509
510   if (ctx->passphrase_cb)
511     {
512       err = _gpgme_engine_set_command_handler
513         (ctx->engine, _gpgme_passphrase_command_handler, ctx);
514       if (err)
515         return err;
516     }
517
518   _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
519
520   return _gpgme_engine_op_decrypt (ctx->engine,
521                                    flags,
522                                    cipher, plain,
523                                    ctx->export_session_keys,
524                                    ctx->override_session_key,
525                                    ctx->auto_key_retrieve);
526 }
527
528
529 gpgme_error_t
530 gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
531                         gpgme_data_t plain)
532 {
533   gpgme_error_t err;
534
535   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx,
536               "cipher=%p, plain=%p", cipher, plain);
537
538   if (!ctx)
539     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
540
541   err = _gpgme_decrypt_start (ctx, 0, 0, cipher, plain);
542   return TRACE_ERR (err);
543 }
544
545
546 /* Decrypt ciphertext CIPHER within CTX and store the resulting
547    plaintext in PLAIN.  */
548 gpgme_error_t
549 gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
550 {
551   gpgme_error_t err;
552
553   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx,
554               "cipher=%p, plain=%p", cipher, plain);
555
556   if (!ctx)
557     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
558
559   err = _gpgme_decrypt_start (ctx, 1, 0, cipher, plain);
560   if (!err)
561     err = _gpgme_wait_one (ctx);
562   return TRACE_ERR (err);
563 }