diff --git a/contrib/ci/Dockerfile-fedora.in b/contrib/ci/Dockerfile-fedora.in
index b8e18b6ec..1fd649824 100644
--- a/contrib/ci/Dockerfile-fedora.in
+++ b/contrib/ci/Dockerfile-fedora.in
@@ -6,6 +6,7 @@ ENV LC_ALL en_US.UTF-8
RUN echo fubar > /etc/machine-id
RUN dnf -y update
RUN echo fubar > /etc/machine-id
+RUN dnf -y install https://kojipkgs.fedoraproject.org//packages/libjcat/0.1.0/1.fc31/x86_64/libjcat-0.1.0-1.fc31.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/libjcat/0.1.0/1.fc31/x86_64/libjcat-devel-0.1.0-1.fc31.x86_64.rpm
%%%INSTALL_DEPENDENCIES_COMMAND%%%
RUN dnf -y update glib2 glib2-devel --releasever=32
RUN mkdir /build
diff --git a/contrib/ci/build_windows.sh b/contrib/ci/build_windows.sh
index 96e8a71f9..8821d03ae 100755
--- a/contrib/ci/build_windows.sh
+++ b/contrib/ci/build_windows.sh
@@ -15,7 +15,6 @@ meson .. \
--libexecdir=$target \
--bindir=$target \
-Dbuild=standalone \
- -Dgpg=false \
-Dplugin_coreboot=false \
-Dplugin_flashrom=false \
-Dplugin_uefi=false \
@@ -38,6 +37,9 @@ meson .. \
-Dgcab:tests=false \
-Dlibxmlb:introspection=false \
-Dlibxmlb:gtkdoc=false \
+ -Dlibjcat:man=false \
+ -Dlibjcat:gpg=false \
+ -Dlibjcat:introspection=false \
-Dgudev=false $@
ninja -v
diff --git a/contrib/ci/debian.sh b/contrib/ci/debian.sh
index 7d50eeff3..b7f62429a 100755
--- a/contrib/ci/debian.sh
+++ b/contrib/ci/debian.sh
@@ -44,6 +44,8 @@ lintian ../*changes \
--suppress-tags no-symbols-control-file \
--suppress-tags gzip-file-is-not-multi-arch-same-safe \
--suppress-tags binary-is-wrong-architecture \
+ --suppress-tags missing-dependency-on-libc \
+ --suppress-tags arch-dependent-file-not-in-arch-specific-directory \
--allow-root
#if invoked outside of CI
diff --git a/contrib/ci/dependencies.xml b/contrib/ci/dependencies.xml
index 220b7a5a5..4c5b43375 100644
--- a/contrib/ci/dependencies.xml
+++ b/contrib/ci/dependencies.xml
@@ -633,6 +633,11 @@
+
+
+ libjcat-devel
+
+
libarchive-devel
diff --git a/contrib/debian/rules b/contrib/debian/rules
index d362fcd21..6a0a002ec 100755
--- a/contrib/debian/rules
+++ b/contrib/debian/rules
@@ -46,6 +46,9 @@ override_dh_auto_configure:
else \
export UEFI="-Dplugin_uefi=false -Dplugin_redfish=false -Dplugin_nvme=false"; \
fi; \
+ if [ ! -z "$$CI" ]; then \
+ export CI="-Dlibjcat:introspection=false $$CI"; \
+ fi; \
dh_auto_configure -- $$UEFI $$DELL $$FLASHROM $$CI -Dplugin_dummy=true -Dgtkdoc=true
override_dh_install:
@@ -56,6 +59,16 @@ override_dh_install:
if [ -d debian/tmp/usr/libexec/fwupd/efi/ ]; then \
dh_install -pfwupd usr/libexec/fwupd/efi ;\
fi
+ #libjcat built as a subproject for CI
+ if [ ! -z "$$CI" ]; then \
+ dh_install -plibfwupd-dev usr/include/libjcat-1; \
+ dh_install -plibfwupd2 usr/lib/*/libjcat.so.*; \
+ dh_install -plibfwupd-dev usr/lib/*/libjcat.so; \
+ dh_install -plibfwupd-dev usr/lib/*/pkgconfig/jcat.pc; \
+ dh_install -plibfwupd-dev usr/libexec/jcat-tool; \
+ dh_install -plibfwupd-dev usr/share/gir-1.0/Jcat*; \
+ dh_install -pfwupd-tests usr/libexec/installed-tests/libjcat; \
+ fi
dh_missing -a --fail-missing
#this is placed in fwupd-tests
diff --git a/contrib/setup-win32.nsi b/contrib/setup-win32.nsi
index 876b5efea..59a0c655e 100644
--- a/contrib/setup-win32.nsi
+++ b/contrib/setup-win32.nsi
@@ -60,11 +60,13 @@ Section "fwupd"
# fwupd
File "dfu-tool.exe"
+ File "jcat-tool.exe"
File "fwupdtool.exe"
File "libfwupd-2.dll"
File "libfwupdplugin-1.dll"
File "libgcab-1.0-0.dll"
File "libxmlb-1.dll"
+ File "libjcat-1.dll"
SetOutPath "$INSTDIR\fwupd-plugins-3"
File /r "fwupd-plugins-3/libfu_plugin_*.dll"
SetOutPath "$INSTDIR\etc\fwupd"
diff --git a/data/pki/meson.build b/data/pki/meson.build
index eefcc9142..94bb0b6f1 100644
--- a/data/pki/meson.build
+++ b/data/pki/meson.build
@@ -1,30 +1,26 @@
-if get_option('gpg')
- install_data([
- 'GPG-KEY-Hughski-Limited',
- 'GPG-KEY-Linux-Foundation-Firmware',
- 'GPG-KEY-Linux-Vendor-Firmware-Service',
- ],
- install_dir : join_paths(sysconfdir, 'pki', 'fwupd')
- )
+install_data([
+ 'GPG-KEY-Hughski-Limited',
+ 'GPG-KEY-Linux-Foundation-Firmware',
+ 'GPG-KEY-Linux-Vendor-Firmware-Service',
+ ],
+ install_dir : join_paths(sysconfdir, 'pki', 'fwupd')
+)
- install_data([
- 'GPG-KEY-Linux-Foundation-Metadata',
- 'GPG-KEY-Linux-Vendor-Firmware-Service',
- ],
- install_dir : join_paths(sysconfdir, 'pki', 'fwupd-metadata')
- )
-endif
+install_data([
+ 'GPG-KEY-Linux-Foundation-Metadata',
+ 'GPG-KEY-Linux-Vendor-Firmware-Service',
+ ],
+ install_dir : join_paths(sysconfdir, 'pki', 'fwupd-metadata')
+)
-if get_option('pkcs7')
- install_data([
- 'LVFS-CA.pem',
- ],
- install_dir : join_paths(sysconfdir, 'pki', 'fwupd')
- )
- install_data([
- 'LVFS-CA.pem',
- ],
- install_dir : join_paths(sysconfdir, 'pki', 'fwupd-metadata')
- )
-endif
+install_data([
+ 'LVFS-CA.pem',
+ ],
+ install_dir : join_paths(sysconfdir, 'pki', 'fwupd')
+)
+install_data([
+ 'LVFS-CA.pem',
+ ],
+ install_dir : join_paths(sysconfdir, 'pki', 'fwupd-metadata')
+)
diff --git a/data/remotes.d/lvfs-testing.conf b/data/remotes.d/lvfs-testing.conf
index bbd747301..740a793e8 100644
--- a/data/remotes.d/lvfs-testing.conf
+++ b/data/remotes.d/lvfs-testing.conf
@@ -3,7 +3,6 @@
# this remote provides metadata and firmware marked as 'testing' from the LVFS
Enabled=false
Title=Linux Vendor Firmware Service (testing)
-Keyring=gpg
MetadataURI=https://cdn.fwupd.org/downloads/firmware-testing.xml.gz
ReportURI=https://fwupd.org/lvfs/firmware/report
Username=
diff --git a/data/remotes.d/lvfs.conf b/data/remotes.d/lvfs.conf
index 047f94259..1249ef746 100644
--- a/data/remotes.d/lvfs.conf
+++ b/data/remotes.d/lvfs.conf
@@ -3,7 +3,6 @@
# this remote provides metadata and firmware marked as 'stable' from the LVFS
Enabled=true
Title=Linux Vendor Firmware Service
-Keyring=gpg
MetadataURI=https://cdn.fwupd.org/downloads/firmware.xml.gz
ReportURI=https://fwupd.org/lvfs/firmware/report
OrderBefore=fwupd
diff --git a/data/tests/colorhug/meson.build b/data/tests/colorhug/meson.build
index 7454c9fa2..5d70f8172 100644
--- a/data/tests/colorhug/meson.build
+++ b/data/tests/colorhug/meson.build
@@ -9,17 +9,3 @@ colorhug_test_firmware = custom_target('colorhug-test-firmware',
gcab, '--create', '--nopath', '@OUTPUT@', '@INPUT@',
],
)
-
-if get_option('pkcs7')
- # generate self-signed detached signature
- colorhug_pkcs7_signature = custom_target('firmware.bin.p7c',
- input: 'firmware.bin',
- output: 'firmware.bin.p7c',
- command: [certtool, '--p7-detached-sign',
- '--p7-time',
- '--load-privkey', pkcs7_privkey,
- '--load-certificate', pkcs7_certificate,
- '--infile', '@INPUT@',
- '--outfile', '@OUTPUT@'],
- )
-endif
diff --git a/data/tests/meson.build b/data/tests/meson.build
index 63c35c62d..a1d0445ec 100644
--- a/data/tests/meson.build
+++ b/data/tests/meson.build
@@ -1,12 +1,4 @@
-# generate private PKCS7 key
-certtool = find_program('certtool')
-pkcs7_privkey = custom_target('test-privkey.pem',
- output: 'test-privkey.pem',
- command: [certtool, '--generate-privkey', '--outfile', '@OUTPUT@'],
-)
-
subdir('builder')
-subdir('pki')
subdir('colorhug')
subdir('missing-hwid')
subdir('multiple-rels')
diff --git a/data/tests/pki/GPG-KEY-Linux-Vendor-Firmware-Service b/data/tests/pki/GPG-KEY-Linux-Vendor-Firmware-Service
deleted file mode 120000
index 27abe4c04..000000000
--- a/data/tests/pki/GPG-KEY-Linux-Vendor-Firmware-Service
+++ /dev/null
@@ -1 +0,0 @@
-../../pki/GPG-KEY-Linux-Vendor-Firmware-Service
\ No newline at end of file
diff --git a/data/tests/pki/LVFS-CA.pem b/data/tests/pki/LVFS-CA.pem
deleted file mode 120000
index aa5594497..000000000
--- a/data/tests/pki/LVFS-CA.pem
+++ /dev/null
@@ -1 +0,0 @@
-../../pki/LVFS-CA.pem
\ No newline at end of file
diff --git a/data/tests/pki/meson.build b/data/tests/pki/meson.build
deleted file mode 100644
index f35f2a9ec..000000000
--- a/data/tests/pki/meson.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# generate certificate
-pkcs7_config = join_paths(meson.current_source_dir(), 'test.cfg')
-pkcs7_certificate = custom_target('test.pem',
- input: pkcs7_privkey,
- output: 'test.pem',
- command: [certtool, '--generate-self-signed',
- '--template', pkcs7_config,
- '--load-privkey', '@INPUT@',
- '--outfile', '@OUTPUT@'],
-)
diff --git a/data/tests/pki/test.cfg b/data/tests/pki/test.cfg
deleted file mode 100644
index a9422fb52..000000000
--- a/data/tests/pki/test.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-organization = "Hughski Limited"
-expiration_days = -1
-email = "info@hughski.com"
-signing_key
diff --git a/libfwupd/fwupd-enums.c b/libfwupd/fwupd-enums.c
index 789df10af..186dbed79 100644
--- a/libfwupd/fwupd-enums.c
+++ b/libfwupd/fwupd-enums.c
@@ -401,6 +401,8 @@ fwupd_keyring_kind_from_string (const gchar *keyring_kind)
return FWUPD_KEYRING_KIND_GPG;
if (g_strcmp0 (keyring_kind, "pkcs7") == 0)
return FWUPD_KEYRING_KIND_PKCS7;
+ if (g_strcmp0 (keyring_kind, "jcat") == 0)
+ return FWUPD_KEYRING_KIND_JCAT;
return FWUPD_KEYRING_KIND_UNKNOWN;
}
@@ -423,6 +425,8 @@ fwupd_keyring_kind_to_string (FwupdKeyringKind keyring_kind)
return "gpg";
if (keyring_kind == FWUPD_KEYRING_KIND_PKCS7)
return "pkcs7";
+ if (keyring_kind == FWUPD_KEYRING_KIND_JCAT)
+ return "jcat";
return NULL;
}
diff --git a/libfwupd/fwupd-enums.h b/libfwupd/fwupd-enums.h
index 9a8fa1115..7a5500277 100644
--- a/libfwupd/fwupd-enums.h
+++ b/libfwupd/fwupd-enums.h
@@ -232,6 +232,7 @@ typedef enum {
* @FWUPD_KEYRING_KIND_NONE: No verification
* @FWUPD_KEYRING_KIND_GPG: Verification using GPG
* @FWUPD_KEYRING_KIND_PKCS7: Verification using PKCS7
+ * @FWUPD_KEYRING_KIND_JCAT: Verification using Jcat
*
* The update state.
**/
@@ -240,6 +241,7 @@ typedef enum {
FWUPD_KEYRING_KIND_NONE, /* Since: 0.9.7 */
FWUPD_KEYRING_KIND_GPG, /* Since: 0.9.7 */
FWUPD_KEYRING_KIND_PKCS7, /* Since: 0.9.7 */
+ FWUPD_KEYRING_KIND_JCAT, /* Since: 1.4.0 */
/*< private >*/
FWUPD_KEYRING_KIND_LAST
} FwupdKeyringKind;
diff --git a/libfwupd/fwupd-remote.c b/libfwupd/fwupd-remote.c
index 08ad6d5d1..0edecc9cd 100644
--- a/libfwupd/fwupd-remote.c
+++ b/libfwupd/fwupd-remote.c
@@ -146,16 +146,6 @@ fwupd_remote_set_filename_source (FwupdRemote *self, const gchar *filename_sourc
priv->filename_source = g_strdup (filename_source);
}
-static const gchar *
-fwupd_remote_get_suffix_for_keyring_kind (FwupdKeyringKind keyring_kind)
-{
- if (keyring_kind == FWUPD_KEYRING_KIND_GPG)
- return ".asc";
- if (keyring_kind == FWUPD_KEYRING_KIND_PKCS7)
- return ".p7b";
- return NULL;
-}
-
static SoupURI *
fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error)
{
@@ -231,7 +221,6 @@ static void
fwupd_remote_set_metadata_uri (FwupdRemote *self, const gchar *metadata_uri)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
- const gchar *suffix;
g_autoptr(SoupURI) uri = NULL;
/* build the URI */
@@ -243,9 +232,8 @@ fwupd_remote_set_metadata_uri (FwupdRemote *self, const gchar *metadata_uri)
priv->metadata_uri = g_strdup (metadata_uri);
/* generate the signature URI too */
- suffix = fwupd_remote_get_suffix_for_keyring_kind (priv->keyring_kind);
- if (suffix != NULL)
- priv->metadata_uri_sig = g_strconcat (metadata_uri, suffix, NULL);
+ if (priv->keyring_kind == FWUPD_KEYRING_KIND_JCAT)
+ priv->metadata_uri_sig = g_strconcat (metadata_uri, ".jcat", NULL);
}
/* note, this has to be set after MetadataURI */
@@ -311,7 +299,6 @@ static void
fwupd_remote_set_filename_cache (FwupdRemote *self, const gchar *filename)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
- const gchar *suffix;
g_return_if_fail (FWUPD_IS_REMOTE (self));
@@ -319,10 +306,9 @@ fwupd_remote_set_filename_cache (FwupdRemote *self, const gchar *filename)
priv->filename_cache = g_strdup (filename);
/* create for all remote types */
- suffix = fwupd_remote_get_suffix_for_keyring_kind (priv->keyring_kind);
- if (suffix != NULL) {
+ if (priv->keyring_kind == FWUPD_KEYRING_KIND_JCAT) {
g_free (priv->filename_cache_sig);
- priv->filename_cache_sig = g_strconcat (filename, suffix, NULL);
+ priv->filename_cache_sig = g_strconcat (filename, ".jcat", NULL);
}
}
@@ -375,7 +361,7 @@ fwupd_remote_load_from_filename (FwupdRemote *self,
/* get verification type, falling back to GPG */
keyring_kind = g_key_file_get_string (kf, group, "Keyring", NULL);
if (keyring_kind == NULL) {
- priv->keyring_kind = FWUPD_KEYRING_KIND_GPG;
+ priv->keyring_kind = FWUPD_KEYRING_KIND_JCAT;
} else {
priv->keyring_kind = fwupd_keyring_kind_from_string (keyring_kind);
if (priv->keyring_kind == FWUPD_KEYRING_KIND_UNKNOWN) {
@@ -386,6 +372,11 @@ fwupd_remote_load_from_filename (FwupdRemote *self,
keyring_kind);
return FALSE;
}
+ if (priv->keyring_kind == FWUPD_KEYRING_KIND_GPG ||
+ priv->keyring_kind == FWUPD_KEYRING_KIND_PKCS7) {
+ g_debug ("converting Keyring value to Jcat");
+ priv->keyring_kind = FWUPD_KEYRING_KIND_JCAT;
+ }
}
/* all remotes need a URI, even if it's file:// to the cache */
diff --git a/libfwupd/fwupd-self-test.c b/libfwupd/fwupd-self-test.c
index b72460adb..2acac6ffe 100644
--- a/libfwupd/fwupd-self-test.c
+++ b/libfwupd/fwupd-self-test.c
@@ -168,14 +168,14 @@ fwupd_remote_download_func (void)
"lvfs",
"metadata.xml.gz",
NULL);
- expected_signature = g_strdup_printf ("%s.asc", expected_metadata);
+ expected_signature = g_strdup_printf ("%s.jcat", expected_metadata);
fwupd_remote_set_remotes_dir (remote, directory);
fn = g_build_filename (FU_SELF_TEST_REMOTES_DIR, "remotes.d", "lvfs.conf", NULL);
ret = fwupd_remote_load_from_filename (remote, fn, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpint (fwupd_remote_get_kind (remote), ==, FWUPD_REMOTE_KIND_DOWNLOAD);
- g_assert_cmpint (fwupd_remote_get_keyring_kind (remote), ==, FWUPD_KEYRING_KIND_GPG);
+ g_assert_cmpint (fwupd_remote_get_keyring_kind (remote), ==, FWUPD_KEYRING_KIND_JCAT);
g_assert_cmpint (fwupd_remote_get_priority (remote), ==, 0);
g_assert (fwupd_remote_get_enabled (remote));
g_assert (fwupd_remote_get_metadata_uri (remote) != NULL);
@@ -209,14 +209,14 @@ fwupd_remote_baseuri_func (void)
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpint (fwupd_remote_get_kind (remote), ==, FWUPD_REMOTE_KIND_DOWNLOAD);
- g_assert_cmpint (fwupd_remote_get_keyring_kind (remote), ==, FWUPD_KEYRING_KIND_GPG);
+ g_assert_cmpint (fwupd_remote_get_keyring_kind (remote), ==, FWUPD_KEYRING_KIND_JCAT);
g_assert_cmpint (fwupd_remote_get_priority (remote), ==, 0);
g_assert (fwupd_remote_get_enabled (remote));
g_assert_cmpstr (fwupd_remote_get_checksum (remote), ==, NULL);
g_assert_cmpstr (fwupd_remote_get_metadata_uri (remote), ==,
"https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz");
g_assert_cmpstr (fwupd_remote_get_metadata_uri_sig (remote), ==,
- "https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz.asc");
+ "https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz.jcat");
firmware_uri = fwupd_remote_build_firmware_uri (remote, "http://bbc.co.uk/firmware.cab", &error);
g_assert_no_error (error);
g_assert_cmpstr (firmware_uri, ==, "https://my.fancy.cdn/firmware.cab");
@@ -245,14 +245,14 @@ fwupd_remote_nopath_func (void)
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpint (fwupd_remote_get_kind (remote), ==, FWUPD_REMOTE_KIND_DOWNLOAD);
- g_assert_cmpint (fwupd_remote_get_keyring_kind (remote), ==, FWUPD_KEYRING_KIND_GPG);
+ g_assert_cmpint (fwupd_remote_get_keyring_kind (remote), ==, FWUPD_KEYRING_KIND_JCAT);
g_assert_cmpint (fwupd_remote_get_priority (remote), ==, 0);
g_assert (fwupd_remote_get_enabled (remote));
g_assert_cmpstr (fwupd_remote_get_checksum (remote), ==, NULL);
g_assert_cmpstr (fwupd_remote_get_metadata_uri (remote), ==,
"https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz");
g_assert_cmpstr (fwupd_remote_get_metadata_uri_sig (remote), ==,
- "https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz.asc");
+ "https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz.jcat");
firmware_uri = fwupd_remote_build_firmware_uri (remote, "firmware.cab", &error);
g_assert_no_error (error);
g_assert_cmpstr (firmware_uri, ==, "https://s3.amazonaws.com/lvfsbucket/downloads/firmware.cab");
diff --git a/libfwupdplugin/fu-cabinet.c b/libfwupdplugin/fu-cabinet.c
index 632981ed8..ef8fe2bc7 100644
--- a/libfwupdplugin/fu-cabinet.c
+++ b/libfwupdplugin/fu-cabinet.c
@@ -14,6 +14,7 @@
#include "fu-cabinet.h"
#include "fu-common.h"
+#include "fwupd-enums.h"
#include "fwupd-error.h"
struct _FuCabinet {
@@ -23,6 +24,8 @@ struct _FuCabinet {
gchar *container_checksum;
XbBuilder *builder;
XbSilo *silo;
+ JcatContext *jcat_context;
+ JcatFile *jcat_file;
};
G_DEFINE_TYPE (FuCabinet, fu_cabinet, G_TYPE_OBJECT)
@@ -37,6 +40,8 @@ fu_cabinet_finalize (GObject *obj)
g_object_unref (self->builder);
g_free (self->container_checksum);
g_object_unref (self->gcab_cabinet);
+ g_object_unref (self->jcat_context);
+ g_object_unref (self->jcat_file);
G_OBJECT_CLASS (fu_cabinet_parent_class)->finalize (obj);
}
@@ -53,6 +58,8 @@ fu_cabinet_init (FuCabinet *self)
self->size_max = 1024 * 1024 * 100;
self->gcab_cabinet = gcab_cabinet_new ();
self->builder = xb_builder_new ();
+ self->jcat_file = jcat_file_new ();
+ self->jcat_context = jcat_context_new ();
}
/**
@@ -71,6 +78,24 @@ fu_cabinet_set_size_max (FuCabinet *self, guint64 size_max)
self->size_max = size_max;
}
+/**
+ * fu_cabinet_set_jcat_context: (skip):
+ * @self: A #FuCabinet
+ * @jcat_context: (nullable): A #JcatContext
+ *
+ * Sets the Jcat context, which is used for setting the trust flags on the
+ * each release in the archive.
+ *
+ * Since: 1.4.0
+ **/
+void
+fu_cabinet_set_jcat_context (FuCabinet *self, JcatContext *jcat_context)
+{
+ g_return_if_fail (FU_IS_CABINET (self));
+ g_return_if_fail (JCAT_IS_CONTEXT (jcat_context));
+ g_set_object (&self->jcat_context, jcat_context);
+}
+
/**
* fu_cabinet_get_silo: (skip):
* @self: A #FuCabinet
@@ -111,11 +136,18 @@ fu_cabinet_parse_release (FuCabinet *self, XbNode *release, GError **error)
GCabFile *cabfile;
GBytes *blob;
const gchar *csum_filename = NULL;
- const gchar *suffixes[] = { "asc", "p7b", "p7c", NULL };
g_autofree gchar *basename = NULL;
- g_autofree gchar *release_key = NULL;
g_autoptr(XbNode) csum_tmp = NULL;
+ g_autoptr(XbNode) metadata_trust = NULL;
g_autoptr(XbNode) nsize = NULL;
+ g_autoptr(JcatItem) item = NULL;
+ g_autoptr(GBytes) release_flags_blob = NULL;
+ FwupdReleaseFlags release_flags = FWUPD_RELEASE_FLAG_NONE;
+
+ /* we set this with XbBuilderSource before the silo was created */
+ metadata_trust = xb_node_query_first (release, "../../info/metadata_trust", NULL);
+ if (metadata_trust != NULL)
+ release_flags |= FWUPD_RELEASE_FLAG_TRUSTED_METADATA;
/* ensure we always have a content checksum */
csum_tmp = xb_node_query_first (release, "checksum[@target='content']", NULL);
@@ -148,8 +180,7 @@ fu_cabinet_parse_release (FuCabinet *self, XbNode *release, GError **error)
}
/* set the blob */
- release_key = g_strdup_printf ("fwupd::ReleaseBlob(%s)", basename);
- xb_node_set_data (release, release_key, blob);
+ xb_node_set_data (release, "fwupd::FirmwareBlob", blob);
/* set as metadata if unset, but error if specified and incorrect */
nsize = xb_node_query_first (release, "size[@type='installed']", NULL);
@@ -185,15 +216,38 @@ fu_cabinet_parse_release (FuCabinet *self, XbNode *release, GError **error)
}
}
- /* if the signing file exists, set that too */
- for (guint i = 0; suffixes[i] != NULL; i++) {
+ /* find out if the payload is signed, falling back to detached */
+ item = jcat_file_get_item_by_id (self->jcat_file, basename, NULL);
+ if (item != NULL) {
+ g_autoptr(GError) error_local = NULL;
+ g_autoptr(GPtrArray) results = NULL;
+ results = jcat_context_verify_item (self->jcat_context,
+ blob, item,
+ JCAT_VERIFY_FLAG_REQUIRE_CHECKSUM |
+ JCAT_VERIFY_FLAG_REQUIRE_SIGNATURE,
+ &error_local);
+ if (results == NULL) {
+ g_debug ("failed to verify payload %s: %s",
+ basename, error_local->message);
+ } else {
+ g_debug ("verified payload %s: %u",
+ basename, results->len);
+ release_flags |= FWUPD_RELEASE_FLAG_TRUSTED_PAYLOAD;
+ }
+
+ /* legacy GPG detached signature */
+ } else {
g_autofree gchar *basename_sig = NULL;
- basename_sig = g_strdup_printf ("%s.%s", basename, suffixes[i]);
+ basename_sig = g_strdup_printf ("%s.asc", basename);
cabfile = fu_cabinet_get_file_by_name (self, basename_sig);
if (cabfile != NULL) {
- g_autofree gchar *release_key_sig = NULL;
- blob = gcab_file_get_bytes (cabfile);
- if (blob == NULL) {
+ GBytes *data_sig;
+ g_autoptr(JcatResult) jcat_result = NULL;
+ g_autoptr(JcatBlob) jcat_blob = NULL;
+ g_autoptr(GError) error_local = NULL;
+
+ data_sig = gcab_file_get_bytes (cabfile);
+ if (data_sig == NULL) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
@@ -201,12 +255,25 @@ fu_cabinet_parse_release (FuCabinet *self, XbNode *release, GError **error)
basename_sig);
return FALSE;
}
- release_key_sig = g_strdup_printf ("fwupd::ReleaseBlob(%s)",
- basename_sig);
- xb_node_set_data (release, release_key_sig, blob);
+ jcat_blob = jcat_blob_new (JCAT_BLOB_KIND_GPG, data_sig);
+ jcat_result = jcat_context_verify_blob (self->jcat_context,
+ blob, jcat_blob,
+ JCAT_VERIFY_FLAG_REQUIRE_SIGNATURE,
+ &error_local);
+ if (jcat_result == NULL) {
+ g_debug ("failed to verify payload %s using detached: %s",
+ basename, error_local->message);
+ } else {
+ g_debug ("verified payload %s using detached", basename);
+ release_flags |= FWUPD_RELEASE_FLAG_TRUSTED_PAYLOAD;
+ }
}
}
+ /* this means we can get the data from fu_keyring_get_release_flags */
+ release_flags_blob = g_bytes_new (&release_flags, sizeof(release_flags));
+ xb_node_set_data (release, "fwupd::ReleaseFlags", release_flags_blob);
+
/* success */
return TRUE;
}
@@ -283,11 +350,22 @@ fu_cabinet_set_container_checksum_cb (XbBuilderFixup *builder_fixup,
/* adds each GCabFile to the silo */
static gboolean
-fu_cabinet_build_silo_file (FuCabinet *self, GCabFile *cabfile, GError **error)
+fu_cabinet_build_silo_file (FuCabinet *self,
+ GCabFile *cabfile,
+ FwupdReleaseFlags release_flags,
+ GError **error)
{
GBytes *blob;
g_autoptr(GError) error_local = NULL;
g_autoptr(XbBuilderSource) source = xb_builder_source_new ();
+ g_autoptr(XbBuilderNode) bn_info = xb_builder_node_new ("info");
+
+ /* indicate the metainfo file was signed */
+ if (release_flags & FWUPD_RELEASE_FLAG_TRUSTED_METADATA) {
+ g_autoptr(XbBuilderNode) bn_trust = NULL;
+ xb_builder_node_insert (bn_info, "metadata_trust", NULL);
+ }
+ xb_builder_source_set_info (source, bn_info);
/* rewrite to be under a components root */
xb_builder_source_set_prefix (source, "components");
@@ -318,6 +396,71 @@ fu_cabinet_build_silo_file (FuCabinet *self, GCabFile *cabfile, GError **error)
return TRUE;
}
+static gboolean
+fu_cabinet_build_silo_metainfo (FuCabinet *self, GCabFile *cabfile, GError **error)
+{
+ FwupdReleaseFlags release_flags = FWUPD_RELEASE_FLAG_NONE;
+ const gchar *fn = gcab_file_get_extract_name (cabfile);
+ g_autoptr(JcatItem) item = NULL;
+
+ /* validate against the Jcat file */
+ item = jcat_file_get_item_by_id (self->jcat_file, fn, NULL);
+ if (item == NULL) {
+ g_debug ("failed to verify %s: no JcatItem", fn);
+ } else {
+ g_autoptr(GError) error_local = NULL;
+ g_autoptr(GPtrArray) results = NULL;
+ results = jcat_context_verify_item (self->jcat_context,
+ gcab_file_get_bytes (cabfile),
+ item,
+ JCAT_VERIFY_FLAG_REQUIRE_CHECKSUM |
+ JCAT_VERIFY_FLAG_REQUIRE_SIGNATURE,
+ &error_local);
+ if (results == NULL) {
+ g_debug ("failed to verify %s: %s",
+ fn, error_local->message);
+ } else {
+ g_debug ("verified metadata %s: %u",
+ fn, results->len);
+ release_flags |= FWUPD_RELEASE_FLAG_TRUSTED_METADATA;
+ }
+ }
+
+ /* actually parse the XML now */
+ g_debug ("processing file: %s", fn);
+ if (!fu_cabinet_build_silo_file (self, cabfile, release_flags, error)) {
+ g_prefix_error (error, "%s could not be loaded: ",
+ gcab_file_get_extract_name (cabfile));
+ return FALSE;
+ }
+
+ /* success */
+ return TRUE;
+}
+
+/* load the firmware.jcat files if included */
+static gboolean
+fu_cabinet_build_jcat_folder (FuCabinet *self, GCabFolder *cabfolder, GError **error)
+{
+ g_autoptr(GSList) cabfiles = gcab_folder_get_files (cabfolder);
+ for (GSList *l = cabfiles; l != NULL; l = l->next) {
+ GCabFile *cabfile = GCAB_FILE (l->data);
+ const gchar *fn = gcab_file_get_extract_name (cabfile);
+ if (g_str_has_suffix (fn, ".jcat")) {
+ GBytes *data_jcat = gcab_file_get_bytes (cabfile);
+ g_autoptr(GInputStream) istream = NULL;
+ istream = g_memory_input_stream_new_from_bytes (data_jcat);
+ if (!jcat_file_import_stream (self->jcat_file,
+ istream,
+ JCAT_IMPORT_FLAG_NONE,
+ NULL,
+ error))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
/* adds each GCabFolder to the silo */
static gboolean
fu_cabinet_build_silo_folder (FuCabinet *self, GCabFolder *cabfolder, GError **error)
@@ -326,14 +469,10 @@ fu_cabinet_build_silo_folder (FuCabinet *self, GCabFolder *cabfolder, GError **e
for (GSList *l = cabfiles; l != NULL; l = l->next) {
GCabFile *cabfile = GCAB_FILE (l->data);
const gchar *fn = gcab_file_get_extract_name (cabfile);
- g_debug ("processing file: %s", fn);
- if (g_str_has_suffix (fn, ".metainfo.xml")) {
- if (!fu_cabinet_build_silo_file (self, cabfile, error)) {
- g_prefix_error (error, "%s could not be loaded: ",
- gcab_file_get_extract_name (cabfile));
- return FALSE;
- }
- }
+ if (!g_str_has_suffix (fn, ".metainfo.xml"))
+ continue;
+ if (!fu_cabinet_build_silo_metainfo (self, cabfile, error))
+ return FALSE;
}
return TRUE;
}
@@ -352,8 +491,17 @@ fu_cabinet_build_silo (FuCabinet *self, GBytes *data, GError **error)
XB_SILO_PROFILE_FLAG_DEBUG);
}
- /* look at each folder */
+ /* load Jcat */
folders = gcab_cabinet_get_folders (self->gcab_cabinet);
+ if (self->jcat_context != NULL) {
+ for (guint i = 0; i < folders->len; i++) {
+ GCabFolder *cabfolder = GCAB_FOLDER (g_ptr_array_index (folders, i));
+ if (!fu_cabinet_build_jcat_folder (self, cabfolder, error))
+ return FALSE;
+ }
+ }
+
+ /* adds each metainfo file to the silo */
for (guint i = 0; i < folders->len; i++) {
GCabFolder *cabfolder = GCAB_FOLDER (g_ptr_array_index (folders, i));
g_debug ("processing folder: %u/%u", i + 1, folders->len);
diff --git a/libfwupdplugin/fu-cabinet.h b/libfwupdplugin/fu-cabinet.h
index e340e6901..de26741ec 100644
--- a/libfwupdplugin/fu-cabinet.h
+++ b/libfwupdplugin/fu-cabinet.h
@@ -8,6 +8,7 @@
#include
#include
+#include
#define FU_TYPE_CABINET (fu_cabinet_get_type ())
@@ -28,6 +29,8 @@ typedef enum {
FuCabinet *fu_cabinet_new (void);
void fu_cabinet_set_size_max (FuCabinet *self,
guint64 size_max);
+void fu_cabinet_set_jcat_context (FuCabinet *self,
+ JcatContext *jcat_context);
gboolean fu_cabinet_parse (FuCabinet *self,
GBytes *data,
FuCabinetParseFlags flags,
diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c
index 80b4ec73d..60b4b18c6 100644
--- a/libfwupdplugin/fu-self-test.c
+++ b/libfwupdplugin/fu-self-test.c
@@ -746,9 +746,7 @@ fu_common_store_cab_func (void)
csum = xb_node_query_first (rel, "checksum[@target='content']", &error);
g_assert_nonnull (csum);
g_assert_cmpstr (xb_node_get_text (csum), ==, "7c211433f02071597741e6ff5a8ea34789abbf43");
- blob_tmp = xb_node_get_data (rel, "fwupd::ReleaseBlob(firmware.dfu)");
- g_assert_nonnull (blob_tmp);
- blob_tmp = xb_node_get_data (rel, "fwupd::ReleaseBlob(firmware.dfu.asc)");
+ blob_tmp = xb_node_get_data (rel, "fwupd::FirmwareBlob");
g_assert_nonnull (blob_tmp);
req = xb_node_query_first (component, "requires/id", &error);
g_assert_no_error (error);
@@ -791,10 +789,8 @@ fu_common_store_cab_unsigned_func (void)
g_assert_cmpstr (xb_node_get_attr (rel, "version"), ==, "1.2.3");
csum = xb_node_query_first (rel, "checksum[@target='content']", &error);
g_assert_null (csum);
- blob_tmp = xb_node_get_data (rel, "fwupd::ReleaseBlob(firmware.bin)");
+ blob_tmp = xb_node_get_data (rel, "fwupd::FirmwareBlob");
g_assert_nonnull (blob_tmp);
- blob_tmp = xb_node_get_data (rel, "fwupd::ReleaseBlob(firmware.bin.asc)");
- g_assert_null (blob_tmp);
}
static void
@@ -830,7 +826,7 @@ fu_common_store_cab_folder_func (void)
g_assert_no_error (error);
g_assert_nonnull (rel);
g_assert_cmpstr (xb_node_get_attr (rel, "version"), ==, "1.2.3");
- blob_tmp = xb_node_get_data (rel, "fwupd::ReleaseBlob(firmware.bin)");
+ blob_tmp = xb_node_get_data (rel, "fwupd::FirmwareBlob");
g_assert_nonnull (blob_tmp);
}
diff --git a/libfwupdplugin/fwupdplugin.map b/libfwupdplugin/fwupdplugin.map
index d140668b8..c07c419e2 100644
--- a/libfwupdplugin/fwupdplugin.map
+++ b/libfwupdplugin/fwupdplugin.map
@@ -544,6 +544,7 @@ LIBFWUPDPLUGIN_1.4.0 {
fu_cabinet_get_type;
fu_cabinet_new;
fu_cabinet_parse;
+ fu_cabinet_set_jcat_context;
fu_cabinet_set_size_max;
fu_device_get_root;
fu_device_set_version_bootloader;
diff --git a/libfwupdplugin/meson.build b/libfwupdplugin/meson.build
index b73e6325d..40b59668a 100644
--- a/libfwupdplugin/meson.build
+++ b/libfwupdplugin/meson.build
@@ -79,6 +79,7 @@ fwupdplugin_headers_private = [
introspection_deps = [
libxmlb,
+ libjcat,
giounix,
gusb,
]
@@ -95,6 +96,7 @@ library_deps = [
libjsonglib,
libgcab,
valgrind,
+ libjcat,
platform_deps,
]
@@ -136,6 +138,7 @@ fwupdplugin_pkgg.generate(
'libgcab-1.0',
'libsoup-2.4',
'xmlb',
+ 'jcat',
],
subdirs : 'fwupd-1',
version : meson.project_version(),
@@ -218,9 +221,6 @@ if get_option('tests')
noreqs_test_firmware,
fu_hash,
]
- if get_option('pkcs7')
- test_deps += colorhug_pkcs7_signature
- endif
testdatadir_src = join_paths(meson.source_root(), 'data', 'tests')
testdatadir_dst = join_paths(meson.build_root(), 'data', 'tests')
pluginbuilddir = join_paths(meson.build_root(), 'plugins', 'test')
diff --git a/meson.build b/meson.build
index c3eb4a436..e192b90ed 100644
--- a/meson.build
+++ b/meson.build
@@ -187,6 +187,7 @@ else
gudev = dependency('', required : false)
endif
libxmlb = dependency('xmlb', version : '>= 0.1.13', fallback : ['libxmlb', 'libxmlb_dep'])
+libjcat = dependency('jcat', version : '>= 0.1.0', fallback : ['libjcat', 'libjcat_dep'])
gusb = dependency('gusb', version : '>= 0.2.9', fallback : ['gusb', 'gusb_dep'])
sqlite = dependency('sqlite3')
libarchive = dependency('libarchive')
@@ -206,18 +207,6 @@ if build_daemon
udevdir = udev.get_pkgconfig_variable('udevdir')
endif
endif
-if get_option('pkcs7')
- gnutls = dependency('gnutls', version : '>= 3.4.4.1')
- if gnutls.version().version_compare('>= 3.6.0')
- conf.set('HAVE_GNUTLS_3_6_0', '1')
- endif
- conf.set('ENABLE_PKCS7', '1')
-endif
-if get_option('gpg')
- gpgme = cc.find_library('gpgme')
- gpgerror = cc.find_library('gpg-error')
- conf.set('ENABLE_GPG', '1')
-endif
libm = cc.find_library('m', required: false)
libgcab = dependency('libgcab-1.0', version : '>= 1.0', fallback : ['gcab', 'gcab_dep'])
gcab = find_program('gcab', required : true)
diff --git a/meson_options.txt b/meson_options.txt
index be0adfef6..3da9b6c44 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -2,13 +2,11 @@ option('build', type : 'combo', choices : ['all', 'standalone', 'library'], valu
option('agent', type : 'boolean', value : true, description : 'enable the fwupd agent')
option('consolekit', type : 'boolean', value : true, description : 'enable ConsoleKit support')
option('firmware-packager', type : 'boolean', value : true, description : 'enable firmware-packager installation')
-option('gpg', type : 'boolean', value : true, description : 'enable the GPG verification support')
option('gtkdoc', type : 'boolean', value : false, description : 'enable developer documentation')
option('introspection', type : 'boolean', value : true, description : 'generate GObject Introspection data')
option('lvfs', type : 'boolean', value : true, description : 'enable LVFS remotes')
option('man', type : 'boolean', value : true, description : 'enable man pages')
option('gudev', type : 'boolean', value : true, description : 'enable GUdev support')
-option('pkcs7', type : 'boolean', value : true, description : 'enable the PKCS7 verification support')
option('plugin_altos', type : 'boolean', value : true, description : 'enable altos support')
option('plugin_amt', type : 'boolean', value : true, description : 'enable Intel AMT support')
option('plugin_dell', type : 'boolean', value : true, description : 'enable Dell-specific support')
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 6762aff01..ea688ea8b 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -45,6 +45,31 @@ parts:
- -lib/pkgconfig
build-packages:
- libssl-dev
+ nettle:
+ plugin: autotools
+ source: https://ftp.gnu.org/gnu/nettle/nettle-3.5.tar.gz
+ build-packages:
+ - libgmp-dev
+ prime:
+ - -include
+ - -bin
+ - -share/man
+ - -lib/pkgconfig
+ gnutls:
+ plugin: autotools
+ source: https://www.gnupg.org/ftp/gcrypt/gnutls/v3.6/gnutls-3.6.12.tar.xz
+ build-packages:
+ - libtasn1-6-dev
+ - libunistring-dev
+ - libidn2-dev
+ - libunbound-dev
+ - libp11-kit-dev
+ prime:
+ - -include
+ - -bin
+ - -share/man
+ - -lib/pkgconfig
+ after: [nettle]
meson:
plugin: python
source: https://github.com/mesonbuild/meson/releases/download/0.51.2/meson-0.51.2.tar.gz
@@ -150,7 +175,11 @@ parts:
-Dplugin_modem_manager=true,
-Dudevdir=$SNAPCRAFT_STAGE/lib/udev,
"-Dlibxmlb:gtkdoc=false",
- "-Dlibxmlb:introspection=false"]
+ "-Dlibxmlb:introspection=false",
+ "-Dlibjcat:man=false",
+ "-Dlibjcat:gtkdoc=false",
+ "-Dlibjcat:introspection=false",
+ "-Dlibjcat:tests=false"]
source: .
source-type: git
override-build: |
@@ -159,7 +188,6 @@ parts:
build-packages:
- bash-completion
- gcab
- - gnutls-dev
- gnu-efi
- libarchive-dev
- libcairo-dev
@@ -236,7 +264,9 @@ parts:
- -usr/share/gir-1.0
- -usr/share/upstart
- -usr/lib/*/pkgconfig
- after: [meson, build-introspection, modemmanager, libmbim, libqmi, tpm2-tss]
+ # we don't want system gnutls leaking in
+ - -usr/lib/*/libgnutls*
+ after: [meson, build-introspection, modemmanager, libmbim, libqmi, tpm2-tss, gnutls]
fix-bash-completion:
plugin: make
source: contrib/snap/fix-bash-completion
diff --git a/src/fu-engine.c b/src/fu-engine.c
index f17e9d439..5d36ca0cf 100644
--- a/src/fu-engine.c
+++ b/src/fu-engine.c
@@ -97,6 +97,7 @@ struct _FuEngine
GHashTable *approved_firmware;
GHashTable *firmware_gtypes;
gchar *host_machine_id;
+ JcatContext *jcat_context;
gboolean loaded;
};
@@ -1728,8 +1729,7 @@ fu_engine_install_release (FuEngine *self,
FuPlugin *plugin;
FwupdVersionFormat fmt;
GBytes *blob_fw;
- const gchar *tmp = NULL;
- g_autofree gchar *release_key = NULL;
+ const gchar *tmp;
g_autofree gchar *version_orig = NULL;
g_autofree gchar *version_rel = NULL;
g_autoptr(FuDevice) device_tmp = NULL;
@@ -1737,19 +1737,13 @@ fu_engine_install_release (FuEngine *self,
g_autoptr(GBytes) blob_fw2 = NULL;
g_autoptr(GError) error_local = NULL;
- /* get the blob */
- tmp = xb_node_query_attr (rel, "checksum[@target='content']", "filename", NULL);
- if (tmp == NULL)
- tmp = "firmware.bin";
-
- /* not all devices have to use the same blob */
- release_key = g_strdup_printf ("fwupd::ReleaseBlob(%s)", tmp);
- blob_fw = xb_node_get_data (rel, release_key);
+ /* get per-release firmware blob */
+ blob_fw = xb_node_get_data (rel, "fwupd::FirmwareBlob");
if (blob_fw == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_READ,
- "Failed to get firmware blob using %s", tmp);
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "Failed to get firmware blob from release");
return FALSE;
}
@@ -2994,22 +2988,82 @@ fu_engine_remote_list_changed_cb (FuRemoteList *remote_list, FuEngine *self)
fu_engine_emit_changed (self);
}
-static FuKeyringResult *
-fu_engine_get_existing_keyring_result (FuEngine *self,
- FuKeyring *kr,
- FwupdRemote *remote,
- GError **error)
+static gint
+fu_engine_sort_jcat_results_timestamp_cb (gconstpointer a, gconstpointer b)
+{
+ JcatResult *ra = *((JcatResult **) a);
+ JcatResult *rb = *((JcatResult **) b);
+ if (jcat_result_get_timestamp (ra) < jcat_result_get_timestamp (rb))
+ return -1;
+ if (jcat_result_get_timestamp (ra) > jcat_result_get_timestamp (rb))
+ return 1;
+ return 0;
+}
+
+static JcatResult *
+fu_engine_get_system_jcat_result (FuEngine *self, FwupdRemote *remote, GError **error)
{
g_autoptr(GBytes) blob = NULL;
g_autoptr(GBytes) blob_sig = NULL;
+ g_autoptr(GInputStream) istream = NULL;
+ g_autoptr(GPtrArray) results = NULL;
+ g_autoptr(JcatItem) jcat_item = NULL;
+ g_autoptr(JcatFile) jcat_file = jcat_file_new ();
+
blob = fu_common_get_contents_bytes (fwupd_remote_get_filename_cache (remote), error);
if (blob == NULL)
return NULL;
blob_sig = fu_common_get_contents_bytes (fwupd_remote_get_filename_cache_sig (remote), error);
if (blob_sig == NULL)
return NULL;
- return fu_keyring_verify_data (kr, blob, blob_sig,
- FU_KEYRING_VERIFY_FLAG_NONE, error);
+ istream = g_memory_input_stream_new_from_bytes (blob_sig);
+ if (!jcat_file_import_stream (jcat_file, istream,
+ JCAT_IMPORT_FLAG_NONE,
+ NULL, error))
+ return NULL;
+ jcat_item = jcat_file_get_item_default (jcat_file, error);
+ if (jcat_item == NULL)
+ return NULL;
+ results = jcat_context_verify_item (self->jcat_context,
+ blob, jcat_item,
+ JCAT_VERIFY_FLAG_REQUIRE_CHECKSUM |
+ JCAT_VERIFY_FLAG_REQUIRE_SIGNATURE,
+ error);
+ if (results == NULL)
+ return NULL;
+ g_ptr_array_sort (results, fu_engine_sort_jcat_results_timestamp_cb);
+
+ /* return the newest one */
+ return g_object_ref (g_ptr_array_index (results, 0));
+}
+
+static gboolean
+fu_engine_validate_result_timestamp (JcatResult *jcat_result,
+ JcatResult *jcat_result_old,
+ GError **error)
+{
+ gint64 delta = 0;
+
+ g_return_val_if_fail (JCAT_IS_RESULT (jcat_result), FALSE);
+ g_return_val_if_fail (JCAT_IS_RESULT (jcat_result_old), FALSE);
+
+ if (jcat_result_get_timestamp (jcat_result) > 0 &&
+ jcat_result_get_timestamp (jcat_result_old) > 0) {
+ delta = jcat_result_get_timestamp (jcat_result) -
+ jcat_result_get_timestamp (jcat_result_old);
+ }
+ if (delta < 0) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "new signing timestamp was %"
+ G_GINT64_FORMAT " seconds older",
+ -delta);
+ return FALSE;
+ }
+ if (delta > 0)
+ g_debug ("timestamp increased, so no rollback");
+ return TRUE;
}
/**
@@ -3017,7 +3071,7 @@ fu_engine_get_existing_keyring_result (FuEngine *self,
* @self: A #FuEngine
* @remote_id: A remote ID, e.g. `lvfs`
* @bytes_raw: Blob of metadata
- * @bytes_sig: Blob of metadata signature
+ * @bytes_sig: Blob of metadata signature, typically Jcat binary format
* @error: A #GError, or %NULL
*
* Updates the metadata for a specific remote.
@@ -3059,31 +3113,41 @@ fu_engine_update_metadata_bytes (FuEngine *self, const gchar *remote_id,
/* verify file */
keyring_kind = fwupd_remote_get_keyring_kind (remote);
if (keyring_kind != FWUPD_KEYRING_KIND_NONE) {
- g_autoptr(FuKeyring) kr = NULL;
- g_autoptr(FuKeyringResult) kr_result = NULL;
- g_autoptr(FuKeyringResult) kr_result_old = NULL;
+ JcatResult *jcat_result;
g_autoptr(GError) error_local = NULL;
- kr = fu_keyring_create_for_kind (keyring_kind, error);
- if (kr == NULL)
+ g_autoptr(GInputStream) istream = NULL;
+ g_autoptr(GPtrArray) results = NULL;
+ g_autoptr(JcatFile) jcat_file = jcat_file_new ();
+ g_autoptr(JcatItem) jcat_item = NULL;
+ g_autoptr(JcatResult) jcat_result_old = NULL;
+
+ /* load Jcat file */
+ istream = g_memory_input_stream_new_from_bytes (bytes_sig);
+ if (!jcat_file_import_stream (jcat_file, istream,
+ JCAT_IMPORT_FLAG_NONE,
+ NULL, error))
return FALSE;
- if (!fu_keyring_setup (kr, error))
+
+ /* this should only be signing one thing */
+ jcat_item = jcat_file_get_item_default (jcat_file, error);
+ if (jcat_item == NULL)
return FALSE;
- sysconfdir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR);
- pki_dir = g_build_filename (sysconfdir, "pki", "fwupd-metadata", NULL);
- if (!fu_keyring_add_public_keys (kr, pki_dir, error))
- return FALSE;
- kr_result = fu_keyring_verify_data (kr, bytes_raw, bytes_sig,
- FU_KEYRING_VERIFY_FLAG_NONE,
+ results = jcat_context_verify_item (self->jcat_context,
+ bytes_raw, jcat_item,
+ JCAT_VERIFY_FLAG_REQUIRE_CHECKSUM |
+ JCAT_VERIFY_FLAG_REQUIRE_SIGNATURE,
error);
- if (kr_result == NULL)
+ if (results == NULL)
return FALSE;
+ /* return the newest one */
+ g_ptr_array_sort (results, fu_engine_sort_jcat_results_timestamp_cb);
+ jcat_result = g_ptr_array_index (results, 0);
+
/* verify the metadata was signed later than the existing
* metadata for this remote to mitigate a rollback attack */
- kr_result_old = fu_engine_get_existing_keyring_result (self, kr,
- remote,
- &error_local);
- if (kr_result_old == NULL) {
+ jcat_result_old = fu_engine_get_system_jcat_result (self, remote, &error_local);
+ if (jcat_result_old == NULL) {
if (g_error_matches (error_local,
G_FILE_ERROR,
G_FILE_ERROR_NOENT)) {
@@ -3094,23 +3158,10 @@ fu_engine_update_metadata_bytes (FuEngine *self, const gchar *remote_id,
error_local->message);
}
} else {
- gint64 delta = 0;
- if (fu_keyring_result_get_timestamp (kr_result) > 0 &&
- fu_keyring_result_get_timestamp (kr_result_old) > 0) {
- delta = fu_keyring_result_get_timestamp (kr_result) -
- fu_keyring_result_get_timestamp (kr_result_old);
- }
- if (delta < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "new signing timestamp was %"
- G_GINT64_FORMAT " seconds older",
- -delta);
+ if (!fu_engine_validate_result_timestamp (jcat_result,
+ jcat_result_old,
+ error))
return FALSE;
- } else if (delta > 0) {
- g_debug ("timestamp increased, so no rollback");
- }
}
}
@@ -3210,6 +3261,7 @@ fu_engine_get_silo_from_blob (FuEngine *self, GBytes *blob_cab, GError **error)
/* load file */
fu_engine_set_status (self, FWUPD_STATUS_DECOMPRESSING);
fu_cabinet_set_size_max (cabinet, fu_engine_get_archive_size_max (self));
+ fu_cabinet_set_jcat_context (cabinet, self->jcat_context);
if (!fu_cabinet_parse (cabinet, blob_cab, FU_CABINET_PARSE_FLAG_NONE, error))
return NULL;
silo = fu_cabinet_get_silo (cabinet);
@@ -3952,31 +4004,30 @@ fu_engine_add_approved_firmware (FuEngine *self, const gchar *checksum)
gchar *
fu_engine_self_sign (FuEngine *self,
const gchar *value,
- FuKeyringSignFlags flags,
+ JcatSignFlags flags,
GError **error)
{
- g_autoptr(FuKeyring) kr = NULL;
- g_autoptr(FuKeyringResult) kr_result = NULL;
+ g_autoptr(JcatBlob) jcat_signature = NULL;
+ g_autoptr(JcatEngine) jcat_engine = NULL;
+ g_autoptr(JcatResult) jcat_result = NULL;
g_autoptr(GBytes) payload = NULL;
- g_autoptr(GBytes) signature = NULL;
/* create detached signature and verify */
- kr = fu_keyring_create_for_kind (FWUPD_KEYRING_KIND_PKCS7, error);
- if (kr == NULL)
- return NULL;
- if (!fu_keyring_setup (kr, error))
+ jcat_engine = jcat_context_get_engine (self->jcat_context,
+ JCAT_BLOB_KIND_PKCS7,
+ error);
+ if (jcat_engine == NULL)
return NULL;
payload = g_bytes_new (value, strlen (value));
- signature = fu_keyring_sign_data (kr, payload, flags, error);
- if (signature == NULL)
+ jcat_signature = jcat_engine_self_sign (jcat_engine, payload, flags, error);
+ if (jcat_signature == NULL)
return NULL;
- kr_result = fu_keyring_verify_data (kr, payload, signature,
- FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT,
- error);
- if (kr_result == NULL)
+ jcat_result = jcat_engine_self_verify (jcat_engine, payload,
+ jcat_blob_get_data (jcat_signature),
+ JCAT_VERIFY_FLAG_NONE, error);
+ if (jcat_result == NULL)
return NULL;
- return g_strndup (g_bytes_get_data (signature, NULL),
- g_bytes_get_size (signature));
+ return jcat_blob_get_data_as_string (jcat_signature);
}
/**
@@ -5219,23 +5270,21 @@ fu_engine_udev_uevent_cb (GUdevClient *gudev_client,
static void
fu_engine_ensure_client_certificate (FuEngine *self)
{
- g_autoptr(FuKeyring) kr = NULL;
g_autoptr(GBytes) blob = g_bytes_new_static ("test\0", 5);
- g_autoptr(GBytes) sig = NULL;
g_autoptr(GError) error = NULL;
+ g_autoptr(JcatBlob) jcat_sig = NULL;
+ g_autoptr(JcatEngine) jcat_engine = NULL;
/* create keyring and sign dummy data to ensure certificate exists */
- kr = fu_keyring_create_for_kind (FWUPD_KEYRING_KIND_PKCS7, &error);
- if (kr == NULL) {
+ jcat_engine = jcat_context_get_engine (self->jcat_context,
+ JCAT_BLOB_KIND_PKCS7,
+ &error);
+ if (jcat_engine == NULL) {
g_message ("failed to create keyring: %s", error->message);
return;
}
- if (!fu_keyring_setup (kr, &error)) {
- g_message ("failed to setup keyring: %s", error->message);
- return;
- }
- sig = fu_keyring_sign_data (kr, blob, FU_KEYRING_SIGN_FLAG_NONE, &error);
- if (sig == NULL) {
+ jcat_sig = jcat_engine_self_sign (jcat_engine, blob, JCAT_SIGN_FLAG_NONE, &error);
+ if (jcat_sig == NULL) {
g_message ("failed to sign using keyring: %s", error->message);
return;
}
@@ -5486,6 +5535,10 @@ fu_engine_init (FuEngine *self)
#ifdef HAVE_UTSNAME_H
struct utsname uname_tmp;
#endif
+ g_autofree gchar *keyring_path = NULL;
+ g_autofree gchar *pkidir_fw = NULL;
+ g_autofree gchar *pkidir_md = NULL;
+ g_autofree gchar *sysconfdir = NULL;
self->percentage = 0;
self->status = FWUPD_STATUS_IDLE;
self->config = fu_config_new ();
@@ -5518,6 +5571,16 @@ fu_engine_init (FuEngine *self)
g_signal_connect (self->idle, "notify::status",
G_CALLBACK (fu_engine_idle_status_notify_cb), self);
+ /* setup Jcat context */
+ self->jcat_context = jcat_context_new ();
+ keyring_path = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
+ jcat_context_set_keyring_path (self->jcat_context, keyring_path);
+ sysconfdir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR);
+ pkidir_fw = g_build_filename (sysconfdir, "pki", "fwupd", NULL);
+ jcat_context_add_public_keys (self->jcat_context, pkidir_fw);
+ pkidir_md = g_build_filename (sysconfdir, "pki", "fwupd-metadata", NULL);
+ jcat_context_add_public_keys (self->jcat_context, pkidir_md);
+
/* add some runtime versions of things the daemon depends on */
fu_engine_add_runtime_version (self, "org.freedesktop.fwupd", VERSION);
fu_engine_add_runtime_version (self, "com.redhat.fwupdate", "12");
@@ -5573,6 +5636,7 @@ fu_engine_finalize (GObject *obj)
g_object_unref (self->hwids);
g_object_unref (self->history);
g_object_unref (self->device_list);
+ g_object_unref (self->jcat_context);
g_ptr_array_unref (self->plugin_filter);
g_ptr_array_unref (self->udev_subsystems);
#ifdef HAVE_GUDEV
diff --git a/src/fu-engine.h b/src/fu-engine.h
index 482c11de0..044e62018 100644
--- a/src/fu-engine.h
+++ b/src/fu-engine.h
@@ -8,12 +8,12 @@
#include
#include
+#include
#include "fwupd-device.h"
#include "fwupd-enums.h"
#include "fu-common.h"
-#include "fu-keyring.h"
#include "fu-install-task.h"
#include "fu-plugin.h"
@@ -147,7 +147,7 @@ void fu_engine_add_approved_firmware (FuEngine *self,
const gchar *checksum);
gchar *fu_engine_self_sign (FuEngine *self,
const gchar *value,
- FuKeyringSignFlags flags,
+ JcatSignFlags flags,
GError **error);
gboolean fu_engine_modify_config (FuEngine *self,
const gchar *key,
diff --git a/src/fu-keyring-gpg.c b/src/fu-keyring-gpg.c
deleted file mode 100644
index f06449cf2..000000000
--- a/src/fu-keyring-gpg.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#define G_LOG_DOMAIN "FuKeyring"
-
-#include "config.h"
-
-#include
-
-#include "fwupd-error.h"
-
-#include "fu-common.h"
-#include "fu-keyring-gpg.h"
-
-struct _FuKeyringGpg
-{
- FuKeyring parent_instance;
- gpgme_ctx_t ctx;
-};
-
-G_DEFINE_TYPE (FuKeyringGpg, fu_keyring_gpg, FU_TYPE_KEYRING)
-
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gpgme_data_t, gpgme_data_release, NULL)
-
-static gboolean
-fu_keyring_gpg_add_public_key (FuKeyringGpg *self,
- const gchar *filename,
- GError **error)
-{
- gpgme_error_t rc;
- gpgme_import_result_t result;
- gpgme_import_status_t s;
- g_auto(gpgme_data_t) data = NULL;
-
- /* import public key */
- g_debug ("Adding GnuPG public key %s", filename);
- rc = gpgme_data_new_from_file (&data, filename, 1);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to load %s: %s",
- filename, gpgme_strerror (rc));
- return FALSE;
- }
- rc = gpgme_op_import (self->ctx, data);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to import %s: %s",
- filename, gpgme_strerror (rc));
- return FALSE;
- }
-
- /* print what keys were imported */
- result = gpgme_op_import_result (self->ctx);
- for (s = result->imports; s != NULL; s = s->next) {
- g_debug ("importing key %s [%u] %s",
- s->fpr, s->status, gpgme_strerror (s->result));
- }
-
- /* make sure keys were really imported */
- if (result->imported == 0 && result->unchanged == 0) {
- g_debug("imported: %d, unchanged: %d, not_imported: %d",
- result->imported,
- result->unchanged,
- result->not_imported);
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "key import failed %s",
- filename);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-fu_keyring_gpg_setup (FuKeyring *keyring, GError **error)
-{
- FuKeyringGpg *self = FU_KEYRING_GPG (keyring);
- gpgme_error_t rc;
- g_autofree gchar *gpg_home = NULL;
- g_autofree gchar *localstatedir = NULL;
-
- if (self->ctx != NULL)
- return TRUE;
-
- /* startup gpgme */
- rc = gpg_err_init ();
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to init: %s",
- gpgme_strerror (rc));
- return FALSE;
- }
-
- /* create a new GPG context */
- rc = gpgme_new (&self->ctx);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to create context: %s",
- gpgme_strerror (rc));
- return FALSE;
- }
-
- /* set the protocol */
- rc = gpgme_set_protocol (self->ctx, GPGME_PROTOCOL_OpenPGP);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to set protocol: %s",
- gpgme_strerror (rc));
- return FALSE;
- }
-
- /* set a custom home directory */
- localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
- gpg_home = g_build_filename (localstatedir, "gnupg", NULL);
- if (g_mkdir_with_parents (gpg_home, 0700) < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to create %s",
- gpg_home);
- return FALSE;
- }
- g_debug ("Using keyring at %s", gpg_home);
- rc = gpgme_ctx_set_engine_info (self->ctx,
- GPGME_PROTOCOL_OpenPGP,
- NULL,
- gpg_home);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to set protocol: %s",
- gpgme_strerror (rc));
- return FALSE;
- }
-
- /* enable armor mode */
- gpgme_set_armor (self->ctx, TRUE);
- return TRUE;
-}
-
-static gboolean
-fu_keyring_gpg_add_public_keys (FuKeyring *keyring,
- const gchar *path,
- GError **error)
-{
- FuKeyringGpg *self = FU_KEYRING_GPG (keyring);
- const gchar *fn_tmp;
- g_autoptr(GDir) dir = NULL;
-
- /* search all the public key files */
- dir = g_dir_open (path, 0, error);
- if (dir == NULL)
- return FALSE;
- while ((fn_tmp = g_dir_read_name (dir)) != NULL) {
- g_autofree gchar *path_tmp = NULL;
- if (!g_str_has_prefix (fn_tmp, "GPG-KEY-"))
- continue;
- path_tmp = g_build_filename (path, fn_tmp, NULL);
- if (!fu_keyring_gpg_add_public_key (self, path_tmp, error))
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-fu_keyring_gpg_check_signature (gpgme_signature_t signature, GError **error)
-{
- gboolean ret = FALSE;
-
- /* look at the signature status */
- switch (gpgme_err_code (signature->status)) {
- case GPG_ERR_NO_ERROR:
- ret = TRUE;
- break;
- case GPG_ERR_SIG_EXPIRED:
- case GPG_ERR_KEY_EXPIRED:
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "valid signature '%s' has expired",
- signature->fpr);
- break;
- case GPG_ERR_CERT_REVOKED:
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "valid signature '%s' has been revoked",
- signature->fpr);
- break;
- case GPG_ERR_BAD_SIGNATURE:
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "'%s' is not a valid signature",
- signature->fpr);
- break;
- case GPG_ERR_NO_PUBKEY:
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "Could not check signature '%s' as no public key",
- signature->fpr);
- break;
- default:
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "gpgme failed to verify signature '%s'",
- signature->fpr);
- break;
- }
- return ret;
-}
-
-static FuKeyringResult *
-fu_keyring_gpg_verify_data (FuKeyring *keyring,
- GBytes *blob,
- GBytes *blob_signature,
- FuKeyringVerifyFlags flags,
- GError **error)
-{
- FuKeyringGpg *self = FU_KEYRING_GPG (keyring);
- gpgme_error_t rc;
- gpgme_signature_t s;
- gpgme_verify_result_t result;
- gint64 timestamp_newest = 0;
- g_auto(gpgme_data_t) data = NULL;
- g_auto(gpgme_data_t) sig = NULL;
- g_autoptr(GString) authority_newest = g_string_new (NULL);
-
- /* not supported */
- if (flags & FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT) {
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "no GPG client certificate support");
- return NULL;
- }
-
- /* load file data */
- rc = gpgme_data_new_from_mem (&data,
- g_bytes_get_data (blob, NULL),
- g_bytes_get_size (blob), 0);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to load data: %s",
- gpgme_strerror (rc));
- return NULL;
- }
- rc = gpgme_data_new_from_mem (&sig,
- g_bytes_get_data (blob_signature, NULL),
- g_bytes_get_size (blob_signature), 0);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to load signature: %s",
- gpgme_strerror (rc));
- return NULL;
- }
-
- /* verify */
- rc = gpgme_op_verify (self->ctx, sig, data, NULL);
- if (rc != GPG_ERR_NO_ERROR) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "failed to verify data: %s",
- gpgme_strerror (rc));
- return NULL;
- }
-
-
- /* verify the result */
- result = gpgme_op_verify_result (self->ctx);
- if (result == NULL) {
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "no result record from libgpgme");
- return NULL;
- }
-
- /* look at each signature */
- for (s = result->signatures; s != NULL ; s = s->next ) {
- g_debug ("returned signature fingerprint %s", s->fpr);
- if (!fu_keyring_gpg_check_signature (s, error))
- return NULL;
-
- /* save details about the key for the result */
- if ((gint64) s->timestamp > timestamp_newest) {
- timestamp_newest = (gint64) s->timestamp;
- g_string_assign (authority_newest, s->fpr);
- }
- }
- return FU_KEYRING_RESULT (g_object_new (FU_TYPE_KEYRING_RESULT,
- "timestamp", timestamp_newest,
- "authority", authority_newest->str,
- NULL));
-}
-
-static void
-fu_keyring_gpg_finalize (GObject *object)
-{
- FuKeyringGpg *self = FU_KEYRING_GPG (object);
- if (self->ctx != NULL)
- gpgme_release (self->ctx);
- G_OBJECT_CLASS (fu_keyring_gpg_parent_class)->finalize (object);
-}
-
-static void
-fu_keyring_gpg_class_init (FuKeyringGpgClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FuKeyringClass *klass_app = FU_KEYRING_CLASS (klass);
- klass_app->setup = fu_keyring_gpg_setup;
- klass_app->add_public_keys = fu_keyring_gpg_add_public_keys;
- klass_app->verify_data = fu_keyring_gpg_verify_data;
- object_class->finalize = fu_keyring_gpg_finalize;
-}
-
-static void
-fu_keyring_gpg_init (FuKeyringGpg *self)
-{
- FuKeyring *keyring = FU_KEYRING (self);
- g_autofree gchar *name = NULL;
- name = g_strdup_printf ("gpgme-v%s", gpgme_check_version (NULL));
- fu_keyring_set_name (keyring, name);
-}
-
-FuKeyring *
-fu_keyring_gpg_new (void)
-{
- return FU_KEYRING (g_object_new (FU_TYPE_KEYRING_GPG, NULL));
-}
diff --git a/src/fu-keyring-gpg.h b/src/fu-keyring-gpg.h
deleted file mode 100644
index 8c5c7f89d..000000000
--- a/src/fu-keyring-gpg.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#pragma once
-
-#include "fu-keyring.h"
-
-#define FU_TYPE_KEYRING_GPG (fu_keyring_gpg_get_type ())
-
-G_DECLARE_FINAL_TYPE (FuKeyringGpg, fu_keyring_gpg, FU, KEYRING_GPG, FuKeyring)
-
-FuKeyring *fu_keyring_gpg_new (void);
diff --git a/src/fu-keyring-pkcs7.c b/src/fu-keyring-pkcs7.c
deleted file mode 100644
index a42feaa7e..000000000
--- a/src/fu-keyring-pkcs7.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#define G_LOG_DOMAIN "FuKeyring"
-
-#include "config.h"
-
-#include
-#include
-#include
-
-#include "fu-common.h"
-#include "fu-keyring-pkcs7.h"
-
-#include "fwupd-error.h"
-
-struct _FuKeyringPkcs7
-{
- FuKeyring parent_instance;
- gnutls_x509_trust_list_t tl;
-};
-
-G_DEFINE_TYPE (FuKeyringPkcs7, fu_keyring_pkcs7, FU_TYPE_KEYRING)
-
-typedef guchar gnutls_data_t;
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_pkcs7_t, gnutls_pkcs7_deinit, NULL)
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_privkey_t, gnutls_privkey_deinit, NULL)
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_pubkey_t, gnutls_pubkey_deinit, NULL)
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_x509_crt_t, gnutls_x509_crt_deinit, NULL)
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_x509_dn_t, gnutls_x509_dn_deinit, NULL)
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_x509_privkey_t, gnutls_x509_privkey_deinit, NULL)
-#ifdef HAVE_GNUTLS_3_6_0
-G_DEFINE_AUTO_CLEANUP_FREE_FUNC(gnutls_x509_spki_t, gnutls_x509_spki_deinit, NULL)
-#endif
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(gnutls_data_t, gnutls_free)
-#pragma clang diagnostic pop
-
-static gnutls_x509_crt_t
-fu_keyring_pkcs7_load_crt_from_filename (const gchar *filename,
- gnutls_x509_crt_fmt_t format,
- GError **error)
-{
- gnutls_datum_t d = { 0 };
- gsize bufsz = 0;
- int rc;
- g_autofree gchar *buf = NULL;
- g_auto(gnutls_x509_crt_t) crt = NULL;
-
- /* create certificate */
- rc = gnutls_x509_crt_init (&crt);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* import the certificate */
- if (!g_file_get_contents (filename, &buf, &bufsz, error))
- return NULL;
- d.size = bufsz;
- d.data = (unsigned char *) buf;
- rc = gnutls_x509_crt_import (crt, &d, GNUTLS_X509_FMT_PEM);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_import: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
- return g_steal_pointer (&crt);
-}
-
-static gboolean
-fu_keyring_pkcs7_add_public_key (FuKeyringPkcs7 *self,
- const gchar *filename,
- gnutls_x509_crt_fmt_t format,
- GError **error)
-{
- guint key_usage = 0;
- int rc;
- g_auto(gnutls_x509_crt_t) crt = NULL;
-
- /* load file and add to the trust list */
- g_debug ("trying to load certificate from %s", filename);
- crt = fu_keyring_pkcs7_load_crt_from_filename (filename, format, error);
- if (crt == NULL)
- return FALSE;
- rc = gnutls_x509_crt_get_key_usage (crt, &key_usage, NULL);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to get key usage: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- if ((key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) == 0 &&
- (key_usage & GNUTLS_KEY_KEY_CERT_SIGN) == 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "certificate %s not suitable for use [0x%x]",
- filename, key_usage);
- return FALSE;
- }
- rc = gnutls_x509_trust_list_add_cas (self->tl, &crt, 1, 0);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to add to trust list: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- g_debug ("loaded %i certificates", rc);
-
- /* confusingly the trust list does not copy the certificate */
- crt = NULL;
- return TRUE;
-}
-
-static gboolean
-fu_keyring_pkcs7_add_public_keys (FuKeyring *keyring,
- const gchar *path,
- GError **error)
-{
- FuKeyringPkcs7 *self = FU_KEYRING_PKCS7 (keyring);
- const gchar *fn_tmp;
- g_autoptr(GDir) dir = NULL;
-
- /* search all the public key files */
- dir = g_dir_open (path, 0, error);
- if (dir == NULL)
- return FALSE;
- while ((fn_tmp = g_dir_read_name (dir)) != NULL) {
- g_autofree gchar *path_tmp = NULL;
- path_tmp = g_build_filename (path, fn_tmp, NULL);
- if (g_str_has_suffix (fn_tmp, ".pem")) {
- if (!fu_keyring_pkcs7_add_public_key (self, path_tmp,
- GNUTLS_X509_FMT_PEM,
- error))
- return FALSE;
- }
- if (g_str_has_suffix (fn_tmp, ".cer") ||
- g_str_has_suffix (fn_tmp, ".crt") ||
- g_str_has_suffix (fn_tmp, ".der")) {
- if (!fu_keyring_pkcs7_add_public_key (self, path_tmp,
- GNUTLS_X509_FMT_DER,
- error))
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static gnutls_privkey_t
-fu_keyring_pkcs7_load_privkey (FuKeyringPkcs7 *self, GError **error)
-{
- int rc;
- gnutls_datum_t d = { 0 };
- gsize bufsz = 0;
- g_autofree gchar *buf = NULL;
- g_autofree gchar *fn = NULL;
- g_autofree gchar *localstatedir = NULL;
- g_auto(gnutls_privkey_t) key = NULL;
-
- /* load the private key */
- rc = gnutls_privkey_init (&key);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "privkey_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
- localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
- fn = g_build_filename (localstatedir, "pki", "secret.key", NULL);
- if (!g_file_get_contents (fn, &buf, &bufsz, error))
- return NULL;
- d.size = bufsz;
- d.data = (unsigned char *) buf;
- rc = gnutls_privkey_import_x509_raw (key, &d, GNUTLS_X509_FMT_PEM, NULL, 0);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "privkey_import_x509_raw: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
- return g_steal_pointer (&key);
-}
-
-static gnutls_x509_crt_t
-fu_keyring_pkcs7_load_client_certificate (FuKeyringPkcs7 *self, GError **error)
-{
- g_autofree gchar *filename = NULL;
- g_autofree gchar *localstatedir = NULL;
- localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
- filename = g_build_filename (localstatedir, "pki", "client.pem", NULL);
- return fu_keyring_pkcs7_load_crt_from_filename (filename,
- GNUTLS_X509_FMT_PEM,
- error);
-}
-
-static gnutls_pubkey_t
-fu_keyring_pkcs7_load_pubkey_from_privkey (gnutls_privkey_t privkey, GError **error)
-{
- g_auto(gnutls_pubkey_t) pubkey = NULL;
- int rc;
-
- /* get the public key part of the private key */
- rc = gnutls_pubkey_init (&pubkey);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "pubkey_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
- rc = gnutls_pubkey_import_privkey (pubkey, privkey, 0, 0);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "pubkey_import_privkey: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* success */
- return g_steal_pointer (&pubkey);
-}
-
-/* generates a private key just like:
- * `certtool --generate-privkey` */
-static gboolean
-fu_keyring_pkcs7_ensure_private_key (FuKeyringPkcs7 *self, GError **error)
-{
-#ifdef HAVE_GNUTLS_3_6_0
- gnutls_datum_t d = { 0 };
- int bits;
- int key_type = GNUTLS_PK_RSA;
- int rc;
- g_autofree gchar *fn = NULL;
- g_autofree gchar *localstatedir = NULL;
- g_auto(gnutls_x509_privkey_t) key = NULL;
- g_auto(gnutls_x509_spki_t) spki = NULL;
- g_autoptr(GFile) file = NULL;
- g_autoptr(gnutls_data_t) d_payload = NULL;
-
- /* check exists */
- localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
- fn = g_build_filename (localstatedir, "pki", "secret.key", NULL);
- if (g_file_test (fn, G_FILE_TEST_EXISTS))
- return TRUE;
-
- /* initialize key and SPKI */
- rc = gnutls_x509_privkey_init (&key);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "privkey_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- rc = gnutls_x509_spki_init (&spki);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "spki_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* generate key */
- bits = gnutls_sec_param_to_pk_bits (key_type, GNUTLS_SEC_PARAM_HIGH);
- g_debug ("generating a %d bit %s private key...",
- bits, gnutls_pk_algorithm_get_name (key_type));
- rc = gnutls_x509_privkey_generate2(key, key_type, bits, 0, NULL, 0);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "privkey_generate2: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- rc = gnutls_x509_privkey_verify_params (key);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "privkey_verify_params: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* create parents if required */
- if (!fu_common_mkdir_parent (fn, error))
- return FALSE;
-
- /* save to file */
- rc = gnutls_x509_privkey_export2 (key, GNUTLS_X509_FMT_PEM, &d);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "privkey_export2: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- d_payload = d.data;
- file = g_file_new_for_path (fn);
- return g_file_replace_contents (file, (const char *) d_payload, d.size,
- NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL,
- NULL, error);
-#else
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "cannot build private key as GnuTLS version is too old");
- return FALSE;
-#endif
-}
-
-/* generates a self signed certificate just like:
- * `certtool --generate-self-signed --load-privkey priv.pem` */
-static gboolean
-fu_keyring_pkcs7_ensure_client_certificate (FuKeyringPkcs7 *self, GError **error)
-{
- int rc;
- gnutls_datum_t d = { 0 };
- guchar sha1buf[20];
- gsize sha1bufsz = sizeof(sha1buf);
- g_autofree gchar *fn = NULL;
- g_autofree gchar *localstatedir = NULL;
- g_auto(gnutls_privkey_t) key = NULL;
- g_auto(gnutls_pubkey_t) pubkey = NULL;
- g_auto(gnutls_x509_crt_t) crt = NULL;
- g_autoptr(gnutls_data_t) d_payload = NULL;
-
- /* check exists */
- localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
- fn = g_build_filename (localstatedir, "pki", "client.pem", NULL);
- if (g_file_test (fn, G_FILE_TEST_EXISTS))
- return TRUE;
-
- /* ensure the private key exists */
- if (!fu_keyring_pkcs7_ensure_private_key (self, error)) {
- g_prefix_error (error, "failed to generate private key: ");
- return FALSE;
- }
-
- /* load private key */
- key = fu_keyring_pkcs7_load_privkey (self, error);
- if (key == NULL)
- return FALSE;
-
- /* load the public key from the private key */
- pubkey = fu_keyring_pkcs7_load_pubkey_from_privkey (key, error);
- if (pubkey == NULL)
- return FALSE;
-
- /* create certificate */
- rc = gnutls_x509_crt_init (&crt);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set public key */
- rc = gnutls_x509_crt_set_pubkey (crt, pubkey);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_set_pubkey: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set positive random serial number */
- rc = gnutls_rnd (GNUTLS_RND_NONCE, sha1buf, sizeof(sha1buf));
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "gnutls_rnd: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- sha1buf[0] &= 0x7f;
- rc = gnutls_x509_crt_set_serial(crt, sha1buf, sizeof(sha1buf));
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_set_serial: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set activation */
- rc = gnutls_x509_crt_set_activation_time (crt, time (NULL));
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "set_activation_time: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set expiration */
- rc = gnutls_x509_crt_set_expiration_time (crt, (time_t) -1);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "set_expiration_time: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set basic constraints */
- rc = gnutls_x509_crt_set_basic_constraints (crt, 0, -1);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "set_basic_constraints: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set usage */
- rc = gnutls_x509_crt_set_key_usage (crt, GNUTLS_KEY_DIGITAL_SIGNATURE);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "set_key_usage: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set subject key ID */
- rc = gnutls_x509_crt_get_key_id (crt, GNUTLS_KEYID_USE_SHA1, sha1buf, &sha1bufsz);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "get_key_id: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- rc = gnutls_x509_crt_set_subject_key_id (crt, sha1buf, sha1bufsz);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "set_subject_key_id: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* set version */
- rc = gnutls_x509_crt_set_version (crt, 3);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "error setting certificate version: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* self-sign certificate */
- rc = gnutls_x509_crt_privkey_sign (crt, crt, key, GNUTLS_DIG_SHA256, 0);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_privkey_sign: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
-
- /* export to file */
- rc = gnutls_x509_crt_export2 (crt, GNUTLS_X509_FMT_PEM, &d);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "crt_export2: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- d_payload = d.data;
- return g_file_set_contents (fn, (const gchar *) d_payload, d.size, error);
-}
-
-static gboolean
-fu_keyring_pkcs7_setup (FuKeyring *keyring, GError **error)
-{
- FuKeyringPkcs7 *self = FU_KEYRING_PKCS7 (keyring);
- int rc;
-
- if (self->tl != NULL)
- return TRUE;
-
- /* create trust list, a bit like a keyring */
- rc = gnutls_x509_trust_list_init (&self->tl, 0);
- if (rc != GNUTLS_E_SUCCESS) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to create trust list: %s [%i]",
- gnutls_strerror (rc), rc);
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-_gnutls_datum_deinit (gnutls_datum_t *d)
-{
- gnutls_free (d->data);
- gnutls_free (d);
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(gnutls_datum_t, _gnutls_datum_deinit)
-#pragma clang diagnostic pop
-
-static gchar *
-fu_keyring_pkcs7_datum_to_dn_str (const gnutls_datum_t *raw)
-{
- g_auto(gnutls_x509_dn_t) dn = NULL;
- g_autoptr(gnutls_datum_t) str = NULL;
- int rc;
- rc = gnutls_x509_dn_init (&dn);
- if (rc < 0)
- return NULL;
- rc = gnutls_x509_dn_import (dn, raw);
- if (rc < 0)
- return NULL;
- str = (gnutls_datum_t *) gnutls_malloc (sizeof (gnutls_datum_t));
- str->data = NULL;
- rc = gnutls_x509_dn_get_str2 (dn, str, 0);
- if (rc < 0)
- return NULL;
- return g_strndup ((const gchar *) str->data, str->size);
-}
-
-/* verifies a detached signature just like:
- * `certtool --p7-verify --load-certificate client.pem --infile=test.p7b` */
-static FuKeyringResult *
-fu_keyring_pkcs7_verify_data (FuKeyring *keyring,
- GBytes *blob,
- GBytes *blob_signature,
- FuKeyringVerifyFlags flags,
- GError **error)
-{
- FuKeyringPkcs7 *self = FU_KEYRING_PKCS7 (keyring);
- gnutls_datum_t datum = { 0 };
- gint64 timestamp_newest = 0;
- int count;
- int rc;
- g_auto(gnutls_pkcs7_t) pkcs7 = NULL;
- g_auto(gnutls_x509_crt_t) crt = NULL;
- g_autoptr(GString) authority_newest = g_string_new (NULL);
-
- /* startup */
- rc = gnutls_pkcs7_init (&pkcs7);
- if (rc != GNUTLS_E_SUCCESS) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to init pkcs7: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* import the signature */
- datum.data = (guchar *) g_bytes_get_data (blob_signature, NULL);
- datum.size = g_bytes_get_size (blob_signature);
- rc = gnutls_pkcs7_import (pkcs7, &datum, GNUTLS_X509_FMT_PEM);
- if (rc != GNUTLS_E_SUCCESS) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to import the PKCS7 signature: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* verify the blob */
- datum.data = (guchar *) g_bytes_get_data (blob, NULL);
- datum.size = g_bytes_get_size (blob);
- count = gnutls_pkcs7_get_signature_count (pkcs7);
- g_debug ("got %i PKCS7 signatures", count);
- if (count == 0) {
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "no PKCS7 signatures found");
- return NULL;
- }
-
- /* use client certificate */
- if (flags & FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT) {
- if (!fu_keyring_pkcs7_ensure_client_certificate (self, error)) {
- g_prefix_error (error, "failed to generate client certificate: ");
- return NULL;
- }
- crt = fu_keyring_pkcs7_load_client_certificate (self, error);
- if (crt == NULL)
- return NULL;
- }
-
- for (gint i = 0; i < count; i++) {
- gnutls_pkcs7_signature_info_st info;
- gint64 signing_time = 0;
- gnutls_certificate_verify_flags verify_flags = 0;
-
- /* use with care */
- if (flags & FU_KEYRING_VERIFY_FLAG_DISABLE_TIME_CHECKS) {
- g_debug ("WARNING: disabling time checks");
- verify_flags |= GNUTLS_VERIFY_DISABLE_TIME_CHECKS;
- verify_flags |= GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS;
- }
-
- /* verify the data against the detached signature */
- if (flags & FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT) {
- rc = gnutls_pkcs7_verify_direct (pkcs7, crt, i, &datum, 0);
- } else {
- rc = gnutls_pkcs7_verify (pkcs7, self->tl,
- NULL, /* vdata */
- 0, /* vdata_size */
- i, /* index */
- &datum, /* data */
- verify_flags);
- }
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to verify data: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* save details about the key for the result */
- rc = gnutls_pkcs7_get_signature_info (pkcs7, i, &info);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "failed to get signature info: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
- signing_time = info.signing_time > 0 ? (gint64) info.signing_time : 1;
- if (signing_time > timestamp_newest) {
- g_autofree gchar *dn = NULL;
- timestamp_newest = signing_time;
- dn = fu_keyring_pkcs7_datum_to_dn_str (&info.issuer_dn);
- if (dn != NULL)
- g_string_assign (authority_newest, dn);
- }
- gnutls_pkcs7_signature_info_deinit (&info);
- }
-
- /* success */
- return FU_KEYRING_RESULT (g_object_new (FU_TYPE_KEYRING_RESULT,
- "timestamp", timestamp_newest,
- "authority", authority_newest->str,
- NULL));
-}
-
-/* creates a detached signature just like:
- * `certtool --p7-detached-sign --load-certificate client.pem \
- * --load-privkey secret.pem --outfile=test.p7b` */
-static GBytes *
-fu_keyring_pkcs7_sign_data (FuKeyring *keyring,
- GBytes *blob,
- FuKeyringSignFlags flags,
- GError **error)
-{
- FuKeyringPkcs7 *self = FU_KEYRING_PKCS7 (keyring);
- gnutls_datum_t d = { 0 };
- gnutls_digest_algorithm_t dig = GNUTLS_DIG_NULL;
- guint gnutls_flags = 0;
- int rc;
- g_auto(gnutls_pkcs7_t) pkcs7 = NULL;
- g_auto(gnutls_privkey_t) key = NULL;
- g_auto(gnutls_pubkey_t) pubkey = NULL;
- g_auto(gnutls_x509_crt_t) crt = NULL;
- g_autoptr(gnutls_data_t) d_payload = NULL;
-
- /* ensure the client certificate exists */
- if (!fu_keyring_pkcs7_ensure_client_certificate (self, error)) {
- g_prefix_error (error, "failed to generate client certificate: ");
- return NULL;
- }
-
- /* import the keys */
- crt = fu_keyring_pkcs7_load_client_certificate (self, error);
- if (crt == NULL)
- return NULL;
- key = fu_keyring_pkcs7_load_privkey (self, error);
- if (key == NULL)
- return NULL;
-
- /* get the digest algorithm from the publix key */
- pubkey = fu_keyring_pkcs7_load_pubkey_from_privkey (key, error);
- if (pubkey == NULL)
- return NULL;
- rc = gnutls_pubkey_get_preferred_hash_algorithm (pubkey, &dig, NULL);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "preferred_hash_algorithm: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* create container */
- rc = gnutls_pkcs7_init (&pkcs7);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "pkcs7_init: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* sign data */
- d.data = (unsigned char *) g_bytes_get_data (blob, NULL);
- d.size = g_bytes_get_size (blob);
- if (flags & FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP)
- gnutls_flags |= GNUTLS_PKCS7_INCLUDE_TIME;
- if (flags & FU_KEYRING_SIGN_FLAG_ADD_CERT)
- gnutls_flags |= GNUTLS_PKCS7_INCLUDE_CERT;
- rc = gnutls_pkcs7_sign (pkcs7, crt, key, &d, NULL, NULL, dig, gnutls_flags);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "pkcs7_sign: %s [%i]",
- gnutls_strerror (rc), rc);
- return NULL;
- }
-
- /* set certificate */
- if (flags & FU_KEYRING_SIGN_FLAG_ADD_CERT) {
- rc = gnutls_pkcs7_set_crt (pkcs7, crt);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "pkcs7_set_cr: %s", gnutls_strerror (rc));
- return NULL;
- }
- }
-
- /* export */
- rc = gnutls_pkcs7_export2 (pkcs7, GNUTLS_X509_FMT_PEM, &d);
- if (rc < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_SIGNATURE_INVALID,
- "pkcs7_export: %s", gnutls_strerror (rc));
- return NULL;
- }
- d_payload = d.data;
- return g_bytes_new (d_payload, d.size);
-}
-
-static void
-fu_keyring_pkcs7_finalize (GObject *object)
-{
- FuKeyringPkcs7 *self = FU_KEYRING_PKCS7 (object);
- gnutls_x509_trust_list_deinit (self->tl, 1);
- G_OBJECT_CLASS (fu_keyring_pkcs7_parent_class)->finalize (object);
-}
-
-static void
-fu_keyring_pkcs7_class_init (FuKeyringPkcs7Class *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FuKeyringClass *klass_app = FU_KEYRING_CLASS (klass);
- klass_app->setup = fu_keyring_pkcs7_setup;
- klass_app->add_public_keys = fu_keyring_pkcs7_add_public_keys;
- klass_app->sign_data = fu_keyring_pkcs7_sign_data;
- klass_app->verify_data = fu_keyring_pkcs7_verify_data;
- object_class->finalize = fu_keyring_pkcs7_finalize;
-}
-
-static void
-fu_keyring_pkcs7_init (FuKeyringPkcs7 *self)
-{
- FuKeyring *keyring = FU_KEYRING (self);
- g_autofree gchar *name = NULL;
- name = g_strdup_printf ("gnutls-v%s", gnutls_check_version (NULL));
- fu_keyring_set_name (keyring, name);
-}
-
-FuKeyring *
-fu_keyring_pkcs7_new (void)
-{
- return FU_KEYRING (g_object_new (FU_TYPE_KEYRING_PKCS7, NULL));
-}
diff --git a/src/fu-keyring-pkcs7.h b/src/fu-keyring-pkcs7.h
deleted file mode 100644
index eda168f27..000000000
--- a/src/fu-keyring-pkcs7.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#pragma once
-
-#include "fu-keyring.h"
-
-#define FU_TYPE_KEYRING_PKCS7 (fu_keyring_pkcs7_get_type ())
-
-G_DECLARE_FINAL_TYPE (FuKeyringPkcs7, fu_keyring_pkcs7, FU, KEYRING_PKCS7, FuKeyring)
-
-FuKeyring *fu_keyring_pkcs7_new (void);
diff --git a/src/fu-keyring-result.c b/src/fu-keyring-result.c
deleted file mode 100644
index 42f024387..000000000
--- a/src/fu-keyring-result.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#define G_LOG_DOMAIN "FuKeyring"
-
-#include "config.h"
-
-#include "fwupd-error.h"
-
-#include "fu-keyring-result.h"
-
-struct _FuKeyringResult
-{
- GObject parent_instance;
- gint64 timestamp;
- gchar *authority;
-};
-
-G_DEFINE_TYPE (FuKeyringResult, fu_keyring_result, G_TYPE_OBJECT)
-
-enum {
- PROP_0,
- PROP_TIMESTAMP,
- PROP_AUTHORITY,
- PROP_LAST
-};
-
-gint64
-fu_keyring_result_get_timestamp (FuKeyringResult *self)
-{
- g_return_val_if_fail (FU_IS_KEYRING_RESULT (self), 0);
- return self->timestamp;
-}
-
-const gchar *
-fu_keyring_result_get_authority (FuKeyringResult *self)
-{
- g_return_val_if_fail (FU_IS_KEYRING_RESULT (self), NULL);
- return self->authority;
-}
-
-static void
-fu_keyring_result_finalize (GObject *object)
-{
- FuKeyringResult *self = FU_KEYRING_RESULT (object);
- g_free (self->authority);
- G_OBJECT_CLASS (fu_keyring_result_parent_class)->finalize (object);
-}
-
-static void
-fu_keyring_result_get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- FuKeyringResult *self = FU_KEYRING_RESULT (object);
- switch (prop_id) {
- case PROP_TIMESTAMP:
- g_value_set_int64 (value, self->timestamp);
- break;
- case PROP_AUTHORITY:
- g_value_set_string (value, self->authority);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-fu_keyring_result_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- FuKeyringResult *self = FU_KEYRING_RESULT (object);
- switch (prop_id) {
- case PROP_TIMESTAMP:
- self->timestamp = g_value_get_int64 (value);
- break;
- case PROP_AUTHORITY:
- self->authority = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-fu_keyring_result_class_init (FuKeyringResultClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GParamSpec *pspec;
-
- object_class->get_property = fu_keyring_result_get_property;
- object_class->set_property = fu_keyring_result_set_property;
- object_class->finalize = fu_keyring_result_finalize;
-
- pspec = g_param_spec_int64 ("timestamp", NULL, NULL,
- 0, G_MAXINT64, 0,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME);
- g_object_class_install_property (object_class, PROP_TIMESTAMP, pspec);
-
- pspec = g_param_spec_string ("authority", NULL, NULL, NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME);
- g_object_class_install_property (object_class, PROP_AUTHORITY, pspec);
-}
-
-static void
-fu_keyring_result_init (FuKeyringResult *self)
-{
-}
diff --git a/src/fu-keyring-result.h b/src/fu-keyring-result.h
deleted file mode 100644
index 14a5acd29..000000000
--- a/src/fu-keyring-result.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#pragma once
-
-#include
-
-#define FU_TYPE_KEYRING_RESULT (fu_keyring_result_get_type ())
-
-G_DECLARE_FINAL_TYPE (FuKeyringResult, fu_keyring_result, FU, KEYRING_RESULT, GObject)
-
-gint64 fu_keyring_result_get_timestamp (FuKeyringResult *self);
-const gchar *fu_keyring_result_get_authority (FuKeyringResult *self);
diff --git a/src/fu-keyring-utils.c b/src/fu-keyring-utils.c
index f14068ba4..f4e09de64 100644
--- a/src/fu-keyring-utils.c
+++ b/src/fu-keyring-utils.c
@@ -1,70 +1,15 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017-2020 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
-#define G_LOG_DOMAIN "FuKeyring"
-
#include
#include "fwupd-error.h"
-#include "fu-common.h"
#include "fu-keyring-utils.h"
-#ifdef ENABLE_GPG
-#include "fu-keyring-gpg.h"
-#endif
-#ifdef ENABLE_PKCS7
-#include "fu-keyring-pkcs7.h"
-#endif
-
-/**
- * fu_keyring_create_for_kind:
- * @kind: A #FwupdKeyringKind, e.g. %FWUPD_KEYRING_KIND_GPG
- * @error: A #GError, or %NULL
- *
- * Creates a new keyring of the specified kind.
- *
- * If the keyring cannot be created (for example, if fwupd is compiled without
- * GPG support) then an error is returned.
- *
- * Returns: (transfer full): a new #FuKeyring, or %NULL for error
- **/
-FuKeyring *
-fu_keyring_create_for_kind (FwupdKeyringKind kind, GError **error)
-{
- if (kind == FWUPD_KEYRING_KIND_GPG) {
-#ifdef ENABLE_GPG
- return fu_keyring_gpg_new ();
-#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not compiled with GPG support");
- return NULL;
-#endif
- }
- if (kind == FWUPD_KEYRING_KIND_PKCS7) {
-#ifdef ENABLE_PKCS7
- return fu_keyring_pkcs7_new ();
-#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not compiled with PKCS7 support");
- return NULL;
-#endif
- }
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Keyring kind %s not supported",
- fwupd_keyring_kind_to_string (kind));
- return NULL;
-}
-
/**
* fu_keyring_get_release_flags:
* @release: A #XbNode, e.g. %FWUPD_KEYRING_KIND_GPG
@@ -80,97 +25,27 @@ fu_keyring_get_release_flags (XbNode *release,
FwupdReleaseFlags *flags,
GError **error)
{
- FwupdKeyringKind keyring_kind = FWUPD_KEYRING_KIND_UNKNOWN;
- GBytes *blob_payload;
- GBytes *blob_signature;
- const gchar *fn;
- g_autofree gchar *pki_dir = NULL;
- g_autofree gchar *release_key = NULL;
- g_autofree gchar *sysconfdir = NULL;
- g_autoptr(GError) error_local = NULL;
- g_autoptr(FuKeyring) kr = NULL;
- g_autoptr(FuKeyringResult) kr_result = NULL;
- struct {
- FwupdKeyringKind kind;
- const gchar *ext;
- } keyrings[] = {
- { FWUPD_KEYRING_KIND_GPG, "asc" },
- { FWUPD_KEYRING_KIND_PKCS7, "p7b" },
- { FWUPD_KEYRING_KIND_PKCS7, "p7c" },
- { FWUPD_KEYRING_KIND_NONE, NULL }
- };
+ GBytes *blob;
- /* custom filename specified */
- fn = xb_node_query_attr (release, "checksum[@target='content']", "filename", NULL);
- if (fn == NULL)
- fn = "filename.bin";
-
- /* no signature == no trust */
- for (guint i = 0; keyrings[i].ext != NULL; i++) {
- g_autofree gchar *fn_tmp = NULL;
- fn_tmp = g_strdup_printf ("fwupd::ReleaseBlob(%s.%s)",
- fn, keyrings[i].ext);
- blob_signature = g_object_get_data (G_OBJECT (release), fn_tmp);
- if (blob_signature != NULL) {
- keyring_kind = keyrings[i].kind;
- break;
- }
- }
- if (keyring_kind == FWUPD_KEYRING_KIND_UNKNOWN) {
- g_debug ("firmware archive contained no signature");
+ blob = g_object_get_data (G_OBJECT (release), "fwupd::ReleaseFlags");
+ if (blob == NULL) {
+ g_debug ("no fwupd::ReleaseFlags set by loader");
return TRUE;
- }
-
- /* get payload */
- release_key = g_strdup_printf ("fwupd::ReleaseBlob(%s)", fn);
- blob_payload = g_object_get_data (G_OBJECT (release), release_key);
- if (blob_payload == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
- "no payload");
+ "no fwupd::ReleaseFlags set by loader");
return FALSE;
}
-
- /* check we were installed correctly */
- sysconfdir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR);
- pki_dir = g_build_filename (sysconfdir, "pki", PACKAGE_NAME, NULL);
-#if defined(ENABLE_PKCS7) || defined(ENABLE_PKCS7)
- if (!g_file_test (pki_dir, G_FILE_TEST_EXISTS)) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_FOUND,
- "PKI directory %s not found", pki_dir);
- return FALSE;
- }
-#endif
-
- /* verify against the system trusted keys */
- kr = fu_keyring_create_for_kind (keyring_kind, error);
- if (kr == NULL)
- return FALSE;
- if (!fu_keyring_setup (kr, error)) {
- g_prefix_error (error, "failed to set up %s keyring: ",
- fu_keyring_get_name (kr));
- return FALSE;
- }
- if (!fu_keyring_add_public_keys (kr, pki_dir, error)) {
- g_prefix_error (error, "failed to add public keys to %s keyring: ",
- fu_keyring_get_name (kr));
- return FALSE;
- }
- kr_result = fu_keyring_verify_data (kr, blob_payload, blob_signature,
- FU_KEYRING_VERIFY_FLAG_NONE,
- &error_local);
- if (kr_result == NULL) {
- g_warning ("untrusted as failed to verify from %s keyring: %s",
- fu_keyring_get_name (kr),
- error_local->message);
+ if (g_bytes_get_size (blob) != sizeof(FwupdReleaseFlags)) {
+ g_critical ("invalid fwupd::ReleaseFlags set by loader");
return TRUE;
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "invalid fwupd::ReleaseFlags set by loader");
+ return FALSE;
}
-
- /* awesome! */
- g_debug ("marking payload as trusted");
- *flags |= FWUPD_RELEASE_FLAG_TRUSTED_PAYLOAD;
+ memcpy (flags, g_bytes_get_data (blob, NULL), sizeof(FwupdReleaseFlags));
return TRUE;
}
diff --git a/src/fu-keyring-utils.h b/src/fu-keyring-utils.h
index 5a95b2d26..92f66bba9 100644
--- a/src/fu-keyring-utils.h
+++ b/src/fu-keyring-utils.h
@@ -7,12 +7,10 @@
#pragma once
#include
+#include
-#include "fu-keyring.h"
#include "fwupd-enums.h"
-FuKeyring *fu_keyring_create_for_kind (FwupdKeyringKind kind,
- GError **error);
gboolean fu_keyring_get_release_flags (XbNode *release,
FwupdReleaseFlags *flags,
GError **error);
diff --git a/src/fu-keyring.c b/src/fu-keyring.c
deleted file mode 100644
index 1265e4c76..000000000
--- a/src/fu-keyring.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#define G_LOG_DOMAIN "FuKeyring"
-
-#include "config.h"
-
-#include "fwupd-error.h"
-
-#include "fu-keyring.h"
-
-typedef struct {
- gchar *name;
-} FuKeyringPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (FuKeyring, fu_keyring, G_TYPE_OBJECT)
-#define GET_PRIVATE(o) (fu_keyring_get_instance_private (o))
-
-gboolean
-fu_keyring_setup (FuKeyring *keyring, GError **error)
-{
- FuKeyringClass *klass = FU_KEYRING_GET_CLASS (keyring);
- g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
- return klass->setup (keyring, error);
-}
-
-gboolean
-fu_keyring_add_public_keys (FuKeyring *keyring, const gchar *path, GError **error)
-{
- FuKeyringClass *klass = FU_KEYRING_GET_CLASS (keyring);
- g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- return klass->add_public_keys (keyring, path, error);
-}
-
-FuKeyringResult *
-fu_keyring_verify_data (FuKeyring *keyring,
- GBytes *blob,
- GBytes *blob_signature,
- FuKeyringVerifyFlags flags,
- GError **error)
-{
- FuKeyringClass *klass = FU_KEYRING_GET_CLASS (keyring);
- g_return_val_if_fail (FU_IS_KEYRING (keyring), NULL);
- g_return_val_if_fail (blob != NULL, NULL);
- g_return_val_if_fail (blob_signature != NULL, NULL);
- return klass->verify_data (keyring, blob, blob_signature, flags, error);
-}
-
-GBytes *
-fu_keyring_sign_data (FuKeyring *keyring,
- GBytes *blob,
- FuKeyringSignFlags flags,
- GError **error)
-{
- FuKeyringClass *klass = FU_KEYRING_GET_CLASS (keyring);
- g_return_val_if_fail (FU_IS_KEYRING (keyring), NULL);
- g_return_val_if_fail (blob != NULL, NULL);
- if (klass->sign_data == NULL) {
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "signing data is not supported");
- return NULL;
- }
- return klass->sign_data (keyring, blob, flags, error);
-}
-
-const gchar *
-fu_keyring_get_name (FuKeyring *self)
-{
- FuKeyringPrivate *priv = GET_PRIVATE (self);
- return priv->name;
-}
-
-void
-fu_keyring_set_name (FuKeyring *self, const gchar *name)
-{
- FuKeyringPrivate *priv = GET_PRIVATE (self);
- g_free (priv->name);
- priv->name = g_strdup (name);
-}
-
-static void
-fu_keyring_finalize (GObject *object)
-{
- FuKeyring *self = FU_KEYRING (object);
- FuKeyringPrivate *priv = GET_PRIVATE (self);
- g_free (priv->name);
- G_OBJECT_CLASS (fu_keyring_parent_class)->finalize (object);
-}
-
-static void
-fu_keyring_class_init (FuKeyringClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = fu_keyring_finalize;
-}
-
-static void
-fu_keyring_init (FuKeyring *keyring)
-{
-}
diff --git a/src/fu-keyring.h b/src/fu-keyring.h
deleted file mode 100644
index beca1a6c6..000000000
--- a/src/fu-keyring.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2017 Richard Hughes
- *
- * SPDX-License-Identifier: LGPL-2.1+
- */
-
-#pragma once
-
-#include
-#include
-
-#include "fu-keyring-result.h"
-
-#define FU_TYPE_KEYRING (fu_keyring_get_type ())
-G_DECLARE_DERIVABLE_TYPE (FuKeyring, fu_keyring, FU, KEYRING, GObject)
-
-/**
- * FuKeyringVerifyFlags:
- * @FU_KEYRING_VERIFY_FLAG_NONE: No flags set
- * @FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT: Use client certificate to verify
- * @FU_KEYRING_VERIFY_FLAG_DISABLE_TIME_CHECKS: Disable checking of validity periods
- *
- * The flags to use when interacting with a keyring
- **/
-typedef enum {
- FU_KEYRING_VERIFY_FLAG_NONE = 0,
- FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT = 1 << 1,
- FU_KEYRING_VERIFY_FLAG_DISABLE_TIME_CHECKS = 1 << 2,
- /*< private >*/
- FU_KEYRING_VERIFY_FLAG_LAST
-} FuKeyringVerifyFlags;
-
-/**
- * FuKeyringSignFlags:
- * @FU_KEYRING_SIGN_FLAG_NONE: No flags set
- * @FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP: Add a timestamp
- * @FU_KEYRING_SIGN_FLAG_ADD_CERT: Add a certificate
- *
- * The flags to when signing a binary
- **/
-typedef enum {
- FU_KEYRING_SIGN_FLAG_NONE = 0,
- FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP = 1 << 0,
- FU_KEYRING_SIGN_FLAG_ADD_CERT = 1 << 1,
- /*< private >*/
- FU_KEYRING_SIGN_FLAG_LAST
-} FuKeyringSignFlags;
-
-struct _FuKeyringClass
-{
- GObjectClass parent_class;
- gboolean (*setup) (FuKeyring *keyring,
- GError **error);
- gboolean (*add_public_keys) (FuKeyring *keyring,
- const gchar *path,
- GError **error);
- FuKeyringResult *(*verify_data) (FuKeyring *keyring,
- GBytes *payload,
- GBytes *payload_signature,
- FuKeyringVerifyFlags flags,
- GError **error);
- GBytes *(*sign_data) (FuKeyring *keyring,
- GBytes *payload,
- FuKeyringSignFlags flags,
- GError **error);
-};
-
-gboolean fu_keyring_setup (FuKeyring *keyring,
- GError **error);
-gboolean fu_keyring_add_public_keys (FuKeyring *keyring,
- const gchar *path,
- GError **error);
-FuKeyringResult *fu_keyring_verify_data (FuKeyring *keyring,
- GBytes *blob,
- GBytes *blob_signature,
- FuKeyringVerifyFlags flags,
- GError **error);
-GBytes *fu_keyring_sign_data (FuKeyring *keyring,
- GBytes *blob,
- FuKeyringSignFlags flags,
- GError **error);
-const gchar *fu_keyring_get_name (FuKeyring *self);
-void fu_keyring_set_name (FuKeyring *self,
- const gchar *name);
diff --git a/src/fu-main.c b/src/fu-main.c
index bb6077da4..347b26530 100644
--- a/src/fu-main.c
+++ b/src/fu-main.c
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include "fwupd-device-private.h"
#include "fwupd-release-private.h"
@@ -900,10 +901,10 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
g_debug ("got option %s", prop_key);
if (g_strcmp0 (prop_key, "add-timestamp") == 0 &&
g_variant_get_boolean (prop_value) == TRUE)
- helper->flags |= FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP;
+ helper->flags |= JCAT_SIGN_FLAG_ADD_TIMESTAMP;
if (g_strcmp0 (prop_key, "add-cert") == 0 &&
g_variant_get_boolean (prop_value) == TRUE)
- helper->flags |= FU_KEYRING_SIGN_FLAG_ADD_CERT;
+ helper->flags |= JCAT_SIGN_FLAG_ADD_CERT;
g_variant_unref (prop_value);
}
diff --git a/src/fu-self-test.c b/src/fu-self-test.c
index e05fa731b..40decb5cf 100644
--- a/src/fu-self-test.c
+++ b/src/fu-self-test.c
@@ -19,7 +19,6 @@
#include "fu-device-list.h"
#include "fu-device-private.h"
#include "fu-engine.h"
-#include "fu-keyring.h"
#include "fu-history.h"
#include "fu-install-task.h"
#include "fu-plugin-private.h"
@@ -28,13 +27,6 @@
#include "fu-hash.h"
#include "fu-smbios-private.h"
-#ifdef ENABLE_GPG
-#include "fu-keyring-gpg.h"
-#endif
-#ifdef ENABLE_PKCS7
-#include "fu-keyring-pkcs7.h"
-#endif
-
typedef struct {
FuPlugin *plugin;
} FuTest;
@@ -2591,185 +2583,6 @@ fu_history_func (gconstpointer user_data)
g_assert_cmpstr (g_ptr_array_index (approved_firmware, 1), ==, "bar");
}
-static void
-fu_keyring_gpg_func (gconstpointer user_data)
-{
-#ifdef ENABLE_GPG
- gboolean ret;
- g_autofree gchar *fw_fail = NULL;
- g_autofree gchar *fw_pass = NULL;
- g_autofree gchar *pki_dir = NULL;
- g_autoptr(FuKeyring) keyring = NULL;
- g_autoptr(FuKeyringResult) result_fail = NULL;
- g_autoptr(FuKeyringResult) result_pass = NULL;
- g_autoptr(GBytes) blob_fail = NULL;
- g_autoptr(GBytes) blob_pass = NULL;
- g_autoptr(GBytes) blob_sig = NULL;
- g_autoptr(GError) error = NULL;
- const gchar *sig_gpgme =
- "-----BEGIN PGP SIGNATURE-----\n"
- "Version: GnuPG v1\n\n"
- "iQEcBAABCAAGBQJVt0B4AAoJEEim2A5FOLrCFb8IAK+QTLY34Wu8xZ8nl6p3JdMu"
- "HOaifXAmX7291UrsFRwdabU2m65pqxQLwcoFrqGv738KuaKtu4oIwo9LIrmmTbEh"
- "IID8uszxBt0bMdcIHrvwd+ADx+MqL4hR3guXEE3YOBTLvv2RF1UBcJPInNf/7Ui1"
- "3lW1c3trL8RAJyx1B5RdKqAMlyfwiuvKM5oT4SN4uRSbQf+9mt78ZSWfJVZZH/RR"
- "H9q7PzR5GdmbsRPM0DgC27Trvqjo3MzoVtoLjIyEb/aWqyulUbnJUNKPYTnZgkzM"
- "v2yVofWKIM3e3wX5+MOtf6EV58mWa2cHJQ4MCYmpKxbIvAIZagZ4c9A8BA6tQWg="
- "=fkit\n"
- "-----END PGP SIGNATURE-----\n";
-
- /* add keys to keyring */
- keyring = fu_keyring_gpg_new ();
- ret = fu_keyring_setup (keyring, &error);
- g_assert_no_error (error);
- g_assert_true (ret);
- pki_dir = g_build_filename (TESTDATADIR_SRC, "pki", NULL);
- ret = fu_keyring_add_public_keys (keyring, pki_dir, &error);
- g_assert_no_error (error);
- g_assert_true (ret);
-
- /* verify with GnuPG */
- fw_pass = g_build_filename (TESTDATADIR_SRC, "colorhug", "firmware.bin", NULL);
- blob_pass = fu_common_get_contents_bytes (fw_pass, &error);
- g_assert_no_error (error);
- g_assert_nonnull (blob_pass);
- blob_sig = g_bytes_new_static (sig_gpgme, strlen (sig_gpgme));
- result_pass = fu_keyring_verify_data (keyring, blob_pass, blob_sig,
- FU_KEYRING_VERIFY_FLAG_NONE,
- &error);
- g_assert_no_error (error);
- g_assert_nonnull (result_pass);
- g_assert_cmpint (fu_keyring_result_get_timestamp (result_pass), == , 1438072952);
- g_assert_cmpstr (fu_keyring_result_get_authority (result_pass), == ,
- "3FC6B804410ED0840D8F2F9748A6D80E4538BAC2");
-
- /* verify will fail with GnuPG */
- fw_fail = g_build_filename (TESTDATADIR_DST, "colorhug", "colorhug-als-3.0.2.cab", NULL);
- blob_fail = fu_common_get_contents_bytes (fw_fail, &error);
- g_assert_no_error (error);
- g_assert_nonnull (blob_fail);
- result_fail = fu_keyring_verify_data (keyring, blob_fail, blob_sig,
- FU_KEYRING_VERIFY_FLAG_NONE, &error);
- g_assert_error (error, FWUPD_ERROR, FWUPD_ERROR_SIGNATURE_INVALID);
- g_assert_null (result_fail);
- g_clear_error (&error);
-#else
- g_test_skip ("no GnuPG support enabled");
-#endif
-}
-
-static void
-fu_keyring_pkcs7_func (gconstpointer user_data)
-{
-#ifdef ENABLE_PKCS7
- gboolean ret;
- g_autofree gchar *fw_fail = NULL;
- g_autofree gchar *fw_pass = NULL;
- g_autofree gchar *pki_dir = NULL;
- g_autofree gchar *sig_fn = NULL;
- g_autofree gchar *sig_fn2 = NULL;
- g_autoptr(FuKeyring) keyring = NULL;
- g_autoptr(FuKeyringResult) result_fail = NULL;
- g_autoptr(FuKeyringResult) result_pass = NULL;
- g_autoptr(GBytes) blob_fail = NULL;
- g_autoptr(GBytes) blob_pass = NULL;
- g_autoptr(GBytes) blob_sig = NULL;
- g_autoptr(GBytes) blob_sig2 = NULL;
- g_autoptr(GError) error = NULL;
-
- /* add keys to keyring */
- keyring = fu_keyring_pkcs7_new ();
- ret = fu_keyring_setup (keyring, &error);
- g_assert_no_error (error);
- g_assert_true (ret);
- pki_dir = g_build_filename (TESTDATADIR_SRC, "pki", NULL);
- ret = fu_keyring_add_public_keys (keyring, pki_dir, &error);
- g_assert_no_error (error);
- g_assert_true (ret);
-
- /* verify with a signature from the old LVFS */
- fw_pass = g_build_filename (TESTDATADIR_SRC, "colorhug", "firmware.bin", NULL);
- blob_pass = fu_common_get_contents_bytes (fw_pass, &error);
- g_assert_no_error (error);
- g_assert_nonnull (blob_pass);
- sig_fn = g_build_filename (TESTDATADIR_SRC, "colorhug", "firmware.bin.p7b", NULL);
- blob_sig = fu_common_get_contents_bytes (sig_fn, &error);
- g_assert_no_error (error);
- g_assert_nonnull (blob_sig);
- result_pass = fu_keyring_verify_data (keyring, blob_pass, blob_sig,
- FU_KEYRING_VERIFY_FLAG_DISABLE_TIME_CHECKS,
- &error);
- g_assert_no_error (error);
- g_assert_nonnull (result_pass);
- g_assert_cmpint (fu_keyring_result_get_timestamp (result_pass), >= , 1502871248);
- g_assert_cmpstr (fu_keyring_result_get_authority (result_pass), == , "O=Linux Vendor Firmware Project,CN=LVFS CA");
-
- /* verify will fail with a self-signed signature */
- sig_fn2 = g_build_filename (TESTDATADIR_DST, "colorhug", "firmware.bin.p7c", NULL);
- blob_sig2 = fu_common_get_contents_bytes (sig_fn2, &error);
- g_assert_no_error (error);
- g_assert_nonnull (blob_sig2);
- result_fail = fu_keyring_verify_data (keyring, blob_pass, blob_sig2,
- FU_KEYRING_VERIFY_FLAG_NONE, &error);
- g_assert_error (error, FWUPD_ERROR, FWUPD_ERROR_SIGNATURE_INVALID);
- g_assert_null (result_fail);
- g_clear_error (&error);
-
- /* verify will fail with valid signature and different data */
- fw_fail = g_build_filename (TESTDATADIR_DST, "colorhug", "colorhug-als-3.0.2.cab", NULL);
- blob_fail = fu_common_get_contents_bytes (fw_fail, &error);
- g_assert_no_error (error);
- g_assert_nonnull (blob_fail);
- result_fail = fu_keyring_verify_data (keyring, blob_fail, blob_sig,
- FU_KEYRING_VERIFY_FLAG_NONE, &error);
- g_assert_error (error, FWUPD_ERROR, FWUPD_ERROR_SIGNATURE_INVALID);
- g_assert_null (result_fail);
- g_clear_error (&error);
-#else
- g_test_skip ("no GnuTLS support enabled");
-#endif
-}
-
-static void
-fu_keyring_pkcs7_self_signed_func (gconstpointer user_data)
-{
-#ifdef ENABLE_PKCS7
- gboolean ret;
- g_autoptr(FuKeyring) kr = NULL;
- g_autoptr(FuKeyringResult) kr_result = NULL;
- g_autoptr(GBytes) payload = NULL;
- g_autoptr(GBytes) signature = NULL;
- g_autoptr(GError) error = NULL;
-
-#ifndef HAVE_GNUTLS_3_6_0
- /* required to create the private key correctly */
- g_test_skip ("GnuTLS version too old");
- return;
-#endif
-
- /* create detached signature and verify */
- kr = fu_keyring_pkcs7_new ();
- ret = fu_keyring_setup (kr, &error);
- g_assert_no_error (error);
- g_assert_true (ret);
- payload = fu_common_get_contents_bytes ("/etc/machine-id", &error);
- g_assert_no_error (error);
- g_assert_nonnull (payload);
- signature = fu_keyring_sign_data (kr, payload, FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP, &error);
- g_assert_no_error (error);
- g_assert_nonnull (signature);
- ret = fu_common_set_contents_bytes ("/tmp/test.p7b", signature, &error);
- g_assert_no_error (error);
- g_assert_true (ret);
- kr_result = fu_keyring_verify_data (kr, payload, signature,
- FU_KEYRING_VERIFY_FLAG_USE_CLIENT_CERT, &error);
- g_assert_no_error (error);
- g_assert_nonnull (kr_result);
-#else
- g_test_skip ("no GnuTLS support enabled");
-#endif
-}
-
static GBytes *
_build_cab (GCabCompression compression, ...)
{
@@ -3209,11 +3022,5 @@ main (int argc, char **argv)
fu_plugin_list_func);
g_test_add_data_func ("/fwupd/plugin-list{depsolve}", self,
fu_plugin_list_depsolve_func);
- g_test_add_data_func ("/fwupd/keyring{gpg}", self,
- fu_keyring_gpg_func);
- g_test_add_data_func ("/fwupd/keyring{pkcs7}", self,
- fu_keyring_pkcs7_func);
- g_test_add_data_func ("/fwupd/keyring{pkcs7-self-signed}", self,
- fu_keyring_pkcs7_self_signed_func);
return g_test_run ();
}
diff --git a/src/fu-tool.c b/src/fu-tool.c
index 5c18c7ec2..dce0a6368 100644
--- a/src/fu-tool.c
+++ b/src/fu-tool.c
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include "fu-device-private.h"
#include "fu-engine.h"
@@ -1376,8 +1377,8 @@ fu_util_self_sign (FuUtilPrivate *priv, gchar **values, GError **error)
if (!fu_util_start_engine (priv, FU_ENGINE_LOAD_FLAG_NONE, error))
return FALSE;
sig = fu_engine_self_sign (priv->engine, values[0],
- FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP |
- FU_KEYRING_SIGN_FLAG_ADD_CERT, error);
+ JCAT_SIGN_FLAG_ADD_TIMESTAMP |
+ JCAT_SIGN_FLAG_ADD_CERT, error);
if (sig == NULL)
return FALSE;
g_print ("%s\n", sig);
diff --git a/src/meson.build b/src/meson.build
index e9aac607e..aae719fef 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -4,21 +4,8 @@ if build_daemon
)
endif
-keyring_deps = []
-keyring_src = []
systemd_src = []
-if get_option('gpg')
- keyring_src += 'fu-keyring-gpg.c'
- keyring_deps += gpgme
- keyring_deps += gpgerror
-endif
-
-if get_option('pkcs7')
- keyring_src += 'fu-keyring-pkcs7.c'
- keyring_deps += gnutls
-endif
-
if get_option('systemd')
systemd_src += 'fu-systemd.c'
endif
@@ -132,7 +119,6 @@ fwupdtool = executable(
export_dynamic : true,
sources : [
'fu-tool.c',
- keyring_src,
'fu-config.c',
'fu-debug.c',
'fu-device-list.c',
@@ -141,8 +127,6 @@ fwupdtool = executable(
'fu-history.c',
'fu-idle.c',
'fu-install-task.c',
- 'fu-keyring.c',
- 'fu-keyring-result.c',
'fu-keyring-utils.c',
'fu-plugin-list.c',
'fu-progressbar.c',
@@ -156,7 +140,7 @@ fwupdtool = executable(
fwupdplugin_incdir,
],
dependencies : [
- keyring_deps,
+ libjcat,
libxmlb,
libgcab,
giounix,
@@ -233,7 +217,6 @@ executable(
resources_src,
fu_hash,
sources : [
- keyring_src,
'fu-config.c',
'fu-debug.c',
'fu-device-list.c',
@@ -242,8 +225,6 @@ executable(
'fu-history.c',
'fu-idle.c',
'fu-install-task.c',
- 'fu-keyring.c',
- 'fu-keyring-result.c',
'fu-keyring-utils.c',
'fu-main.c',
'fu-plugin-list.c',
@@ -256,7 +237,7 @@ executable(
fwupdplugin_incdir,
],
dependencies : [
- keyring_deps,
+ libjcat,
libxmlb,
libgcab,
giounix,
@@ -272,7 +253,7 @@ executable(
],
link_with : [
fwupd,
- fwupdplugin
+ fwupdplugin,
],
c_args : [
'-DFU_OFFLINE_DESTDIR=""',
@@ -293,7 +274,6 @@ if get_option('tests')
test_deps,
fu_hash,
sources : [
- keyring_src,
'fu-config.c',
'fu-device-list.c',
'fu-engine.c',
@@ -301,8 +281,6 @@ if get_option('tests')
'fu-history.c',
'fu-idle.c',
'fu-install-task.c',
- 'fu-keyring.c',
- 'fu-keyring-result.c',
'fu-keyring-utils.c',
'fu-plugin-list.c',
'fu-progressbar.c',
@@ -316,7 +294,7 @@ if get_option('tests')
fwupdplugin_incdir,
],
dependencies : [
- keyring_deps,
+ libjcat,
libxmlb,
libgcab,
giounix,
diff --git a/subprojects/.gitignore b/subprojects/.gitignore
index 4d276a280..c607d93e3 100644
--- a/subprojects/.gitignore
+++ b/subprojects/.gitignore
@@ -1,4 +1,5 @@
gusb
gcab
flashrom
+libjcat
libxmlb
diff --git a/subprojects/libjcat.wrap b/subprojects/libjcat.wrap
new file mode 100644
index 000000000..15615559a
--- /dev/null
+++ b/subprojects/libjcat.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory = libjcat
+url = https://github.com/hughsie/libjcat.git
+revision = master