Skip to content

Commit

Permalink
sign-ed25519: Implement sign and verify using openssl
Browse files Browse the repository at this point in the history
libsodium is used if configured to keep the old behaviour, but if
it is not enabled, and openssl is used, then ed25519 is now supported.
  • Loading branch information
alexlarsson committed Jul 7, 2023
1 parent 501575c commit 7b85adf
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 30 deletions.
7 changes: 6 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ AS_IF([test x$with_ed25519_libsodium != xno], [
AS_IF([ test x$have_libsodium = xno ], [
AC_MSG_ERROR([Need LIBSODIUM version $LIBSODIUM_DEPENDENCY or later])
])
OSTREE_FEATURES="$OSTREE_FEATURES sign-ed25519"
], with_ed25519_libsodium=no )
AM_CONDITIONAL(USE_LIBSODIUM, test "x$have_libsodium" = xyes)

Expand Down Expand Up @@ -450,6 +449,11 @@ if test x$with_openssl != xno; then OSTREE_FEATURES="$OSTREE_FEATURES openssl";
AM_CONDITIONAL(USE_OPENSSL, test $with_openssl != no)
dnl end openssl

if test x$with_openssl != xno || test x$with_ed25519_libsodium != xno; then
AC_DEFINE([HAVE_ED25519], 1, [Define if ed25519 is supported ])
OSTREE_FEATURES="$OSTREE_FEATURES sign-ed25519"
fi

dnl begin gnutls; in contrast to openssl this one only
dnl supports --with-crypto=gnutls
GNUTLS_DEPENDENCY="gnutls >= 3.5.0"
Expand Down Expand Up @@ -684,6 +688,7 @@ echo "
systemd: $with_libsystemd
libmount: $with_libmount
libsodium (ed25519 signatures): $with_ed25519_libsodium
openssl (ed25519 signatures): $with_openssl
libarchive (parse tar files directly): $with_libarchive
static deltas: yes (always enabled now)
O_TMPFILE: $enable_otmpfile
Expand Down
85 changes: 67 additions & 18 deletions src/libostree/ostree-sign-ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,17 @@
#include "ostree-sign-ed25519.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
Expand Down Expand Up @@ -99,12 +108,13 @@ _ostree_sign_ed25519_init (OstreeSignEd25519 *self)
self->public_keys = NULL;
self->revoked_keys = NULL;

#ifdef HAVE_LIBSODIUM
#if defined(USE_LIBSODIUM)
if (sodium_init () < 0)
self->state = ED25519_FAILED_INITIALIZATION;
#elif defined(USE_OPENSSL)
#else
self->state = ED25519_NOT_SUPPORTED;
#endif /* HAVE_LIBSODIUM */
#endif
}

static gboolean
Expand All @@ -117,7 +127,7 @@ _ostree_sign_ed25519_is_initialized (OstreeSignEd25519 *self, GError **error)
case ED25519_NOT_SUPPORTED:
return glnx_throw (error, "ed25519: engine is not supported");
case ED25519_FAILED_INITIALIZATION:
return glnx_throw (error, "ed25519: libsodium library isn't initialized properly");
return glnx_throw (error, "ed25519: crypto library isn't initialized properly");
}

return TRUE;
Expand All @@ -131,31 +141,46 @@ ostree_sign_ed25519_data (OstreeSign *self, GBytes *data, GBytes **signature,
g_assert (OSTREE_IS_SIGN (self));
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private (OSTREE_SIGN_ED25519 (self));

#ifdef HAVE_LIBSODIUM
guchar *sig = NULL;
#endif

if (!_ostree_sign_ed25519_is_initialized (sign, error))
return FALSE;

if (sign->secret_key == NULL)
return glnx_throw (error, "Not able to sign: secret key is not set");

#ifdef HAVE_LIBSODIUM
unsigned long long sig_size = 0;
g_autofree guchar *sig = g_malloc0 (OSTREE_SIGN_ED25519_SIG_SIZE);

sig = g_malloc0 (crypto_sign_BYTES);

#if defined(USE_LIBSODIUM)
if (crypto_sign_detached (sig, &sig_size, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
sign->secret_key))
sig_size = 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_private_key (EVP_PKEY_ED25519, NULL, sign->secret_key,
OSTREE_SIGN_ED25519_SEED_SIZE);
if (!pkey)
{
return glnx_throw (error, "Not able to sign: fail to sign the object");
EVP_MD_CTX_free (ctx);
return glnx_throw (error, "openssl: Failed to initialize ed5519 key");
}

*signature = g_bytes_new_take (sig, sig_size);
size_t len;
if (EVP_DigestSignInit (ctx, NULL, NULL, NULL, pkey)
&& EVP_DigestSign (ctx, sig, &len, g_bytes_get_data (data, NULL), g_bytes_get_size (data)))
sig_size = len;

EVP_PKEY_free (pkey);
EVP_MD_CTX_free (ctx);

#endif

if (sig_size == 0)
return glnx_throw (error, "Failed to sign");

*signature = g_bytes_new_take (g_steal_pointer (&sig), sig_size);
return TRUE;
#endif /* HAVE_LIBSODIUM */
return FALSE;
}

static gint
Expand Down Expand Up @@ -207,6 +232,7 @@ 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 @@ -230,10 +256,33 @@ ostree_sign_ed25519_data_verify (OstreeSign *self, GBytes *data, GVariant *signa
continue;
}

if (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)
#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
if (!valid)
{
/* Incorrect signature! */
if (invalid_signatures == NULL)
Expand Down
10 changes: 4 additions & 6 deletions src/libostree/ostree-sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@
#include "ostree-autocleanups.h"
#include "ostree-core.h"
#include "ostree-sign-dummy.h"
#include "ostree-sign-ed25519.h"
#include "ostree-sign-private.h"
#include "ostree-sign.h"
#ifdef HAVE_LIBSODIUM
#include "ostree-sign-ed25519.h"
#endif

#include "ostree-autocleanups.h"
#include "ostree-repo-private.h"
Expand All @@ -59,15 +57,15 @@ typedef struct
} _sign_type;

_sign_type sign_types[] = {
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
{ OSTREE_SIGN_NAME_ED25519, 0 },
#endif
{ "dummy", 0 }
};

enum
{
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
SIGN_ED25519,
#endif
SIGN_DUMMY
Expand Down Expand Up @@ -535,7 +533,7 @@ ostree_sign_get_by_name (const gchar *name, GError **error)
OstreeSign *sign = NULL;

/* Get types if not initialized yet */
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
if (sign_types[SIGN_ED25519].type == 0)
sign_types[SIGN_ED25519].type = OSTREE_TYPE_SIGN_ED25519;
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/ostree/ot-builtin-sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static GOptionEntry options[]
{ "verify", 0, 0, G_OPTION_ARG_NONE, &opt_verify, "Verify signatures", NULL },
{ "sign-type", 's', 0, G_OPTION_ARG_STRING, &opt_sign_name,
"Signature type to use (defaults to 'ed25519')", "NAME" },
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
{ "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_filename, "Read key(s) from file", "NAME" },
{ "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir,
"Redefine system-wide directories with public and revoked keys for verification",
Expand Down
8 changes: 4 additions & 4 deletions src/ostree/ot-builtin-static-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static GOptionEntry generate_options[] = {
{ "sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "Sign the delta with", "KEY_ID" },
{ "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name,
"Signature type to use (defaults to 'ed25519')", "NAME" },
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
{ "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME" },
#endif
{ NULL }
Expand All @@ -114,7 +114,7 @@ static GOptionEntry generate_options[] = {
static GOptionEntry apply_offline_options[] = {
{ "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name,
"Signature type to use (defaults to 'ed25519')", "NAME" },
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
{ "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME" },
{ "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir,
"Redefine system-wide directories with public and revoked keys for verification", "NAME" },
Expand All @@ -127,7 +127,7 @@ static GOptionEntry list_options[] = { { NULL } };
static GOptionEntry verify_options[] = {
{ "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name,
"Signature type to use (defaults to 'ed25519')", "NAME" },
#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
{ "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME" },
{ "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir,
"Redefine system-wide directories with public and revoked keys for verification", "NAME" },
Expand Down Expand Up @@ -513,7 +513,7 @@ ot_static_delta_builtin_apply_offline (int argc, char **argv, OstreeCommandInvoc
return FALSE;
}

#if defined(HAVE_LIBSODIUM)
#if defined(HAVE_ED25519)
/* Initialize crypto system */
opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519;
#endif
Expand Down

0 comments on commit 7b85adf

Please sign in to comment.