aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2017-07-17 13:52:26 +0000
committerWerner Koch <[email protected]>2017-07-17 13:53:16 +0000
commita149afe338d61d86985c533cde5e7dbcd31e8698 (patch)
treec930065acfb8403fe8391dc0d93b866f599bc52e
parentagent: New GETINFO sub-command jent_active. (diff)
downloadgnupg-a149afe338d61d86985c533cde5e7dbcd31e8698.tar.gz
gnupg-a149afe338d61d86985c533cde5e7dbcd31e8698.zip
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 <[email protected]>
-rw-r--r--common/compliance.c40
-rw-r--r--common/compliance.h2
-rw-r--r--g10/call-agent.c18
-rw-r--r--g10/encrypt.c20
-rw-r--r--g10/sign.c10
-rw-r--r--sm/call-agent.c19
-rw-r--r--sm/encrypt.c11
-rw-r--r--sm/sign.c11
8 files changed, 131 insertions, 0 deletions
diff --git a/common/compliance.c b/common/compliance.c
index 8b9167758..268ea4dbf 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 d55bbf3ac..2076e79cb 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 7b769332e..3ad13e874 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 4b21a6178..c63ec8838 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 0ba115188..f7dd974fe 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 0e47c1448..ba8fb122b 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 9e3216a79..73519325e 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 7ba231939..14115017d 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)