summaryrefslogtreecommitdiff
path: root/sm
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-02-09 16:00:23 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-02-09 16:00:23 +0900
commit5ce840383da7cf82ffa7dfaeda187f3fe3d591a7 (patch)
treef93fb33cde2a62aa414b61dca085f3fd0613aaca /sm
parentd9f0d99e31569835e295b990029c6dd19554299c (diff)
downloadgpg2-5ce840383da7cf82ffa7dfaeda187f3fe3d591a7.tar.gz
gpg2-5ce840383da7cf82ffa7dfaeda187f3fe3d591a7.tar.bz2
gpg2-5ce840383da7cf82ffa7dfaeda187f3fe3d591a7.zip
Imported Upstream version 2.1.22upstream/2.1.22
Diffstat (limited to 'sm')
-rw-r--r--sm/call-agent.c19
-rw-r--r--sm/decrypt.c53
-rw-r--r--sm/encrypt.c54
-rw-r--r--sm/gpgsm.c56
-rw-r--r--sm/gpgsm.h2
-rw-r--r--sm/keylist.c5
-rw-r--r--sm/sign.c40
-rw-r--r--sm/verify.c42
8 files changed, 260 insertions, 11 deletions
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/decrypt.c b/sm/decrypt.c
index 976bd12..cdce1d4 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -32,6 +32,7 @@
#include "keydb.h"
#include "../common/i18n.h"
+#include "../common/compliance.h"
struct decrypt_filter_parm_s
{
@@ -41,7 +42,7 @@ struct decrypt_filter_parm_s
gcry_cipher_hd_t hd;
char iv[16];
size_t ivlen;
- int any_data; /* dod we push anything through the filter at all? */
+ int any_data; /* did we push anything through the filter at all? */
unsigned char lastblock[16]; /* to strip the padding we have to
keep this one */
char helpblock[16]; /* needed because there is no block buffering in
@@ -325,6 +326,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
int algo, mode;
const char *algoid;
int any_key = 0;
+ int is_de_vs; /* Computed compliance with CO_DE_VS. */
audit_log (ctrl->audit, AUDIT_GOT_DATA);
@@ -356,6 +358,20 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
goto leave;
}
+ /* Check compliance. */
+ if (! gnupg_cipher_is_allowed (opt.compliance, 0, algo, mode))
+ {
+ log_error (_("cipher algorithm '%s'"
+ " may not be used in %s mode\n"),
+ gcry_cipher_algo_name (algo),
+ gnupg_compliance_option_string (opt.compliance));
+ rc = gpg_error (GPG_ERR_CIPHER_ALGO);
+ goto leave;
+ }
+
+ /* For CMS, CO_DE_VS demands CBC mode. */
+ is_de_vs = gnupg_cipher_is_compliant (CO_DE_VS, algo, mode);
+
audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
dfparm.algo = algo;
dfparm.mode = mode;
@@ -460,7 +476,37 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
desc = gpgsm_format_keydesc (cert);
+ {
+ unsigned int nbits;
+ int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
+
+ /* Print compliance warning. */
+ if (! gnupg_pk_is_compliant (opt.compliance,
+ pk_algo, NULL, nbits, NULL))
+ {
+ char kidstr[10+1];
+
+ snprintf (kidstr, sizeof kidstr, "0x%08lX",
+ gpgsm_get_short_fingerprint (cert, NULL));
+ log_info
+ (_("Note: key %s is not suitable for encryption"
+ " in %s mode\n"),
+ kidstr,
+ gnupg_compliance_option_string (opt.compliance));
+ }
+
+ /* Check that all certs are compliant with CO_DE_VS. */
+ is_de_vs =
+ (is_de_vs
+ && gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL,
+ nbits, NULL));
+ }
+
oops:
+ if (rc)
+ /* We cannot check compliance of certs that we
+ * don't have. */
+ is_de_vs = 0;
xfree (issuer);
xfree (serial);
ksba_cert_release (cert);
@@ -489,6 +535,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
ksba_writer_set_filter (writer,
decrypt_filter,
&dfparm);
+
+ if (is_de_vs)
+ gpgsm_status (ctrl, STATUS_DECRYPTION_COMPLIANCE_MODE,
+ gnupg_status_compliance_flag (CO_DE_VS));
+
}
audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
}
diff --git a/sm/encrypt.c b/sm/encrypt.c
index c43a9e6..6213a66 100644
--- a/sm/encrypt.c
+++ b/sm/encrypt.c
@@ -33,6 +33,7 @@
#include "keydb.h"
#include "../common/i18n.h"
+#include "../common/compliance.h"
struct dek_s {
@@ -312,6 +313,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
estream_t data_fp = NULL;
certlist_t cl;
int count;
+ int compliant;
memset (&encparm, 0, sizeof encparm);
@@ -405,6 +407,29 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
goto leave;
}
+ /* Check compliance. */
+ if (!gnupg_cipher_is_allowed
+ (opt.compliance, 1, gcry_cipher_map_name (opt.def_cipher_algoid),
+ gcry_cipher_mode_from_oid (opt.def_cipher_algoid)))
+ {
+ log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
+ opt.def_cipher_algoid,
+ gnupg_compliance_option_string (opt.compliance));
+ rc = gpg_error (GPG_ERR_CIPHER_ALGO);
+ 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)
@@ -442,11 +467,36 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);
+ compliant = gnupg_cipher_is_compliant (CO_DE_VS, dek->algo,
+ GCRY_CIPHER_MODE_CBC);
+
/* Gather certificates of recipients, encrypt the session key for
each and store them in the CMS object */
for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
{
unsigned char *encval;
+ unsigned int nbits;
+ int pk_algo;
+
+ /* Check compliance. */
+ pk_algo = gpgsm_get_key_algo_info (cl->cert, &nbits);
+ if (!gnupg_pk_is_compliant (opt.compliance, pk_algo, NULL, nbits, NULL))
+ {
+ char kidstr[10+1];
+
+ snprintf (kidstr, sizeof kidstr, "0x%08lX",
+ gpgsm_get_short_fingerprint (cl->cert, NULL));
+ log_info (_("WARNING: key %s is not suitable for encryption"
+ " in %s mode\n"),
+ kidstr,
+ gnupg_compliance_option_string (opt.compliance));
+ }
+
+ /* Fixme: When adding ECC we need to provide the curvename and
+ * the key to gnupg_pk_is_compliant. */
+ if (compliant
+ && !gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL, nbits, NULL))
+ compliant = 0;
rc = encrypt_dek (dek, cl->cert, &encval);
if (rc)
@@ -480,6 +530,10 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
}
}
+ if (compliant)
+ gpgsm_status (ctrl, STATUS_ENCRYPTION_COMPLIANCE_MODE,
+ gnupg_status_compliance_flag (CO_DE_VS));
+
/* Main control loop for encryption. */
recpno = 0;
do
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index cb181e8..10eff0a 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -41,6 +41,7 @@
#include "../common/gc-opt-flags.h"
#include "../common/asshelp.h"
#include "../common/init.h"
+#include "../common/compliance.h"
#ifndef O_BINARY
@@ -946,6 +947,9 @@ main ( int argc, char **argv)
dotlock_create (NULL, 0); /* Register lockfile cleanup. */
+ /* Tell the compliance module who we are. */
+ gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPGSM);
+
opt.autostart = 1;
opt.session_env = session_env_new ();
if (!opt.session_env)
@@ -1443,7 +1447,19 @@ main ( int argc, char **argv)
case oNoAutostart: opt.autostart = 0; break;
case oCompliance:
- /* Dummy option for now. */
+ {
+ struct gnupg_compliance_option compliance_options[] =
+ {
+ { "de-vs", CO_DE_VS }
+ };
+ int compliance = gnupg_parse_compliance_option (pargs.r.ret_str,
+ compliance_options,
+ DIM (compliance_options),
+ opt.quiet);
+ if (compliance < 0)
+ gpgsm_exit (1);
+ opt.compliance = compliance;
+ }
break;
default:
@@ -1598,6 +1614,44 @@ main ( int argc, char **argv)
}
}
+ /* Check our chosen algorithms against the list of allowed
+ * algorithms in the current compliance mode, and fail hard if it is
+ * not. This is us being nice to the user informing her early that
+ * the chosen algorithms are not available. We also check and
+ * enforce this right before the actual operation. */
+ if (! gnupg_cipher_is_allowed (opt.compliance,
+ cmd == aEncr || cmd == aSignEncr,
+ gcry_cipher_map_name (opt.def_cipher_algoid),
+ GCRY_CIPHER_MODE_NONE)
+ && ! gnupg_cipher_is_allowed (opt.compliance,
+ cmd == aEncr || cmd == aSignEncr,
+ gcry_cipher_mode_from_oid
+ (opt.def_cipher_algoid),
+ GCRY_CIPHER_MODE_NONE))
+ log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
+ opt.def_cipher_algoid,
+ gnupg_compliance_option_string (opt.compliance));
+
+ if (forced_digest_algo
+ && ! gnupg_digest_is_allowed (opt.compliance,
+ cmd == aSign
+ || cmd == aSignEncr
+ || cmd == aClearsign,
+ opt.forced_digest_algo))
+ log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+ forced_digest_algo,
+ gnupg_compliance_option_string (opt.compliance));
+
+ if (extra_digest_algo
+ && ! gnupg_digest_is_allowed (opt.compliance,
+ cmd == aSign
+ || cmd == aSignEncr
+ || cmd == aClearsign,
+ opt.extra_digest_algo))
+ log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+ forced_digest_algo,
+ gnupg_compliance_option_string (opt.compliance));
+
if (log_get_errorcount(0))
gpgsm_exit(2);
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index df96770..8c1f520 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -34,6 +34,7 @@
#include "../common/audit.h"
#include "../common/session-env.h"
#include "../common/ksba-io-support.h"
+#include "../common/compliance.h"
#define MAX_DIGEST_LEN 64
@@ -144,6 +145,7 @@ struct
OID per string. */
strlist_t ignored_cert_extensions;
+ enum gnupg_compliance_mode compliance;
} opt;
/* Debug values and macros. */
diff --git a/sm/keylist.c b/sm/keylist.c
index 13de45d..abec049 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -36,6 +36,7 @@
#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
#include "../common/i18n.h"
#include "../common/tlv.h"
+#include "../common/compliance.h"
struct list_external_parm_s
{
@@ -351,8 +352,8 @@ email_kludge (const char *name)
static void
print_compliance_flags (int algo, unsigned int nbits, estream_t fp)
{
- if (algo == GCRY_PK_RSA && nbits >= 2048)
- es_fputs ("23", fp);
+ if (gnupg_pk_is_compliant (CO_DE_VS, algo, NULL, nbits, NULL))
+ es_fputs (gnupg_status_compliance_flag (CO_DE_VS), fp);
}
diff --git a/sm/sign.c b/sm/sign.c
index e65562d..24ecad3 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)
@@ -460,6 +471,35 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
break;
}
cl->hash_algo_oid = oid;
+
+ /* Check compliance. */
+ if (! gnupg_digest_is_allowed (opt.compliance, 1, cl->hash_algo))
+ {
+ log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+ gcry_md_algo_name (cl->hash_algo),
+ gnupg_compliance_option_string (opt.compliance));
+ err = gpg_error (GPG_ERR_DIGEST_ALGO);
+ goto leave;
+ }
+
+ {
+ unsigned int nbits;
+ int pk_algo = gpgsm_get_key_algo_info (cl->cert, &nbits);
+
+ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pk_algo,
+ NULL, nbits, NULL))
+ {
+ char kidstr[10+1];
+
+ snprintf (kidstr, sizeof kidstr, "0x%08lX",
+ gpgsm_get_short_fingerprint (cl->cert, NULL));
+ log_error (_("key %s may not be used for signing in %s mode\n"),
+ kidstr,
+ gnupg_compliance_option_string (opt.compliance));
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ goto leave;
+ }
+ }
}
if (opt.verbose)
diff --git a/sm/verify.c b/sm/verify.c
index 6c034e6..10b3f43 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -33,6 +33,7 @@
#include "keydb.h"
#include "../common/i18n.h"
+#include "../common/compliance.h"
static char *
strtimestamp_r (ksba_isotime_t atime)
@@ -341,16 +342,11 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
&msgdigest, &msgdigestlen);
if (!rc)
{
- size_t is_enabled;
-
algoid = ksba_cms_get_digest_algo (cms, signer);
algo = gcry_md_map_name (algoid);
if (DBG_X509)
log_debug ("signer %d - digest algo: %d\n", signer, algo);
- is_enabled = sizeof algo;
- if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
- &algo, &is_enabled)
- || !is_enabled)
+ if (! gcry_md_is_enabled (data_md, algo))
{
log_error ("digest algo %d (%s) has not been enabled\n",
algo, algoid?algoid:"");
@@ -454,6 +450,39 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
goto next_signer;
}
+ /* Check compliance. */
+ {
+ unsigned int nbits;
+ int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
+
+ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
+ pk_algo, NULL, nbits, NULL))
+ {
+ char kidstr[10+1];
+
+ snprintf (kidstr, sizeof kidstr, "0x%08lX",
+ gpgsm_get_short_fingerprint (cert, NULL));
+ log_error (_("key %s may not be used for signing in %s mode\n"),
+ kidstr,
+ gnupg_compliance_option_string (opt.compliance));
+ goto next_signer;
+ }
+
+ if (! gnupg_digest_is_allowed (opt.compliance, 0, sigval_hash_algo))
+ {
+ log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+ gcry_md_algo_name (sigval_hash_algo),
+ gnupg_compliance_option_string (opt.compliance));
+ goto next_signer;
+ }
+
+ /* Check compliance with CO_DE_VS. */
+ if (gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL, nbits, NULL)
+ && gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
+ gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
+ gnupg_status_compliance_flag (CO_DE_VS));
+ }
+
log_info (_("Signature made "));
if (*sigtime)
dump_isotime (sigtime);
@@ -636,7 +665,6 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
(verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
"0 chain": "0 shell");
-
next_signer:
rc = 0;
xfree (issuer);