[git] GnuPG - branch, gniibe/decryption-key, created. gnupg-2.2.7-138-gfed3e10

by NIIBE Yutaka cvs at cvs.gnupg.org
Fri Jun 8 09:28:52 CEST 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, gniibe/decryption-key has been created
        at  fed3e10121a76cf270e72ff0bcf31a4ed40068e8 (commit)

- Log -----------------------------------------------------------------
commit fed3e10121a76cf270e72ff0bcf31a4ed40068e8
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jun 8 16:21:05 2018 +0900

    g10: Change the order of handling private key for encryption.
    
    * g10/packet.h (struct pubkey_enc_list): New.
    * g10/gpgv.c (get_session_key): Supply struct pubkey_enc_list.
    * g10/test-stubs.c (get_session_key): Likewise.
    * g10/mainproc.c (struct kidlist_item): Remove.
    (release_list): Use struct pubkey_enc_list.
    (proc_pubkey_enc, print_pkenc_list): Likewise.
    (proc_encrypted): Don't loop for pkenc_list, but just supply the list
    to get_session_key.
    * g10/pubkey-enc.c (get_session_key): Loop for secret key available,
    and check pkenc_list for each secret key.
    
    --
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/g10/gpgv.c b/g10/gpgv.c
index c43067d..16d9044 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -490,7 +490,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
  * No encryption here but mainproc links to these functions.
  */
 gpg_error_t
-get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek)
+get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek)
 {
   (void)ctrl;
   (void)k;
diff --git a/g10/mainproc.c b/g10/mainproc.c
index d5fee73..835ab6b 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -46,16 +46,6 @@
 #define MAX_NESTING_DEPTH 32
 
 
-/* An object to build a list of keyid related info.  */
-struct kidlist_item
-{
-  struct kidlist_item *next;
-  u32 kid[2];
-  int pubkey_algo;
-  gcry_mpi_t data[2];
-};
-
-
 /*
  * Object to hold the processing context.
  */
@@ -95,7 +85,7 @@ struct mainproc_context
   iobuf_t iobuf;    /* Used to get the filename etc. */
   int trustletter;  /* Temporary usage in list_node. */
   ulong symkeys;    /* Number of symmetrically encrypted session keys.  */
-  struct kidlist_item *pkenc_list; /* List of encryption packets. */
+  struct pubkey_enc_list *pkenc_list; /* List of encryption packets. */
   struct {
     unsigned int sig_seen:1;      /* Set to true if a signature packet
                                      has been seen. */
@@ -135,7 +125,7 @@ release_list( CTX c )
   release_kbnode (c->list);
   while (c->pkenc_list)
     {
-      struct kidlist_item *tmp = c->pkenc_list->next;
+      struct pubkey_enc_list *tmp = c->pkenc_list->next;
 
       mpi_release (c->pkenc_list->data[0]);
       mpi_release (c->pkenc_list->data[1]);
@@ -464,7 +454,7 @@ static void
 proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
 {
   PKT_pubkey_enc *enc;
-  struct kidlist_item *x = xmalloc (sizeof *x);
+  struct pubkey_enc_list *x = xmalloc (sizeof *x);
 
   /* Check whether the secret key is available and store in this case.  */
   c->last_was_session_key = 1;
@@ -485,8 +475,8 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
 
   if (!opt.list_only && !opt.override_session_key)
     {
-      x->kid[0] = enc->keyid[0];
-      x->kid[1] = enc->keyid[1];
+      x->keyid[0] = enc->keyid[0];
+      x->keyid[1] = enc->keyid[1];
       x->pubkey_algo = enc->pubkey_algo;
       x->data[0] = x->data[1] = NULL;
       if (enc->data[0])
@@ -507,7 +497,7 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
  * not decrypt.
  */
 static void
-print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
+print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list)
 {
   for (; list; list = list->next)
     {
@@ -520,19 +510,19 @@ print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
       if (!algstr)
         algstr = "[?]";
       pk->pubkey_algo = list->pubkey_algo;
-      if (!get_pubkey (ctrl, pk, list->kid))
+      if (!get_pubkey (ctrl, pk, list->keyid))
         {
           char *p;
           log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"),
                     nbits_from_pk (pk), algstr, keystr_from_pk(pk),
                     strtimestamp (pk->timestamp));
-          p = get_user_id_native (ctrl, list->kid);
+          p = get_user_id_native (ctrl, list->keyid);
           log_printf (_("      \"%s\"\n"), p);
           xfree (p);
         }
       else
         log_info (_("encrypted with %s key, ID %s\n"),
-                  algstr, keystr(list->kid));
+                  algstr, keystr(list->keyid));
 
       free_public_key (pk);
     }
@@ -542,7 +532,6 @@ print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
 static void
 proc_encrypted (CTX c, PACKET *pkt)
 {
-  struct kidlist_item *item;
   int result = 0;
 
   if (!opt.quiet)
@@ -555,7 +544,7 @@ proc_encrypted (CTX c, PACKET *pkt)
     }
 
   /* Figure out the session key by looking at all pkenc packets. */
-  if (opt.list_only)
+  if (opt.list_only || c->dek)
     ;
   else if (opt.override_session_key)
     {
@@ -572,53 +561,16 @@ proc_encrypted (CTX c, PACKET *pkt)
     }
   else
     {
-      for (item = c->pkenc_list; item; item = item->next)
-        if (item->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
-            || item->pubkey_algo == PUBKEY_ALGO_ECDH
-            || item->pubkey_algo == PUBKEY_ALGO_RSA
-            || item->pubkey_algo == PUBKEY_ALGO_RSA_E
-            || item->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
-          {
-            if  (((!item->kid[0] && !item->kid[1])
-                  || opt.try_all_secrets
-                  || have_secret_key_with_kid (item->kid)))
-              {
-                PKT_pubkey_enc enc;
-
-                enc.keyid[0] = item->kid[0];
-                enc.keyid[1] = item->kid[1];
-                enc.pubkey_algo = item->pubkey_algo;
-                enc.data[0] = item->data[0];
-                enc.data[1] = item->data[1];
-
-                c->dek = xmalloc_secure_clear (sizeof *c->dek);
-                if (!(result = get_session_key (c->ctrl, &enc, c->dek)))
-                  break;
-
-                log_info (_("public key decryption failed: %s\n"),
-                          gpg_strerror (result));
-                write_status_error ("pkdecrypt_failed", result);
-
-                /* Error: Delete the DEK. */
-                xfree (c->dek);
-                c->dek = NULL;
-              }
-            else
-              {
-                if (is_status_enabled ())
-                  {
-                    char buf[20];
-                    snprintf (buf, sizeof buf, "%08lX%08lX",
-                              (ulong)item->kid[0], (ulong)item->kid[1]);
-                    write_status_text (STATUS_NO_SECKEY, buf);
-                  }
-              }
-          }
-      else
+      c->dek = xmalloc_secure_clear (sizeof *c->dek);
+      if ((result = get_session_key (c->ctrl, c->pkenc_list, c->dek)))
         {
           log_info (_("public key decryption failed: %s\n"),
-                    gpg_strerror (GPG_ERR_PUBKEY_ALGO));
-          write_status_error ("pkdecrypt_failed", GPG_ERR_PUBKEY_ALGO);
+                    gpg_strerror (result));
+          write_status_error ("pkdecrypt_failed", result);
+
+          /* Error: Delete the DEK. */
+          xfree (c->dek);
+          c->dek = NULL;
         }
     }
 
@@ -698,7 +650,7 @@ proc_encrypted (CTX c, PACKET *pkt)
       && gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo,
                                     GCRY_CIPHER_MODE_CFB))
     {
-      struct kidlist_item *i;
+      struct pubkey_enc_list *i;
       int compliant = 1;
       PKT_public_key *pk = xmalloc (sizeof *pk);
 
@@ -711,7 +663,7 @@ proc_encrypted (CTX c, PACKET *pkt)
         {
           memset (pk, 0, sizeof *pk);
           pk->pubkey_algo = i->pubkey_algo;
-          if (get_pubkey (c->ctrl, pk, i->kid) != 0
+          if (get_pubkey (c->ctrl, pk, i->keyid) != 0
               || ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
                                           nbits_from_pk (pk), NULL))
             compliant = 0;
diff --git a/g10/packet.h b/g10/packet.h
index e8397ea..a4157c5 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -131,6 +131,16 @@ typedef struct {
 } PKT_pubkey_enc;
 
 
+/* An object to build a list of public-key encrypted session key.  */
+struct pubkey_enc_list
+{
+  struct pubkey_enc_list *next;
+  u32 keyid[2];
+  int pubkey_algo;
+  gcry_mpi_t data[PUBKEY_MAX_NENC];
+};
+
+
 /* A one-pass signature packet as defined in RFC 4880, Section
    5.4.  All fields are serialized.  */
 typedef struct {
@@ -887,7 +897,7 @@ gpg_error_t check_signature2 (ctrl_t ctrl,
 
 
 /*-- pubkey-enc.c --*/
-gpg_error_t get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek);
+gpg_error_t get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek);
 gpg_error_t get_override_session_key (DEK *dek, const char *string);
 
 /*-- compress.c --*/
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 0185097..8540e03 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -38,7 +38,7 @@
 #include "../common/compliance.h"
 
 
-static gpg_error_t get_it (ctrl_t ctrl, PKT_pubkey_enc *k,
+static gpg_error_t get_it (ctrl_t ctrl, struct pubkey_enc_list *k,
                            DEK *dek, PKT_public_key *sk, u32 *keyid);
 
 
@@ -72,92 +72,92 @@ is_algo_in_prefs (kbnode_t keyblock, preftype_t type, int algo)
  * which should have been allocated in secure memory by the caller.
  */
 gpg_error_t
-get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
+get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
 {
   PKT_public_key *sk = NULL;
   int rc;
+  void *enum_context = NULL;
+  u32 keyid[2];
+  int search_for_secret_keys = 1;
 
   if (DBG_CLOCK)
     log_clock ("get_session_key enter");
 
-  rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
-  if (rc)
-    goto leave;
-
-  if ((k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets)
+  while (search_for_secret_keys)
     {
+      struct pubkey_enc_list *k;
+
+      free_public_key (sk);
       sk = xmalloc_clear (sizeof *sk);
-      sk->pubkey_algo = k->pubkey_algo; /* We want a pubkey with this algo.  */
-      if (!(rc = get_seckey (ctrl, sk, k->keyid)))
+      rc = enum_secret_keys (ctrl, &enum_context, sk);
+      if (rc)
         {
-          /* Check compliance.  */
-          if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
-                                     sk->pubkey_algo,
-                                     sk->pkey, nbits_from_pk (sk), NULL))
-            {
-              log_info (_("key %s is not suitable for decryption"
-                          " in %s mode\n"),
-                        keystr_from_pk (sk),
-                        gnupg_compliance_option_string (opt.compliance));
-              rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
-            }
-          else
-            rc = get_it (ctrl, k, dek, sk, k->keyid);
+          rc = GPG_ERR_NO_SECKEY;
+          break;
         }
-    }
-  else if (opt.skip_hidden_recipients)
-    rc = gpg_error (GPG_ERR_NO_SECKEY);
-  else  /* Anonymous receiver: Try all available secret keys.  */
-    {
-      void *enum_context = NULL;
-      u32 keyid[2];
 
-      for (;;)
+      if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+        continue;
+
+      /* Check compliance.  */
+      if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
+                                 sk->pubkey_algo,
+                                 sk->pkey, nbits_from_pk (sk), NULL))
         {
-          free_public_key (sk);
-          sk = xmalloc_clear (sizeof *sk);
-          rc = enum_secret_keys (ctrl, &enum_context, sk);
-          if (rc)
-            {
-              rc = GPG_ERR_NO_SECKEY;
-              break;
-            }
-          if (sk->pubkey_algo != k->pubkey_algo)
+          log_info (_("key %s is not suitable for decryption"
+                      " in %s mode\n"),
+                    keystr_from_pk (sk),
+                    gnupg_compliance_option_string (opt.compliance));
+          continue;
+        }
+
+      for (k = list; k; k = k->next)
+        {
+          if (!(k->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
+                || k->pubkey_algo == PUBKEY_ALGO_ECDH
+                || k->pubkey_algo == PUBKEY_ALGO_RSA
+                || k->pubkey_algo == PUBKEY_ALGO_RSA_E
+                || k->pubkey_algo == PUBKEY_ALGO_ELGAMAL))
             continue;
-          if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+
+          if (openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC))
+            continue;
+
+          if (sk->pubkey_algo != k->pubkey_algo)
             continue;
+
           keyid_from_pk (sk, keyid);
-          if (!opt.quiet)
-            log_info (_("anonymous recipient; trying secret key %s ...\n"),
-                      keystr (keyid));
-
-          /* Check compliance.  */
-          if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
-                                     sk->pubkey_algo,
-                                     sk->pkey, nbits_from_pk (sk), NULL))
+
+          if (!k->keyid[0] && !k->keyid[1])
             {
-              log_info (_("key %s is not suitable for decryption"
-                          " in %s mode\n"),
-                          keystr_from_pk (sk),
-                          gnupg_compliance_option_string (opt.compliance));
-              continue;
+              if (!opt.quiet)
+                log_info (_("anonymous recipient; trying secret key %s ...\n"),
+                          keystr (keyid));
             }
+          else if (opt.try_all_secrets
+                   || (k->keyid[0] == keyid[0] && k->keyid[1] == keyid[1]))
+            ;
+          else
+            continue;
 
           rc = get_it (ctrl, k, dek, sk, keyid);
           if (!rc)
             {
-              if (!opt.quiet)
+              if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
                 log_info (_("okay, we are the anonymous recipient.\n"));
+              search_for_secret_keys = 0;
               break;
             }
           else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
-            break; /* Don't try any more secret keys.  */
+            {
+              search_for_secret_keys = 0;
+              break; /* Don't try any more secret keys.  */
+            }
         }
-      enum_secret_keys (ctrl, &enum_context, NULL);  /* free context */
     }
-
- leave:
+  enum_secret_keys (ctrl, &enum_context, NULL);  /* free context */
   free_public_key (sk);
+
   if (DBG_CLOCK)
     log_clock ("get_session_key leave");
   return rc;
@@ -166,7 +166,7 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
 
 static gpg_error_t
 get_it (ctrl_t ctrl,
-        PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
+        struct pubkey_enc_list *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
 {
   gpg_error_t err;
   byte *frame = NULL;
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index e5fd3ae..088aba8 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -253,7 +253,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
  * No encryption here but mainproc links to these functions.
  */
 gpg_error_t
-get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek)
+get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek)
 {
   (void)ctrl;
   (void)k;

commit 2d6f17c776cd59bc747959711bcc43d61816f3d6
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jun 7 10:28:00 2018 +0900

    g10: Defer selection of decryption key at proc_encrypted.
    
    * g10/mainproc.c (struct kidlist_item): Remove REASON.  Add DATA.
    (release_list): Release DATA.
    (proc_pubkey_enc): Don't get DEK here.
    (print_pkenc_list): Don't output failure reason here.
    (proc_encrypted): Get DEK here, and output failure reason.
    
    --
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/g10/mainproc.c b/g10/mainproc.c
index 5689d73..d5fee73 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -52,7 +52,7 @@ struct kidlist_item
   struct kidlist_item *next;
   u32 kid[2];
   int pubkey_algo;
-  int reason;
+  gcry_mpi_t data[2];
 };
 
 
@@ -136,6 +136,9 @@ release_list( CTX c )
   while (c->pkenc_list)
     {
       struct kidlist_item *tmp = c->pkenc_list->next;
+
+      mpi_release (c->pkenc_list->data[0]);
+      mpi_release (c->pkenc_list->data[1]);
       xfree (c->pkenc_list);
       c->pkenc_list = tmp;
     }
@@ -461,7 +464,7 @@ static void
 proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
 {
   PKT_pubkey_enc *enc;
-  int result = 0;
+  struct kidlist_item *x = xmalloc (sizeof *x);
 
   /* Check whether the secret key is available and store in this case.  */
   c->last_was_session_key = 1;
@@ -472,76 +475,27 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
   if (opt.verbose)
     log_info (_("public key is %s\n"), keystr (enc->keyid));
 
-  if (is_status_enabled())
+  if (is_status_enabled ())
     {
       char buf[50];
       snprintf (buf, sizeof buf, "%08lX%08lX %d 0",
-		(ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
+                (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
       write_status_text (STATUS_ENC_TO, buf);
     }
 
-  if (!opt.list_only && opt.override_session_key)
-    {
-      /* It does not make much sense to store the session key in
-       * secure memory because it has already been passed on the
-       * command line and the GCHQ knows about it.  */
-      c->dek = xmalloc_clear (sizeof *c->dek);
-      result = get_override_session_key (c->dek, opt.override_session_key);
-      if (result)
-        {
-          xfree (c->dek);
-          c->dek = NULL;
-	}
-    }
-  else if (enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
-           || enc->pubkey_algo == PUBKEY_ALGO_ECDH
-           || enc->pubkey_algo == PUBKEY_ALGO_RSA
-           || enc->pubkey_algo == PUBKEY_ALGO_RSA_E
-           || enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
-    {
-      /* Note that we also allow type 20 Elgamal keys for decryption.
-         There are still a couple of those keys in active use as a
-         subkey.  */
-
-      /* FIXME: Store this all in a list and process it later so that
-         we can prioritize what key to use.  This gives a better user
-         experience if wildcard keyids are used.  */
-      if  (!c->dek && ((!enc->keyid[0] && !enc->keyid[1])
-                       || opt.try_all_secrets
-                       || have_secret_key_with_kid (enc->keyid)))
-        {
-          if(opt.list_only)
-            result = GPG_ERR_MISSING_ACTION; /* fixme: Use better error code. */
-          else
-            {
-              c->dek = xmalloc_secure_clear (sizeof *c->dek);
-              if ((result = get_session_key (ctrl, enc, c->dek)))
-                {
-                  /* Error: Delete the DEK. */
-                  xfree (c->dek);
-                  c->dek = NULL;
-		}
-	    }
-	}
-      else
-        result = GPG_ERR_NO_SECKEY;
-    }
-  else
-    result = GPG_ERR_PUBKEY_ALGO;
-
-  if (1)
+  if (!opt.list_only && !opt.override_session_key)
     {
-      /* Store it for later display.  */
-      struct kidlist_item *x = xmalloc (sizeof *x);
       x->kid[0] = enc->keyid[0];
       x->kid[1] = enc->keyid[1];
       x->pubkey_algo = enc->pubkey_algo;
-      x->reason = result;
+      x->data[0] = x->data[1] = NULL;
+      if (enc->data[0])
+        {
+          x->data[0] = mpi_copy (enc->data[0]);
+          x->data[1] = mpi_copy (enc->data[1]);
+        }
       x->next = c->pkenc_list;
       c->pkenc_list = x;
-
-      if (!result && opt.verbose > 1)
-        log_info (_("public key encrypted data: good DEK\n"));
     }
 
   free_packet(pkt, NULL);
@@ -553,18 +507,13 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
  * not decrypt.
  */
 static void
-print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list, int failed)
+print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
 {
   for (; list; list = list->next)
     {
       PKT_public_key *pk;
       const char *algstr;
 
-      if (failed && !list->reason)
-        continue;
-      if (!failed && list->reason)
-        continue;
-
       algstr = openpgp_pk_algo_name (list->pubkey_algo);
       pk = xmalloc_clear (sizeof *pk);
 
@@ -586,27 +535,6 @@ print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list, int failed)
                   algstr, keystr(list->kid));
 
       free_public_key (pk);
-
-      if (gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY)
-        {
-          if (is_status_enabled())
-            {
-              char buf[20];
-              snprintf (buf, sizeof buf, "%08lX%08lX",
-                        (ulong)list->kid[0], (ulong)list->kid[1]);
-              write_status_text (STATUS_NO_SECKEY, buf);
-	    }
-	}
-      else if (gpg_err_code (list->reason) == GPG_ERR_MISSING_ACTION)
-        {
-          /* Not tested for secret key due to --list-only mode.  */
-        }
-      else if (list->reason)
-        {
-          log_info (_("public key decryption failed: %s\n"),
-                    gpg_strerror (list->reason));
-          write_status_error ("pkdecrypt_failed", list->reason);
-        }
     }
 }
 
@@ -614,6 +542,7 @@ print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list, int failed)
 static void
 proc_encrypted (CTX c, PACKET *pkt)
 {
+  struct kidlist_item *item;
   int result = 0;
 
   if (!opt.quiet)
@@ -622,11 +551,79 @@ proc_encrypted (CTX c, PACKET *pkt)
         log_info (_("encrypted with %lu passphrases\n"), c->symkeys);
       else if (c->symkeys == 1)
         log_info (_("encrypted with 1 passphrase\n"));
-      print_pkenc_list (c->ctrl, c->pkenc_list, 1 );
-      print_pkenc_list (c->ctrl, c->pkenc_list, 0 );
+      print_pkenc_list (c->ctrl, c->pkenc_list);
+    }
+
+  /* Figure out the session key by looking at all pkenc packets. */
+  if (opt.list_only)
+    ;
+  else if (opt.override_session_key)
+    {
+      c->dek = xmalloc_clear (sizeof *c->dek);
+      result = get_override_session_key (c->dek, opt.override_session_key);
+      if (result)
+        {
+          xfree (c->dek);
+          c->dek = NULL;
+          log_info (_("public key decryption failed: %s\n"),
+                    gpg_strerror (result));
+          write_status_error ("pkdecrypt_failed", result);
+        }
+    }
+  else
+    {
+      for (item = c->pkenc_list; item; item = item->next)
+        if (item->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
+            || item->pubkey_algo == PUBKEY_ALGO_ECDH
+            || item->pubkey_algo == PUBKEY_ALGO_RSA
+            || item->pubkey_algo == PUBKEY_ALGO_RSA_E
+            || item->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
+          {
+            if  (((!item->kid[0] && !item->kid[1])
+                  || opt.try_all_secrets
+                  || have_secret_key_with_kid (item->kid)))
+              {
+                PKT_pubkey_enc enc;
+
+                enc.keyid[0] = item->kid[0];
+                enc.keyid[1] = item->kid[1];
+                enc.pubkey_algo = item->pubkey_algo;
+                enc.data[0] = item->data[0];
+                enc.data[1] = item->data[1];
+
+                c->dek = xmalloc_secure_clear (sizeof *c->dek);
+                if (!(result = get_session_key (c->ctrl, &enc, c->dek)))
+                  break;
+
+                log_info (_("public key decryption failed: %s\n"),
+                          gpg_strerror (result));
+                write_status_error ("pkdecrypt_failed", result);
+
+                /* Error: Delete the DEK. */
+                xfree (c->dek);
+                c->dek = NULL;
+              }
+            else
+              {
+                if (is_status_enabled ())
+                  {
+                    char buf[20];
+                    snprintf (buf, sizeof buf, "%08lX%08lX",
+                              (ulong)item->kid[0], (ulong)item->kid[1]);
+                    write_status_text (STATUS_NO_SECKEY, buf);
+                  }
+              }
+          }
+      else
+        {
+          log_info (_("public key decryption failed: %s\n"),
+                    gpg_strerror (GPG_ERR_PUBKEY_ALGO));
+          write_status_error ("pkdecrypt_failed", GPG_ERR_PUBKEY_ALGO);
+        }
     }
 
-  /* FIXME: Figure out the session key by looking at all pkenc packets. */
+  if (c->dek && opt.verbose > 1)
+    log_info (_("public key encrypted data: good DEK\n"));
 
   write_status (STATUS_BEGIN_DECRYPTION);
 

-----------------------------------------------------------------------


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list