sign-ed25519: Implement sign and verify using openssl
authorAlexander Larsson <alexl@redhat.com>
Thu, 6 Jul 2023 15:12:46 +0000 (17:12 +0200)
committerAlexander Larsson <alexl@redhat.com>
Fri, 7 Jul 2023 15:16:30 +0000 (17:16 +0200)
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
src/libostree/ostree-sign-ed25519.c
src/libostree/ostree-sign.c
src/ostree/ot-builtin-sign.c
src/ostree/ot-builtin-static-delta.c

index 723d2719cd54d844ab6c3fbb8c6c573508dff01f..5eb7367e3c55298ee9053ea7f6693247872f92b2 100644 (file)
@@ -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
index 7751ddbd10a944046ac3a4c76d94c51805da24cd..6ff132600baa2774dee5e08bc1ad76b45b4ec98f 100644 (file)
 #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
@@ -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)
index be333a3070fd000ba7824ccd3a13acfccc79fde0..d76271bca74d939f617a5ced4ee1afa177bb0d96 100644 (file)
 #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
index cd331a486e9c23f21730d61de49dbf4c7d6d4c1c..f51fc51e6073cd8a54ae0d4e13c0fd53fc2a10f5 100644 (file)
@@ -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",
index a10040bdd1d1fa8497b066ea2158a548a58ec374..ba9a2f2c4a84be0d11e6c76885d2a7678e573651 100644 (file)
@@ -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