lib/sign: initial implementation
Added the initial version of signing interface allowing to allowing to sign and verify commits. Implemented initial signing modules: - dummy -- simple module allowing to sign/verify with ASCII string - ed25519 -- module allowing to sign/verify commit with ed25519 (EdDSA) signature scheme provided by libsodium library. Signed-off-by: Denis Pynkin <denis.pynkin@collabora.com>
This commit is contained in:
parent
84c8164610
commit
edbbe1c4f2
|
|
@ -46,6 +46,8 @@ libostree_public_headers = \
|
||||||
src/libostree/ostree-repo-finder-mount.h \
|
src/libostree/ostree-repo-finder-mount.h \
|
||||||
src/libostree/ostree-repo-finder-override.h \
|
src/libostree/ostree-repo-finder-override.h \
|
||||||
src/libostree/ostree-kernel-args.h \
|
src/libostree/ostree-kernel-args.h \
|
||||||
|
src/libostree/ostree-sign.h \
|
||||||
|
src/libostree/ostree-sign-ed25519.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# This one is generated via configure.ac, and the gtk-doc
|
# This one is generated via configure.ac, and the gtk-doc
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,20 @@ libostree_1_la_CFLAGS += $(OT_DEP_SELINUX_CFLAGS)
|
||||||
libostree_1_la_LIBADD += $(OT_DEP_SELINUX_LIBS)
|
libostree_1_la_LIBADD += $(OT_DEP_SELINUX_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
libostree_1_la_SOURCES += \
|
||||||
|
src/libostree/ostree-sign.c \
|
||||||
|
src/libostree/ostree-sign.h \
|
||||||
|
src/libostree/ostree-sign-dummy.c \
|
||||||
|
src/libostree/ostree-sign-dummy.h \
|
||||||
|
src/libostree/ostree-sign-ed25519.c \
|
||||||
|
src/libostree/ostree-sign-ed25519.h \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
if USE_LIBSODIUM
|
||||||
|
libostree_1_la_CFLAGS += $(OT_DEP_LIBSODIUM_CFLAGS)
|
||||||
|
libostree_1_la_LIBADD += $(OT_DEP_LIBSODIUM_LIBS)
|
||||||
|
endif # USE_LIBSODIUM
|
||||||
|
|
||||||
# XXX: work around clang being passed -fstack-clash-protection which it doesn't understand
|
# XXX: work around clang being passed -fstack-clash-protection which it doesn't understand
|
||||||
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1672012
|
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1672012
|
||||||
INTROSPECTION_SCANNER_ENV = CC=gcc
|
INTROSPECTION_SCANNER_ENV = CC=gcc
|
||||||
|
|
|
||||||
|
|
@ -112,11 +112,6 @@ ostree_SOURCES += \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_LIBSODIUM
|
|
||||||
ostree_CFLAGS += $(OT_DEP_LIBSODIUM_CFLAGS)
|
|
||||||
ostree_LDADD += $(OT_DEP_LIBSODIUM_LIBS)
|
|
||||||
endif # USE_LIBSODIUM
|
|
||||||
|
|
||||||
if USE_CURL_OR_SOUP
|
if USE_CURL_OR_SOUP
|
||||||
ostree_SOURCES += src/ostree/ot-remote-builtin-add-cookie.c \
|
ostree_SOURCES += src/ostree/ot-remote-builtin-add-cookie.c \
|
||||||
src/ostree/ot-remote-builtin-delete-cookie.c \
|
src/ostree/ot-remote-builtin-delete-cookie.c \
|
||||||
|
|
@ -166,3 +161,8 @@ if USE_LIBARCHIVE
|
||||||
ostree_CFLAGS += $(OT_DEP_LIBARCHIVE_CFLAGS)
|
ostree_CFLAGS += $(OT_DEP_LIBARCHIVE_CFLAGS)
|
||||||
ostree_LDADD += $(OT_DEP_LIBARCHIVE_LIBS)
|
ostree_LDADD += $(OT_DEP_LIBARCHIVE_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_LIBSODIUM
|
||||||
|
ostree_CFLAGS += $(OT_DEP_LIBSODIUM_CFLAGS)
|
||||||
|
ostree_LDADD += $(OT_DEP_LIBSODIUM_LIBS)
|
||||||
|
endif # USE_LIBSODIUM
|
||||||
|
|
|
||||||
|
|
@ -705,3 +705,26 @@ ostree_kernel_args_from_string
|
||||||
ostree_kernel_args_to_strv
|
ostree_kernel_args_to_strv
|
||||||
ostree_kernel_args_to_string
|
ostree_kernel_args_to_string
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>ostree-sign</FILE>
|
||||||
|
OstreeSign
|
||||||
|
OstreeSignDummy
|
||||||
|
OstreeSignEd25519
|
||||||
|
ostree_sign_list_names
|
||||||
|
ostree_sign_commit
|
||||||
|
ostree_sign_commit_verify
|
||||||
|
ostree_sign_data
|
||||||
|
ostree_sign_get_by_name
|
||||||
|
ostree_sign_get_name
|
||||||
|
ostree_sign_detached_metadata_append
|
||||||
|
ostree_sign_metadata_verify
|
||||||
|
ostree_sign_load_pk
|
||||||
|
ostree_sign_set_pk
|
||||||
|
ostree_sign_set_sk
|
||||||
|
ostree_sign_ed25519_keypair_generate
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
ostree_sign_get_type
|
||||||
|
ostree_sign_dummy_get_type
|
||||||
|
ostree_sign_ed25519_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,22 @@
|
||||||
LIBOSTREE_2020.2 {
|
LIBOSTREE_2020.2 {
|
||||||
global:
|
global:
|
||||||
ostree_repo_commit_modifier_set_sepolicy_from_commit;
|
ostree_repo_commit_modifier_set_sepolicy_from_commit;
|
||||||
|
someostree_symbol_deleteme;
|
||||||
|
ostree_sign_get_type;
|
||||||
|
ostree_sign_list_names;
|
||||||
|
ostree_sign_commit;
|
||||||
|
ostree_sign_commit_verify;
|
||||||
|
ostree_sign_data;
|
||||||
|
ostree_sign_get_by_name;
|
||||||
|
ostree_sign_get_name;
|
||||||
|
ostree_sign_detached_metadata_append;
|
||||||
|
ostree_sign_metadata_verify;
|
||||||
|
ostree_sign_load_pk;
|
||||||
|
ostree_sign_set_pk;
|
||||||
|
ostree_sign_set_sk;
|
||||||
|
ostree_sign_dummy_get_type;
|
||||||
|
ostree_sign_ed25519_get_type;
|
||||||
|
ostree_sign_ed25519_keypair_generate;
|
||||||
} LIBOSTREE_2020.1;
|
} LIBOSTREE_2020.1;
|
||||||
|
|
||||||
/* Stub section for the stable release *after* this development one; don't
|
/* Stub section for the stable release *after* this development one; don't
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0+
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "ostree-sign-dummy.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define OSTREE_SIGN_DUMMY_NAME "dummy"
|
||||||
|
|
||||||
|
#define OSTREE_SIGN_METADATA_DUMMY_KEY "ostree.sign.dummy"
|
||||||
|
#define OSTREE_SIGN_METADATA_DUMMY_TYPE "aay"
|
||||||
|
|
||||||
|
#define OSTREE_SIGN_DUMMY_SIGNATURE "dummysign"
|
||||||
|
|
||||||
|
struct _OstreeSignDummy
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
gchar *signature_ascii;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_dummy_iface_init (OstreeSignInterface *self);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (OstreeSignDummy, ostree_sign_dummy, G_TYPE_OBJECT,
|
||||||
|
G_IMPLEMENT_INTERFACE (OSTREE_TYPE_SIGN, ostree_sign_dummy_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_dummy_iface_init (OstreeSignInterface *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
self->data = ostree_sign_dummy_data;
|
||||||
|
self->get_name = ostree_sign_dummy_get_name;
|
||||||
|
self->metadata_key = ostree_sign_dummy_metadata_key;
|
||||||
|
self->metadata_format = ostree_sign_dummy_metadata_format;
|
||||||
|
self->metadata_verify = ostree_sign_dummy_metadata_verify;
|
||||||
|
self->set_sk = ostree_sign_dummy_set_signature;
|
||||||
|
self->set_pk = ostree_sign_dummy_set_signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_dummy_class_init (OstreeSignDummyClass *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_dummy_init (OstreeSignDummy *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
self->signature_ascii = g_strdup(OSTREE_SIGN_DUMMY_SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_dummy_set_signature (OstreeSign *self, GVariant *key, GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
OstreeSignDummy *sign = ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
|
||||||
|
|
||||||
|
if (sign->signature_ascii != NULL)
|
||||||
|
g_free(sign->signature_ascii);
|
||||||
|
|
||||||
|
sign->signature_ascii = g_variant_dup_string (key, 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_dummy_data (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
OstreeSignDummy *sign = ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
|
||||||
|
|
||||||
|
*signature = g_bytes_new (sign->signature_ascii, strlen(sign->signature_ascii));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_dummy_get_name (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
g_autofree gchar *name = g_strdup(OSTREE_SIGN_DUMMY_NAME);
|
||||||
|
|
||||||
|
return g_steal_pointer (&name);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_dummy_metadata_key (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_autofree gchar *key = g_strdup(OSTREE_SIGN_METADATA_DUMMY_KEY);
|
||||||
|
return g_steal_pointer (&key);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_dummy_metadata_format (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_autofree gchar *type = g_strdup(OSTREE_SIGN_METADATA_DUMMY_TYPE);
|
||||||
|
return g_steal_pointer (&type);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_dummy_metadata_verify (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *signatures,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
|
|
||||||
|
OstreeSignDummy *sign = ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
|
||||||
|
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
if (signatures == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"signature: dummy: commit have no signatures of my type");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!g_variant_is_of_type (signatures, (GVariantType *) OSTREE_SIGN_METADATA_DUMMY_TYPE))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"signature: dummy: wrong type passed for verification");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (gsize i = 0; i < g_variant_n_children(signatures); i++)
|
||||||
|
{
|
||||||
|
g_autoptr (GVariant) child = g_variant_get_child_value (signatures, i);
|
||||||
|
g_autoptr (GBytes) signature = g_variant_get_data_as_bytes(child);
|
||||||
|
|
||||||
|
gsize sign_size = 0;
|
||||||
|
g_bytes_get_data (signature, &sign_size);
|
||||||
|
g_autofree gchar *sign_ascii = g_strndup(g_bytes_get_data (signature, NULL), sign_size);
|
||||||
|
g_debug("Read signature %d: %s", (gint)i, sign_ascii);
|
||||||
|
|
||||||
|
if (!g_strcmp0(sign_ascii, sign->signature_ascii))
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0+
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ostree-sign.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define OSTREE_TYPE_SIGN_DUMMY (ostree_sign_dummy_get_type ())
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
G_DECLARE_FINAL_TYPE (OstreeSignDummy,
|
||||||
|
ostree_sign_dummy,
|
||||||
|
OSTREE,
|
||||||
|
SIGN_DUMMY,
|
||||||
|
GObject)
|
||||||
|
|
||||||
|
gchar * ostree_sign_dummy_get_name (OstreeSign *self);
|
||||||
|
|
||||||
|
gboolean ostree_sign_dummy_data (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gchar * ostree_sign_dummy_metadata_key (OstreeSign *self);
|
||||||
|
gchar * ostree_sign_dummy_metadata_format (OstreeSign *self);
|
||||||
|
|
||||||
|
gboolean ostree_sign_dummy_metadata_verify (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *signatures,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean ostree_sign_dummy_set_signature (OstreeSign *self, GVariant *key, GError **error);
|
||||||
|
|
||||||
|
void ostree_sign_dummy_finalize (GObject *gobject);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
@ -0,0 +1,342 @@
|
||||||
|
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0+
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "ostree-sign-ed25519.h"
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
#include <sodium.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OSTREE_SIGN_ED25519_NAME "ed25519"
|
||||||
|
|
||||||
|
#define OSTREE_SIGN_METADATA_ED25519_KEY "ostree.sign.ed25519"
|
||||||
|
#define OSTREE_SIGN_METADATA_ED25519_TYPE "aay"
|
||||||
|
|
||||||
|
struct _OstreeSignEd25519
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
gboolean initialized;
|
||||||
|
guchar *secret_key;
|
||||||
|
guchar *public_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_ed25519_iface_init (OstreeSignInterface *self);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (OstreeSignEd25519, ostree_sign_ed25519, G_TYPE_OBJECT,
|
||||||
|
G_IMPLEMENT_INTERFACE (OSTREE_TYPE_SIGN, ostree_sign_ed25519_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_ed25519_iface_init (OstreeSignInterface *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
self->data = ostree_sign_ed25519_data;
|
||||||
|
self->get_name = ostree_sign_ed25519_get_name;
|
||||||
|
self->metadata_key = ostree_sign_ed25519_metadata_key;
|
||||||
|
self->metadata_format = ostree_sign_ed25519_metadata_format;
|
||||||
|
self->metadata_verify = ostree_sign_ed25519_metadata_verify;
|
||||||
|
self->set_sk = ostree_sign_ed25519_set_sk;
|
||||||
|
self->set_pk = ostree_sign_ed25519_set_pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_ed25519_class_init (OstreeSignEd25519Class *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_ed25519_init (OstreeSignEd25519 *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
self->initialized = TRUE;
|
||||||
|
self->secret_key = NULL;
|
||||||
|
self->public_key = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
if (sodium_init() < 0)
|
||||||
|
{
|
||||||
|
self->initialized = FALSE;
|
||||||
|
g_warning ("libsodium library couldn't be initialized");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
g_error ("ed25519 signature isn't supported");
|
||||||
|
#endif /* HAVE_LIBSODIUM */
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_data (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
OstreeSignEd25519 *sign = ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
g_autofree guchar *sig = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((sign->initialized != TRUE) || (sign->secret_key == NULL))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Not able to sign: libsodium library isn't initialized properly");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
unsigned long long sig_size = 0;
|
||||||
|
|
||||||
|
sig = g_malloc0(crypto_sign_BYTES);
|
||||||
|
|
||||||
|
if (crypto_sign_detached (sig,
|
||||||
|
&sig_size,
|
||||||
|
g_bytes_get_data (data, NULL),
|
||||||
|
g_bytes_get_size (data),
|
||||||
|
sign->secret_key))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Not able to sign the object");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("sign: data hash = 0x%x", g_bytes_hash(data));
|
||||||
|
*signature = g_bytes_new (sig, sig_size);
|
||||||
|
return TRUE;
|
||||||
|
#endif /* HAVE_LIBSODIUM */
|
||||||
|
err:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_ed25519_get_name (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
g_autofree gchar *name = g_strdup (OSTREE_SIGN_ED25519_NAME);
|
||||||
|
|
||||||
|
return g_steal_pointer (&name);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_ed25519_metadata_key (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_autofree gchar *key = g_strdup(OSTREE_SIGN_METADATA_ED25519_KEY);
|
||||||
|
return g_steal_pointer (&key);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_ed25519_metadata_format (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_autofree gchar *type = g_strdup (OSTREE_SIGN_METADATA_ED25519_TYPE);
|
||||||
|
return g_steal_pointer (&type);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_metadata_verify (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *signatures,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
OstreeSignEd25519 *sign = ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
|
||||||
|
|
||||||
|
if (signatures == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"signature: ed25519: commit have no signatures of my type");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_variant_is_of_type (signatures, (GVariantType *) OSTREE_SIGN_METADATA_ED25519_TYPE))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"signature: ed25519: wrong type passed for verification");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sign->initialized != TRUE) || (sign->public_key == NULL))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Not able to verify: libsodium library isn't initialized properly");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
g_debug ("verify: data hash = 0x%x", g_bytes_hash(data));
|
||||||
|
|
||||||
|
for (gsize i = 0; i < g_variant_n_children(signatures); i++)
|
||||||
|
{
|
||||||
|
g_autoptr (GVariant) child = g_variant_get_child_value (signatures, i);
|
||||||
|
g_autoptr (GBytes) signature = g_variant_get_data_as_bytes(child);
|
||||||
|
|
||||||
|
g_autofree char * hex = g_malloc0 (crypto_sign_PUBLICKEYBYTES*2 + 1);
|
||||||
|
|
||||||
|
g_debug("Read signature %d: %s", (gint)i, g_variant_print(child, TRUE));
|
||||||
|
|
||||||
|
if (crypto_sign_verify_detached ((guchar *) g_variant_get_data (child),
|
||||||
|
g_bytes_get_data (data, NULL),
|
||||||
|
g_bytes_get_size (data),
|
||||||
|
sign->public_key) != 0)
|
||||||
|
{
|
||||||
|
/* Incorrect signature! */
|
||||||
|
g_debug("Signature couldn't be verified with key '%s'",
|
||||||
|
sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, sign->public_key, crypto_sign_PUBLICKEYBYTES));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = TRUE;
|
||||||
|
g_debug ("Signature verified successfully with key '%s'",
|
||||||
|
sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, sign->public_key, crypto_sign_PUBLICKEYBYTES));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != TRUE)
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Not able to verify: no valid signatures found");
|
||||||
|
#endif /* HAVE_LIBSODIUM */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
ostree_sign_ed25519_keypair_generate (OstreeSign *self,
|
||||||
|
GVariant **out_secret_key,
|
||||||
|
GVariant **out_public_key,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
OstreeSignEd25519 *sign = ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
|
||||||
|
|
||||||
|
if (sign->initialized != TRUE)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Not able to sign -- libsodium library isn't initialized properly");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
|
||||||
|
unsigned char sk[crypto_sign_SECRETKEYBYTES];
|
||||||
|
|
||||||
|
if (crypto_sign_keypair(pk, sk))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Not able to generate keypair");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_secret_key = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, sk, crypto_sign_SECRETKEYBYTES, sizeof(guchar));
|
||||||
|
*out_public_key = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, pk, crypto_sign_PUBLICKEYBYTES, sizeof(guchar));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
#endif /* HAVE_LIBSODIUM */
|
||||||
|
|
||||||
|
err:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_set_sk (OstreeSign *self,
|
||||||
|
GVariant *secret_key,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
OstreeSignEd25519 *sign = ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
|
||||||
|
g_autofree char * hex = NULL;
|
||||||
|
|
||||||
|
g_free (sign->secret_key);
|
||||||
|
|
||||||
|
gsize n_elements = 0;
|
||||||
|
sign->secret_key = (guchar *) g_variant_get_fixed_array (secret_key, &n_elements, sizeof(guchar));
|
||||||
|
|
||||||
|
if (n_elements != crypto_sign_SECRETKEYBYTES)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Incorrect ed25519 secret key");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
hex = g_malloc0 (crypto_sign_SECRETKEYBYTES*2 + 1);
|
||||||
|
g_debug ("Set ed25519 secret key = %s", sodium_bin2hex (hex, crypto_sign_SECRETKEYBYTES*2+1, sign->secret_key, n_elements));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
#endif /* HAVE_LIBSODIUM */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_set_pk (OstreeSign *self,
|
||||||
|
GVariant *public_key,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
OstreeSignEd25519 *sign = ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
|
||||||
|
g_autofree char * hex = NULL;
|
||||||
|
|
||||||
|
gsize n_elements = 0;
|
||||||
|
g_free (sign->public_key);
|
||||||
|
sign->public_key = (guchar *) g_variant_get_fixed_array (public_key, &n_elements, sizeof(guchar));
|
||||||
|
|
||||||
|
hex = g_malloc0 (crypto_sign_PUBLICKEYBYTES*2 + 1);
|
||||||
|
g_debug ("Read ed25519 public key = %s", sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, sign->public_key, n_elements));
|
||||||
|
|
||||||
|
if (n_elements != crypto_sign_PUBLICKEYBYTES)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Incorrect ed25519 public key");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("Set ed25519 public key = %s", sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, sign->public_key, n_elements));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
#endif /* HAVE_LIBSODIUM */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0+
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ostree-sign.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define OSTREE_TYPE_SIGN_ED25519 (ostree_sign_ed25519_get_type ())
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
G_DECLARE_FINAL_TYPE (OstreeSignEd25519,
|
||||||
|
ostree_sign_ed25519,
|
||||||
|
OSTREE,
|
||||||
|
SIGN_ED25519,
|
||||||
|
GObject)
|
||||||
|
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_data (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gchar * ostree_sign_ed25519_get_name (OstreeSign *self);
|
||||||
|
gchar * ostree_sign_ed25519_metadata_key (OstreeSign *self);
|
||||||
|
gchar * ostree_sign_ed25519_metadata_format (OstreeSign *self);
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_metadata_verify (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *signatures,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_set_sk (OstreeSign *self,
|
||||||
|
GVariant *secret_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean ostree_sign_ed25519_set_pk (OstreeSign *self,
|
||||||
|
GVariant *public_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void ostree_sign_ed25519_finalize (GObject *gobject);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_ed25519_keypair_generate (OstreeSign *self,
|
||||||
|
GVariant **out_secret_key,
|
||||||
|
GVariant **out_public_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
@ -0,0 +1,347 @@
|
||||||
|
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0+
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "libglnx.h"
|
||||||
|
#include "otutil.h"
|
||||||
|
|
||||||
|
#include "ostree-autocleanups.h"
|
||||||
|
#include "ostree-core.h"
|
||||||
|
#include "ostree-sign.h"
|
||||||
|
#include "ostree-sign-dummy.h"
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
#include "ostree-sign-ed25519.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define G_LOG_DOMAIN "OSTreeSign"
|
||||||
|
|
||||||
|
G_DEFINE_INTERFACE (OstreeSign, ostree_sign, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_sign_default_init (OstreeSignInterface *iface)
|
||||||
|
{
|
||||||
|
g_debug ("OstreeSign initialization");
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_metadata_key (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_key != NULL, NULL);
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->metadata_key (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar * ostree_sign_metadata_format (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_format != NULL, NULL);
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->metadata_format (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_set_sk (OstreeSign *self,
|
||||||
|
GVariant *secret_key,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
if (OSTREE_SIGN_GET_IFACE (self)->set_sk == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->set_sk (self, secret_key, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_set_pk (OstreeSign *self,
|
||||||
|
GVariant *public_key,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
if (OSTREE_SIGN_GET_IFACE (self)->set_pk == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->set_pk (self, public_key, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load private keys for verification from anywhere.
|
||||||
|
* No need to have the same function for secret keys -- the signing SW must do it in it's own way
|
||||||
|
* */
|
||||||
|
gboolean
|
||||||
|
ostree_sign_load_pk (OstreeSign *self,
|
||||||
|
gchar *remote_name,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->load_pk != NULL, FALSE);
|
||||||
|
|
||||||
|
if (remote_name == NULL)
|
||||||
|
remote_name = OSTREE_SIGN_ALL_REMOTES;
|
||||||
|
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->load_pk (self, remote_name, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ostree_sign_data (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->data != NULL, FALSE);
|
||||||
|
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->data (self, data, signature, cancellable, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adopted version of _ostree_detached_metadata_append_gpg_sig ()
|
||||||
|
*/
|
||||||
|
GVariant *
|
||||||
|
ostree_sign_detached_metadata_append (OstreeSign *self,
|
||||||
|
GVariant *existing_metadata,
|
||||||
|
GBytes *signature_bytes)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (signature_bytes != NULL, FALSE);
|
||||||
|
|
||||||
|
GVariantDict metadata_dict;
|
||||||
|
g_autoptr(GVariant) signature_data = NULL;
|
||||||
|
g_autoptr(GVariantBuilder) signature_builder = NULL;
|
||||||
|
|
||||||
|
g_variant_dict_init (&metadata_dict, existing_metadata);
|
||||||
|
|
||||||
|
g_autofree gchar *signature_key = ostree_sign_metadata_key(self);
|
||||||
|
g_autofree GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(self);
|
||||||
|
|
||||||
|
signature_data = g_variant_dict_lookup_value (&metadata_dict,
|
||||||
|
signature_key,
|
||||||
|
(GVariantType*)signature_format);
|
||||||
|
|
||||||
|
/* signature_data may be NULL */
|
||||||
|
signature_builder = ot_util_variant_builder_from_variant (signature_data, signature_format);
|
||||||
|
|
||||||
|
g_variant_builder_add (signature_builder, "@ay", ot_gvariant_new_ay_bytes (signature_bytes));
|
||||||
|
|
||||||
|
g_variant_dict_insert_value (&metadata_dict,
|
||||||
|
signature_key,
|
||||||
|
g_variant_builder_end (signature_builder));
|
||||||
|
|
||||||
|
return g_variant_dict_end (&metadata_dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
ostree_sign_metadata_verify (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *signatures,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_verify != NULL, FALSE);
|
||||||
|
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->metadata_verify(self, data, signatures, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
ostree_sign_commit_verify (OstreeSign *self,
|
||||||
|
OstreeRepo *repo,
|
||||||
|
const gchar *commit_checksum,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
|
||||||
|
g_autoptr(GVariant) commit_variant = NULL;
|
||||||
|
/* Load the commit */
|
||||||
|
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
|
||||||
|
commit_checksum, &commit_variant,
|
||||||
|
error))
|
||||||
|
return glnx_prefix_error (error, "Failed to read commit");
|
||||||
|
|
||||||
|
/* Load the metadata */
|
||||||
|
g_autoptr(GVariant) metadata = NULL;
|
||||||
|
if (!ostree_repo_read_commit_detached_metadata (repo,
|
||||||
|
commit_checksum,
|
||||||
|
&metadata,
|
||||||
|
cancellable,
|
||||||
|
error))
|
||||||
|
return glnx_prefix_error (error, "Failed to read detached metadata");
|
||||||
|
|
||||||
|
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit_variant);
|
||||||
|
|
||||||
|
/* XXX This is a hackish way to indicate to use ALL remote-specific
|
||||||
|
* keyrings in the signature verification. We want this when
|
||||||
|
* verifying a signed commit that's already been pulled. */
|
||||||
|
/*
|
||||||
|
if (remote_name == NULL)
|
||||||
|
remote_name = OSTREE_ALL_REMOTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
g_autoptr(GVariant) signatures = NULL;
|
||||||
|
|
||||||
|
g_autofree gchar *signature_key = ostree_sign_metadata_key(self);
|
||||||
|
g_autofree GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(self);
|
||||||
|
|
||||||
|
if (metadata)
|
||||||
|
signatures = g_variant_lookup_value (metadata,
|
||||||
|
signature_key,
|
||||||
|
signature_format);
|
||||||
|
|
||||||
|
|
||||||
|
return ostree_sign_metadata_verify (self,
|
||||||
|
signed_data,
|
||||||
|
signatures,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar * ostree_sign_get_name (OstreeSign *self)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
|
||||||
|
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->get_name != NULL, FALSE);
|
||||||
|
|
||||||
|
return OSTREE_SIGN_GET_IFACE (self)->get_name (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
OstreeSign * ostree_sign_get_by_name (const gchar *name, GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
GType types [] = {
|
||||||
|
#if defined(HAVE_LIBSODIUM)
|
||||||
|
OSTREE_TYPE_SIGN_ED25519,
|
||||||
|
#endif
|
||||||
|
OSTREE_TYPE_SIGN_DUMMY
|
||||||
|
};
|
||||||
|
OstreeSign *ret = NULL;
|
||||||
|
|
||||||
|
for (gint i=0; i < G_N_ELEMENTS(types); i++)
|
||||||
|
{
|
||||||
|
g_autoptr (OstreeSign) sign = g_object_new (types[i], NULL);
|
||||||
|
g_autofree gchar *sign_name = OSTREE_SIGN_GET_IFACE (sign)->get_name(sign);
|
||||||
|
|
||||||
|
g_debug ("Found '%s' signing module", sign_name);
|
||||||
|
|
||||||
|
if (g_strcmp0 (name, sign_name) == 0)
|
||||||
|
{
|
||||||
|
ret = g_steal_pointer (&sign);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == NULL)
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Requested signature type is not implemented");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ostree_sign_commit:
|
||||||
|
* @self: Self
|
||||||
|
* @commit_checksum: SHA256 of given commit to sign
|
||||||
|
* @cancellable: A #GCancellable
|
||||||
|
* @error: a #GError
|
||||||
|
*
|
||||||
|
* Add a GPG signature to a commit.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
ostree_sign_commit (OstreeSign *self,
|
||||||
|
OstreeRepo *repo,
|
||||||
|
const gchar *commit_checksum,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) commit_data = NULL;
|
||||||
|
g_autoptr(GBytes) signature = NULL;
|
||||||
|
g_autoptr(GVariant) commit_variant = NULL;
|
||||||
|
g_autoptr(GVariant) old_metadata = NULL;
|
||||||
|
g_autoptr(GVariant) new_metadata = NULL;
|
||||||
|
|
||||||
|
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
|
||||||
|
commit_checksum, &commit_variant, error))
|
||||||
|
return glnx_prefix_error (error, "Failed to read commit");
|
||||||
|
|
||||||
|
if (!ostree_repo_read_commit_detached_metadata (repo,
|
||||||
|
commit_checksum,
|
||||||
|
&old_metadata,
|
||||||
|
cancellable,
|
||||||
|
error))
|
||||||
|
return glnx_prefix_error (error, "Failed to read detached metadata");
|
||||||
|
|
||||||
|
// TODO: d4s: check if already signed?
|
||||||
|
|
||||||
|
commit_data = g_variant_get_data_as_bytes (commit_variant);
|
||||||
|
|
||||||
|
if (!ostree_sign_data (self, commit_data, &signature,
|
||||||
|
cancellable, error))
|
||||||
|
return glnx_prefix_error (error, "Not able to sign the cobject");
|
||||||
|
|
||||||
|
new_metadata =
|
||||||
|
ostree_sign_detached_metadata_append (self, old_metadata, signature);
|
||||||
|
|
||||||
|
if (!ostree_repo_write_commit_detached_metadata (repo,
|
||||||
|
commit_checksum,
|
||||||
|
new_metadata,
|
||||||
|
cancellable,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GStrv ostree_sign_list_names(void)
|
||||||
|
{
|
||||||
|
g_debug ("%s enter", __FUNCTION__);
|
||||||
|
|
||||||
|
GType types [] = {
|
||||||
|
#if defined(HAVE_LIBSODIUM)
|
||||||
|
OSTREE_TYPE_SIGN_ED25519,
|
||||||
|
#endif
|
||||||
|
OSTREE_TYPE_SIGN_DUMMY
|
||||||
|
};
|
||||||
|
GStrv names = g_new0 (char *, G_N_ELEMENTS(types)+1);
|
||||||
|
gint i = 0;
|
||||||
|
|
||||||
|
for (i=0; i < G_N_ELEMENTS(types); i++)
|
||||||
|
{
|
||||||
|
g_autoptr (OstreeSign) sign = g_object_new (types[i], NULL);
|
||||||
|
names[i] = OSTREE_SIGN_GET_IFACE (sign)->get_name(sign);
|
||||||
|
g_debug ("Found '%s' signing module", names[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0+
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "ostree-ref.h"
|
||||||
|
#include "ostree-remote.h"
|
||||||
|
#include "ostree-types.h"
|
||||||
|
|
||||||
|
/* Special remote */
|
||||||
|
#define OSTREE_SIGN_ALL_REMOTES "__OSTREE_ALL_REMOTES__"
|
||||||
|
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define OSTREE_TYPE_SIGN (ostree_sign_get_type ())
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
G_DECLARE_INTERFACE (OstreeSign, ostree_sign, OSTREE, SIGN, GObject)
|
||||||
|
|
||||||
|
struct _OstreeSignInterface
|
||||||
|
{
|
||||||
|
GTypeInterface g_iface;
|
||||||
|
gchar *(* get_name) (OstreeSign *self);
|
||||||
|
gboolean (* data) (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
gchar *(* metadata_key) (OstreeSign *self);
|
||||||
|
gchar *(* metadata_format) (OstreeSign *self);
|
||||||
|
gboolean (* metadata_verify) (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *metadata,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean (* set_sk) (OstreeSign *self,
|
||||||
|
GVariant *secret_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean (* set_pk) (OstreeSign *self,
|
||||||
|
GVariant *public_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean (* load_pk) (OstreeSign *self,
|
||||||
|
gchar *remote_name,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
const gchar * ostree_sign_get_name (OstreeSign *self);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_data (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GBytes **signature,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gchar * ostree_sign_metadata_key (OstreeSign *self);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gchar * ostree_sign_metadata_format (OstreeSign *self);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
GVariant * ostree_sign_detached_metadata_append (OstreeSign *self,
|
||||||
|
GVariant *existing_metadata,
|
||||||
|
GBytes *signature_bytes);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_commit (OstreeSign *self,
|
||||||
|
OstreeRepo *repo,
|
||||||
|
const gchar *commit_checksum,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_metadata_verify (OstreeSign *self,
|
||||||
|
GBytes *data,
|
||||||
|
GVariant *signatures,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_commit_verify (OstreeSign *self,
|
||||||
|
OstreeRepo *repo,
|
||||||
|
const gchar *commit_checksum,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_set_sk (OstreeSign *self,
|
||||||
|
GVariant *secret_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_set_pk (OstreeSign *self,
|
||||||
|
GVariant *public_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
gboolean ostree_sign_load_pk (OstreeSign *self,
|
||||||
|
gchar *remote_name,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ostree_sign_list_names:
|
||||||
|
*
|
||||||
|
* Return the array with all available sign modules names.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): an array of strings, free when you used it
|
||||||
|
*/
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
GStrv ostree_sign_list_names(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ostree_sign_get_by_name:
|
||||||
|
*
|
||||||
|
* Tries to find and return proper signing engine by it's name.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a constant, free when you used it
|
||||||
|
*/
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
OstreeSign * ostree_sign_get_by_name (const gchar *name, GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
Loading…
Reference in New Issue