LCOV - code coverage report
Current view: top level - src - decrypt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 110 175 62.9 %
Date: 2016-09-12 12:35:26 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /* decrypt.c - Decrypt function.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004 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             : 
      29             : #include "debug.h"
      30             : #include "gpgme.h"
      31             : #include "util.h"
      32             : #include "context.h"
      33             : #include "ops.h"
      34             : 
      35             : 
      36             : 
      37             : typedef struct
      38             : {
      39             :   struct _gpgme_op_decrypt_result result;
      40             : 
      41             :   /* The error code from a FAILURE status line or 0.  */
      42             :   gpg_error_t failure_code;
      43             : 
      44             :   int okay;
      45             :   int failed;
      46             : 
      47             :   /* A pointer to the next pointer of the last recipient in the list.
      48             :      This makes appending new invalid signers painless while
      49             :      preserving the order.  */
      50             :   gpgme_recipient_t *last_recipient_p;
      51             : } *op_data_t;
      52             : 
      53             : 
      54             : static void
      55          38 : release_op_data (void *hook)
      56             : {
      57          38 :   op_data_t opd = (op_data_t) hook;
      58          38 :   gpgme_recipient_t recipient = opd->result.recipients;
      59             : 
      60          38 :   if (opd->result.unsupported_algorithm)
      61           0 :     free (opd->result.unsupported_algorithm);
      62             : 
      63          38 :   if (opd->result.file_name)
      64           6 :     free (opd->result.file_name);
      65             : 
      66         108 :   while (recipient)
      67             :     {
      68          32 :       gpgme_recipient_t next = recipient->next;
      69          32 :       free (recipient);
      70          32 :       recipient = next;
      71             :     }
      72          38 : }
      73             : 
      74             : 
      75             : gpgme_decrypt_result_t
      76          35 : gpgme_op_decrypt_result (gpgme_ctx_t ctx)
      77             : {
      78             :   void *hook;
      79             :   op_data_t opd;
      80             :   gpgme_error_t err;
      81             : 
      82          35 :   TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);
      83             : 
      84          35 :   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
      85          35 :   opd = hook;
      86          35 :   if (err || !opd)
      87             :     {
      88           0 :       TRACE_SUC0 ("result=(null)");
      89           0 :       return NULL;
      90             :     }
      91             : 
      92             :   if (_gpgme_debug_trace ())
      93             :     {
      94             :       gpgme_recipient_t rcp;
      95             : 
      96          35 :       if (opd->result.unsupported_algorithm)
      97             :         {
      98           0 :           TRACE_LOG1 ("result: unsupported_algorithm: %s",
      99             :                       opd->result.unsupported_algorithm);
     100             :         }
     101          35 :       if (opd->result.wrong_key_usage)
     102             :         {
     103           0 :           TRACE_LOG ("result: wrong key usage");
     104             :         }
     105          35 :       rcp = opd->result.recipients;
     106         102 :       while (rcp)
     107             :         {
     108          32 :           TRACE_LOG3 ("result: recipient: keyid=%s, pubkey_algo=%i, "
     109             :                       "status=%s", rcp->keyid, rcp->pubkey_algo,
     110             :                       gpg_strerror (rcp->status));
     111          32 :           rcp = rcp->next;
     112             :         }
     113          35 :       if (opd->result.file_name)
     114             :         {
     115           6 :           TRACE_LOG1 ("result: original file name: %s", opd->result.file_name);
     116             :         }
     117             :     }
     118             : 
     119          35 :   TRACE_SUC1 ("result=%p", &opd->result);
     120          35 :   return &opd->result;
     121             : }
     122             : 
     123             : 
     124             : static gpgme_error_t
     125          30 : parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
     126             : {
     127             :   gpgme_recipient_t rec;
     128             :   char *tail;
     129             :   int i;
     130             : 
     131          30 :   rec = malloc (sizeof (*rec));
     132          30 :   if (!rec)
     133           0 :     return gpg_error_from_syserror ();
     134             : 
     135          30 :   rec->next = NULL;
     136          30 :   rec->keyid = rec->_keyid;
     137          30 :   rec->status = 0;
     138             : 
     139         510 :   for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
     140             :     {
     141         480 :       if (args[i] == '\0' || args[i] == ' ')
     142             :         break;
     143             : 
     144         480 :       rec->_keyid[i] = args[i];
     145             :     }
     146          30 :   rec->_keyid[i] = '\0';
     147             : 
     148          30 :   args = &args[i];
     149          30 :   if (*args != '\0' && *args != ' ')
     150             :     {
     151           0 :       free (rec);
     152           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE);
     153             :     }
     154             : 
     155          90 :   while (*args == ' ')
     156          30 :     args++;
     157             : 
     158          30 :   if (*args)
     159             :     {
     160          30 :       gpg_err_set_errno (0);
     161          30 :       rec->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol);
     162          30 :       if (errno || args == tail || *tail != ' ')
     163             :         {
     164             :           /* The crypto backend does not behave.  */
     165           0 :           free (rec);
     166           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     167             :         }
     168             :     }
     169             : 
     170             :   /* FIXME: The key length is always 0 right now, so no need to parse
     171             :      it.  */
     172             : 
     173          30 :   *recp = rec;
     174          30 :   return 0;
     175             : }
     176             : 
     177             : 
     178             : gpgme_error_t
     179         542 : _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
     180             :                                char *args)
     181             : {
     182         542 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
     183             :   gpgme_error_t err;
     184             :   void *hook;
     185             :   op_data_t opd;
     186             : 
     187         542 :   err = _gpgme_passphrase_status_handler (priv, code, args);
     188         541 :   if (err)
     189           0 :     return err;
     190             : 
     191         541 :   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
     192         541 :   opd = hook;
     193         541 :   if (err)
     194           0 :     return err;
     195             : 
     196         541 :   switch (code)
     197             :     {
     198             :     case GPGME_STATUS_FAILURE:
     199           0 :       opd->failure_code = _gpgme_parse_failure (args);
     200           0 :       break;
     201             : 
     202             :     case GPGME_STATUS_EOF:
     203             :       /* FIXME: These error values should probably be attributed to
     204             :          the underlying crypto engine (as error source).  */
     205          38 :       if (opd->failed)
     206           0 :         return gpg_error (GPG_ERR_DECRYPT_FAILED);
     207          38 :       else if (!opd->okay)
     208           0 :         return gpg_error (GPG_ERR_NO_DATA);
     209          38 :       else if (opd->failure_code)
     210           0 :         return opd->failure_code;
     211          38 :       break;
     212             : 
     213             :     case GPGME_STATUS_DECRYPTION_INFO:
     214             :       /* Fixme: Provide a way to return the used symmetric algorithm. */
     215          36 :       break;
     216             : 
     217             :     case GPGME_STATUS_DECRYPTION_OKAY:
     218          39 :       opd->okay = 1;
     219          39 :       break;
     220             : 
     221             :     case GPGME_STATUS_DECRYPTION_FAILED:
     222           0 :       opd->failed = 1;
     223           0 :       break;
     224             : 
     225             :     case GPGME_STATUS_ERROR:
     226             :       /* Note that this is an informational status code which should
     227             :          not lead to an error return unless it is something not
     228             :          related to the backend.  */
     229             :       {
     230           0 :         const char d_alg[] = "decrypt.algorithm";
     231           0 :         const char k_alg[] = "decrypt.keyusage";
     232             : 
     233           0 :         if (!strncmp (args, d_alg, sizeof (d_alg) - 1))
     234             :           {
     235           0 :             args += sizeof (d_alg) - 1;
     236           0 :             while (*args == ' ')
     237           0 :               args++;
     238             : 
     239           0 :             if (gpg_err_code (atoi (args)) == GPG_ERR_UNSUPPORTED_ALGORITHM)
     240             :               {
     241             :                 char *end;
     242             : 
     243           0 :                 while (*args && *args != ' ')
     244           0 :                   args++;
     245           0 :                 while (*args == ' ')
     246           0 :                   args++;
     247             : 
     248           0 :                 end = strchr (args, ' ');
     249           0 :                 if (end)
     250           0 :                   *end = '\0';
     251             : 
     252           0 :                 if (!(*args == '?' && *(args + 1) == '\0'))
     253             :                   {
     254           0 :                     opd->result.unsupported_algorithm = strdup (args);
     255           0 :                     if (!opd->result.unsupported_algorithm)
     256           0 :                       return gpg_error_from_syserror ();
     257             :                   }
     258             :               }
     259             :           }
     260           0 :         else if (!strncmp (args, k_alg, sizeof (k_alg) - 1))
     261             :           {
     262           0 :             args += sizeof (k_alg) - 1;
     263           0 :             while (*args == ' ')
     264           0 :               args++;
     265             : 
     266           0 :             if (gpg_err_code (atoi (args)) == GPG_ERR_WRONG_KEY_USAGE)
     267           0 :               opd->result.wrong_key_usage = 1;
     268             :           }
     269             :       }
     270           0 :       break;
     271             : 
     272             :     case GPGME_STATUS_ENC_TO:
     273          30 :       err = parse_enc_to (args, opd->last_recipient_p, ctx->protocol);
     274          30 :       if (err)
     275           0 :         return err;
     276             : 
     277          30 :       opd->last_recipient_p = &(*opd->last_recipient_p)->next;
     278          30 :       break;
     279             : 
     280             :     case GPGME_STATUS_NO_SECKEY:
     281             :       {
     282           1 :         gpgme_recipient_t rec = opd->result.recipients;
     283             : 
     284           2 :         while (rec)
     285             :           {
     286           1 :             if (!strcmp (rec->keyid, args))
     287             :               {
     288           1 :                 rec->status = gpg_error (GPG_ERR_NO_SECKEY);
     289           1 :                 break;
     290             :               }
     291           0 :             rec = rec->next;
     292             :           }
     293             :         /* FIXME: Is this ok?  */
     294           1 :         if (!rec)
     295           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     296             :       }
     297           1 :       break;
     298             : 
     299             :     case GPGME_STATUS_PLAINTEXT:
     300          36 :       err = _gpgme_parse_plaintext (args, &opd->result.file_name);
     301          36 :       if (err)
     302           0 :         return err;
     303          36 :       break;
     304             : 
     305             :     case GPGME_STATUS_INQUIRE_MAXLEN:
     306           7 :       if (ctx->status_cb && !ctx->full_status)
     307             :         {
     308           0 :           err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
     309           0 :           if (err)
     310           0 :             return err;
     311             :         }
     312           7 :       break;
     313             : 
     314             :     default:
     315         354 :       break;
     316             :     }
     317             : 
     318         541 :   return 0;
     319             : }
     320             : 
     321             : 
     322             : static gpgme_error_t
     323         420 : decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
     324             : {
     325             :   gpgme_error_t err;
     326             : 
     327         420 :   err = _gpgme_progress_status_handler (priv, code, args);
     328         420 :   if (!err)
     329         420 :     err = _gpgme_decrypt_status_handler (priv, code, args);
     330         419 :   return err;
     331             : }
     332             : 
     333             : 
     334             : gpgme_error_t
     335          37 : _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
     336             : {
     337             :   gpgme_error_t err;
     338             :   void *hook;
     339             :   op_data_t opd;
     340             : 
     341          37 :   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
     342             :                                sizeof (*opd), release_op_data);
     343          37 :   opd = hook;
     344          37 :   if (err)
     345           0 :     return err;
     346             : 
     347          37 :   opd->last_recipient_p = &opd->result.recipients;
     348          37 :   return 0;
     349             : }
     350             : 
     351             : 
     352             : static gpgme_error_t
     353          30 : decrypt_start (gpgme_ctx_t ctx, int synchronous,
     354             :                       gpgme_data_t cipher, gpgme_data_t plain)
     355             : {
     356             :   gpgme_error_t err;
     357             : 
     358          30 :   err = _gpgme_op_reset (ctx, synchronous);
     359          30 :   if (err)
     360           0 :     return err;
     361             : 
     362          30 :   err = _gpgme_op_decrypt_init_result (ctx);
     363          30 :   if (err)
     364           0 :     return err;
     365             : 
     366          30 :   if (!cipher)
     367           0 :     return gpg_error (GPG_ERR_NO_DATA);
     368          30 :   if (!plain)
     369           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     370             : 
     371          30 :   if (err)
     372           0 :     return err;
     373             : 
     374          30 :   if (ctx->passphrase_cb)
     375             :     {
     376          27 :       err = _gpgme_engine_set_command_handler
     377             :         (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
     378          27 :       if (err)
     379           0 :         return err;
     380             :     }
     381             : 
     382          30 :   _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
     383             : 
     384          30 :   return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain);
     385             : }
     386             : 
     387             : 
     388             : gpgme_error_t
     389           0 : gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
     390             :                         gpgme_data_t plain)
     391             : {
     392             :   gpgme_error_t err;
     393             : 
     394           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx,
     395             :               "cipher=%p, plain=%p", cipher, plain);
     396             : 
     397           0 :   if (!ctx)
     398           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     399             : 
     400           0 :   err = decrypt_start (ctx, 0, cipher, plain);
     401           0 :   return TRACE_ERR (err);
     402             : }
     403             : 
     404             : 
     405             : /* Decrypt ciphertext CIPHER within CTX and store the resulting
     406             :    plaintext in PLAIN.  */
     407             : gpgme_error_t
     408          30 : gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
     409             : {
     410             :   gpgme_error_t err;
     411             : 
     412          30 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx,
     413             :               "cipher=%p, plain=%p", cipher, plain);
     414             : 
     415          30 :   if (!ctx)
     416           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     417             : 
     418          30 :   err = decrypt_start (ctx, 1, cipher, plain);
     419          29 :   if (!err)
     420          29 :     err = _gpgme_wait_one (ctx);
     421          31 :   return TRACE_ERR (err);
     422             : }

Generated by: LCOV version 1.11