summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Pynkin <denis.pynkin@collabora.com>2019-07-31 01:13:48 +0300
committerDenis Pynkin <denis.pynkin@collabora.com>2020-03-25 15:23:54 +0300
commitc3608aa56a4e1551240b7effe2c40bb609211b3d (patch)
treea6f7428ae662a7f16959906aab365ee044e4accc
parentedbbe1c4f2267c0d95d4ee14f6cbc516a1d31dca (diff)
downloadostree-c3608aa56a4e1551240b7effe2c40bb609211b3d.tar.gz
sign: add new builtin for signing
This builtin allows to sign and verify commit with new signature mechanism. At the moment it is possible to use 'dummy' and 'ed25519' signing modules. 'dummy' module use any ASCII string from command line as a key for commit's signing or verification. Support of ed25519 signature is implemented with `libsoium` library. Secret and public key should be provided in hex presentation via command line. Based on 'gpg-sign' source. Signed-off-by: Denis Pynkin <denis.pynkin@collabora.com>
-rw-r--r--Makefile-ostree.am1
-rw-r--r--src/ostree/main.c3
-rw-r--r--src/ostree/ot-builtin-sign.c211
-rw-r--r--src/ostree/ot-builtins.h1
4 files changed, 216 insertions, 0 deletions
diff --git a/Makefile-ostree.am b/Makefile-ostree.am
index f37d974a..e5767641 100644
--- a/Makefile-ostree.am
+++ b/Makefile-ostree.am
@@ -43,6 +43,7 @@ ostree_SOURCES = src/ostree/main.c \
src/ostree/ot-builtin-remote.c \
src/ostree/ot-builtin-reset.c \
src/ostree/ot-builtin-rev-parse.c \
+ src/ostree/ot-builtin-sign.c \
src/ostree/ot-builtin-summary.c \
src/ostree/ot-builtin-show.c \
src/ostree/ot-builtin-static-delta.c \
diff --git a/src/ostree/main.c b/src/ostree/main.c
index a523ff9a..a9f57392 100644
--- a/src/ostree/main.c
+++ b/src/ostree/main.c
@@ -109,6 +109,9 @@ static OstreeCommand commands[] = {
{ "rev-parse", OSTREE_BUILTIN_FLAG_NONE,
ostree_builtin_rev_parse,
"Output the target of a rev" },
+ { "sign", OSTREE_BUILTIN_FLAG_NONE,
+ ostree_builtin_sign,
+ "Sign a commit" },
{ "show", OSTREE_BUILTIN_FLAG_NONE,
ostree_builtin_show,
"Output a metadata object" },
diff --git a/src/ostree/ot-builtin-sign.c b/src/ostree/ot-builtin-sign.c
new file mode 100644
index 00000000..8edd5490
--- /dev/null
+++ b/src/ostree/ot-builtin-sign.c
@@ -0,0 +1,211 @@
+/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
+
+/*
+ * Copyright (C) 2015 Colin Walters <walters@verbum.org>
+ * Copyright (C) 2019 Denis Pynkin (d4s) <denis.pynkin@collabora.com>
+ *
+ * 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.
+ *
+ * Author: Colin Walters <walters@verbum.org>
+ */
+
+#include "config.h"
+
+#include "ot-main.h"
+#include "ot-builtins.h"
+#include "ostree.h"
+#include "otutil.h"
+#include "ostree-core-private.h"
+#include "ostree-sign.h"
+#include "ostree-sign-dummy.h"
+#if defined(HAVE_LIBSODIUM)
+#include "ostree-sign-ed25519.h"
+#include <sodium.h>
+#endif
+
+static gboolean opt_delete;
+static gboolean opt_verify;
+static char *opt_sign_name;
+
+/* ATTENTION:
+ * Please remember to update the bash-completion script (bash/ostree) and
+ * man page (man/ostree-sign.xml) when changing the option list.
+ */
+
+static GOptionEntry options[] = {
+ { "delete", 'd', 0, G_OPTION_ARG_NONE, &opt_delete, "Delete signatures having any of the KEY-IDs", NULL},
+ { "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)
+#endif
+ { NULL }
+};
+
+static void
+usage_error (GOptionContext *context, const char *message, GError **error)
+{
+ g_autofree char *help = g_option_context_get_help (context, TRUE, NULL);
+ g_printerr ("%s", help);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, message);
+}
+
+gboolean
+ostree_builtin_sign (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(GOptionContext) context = NULL;
+ g_autoptr(OstreeRepo) repo = NULL;
+ g_autoptr (OstreeSign) sign = NULL;
+ g_autofree char *resolved_commit = NULL;
+ const char *commit;
+ char **key_ids;
+ int n_key_ids, ii;
+ gboolean ret = FALSE;
+#if defined(HAVE_LIBSODIUM)
+ g_autoptr (GVariant) ed25519_sk = NULL;
+ g_autoptr (GVariant) ed25519_pk = NULL;
+#endif
+
+
+ context = g_option_context_new ("COMMIT KEY-ID...");
+
+
+ if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
+ goto out;
+
+ if (argc < 2)
+ {
+ usage_error (context, "Need a COMMIT to sign or verify", error);
+ goto out;
+ }
+
+ commit = argv[1];
+
+ if (!opt_verify && argc < 3)
+ {
+ usage_error (context, "Need at least one KEY-ID to sign with", error);
+ goto out;
+ }
+
+ key_ids = argv + 2;
+ n_key_ids = argc - 2;
+
+ if (!ostree_repo_resolve_rev (repo, commit, FALSE, &resolved_commit, error))
+ goto out;
+
+ /* Initialize crypto system */
+ if (!opt_sign_name)
+ opt_sign_name = "ed25519";
+
+ sign = ostree_sign_get_by_name (opt_sign_name, error);
+ if (sign == NULL)
+ {
+ ret = FALSE;
+ goto out;
+ }
+
+ for (ii = 0; ii < n_key_ids; ii++)
+ {
+ g_autoptr (GVariant) sk = NULL;
+ g_autoptr (GVariant) pk = NULL;
+ g_autofree guchar *key = NULL;
+
+ if (!g_strcmp0(ostree_sign_get_name(sign), "dummy"))
+ {
+ // Just use the string as signature
+ sk = g_variant_new_string(key_ids[ii]);
+ pk = g_variant_new_string(key_ids[ii]);
+ }
+ if (opt_verify)
+ {
+#if defined(HAVE_LIBSODIUM)
+ if (!g_strcmp0(ostree_sign_get_name(sign), "ed25519"))
+ {
+ gsize key_len = 0;
+ key = g_malloc0 (crypto_sign_PUBLICKEYBYTES);
+ if (sodium_hex2bin (key, crypto_sign_PUBLICKEYBYTES,
+ key_ids[ii], strlen (key_ids[ii]),
+ NULL, &key_len, NULL) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid KEY '%s'", key_ids[ii]);
+
+ goto out;
+ }
+
+ pk = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, key, key_len, sizeof(guchar));
+ }
+#endif
+
+ if (!ostree_sign_set_pk (sign, pk, error))
+ {
+ ret = FALSE;
+ goto out;
+ }
+
+ if (ostree_sign_commit_verify (sign,
+ repo,
+ resolved_commit,
+ cancellable,
+ error))
+ ret = TRUE;
+ }
+ else
+ {
+#if defined(HAVE_LIBSODIUM)
+ if (!g_strcmp0(ostree_sign_get_name(sign), "ed25519"))
+ {
+ gsize key_len = 0;
+ key = g_malloc0 (crypto_sign_SECRETKEYBYTES);
+ if (sodium_hex2bin (key, crypto_sign_SECRETKEYBYTES,
+ key_ids[ii], strlen (key_ids[ii]),
+ NULL, &key_len, NULL) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid KEY '%s'", key_ids[ii]);
+
+ goto out;
+ }
+
+ sk = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, key, key_len, sizeof(guchar));
+ }
+#endif
+ if (!ostree_sign_set_sk (sign, sk, error))
+ {
+ ret = FALSE;
+ goto out;
+ }
+
+ ret = ostree_sign_commit (sign,
+ repo,
+ resolved_commit,
+ cancellable,
+ error);
+ if (ret != TRUE)
+ goto out;
+ }
+ }
+
+ // No valid signature found
+ if (opt_verify && (ret != TRUE))
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No valid signatures found");
+
+out:
+ return ret;
+}
diff --git a/src/ostree/ot-builtins.h b/src/ostree/ot-builtins.h
index 12a99b45..e372d359 100644
--- a/src/ostree/ot-builtins.h
+++ b/src/ostree/ot-builtins.h
@@ -53,6 +53,7 @@ BUILTINPROTO(prune);
BUILTINPROTO(refs);
BUILTINPROTO(reset);
BUILTINPROTO(fsck);
+BUILTINPROTO(sign);
BUILTINPROTO(show);
BUILTINPROTO(static_delta);
BUILTINPROTO(summary);