Add helper code to validate public key signatures

We'll use this in the future for checking device firmware.
This commit is contained in:
Richard Hughes 2015-04-14 13:52:34 +01:00
parent 8ccb1af4fe
commit 36a889034c
14 changed files with 547 additions and 2 deletions

View File

@ -132,6 +132,20 @@ if test x$enable_colorhug != xno; then
fi
AM_CONDITIONAL(HAVE_COLORHUG, test x$enable_colorhug = xyes)
# gpgme support
AC_MSG_CHECKING([for gpgme])
if ! test -x "/usr/bin/gpgme-config"; then
AC_MSG_ERROR([Cannot locate gpgme])
else
AC_MSG_RESULT([yes])
GPGME_CFLAGS="`\"/usr/bin/gpgme-config\" --cflags`"
GPGME_LIBS="`\"/usr/bin/gpgme-config\" --libs`"
GPGME_CFLAGS+=" `\"/usr/bin/gpg-error-config\" --cflags`"
GPGME_LIBS+=" `\"/usr/bin/gpg-error-config\" --libs`"
AC_SUBST([GPGME_CFLAGS])
AC_SUBST([GPGME_LIBS])
fi
# UEFI support
AC_ARG_ENABLE(uefi, AS_HELP_STRING([--enable-uefi],[Enable ColorHug support]),
enable_uefi=$enableval, enable_uefi=yes)
@ -161,6 +175,7 @@ libfwupd/fwupd.pc
libfwupd/Makefile
man/Makefile
data/Makefile
data/pki/Makefile
data/tests/Makefile
policy/Makefile
po/Makefile.in

View File

@ -76,6 +76,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';'
%license COPYING
%{_libexecdir}/fwupd
%{_bindir}/fwupdmgr
%{_sysconfdir}/pki/fwupd
%{_sysconfdir}/dbus-1/system.d/org.freedesktop.fwupd.conf
%{_datadir}/dbus-1/interfaces/org.freedesktop.fwupd.xml
%{_datadir}/polkit-1/actions/org.freedesktop.fwupd.policy

View File

@ -1,4 +1,4 @@
SUBDIRS = tests
SUBDIRS = tests pki
dbusdir = $(sysconfdir)/dbus-1/system.d
dist_dbus_DATA = org.freedesktop.fwupd.conf

View File

@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBFUr0UoBCACsdOLuTJ81dICrSvUhyznBsL4WgEa2RUbEjJuaXwrEyPMikHE1
Clda2YI7VbpCgIVq8Zy63CGJ4Xqs2T6pyetaXnbX8J0C+7wg2IfPv7pUyCsP7/JR
HRB2GNelCWrsGArN1cOPI0ESH4yHWKF9KCGlpsLfSHmvF7D8vcKlKQUlO4T6lxOP
SNjMSXkMsxfDDhl1mzqrwxfU4V6nnPcuMwU7tvg+39PioP4Ny1tKP4SSpBfh7qwz
XXRd505dqNLOubxmOPZ5rznVkKmW2cwahO6fr5zVA8/2TDZQ79mdbfvSJVlW06qs
C5PYmLnBjyzE5uQ4oxSIuUEiMfqrn3Qs6PhhABEBAAG0Ikh1Z2hza2kgTGltaXRl
ZCA8aW5mb0BodWdoc2tpLmNvbT6JATgEEwECACIFAlUr0UoCGwMGCwkIBwMCBhUI
AgkKCwQWAgMBAh4BAheAAAoJEK2KUo/sRIge/fUH/Rblgzh5GeB0Zp2U9W+r26iJ
t1AD5a/fKxQahz/pwMkevQCCMzI1vpX12P3HtACZOD3Zjh9RXY6Z3033YZjrRApe
FkOVfcyUF1nP/z2Ox3jE3+B8v1u0UzH/MqtF/1095mqvR7gllE288KDqu7bvd5l3
z4IETk5qqoeCe9LYc8aob973dbocyS/gou/FLCKxoXVEe8DPRwv8qmXlXOujxdxd
FcslpYqtjj4fgUswQ/cY/a1UcAX5zCnVqFbU7oJH2uTNewKuaZ2wgPbnzvwx8JYl
VfFdPN7GZ0NMrZDLeJ0SLXer/9+qAKNH4UpQS9axXQL+VKOzsZCXuv31VDCj5Jy5
AQ0EVSvRSgEIAMgVrZP3LmA9bx7B8l+agVh5DNXrMixX9jhZ0Yfn8+UIMMNTZziD
ZV3nXxswKPrcsqQ+KP9iUwq3V2oio46bvHiMMoZSGCaTv4yiKOliFOMYr9NAOSTZ
8mOI24dNXI9XqQ7ZA8m4uKmgHZQUIUUlx693uRI2Wmk/Y5XEBoL2+XdA5KalO+36
27YXpdyU3GiMCOtSBLWNfBxXw6oKdNUp+8o/fYrmQnBxuGgmVlcZEmjhrIGXaCH1
iDeWIFqaM/S+DXMF3bgqvqRZq1U2RwT2oxapAuaG/0I5JaKKpb3HqMCXfOUxpFPk
zgUYpHatUcePG/94K8N8CRjnJ+l83H5PewcAEQEAAYkBHwQYAQIACQUCVSvRSgIb
DAAKCRCtilKP7ESIHrrcCACc6UTZzVGbVq9pXSz2Bw2xQpAEAhnnedPgfXwEJMM0
24bMUNsyJcQZAW1d5KfJYNAihOfse3oDQ/hJAycTK3GAHsPfljEQjWGn27eC8Fxu
mHpfNpxbTirChfepCNctZG818Hp2v+K4X/PjyQMQ6J5H9oinnlasVQ6wzdZifnWm
7E5OL0NV/ni9xqq4fC5y5qxNBeYVmHUF4H0E3VOuCbESAOnUDpCo998Dc68eZEmV
f3IMukvvnxM9VOZQSnp7J/kkhPB5fim2z2qrlJK9N+tBjAMugxtnAV2fIaZYTiba
SnN2hheFd9Y0nMmWbwRqFtwMG1m/tS3JlD52Rpwzk59B
=WFoi
-----END PGP PUBLIC KEY BLOCK-----

4
data/pki/Makefile.am Normal file
View File

@ -0,0 +1,4 @@
pkidir = $(sysconfdir)/pki/fwupd
dist_pki_DATA = GPG-KEY-Hughski-Limited
-include $(top_srcdir)/git.mk

View File

@ -1,4 +1,7 @@
test_files = colorhug-als-3.0.2.cab
test_files = \
colorhug-als-3.0.2.cab \
firmware.bin \
pki/GPG-KEY-Hughski-Limited
EXTRA_DIST = $(test_files)

BIN
data/tests/firmware.bin Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
../../pki/GPG-KEY-Hughski-Limited

View File

@ -71,6 +71,9 @@ fwupd_error_quark (void)
g_dbus_error_register_error (quark,
FWUPD_ERROR_NOT_SUPPORTED,
"org.freedesktop.fwupd.NotSupported");
g_dbus_error_register_error (quark,
FWUPD_ERROR_SIGNATURE_INVALID,
"org.freedesktop.fwupd.SignatureInvalid");
}
return quark;
}

View File

@ -39,6 +39,7 @@
* @FWUPD_ERROR_NOT_FOUND: No matching device exists
* @FWUPD_ERROR_NOTHING_TO_DO: Nothing to do
* @FWUPD_ERROR_NOT_SUPPORTED: Action was not possible
* @FWUPD_ERROR_SIGNATURE_INVALID: Signature was invalid
*
* The error code.
**/
@ -54,6 +55,7 @@ typedef enum {
FWUPD_ERROR_NOT_FOUND, /* Since: 0.1.1 */
FWUPD_ERROR_NOTHING_TO_DO, /* Since: 0.1.1 */
FWUPD_ERROR_NOT_SUPPORTED, /* Since: 0.1.1 */
FWUPD_ERROR_SIGNATURE_INVALID, /* Since: 0.1.2 */
/*< private >*/
FWUPD_ERROR_LAST
} FwupdError;

View File

@ -11,6 +11,7 @@ AM_CPPFLAGS = \
$(PIE_CFLAGS) \
$(POLKIT_CFLAGS) \
$(UEFI_CFLAGS) \
$(GPGME_CFLAGS) \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(top_srcdir)/libfwupd \
@ -80,6 +81,8 @@ fwupd_SOURCES = \
fu-debug.h \
fu-device.c \
fu-device.h \
fu-keyring.c \
fu-keyring.h \
fu-pending.c \
fu-pending.h \
fu-provider.c \
@ -109,6 +112,7 @@ fwupd_LDADD = \
$(GUDEV_LIBS) \
$(POLKIT_LIBS) \
$(SQLITE_LIBS) \
$(GPGME_LIBS) \
$(UEFI_LIBS)
fwupd_LDFLAGS = \
@ -133,6 +137,8 @@ fu_self_test_SOURCES = \
fu-cab.h \
fu-device.c \
fu-device.h \
fu-keyring.c \
fu-keyring.h \
fu-pending.c \
fu-pending.h \
fu-provider.c \
@ -146,6 +152,7 @@ fu_self_test_LDADD = \
$(APPSTREAM_GLIB_LIBS) \
$(SQLITE_LIBS) \
$(GCAB_LIBS) \
$(GPGME_LIBS) \
$(GLIB_LIBS)
fu_self_test_CFLAGS = $(WARNINGFLAGS_C)

368
src/fu-keyring.c Normal file
View File

@ -0,0 +1,368 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <fwupd.h>
#include <gpgme.h>
#include "fu-cleanup.h"
#include "fu-keyring.h"
static void fu_keyring_finalize (GObject *object);
#define FU_KEYRING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FU_TYPE_KEYRING, FuKeyringPrivate))
/**
* FuKeyringPrivate:
*
* Private #FuKeyring data
**/
struct _FuKeyringPrivate
{
gpgme_ctx_t ctx;
};
G_DEFINE_TYPE (FuKeyring, fu_keyring, G_TYPE_OBJECT)
/**
* fu_keyring_setup:
**/
static gboolean
fu_keyring_setup (FuKeyring *keyring, GError **error)
{
gpgme_error_t rc;
g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
if (keyring->priv->ctx != NULL)
return TRUE;
/* check version */
gpgme_check_version (NULL);
/* startup gpgme */
rc = gpg_err_init ();
if (rc != GPG_ERR_NO_ERROR) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to startup GPG: %s",
gpgme_strerror (rc));
return FALSE;
}
/* create a new GPG context */
rc = gpgme_new (&keyring->priv->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 (keyring->priv->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;
}
/* enable armor mode */
gpgme_set_armor (keyring->priv->ctx, TRUE);
return TRUE;
}
/**
* fu_keyring_add_public_key:
**/
gboolean
fu_keyring_add_public_key (FuKeyring *keyring, const gchar *filename, GError **error)
{
gboolean ret = TRUE;
gpgme_data_t data = NULL;
gpgme_error_t rc;
g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
/* import public key */
rc = gpgme_data_new_from_file (&data, filename, 1);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to load %s: %s",
filename, gpgme_strerror (rc));
goto out;
}
rc = gpgme_op_import (keyring->priv->ctx, data);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to import %s: %s",
filename, gpgme_strerror (rc));
goto out;
}
out:
gpgme_data_release (data);
return ret;
}
/**
* fu_keyring_add_public_keys:
**/
gboolean
fu_keyring_add_public_keys (FuKeyring *keyring, const gchar *dirname, GError **error)
{
_cleanup_dir_close_ GDir *dir = NULL;
g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
g_return_val_if_fail (dirname != NULL, FALSE);
/* setup context */
if (!fu_keyring_setup (keyring, error))
return FALSE;
/* search all the public key files */
dir = g_dir_open (dirname, 0, error);
if (dir == NULL)
return FALSE;
do {
const gchar *filename;
_cleanup_free_ gchar *path_tmp = NULL;
filename = g_dir_read_name (dir);
if (filename == NULL)
break;
path_tmp = g_build_filename (dirname, filename, NULL);
if (!fu_keyring_add_public_key (keyring, path_tmp, error))
return FALSE;
} while (TRUE);
return TRUE;
}
/**
* fu_keyring_check_signature:
**/
static gboolean
fu_keyring_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;
}
/**
* fu_keyring_verify_file:
**/
gboolean
fu_keyring_verify_file (FuKeyring *keyring,
const gchar *filename,
const gchar *signature,
GError **error)
{
gboolean has_header;
gboolean ret = TRUE;
gpgme_data_t data = NULL;
gpgme_data_t sig = NULL;
gpgme_error_t rc;
gpgme_signature_t s;
gpgme_verify_result_t result;
_cleanup_string_free_ GString *sig_v1 = NULL;
g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (signature != NULL, FALSE);
/* setup context */
if (!fu_keyring_setup (keyring, error))
return FALSE;
/* has header already */
has_header = g_strstr_len (signature, -1, "BEGIN PGP SIGNATURE") != NULL;
/* load file data */
rc = gpgme_data_new_from_file (&data, filename, 1);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to load %s: %s",
filename, gpgme_strerror (rc));
goto out;
}
/* load signature */
sig_v1 = g_string_new ("");
if (!has_header) {
g_string_append (sig_v1, "-----BEGIN PGP SIGNATURE-----\n");
g_string_append (sig_v1, "Version: GnuPG v1\n\n");
}
g_string_append_printf (sig_v1, "%s\n", signature);
if (!has_header)
g_string_append (sig_v1, "-----END PGP SIGNATURE-----\n");
rc = gpgme_data_new_from_mem (&sig, sig_v1->str, sig_v1->len, 0);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to load signature %s: %s",
signature, gpgme_strerror (rc));
goto out;
}
/* verify */
rc = gpgme_op_verify (keyring->priv->ctx, sig, data, NULL);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to verify %s: %s",
filename, gpgme_strerror (rc));
goto out;
}
/* verify the result */
result = gpgme_op_verify_result (keyring->priv->ctx);
if (result == NULL) {
ret = FALSE;
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"no result record from libgpgme");
goto out;
}
/* look at each signature */
for (s = result->signatures; s != NULL ; s = s->next ) {
ret = fu_keyring_check_signature (s, error);
if (!ret)
goto out;
}
out:
if (data != NULL)
gpgme_data_release (data);
if (sig != NULL)
gpgme_data_release (sig);
return ret;
}
/**
* fu_keyring_class_init:
**/
static void
fu_keyring_class_init (FuKeyringClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = fu_keyring_finalize;
g_type_class_add_private (klass, sizeof (FuKeyringPrivate));
}
/**
* fu_keyring_init:
**/
static void
fu_keyring_init (FuKeyring *keyring)
{
keyring->priv = FU_KEYRING_GET_PRIVATE (keyring);
}
/**
* fu_keyring_finalize:
**/
static void
fu_keyring_finalize (GObject *object)
{
FuKeyring *keyring = FU_KEYRING (object);
FuKeyringPrivate *priv = keyring->priv;
if (priv->ctx != NULL)
gpgme_release (priv->ctx);
G_OBJECT_CLASS (fu_keyring_parent_class)->finalize (object);
}
/**
* fu_keyring_new:
**/
FuKeyring *
fu_keyring_new (void)
{
FuKeyring *keyring;
keyring = g_object_new (FU_TYPE_KEYRING, NULL);
return FU_KEYRING (keyring);
}

70
src/fu-keyring.h Normal file
View File

@ -0,0 +1,70 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __FU_KEYRING_H
#define __FU_KEYRING_H
#include <glib-object.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define FU_TYPE_KEYRING (fu_keyring_get_type ())
#define FU_KEYRING(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FU_TYPE_KEYRING, FuKeyring))
#define FU_KEYRING_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), FU_TYPE_KEYRING, FuKeyringClass))
#define FU_IS_KEYRING(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FU_TYPE_KEYRING))
#define FU_IS_KEYRING_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FU_TYPE_KEYRING))
#define FU_KEYRING_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FU_TYPE_KEYRING, FuKeyringClass))
#define FU_KEYRING_ERROR fu_keyring_error_quark()
typedef struct _FuKeyringPrivate FuKeyringPrivate;
typedef struct _FuKeyring FuKeyring;
typedef struct _FuKeyringClass FuKeyringClass;
struct _FuKeyring
{
GObject parent;
FuKeyringPrivate *priv;
};
struct _FuKeyringClass
{
GObjectClass parent_class;
};
GType fu_keyring_get_type (void);
FuKeyring *fu_keyring_new (void);
gboolean fu_keyring_add_public_keys (FuKeyring *keyring,
const gchar *dirname,
GError **error);
gboolean fu_keyring_add_public_key (FuKeyring *keyring,
const gchar *filename,
GError **error);
gboolean fu_keyring_verify_file (FuKeyring *keyring,
const gchar *filename,
const gchar *signature,
GError **error);
G_END_DECLS
#endif /* __FU_KEYRING_H */

View File

@ -28,6 +28,7 @@
#include "fu-cab.h"
#include "fu-cleanup.h"
#include "fu-keyring.h"
#include "fu-pending.h"
#include "fu-provider-fake.h"
@ -287,6 +288,45 @@ fu_pending_func (void)
g_clear_error (&error);
}
static void
fu_keyring_func (void)
{
gboolean ret;
_cleanup_error_free_ GError *error = NULL;
_cleanup_free_ gchar *fw_fail = NULL;
_cleanup_free_ gchar *fw_pass = NULL;
_cleanup_free_ gchar *pki_dir = NULL;
_cleanup_object_unref_ FuKeyring *keyring = NULL;
const gchar *sig =
"iQEcBAABAgAGBQJVK9RSAAoJEBesuo36lw4XvmoH/3tJL5wVRN+rsvoo/FMc3w4g"
"I7rizJNIgQ04WVTREX6tRZJfxYzGAaeokVeqah2JUC4u1j22BDkoG/Fs+/2/Z/OP"
"PTxMoiEzfzryWpVwt20As+H9CmMZGdCfvKgnWiosAENCzE7JE1miJ4YvTpRtdPMh"
"erz8DqLTFAfr72aimf5hBs8ZFkBGPGjljdTDv78hk2WDep5E1+1swGoFbhDcXyih"
"8GZjSLP7XkKo23/p6odCJD3SkkDE7jIUMA8GrTHHXIhF41UsriKx2ERYoau5k3cX"
"OdK3/cRQ6BeuSBMLr7hUpa0RwlKUKex/I7+p/T9Ohk4lNnGS7GpE45RbpflK1VQ="
"=0D8+";
/* add test keys to keyring */
keyring = fu_keyring_new ();
pki_dir = fu_test_get_filename ("pki");
ret = fu_keyring_add_public_keys (keyring, pki_dir, &error);
g_assert_no_error (error);
g_assert (ret);
/* verify */
fw_pass = fu_test_get_filename ("firmware.bin");
ret = fu_keyring_verify_file (keyring, fw_pass, sig, &error);
g_assert_no_error (error);
g_assert (ret);
/* verify will fail */
fw_fail = fu_test_get_filename ("colorhug-als-3.0.2.cab");
ret = fu_keyring_verify_file (keyring, fw_fail, sig, &error);
g_assert_error (error, FWUPD_ERROR, FWUPD_ERROR_SIGNATURE_INVALID);
g_assert (!ret);
g_clear_error (&error);
}
int
main (int argc, char **argv)
{
@ -299,6 +339,7 @@ main (int argc, char **argv)
g_test_add_func ("/fwupd/cab", fu_cab_func);
g_test_add_func ("/fwupd/pending", fu_pending_func);
g_test_add_func ("/fwupd/provider", fu_provider_func);
g_test_add_func ("/fwupd/keyring", fu_keyring_func);
return g_test_run ();
}