Page MenuHome GnuPG

GpgME: gpgme_op_decrypt_verify creates incomplete verification result for not encrypted data
Closed, ResolvedPublic

Description

To simplify extracting signed and/or encrypted archives for users of [q]gpgme it would be good if they could simply use gpgme_op_decrypt_verify or DecryptVerifyArchiveJob for all archives regardless of whether they are encrypted or only signed. Currently, this doesn't work if the archive is only signed because the finalization of the decryption result returns an error ("no data") and therefore the finalization of the verification result is skipped (in decrypt_verify_status_handler):

err = _gpgme_progress_status_handler (priv, code, args);
if (!err)
  err = _gpgme_decrypt_status_handler (priv, code, args);
if (!err)
  err = _gpgme_verify_status_handler (priv, code, args);

This can be tested with lang/qt/tests/run-decryptverifyarchivejob and a signed-only archive. The result will show

Summary:                   GpgME::Signature::Summary()

because the summary hasn't been calculated.

Event Timeline

ikloecker created this task.

I see two possible solutions.

a) Call the verify status handler before the decrypt status handler.
This could obviously cause other problems, e.g. if the verify status handler returns an error on GPGME_STATUS_EOF (which can happen if a status error was detected previously, or, highly unlikely, if a memory allocation failed) then the finalization of the decryption result will be skipped.

b) Call the verify status handler on GPGME_STATUS_EOF even if the decrypt status handler returned an error, i.e.

@@ -35,13 +35,15 @@ decrypt_verify_status_handler (void *priv, gpgme_status_code_t code,
 			       char *args)
 {
   gpgme_error_t err;
+  gpgme_error_t err2;
 
   err = _gpgme_progress_status_handler (priv, code, args);
   if (!err)
     err = _gpgme_decrypt_status_handler (priv, code, args);
-  if (!err)
-      err = _gpgme_verify_status_handler (priv, code, args);
-  return err;
+  /* allow handling of EOF even if previous handler returned an error */
+  if (!err || code == GPGME_STATUS_EOF)
+    err2 = _gpgme_verify_status_handler (priv, code, args);
+  return err ? err : err2;
 }

I think I prefer solution b) because it avoids the unforeseen side effects of changing the order of the two calls. In particular, it avoids introducing the same problem for the decryption result that we are trying to fix for the verification result.

P.S.
c) The least hacky solution would probably be a combined decrypt_verify_status_handler. But that would likely add a lot of duplicate code and would break the clean separation of decryption and verification.

I have some doubts that signed-only archives are very useful. The only use case is that this allows to sign stuff without saving it first. You would need to do this in my generally preferred detach signature case.

You solution b) seems to be best. Could we easily do this only in archive mode to avoid any risk of regression?

ikloecker moved this task from Restricted Project Column to Restricted Project Column on the Restricted Project board.
ikloecker moved this task from Restricted Project Column to Restricted Project Column on the Restricted Project board.

I made the condition for calling the verify handler more strict by checking if err is a NO DATA error. This should minimize the risk of regression.