dirmngr: Fix https incorrectly reported in help
[gnupg.git] / g10 / decrypt-data.c
index c9da9be..1380faf 100644 (file)
@@ -27,9 +27,9 @@
 #include "gpg.h"
 #include "util.h"
 #include "packet.h"
-#include "cipher.h"
 #include "options.h"
 #include "i18n.h"
+#include "status.h"
 
 
 static int mdc_decode_filter ( void *opaque, int control, IOBUF a,
@@ -74,7 +74,7 @@ release_dfx_context (decode_filter_ctx_t dfx)
  * Decrypt the data, specified by ED with the key DEK.
  */
 int
-decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
+decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
 {
   decode_filter_ctx_t dfx;
   byte *p;
@@ -82,7 +82,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
   byte temp[32];
   unsigned blocksize;
   unsigned nprefix;
-  
+
   dfx = xtrycalloc (1, sizeof *dfx);
   if (!dfx)
     return gpg_error_from_syserror ();
@@ -91,12 +91,37 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
   if ( opt.verbose && !dek->algo_info_printed )
     {
       if (!openpgp_cipher_test_algo (dek->algo))
-        log_info (_("%s encrypted data\n"), 
+        log_info (_("%s encrypted data\n"),
                   openpgp_cipher_algo_name (dek->algo));
       else
         log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
       dek->algo_info_printed = 1;
     }
+
+  {
+    char buf[20];
+
+    snprintf (buf, sizeof buf, "%d %d", ed->mdc_method, dek->algo);
+    write_status_text (STATUS_DECRYPTION_INFO, buf);
+  }
+
+  if (opt.show_session_key)
+    {
+      char numbuf[25];
+      char *hexbuf;
+
+      snprintf (numbuf, sizeof numbuf, "%d:", dek->algo);
+      hexbuf = bin2hex (dek->key, dek->keylen, NULL);
+      if (!hexbuf)
+        {
+          rc = gpg_error_from_syserror ();
+          goto leave;
+        }
+      log_info ("session key: '%s%s'\n", numbuf, hexbuf);
+      write_status_strings (STATUS_SESSION_KEY, numbuf, hexbuf, NULL);
+      xfree (hexbuf);
+    }
+
   rc = openpgp_cipher_test_algo (dek->algo);
   if (rc)
     goto leave;
@@ -105,14 +130,19 @@ decrypt_data( 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 ) 
+  if ( ed->mdc_method )
     {
       if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
         BUG ();
       if ( DBG_HASHING )
-        gcry_md_start_debug (dfx->mdc_hash, "checkmdc");
+        gcry_md_debug (dfx->mdc_hash, "checkmdc");
     }
 
   rc = openpgp_cipher_open (&dfx->cipher_hd, dek->algo,
@@ -138,11 +168,11 @@ decrypt_data( 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;
     }
 
-  if (!ed->buf) 
+  if (!ed->buf)
     {
       log_error(_("problem handling encrypted packet\n"));
       goto leave;
@@ -152,7 +182,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
 
   if ( ed->len )
     {
-      for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) 
+      for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- )
         {
           if ( (c=iobuf_get(ed->buf)) == -1 )
             break;
@@ -160,7 +190,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
             temp[i] = c;
         }
     }
-  else 
+  else
     {
       for (i=0; i < (nprefix+2); i++ )
         if ( (c=iobuf_get(ed->buf)) == -1 )
@@ -168,7 +198,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
         else
           temp[i] = c;
     }
-  
+
   gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
   gcry_cipher_sync (dfx->cipher_hd);
   p = temp;
@@ -179,7 +209,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
       rc = gpg_error (GPG_ERR_BAD_KEY);
       goto leave;
     }
-  
+
   if ( dfx->mdc_hash )
     gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
 
@@ -191,12 +221,43 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
   else
     iobuf_push_filter ( ed->buf, decode_filter, dfx );
 
-  proc_packets ( procctx, ed->buf );
+  if (opt.unwrap_encryption)
+    {
+      char *filename;
+      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);
+        }
+    }
+  else
+    proc_packets (ctrl, procctx, ed->buf );
+
   ed->buf = NULL;
   if (dfx->eof_seen > 1 )
     rc = gpg_error (GPG_ERR_INV_PACKET);
   else if ( ed->mdc_method )
-    { 
+    {
       /* We used to let parse-packet.c handle the MDC packet but this
          turned out to be a problem with compressed packets: With old
          style packets there is no length information available and
@@ -218,20 +279,16 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
       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); */
     }
-  
-  
+
+
  leave:
   release_dfx_context (dfx);
   return rc;
@@ -255,7 +312,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
      looking for the EOF on fixed data works only if the encrypted
      packet is not followed by other data.  This used to be a long
      standing bug which was fixed on 2009-10-02.  */
-  
+
   if ( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen )
     {
       *ret_len = 0;
@@ -265,7 +322,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
     {
       assert (a);
       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)
         {
@@ -286,7 +343,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
               buf[n] = c;
             }
         }
-      if (n == 44) 
+      if (n == 44)
         {
           /* We have enough stuff - flush the deferred stuff.  */
           if ( !dfx->defer_filled )  /* First time. */
@@ -301,7 +358,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
           /* Fill up the buffer. */
           if (dfx->partial)
             {
-              for (; n < size; n++ ) 
+              for (; n < size; n++ )
                 {
                   if ( (c = iobuf_get(a)) == -1 )
                     {
@@ -313,7 +370,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
             }
           else
             {
-              for (; n < size && dfx->length; n++, dfx->length--) 
+              for (; n < size && dfx->length; n++, dfx->length--)
                 {
                   c = iobuf_get(a);
                   if (c == -1)
@@ -326,7 +383,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
               if (!dfx->length)
                 dfx->eof_seen = 1; /* Normal EOF.  */
             }
-          
+
           /* Move the trailing 22 bytes back to the defer buffer.  We
              have at least 44 bytes thus a memmove is not needed.  */
           n -= 22;
@@ -362,13 +419,13 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
        }
       *ret_len = n;
     }
-  else if ( control == IOBUFCTRL_FREE ) 
+  else if ( control == IOBUFCTRL_FREE )
     {
       release_dfx_context (dfx);
     }
-  else if ( control == IOBUFCTRL_DESC ) 
+  else if ( control == IOBUFCTRL_DESC )
     {
-      *(char**)buf = "mdc_decode_filter";
+      mem2str (buf, "mdc_decode_filter", *ret_len);
     }
   return rc;
 }
@@ -388,13 +445,13 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
       *ret_len = 0;
       rc = -1;
     }
-  else if ( control == IOBUFCTRL_UNDERFLOW ) 
+  else if ( control == IOBUFCTRL_UNDERFLOW )
     {
       assert(a);
-      
+
       if (fc->partial)
         {
-          for (n=0; n < size; n++ ) 
+          for (n=0; n < size; n++ )
             {
               c = iobuf_get(a);
               if (c == -1)
@@ -407,7 +464,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
         }
       else
         {
-          for (n=0; n < size && fc->length; n++, fc->length--) 
+          for (n=0; n < size && fc->length; n++, fc->length--)
             {
               c = iobuf_get(a);
               if (c == -1)
@@ -433,14 +490,13 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
         }
       *ret_len = n;
     }
-  else if ( control == IOBUFCTRL_FREE ) 
+  else if ( control == IOBUFCTRL_FREE )
     {
       release_dfx_context (fc);
     }
   else if ( control == IOBUFCTRL_DESC )
     {
-      *(char**)buf = "decode_filter";
+      mem2str (buf, "decode_filter", *ret_len);
     }
   return rc;
 }
-