Blame SOURCES/0001-Validate-that-gpgme_op_verify_result-returned-at-lea.patch

92fc95
From 839b89f45a38b2373bf5836337a33f450aaab72e Mon Sep 17 00:00:00 2001
92fc95
From: Richard Hughes <richard@hughsie.com>
92fc95
Date: Thu, 28 May 2020 10:41:23 +0100
92fc95
Subject: [PATCH] Validate that gpgme_op_verify_result() returned at least one
92fc95
 signature
92fc95
92fc95
If a detached signature is actually a PGP message, gpgme_op_verify() returns
92fc95
the rather perplexing GPG_ERR_NO_ERROR, and then gpgme_op_verify_result()
92fc95
builds an empty list.
92fc95
92fc95
Explicitly check for no signatures present to avoid returning a JcatResult with
92fc95
no timestamp and an empty authority.
92fc95
92fc95
Many thanks to Justin Steven <justin@justinsteven.com> for the discovery and
92fc95
coordinated disclosure of this issue. Fixes CVE-2020-10759
92fc95
---
92fc95
 libjcat/jcat-gpg-engine.c |  7 +++++
92fc95
 libjcat/jcat-self-test.c  | 55 +++++++++++++++++++++++++++++++++++++++
92fc95
 2 files changed, 62 insertions(+)
92fc95
92fc95
diff --git libjcat/jcat-gpg-engine.c libjcat/jcat-gpg-engine.c
92fc95
index 0812a62..bd44dba 100644
92fc95
--- libjcat/jcat-gpg-engine.c
92fc95
+++ libjcat/jcat-gpg-engine.c
92fc95
@@ -267,6 +267,13 @@ jcat_gpg_engine_pubkey_verify (JcatEngine *engine,
92fc95
 				     "no result record from libgpgme");
92fc95
 		return NULL;
92fc95
 	}
92fc95
+	if (result->signatures == NULL) {
92fc95
+		g_set_error_literal (error,
92fc95
+				     G_IO_ERROR,
92fc95
+				     G_IO_ERROR_FAILED,
92fc95
+				     "no signatures from libgpgme");
92fc95
+		return NULL;
92fc95
+	}
92fc95
 
92fc95
 	/* look at each signature */
92fc95
 	for (s = result->signatures; s != NULL ; s = s->next ) {
92fc95
diff --git libjcat/jcat-self-test.c libjcat/jcat-self-test.c
92fc95
index d79a3a9..fd4295e 100644
92fc95
--- libjcat/jcat-self-test.c
92fc95
+++ libjcat/jcat-self-test.c
92fc95
@@ -393,6 +393,60 @@ jcat_gpg_engine_func (void)
92fc95
 #endif
92fc95
 }
92fc95
 
92fc95
+static void
92fc95
+jcat_gpg_engine_msg_func (void)
92fc95
+{
92fc95
+#ifdef ENABLE_GPG
92fc95
+	g_autofree gchar *fn = NULL;
92fc95
+	g_autofree gchar *pki_dir = NULL;
92fc95
+	g_autoptr(GBytes) data = NULL;
92fc95
+	g_autoptr(GBytes) data_sig = NULL;
92fc95
+	g_autoptr(GError) error = NULL;
92fc95
+	g_autoptr(JcatContext) context = jcat_context_new ();
92fc95
+	g_autoptr(JcatEngine) engine = NULL;
92fc95
+	g_autoptr(JcatResult) result = NULL;
92fc95
+	const gchar *sig =
92fc95
+	"-----BEGIN PGP MESSAGE-----\n"
92fc95
+	"owGbwMvMwMEovmZX76/pfOKMp0WSGOLOX3/ikZqTk6+jUJ5flJOiyNXJaMzCwMjB\n"
92fc95
+	"ICumyCJmt5VRUil28/1+z1cwbaxMID0MXJwCMJG4RxwMLUYXDkUad34I3vrT8+X2\n"
92fc95
+	"m+ZyHyMWnTiQYaQb/eLJGqbiAJc5Jr4a/PPqHNi7auwzGsKsljebabjtnJRzpDr0\n"
92fc95
+	"YvwrnmmWLJUnTzjM3MH5Kn+RzqXkywsYdk9yD2OUdLy736CiemFMdcuF02lOZvPU\n"
92fc95
+	"HaTKl76wW62QH8Lr8yGMQ1Xgc6nC2ZwUhvctky7NOZtc1T477uBTL81p31ZmaIUJ\n"
92fc95
+	"paS8uWZl8UzX5sFsqQi37G1TbDc8Cm+oU/yRkFj2pLBzw367ncsa4n7EqEWu1yrN\n"
92fc95
+	"yD39LUeErePdqfKCG+xhL6WkWt5ZJ/6//XnjouXhl5Z4tWspT49MtNp5d3aDQ43c\n"
92fc95
+	"mnbresn6A7KMZgdOiwIA\n"
92fc95
+	"=a9ui\n"
92fc95
+	"-----END PGP MESSAGE-----\n";
92fc95
+
92fc95
+	/* set up context */
92fc95
+	jcat_context_set_keyring_path (context, "/tmp/libjcat-self-test/var");
92fc95
+	pki_dir = g_test_build_filename (G_TEST_DIST, "pki", NULL);
92fc95
+	jcat_context_add_public_keys (context, pki_dir);
92fc95
+
92fc95
+	/* get engine */
92fc95
+	engine = jcat_context_get_engine (context, JCAT_BLOB_KIND_GPG, &error);
92fc95
+	g_assert_no_error (error);
92fc95
+	g_assert_nonnull (engine);
92fc95
+	g_assert_cmpint (jcat_engine_get_kind (engine), ==, JCAT_BLOB_KIND_GPG);
92fc95
+	g_assert_cmpint (jcat_engine_get_verify_kind (engine), ==, JCAT_ENGINE_VERIFY_KIND_SIGNATURE);
92fc95
+
92fc95
+	/* verify with GnuPG, which should fail as the signature is not a
92fc95
+	 * detached signature at all, but gnupg stabs us in the back by returning
92fc95
+	 * success from gpgme_op_verify() with an empty list of signatures */
92fc95
+	fn = g_test_build_filename (G_TEST_DIST, "colorhug", "firmware.bin", NULL);
92fc95
+	data = jcat_get_contents_bytes (fn, &error);
92fc95
+	g_assert_no_error (error);
92fc95
+	g_assert_nonnull (data);
92fc95
+	data_sig = g_bytes_new_static (sig, strlen (sig));
92fc95
+	result = jcat_engine_pubkey_verify (engine, data, data_sig,
92fc95
+					    JCAT_VERIFY_FLAG_NONE, &error);
92fc95
+	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
92fc95
+	g_assert_null (result);
92fc95
+#else
92fc95
+	g_test_skip ("no GnuPG support enabled");
92fc95
+#endif
92fc95
+}
92fc95
+
92fc95
 static void
92fc95
 jcat_pkcs7_engine_func (void)
92fc95
 {
92fc95
@@ -753,6 +807,7 @@ main (int argc, char **argv)
92fc95
 	g_test_add_func ("/jcat/engine{sha1}", jcat_sha1_engine_func);
92fc95
 	g_test_add_func ("/jcat/engine{sha256}", jcat_sha256_engine_func);
92fc95
 	g_test_add_func ("/jcat/engine{gpg}", jcat_gpg_engine_func);
92fc95
+	g_test_add_func ("/jcat/engine{gpg-msg}", jcat_gpg_engine_msg_func);
92fc95
 	g_test_add_func ("/jcat/engine{pkcs7}", jcat_pkcs7_engine_func);
92fc95
 	g_test_add_func ("/jcat/engine{pkcs7-self-signed}", jcat_pkcs7_engine_self_signed_func);
92fc95
 	g_test_add_func ("/jcat/context{verify-blob}", jcat_context_verify_blob_func);
92fc95
-- 
92fc95
2.26.2
92fc95