diff --git a/doc/gpg.texi b/doc/gpg.texi index ff66301d1..f6c445658 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -2957,6 +2957,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 gpg 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 gpg 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. + @end table diff --git a/g10/encrypt.c b/g10/encrypt.c index bca7344f4..28a761747 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -847,6 +847,17 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, gnupg_status_compliance_flag (CO_DE_VS), NULL); + if (opt.flags.require_compliance + && opt.compliance == CO_DE_VS + && !compliant) + { + log_error (_("operation forced to fail due to" + " unfulfilled compliance rules\n")); + rc = gpg_error (GPG_ERR_FORBIDDEN); + g10_errors_seen = 1; + goto leave; + } + cfx.dek->use_aead = use_aead (pk_list, cfx.dek->algo); if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (pk_list, cfx.dek->algo); diff --git a/g10/gpg.c b/g10/gpg.c index 1155f501c..4883493db 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -442,6 +442,7 @@ enum cmd_and_opt_values oChUid, oForceSignKey, oForbidGenKey, + oRequireCompliance, oNoop }; @@ -911,6 +912,7 @@ static gpgrt_opt_t opts[] = { ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"), ARGPARSE_s_n (oUseKeyboxd, "use-keyboxd", "@"), ARGPARSE_s_n (oForbidGenKey, "forbid-gen-key", "@"), + ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"), /* Options which can be used in special circumstances. They are not * published and we hope they are never required. */ ARGPARSE_s_n (oUseOnlyOpenPGPCard, "use-only-openpgp-card", "@"), @@ -3731,6 +3733,10 @@ main (int argc, char **argv) mopt.forbid_gen_key = 1; break; + case oRequireCompliance: + opt.flags.require_compliance = 1; + break; + case oNoop: break; default: diff --git a/g10/mainproc.c b/g10/mainproc.c index f44e68453..70685fab9 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -546,6 +546,7 @@ proc_encrypted (CTX c, PACKET *pkt) { int result = 0; int early_plaintext = literals_seen; + unsigned int compliance_de_vs = 0; if (pkt->pkttype == PKT_ENCRYPTED_AEAD) c->seen_pkt_encrypted_aead = 1; @@ -721,10 +722,12 @@ proc_encrypted (CTX c, PACKET *pkt) xfree (pk); if (compliant) - write_status_strings (STATUS_DECRYPTION_COMPLIANCE_MODE, - gnupg_status_compliance_flag (CO_DE_VS), - NULL); - + { + write_status_strings (STATUS_DECRYPTION_COMPLIANCE_MODE, + gnupg_status_compliance_flag (CO_DE_VS), + NULL); + compliance_de_vs |= 1; + } } if (!result) @@ -779,9 +782,15 @@ proc_encrypted (CTX c, PACKET *pkt) log_info(_("decryption okay\n")); if (pkt->pkt.encrypted->aead_algo) - write_status (STATUS_GOODMDC); + { + write_status (STATUS_GOODMDC); + compliance_de_vs |= 2; + } else if (pkt->pkt.encrypted->mdc_method && !result) - write_status (STATUS_GOODMDC); + { + write_status (STATUS_GOODMDC); + compliance_de_vs |= 2; + } else log_info (_("WARNING: message was not integrity protected\n")); } @@ -823,6 +832,17 @@ proc_encrypted (CTX c, PACKET *pkt) * a misplace extra literal data packets follows after this * encrypted packet. */ literals_seen++; + + /* The --require-compliance option allows to simplify decryption in + * de-vs compliance mode by just looking at the exit status. */ + if (opt.flags.require_compliance + && opt.compliance == CO_DE_VS + && compliance_de_vs != (2|1)) + { + log_error (_("operation forced to fail due to" + " unfulfilled compliance rules\n")); + g10_errors_seen = 1; + } } @@ -2439,6 +2459,15 @@ check_sig_and_print (CTX c, kbnode_t node) write_status_strings (STATUS_VERIFICATION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS), NULL); + else if (opt.flags.require_compliance + && opt.compliance == CO_DE_VS) + { + log_error (_("operation forced to fail due to" + " unfulfilled compliance rules\n")); + if (!rc) + rc = gpg_error (GPG_ERR_FORBIDDEN); + } + free_public_key (pk); pk = NULL; diff --git a/g10/options.h b/g10/options.h index 8df463ed4..10e61ea4c 100644 --- a/g10/options.h +++ b/g10/options.h @@ -269,6 +269,9 @@ struct /* The next flag is set internally iff IMPORT_CLEAN has * been set by the user and is not the default value. */ unsigned int expl_import_clean:1; + /* Fail if an operation can't be done in the requested compliance + * mode. */ + unsigned int require_compliance:1; } flags; /* Linked list of ways to find a key if the key isn't on the local