[git] GnuPG - branch, master, updated. gnupg-2.1.21-100-ga149afe

by Werner Koch cvs at cvs.gnupg.org
Mon Jul 17 15:59:52 CEST 2017


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, master has been updated
       via  a149afe338d61d86985c533cde5e7dbcd31e8698 (commit)
       via  bbbd0db34b4e387f8dc089fb7d69fdcf2ed91a01 (commit)
       via  849467870ee1c10e0a7b1e89cfc9e8214e4963fe (commit)
      from  58eafd11ed5501c0b72fcb553eb3e097ad29b3c6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a149afe338d61d86985c533cde5e7dbcd31e8698
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Jul 17 15:52:26 2017 +0200

    gpg,sm: Check compliance of the RNG.
    
    * common/compliance.c (gnupg_rng_is_compliant): New.
    * g10/call-agent.c (start_agent) [W32]: Check rng compliance.
    * sm/call-agent.c (start_agent) [W32]: Ditto.
    * g10/encrypt.c (encrypt_simple, encrypt_crypt): Check that the RNG is
    compliant.
    * sm/encrypt.c (gpgsm_encrypt): Ditto.
    * g10/sign.c (do_sign): Ditto.
    * sm/sign.c (gpgsm_sign): Ditto.
    --
    
    Under Windows we need to check that the Jitter RNG is active in de-vs
    mode.  Under Linux this is not necessary because /dev/random can be
    scrutinized and is believed to provide enough entropy.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/common/compliance.c b/common/compliance.c
index 8b91677..268ea4d 100644
--- a/common/compliance.c
+++ b/common/compliance.c
@@ -466,6 +466,46 @@ gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer,
 }
 
 
+/* Return True if the random number generator is compliant in
+ * COMPLIANCE mode.  */
+int
+gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance)
+{
+  static int result = -1;
+
+  if (result != -1)
+    ; /* Use cached result.  */
+  else if (compliance == CO_DE_VS)
+    {
+      /* In DE_VS mode under Windows we require that the JENT RNG
+       * is active.  */
+#ifdef HAVE_W32_SYSTEM
+# if GCRYPT_VERSION_NUMBER >= 0x010800
+      char *buf;
+      char *fields[5];
+
+      buf = gcry_get_config (0, "rng-type");
+      if (buf
+          && split_fields_colon (buf, fields, DIM (fields)) >= 5
+          && atoi (fields[4]) > 0)
+        result = 1;
+      else
+        result = 0;
+      gcry_free (buf);
+# else
+      result = 0;  /* No JENT - can't be compliant.  */
+# endif
+#else /*!HAVE_W32_SYSTEM*/
+      result = 1;  /* Not Windows - RNG is good.  */
+#endif /*!HAVE_W32_SYSTEM*/
+    }
+  else
+    result = 1;
+
+  return result;
+}
+
+
 const char *
 gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
 {
diff --git a/common/compliance.h b/common/compliance.h
index d55bbf3..2076e79 100644
--- a/common/compliance.h
+++ b/common/compliance.h
@@ -66,6 +66,8 @@ int gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance,
 int gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance,
                              int producer,
                              digest_algo_t digest);
+int gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance);
+
 const char *gnupg_status_compliance_flag (enum gnupg_compliance_mode
                                           compliance);
 
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 7b76933..3ad13e8 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -281,6 +281,24 @@ start_agent (ctrl_t ctrl, int flag_for_card)
                   write_status_error ("set_pinentry_mode", rc);
                 }
             }
+
+          /* In DE_VS mode under Windows we require that the JENT RNG
+           * is active.  */
+#ifdef HAVE_W32_SYSTEM
+          if (!rc && opt.compliance == CO_DE_VS)
+            {
+              if (assuan_transact (agent_ctx, "GETINFO jent_active",
+                                   NULL, NULL, NULL, NULL, NULL, NULL))
+                {
+                  rc = gpg_error (GPG_ERR_FORBIDDEN);
+                  log_error (_("%s is not compliant with %s mode\n"),
+                             GPG_AGENT_NAME,
+                             gnupg_compliance_option_string (opt.compliance));
+                  write_status_error ("random-compliance", rc);
+                }
+            }
+#endif /*HAVE_W32_SYSTEM*/
+
         }
     }
 
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 4b21a61..c63ec88 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -185,6 +185,16 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
   progress_filter_context_t *pfx;
   int do_compress = !!default_compress_algo();
 
+  if (!gnupg_rng_is_compliant (opt.compliance))
+    {
+      rc = gpg_error (GPG_ERR_FORBIDDEN);
+      log_error (_("%s is not compliant with %s mode\n"),
+                 "RNG",
+                 gnupg_compliance_option_string (opt.compliance));
+      write_status_error ("random-compliance", rc);
+      return rc;
+    }
+
   pfx = new_progress_context ();
   memset( &cfx, 0, sizeof cfx);
   memset( &zfx, 0, sizeof zfx);
@@ -626,6 +636,16 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
       goto leave;
     }
 
+  if (!gnupg_rng_is_compliant (opt.compliance))
+    {
+      rc = gpg_error (GPG_ERR_FORBIDDEN);
+      log_error (_("%s is not compliant with %s mode\n"),
+                 "RNG",
+                 gnupg_compliance_option_string (opt.compliance));
+      write_status_error ("random-compliance", rc);
+      goto leave;
+    }
+
   compliant = gnupg_cipher_is_compliant (CO_DE_VS, cfx.dek->algo,
                                          GCRY_CIPHER_MODE_CFB);
 
diff --git a/g10/sign.c b/g10/sign.c
index 0ba1151..f7dd974 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -299,6 +299,16 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
       goto leave;
     }
 
+  if (!gnupg_rng_is_compliant (opt.compliance))
+    {
+      err = gpg_error (GPG_ERR_FORBIDDEN);
+      log_error (_("%s is not compliant with %s mode\n"),
+                 "RNG",
+                 gnupg_compliance_option_string (opt.compliance));
+      write_status_error ("random-compliance", err);
+      goto leave;
+    }
+
   print_digest_algo_note (mdalgo);
   dp = gcry_md_read  (md, mdalgo);
   sig->digest_algo = mdalgo;
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 0e47c14..ba8fb12 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -171,6 +171,25 @@ start_agent (ctrl_t ctrl)
                            str_pinentry_mode (opt.pinentry_mode),
                            gpg_strerror (rc));
             }
+
+          /* In DE_VS mode under Windows we require that the JENT RNG
+           * is active.  */
+#ifdef HAVE_W32_SYSTEM
+          if (!rc && opt.compliance == CO_DE_VS)
+            {
+              if (assuan_transact (agent_ctx, "GETINFO jent_active",
+                                   NULL, NULL, NULL, NULL, NULL, NULL))
+                {
+                  rc = gpg_error (GPG_ERR_FORBIDDEN);
+                  log_error (_("%s is not compliant with %s mode\n"),
+                             GPG_AGENT_NAME,
+                             gnupg_compliance_option_string (opt.compliance));
+                  gpgsm_status_with_error (ctrl, STATUS_ERROR,
+                                           "random-compliance", rc);
+                }
+            }
+#endif /*HAVE_W32_SYSTEM*/
+
         }
     }
 
diff --git a/sm/encrypt.c b/sm/encrypt.c
index 9e3216a..7351932 100644
--- a/sm/encrypt.c
+++ b/sm/encrypt.c
@@ -420,6 +420,17 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
       goto leave;
     }
 
+  if (!gnupg_rng_is_compliant (opt.compliance))
+    {
+      rc = gpg_error (GPG_ERR_FORBIDDEN);
+      log_error (_("%s is not compliant with %s mode\n"),
+                 "RNG",
+                 gnupg_compliance_option_string (opt.compliance));
+      gpgsm_status_with_error (ctrl, STATUS_ERROR,
+                               "random-compliance", rc);
+      goto leave;
+    }
+
   /* Create a session key */
   dek = xtrycalloc_secure (1, sizeof *dek);
   if (!dek)
diff --git a/sm/sign.c b/sm/sign.c
index 7ba2319..1411501 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -339,6 +339,17 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
       goto leave;
     }
 
+  if (!gnupg_rng_is_compliant (opt.compliance))
+    {
+      rc = gpg_error (GPG_ERR_FORBIDDEN);
+      log_error (_("%s is not compliant with %s mode\n"),
+                 "RNG",
+                 gnupg_compliance_option_string (opt.compliance));
+      gpgsm_status_with_error (ctrl, STATUS_ERROR,
+                               "random-compliance", rc);
+      goto leave;
+    }
+
   ctrl->pem_name = "SIGNED MESSAGE";
   rc = gnupg_ksba_create_writer
     (&b64writer, ((ctrl->create_pem? GNUPG_KSBA_IO_PEM : 0)

commit bbbd0db34b4e387f8dc089fb7d69fdcf2ed91a01
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Jul 17 14:08:00 2017 +0200

    agent: New GETINFO sub-command jent_active.
    
    * agent/command.c (cmd_getinfo): Implement it for gcrypt >= 1.8.
    --
    
    For the de-vs compliance of gpg we need to check whether the Jitter
    RNG is used on Windows.  This change allows to test this for
    gpg-agent.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/agent/command.c b/agent/command.c
index d370821..e387db5 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -2852,6 +2852,7 @@ static const char hlp_getinfo[] =
   "  cmd_has_option\n"
   "              - Returns OK if the command CMD implements the option OPT.\n"
   "  connections - Return number of active connections.\n"
+  "  jent_active - Returns OK if Libgcrypt's JENT is active.\n"
   "  restricted  - Returns OK if the connection is in restricted mode.\n";
 static gpg_error_t
 cmd_getinfo (assuan_context_t ctx, char *line)
@@ -2992,6 +2993,24 @@ cmd_getinfo (assuan_context_t ctx, char *line)
                 get_agent_active_connection_count ());
       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
     }
+  else if (!strcmp (line, "jent_active"))
+    {
+#if GCRYPT_VERSION_NUMBER >= 0x010800
+      char *buf;
+      char *fields[5];
+
+      buf = gcry_get_config (0, "rng-type");
+      if (buf
+          && split_fields_colon (buf, fields, DIM (fields)) >= 5
+          && atoi (fields[4]) > 0)
+        rc = 0;
+      else
+        rc = gpg_error (GPG_ERR_FALSE);
+      gcry_free (buf);
+#else
+      rc = gpg_error (GPG_ERR_FALSE);
+#endif
+    }
   else
     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
   return rc;

commit 849467870ee1c10e0a7b1e89cfc9e8214e4963fe
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Jul 17 13:00:44 2017 +0200

    common: New function split_fields_colon.
    
    * common/stringhelp.c (split_fields_colon): New.
    * common/t-stringhelp.c (test_split_fields_colon): New test.
    (main): Call that test.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/common/stringhelp.c b/common/stringhelp.c
index 3b481e8..0abac8a 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -1339,6 +1339,42 @@ split_fields (char *string, char **array, int arraysize)
 }
 
 
+/* Split a string into colon delimited fields A pointer to each field
+ * is stored in ARRAY.  Stop splitting at ARRAYSIZE fields.  The
+ * function modifies STRING.  The number of parsed fields is returned.
+ * Note that leading and trailing spaces are not removed from the fields.
+ * Example:
+ *
+ *   char *fields[2];
+ *   if (split_fields (string, fields, DIM (fields)) < 2)
+ *     return  // Not enough args.
+ *   foo (fields[0]);
+ *   foo (fields[1]);
+ */
+int
+split_fields_colon (char *string, char **array, int arraysize)
+{
+  int n = 0;
+  char *p, *pend;
+
+  p = string;
+  do
+    {
+      if (n == arraysize)
+        break;
+      array[n++] = p;
+      pend = strchr (p, ':');
+      if (!pend)
+        break;
+      *pend++ = 0;
+      p = pend;
+    }
+  while (*p);
+
+  return n;
+}
+
+
 

 /* Version number parsing.  */
 
diff --git a/common/stringhelp.h b/common/stringhelp.h
index a643f35..5b07af9 100644
--- a/common/stringhelp.h
+++ b/common/stringhelp.h
@@ -151,6 +151,10 @@ char **strtokenize (const char *string, const char *delim);
  * provided ARRAY.  */
 int split_fields (char *string, char **array, int arraysize);
 
+/* Split STRING into colon delimited fields and store them in the
+ * provided ARRAY.  */
+int split_fields_colon (char *string, char **array, int arraysize);
+
 /* Return True if MYVERSION is greater or equal than REQ_VERSION.  */
 int compare_version_strings (const char *my_version, const char *req_version);
 
diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c
index 189fed1..7c6fb80 100644
--- a/common/t-stringhelp.c
+++ b/common/t-stringhelp.c
@@ -761,6 +761,81 @@ test_split_fields (void)
 }
 
 
+static void
+test_split_fields_colon (void)
+{
+  struct {
+    const char *s;
+    int nfields;
+    const char *fields_expected[10];
+  } tv[] = {
+    {
+      "a:bc:cde:fghi:jklmn:  foo ", 6,
+      { "a", "bc", "cde", "fghi", "jklmn", "  foo ", NULL }
+    },
+    {
+      " a:bc: def ", 2,
+      { " a", "bc", NULL }
+    },
+    {
+      " a:bc :def ", 3,
+      { " a", "bc ", "def ", NULL }
+    },
+    {
+      " a:bc: def ", 4,
+      { " a", "bc", " def ", NULL }
+    },
+    {
+      "", 0,
+      { NULL }
+    }
+  };
+
+  int tidx;
+  char *fields[10];
+  int field_count_expected, nfields, field_count, i;
+  char *s2;
+
+  for (tidx = 0; tidx < DIM(tv); tidx++)
+    {
+      nfields = tv[tidx].nfields;
+      assert (nfields <= DIM (fields));
+
+      /* Count the fields.  */
+      for (field_count_expected = 0;
+           tv[tidx].fields_expected[field_count_expected];
+           field_count_expected ++)
+        ;
+      if (field_count_expected > nfields)
+        field_count_expected = nfields;
+
+      /* We need to copy s since split_fields modifies in place.  */
+      s2 = xstrdup (tv[tidx].s);
+      field_count = split_fields_colon (s2, fields, nfields);
+
+      if (field_count != field_count_expected)
+        {
+          printf ("%s: tidx %d: expected %d, got %d\n",
+                  __func__, tidx, field_count_expected, field_count);
+          fail (tidx * 1000);
+        }
+      else
+        {
+          for (i = 0; i < field_count_expected; i ++)
+            if (strcmp (tv[tidx].fields_expected[i], fields[i]))
+              {
+                printf ("%s: tidx %d, field %d: expected '%s', got '%s'\n",
+                        __func__,
+                        tidx, i, tv[tidx].fields_expected[i], fields[i]);
+                fail (tidx * 1000 + i + 1);
+              }
+        }
+
+      xfree (s2);
+    }
+}
+
+
 static char *
 stresc (char *s)
 {
@@ -996,6 +1071,7 @@ main (int argc, char **argv)
   test_strsplit ();
   test_strtokenize ();
   test_split_fields ();
+  test_split_fields_colon ();
   test_compare_version_strings ();
   test_format_text ();
 

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

Summary of changes:
 agent/command.c       | 19 +++++++++++++
 common/compliance.c   | 40 +++++++++++++++++++++++++++
 common/compliance.h   |  2 ++
 common/stringhelp.c   | 36 ++++++++++++++++++++++++
 common/stringhelp.h   |  4 +++
 common/t-stringhelp.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
 g10/call-agent.c      | 18 ++++++++++++
 g10/encrypt.c         | 20 ++++++++++++++
 g10/sign.c            | 10 +++++++
 sm/call-agent.c       | 19 +++++++++++++
 sm/encrypt.c          | 11 ++++++++
 sm/sign.c             | 11 ++++++++
 12 files changed, 266 insertions(+)


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




More information about the Gnupg-commits mailing list