From 6214d42bd26657e6f406b6f7039fbbac14d52369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 2 Nov 2021 09:58:04 +0100 Subject: [PATCH] import: port importd from libgcrypt to openssl^gcrypt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is heavily based on Kevin Kuehler's work, but the logic is also significantly changed: instead of a straighforward port to openssl, both versions of the code are kept, and at compile time we pick one or the other. The code is purposefully kept "dumb" — the idea is that the libgcrypt codepaths are only temporary and will be removed after everybody upgrades to openssl 3. Thus, a separate abstraction layer is not introduced. Instead, very simple ifdefs are used to select one or the other. If we added an abstraction layer, we'd have to remove it again afterwards, and it don't think it makes sense to do that for a temporary solution. Co-authored-by: Zbigniew Jędrzejewski-Szmek # Conflicts: # meson.build --- TODO | 1 - meson.build | 8 +++--- src/import/pull-job.c | 67 ++++++++++++++++++++++++++++++++++--------- src/import/pull-job.h | 4 +-- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/TODO b/TODO index 0047829c51..e710f2c587 100644 --- a/TODO +++ b/TODO @@ -437,7 +437,6 @@ Features: confusion is gone) - port resolved over from libgcrypt (DNSSEC code) - port journald + fsprg over from libgcrypt - - port importd over from libgcrypt - when that's done: kill gnutls support in resolved * add growvol and makevol options for /etc/crypttab, similar to diff --git a/meson.build b/meson.build index dee05b6017..5748853121 100644 --- a/meson.build +++ b/meson.build @@ -1538,9 +1538,9 @@ lib_openssl_or_gcrypt = conf.get('PREFER_OPENSSL') == 1 ? libopenssl : libgcrypt want_importd = get_option('importd') if want_importd != 'false' have = (conf.get('HAVE_LIBCURL') == 1 and + conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and conf.get('HAVE_ZLIB') == 1 and - conf.get('HAVE_XZ') == 1 and - conf.get('HAVE_GCRYPT') == 1) + conf.get('HAVE_XZ') == 1) if want_importd == 'true' and not have error('importd support was requested, but dependencies are not available') endif @@ -2729,10 +2729,10 @@ if conf.get('ENABLE_IMPORTD') == 1 link_with : [libshared], dependencies : [versiondep, libcurl, + lib_openssl_or_gcrypt, libz, libbzip2, - libxz, - libgcrypt], + libxz], install_rpath : rootlibexecdir, install : true, install_dir : rootlibexecdir) diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 34b116a8f8..f5eb82131e 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -41,8 +41,12 @@ PullJob* pull_job_unref(PullJob *j) { import_compress_free(&j->compress); - if (j->checksum_context) - gcry_md_close(j->checksum_context); + if (j->checksum_ctx) +#if PREFER_OPENSSL + EVP_MD_CTX_free(j->checksum_ctx); +#else + gcry_md_close(j->checksum_ctx); +#endif free(j->url); free(j->etag); @@ -102,9 +106,13 @@ static int pull_job_restart(PullJob *j, const char *new_url) { import_compress_free(&j->compress); - if (j->checksum_context) { - gcry_md_close(j->checksum_context); - j->checksum_context = NULL; + if (j->checksum_ctx) { +#if PREFER_OPENSSL + EVP_MD_CTX_free(j->checksum_ctx); +#else + gcry_md_close(j->checksum_ctx); +#endif + j->checksum_ctx = NULL; } r = pull_job_begin(j); @@ -200,16 +208,30 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { goto finish; } - if (j->checksum_context) { - uint8_t *k; + if (j->checksum_ctx) { + unsigned checksum_len; +#if PREFER_OPENSSL + uint8_t k[EVP_MAX_MD_SIZE]; - k = gcry_md_read(j->checksum_context, GCRY_MD_SHA256); + r = EVP_DigestFinal_ex(j->checksum_ctx, k, &checksum_len); + if (r == 0) { + r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get checksum."); + goto finish; + } + assert(checksum_len <= sizeof k); +#else + const uint8_t *k; + + k = gcry_md_read(j->checksum_ctx, GCRY_MD_SHA256); if (!k) { r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get checksum."); goto finish; } - j->checksum = hexmem(k, gcry_md_get_algo_dlen(GCRY_MD_SHA256)); + checksum_len = gcry_md_get_algo_dlen(GCRY_MD_SHA256); +#endif + + j->checksum = hexmem(k, checksum_len); if (!j->checksum) { r = log_oom(); goto finish; @@ -358,8 +380,16 @@ static int pull_job_write_compressed(PullJob *j, void *p, size_t sz) { return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "Content length incorrect."); - if (j->checksum_context) - gcry_md_write(j->checksum_context, p, sz); + if (j->checksum_ctx) { +#if PREFER_OPENSSL + r = EVP_DigestUpdate(j->checksum_ctx, p, sz); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Could not hash chunk."); +#else + gcry_md_write(j->checksum_ctx, p, sz); +#endif + } r = import_uncompress(&j->compress, p, sz, pull_job_write_uncompressed, j); if (r < 0) @@ -392,11 +422,22 @@ static int pull_job_open_disk(PullJob *j) { } if (j->calc_checksum) { - initialize_libgcrypt(false); +#if PREFER_OPENSSL + j->checksum_ctx = EVP_MD_CTX_new(); + if (!j->checksum_ctx) + return log_oom(); - if (gcry_md_open(&j->checksum_context, GCRY_MD_SHA256, 0) != 0) + r = EVP_DigestInit_ex(j->checksum_ctx, EVP_sha256(), NULL); + if (r == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize hash context."); +#else + initialize_libgcrypt(false); + + if (gcry_md_open(&j->checksum_ctx, GCRY_MD_SHA256, 0) != 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to initialize hash context."); +#endif } return 0; diff --git a/src/import/pull-job.h b/src/import/pull-job.h index bc5258a693..7a98b0f2f6 100644 --- a/src/import/pull-job.h +++ b/src/import/pull-job.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include #include #include "curl-util.h" #include "import-compress.h" #include "macro.h" +#include "openssl-util.h" #include "pull-common.h" typedef struct PullJob PullJob; @@ -74,7 +74,7 @@ struct PullJob { usec_t last_status_usec; bool calc_checksum; - gcry_md_hd_t checksum_context; + hash_context_t checksum_ctx; char *checksum; bool sync;