From f91acf522631025ce036cc574b166939b95540dd Mon Sep 17 00:00:00 2001 From: Jussi Laako Date: Tue, 13 Jun 2017 16:56:21 +0300 Subject: [PATCH] Add --with-crypto=gnutls Introduce support for GnuTLS for computing cryptograpic hashes, similar to the OpenSSL backend. A reason to do this is some distributors want to avoid GPLv3, and GPG pulls that in. A possible extension of using GnuTLS would be replacing the GPG signing with `PKCS#7` signatures and `X.509` keys. We also support `--with-crypto=openssl`, which has the same effect as `--with-openssl`, and continues to be supported. Changes by Colin Walters : - Drop libgcrypt option for now - Unify buildsystem on --with-crypto Link: https://mail.gnome.org/archives/ostree-list/2017-June/msg00002.html Signed-off-by: Jussi Laako Closes: #1189 Approved by: cgwalters --- .papr.yml | 14 +++++++ Makefile-libostree.am | 4 +- configure.ac | 35 ++++++++++++++--- src/libotutil/ot-checksum-instream.c | 58 +++++++++++++++++++++++----- 4 files changed, 95 insertions(+), 16 deletions(-) diff --git a/.papr.yml b/.papr.yml index 4ae345e6..03489142 100644 --- a/.papr.yml +++ b/.papr.yml @@ -63,6 +63,20 @@ tests: --- +context: f26-gnutls +inherit: true +container: + image: registry.fedoraproject.org/fedora:26 +env: + CONFIGOPTS: '--with-crypto=gnutls' + CI_PKGS: pkgconfig(gnutls) + +tests: + - ci/build.sh + - make check TESTS=tests/test-basic.sh + +--- + inherit: true context: f26-experimental-api diff --git a/Makefile-libostree.am b/Makefile-libostree.am index c83569ff..ebbe8437 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -193,11 +193,11 @@ EXTRA_DIST += \ $(NULL) libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ - $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_OPENSSL_CFLAGS) \ + $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \ -fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files)) libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \ - $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_OPENSSL_LIBS) + $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS) libostree_1_la_LIBADD += $(bupsplitpath) EXTRA_libostree_1_la_DEPENDENCIES = $(symbol_files) diff --git a/configure.ac b/configure.ac index 27e1a83d..2a248bc5 100644 --- a/configure.ac +++ b/configure.ac @@ -329,15 +329,29 @@ AS_IF([ test x$with_smack = xyes], [ ]) AM_CONDITIONAL(USE_SMACK, test $with_smack != no) +dnl crypto +AC_ARG_WITH(crypto, +AS_HELP_STRING([--with-crypto], [Choose library for checksums, one of glib, openssl, gnutls (default: glib)]), +:, with_crypto=glib) + +AS_IF([test $with_crypto = glib], + [], + [test $with_crypto = openssl], + [with_openssl=yes], + [test $with_crypto = gnutls], + [], + [AC_MSG_ERROR([Invalid --with-crypto $with_crypto])] + ) + dnl begin openssl (really just libcrypto right now) +dnl Note this option is now deprecated in favor of --with-crypto=openssl OPENSSL_DEPENDENCY="libcrypto >= 1.0.1" AC_ARG_WITH(openssl, -AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]), -:, with_openssl=no) - +AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]),with_openssl=$withval,with_openssl=no) AS_IF([ test x$with_openssl != xno ], [ - PKG_CHECK_MODULES(OT_DEP_OPENSSL, $OPENSSL_DEPENDENCY) + PKG_CHECK_MODULES(OT_DEP_CRYPTO, $OPENSSL_DEPENDENCY) AC_DEFINE([HAVE_OPENSSL], 1, [Define if we have openssl]) + with_crypto=openssl with_openssl=yes ], [ with_openssl=no @@ -346,6 +360,17 @@ if test x$with_openssl != xno; then OSTREE_FEATURES="$OSTREE_FEATURES openssl"; AM_CONDITIONAL(USE_OPENSSL, test $with_openssl != no) dnl end openssl +dnl begin gnutls; in contrast to openssl this one only +dnl supports --with-crypto=gnutls +GNUTLS_DEPENDENCY="gnutls >= 3.5.0" +AS_IF([ test $with_crypto = gnutls ], [ + PKG_CHECK_MODULES(OT_DEP_CRYPTO, $GNUTLS_DEPENDENCY) + AC_DEFINE([HAVE_GNUTLS], 1, [Define if we have gnutls]) + OSTREE_FEATURES="$OSTREE_FEATURES gnutls" +]) +AM_CONDITIONAL(USE_GNUTLS, test $with_crypto = gnutls) +dnl end gnutls + dnl Avahi dependency for finding repos AVAHI_DEPENDENCY="avahi-client >= 0.6.31 avahi-glib >= 0.6.31" @@ -536,7 +561,7 @@ echo " HTTP backend: $fetcher_backend \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux - OpenSSL libcrypto (checksums): $with_openssl + cryptographic checksums: $with_crypto systemd: $have_libsystemd libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive diff --git a/src/libotutil/ot-checksum-instream.c b/src/libotutil/ot-checksum-instream.c index 6838c774..368a337d 100644 --- a/src/libotutil/ot-checksum-instream.c +++ b/src/libotutil/ot-checksum-instream.c @@ -22,15 +22,21 @@ #include "ot-checksum-instream.h" #include "ot-checksum-utils.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) #include +#elif defined(HAVE_GNUTLS) +#include +#include #endif G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM) struct _OtChecksumInstreamPrivate { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) EVP_MD_CTX *checksum; +#elif defined(HAVE_GNUTLS) + gnutls_digest_algorithm_t checksum_type; + gnutls_hash_hd_t checksum; #else GChecksumType checksum_type; GChecksum *checksum; @@ -48,8 +54,10 @@ ot_checksum_instream_finalize (GObject *object) { OtChecksumInstream *self = (OtChecksumInstream*)object; -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) EVP_MD_CTX_destroy (self->priv->checksum); +#elif defined(HAVE_GNUTLS) + gnutls_hash_deinit (self->priv->checksum, NULL); #else g_checksum_free (self->priv->checksum); #endif @@ -75,7 +83,7 @@ ot_checksum_instream_init (OtChecksumInstream *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate); } -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) static const EVP_MD * gchecksum_type_to_openssl (GChecksumType checksum_type) { @@ -88,6 +96,18 @@ gchecksum_type_to_openssl (GChecksumType checksum_type) g_assert_not_reached (); } } +#elif defined(HAVE_GNUTLS) +static gnutls_digest_algorithm_t +gchecksum_type_to_gnutls (GChecksumType checksum_type) +{ + switch (checksum_type) + { + case G_CHECKSUM_SHA256: + return GNUTLS_DIG_SHA256; + default: + g_assert_not_reached (); + } +} #endif OtChecksumInstream * @@ -105,10 +125,13 @@ ot_checksum_instream_new (GInputStream *base, /* For now */ g_assert (checksum_type == G_CHECKSUM_SHA256); -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) stream->priv->checksum = EVP_MD_CTX_create (); g_assert (stream->priv->checksum); g_assert (EVP_DigestInit_ex (stream->priv->checksum, gchecksum_type_to_openssl (checksum_type), NULL)); +#elif defined(HAVE_GNUTLS) + stream->priv->checksum_type = gchecksum_type_to_gnutls (checksum_type); + g_assert (!gnutls_hash_init (&stream->priv->checksum, stream->priv->checksum_type)); #else stream->priv->checksum = g_checksum_new (checksum_type); stream->priv->checksum_type = checksum_type; @@ -135,8 +158,10 @@ ot_checksum_instream_read (GInputStream *stream, error); if (res > 0) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) g_assert (EVP_DigestUpdate (self->priv->checksum, buffer, res)); +#elif defined(HAVE_GNUTLS) + g_assert (!gnutls_hash (self->priv->checksum, buffer, res)); #else g_checksum_update (self->priv->checksum, buffer, res); #endif @@ -150,11 +175,15 @@ ot_checksum_instream_get_digest (OtChecksumInstream *stream, guint8 *buffer, gsize *digest_len) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) unsigned len; EVP_DigestFinal_ex (stream->priv->checksum, buffer, &len); if (digest_len) *digest_len = len; +#elif defined(HAVE_GNUTLS) + gnutls_hash_output (stream->priv->checksum, buffer); + if (digest_len) + *digest_len = gnutls_hash_get_len (stream->priv->checksum_type); #else g_checksum_get_digest (stream->priv->checksum, buffer, digest_len); #endif @@ -164,10 +193,14 @@ guint8* ot_checksum_instream_dup_digest (OtChecksumInstream *stream, gsize *ret_len) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) guint len; guchar *ret = g_malloc0 (EVP_MAX_MD_SIZE); g_assert (EVP_DigestFinal_ex (stream->priv->checksum, ret, &len)); +#elif defined(HAVE_GNUTLS) + guint len = gnutls_hash_get_len (stream->priv->checksum_type); + guchar *ret = g_malloc0 (len); + gnutls_hash_output (stream->priv->checksum, ret); #else gsize len = g_checksum_type_get_length (stream->priv->checksum_type); guchar *ret = g_malloc (len); @@ -181,13 +214,20 @@ ot_checksum_instream_dup_digest (OtChecksumInstream *stream, char * ot_checksum_instream_get_string (OtChecksumInstream *stream) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) unsigned len; guint8 csum[EVP_MAX_MD_SIZE]; g_assert (EVP_DigestFinal_ex (stream->priv->checksum, csum, &len)); char *buf = g_malloc (len * 2 + 1); ot_bin2hex (buf, (guint8*)csum, len); return buf; +#elif defined(HAVE_GNUTLS) + gsize len; + guint8 *csum = ot_checksum_instream_dup_digest(stream, &len); + char *buf = g_malloc0 (len * 2 + 1); + ot_bin2hex (buf, csum, len); + g_free (csum); + return buf; #else return g_strdup (g_checksum_get_string (stream->priv->checksum)); #endif