diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c index 279388509..89d7c9a70 100644 --- a/g10/decrypt-data.c +++ b/g10/decrypt-data.c @@ -215,10 +215,14 @@ aead_checktag (decode_filter_ctx_t dfx, int final, const void *tagbuf) /**************** - * Decrypt the data, specified by ED with the key DEK. + * Decrypt the data, specified by ED with the key DEK. On return + * COMPLIANCE_ERROR is set to true iff the decryption can claim that + * it was compliant in the current mode; otherwise this flag is set to + * false. */ int -decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) +decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek, + int *compliance_error) { decode_filter_ctx_t dfx; enum gcry_cipher_modes ciphermode; @@ -229,6 +233,8 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) unsigned blocksize; unsigned nprefix; + *compliance_error = 0; + dfx = xtrycalloc (1, sizeof *dfx); if (!dfx) return gpg_error_from_syserror (); @@ -260,8 +266,14 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) log_error (_("cipher algorithm '%s' may not be used in %s mode\n"), openpgp_cipher_algo_name (dek->algo), gnupg_compliance_option_string (opt.compliance)); - rc = gpg_error (GPG_ERR_CIPHER_ALGO); - goto leave; + *compliance_error = 1; + if (opt.flags.require_compliance) + { + /* We fail early in this case because it does not make sense + * to first decrypt everything. */ + rc = gpg_error (GPG_ERR_CIPHER_ALGO); + goto leave; + } } write_status_printf (STATUS_DECRYPTION_INFO, "%d %d %d", @@ -420,6 +432,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) if (!ed->buf) { log_error (_("problem handling encrypted packet\n")); + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } diff --git a/g10/gpgv.c b/g10/gpgv.c index 71adb0488..4e9c35de5 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -549,12 +549,14 @@ get_override_session_key (DEK *dek, const char *string) /* Stub: */ int -decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) +decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek, + int *compliance_error) { (void)ctrl; (void)procctx; (void)ed; (void)dek; + (void)compliance_error; return GPG_ERR_GENERAL; } diff --git a/g10/mainproc.c b/g10/mainproc.c index 4939fdef3..4fb7d6840 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -762,17 +762,18 @@ 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); - compliance_de_vs |= 1; - } + compliance_de_vs |= 1; } if (!result) - result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek ); + { + int compl_error; + result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek, + &compl_error); + if (!result && !compl_error) + compliance_de_vs |= 2; + } /* Trigger the deferred error. */ if (!result && early_plaintext) @@ -825,12 +826,12 @@ proc_encrypted (CTX c, PACKET *pkt) if (pkt->pkt.encrypted->aead_algo) { write_status (STATUS_GOODMDC); - compliance_de_vs |= 2; + compliance_de_vs |= 4; } else if (pkt->pkt.encrypted->mdc_method && !result) { write_status (STATUS_GOODMDC); - compliance_de_vs |= 2; + compliance_de_vs |= 4; } else log_info (_("WARNING: message was not integrity protected\n")); @@ -862,6 +863,16 @@ proc_encrypted (CTX c, PACKET *pkt) * ways to specify the session key (symmmetric and PK). */ } + + /* If we concluded that the decryption was compliant, issue a + * compliance status before the thed end of decryption status. */ + if (compliance_de_vs == (4|2|1)) + { + write_status_strings (STATUS_DECRYPTION_COMPLIANCE_MODE, + gnupg_status_compliance_flag (CO_DE_VS), + NULL); + } + xfree (c->dek); c->dek = NULL; free_packet (pkt, NULL); @@ -878,7 +889,7 @@ proc_encrypted (CTX c, PACKET *pkt) * 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)) + && compliance_de_vs != (4|2|1)) { log_error (_("operation forced to fail due to" " unfulfilled compliance rules\n")); diff --git a/g10/packet.h b/g10/packet.h index 187fffc7c..7f7608c95 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -906,8 +906,9 @@ gpg_error_t get_override_session_key (DEK *dek, const char *string); int handle_compressed (ctrl_t ctrl, void *ctx, PKT_compressed *cd, int (*callback)(iobuf_t, void *), void *passthru ); -/*-- encr-data.c --*/ -int decrypt_data (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek ); +/*-- decrypt-data.c --*/ +int decrypt_data (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek, + int *compliance_error); /*-- plaintext.c --*/ gpg_error_t get_output_file (const byte *embedded_name, int embedded_namelen, diff --git a/g10/test-stubs.c b/g10/test-stubs.c index f0ce10b38..2ae4a4183 100644 --- a/g10/test-stubs.c +++ b/g10/test-stubs.c @@ -306,12 +306,14 @@ get_override_session_key (DEK *dek, const char *string) /* Stub: */ int -decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) +decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek, + int *compliance_error) { (void)ctrl; (void)procctx; (void)ed; (void)dek; + (void)compliance_error; return GPG_ERR_GENERAL; }