summaryrefslogtreecommitdiff
path: root/src/libotutil
diff options
context:
space:
mode:
authorDan Nicholson <nicholson@endlessm.com>2019-08-27 10:28:10 -0600
committerDan Nicholson <dbn@endlessos.org>2021-07-15 15:50:04 -0600
commit4fa403aee500df058a7d3ee2b6b1db4300ad7a92 (patch)
tree671d694e8c868b84b5d5e9b71f429b56009e0ad5 /src/libotutil
parentfbff05e28d0e0d3c8424a7d4a5652a253a553b04 (diff)
downloadostree-4fa403aee500df058a7d3ee2b6b1db4300ad7a92.tar.gz
libotutil: Add helper for GPG WKD update URLs
Calculate the advanced and direct update URLs for the key discovery portion[1] of the OpenPGP Web Key Directory specification, and include the URLs in the key listing in ostree_repo_remote_get_gpg_keys(). These URLs can be used to locate updated GPG keys for the remote. 1. https://datatracker.ietf.org/doc/html/draft-koch-openpgp-webkey-service#section-3.1
Diffstat (limited to 'src/libotutil')
-rw-r--r--src/libotutil/ot-gpg-utils.c75
-rw-r--r--src/libotutil/ot-gpg-utils.h5
2 files changed, 80 insertions, 0 deletions
diff --git a/src/libotutil/ot-gpg-utils.c b/src/libotutil/ot-gpg-utils.c
index 743d941e..4dbefdbd 100644
--- a/src/libotutil/ot-gpg-utils.c
+++ b/src/libotutil/ot-gpg-utils.c
@@ -27,6 +27,7 @@
#include <gio/gunixoutputstream.h>
#include "libglnx.h"
+#include "zbase32.h"
/* Like glnx_throw_errno_prefix, but takes @gpg_error */
gboolean
@@ -538,3 +539,77 @@ ot_gpgme_kill_agent (const char *homedir)
return;
}
}
+
+/* Takes the SHA1 checksum of the local component of an email address and
+ * returns the zbase32 encoding.
+ */
+static char *
+encode_wkd_local (const char *local)
+{
+ g_return_val_if_fail (local != NULL, NULL);
+
+ guint8 digest[20] = { 0 };
+ gsize len = sizeof (digest);
+ g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA1);
+ g_checksum_update (checksum, (const guchar *)local, -1);
+ g_checksum_get_digest (checksum, digest, &len);
+
+ char *encoded = zbase32_encode (digest, len);
+
+ /* If the returned string is NULL, then there must have been a memory
+ * allocation problem. Just exit immediately like g_malloc.
+ */
+ if (encoded == NULL)
+ g_error ("%s: %s", G_STRLOC, g_strerror (errno));
+
+ return encoded;
+}
+
+/* Implementation of OpenPGP Web Key Directory URLs as defined in
+ * https://datatracker.ietf.org/doc/html/draft-koch-openpgp-webkey-service
+ */
+gboolean
+ot_gpg_wkd_urls (const char *email,
+ char **out_advanced_url,
+ char **out_direct_url,
+ GError **error)
+{
+ g_return_val_if_fail (email != NULL, FALSE);
+
+ g_auto(GStrv) email_parts = g_strsplit (email, "@", -1);
+ if (g_strv_length (email_parts) != 2)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Invalid email address \"%s\"", email);
+ return FALSE;
+ }
+
+ g_autofree char *local_lowered = g_ascii_strdown (email_parts[0], -1);
+ g_autofree char *domain_lowered = g_ascii_strdown (email_parts[1], -1);
+ g_autofree char *local_encoded = encode_wkd_local (local_lowered);
+ g_autofree char *local_escaped = g_uri_escape_string (email_parts[0], NULL, FALSE);
+
+ g_autofree char *advanced_url = g_strdup_printf ("https://openpgpkey.%s"
+ "/.well-known/openpgpkey"
+ "/%s/hu/%s?l=%s",
+ email_parts[1],
+ domain_lowered,
+ local_encoded,
+ local_escaped);
+ g_debug ("GPG UID \"%s\" advanced WKD URL: %s", email, advanced_url);
+
+ g_autofree char *direct_url = g_strdup_printf ("https://%s"
+ "/.well-known/openpgpkey"
+ "/hu/%s?l=%s",
+ email_parts[1],
+ local_encoded,
+ local_escaped);
+ g_debug ("GPG UID \"%s\" direct WKD URL: %s", email, direct_url);
+
+ if (out_advanced_url != NULL)
+ *out_advanced_url = g_steal_pointer (&advanced_url);
+ if (out_direct_url != NULL)
+ *out_direct_url = g_steal_pointer (&direct_url);
+
+ return TRUE;
+}
diff --git a/src/libotutil/ot-gpg-utils.h b/src/libotutil/ot-gpg-utils.h
index e8a240b5..b559b695 100644
--- a/src/libotutil/ot-gpg-utils.h
+++ b/src/libotutil/ot-gpg-utils.h
@@ -48,4 +48,9 @@ gpgme_ctx_t ot_gpgme_new_ctx (const char *homedir,
void ot_gpgme_kill_agent (const char *homedir);
+gboolean ot_gpg_wkd_urls (const char *email,
+ char **out_advanced_url,
+ char **out_direct_url,
+ GError **error);
+
G_END_DECLS