LCOV - code coverage report
Current view: top level - src - decrypt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 145 244 59.4 %
Date: 2018-11-15 08:49:49 Functions: 9 11 81.8 %

          Line data    Source code
       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             : #include "data.h"
      36             : 
      37             : 
      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 than 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 protection mode is active, this flag
      61             :    * is set.  */
      62             :   int not_integrity_protected;
      63             : 
      64             :   /* The error code from the first ERROR line.  This is in some cases
      65             :    * used to return a better matching error code to the caller.  */
      66             :   gpg_error_t first_status_error;
      67             : 
      68             :   /* A pointer to the next pointer of the last recipient in the list.
      69             :      This makes appending new invalid signers painless while
      70             :      preserving the order.  */
      71             :   gpgme_recipient_t *last_recipient_p;
      72             : 
      73             :   /* The data object serial number of the plaintext.  */
      74             :   uint64_t plaintext_dserial;
      75             : } *op_data_t;
      76             : 
      77             : 
      78             : static void
      79          53 : release_op_data (void *hook)
      80             : {
      81          53 :   op_data_t opd = (op_data_t) hook;
      82          53 :   gpgme_recipient_t recipient = opd->result.recipients;
      83             : 
      84          53 :   free (opd->result.unsupported_algorithm);
      85          53 :   free (opd->result.file_name);
      86          53 :   free (opd->result.session_key);
      87          53 :   free (opd->result.symkey_algo);
      88             : 
      89         149 :   while (recipient)
      90             :     {
      91          43 :       gpgme_recipient_t next = recipient->next;
      92          43 :       free (recipient);
      93          43 :       recipient = next;
      94             :     }
      95          53 : }
      96             : 
      97             : 
      98             : gpgme_decrypt_result_t
      99          50 : gpgme_op_decrypt_result (gpgme_ctx_t ctx)
     100             : {
     101             :   void *hook;
     102             :   op_data_t opd;
     103             :   gpgme_error_t err;
     104             : 
     105          50 :   TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);
     106             : 
     107          50 :   ctx->ignore_mdc_error = 0;  /* Always reset this flag.  */
     108             : 
     109          50 :   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
     110          50 :   opd = hook;
     111          50 :   if (err || !opd)
     112             :     {
     113           0 :       TRACE_SUC0 ("result=(null)");
     114           0 :       return NULL;
     115             :     }
     116             : 
     117             :   /* Make sure that SYMKEY_ALGO has a value.  */
     118          50 :   if (!opd->result.symkey_algo)
     119             :     {
     120           1 :       opd->result.symkey_algo = strdup ("?.?");
     121           1 :       if (!opd->result.symkey_algo)
     122             :         {
     123           0 :           TRACE_SUC0 ("result=(null)");
     124           0 :           return NULL;
     125             :         }
     126             :     }
     127             : 
     128             :   if (_gpgme_debug_trace ())
     129             :     {
     130             :       gpgme_recipient_t rcp;
     131             : 
     132          50 :       if (opd->result.unsupported_algorithm)
     133             :         {
     134           0 :           TRACE_LOG1 ("result: unsupported_algorithm: %s",
     135             :                       opd->result.unsupported_algorithm);
     136             :         }
     137          50 :       if (opd->result.wrong_key_usage)
     138             :         {
     139           0 :           TRACE_LOG ("result: wrong key usage");
     140             :         }
     141          50 :       rcp = opd->result.recipients;
     142         146 :       while (rcp)
     143             :         {
     144          46 :           TRACE_LOG3 ("result: recipient: keyid=%s, pubkey_algo=%i, "
     145             :                       "status=%s", rcp->keyid, rcp->pubkey_algo,
     146             :                       gpg_strerror (rcp->status));
     147          46 :           rcp = rcp->next;
     148             :         }
     149          50 :       if (opd->result.file_name)
     150             :         {
     151          35 :           TRACE_LOG1 ("result: original file name: %s", opd->result.file_name);
     152             :         }
     153             :     }
     154             : 
     155          50 :   TRACE_SUC1 ("result=%p", &opd->result);
     156          50 :   return &opd->result;
     157             : }
     158             : 
     159             : 
     160             : 
     161             : /* Parse the ARGS of an error status line and record some error
     162             :  * conditions at OPD.  Returns 0 on success.  */
     163             : static gpgme_error_t
     164           0 : parse_status_error (char *args, op_data_t opd)
     165             : {
     166             :   gpgme_error_t err;
     167             :   char *field[3];
     168             :   int nfields;
     169             :   char *args2;
     170             : 
     171           0 :   if (!args)
     172           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     173             : 
     174           0 :   args2 = strdup (args); /* Split modifies the input string. */
     175           0 :   nfields = _gpgme_split_fields (args2, field, DIM (field));
     176           0 :   if (nfields < 1)
     177             :     {
     178           0 :       free (args2);
     179           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing.  */
     180             :     }
     181           0 :   err = nfields < 2 ? 0 : atoi (field[1]);
     182             : 
     183           0 :   if (!strcmp (field[0], "decrypt.algorithm"))
     184             :     {
     185           0 :       if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM
     186           0 :           && nfields > 2
     187           0 :           && strcmp (field[2], "?"))
     188             :         {
     189           0 :           opd->result.unsupported_algorithm = strdup (field[2]);
     190           0 :           if (!opd->result.unsupported_algorithm)
     191             :             {
     192           0 :               free (args2);
     193           0 :               return gpg_error_from_syserror ();
     194             :             }
     195             :         }
     196             :     }
     197           0 :   else if (!strcmp (field[0], "decrypt.keyusage"))
     198             :     {
     199           0 :       if (gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
     200           0 :         opd->result.wrong_key_usage = 1;
     201             :     }
     202           0 :   else if (!strcmp (field[0], "pkdecrypt_failed"))
     203             :     {
     204           0 :       switch (gpg_err_code (err))
     205             :         {
     206             :         case GPG_ERR_CANCELED:
     207             :         case GPG_ERR_FULLY_CANCELED:
     208             :           /* It is better to return with a cancel error code than the
     209             :            * general decryption failed error code.  */
     210           0 :           opd->pkdecrypt_failed = gpg_err_make (gpg_err_source (err),
     211             :                                                 GPG_ERR_CANCELED);
     212           0 :           break;
     213             : 
     214             :         case GPG_ERR_BAD_PASSPHRASE:
     215             :           /* A bad passphrase is severe enough that we return this
     216             :            * error code.  */
     217           0 :           opd->pkdecrypt_failed = err;
     218           0 :           break;
     219             : 
     220             :         default:
     221             :           /* For now all other error codes are ignored and the
     222             :            * standard DECRYPT_FAILED is returned.  */
     223           0 :           break;
     224             :         }
     225             :     }
     226           0 :   else if (!strcmp (field[0], "nomdc_with_legacy_cipher"))
     227             :     {
     228           0 :       opd->result.legacy_cipher_nomdc = 1;
     229           0 :       opd->not_integrity_protected = 1;
     230             :     }
     231             : 
     232             :   /* Record the first error code.  */
     233           0 :   if (err && !opd->first_status_error)
     234           0 :     opd->first_status_error = err;
     235             : 
     236             : 
     237           0 :   free (args2);
     238           0 :   return 0;
     239             : }
     240             : 
     241             : 
     242             : static gpgme_error_t
     243          47 : parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
     244             : {
     245             :   gpgme_recipient_t rec;
     246             :   char *tail;
     247             :   int i;
     248             : 
     249          47 :   rec = malloc (sizeof (*rec));
     250          47 :   if (!rec)
     251           0 :     return gpg_error_from_syserror ();
     252             : 
     253          47 :   rec->next = NULL;
     254          47 :   rec->keyid = rec->_keyid;
     255          47 :   rec->status = 0;
     256             : 
     257         799 :   for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
     258             :     {
     259         752 :       if (args[i] == '\0' || args[i] == ' ')
     260             :         break;
     261             : 
     262         752 :       rec->_keyid[i] = args[i];
     263             :     }
     264          47 :   rec->_keyid[i] = '\0';
     265             : 
     266          47 :   args = &args[i];
     267          47 :   if (*args != '\0' && *args != ' ')
     268             :     {
     269           0 :       free (rec);
     270           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE);
     271             :     }
     272             : 
     273         141 :   while (*args == ' ')
     274          47 :     args++;
     275             : 
     276          47 :   if (*args)
     277             :     {
     278          47 :       gpg_err_set_errno (0);
     279          47 :       rec->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol);
     280          47 :       if (errno || args == tail || *tail != ' ')
     281             :         {
     282             :           /* The crypto backend does not behave.  */
     283           0 :           free (rec);
     284           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     285             :         }
     286             :     }
     287             : 
     288             :   /* FIXME: The key length is always 0 right now, so no need to parse
     289             :      it.  */
     290             : 
     291          47 :   *recp = rec;
     292          47 :   return 0;
     293             : }
     294             : 
     295             : 
     296             : /* Parse the ARGS of a
     297             :  *   DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
     298             :  * status.  Returns 0 on success and updates the OPD.
     299             :  */
     300             : static gpgme_error_t
     301          53 : parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
     302             : {
     303             :   char *field[3];
     304             :   int nfields;
     305             :   char *args2;
     306             :   int mdc, aead_algo;
     307             :   const char *algostr, *modestr;
     308             : 
     309          53 :   if (!args)
     310           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     311             : 
     312          53 :   args2 = strdup (args); /* Split modifies the input string. */
     313          53 :   nfields = _gpgme_split_fields (args2, field, DIM (field));
     314          53 :   if (nfields < 2)
     315             :     {
     316           0 :       free (args2);
     317           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing.  */
     318             :     }
     319             : 
     320          53 :   mdc     = atoi (field[0]);
     321          53 :   algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
     322          53 :   aead_algo    = nfields < 3? 0 : atoi (field[2]);
     323          53 :   modestr = _gpgme_cipher_mode_name (aead_algo, protocol);
     324             : 
     325          53 :   free (args2);
     326             : 
     327          53 :   free (opd->result.symkey_algo);
     328          53 :   if (!aead_algo && mdc != 2)
     329           0 :     opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
     330             :   else
     331          53 :     opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
     332          53 :   if (!opd->result.symkey_algo)
     333           0 :     return gpg_error_from_syserror ();
     334             : 
     335          53 :   if (!mdc && !aead_algo)
     336           0 :     opd->not_integrity_protected = 1;
     337             : 
     338          53 :   return 0;
     339             : }
     340             : 
     341             : 
     342             : gpgme_error_t
     343         911 : _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
     344             :                                char *args)
     345             : {
     346         911 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
     347             :   gpgme_error_t err;
     348             :   void *hook;
     349             :   op_data_t opd;
     350             : 
     351         911 :   err = _gpgme_passphrase_status_handler (priv, code, args);
     352         911 :   if (err)
     353           0 :     return err;
     354             : 
     355         911 :   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
     356         911 :   opd = hook;
     357         911 :   if (err)
     358           0 :     return err;
     359             : 
     360         911 :   switch (code)
     361             :     {
     362             :     case GPGME_STATUS_FAILURE:
     363           0 :       opd->failure_code = _gpgme_parse_failure (args);
     364           0 :       break;
     365             : 
     366             :     case GPGME_STATUS_EOF:
     367             :       /* We force an encryption failure if we know that integrity
     368             :        * protection is missing.  For modern version of gpg using
     369             :        * modern cipher algorithms this is not required because gpg
     370             :        * will issue a failure anyway.  However older gpg versions emit
     371             :        * only a warning.
     372             :        * Fixme: These error values should probably be attributed to
     373             :        * the underlying crypto engine (as error source).  */
     374          55 :       if (opd->failed)
     375             :         {
     376             :           /* This comes from a specialized ERROR status line.  */
     377           0 :           if (opd->pkdecrypt_failed)
     378           0 :             return opd->pkdecrypt_failed;
     379             : 
     380             :           /* For an integrity failure return just DECRYPTION_FAILED;
     381             :            * the actual cause can be taken from an already set
     382             :            * decryption result flag.  */
     383           0 :           if ((opd->not_integrity_protected && !ctx->ignore_mdc_error))
     384           0 :             return gpg_error (GPG_ERR_DECRYPT_FAILED);
     385             : 
     386             :           /* If we have any other ERROR code we prefer that over
     387             :            * NO_SECKEY because it is probably the better matching
     388             :            * code.  For example a garbled message with multiple
     389             :            * plaintext will return BAD_DATA here but may also have
     390             :            * indicated a NO_SECKEY.  */
     391           0 :           if (opd->first_status_error)
     392           0 :             return opd->first_status_error;
     393             : 
     394             :           /* No secret key is pretty common reason.  */
     395           0 :           if (opd->any_no_seckey)
     396           0 :             return gpg_error (GPG_ERR_NO_SECKEY);
     397             : 
     398             :           /* Generic decryption failed error code.  */
     399           0 :           return gpg_error (GPG_ERR_DECRYPT_FAILED);
     400             :         }
     401          55 :       else if (!opd->okay)
     402             :         {
     403             :           /* No data was found.  */
     404           0 :           return gpg_error (GPG_ERR_NO_DATA);
     405             :         }
     406          55 :       else if (opd->failure_code)
     407             :         {
     408             :           /* The engine returned failure code at program exit.  */
     409           0 :           return opd->failure_code;
     410             :         }
     411          55 :       break;
     412             : 
     413             :     case GPGME_STATUS_DECRYPTION_INFO:
     414          53 :       err = parse_decryption_info (args, opd, ctx->protocol);
     415          53 :       if (err)
     416           0 :         return err;
     417          53 :       break;
     418             : 
     419             :     case GPGME_STATUS_DECRYPTION_OKAY:
     420          54 :       opd->okay = 1;
     421          54 :       break;
     422             : 
     423             :     case GPGME_STATUS_DECRYPTION_FAILED:
     424           0 :       opd->failed = 1;
     425             :       /* Tell the data object that it shall not return any data.  We
     426             :        * use the serial number because the data object may be owned by
     427             :        * another thread.  We also don't check for an error because it
     428             :        * is possible that the data object has already been destroyed
     429             :        * and we are then not interested in returning an error.  */
     430           0 :       if (!ctx->ignore_mdc_error)
     431           0 :         _gpgme_data_set_prop (NULL, opd->plaintext_dserial,
     432             :                               DATA_PROP_BLANKOUT, 1);
     433           0 :       break;
     434             : 
     435             :     case GPGME_STATUS_ERROR:
     436             :       /* Note that this is an informational status code which should
     437             :        * not lead to an error return unless it is something not
     438             :        * related to the backend.  However, it is used to return a
     439             :        * better matching final error code.  */
     440           0 :       err = parse_status_error (args, opd);
     441           0 :       if (err)
     442           0 :         return err;
     443           0 :       break;
     444             : 
     445             :     case GPGME_STATUS_ENC_TO:
     446          47 :       err = parse_enc_to (args, opd->last_recipient_p, ctx->protocol);
     447          47 :       if (err)
     448           0 :         return err;
     449             : 
     450          47 :       opd->last_recipient_p = &(*opd->last_recipient_p)->next;
     451          47 :       break;
     452             : 
     453             :     case GPGME_STATUS_SESSION_KEY:
     454           0 :       if (opd->result.session_key)
     455           0 :         free (opd->result.session_key);
     456           0 :       opd->result.session_key = strdup(args);
     457           0 :       break;
     458             : 
     459             :     case GPGME_STATUS_NO_SECKEY:
     460             :       {
     461           2 :         gpgme_recipient_t rec = opd->result.recipients;
     462           5 :         while (rec)
     463             :           {
     464           3 :             if (!strcmp (rec->keyid, args))
     465             :               {
     466           2 :                 rec->status = gpg_error (GPG_ERR_NO_SECKEY);
     467           2 :                 break;
     468             :               }
     469           1 :             rec = rec->next;
     470             :           }
     471             :         /* FIXME: Is this ok?  */
     472           2 :         if (!rec)
     473           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     474           2 :         opd->any_no_seckey = 1;
     475             :       }
     476           2 :       break;
     477             : 
     478             :     case GPGME_STATUS_PLAINTEXT:
     479             :       {
     480          52 :         int mime = 0;
     481          52 :         err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime);
     482          52 :         if (err)
     483           0 :           return err;
     484          52 :         opd->result.is_mime = !!mime;
     485             :       }
     486          52 :       break;
     487             : 
     488             :     case GPGME_STATUS_INQUIRE_MAXLEN:
     489          15 :       if (ctx->status_cb && !ctx->full_status)
     490             :         {
     491           0 :           err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
     492           0 :           if (err)
     493           0 :             return err;
     494             :         }
     495          15 :       break;
     496             : 
     497             :     case GPGME_STATUS_DECRYPTION_COMPLIANCE_MODE:
     498          14 :       PARSE_COMPLIANCE_FLAGS (args, &opd->result);
     499          14 :       break;
     500             : 
     501             :     default:
     502         619 :       break;
     503             :     }
     504             : 
     505         911 :   return 0;
     506             : }
     507             : 
     508             : 
     509             : static gpgme_error_t
     510         508 : decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
     511             : {
     512             :   gpgme_error_t err;
     513             : 
     514         508 :   err = _gpgme_progress_status_handler (priv, code, args);
     515         508 :   if (!err)
     516         508 :     err = _gpgme_decrypt_status_handler (priv, code, args);
     517         508 :   return err;
     518             : }
     519             : 
     520             : 
     521             : gpgme_error_t
     522          55 : _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx, gpgme_data_t plaintext)
     523             : {
     524             :   gpgme_error_t err;
     525             :   void *hook;
     526             :   op_data_t opd;
     527             : 
     528          55 :   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
     529             :                                sizeof (*opd), release_op_data);
     530          55 :   opd = hook;
     531          55 :   if (err)
     532           0 :     return err;
     533             : 
     534          55 :   opd->last_recipient_p = &opd->result.recipients;
     535          55 :   opd->plaintext_dserial = _gpgme_data_get_dserial (plaintext);
     536          55 :   return 0;
     537             : }
     538             : 
     539             : 
     540             : gpgme_error_t
     541          36 : _gpgme_decrypt_start (gpgme_ctx_t ctx, int synchronous,
     542             :                       gpgme_decrypt_flags_t flags,
     543             :                       gpgme_data_t cipher, gpgme_data_t plain)
     544             : {
     545             :   gpgme_error_t err;
     546             : 
     547          36 :   assert (!(flags & GPGME_DECRYPT_VERIFY));
     548             : 
     549          36 :   err = _gpgme_op_reset (ctx, synchronous);
     550          36 :   if (err)
     551           0 :     return err;
     552             : 
     553          36 :   err = _gpgme_op_decrypt_init_result (ctx, plain);
     554          36 :   if (err)
     555           0 :     return err;
     556             : 
     557          36 :   if (!cipher)
     558           0 :     return gpg_error (GPG_ERR_NO_DATA);
     559          36 :   if (!plain)
     560           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     561             : 
     562          36 :   if (err)
     563           0 :     return err;
     564             : 
     565          36 :   if (ctx->passphrase_cb)
     566             :     {
     567          31 :       err = _gpgme_engine_set_command_handler
     568             :         (ctx->engine, _gpgme_passphrase_command_handler, ctx);
     569          31 :       if (err)
     570           0 :         return err;
     571             :     }
     572             : 
     573          36 :   _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
     574             : 
     575          72 :   return _gpgme_engine_op_decrypt (ctx->engine,
     576             :                                    flags,
     577             :                                    cipher, plain,
     578          36 :                                    ctx->export_session_keys,
     579          36 :                                    ctx->override_session_key,
     580          36 :                                    ctx->auto_key_retrieve);
     581             : }
     582             : 
     583             : 
     584             : gpgme_error_t
     585           0 : gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
     586             :                         gpgme_data_t plain)
     587             : {
     588             :   gpgme_error_t err;
     589             : 
     590           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx,
     591             :               "cipher=%p, plain=%p", cipher, plain);
     592             : 
     593           0 :   if (!ctx)
     594           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     595             : 
     596           0 :   err = _gpgme_decrypt_start (ctx, 0, 0, cipher, plain);
     597           0 :   return TRACE_ERR (err);
     598             : }
     599             : 
     600             : 
     601             : /* Decrypt ciphertext CIPHER within CTX and store the resulting
     602             :    plaintext in PLAIN.  */
     603             : gpgme_error_t
     604          33 : gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
     605             : {
     606             :   gpgme_error_t err;
     607             : 
     608          33 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx,
     609             :               "cipher=%p, plain=%p", cipher, plain);
     610             : 
     611          33 :   if (!ctx)
     612           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     613             : 
     614          33 :   err = _gpgme_decrypt_start (ctx, 1, 0, cipher, plain);
     615          32 :   if (!err)
     616          32 :     err = _gpgme_wait_one (ctx);
     617          33 :   ctx->ignore_mdc_error = 0;  /* Always reset.  */
     618          33 :   return TRACE_ERR (err);
     619             : }

Generated by: LCOV version 1.13