Skip to content

Commit

Permalink
Factor out a libotcore
Browse files Browse the repository at this point in the history
This will contain logic shared between ostree-prepare-root
and libostree-1.so.  It will just link to libgio.so, so as
to avoid pulling in e.g. libcurl and other things.

In other words, `ostree-prepare-root` will not link to `libostree-1.so`,
but will pull in just what it needs from this library.
  • Loading branch information
cgwalters committed Jul 8, 2023
1 parent 265cf7d commit 67359a4
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 52 deletions.
4 changes: 2 additions & 2 deletions Makefile-libostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,12 @@ EXTRA_DIST += \
$(top_srcdir)/src/libostree/libostree-released.sym \
$(NULL)

libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/composefs -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \
libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/composefs -I$(srcdir)/src/libotutil -I$(srcdir)/src/libotcore -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \
$(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \
-fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' \
-DPKGLIBEXECDIR=\"$(pkglibexecdir)\"
libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files))
libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \
libostree_1_la_LIBADD = libotutil.la libotcore.la libglnx.la libbsdiff.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \
$(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS)
# Some change between rust-1.21.0-1.fc27 and rust-1.22.1-1.fc27.x86_64
libostree_1_la_LIBADD += $(bupsplitpath)
Expand Down
24 changes: 24 additions & 0 deletions Makefile-otcore.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 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, see <https://www.gnu.org/licenses/>.

noinst_LTLIBRARIES += libotcore.la

libotcore_la_SOURCES = \
src/libotcore/otcore.h \
src/libotcore/otcore-ed25519-verify.c \
$(NULL)

libotcore_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_CRYPTO_LIBS) $(LIBSYSTEMD_CFLAGS)
libotcore_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) $(LIBSYSTEMD_LIBS) $(OT_DEP_CRYPTO_LIBS)
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ noinst_LTLIBRARIES += libcomposefs.la
endif

include Makefile-otutil.am
include Makefile-otcore.am
include Makefile-libostree.am
include Makefile-ostree.am
include Makefile-switchroot.am
Expand Down
61 changes: 11 additions & 50 deletions src/libostree/ostree-sign-ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,15 @@
#include "config.h"

#include "ostree-sign-ed25519.h"
#include "otcore.h"
#include <libglnx.h>
#include <ot-checksum-utils.h>

#ifdef HAVE_LIBSODIUM
#include <sodium.h>
#define USE_LIBSODIUM
#else

#if defined(HAVE_OPENSSL)
#include <openssl/evp.h>
#define USE_OPENSSL
#endif

#endif

#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "OSTreeSign"

#define OSTREE_SIGN_ED25519_NAME "ed25519"

#define OSTREE_SIGN_METADATA_ED25519_KEY "ostree.sign.ed25519"
#define OSTREE_SIGN_METADATA_ED25519_TYPE "aay"

#define OSTREE_SIGN_ED25519_SIG_SIZE 64U
#define OSTREE_SIGN_ED25519_PUBKEY_SIZE 32U
#define OSTREE_SIGN_ED25519_SEED_SIZE 32U
#define OSTREE_SIGN_ED25519_SECKEY_SIZE \
(OSTREE_SIGN_ED25519_SEED_SIZE + OSTREE_SIGN_ED25519_PUBKEY_SIZE)
Expand Down Expand Up @@ -108,12 +92,11 @@ _ostree_sign_ed25519_init (OstreeSignEd25519 *self)
self->public_keys = NULL;
self->revoked_keys = NULL;

#if defined(USE_LIBSODIUM)
if (sodium_init () < 0)
self->state = ED25519_FAILED_INITIALIZATION;
#elif defined(USE_OPENSSL)
#else
#if !(defined(USE_OPENSSL) || defined(USE_LIBSODIUM))
self->state = ED25519_NOT_SUPPORTED;
#else
if (!otcore_ed25519_init ())
self->state = ED25519_FAILED_INITIALIZATION;
#endif
}

Expand Down Expand Up @@ -232,7 +215,6 @@ ostree_sign_ed25519_data_verify (OstreeSign *self, GBytes *data, GVariant *signa
{
g_autoptr (GVariant) child = g_variant_get_child_value (signatures, i);
g_autoptr (GBytes) signature = g_variant_get_data_as_bytes (child);
gboolean valid = FALSE;

if (g_bytes_get_size (signature) != OSTREE_SIGN_ED25519_SIG_SIZE)
return glnx_throw (
Expand All @@ -246,7 +228,6 @@ ostree_sign_ed25519_data_verify (OstreeSign *self, GBytes *data, GVariant *signa

for (GList *public_key = sign->public_keys; public_key != NULL; public_key = public_key->next)
{

/* TODO: use non-list for tons of revoked keys? */
if (g_list_find_custom (sign->revoked_keys, public_key->data, _compare_ed25519_keys)
!= NULL)
Expand All @@ -256,32 +237,12 @@ ostree_sign_ed25519_data_verify (OstreeSign *self, GBytes *data, GVariant *signa
continue;
}

#if defined(USE_LIBSODIUM)
valid = crypto_sign_verify_detached ((guchar *)g_variant_get_data (child),
g_bytes_get_data (data, NULL),
g_bytes_get_size (data), public_key->data)
== 0;
#elif defined(USE_OPENSSL)
EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
if (!ctx)
return glnx_throw (error, "openssl: failed to allocate context");
EVP_PKEY *pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, public_key->data,
OSTREE_SIGN_ED25519_PUBKEY_SIZE);
if (!pkey)
{
EVP_MD_CTX_free (ctx);
return glnx_throw (error, "openssl: Failed to initialize ed5519 key");
}

valid = EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, pkey) != 0
&& EVP_DigestVerify (ctx, g_bytes_get_data (signature, NULL),
g_bytes_get_size (signature), g_bytes_get_data (data, NULL),
g_bytes_get_size (data))
!= 0;

EVP_PKEY_free (pkey);
EVP_MD_CTX_free (ctx);
#endif
bool valid = false;
// Wrap the pubkey in a GBytes as that's what this API wants
g_autoptr (GBytes) public_key_bytes
= g_bytes_new_static (public_key->data, OSTREE_SIGN_ED25519_PUBKEY_SIZE);
if (!otcore_validate_ed25519_signature (data, public_key_bytes, signature, &valid, error))
return FALSE;
if (!valid)
{
/* Incorrect signature! */
Expand Down
1 change: 1 addition & 0 deletions src/libotcore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This library is (will be) shared between `libostree-1.so` and `ostree-prepare-root`.
115 changes: 115 additions & 0 deletions src/libotcore/otcore-ed25519-verify.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* 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, see <https://www.gnu.org/licenses/>.
*/

#include "config.h"

#include "otcore.h"

/* Initialize global state; may be called multiple times and is idempotent. */
bool
otcore_ed25519_init (void)
{
#if defined(HAVE_LIBSODIUM)
static gssize initstate;
if (g_once_init_enter (&initstate))
{
int val = sodium_init () >= 0 ? 1 : -1;
g_once_init_leave (&initstate, val);
}
switch (initstate)
{
case 1:
return true;
case -1:
return false;
default:
g_assert_not_reached ();
}
#else
return true;
#endif
}

/* Validate a single ed25519 signature. If there is an unexpected state, such
* as an ill-forumed public key or signature, a hard error will be returned.
*
* If the signature is not correct, this function will return successfully, but
* `out_valid` will be set to `false`.
*
* If the signature is correct, `out_valid` will be `true`.
* */
gboolean
otcore_validate_ed25519_signature (GBytes *data, GBytes *public_key, GBytes *signature,
bool *out_valid, GError **error)
{
// Since this is signature verification code, let's verify preconditions.
g_assert (data);
g_assert (public_key);
g_assert (signature);
g_assert (out_valid);
// It is OK for error to be NULL, though according to GError rules.

#if defined(HAVE_LIBSODIUM) || defined(HAVE_OPENSSL)
// And strictly verify pubkey and signature lengths
if (g_bytes_get_size (public_key) != OSTREE_SIGN_ED25519_PUBKEY_SIZE)
return glnx_throw (error, "Invalid public key of %" G_GSIZE_FORMAT " expected %" G_GSIZE_FORMAT,
(gsize)g_bytes_get_size (public_key),
(gsize)OSTREE_SIGN_ED25519_PUBKEY_SIZE);
const guint8 *public_key_buf = g_bytes_get_data (public_key, NULL);
if (g_bytes_get_size (signature) != OSTREE_SIGN_ED25519_SIG_SIZE)
return glnx_throw (
error, "Invalid signature length of %" G_GSIZE_FORMAT " bytes, expected %" G_GSIZE_FORMAT,
(gsize)g_bytes_get_size (signature), (gsize)OSTREE_SIGN_ED25519_SIG_SIZE);
const guint8 *signature_buf = g_bytes_get_data (signature, NULL);

#endif

#if defined(HAVE_LIBSODIUM)
// Note that libsodium assumes the passed byte arrays for the signature and public key
// have at least the expected length, but we checked that above.
if (crypto_sign_verify_detached (signature_buf, g_bytes_get_data (data, NULL),
g_bytes_get_size (data), public_key_buf)
== 0)
{
*out_valid = true;
}
return TRUE;
#elif defined(HAVE_OPENSSL)
EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
if (!ctx)
return glnx_throw (error, "openssl: failed to allocate context");
EVP_PKEY *pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, public_key_buf,
OSTREE_SIGN_ED25519_PUBKEY_SIZE);
if (!pkey)
{
EVP_MD_CTX_free (ctx);
return glnx_throw (error, "openssl: Failed to initialize ed5519 key");
}
if (EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, pkey) != 0
&& EVP_DigestVerify (ctx, signature_buf, OSTREE_SIGN_ED25519_SIG_SIZE,
g_bytes_get_data (data, NULL), g_bytes_get_size (data))
!= 0)
{
*out_valid = true;
}
EVP_PKEY_free (pkey);
EVP_MD_CTX_free (ctx);
return TRUE;
#else
return glnx_throw (error, "ed25519 signature validation requested, but support not compiled in");
#endif
}
44 changes: 44 additions & 0 deletions src/libotcore/otcore.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "config.h"

#include "otutil.h"
#include <stdbool.h>

#ifdef HAVE_LIBSODIUM
#include <sodium.h>
#define USE_LIBSODIUM
#elif defined(HAVE_OPENSSL)
#include <openssl/evp.h>
#define USE_OPENSSL
#endif

// Length of a signature in bytes
#define OSTREE_SIGN_ED25519_SIG_SIZE 64U
// Length of a public key in bytes
#define OSTREE_SIGN_ED25519_PUBKEY_SIZE 32U
// This key is stored inside commit metadata.
#define OSTREE_SIGN_METADATA_ED25519_KEY "ostree.sign.ed25519"
// The variant type
#define OSTREE_SIGN_METADATA_ED25519_TYPE "aay"

bool otcore_ed25519_init (void);
gboolean otcore_validate_ed25519_signature (GBytes *data, GBytes *pubkey, GBytes *signature,
bool *out_valid, GError **error);

0 comments on commit 67359a4

Please sign in to comment.