diff --git a/src/decrypt-verify.c b/src/decrypt-verify.c
index b63318f2..3ff15feb 100644
--- a/src/decrypt-verify.c
+++ b/src/decrypt-verify.c
@@ -1,183 +1,187 @@
/* decrypt-verify.c - Decrypt and verify function.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see .
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#if HAVE_CONFIG_H
#include
#endif
#include
#include "debug.h"
#include "gpgme.h"
#include "ops.h"
static gpgme_error_t
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 finalization of signature verification even if previous handler
+ * returned NO DATA error which just means that the data wasn't encrypted. */
+ if (!err
+ || (code == GPGME_STATUS_EOF && gpg_err_code (err) == GPG_ERR_NO_DATA))
+ err2 = _gpgme_verify_status_handler (priv, code, args);
+ return err ? err : err2;
}
static gpgme_error_t
decrypt_verify_start (gpgme_ctx_t ctx, int synchronous,
gpgme_decrypt_flags_t flags,
gpgme_data_t cipher, gpgme_data_t plain)
{
gpgme_error_t err;
assert ((flags & GPGME_DECRYPT_VERIFY));
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
err = _gpgme_op_decrypt_init_result (ctx, plain);
if (err)
return err;
err = _gpgme_op_verify_init_result (ctx);
if (err)
return err;
if (!cipher)
return gpg_error (GPG_ERR_NO_DATA);
if (!plain)
return gpg_error (GPG_ERR_INV_VALUE);
if (ctx->passphrase_cb)
{
err = _gpgme_engine_set_command_handler
(ctx->engine, _gpgme_passphrase_command_handler, ctx);
if (err)
return err;
}
_gpgme_engine_set_status_handler (ctx->engine,
decrypt_verify_status_handler, ctx);
return _gpgme_engine_op_decrypt (ctx->engine,
flags,
cipher, plain,
ctx->export_session_keys,
ctx->override_session_key,
ctx->auto_key_retrieve);
}
/* Decrypt ciphertext CIPHER and make a signature verification within
CTX and store the resulting plaintext in PLAIN. */
gpgme_error_t
gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
gpgme_data_t plain)
{
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_verify_start", ctx,
"cipher=%p, plain=%p", cipher, plain);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = decrypt_verify_start (ctx, 0, GPGME_DECRYPT_VERIFY, cipher, plain);
return TRACE_ERR (err);
}
/* Decrypt ciphertext CIPHER and make a signature verification within
CTX and store the resulting plaintext in PLAIN. */
gpgme_error_t
gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher,
gpgme_data_t plain)
{
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_verify", ctx,
"cipher=%p, plain=%p", cipher, plain);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = decrypt_verify_start (ctx, 1, GPGME_DECRYPT_VERIFY, cipher, plain);
if (!err)
err = _gpgme_wait_one (ctx);
ctx->ignore_mdc_error = 0; /* Always reset. */
return TRACE_ERR (err);
}
/* Decrypt ciphertext CIPHER within CTX and store the resulting
plaintext in PLAIN. */
gpgme_error_t
gpgme_op_decrypt_ext_start (gpgme_ctx_t ctx,
gpgme_decrypt_flags_t flags,
gpgme_data_t cipher,
gpgme_data_t plain)
{
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_ext_start", ctx,
"cipher=%p, plain=%p", cipher, plain);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
if ((flags & GPGME_DECRYPT_VERIFY))
err = decrypt_verify_start (ctx, 0, flags, cipher, plain);
else
err = _gpgme_decrypt_start (ctx, 0, flags, cipher, plain);
return TRACE_ERR (err);
}
/* Decrypt ciphertext CIPHER within CTX and store the resulting
plaintext in PLAIN. */
gpgme_error_t
gpgme_op_decrypt_ext (gpgme_ctx_t ctx,
gpgme_decrypt_flags_t flags,
gpgme_data_t cipher,
gpgme_data_t plain)
{
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_ext", ctx,
"cipher=%p, plain=%p", cipher, plain);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
if ((flags & GPGME_DECRYPT_VERIFY))
err = decrypt_verify_start (ctx, 1, flags, cipher, plain);
else
err = _gpgme_decrypt_start (ctx, 1, flags, cipher, plain);
if (!err)
err = _gpgme_wait_one (ctx);
ctx->ignore_mdc_error = 0; /* Always reset. */
return TRACE_ERR (err);
}
diff --git a/tests/gpg/t-decrypt-verify.c b/tests/gpg/t-decrypt-verify.c
index 211f8129..424cc817 100644
--- a/tests/gpg/t-decrypt-verify.c
+++ b/tests/gpg/t-decrypt-verify.c
@@ -1,146 +1,177 @@
/* t-decrypt-verify.c - Regression test.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see .
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
/* We need to include config.h so that we know whether we are building
with large file system (LFS) support. */
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include "t-support.h"
+static const char normal_signed_message[] =
+"-----BEGIN PGP MESSAGE-----\n"
+"\n"
+"owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
+"GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
+"y1kvP4y+8D5a11ang0udywsA\n"
+"=Crq6\n"
+"-----END PGP MESSAGE-----\n";
+
+
static void
check_verify_result (gpgme_verify_result_t result, unsigned int summary,
const char *fpr, gpgme_error_t status, int validity)
{
gpgme_signature_t sig;
sig = result->signatures;
if (!sig || sig->next)
{
fprintf (stderr, "%s:%i: Unexpected number of signatures\n",
__FILE__, __LINE__);
exit (1);
}
if (sig->summary != summary)
{
fprintf (stderr, "%s:%i: Unexpected signature summary: 0x%x\n",
__FILE__, __LINE__, sig->summary);
exit (1);
}
if (strcmp (sig->fpr, fpr))
{
fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n",
__FILE__, __LINE__, sig->fpr);
exit (1);
}
if (gpgme_err_code (sig->status) != status)
{
fprintf (stderr, "%s:%i: Unexpected signature status: %s\n",
__FILE__, __LINE__, gpgme_strerror (sig->status));
exit (1);
}
if (sig->notations)
{
fprintf (stderr, "%s:%i: Unexpected notation data\n",
__FILE__, __LINE__);
exit (1);
}
if (sig->wrong_key_usage)
{
fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n",
__FILE__, __LINE__);
exit (1);
}
if (sig->validity != validity)
{
fprintf (stderr, "%s:%i: Unexpected validity: "
"want=%i have=%i\n",
__FILE__, __LINE__, validity, sig->validity);
exit (1);
}
if (gpgme_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR)
{
fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n",
__FILE__, __LINE__, gpgme_strerror (sig->validity_reason));
exit (1);
}
}
int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t in, out;
gpgme_decrypt_result_t decrypt_result;
gpgme_verify_result_t verify_result;
char *cipher_2_asc = make_filename ("cipher-2.asc");
char *agent_info;
(void)argc;
(void)argv;
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
fail_if_err (err);
agent_info = getenv("GPG_AGENT_INFO");
if (!(agent_info && strchr (agent_info, ':')))
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
err = gpgme_data_new_from_file (&in, cipher_2_asc, 1);
free (cipher_2_asc);
fail_if_err (err);
err = gpgme_data_new (&out);
fail_if_err (err);
err = gpgme_op_decrypt_verify (ctx, in, out);
fail_if_err (err);
decrypt_result = gpgme_op_decrypt_result (ctx);
if (decrypt_result->unsupported_algorithm)
{
fprintf (stderr, "%s:%i: unsupported algorithm: %s\n",
__FILE__, __LINE__, decrypt_result->unsupported_algorithm);
exit (1);
}
print_data (out);
verify_result = gpgme_op_verify_result (ctx);
check_verify_result (verify_result, GPGME_SIGSUM_VALID|GPGME_SIGSUM_GREEN,
"A0FF4590BB6122EDEF6E3C542D727CC768697734",
GPG_ERR_NO_ERROR, GPGME_VALIDITY_FULL);
gpgme_data_release (in);
gpgme_data_release (out);
+
+ /* Checking a signed, but not encrypted message. */
+ err = gpgme_data_new_from_mem (&in, normal_signed_message, strlen (normal_signed_message), 0);
+ fail_if_err (err);
+ err = gpgme_data_new (&out);
+ fail_if_err (err);
+ err = gpgme_op_decrypt_verify (ctx, in, out);
+ /* should have returned "no data" because the message is not encrypted */
+ if (gpgme_err_code (err) != GPG_ERR_NO_DATA)
+ {
+ fprintf (stderr, "%s:%i: Unexpected result of gpgme_op_decrypt_verify: %s\n",
+ __FILE__, __LINE__, gpgme_strerror (err));
+ }
+ verify_result = gpgme_op_verify_result (ctx);
+ check_verify_result (verify_result, GPGME_SIGSUM_VALID|GPGME_SIGSUM_GREEN,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ GPG_ERR_NO_ERROR, GPGME_VALIDITY_FULL);
+
+ gpgme_data_release (in);
+ gpgme_data_release (out);
+
gpgme_release (ctx);
return 0;
}