From 847d618454e6f8418b169132dbdd0307d9b4d7e0 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 8 Mar 2022 19:06:30 +0100 Subject: [PATCH] gpgsm: New option --require-compliance * sm/gpgsm.c (oRequireCompliance): New. (opts): Add --require-compliance. (main): Set option. * sm/gpgsm.h (opt): Add field require_compliance. (gpgsm_errors_seen): Declare. * sm/verify.c (gpgsm_verify): Emit error if non de-vs compliant. * sm/encrypt.c (gpgsm_encrypt): Ditto. * sm/decrypt.c (gpgsm_decrypt): Ditto. --- doc/gpgsm.texi | 11 +++++++++++ sm/decrypt.c | 8 +++++++- sm/encrypt.c | 9 +++++++++ sm/gpgsm.c | 7 +++++-- sm/gpgsm.h | 8 ++++++++ sm/verify.c | 7 +++++++ 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 39ec52331..06a85b1ed 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -676,6 +676,17 @@ This option adjusts the compliance mode "de-vs" for stricter key size requirements. For example, a value of 3000 turns rsa2048 and dsa2048 keys into non-VS-NfD compliant keys. +@item --require-compliance +@opindex require-compliance +To check that data has been encrypted according to the rules of the +current compliance mode, a gpgsm user needs to evaluate the status +lines. This is allows frontends to handle compliance check in a more +flexible way. However, for scripted use the required evaluation of +the status-line requires quite some effort; this option can be used +instead to make sure that the gpgsm process exits with a failure if +the compliance rules are not fulfilled. Note that this option has +currently an effect only in "de-vs" mode. + @item --ignore-cert-with-oid @var{oid} @opindex ignore-cert-with-oid Add @var{oid} to the list of OIDs to be checked while reading diff --git a/sm/decrypt.c b/sm/decrypt.c index 38aa83210..2aa716f5b 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -1029,7 +1029,13 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp) && gnupg_gcrypt_is_compliant (CO_DE_VS)) gpgsm_status (ctrl, STATUS_DECRYPTION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS)); - + else if (opt.require_compliance + && opt.compliance == CO_DE_VS) + { + log_error (_("operation forced to fail due to" + " unfulfilled compliance rules\n")); + gpgsm_errors_seen = 1; + } } audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc); } diff --git a/sm/encrypt.c b/sm/encrypt.c index 37cfe9263..587b568c6 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -535,6 +535,15 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp) if (compliant && gnupg_gcrypt_is_compliant (CO_DE_VS)) gpgsm_status (ctrl, STATUS_ENCRYPTION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS)); + else if (opt.require_compliance + && opt.compliance == CO_DE_VS) + { + log_error (_("operation forced to fail due to" + " unfulfilled compliance rules\n")); + gpgsm_errors_seen = 1; + rc = gpg_error (GPG_ERR_FORBIDDEN); + goto leave; + } /* Main control loop for encryption. */ recpno = 0; diff --git a/sm/gpgsm.c b/sm/gpgsm.c index e70e2aaff..6e3da64ac 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -199,6 +199,7 @@ enum cmd_and_opt_values { oNoCommonCertsImport, oIgnoreCertExtension, oIgnoreCertWithOID, + oRequireCompliance, oNoAutostart }; @@ -289,6 +290,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oPolicyFile, "policy-file", N_("|FILE|take policy information from FILE")), ARGPARSE_s_s (oCompliance, "compliance", "@"), + ARGPARSE_p_u (oMinRSALength, "min-rsa-length", "@"), ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"), ARGPARSE_s_s (oIgnoreCertExtension, "ignore-cert-extension", "@"), ARGPARSE_s_s (oIgnoreCertWithOID, "ignore-cert-with-oid", "@"), @@ -387,7 +389,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oDisablePubkeyAlgo, "disable-pubkey-algo", "@"), ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"), ARGPARSE_s_n (oNoRandomSeedFile, "no-random-seed-file", "@"), - ARGPARSE_p_u (oMinRSALength, "min-rsa-length", "@"), + ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"), ARGPARSE_header (NULL, N_("Options for unattended use")), @@ -421,7 +423,6 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oLCmessages, "lc-messages", "@"), ARGPARSE_s_s (oXauthority, "xauthority", "@"), - ARGPARSE_header (NULL, ""), /* Stop the header group. */ @@ -1410,6 +1411,8 @@ main ( int argc, char **argv) case oMinRSALength: opt.min_rsa_length = pargs.r.ret_ulong; break; + case oRequireCompliance: opt.require_compliance = 1; break; + default: if (configname) pargs.err = ARGPARSE_PRINT_WARNING; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index fce2767d5..5e7db4bec 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -143,7 +143,13 @@ struct * sunch an OID during --learn-card. */ strlist_t ignore_cert_with_oid; + /* The current compliance mode. */ enum gnupg_compliance_mode compliance; + + /* Fail if an operation can't be done in the requested compliance + * mode. */ + int require_compliance; + } opt; /* Debug values and macros. */ @@ -234,6 +240,8 @@ struct rootca_flags_s /*-- gpgsm.c --*/ +extern int gpgsm_errors_seen; + void gpgsm_exit (int rc); void gpgsm_init_default_ctrl (struct server_control_s *ctrl); int gpgsm_parse_validation_model (const char *model); diff --git a/sm/verify.c b/sm/verify.c index 3c5279ebd..5510f42cb 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -516,6 +516,13 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp) && gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo)) gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS)); + else if (opt.require_compliance + && opt.compliance == CO_DE_VS) + { + log_error (_("operation forced to fail due to" + " unfulfilled compliance rules\n")); + gpgsm_errors_seen = 1; + } /* Now we can check the signature. */