From 7b85adfbbd97054e4b14ca4365c11fbadf97c70c Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 6 Jul 2023 17:12:46 +0200 Subject: [PATCH] sign-ed25519: Implement sign and verify using openssl 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. --- configure.ac | 7 ++- src/libostree/ostree-sign-ed25519.c | 85 ++++++++++++++++++++++------ src/libostree/ostree-sign.c | 10 ++-- src/ostree/ot-builtin-sign.c | 2 +- src/ostree/ot-builtin-static-delta.c | 8 +-- 5 files changed, 82 insertions(+), 30 deletions(-) diff --git a/configure.ac b/configure.ac index 723d2719..5eb7367e 100644 --- a/configure.ac +++ b/configure.ac @@ -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) @@ -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" @@ -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 diff --git a/src/libostree/ostree-sign-ed25519.c b/src/libostree/ostree-sign-ed25519.c index 7751ddbd..6ff13260 100644 --- a/src/libostree/ostree-sign-ed25519.c +++ b/src/libostree/ostree-sign-ed25519.c @@ -26,8 +26,17 @@ #include "ostree-sign-ed25519.h" #include #include + #ifdef HAVE_LIBSODIUM #include +#define USE_LIBSODIUM +#else + +#if defined(HAVE_OPENSSL) +#include +#define USE_OPENSSL +#endif + #endif #undef G_LOG_DOMAIN @@ -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 @@ -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; @@ -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 @@ -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 ( @@ -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) diff --git a/src/libostree/ostree-sign.c b/src/libostree/ostree-sign.c index be333a30..d76271bc 100644 --- a/src/libostree/ostree-sign.c +++ b/src/libostree/ostree-sign.c @@ -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" @@ -59,7 +57,7 @@ typedef struct } _sign_type; _sign_type sign_types[] = { -#if defined(HAVE_LIBSODIUM) +#if defined(HAVE_ED25519) { OSTREE_SIGN_NAME_ED25519, 0 }, #endif { "dummy", 0 } @@ -67,7 +65,7 @@ _sign_type sign_types[] = { enum { -#if defined(HAVE_LIBSODIUM) +#if defined(HAVE_ED25519) SIGN_ED25519, #endif SIGN_DUMMY @@ -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 diff --git a/src/ostree/ot-builtin-sign.c b/src/ostree/ot-builtin-sign.c index cd331a48..f51fc51e 100644 --- a/src/ostree/ot-builtin-sign.c +++ b/src/ostree/ot-builtin-sign.c @@ -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", diff --git a/src/ostree/ot-builtin-static-delta.c b/src/ostree/ot-builtin-static-delta.c index a10040bd..ba9a2f2c 100644 --- a/src/ostree/ot-builtin-static-delta.c +++ b/src/ostree/ot-builtin-static-delta.c @@ -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 } @@ -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" }, @@ -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" }, @@ -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 -- 2.30.2