8c2cd4d7cef30f549b43b4852f03f2e837a91fcf
[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   /* A pointer to the next pointer of the last recipient in the list.
60      This makes appending new invalid signers painless while
61      preserving the order.  */
62   gpgme_recipient_t *last_recipient_p;
63 } *op_data_t;
64
65
66 static void
67 release_op_data (void *hook)
68 {
69   op_data_t opd = (op_data_t) hook;
70   gpgme_recipient_t recipient = opd->result.recipients;
71
72   if (opd->result.unsupported_algorithm)
73     free (opd->result.unsupported_algorithm);
74
75   if (opd->result.file_name)
76     free (opd->result.file_name);
77
78   if (opd->result.session_key)
79     free (opd->result.session_key);
80
81   while (recipient)
82     {
83       gpgme_recipient_t next = recipient->next;
84       free (recipient);
85       recipient = next;
86     }
87 }
88
89
90 gpgme_decrypt_result_t
91 gpgme_op_decrypt_result (gpgme_ctx_t ctx)
92 {
93   void *hook;
94   op_data_t opd;
95   gpgme_error_t err;
96
97   TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);
98
99   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
100   opd = hook;
101   if (err || !opd)
102     {
103       TRACE_SUC0 ("result=(null)");
104       return NULL;
105     }
106
107   if (_gpgme_debug_trace ())
108     {
109       gpgme_recipient_t rcp;
110
111       if (opd->result.unsupported_algorithm)
112         {
113           TRACE_LOG1 ("result: unsupported_algorithm: %s",
114                       opd->result.unsupported_algorithm);
115         }
116       if (opd->result.wrong_key_usage)
117         {
118           TRACE_LOG ("result: wrong key usage");
119         }
120       rcp = opd->result.recipients;
121       while (rcp)
122         {
123           TRACE_LOG3 ("result: recipient: keyid=%s, pubkey_algo=%i, "
124                       "status=%s", rcp->keyid, rcp->pubkey_algo,
125                       gpg_strerror (rcp->status));
126           rcp = rcp->next;
127         }
128       if (opd->result.file_name)
129         {
130           TRACE_LOG1 ("result: original file name: %s", opd->result.file_name);
131         }
132     }
133
134   TRACE_SUC1 ("result=%p", &opd->result);
135   return &opd->result;
136 }
137
138
139 \f
140 /* Parse the ARGS of an error status line and record some error
141  * conditions at OPD.  Returns 0 on success.  */
142 static gpgme_error_t
143 parse_status_error (char *args, op_data_t opd)
144 {
145   gpgme_error_t err;
146   char *field[3];
147   int nfields;
148   char *args2;
149
150   if (!args)
151     return trace_gpg_error (GPG_ERR_INV_ENGINE);
152
153   args2 = strdup (args); /* Split modifies the input string. */
154   nfields = _gpgme_split_fields (args2, field, DIM (field));
155   if (nfields < 1)
156     {
157       free (args2);
158       return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing.  */
159     }
160   err = nfields < 2 ? 0 : atoi (field[1]);
161
162   if (!strcmp (field[0], "decrypt.algorithm"))
163     {
164       if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM
165           && nfields > 2
166           && strcmp (field[2], "?"))
167         {
168           opd->result.unsupported_algorithm = strdup (field[2]);
169           if (!opd->result.unsupported_algorithm)
170             {
171               free (args2);
172               return gpg_error_from_syserror ();
173             }
174         }
175     }
176   else if (!strcmp (field[0], "decrypt.keyusage"))
177     {
178       if (gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
179         opd->result.wrong_key_usage = 1;
180     }
181   else if (!strcmp (field[0], "pkdecrypt_failed"))
182     {
183       switch (gpg_err_code (err))
184         {
185         case GPG_ERR_CANCELED:
186         case GPG_ERR_FULLY_CANCELED:
187           /* It is better to return with a cancel error code than the
188            * general decryption failed error code.  */
189           opd->pkdecrypt_failed = gpg_err_make (gpg_err_source (err),
190                                                 GPG_ERR_CANCELED);
191           break;
192
193         case GPG_ERR_BAD_PASSPHRASE:
194           /* A bad passphrase is severe enough that we return this
195            * error code.  */
196           opd->pkdecrypt_failed = err;
197           break;
198
199         default:
200           /* For now all other error codes are ignored and the
201            * standard DECRYPT_FAILED is returned.  */
202           break;
203         }
204     }
205
206
207   free (args2);
208   return 0;
209 }
210
211
212 static gpgme_error_t
213 parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
214 {
215   gpgme_recipient_t rec;
216   char *tail;
217   int i;
218
219   rec = malloc (sizeof (*rec));
220   if (!rec)
221     return gpg_error_from_syserror ();
222
223   rec->next = NULL;
224   rec->keyid = rec->_keyid;
225   rec->status = 0;
226
227   for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
228     {
229       if (args[i] == '\0' || args[i] == ' ')
230         break;
231
232       rec->_keyid[i] = args[i];
233     }
234   rec->_keyid[i] = '\0';
235
236   args = &args[i];
237   if (*args != '\0' && *args != ' ')
238     {
239       free (rec);
240       return trace_gpg_error (GPG_ERR_INV_ENGINE);
241     }
242
243   while (*args == ' ')
244     args++;
245
246   if (*args)
247     {
248       gpg_err_set_errno (0);
249       rec->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol);
250       if (errno || args == tail || *tail != ' ')
251         {
252           /* The crypto backend does not behave.  */
253           free (rec);
254           return trace_gpg_error (GPG_ERR_INV_ENGINE);
255         }
256     }
257
258   /* FIXME: The key length is always 0 right now, so no need to parse
259      it.  */
260
261   *recp = rec;
262   return 0;
263 }
264
265
266 gpgme_error_t
267 _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
268                                char *args)
269 {
270   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
271   gpgme_error_t err;
272   void *hook;
273   op_data_t opd;
274
275   err = _gpgme_passphrase_status_handler (priv, code, args);
276   if (err)
277     return err;
278
279   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
280   opd = hook;
281   if (err)
282     return err;
283
284   switch (code)
285     {
286     case GPGME_STATUS_FAILURE:
287       opd->failure_code = _gpgme_parse_failure (args);
288       break;
289
290     case GPGME_STATUS_EOF:
291       /* FIXME: These error values should probably be attributed to
292          the underlying crypto engine (as error source).  */
293       if (opd->failed && opd->pkdecrypt_failed)
294         return opd->pkdecrypt_failed;
295       else if (opd->failed && opd->any_no_seckey)
296         return gpg_error (GPG_ERR_NO_SECKEY);
297       else if (opd->failed)
298         return gpg_error (GPG_ERR_DECRYPT_FAILED);
299       else if (!opd->okay)
300         return gpg_error (GPG_ERR_NO_DATA);
301       else if (opd->failure_code)
302         return opd->failure_code;
303       break;
304
305     case GPGME_STATUS_DECRYPTION_INFO:
306       /* Fixme: Provide a way to return the used symmetric algorithm. */
307       break;
308
309     case GPGME_STATUS_DECRYPTION_OKAY:
310       opd->okay = 1;
311       break;
312
313     case GPGME_STATUS_DECRYPTION_FAILED:
314       opd->failed = 1;
315       break;
316
317     case GPGME_STATUS_ERROR:
318       /* Note that this is an informational status code which should
319          not lead to an error return unless it is something not
320          related to the backend.  */
321       err = parse_status_error (args, opd);
322       if (err)
323         return err;
324       break;
325
326     case GPGME_STATUS_ENC_TO:
327       err = parse_enc_to (args, opd->last_recipient_p, ctx->protocol);
328       if (err)
329         return err;
330
331       opd->last_recipient_p = &(*opd->last_recipient_p)->next;
332       break;
333
334     case GPGME_STATUS_SESSION_KEY:
335       if (opd->result.session_key)
336         free (opd->result.session_key);
337       opd->result.session_key = strdup(args);
338       break;
339
340     case GPGME_STATUS_NO_SECKEY:
341       {
342         gpgme_recipient_t rec = opd->result.recipients;
343         while (rec)
344           {
345             if (!strcmp (rec->keyid, args))
346               {
347                 rec->status = gpg_error (GPG_ERR_NO_SECKEY);
348                 break;
349               }
350             rec = rec->next;
351           }
352         /* FIXME: Is this ok?  */
353         if (!rec)
354           return trace_gpg_error (GPG_ERR_INV_ENGINE);
355         opd->any_no_seckey = 1;
356       }
357       break;
358
359     case GPGME_STATUS_PLAINTEXT:
360       err = _gpgme_parse_plaintext (args, &opd->result.file_name);
361       if (err)
362         return err;
363       break;
364
365     case GPGME_STATUS_INQUIRE_MAXLEN:
366       if (ctx->status_cb && !ctx->full_status)
367         {
368           err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
369           if (err)
370             return err;
371         }
372       break;
373
374     case GPGME_STATUS_DECRYPTION_COMPLIANCE_MODE:
375       PARSE_COMPLIANCE_FLAGS (args, &opd->result);
376       break;
377
378     default:
379       break;
380     }
381
382   return 0;
383 }
384
385
386 static gpgme_error_t
387 decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
388 {
389   gpgme_error_t err;
390
391   err = _gpgme_progress_status_handler (priv, code, args);
392   if (!err)
393     err = _gpgme_decrypt_status_handler (priv, code, args);
394   return err;
395 }
396
397
398 gpgme_error_t
399 _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
400 {
401   gpgme_error_t err;
402   void *hook;
403   op_data_t opd;
404
405   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
406                                sizeof (*opd), release_op_data);
407   opd = hook;
408   if (err)
409     return err;
410
411   opd->last_recipient_p = &opd->result.recipients;
412   return 0;
413 }
414
415
416 gpgme_error_t
417 _gpgme_decrypt_start (gpgme_ctx_t ctx, int synchronous,
418                       gpgme_decrypt_flags_t flags,
419                       gpgme_data_t cipher, gpgme_data_t plain)
420 {
421   gpgme_error_t err;
422
423   assert (!(flags & GPGME_DECRYPT_VERIFY));
424
425   err = _gpgme_op_reset (ctx, synchronous);
426   if (err)
427     return err;
428
429   err = _gpgme_op_decrypt_init_result (ctx);
430   if (err)
431     return err;
432
433   if (!cipher)
434     return gpg_error (GPG_ERR_NO_DATA);
435   if (!plain)
436     return gpg_error (GPG_ERR_INV_VALUE);
437
438   if (err)
439     return err;
440
441   if (ctx->passphrase_cb)
442     {
443       err = _gpgme_engine_set_command_handler
444         (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
445       if (err)
446         return err;
447     }
448
449   _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
450
451   return _gpgme_engine_op_decrypt (ctx->engine,
452                                    flags,
453                                    cipher, plain,
454                                    ctx->export_session_keys,
455                                    ctx->override_session_key,
456                                    ctx->auto_key_retrieve);
457 }
458
459
460 gpgme_error_t
461 gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
462                         gpgme_data_t plain)
463 {
464   gpgme_error_t err;
465
466   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx,
467               "cipher=%p, plain=%p", cipher, plain);
468
469   if (!ctx)
470     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
471
472   err = _gpgme_decrypt_start (ctx, 0, 0, cipher, plain);
473   return TRACE_ERR (err);
474 }
475
476
477 /* Decrypt ciphertext CIPHER within CTX and store the resulting
478    plaintext in PLAIN.  */
479 gpgme_error_t
480 gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
481 {
482   gpgme_error_t err;
483
484   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx,
485               "cipher=%p, plain=%p", cipher, plain);
486
487   if (!ctx)
488     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
489
490   err = _gpgme_decrypt_start (ctx, 1, 0, cipher, plain);
491   if (!err)
492     err = _gpgme_wait_one (ctx);
493   return TRACE_ERR (err);
494 }