mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-05 15:55:45 +00:00
Add helper code to validate public key signatures
We'll use this in the future for checking device firmware.
This commit is contained in:
parent
8ccb1af4fe
commit
36a889034c
15
configure.ac
15
configure.ac
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS = tests
|
||||
SUBDIRS = tests pki
|
||||
|
||||
dbusdir = $(sysconfdir)/dbus-1/system.d
|
||||
dist_dbus_DATA = org.freedesktop.fwupd.conf
|
||||
|
30
data/pki/GPG-KEY-Hughski-Limited
Normal file
30
data/pki/GPG-KEY-Hughski-Limited
Normal 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
4
data/pki/Makefile.am
Normal file
@ -0,0 +1,4 @@
|
||||
pkidir = $(sysconfdir)/pki/fwupd
|
||||
dist_pki_DATA = GPG-KEY-Hughski-Limited
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
@ -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
BIN
data/tests/firmware.bin
Normal file
Binary file not shown.
1
data/tests/pki/GPG-KEY-Hughski-Limited
Symbolic link
1
data/tests/pki/GPG-KEY-Hughski-Limited
Symbolic link
@ -0,0 +1 @@
|
||||
../../pki/GPG-KEY-Hughski-Limited
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
368
src/fu-keyring.c
Normal 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
70
src/fu-keyring.h
Normal 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 */
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user