Merge branch 'STABLE-BRANCH-2-2' into master
[gnupg.git] / g10 / decrypt-data.c
index 22a6aef..736534d 100644 (file)
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 
 #include "gpg.h"
-#include "util.h"
+#include "../common/util.h"
 #include "packet.h"
 #include "options.h"
-#include "i18n.h"
-#include "status.h"
+#include "../common/i18n.h"
+#include "../common/status.h"
+#include "../common/compliance.h"
 
 
 static int mdc_decode_filter ( void *opaque, int control, IOBUF a,
@@ -57,7 +57,7 @@ release_dfx_context (decode_filter_ctx_t dfx)
   if (!dfx)
     return;
 
-  assert (dfx->refcount);
+  log_assert (dfx->refcount);
   if ( !--dfx->refcount )
     {
       gcry_cipher_close (dfx->cipher_hd);
@@ -98,6 +98,17 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
       dek->algo_info_printed = 1;
     }
 
+  /* Check compliance.  */
+  if (! gnupg_cipher_is_allowed (opt.compliance, 0, dek->algo,
+                                 GCRY_CIPHER_MODE_CFB))
+    {
+      log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
+                openpgp_cipher_algo_name (dek->algo),
+                gnupg_compliance_option_string (opt.compliance));
+      rc = gpg_error (GPG_ERR_CIPHER_ALGO);
+      goto leave;
+    }
+
   {
     char buf[20];
 
@@ -130,7 +141,12 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
     log_fatal ("unsupported blocksize %u\n", blocksize );
   nprefix = blocksize;
   if ( ed->len && ed->len < (nprefix+2) )
-    BUG();
+    {
+       /* An invalid message.  We can't check that during parsing
+          because we may not know the used cipher then.  */
+      rc = gpg_error (GPG_ERR_INV_PACKET);
+      goto leave;
+    }
 
   if ( ed->mdc_method )
     {
@@ -163,7 +179,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
     }
   else if( rc )
     {
-      log_error("key setup failed: %s\n", g10_errstr(rc) );
+      log_error("key setup failed: %s\n", gpg_strerror (rc) );
       goto leave;
     }
 
@@ -216,7 +232,39 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
   else
     iobuf_push_filter ( ed->buf, decode_filter, dfx );
 
-  proc_packets (ctrl, procctx, ed->buf );
+  if (opt.unwrap_encryption)
+    {
+      char *filename = NULL;
+      estream_t fp;
+      rc = get_output_file ("", 0, ed->buf, &filename, &fp);
+      if (! rc)
+        {
+          iobuf_t output = iobuf_esopen (fp, "w", 0);
+          armor_filter_context_t *afx = NULL;
+
+          if (opt.armor)
+            {
+              afx = new_armor_context ();
+              push_armor_filter (afx, output);
+            }
+
+          iobuf_copy (output, ed->buf);
+          if ((rc = iobuf_error (ed->buf)))
+            log_error (_("error reading '%s': %s\n"),
+                       filename, gpg_strerror (rc));
+          else if ((rc = iobuf_error (output)))
+            log_error (_("error writing '%s': %s\n"),
+                       filename, gpg_strerror (rc));
+
+          iobuf_close (output);
+          if (afx)
+            release_armor_context (afx);
+        }
+      xfree (filename);
+    }
+  else
+    proc_packets (ctrl, procctx, ed->buf );
+
   ed->buf = NULL;
   if (dfx->eof_seen > 1 )
     rc = gpg_error (GPG_ERR_INV_PACKET);
@@ -237,20 +285,16 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
          bytes are appended.  */
       int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
 
-      assert (dfx->cipher_hd);
-      assert (dfx->mdc_hash);
+      log_assert (dfx->cipher_hd);
+      log_assert (dfx->mdc_hash);
       gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
       gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
       gcry_md_final (dfx->mdc_hash);
 
-      if (dfx->defer[0] != '\xd3' || dfx->defer[1] != '\x14' )
-        {
-          log_error("mdc_packet with invalid encoding\n");
-          rc = gpg_error (GPG_ERR_INV_PACKET);
-        }
-      else if (datalen != 20
-               || memcmp (gcry_md_read (dfx->mdc_hash, 0),
-                          dfx->defer+2,datalen ))
+      if (   dfx->defer[0] != '\xd3'
+          || dfx->defer[1] != '\x14'
+          || datalen != 20
+          || memcmp (gcry_md_read (dfx->mdc_hash, 0), dfx->defer+2, datalen))
         rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
       /* log_printhex("MDC message:", dfx->defer, 22); */
       /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
@@ -288,8 +332,8 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
     }
   else if( control == IOBUFCTRL_UNDERFLOW )
     {
-      assert (a);
-      assert (size > 44); /* Our code requires at least this size.  */
+      log_assert (a);
+      log_assert (size > 44); /* Our code requires at least this size.  */
 
       /* Get at least 22 bytes and put it ahead in the buffer.  */
       if (dfx->partial)
@@ -382,7 +426,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
        }
       else
         {
-          assert ( dfx->eof_seen );
+          log_assert ( dfx->eof_seen );
           rc = -1; /* Return EOF.  */
        }
       *ret_len = n;
@@ -393,7 +437,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
     }
   else if ( control == IOBUFCTRL_DESC )
     {
-      *(char**)buf = "mdc_decode_filter";
+      mem2str (buf, "mdc_decode_filter", *ret_len);
     }
   return rc;
 }
@@ -415,7 +459,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
     }
   else if ( control == IOBUFCTRL_UNDERFLOW )
     {
-      assert(a);
+      log_assert (a);
 
       if (fc->partial)
         {
@@ -464,7 +508,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
     }
   else if ( control == IOBUFCTRL_DESC )
     {
-      *(char**)buf = "decode_filter";
+      mem2str (buf, "decode_filter", *ret_len);
     }
   return rc;
 }