LCOV - code coverage report
Current view: top level - g10 - decrypt-data.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 150 219 68.5 %
Date: 2016-11-29 15:00:56 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* decrypt-data.c - Decrypt an encrypted data packet
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2005,
       3             :  *               2006, 2009 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : 
      26             : #include "gpg.h"
      27             : #include "util.h"
      28             : #include "packet.h"
      29             : #include "options.h"
      30             : #include "i18n.h"
      31             : #include "status.h"
      32             : 
      33             : 
      34             : static int mdc_decode_filter ( void *opaque, int control, IOBUF a,
      35             :                                byte *buf, size_t *ret_len);
      36             : static int decode_filter ( void *opaque, int control, IOBUF a,
      37             :                                         byte *buf, size_t *ret_len);
      38             : 
      39             : typedef struct decode_filter_context_s
      40             : {
      41             :   gcry_cipher_hd_t cipher_hd;
      42             :   gcry_md_hd_t mdc_hash;
      43             :   char defer[22];
      44             :   int  defer_filled;
      45             :   int  eof_seen;
      46             :   int  refcount;
      47             :   int  partial;   /* Working on a partial length packet.  */
      48             :   size_t length;  /* If !partial: Remaining bytes in the packet.  */
      49             : } *decode_filter_ctx_t;
      50             : 
      51             : 
      52             : /* Helper to release the decode context.  */
      53             : static void
      54         638 : release_dfx_context (decode_filter_ctx_t dfx)
      55             : {
      56         638 :   if (!dfx)
      57         638 :     return;
      58             : 
      59         638 :   log_assert (dfx->refcount);
      60         638 :   if ( !--dfx->refcount )
      61             :     {
      62         319 :       gcry_cipher_close (dfx->cipher_hd);
      63         319 :       dfx->cipher_hd = NULL;
      64         319 :       gcry_md_close (dfx->mdc_hash);
      65         319 :       dfx->mdc_hash = NULL;
      66         319 :       xfree (dfx);
      67             :     }
      68             : }
      69             : 
      70             : 
      71             : 
      72             : /****************
      73             :  * Decrypt the data, specified by ED with the key DEK.
      74             :  */
      75             : int
      76         319 : decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
      77             : {
      78             :   decode_filter_ctx_t dfx;
      79             :   byte *p;
      80         319 :   int rc=0, c, i;
      81             :   byte temp[32];
      82             :   unsigned blocksize;
      83             :   unsigned nprefix;
      84             : 
      85         319 :   dfx = xtrycalloc (1, sizeof *dfx);
      86         319 :   if (!dfx)
      87           0 :     return gpg_error_from_syserror ();
      88         319 :   dfx->refcount = 1;
      89             : 
      90         319 :   if ( opt.verbose && !dek->algo_info_printed )
      91             :     {
      92           0 :       if (!openpgp_cipher_test_algo (dek->algo))
      93           0 :         log_info (_("%s encrypted data\n"),
      94           0 :                   openpgp_cipher_algo_name (dek->algo));
      95             :       else
      96           0 :         log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
      97           0 :       dek->algo_info_printed = 1;
      98             :     }
      99             : 
     100             :   {
     101             :     char buf[20];
     102             : 
     103         319 :     snprintf (buf, sizeof buf, "%d %d", ed->mdc_method, dek->algo);
     104         319 :     write_status_text (STATUS_DECRYPTION_INFO, buf);
     105             :   }
     106             : 
     107         319 :   if (opt.show_session_key)
     108             :     {
     109             :       char numbuf[25];
     110             :       char *hexbuf;
     111             : 
     112           0 :       snprintf (numbuf, sizeof numbuf, "%d:", dek->algo);
     113           0 :       hexbuf = bin2hex (dek->key, dek->keylen, NULL);
     114           0 :       if (!hexbuf)
     115             :         {
     116           0 :           rc = gpg_error_from_syserror ();
     117           0 :           goto leave;
     118             :         }
     119           0 :       log_info ("session key: '%s%s'\n", numbuf, hexbuf);
     120           0 :       write_status_strings (STATUS_SESSION_KEY, numbuf, hexbuf, NULL);
     121           0 :       xfree (hexbuf);
     122             :     }
     123             : 
     124         319 :   rc = openpgp_cipher_test_algo (dek->algo);
     125         319 :   if (rc)
     126           0 :     goto leave;
     127         319 :   blocksize = openpgp_cipher_get_algo_blklen (dek->algo);
     128         319 :   if ( !blocksize || blocksize > 16 )
     129           0 :     log_fatal ("unsupported blocksize %u\n", blocksize );
     130         319 :   nprefix = blocksize;
     131         319 :   if ( ed->len && ed->len < (nprefix+2) )
     132             :     {
     133             :        /* An invalid message.  We can't check that during parsing
     134             :           because we may not know the used cipher then.  */
     135           0 :       rc = gpg_error (GPG_ERR_INV_PACKET);
     136           0 :       goto leave;
     137             :     }
     138             : 
     139         319 :   if ( ed->mdc_method )
     140             :     {
     141         259 :       if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
     142           0 :         BUG ();
     143         259 :       if ( DBG_HASHING )
     144           0 :         gcry_md_debug (dfx->mdc_hash, "checkmdc");
     145             :     }
     146             : 
     147         319 :   rc = openpgp_cipher_open (&dfx->cipher_hd, dek->algo,
     148             :                             GCRY_CIPHER_MODE_CFB,
     149             :                             (GCRY_CIPHER_SECURE
     150             :                              | ((ed->mdc_method || dek->algo >= 100)?
     151             :                                 0 : GCRY_CIPHER_ENABLE_SYNC)));
     152         319 :   if (rc)
     153             :     {
     154             :       /* We should never get an error here cause we already checked
     155             :        * that the algorithm is available.  */
     156           0 :       BUG();
     157             :     }
     158             : 
     159             : 
     160             :   /* log_hexdump( "thekey", dek->key, dek->keylen );*/
     161         319 :   rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
     162         319 :   if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
     163             :     {
     164           0 :       log_info(_("WARNING: message was encrypted with"
     165             :                  " a weak key in the symmetric cipher.\n"));
     166           0 :       rc=0;
     167             :     }
     168         319 :   else if( rc )
     169             :     {
     170           0 :       log_error("key setup failed: %s\n", gpg_strerror (rc) );
     171           0 :       goto leave;
     172             :     }
     173             : 
     174         319 :   if (!ed->buf)
     175             :     {
     176           0 :       log_error(_("problem handling encrypted packet\n"));
     177           0 :       goto leave;
     178             :     }
     179             : 
     180         319 :   gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);
     181             : 
     182         319 :   if ( ed->len )
     183             :     {
     184         738 :       for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- )
     185             :         {
     186         692 :           if ( (c=iobuf_get(ed->buf)) == -1 )
     187           0 :             break;
     188             :           else
     189         692 :             temp[i] = c;
     190             :         }
     191             :     }
     192             :   else
     193             :     {
     194        4499 :       for (i=0; i < (nprefix+2); i++ )
     195        4226 :         if ( (c=iobuf_get(ed->buf)) == -1 )
     196           0 :           break;
     197             :         else
     198        4226 :           temp[i] = c;
     199             :     }
     200             : 
     201         319 :   gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
     202         319 :   gcry_cipher_sync (dfx->cipher_hd);
     203         319 :   p = temp;
     204             :   /* log_hexdump( "prefix", temp, nprefix+2 ); */
     205         319 :   if (dek->symmetric
     206          57 :       && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
     207             :     {
     208           0 :       rc = gpg_error (GPG_ERR_BAD_KEY);
     209           0 :       goto leave;
     210             :     }
     211             : 
     212         319 :   if ( dfx->mdc_hash )
     213         259 :     gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
     214             : 
     215         319 :   dfx->refcount++;
     216         319 :   dfx->partial = ed->is_partial;
     217         319 :   dfx->length = ed->len;
     218         319 :   if ( ed->mdc_method )
     219         259 :     iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
     220             :   else
     221          60 :     iobuf_push_filter ( ed->buf, decode_filter, dfx );
     222             : 
     223         319 :   if (opt.unwrap_encryption)
     224             :     {
     225             :       char *filename;
     226             :       estream_t fp;
     227           0 :       rc = get_output_file ("", 0, ed->buf, &filename, &fp);
     228           0 :       if (! rc)
     229             :         {
     230           0 :           iobuf_t output = iobuf_esopen (fp, "w", 0);
     231           0 :           armor_filter_context_t *afx = NULL;
     232             : 
     233           0 :           if (opt.armor)
     234             :             {
     235           0 :               afx = new_armor_context ();
     236           0 :               push_armor_filter (afx, output);
     237             :             }
     238             : 
     239           0 :           iobuf_copy (output, ed->buf);
     240           0 :           if ((rc = iobuf_error (ed->buf)))
     241           0 :             log_error (_("error reading '%s': %s\n"),
     242             :                        filename, gpg_strerror (rc));
     243           0 :           else if ((rc = iobuf_error (output)))
     244           0 :             log_error (_("error writing '%s': %s\n"),
     245             :                        filename, gpg_strerror (rc));
     246             : 
     247           0 :           iobuf_close (output);
     248           0 :           if (afx)
     249           0 :             release_armor_context (afx);
     250             :         }
     251             :     }
     252             :   else
     253         319 :     proc_packets (ctrl, procctx, ed->buf );
     254             : 
     255         319 :   ed->buf = NULL;
     256         319 :   if (dfx->eof_seen > 1 )
     257           0 :     rc = gpg_error (GPG_ERR_INV_PACKET);
     258         319 :   else if ( ed->mdc_method )
     259             :     {
     260             :       /* We used to let parse-packet.c handle the MDC packet but this
     261             :          turned out to be a problem with compressed packets: With old
     262             :          style packets there is no length information available and
     263             :          the decompressor uses an implicit end.  However we can't know
     264             :          this implicit end beforehand (:-) and thus may feed the
     265             :          decompressor with more bytes than actually needed.  It would
     266             :          be possible to unread the extra bytes but due to our weird
     267             :          iobuf system any unread is non reliable due to filters
     268             :          already popped off.  The easy and sane solution is to care
     269             :          about the MDC packet only here and never pass it to the
     270             :          packet parser.  Fortunatley the OpenPGP spec requires a
     271             :          strict format for the MDC packet so that we know that 22
     272             :          bytes are appended.  */
     273         259 :       int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
     274             : 
     275         259 :       log_assert (dfx->cipher_hd);
     276         259 :       log_assert (dfx->mdc_hash);
     277         259 :       gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
     278         259 :       gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
     279         259 :       gcry_md_final (dfx->mdc_hash);
     280             : 
     281         259 :       if (   dfx->defer[0] != '\xd3'
     282         259 :           || dfx->defer[1] != '\x14'
     283         259 :           || datalen != 20
     284         259 :           || memcmp (gcry_md_read (dfx->mdc_hash, 0), dfx->defer+2, datalen))
     285           0 :         rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
     286             :       /* log_printhex("MDC message:", dfx->defer, 22); */
     287             :       /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
     288             :     }
     289             : 
     290             : 
     291             :  leave:
     292         319 :   release_dfx_context (dfx);
     293         319 :   return rc;
     294             : }
     295             : 
     296             : 
     297             : 
     298             : static int
     299        1692 : mdc_decode_filter (void *opaque, int control, IOBUF a,
     300             :                    byte *buf, size_t *ret_len)
     301             : {
     302        1692 :   decode_filter_ctx_t dfx = opaque;
     303        1692 :   size_t n, size = *ret_len;
     304        1692 :   int rc = 0;
     305             :   int c;
     306             : 
     307             :   /* Note: We need to distinguish between a partial and a fixed length
     308             :      packet.  The first is the usual case as created by GPG.  However
     309             :      for short messages the format degrades to a fixed length packet
     310             :      and other implementations might use fixed length as well.  Only
     311             :      looking for the EOF on fixed data works only if the encrypted
     312             :      packet is not followed by other data.  This used to be a long
     313             :      standing bug which was fixed on 2009-10-02.  */
     314             : 
     315        1692 :   if ( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen )
     316             :     {
     317         259 :       *ret_len = 0;
     318         259 :       rc = -1;
     319             :     }
     320        1433 :   else if( control == IOBUFCTRL_UNDERFLOW )
     321             :     {
     322         915 :       log_assert (a);
     323         915 :       log_assert (size > 44); /* Our code requires at least this size.  */
     324             : 
     325             :       /* Get at least 22 bytes and put it ahead in the buffer.  */
     326         915 :       if (dfx->partial)
     327             :         {
     328       20240 :           for (n=22; n < 44; n++)
     329             :             {
     330       19360 :               if ( (c = iobuf_get(a)) == -1 )
     331           0 :                 break;
     332       19360 :               buf[n] = c;
     333             :             }
     334             :         }
     335             :       else
     336             :         {
     337         805 :           for (n=22; n < 44 && dfx->length; n++, dfx->length--)
     338             :             {
     339         770 :               c = iobuf_get (a);
     340         770 :               if (c == -1)
     341           0 :                 break; /* Premature EOF.  */
     342         770 :               buf[n] = c;
     343             :             }
     344             :         }
     345         915 :       if (n == 44)
     346             :         {
     347             :           /* We have enough stuff - flush the deferred stuff.  */
     348         915 :           if ( !dfx->defer_filled )  /* First time. */
     349             :             {
     350         259 :               memcpy (buf, buf+22, 22);
     351         259 :               n = 22;
     352             :             }
     353             :           else
     354             :             {
     355         656 :               memcpy (buf, dfx->defer, 22);
     356             :             }
     357             :           /* Fill up the buffer. */
     358         915 :           if (dfx->partial)
     359             :             {
     360     5998328 :               for (; n < size; n++ )
     361             :                 {
     362     5997672 :                   if ( (c = iobuf_get(a)) == -1 )
     363             :                     {
     364         224 :                       dfx->eof_seen = 1; /* Normal EOF. */
     365         224 :                       break;
     366             :                     }
     367     5997448 :                   buf[n] = c;
     368             :                 }
     369             :             }
     370             :           else
     371             :             {
     372        2620 :               for (; n < size && dfx->length; n++, dfx->length--)
     373             :                 {
     374        2585 :                   c = iobuf_get(a);
     375        2585 :                   if (c == -1)
     376             :                     {
     377           0 :                       dfx->eof_seen = 3; /* Premature EOF. */
     378           0 :                       break;
     379             :                     }
     380        2585 :                   buf[n] = c;
     381             :                 }
     382          35 :               if (!dfx->length)
     383          35 :                 dfx->eof_seen = 1; /* Normal EOF.  */
     384             :             }
     385             : 
     386             :           /* Move the trailing 22 bytes back to the defer buffer.  We
     387             :              have at least 44 bytes thus a memmove is not needed.  */
     388         915 :           n -= 22;
     389         915 :           memcpy (dfx->defer, buf+n, 22 );
     390         915 :           dfx->defer_filled = 1;
     391             :         }
     392           0 :       else if ( !dfx->defer_filled )  /* EOF seen but empty defer buffer. */
     393             :         {
     394             :           /* This is bad because it means an incomplete hash. */
     395           0 :           n -= 22;
     396           0 :           memcpy (buf, buf+22, n );
     397           0 :           dfx->eof_seen = 2; /* EOF with incomplete hash.  */
     398             :         }
     399             :       else  /* EOF seen (i.e. read less than 22 bytes). */
     400             :         {
     401           0 :           memcpy (buf, dfx->defer, 22 );
     402           0 :           n -= 22;
     403           0 :           memcpy (dfx->defer, buf+n, 22 );
     404           0 :           dfx->eof_seen = 1; /* Normal EOF. */
     405             :         }
     406             : 
     407         915 :       if ( n )
     408             :         {
     409         915 :           if ( dfx->cipher_hd )
     410         915 :             gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
     411         915 :           if ( dfx->mdc_hash )
     412         915 :             gcry_md_write (dfx->mdc_hash, buf, n);
     413             :         }
     414             :       else
     415             :         {
     416           0 :           log_assert ( dfx->eof_seen );
     417           0 :           rc = -1; /* Return EOF.  */
     418             :         }
     419         915 :       *ret_len = n;
     420             :     }
     421         518 :   else if ( control == IOBUFCTRL_FREE )
     422             :     {
     423         259 :       release_dfx_context (dfx);
     424             :     }
     425         259 :   else if ( control == IOBUFCTRL_DESC )
     426             :     {
     427           0 :       mem2str (buf, "mdc_decode_filter", *ret_len);
     428             :     }
     429        1692 :   return rc;
     430             : }
     431             : 
     432             : 
     433             : static int
     434         384 : decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
     435             : {
     436         384 :   decode_filter_ctx_t fc = opaque;
     437         384 :   size_t size = *ret_len;
     438             :   size_t n;
     439         384 :   int c, rc = 0;
     440             : 
     441             : 
     442         384 :   if ( control == IOBUFCTRL_UNDERFLOW && fc->eof_seen )
     443             :     {
     444          60 :       *ret_len = 0;
     445          60 :       rc = -1;
     446             :     }
     447         324 :   else if ( control == IOBUFCTRL_UNDERFLOW )
     448             :     {
     449         204 :       log_assert (a);
     450             : 
     451         204 :       if (fc->partial)
     452             :         {
     453     1315451 :           for (n=0; n < size; n++ )
     454             :             {
     455     1315307 :               c = iobuf_get(a);
     456     1315307 :               if (c == -1)
     457             :                 {
     458          49 :                   fc->eof_seen = 1; /* Normal EOF. */
     459          49 :                   break;
     460             :                 }
     461     1315258 :               buf[n] = c;
     462             :             }
     463             :         }
     464             :       else
     465             :         {
     466         546 :           for (n=0; n < size && fc->length; n++, fc->length--)
     467             :             {
     468         535 :               c = iobuf_get(a);
     469         535 :               if (c == -1)
     470             :                 {
     471           0 :                   fc->eof_seen = 3; /* Premature EOF. */
     472           0 :                   break;
     473             :                 }
     474         535 :               buf[n] = c;
     475             :             }
     476          11 :           if (!fc->length)
     477          11 :             fc->eof_seen = 1; /* Normal EOF.  */
     478             :         }
     479         204 :       if (n)
     480             :         {
     481         204 :           if (fc->cipher_hd)
     482         204 :             gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
     483             :         }
     484             :       else
     485             :         {
     486           0 :           if (!fc->eof_seen)
     487           0 :             fc->eof_seen = 1;
     488           0 :           rc = -1; /* Return EOF. */
     489             :         }
     490         204 :       *ret_len = n;
     491             :     }
     492         120 :   else if ( control == IOBUFCTRL_FREE )
     493             :     {
     494          60 :       release_dfx_context (fc);
     495             :     }
     496          60 :   else if ( control == IOBUFCTRL_DESC )
     497             :     {
     498           0 :       mem2str (buf, "decode_filter", *ret_len);
     499             :     }
     500         384 :   return rc;
     501             : }

Generated by: LCOV version 1.11