From 8707c9b24465ad2d45c1093a431a0597d8341077 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 29 Mar 2024 23:36:51 +0000 Subject: [PATCH] gcrypt: dlopenify for libsystemd gcrypt is used only for journal sealing operations in libsystemd, so it can be made into a dlopen dependency that is used only on demand. This allows to reduce the footprint of libsystemd in the most common cases. Keep systemd-pull and systemd-resolved with normal linking, as they are executables, and usually built with OpenSSL support anyway. --- meson.build | 9 +- src/basic/gcrypt-util.c | 110 ++++++++-- src/basic/gcrypt-util.h | 50 ++++- src/basic/meson.build | 19 +- src/import/pull-job.c | 4 +- src/journal/journalctl-authenticate.c | 8 +- src/journal/meson.build | 1 - src/libsystemd/sd-journal/fsprg.c | 193 ++++++++++-------- src/libsystemd/sd-journal/fsprg.h | 10 +- .../sd-journal/journal-authenticate.c | 68 +++--- src/libsystemd/sd-journal/journal-file.c | 3 +- src/libsystemd/sd-journal/journal-verify.c | 3 +- src/network/meson.build | 3 +- src/partition/meson.build | 1 - src/resolve/meson.build | 1 - src/resolve/resolved-dns-dnssec.c | 13 +- src/shared/meson.build | 1 - src/systemctl/meson.build | 3 +- src/sysusers/meson.build | 1 - src/test/test-dlopen-so.c | 5 + src/timesync/meson.build | 3 +- src/tmpfiles/meson.build | 1 - test/test-functions | 2 +- 23 files changed, 339 insertions(+), 173 deletions(-) diff --git a/meson.build b/meson.build index 897b3938690..64dde576800 100644 --- a/meson.build +++ b/meson.build @@ -1319,6 +1319,9 @@ if not have # link to neither of the libs if one is not found libgcrypt = [] libgpg_error = [] + libgcrypt_cflags = [] +else + libgcrypt_cflags = libgcrypt.partial_dependency(includes: true, compile_args: true) endif conf.set10('HAVE_GCRYPT', have) @@ -1951,8 +1954,7 @@ libsystemd = shared_library( include_directories : libsystemd_includes, link_args : ['-shared', '-Wl,--version-script=' + libsystemd_sym_path], - link_with : [libbasic, - libbasic_gcrypt], + link_with : [libbasic], link_whole : [libsystemd_static], dependencies : [librt, threads, @@ -1968,7 +1970,6 @@ install_libsystemd_static = static_library( 'systemd', libsystemd_sources, basic_sources, - basic_gcrypt_sources, fundamental_sources, include_directories : libsystemd_includes, build_by_default : static_libsystemd != 'false', @@ -1979,7 +1980,7 @@ install_libsystemd_static = static_library( dependencies : [libblkid, libcap, libdl, - libgcrypt, + libgcrypt_cflags, liblz4_cflags, libmount, libopenssl, diff --git a/src/basic/gcrypt-util.c b/src/basic/gcrypt-util.c index 41c9362be18..081866537c4 100644 --- a/src/basic/gcrypt-util.c +++ b/src/basic/gcrypt-util.c @@ -5,41 +5,125 @@ #include "gcrypt-util.h" #include "hexdecoct.h" -void initialize_libgcrypt(bool secmem) { - if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) - return; +static void *gcrypt_dl = NULL; - gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM); - assert_se(gcry_check_version("1.4.5")); +static DLSYM_FUNCTION(gcry_control); +static DLSYM_FUNCTION(gcry_check_version); +DLSYM_FUNCTION(gcry_md_close); +DLSYM_FUNCTION(gcry_md_copy); +DLSYM_FUNCTION(gcry_md_ctl); +DLSYM_FUNCTION(gcry_md_get_algo_dlen); +DLSYM_FUNCTION(gcry_md_open); +DLSYM_FUNCTION(gcry_md_read); +DLSYM_FUNCTION(gcry_md_reset); +DLSYM_FUNCTION(gcry_md_setkey); +DLSYM_FUNCTION(gcry_md_write); +DLSYM_FUNCTION(gcry_mpi_add); +DLSYM_FUNCTION(gcry_mpi_add_ui); +DLSYM_FUNCTION(gcry_mpi_cmp); +DLSYM_FUNCTION(gcry_mpi_cmp_ui); +DLSYM_FUNCTION(gcry_mpi_get_nbits); +DLSYM_FUNCTION(gcry_mpi_invm); +DLSYM_FUNCTION(gcry_mpi_mod); +DLSYM_FUNCTION(gcry_mpi_mul); +DLSYM_FUNCTION(gcry_mpi_mulm); +DLSYM_FUNCTION(gcry_mpi_new); +DLSYM_FUNCTION(gcry_mpi_powm); +DLSYM_FUNCTION(gcry_mpi_print); +DLSYM_FUNCTION(gcry_mpi_release); +DLSYM_FUNCTION(gcry_mpi_scan); +DLSYM_FUNCTION(gcry_mpi_set_ui); +DLSYM_FUNCTION(gcry_mpi_sub); +DLSYM_FUNCTION(gcry_mpi_subm); +DLSYM_FUNCTION(gcry_mpi_sub_ui); +DLSYM_FUNCTION(gcry_prime_check); +DLSYM_FUNCTION(gcry_randomize); +DLSYM_FUNCTION(gcry_strerror); + +static int dlopen_gcrypt(void) { + return dlopen_many_sym_or_warn( + &gcrypt_dl, + "libgcrypt.so.20", LOG_DEBUG, + DLSYM_ARG(gcry_control), + DLSYM_ARG(gcry_check_version), + DLSYM_ARG(gcry_md_close), + DLSYM_ARG(gcry_md_copy), + DLSYM_ARG(gcry_md_ctl), + DLSYM_ARG(gcry_md_get_algo_dlen), + DLSYM_ARG(gcry_md_open), + DLSYM_ARG(gcry_md_read), + DLSYM_ARG(gcry_md_reset), + DLSYM_ARG(gcry_md_setkey), + DLSYM_ARG(gcry_md_write), + DLSYM_ARG(gcry_mpi_add), + DLSYM_ARG(gcry_mpi_add_ui), + DLSYM_ARG(gcry_mpi_cmp), + DLSYM_ARG(gcry_mpi_cmp_ui), + DLSYM_ARG(gcry_mpi_get_nbits), + DLSYM_ARG(gcry_mpi_invm), + DLSYM_ARG(gcry_mpi_mod), + DLSYM_ARG(gcry_mpi_mul), + DLSYM_ARG(gcry_mpi_mulm), + DLSYM_ARG(gcry_mpi_new), + DLSYM_ARG(gcry_mpi_powm), + DLSYM_ARG(gcry_mpi_print), + DLSYM_ARG(gcry_mpi_release), + DLSYM_ARG(gcry_mpi_scan), + DLSYM_ARG(gcry_mpi_set_ui), + DLSYM_ARG(gcry_mpi_sub), + DLSYM_ARG(gcry_mpi_subm), + DLSYM_ARG(gcry_mpi_sub_ui), + DLSYM_ARG(gcry_prime_check), + DLSYM_ARG(gcry_randomize), + DLSYM_ARG(gcry_strerror)); +} + +int initialize_libgcrypt(bool secmem) { + int r; + + r = dlopen_gcrypt(); + if (r < 0) + return r; + + if (sym_gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) + return 0; + + sym_gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM); + assert_se(sym_gcry_check_version("1.4.5")); /* Turn off "secmem". Clients which wish to make use of this * feature should initialize the library manually */ if (!secmem) - gcry_control(GCRYCTL_DISABLE_SECMEM); + sym_gcry_control(GCRYCTL_DISABLE_SECMEM); - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + sym_gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + + return 0; } # if !PREFER_OPENSSL int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) { - _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL; + _cleanup_(sym_gcry_md_closep) gcry_md_hd_t md = NULL; gcry_error_t err; size_t hash_size; void *hash; char *enc; + int r; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; - hash_size = gcry_md_get_algo_dlen(md_algorithm); + hash_size = sym_gcry_md_get_algo_dlen(md_algorithm); assert(hash_size > 0); - err = gcry_md_open(&md, md_algorithm, 0); + err = sym_gcry_md_open(&md, md_algorithm, 0); if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md) return -EIO; - gcry_md_write(md, s, len); + sym_gcry_md_write(md, s, len); - hash = gcry_md_read(md, 0); + hash = sym_gcry_md_read(md, 0); if (!hash) return -EIO; diff --git a/src/basic/gcrypt-util.h b/src/basic/gcrypt-util.h index 4c40cefbeda..acb50e84b76 100644 --- a/src/basic/gcrypt-util.h +++ b/src/basic/gcrypt-util.h @@ -9,11 +9,59 @@ #if HAVE_GCRYPT #include +#include "dlfcn-util.h" #include "macro.h" -void initialize_libgcrypt(bool secmem); +DLSYM_PROTOTYPE(gcry_md_close); +DLSYM_PROTOTYPE(gcry_md_copy); +DLSYM_PROTOTYPE(gcry_md_ctl); +DLSYM_PROTOTYPE(gcry_md_get_algo_dlen); +DLSYM_PROTOTYPE(gcry_md_open); +DLSYM_PROTOTYPE(gcry_md_read); +DLSYM_PROTOTYPE(gcry_md_reset); +DLSYM_PROTOTYPE(gcry_md_setkey); +DLSYM_PROTOTYPE(gcry_md_write); +DLSYM_PROTOTYPE(gcry_mpi_add); +DLSYM_PROTOTYPE(gcry_mpi_add_ui); +DLSYM_PROTOTYPE(gcry_mpi_cmp); +DLSYM_PROTOTYPE(gcry_mpi_cmp_ui); +DLSYM_PROTOTYPE(gcry_mpi_get_nbits); +DLSYM_PROTOTYPE(gcry_mpi_invm); +DLSYM_PROTOTYPE(gcry_mpi_mod); +DLSYM_PROTOTYPE(gcry_mpi_mul); +DLSYM_PROTOTYPE(gcry_mpi_mulm); +DLSYM_PROTOTYPE(gcry_mpi_new); +DLSYM_PROTOTYPE(gcry_mpi_powm); +DLSYM_PROTOTYPE(gcry_mpi_print); +DLSYM_PROTOTYPE(gcry_mpi_release); +DLSYM_PROTOTYPE(gcry_mpi_scan); +DLSYM_PROTOTYPE(gcry_mpi_set_ui); +DLSYM_PROTOTYPE(gcry_mpi_sub); +DLSYM_PROTOTYPE(gcry_mpi_subm); +DLSYM_PROTOTYPE(gcry_mpi_sub_ui); +DLSYM_PROTOTYPE(gcry_prime_check); +DLSYM_PROTOTYPE(gcry_randomize); +DLSYM_PROTOTYPE(gcry_strerror); +int initialize_libgcrypt(bool secmem); + +static inline gcry_md_hd_t* sym_gcry_md_closep(gcry_md_hd_t *md) { + if (!md || !*md) + return NULL; + sym_gcry_md_close(*md); + + return NULL; +} DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gcry_md_hd_t, gcry_md_close, NULL); + +/* Copied from gcry_md_putc from gcrypt.h due to the need to call the sym_ variant */ +#define sym_gcry_md_putc(h,c) \ + do { \ + gcry_md_hd_t h__ = (h); \ + if ((h__)->bufpos == (h__)->bufsize) \ + sym_gcry_md_write((h__), NULL, 0); \ + (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \ + } while(false) #endif #if !PREFER_OPENSSL diff --git a/src/basic/meson.build b/src/basic/meson.build index ced027ba831..1516a9f7af3 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -35,6 +35,7 @@ basic_sources = files( 'filesystems.c', 'format-util.c', 'fs-util.c', + 'gcrypt-util.c', 'glob-util.c', 'glyph-util.c', 'gunicode.c', @@ -277,6 +278,7 @@ libbasic = static_library( include_directories : basic_includes, dependencies : [libcap, libdl, + libgcrypt_cflags, liblz4_cflags, libm, librt, @@ -286,20 +288,3 @@ libbasic = static_library( userspace], c_args : ['-fvisibility=default'], build_by_default : false) - -############################################################ - -basic_gcrypt_sources = files( - 'gcrypt-util.c', -) - -# A convenience library that is separate from libbasic to avoid -# unnecessary linking to libgcrypt. -libbasic_gcrypt = static_library( - 'basic-gcrypt', - basic_gcrypt_sources, - include_directories : basic_includes, - dependencies : [libgcrypt, - userspace], - c_args : ['-fvisibility=default'], - build_by_default : false) diff --git a/src/import/pull-job.c b/src/import/pull-job.c index a4feda40812..848255179b8 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -431,7 +431,9 @@ static int pull_job_open_disk(PullJob *j) { return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize hash context."); #else - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return log_error_errno(r, "Failed to load libgcrypt: %m"); if (gcry_md_open(&j->checksum_ctx, GCRY_MD_SHA256, 0) != 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), diff --git a/src/journal/journalctl-authenticate.c b/src/journal/journalctl-authenticate.c index 40d10323886..10630f5e6cc 100644 --- a/src/journal/journalctl-authenticate.c +++ b/src/journal/journalctl-authenticate.c @@ -102,10 +102,14 @@ int action_setup_keys(void) { return log_error_errno(r, "Failed to acquire random seed: %m"); log_info("Generating key pair..."); - FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); + r = FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); + if (r < 0) + return log_error_errno(r, "Failed to generate key pair: %m"); log_info("Generating sealing key..."); - FSPRG_GenState0(state, mpk, seed, seed_size); + r = FSPRG_GenState0(state, mpk, seed, seed_size); + if (r < 0) + return log_error_errno(r, "Failed to generate sealing key: %m"); assert(arg_interval > 0); n = now(CLOCK_REALTIME); diff --git a/src/journal/meson.build b/src/journal/meson.build index 11bb6fa1f22..7d87754e0e5 100644 --- a/src/journal/meson.build +++ b/src/journal/meson.build @@ -47,7 +47,6 @@ if get_option('link-journalctl-shared') journalctl_link_with = [libshared] else journalctl_link_with = [ - libbasic_gcrypt, libshared_static, libsystemd_static, ] diff --git a/src/libsystemd/sd-journal/fsprg.c b/src/libsystemd/sd-journal/fsprg.c index e86be6af353..5321bb89bfd 100644 --- a/src/libsystemd/sd-journal/fsprg.c +++ b/src/libsystemd/sd-journal/fsprg.c @@ -50,11 +50,11 @@ static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) { unsigned len; size_t nwritten; - assert(gcry_mpi_cmp_ui(x, 0) >= 0); - len = (gcry_mpi_get_nbits(x) + 7) / 8; + assert(sym_gcry_mpi_cmp_ui(x, 0) >= 0); + len = (sym_gcry_mpi_get_nbits(x) + 7) / 8; assert(len <= buflen); memzero(buf, buflen); - gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x); + sym_gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x); assert(nwritten == len); } @@ -62,10 +62,10 @@ static gcry_mpi_t mpi_import(const void *buf, size_t buflen) { gcry_mpi_t h; _unused_ unsigned len; - assert_se(gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0); - len = (gcry_mpi_get_nbits(h) + 7) / 8; + assert_se(sym_gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0); + len = (sym_gcry_mpi_get_nbits(h) + 7) / 8; assert(len <= buflen); - assert(gcry_mpi_cmp_ui(h, 0) >= 0); + assert(sym_gcry_mpi_cmp_ui(h, 0) >= 0); return h; } @@ -102,30 +102,30 @@ static void det_randomize(void *buf, size_t buflen, const void *seed, size_t see gcry_error_t err; uint32_t ctr; - olen = gcry_md_get_algo_dlen(RND_HASH); - err = gcry_md_open(&hd, RND_HASH, 0); + olen = sym_gcry_md_get_algo_dlen(RND_HASH); + err = sym_gcry_md_open(&hd, RND_HASH, 0); assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */ - gcry_md_write(hd, seed, seedlen); - gcry_md_putc(hd, (idx >> 24) & 0xff); - gcry_md_putc(hd, (idx >> 16) & 0xff); - gcry_md_putc(hd, (idx >> 8) & 0xff); - gcry_md_putc(hd, (idx >> 0) & 0xff); + sym_gcry_md_write(hd, seed, seedlen); + sym_gcry_md_putc(hd, (idx >> 24) & 0xff); + sym_gcry_md_putc(hd, (idx >> 16) & 0xff); + sym_gcry_md_putc(hd, (idx >> 8) & 0xff); + sym_gcry_md_putc(hd, (idx >> 0) & 0xff); for (ctr = 0; buflen; ctr++) { - err = gcry_md_copy(&hd2, hd); + err = sym_gcry_md_copy(&hd2, hd); assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */ - gcry_md_putc(hd2, (ctr >> 24) & 0xff); - gcry_md_putc(hd2, (ctr >> 16) & 0xff); - gcry_md_putc(hd2, (ctr >> 8) & 0xff); - gcry_md_putc(hd2, (ctr >> 0) & 0xff); - gcry_md_final(hd2); + sym_gcry_md_putc(hd2, (ctr >> 24) & 0xff); + sym_gcry_md_putc(hd2, (ctr >> 16) & 0xff); + sym_gcry_md_putc(hd2, (ctr >> 8) & 0xff); + sym_gcry_md_putc(hd2, (ctr >> 0) & 0xff); + sym_gcry_md_ctl(hd2, GCRYCTL_FINALIZE, NULL, 0); cpylen = (buflen < olen) ? buflen : olen; - memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen); - gcry_md_close(hd2); + memcpy(buf, sym_gcry_md_read(hd2, RND_HASH), cpylen); + sym_gcry_md_close(hd2); buf += cpylen; buflen -= cpylen; } - gcry_md_close(hd); + sym_gcry_md_close(hd); } /* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */ @@ -142,8 +142,8 @@ static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */ p = mpi_import(buf, buflen); - while (gcry_prime_check(p, 0)) - gcry_mpi_add_ui(p, p, 4); + while (sym_gcry_prime_check(p, 0)) + sym_gcry_mpi_add_ui(p, p, 4); return p; } @@ -157,8 +157,8 @@ static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen det_randomize(buf, buflen, seed, seedlen, idx); buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */ x = mpi_import(buf, buflen); - assert(gcry_mpi_cmp(x, n) < 0); - gcry_mpi_mulm(x, x, x, n); + assert(sym_gcry_mpi_cmp(x, n) < 0); + sym_gcry_mpi_mulm(x, x, x, n); return x; } @@ -167,51 +167,51 @@ static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { gcry_mpi_t phi, r; int n; - phi = gcry_mpi_new(0); - gcry_mpi_sub_ui(phi, p, 1); + phi = sym_gcry_mpi_new(0); + sym_gcry_mpi_sub_ui(phi, p, 1); /* count number of used bits in m */ for (n = 0; (1ULL << n) <= m; n++) ; - r = gcry_mpi_new(0); - gcry_mpi_set_ui(r, 1); + r = sym_gcry_mpi_new(0); + sym_gcry_mpi_set_ui(r, 1); while (n) { /* square and multiply algorithm for fast exponentiation */ n--; - gcry_mpi_mulm(r, r, r, phi); + sym_gcry_mpi_mulm(r, r, r, phi); if (m & ((uint64_t)1 << n)) { - gcry_mpi_add(r, r, r); - if (gcry_mpi_cmp(r, phi) >= 0) - gcry_mpi_sub(r, r, phi); + sym_gcry_mpi_add(r, r, r); + if (sym_gcry_mpi_cmp(r, phi) >= 0) + sym_gcry_mpi_sub(r, r, phi); } } - gcry_mpi_release(phi); + sym_gcry_mpi_release(phi); return r; } /* Decompose $x \in Z_n$ into $(xp,xq) \in Z_p \times Z_q$ using Chinese Remainder Theorem */ static void CRT_decompose(gcry_mpi_t *xp, gcry_mpi_t *xq, const gcry_mpi_t x, const gcry_mpi_t p, const gcry_mpi_t q) { - *xp = gcry_mpi_new(0); - *xq = gcry_mpi_new(0); - gcry_mpi_mod(*xp, x, p); - gcry_mpi_mod(*xq, x, q); + *xp = sym_gcry_mpi_new(0); + *xq = sym_gcry_mpi_new(0); + sym_gcry_mpi_mod(*xp, x, p); + sym_gcry_mpi_mod(*xq, x, q); } /* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */ static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) { gcry_mpi_t a, u; - a = gcry_mpi_new(0); - u = gcry_mpi_new(0); - *x = gcry_mpi_new(0); - gcry_mpi_subm(a, xq, xp, q); - gcry_mpi_invm(u, p, q); - gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */ - gcry_mpi_mul(*x, p, a); - gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */ - gcry_mpi_release(a); - gcry_mpi_release(u); + a = sym_gcry_mpi_new(0); + u = sym_gcry_mpi_new(0); + *x = sym_gcry_mpi_new(0); + sym_gcry_mpi_subm(a, xq, xp, q); + sym_gcry_mpi_invm(u, p, q); + sym_gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */ + sym_gcry_mpi_mul(*x, p, a); + sym_gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */ + sym_gcry_mpi_release(a); + sym_gcry_mpi_release(u); } /******************************************************************************/ @@ -245,18 +245,21 @@ static uint16_t read_secpar(const void *buf) { return 16 * (secpar + 1); } -void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) { +int FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) { uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN]; gcry_mpi_t n, p, q; uint16_t secpar; + int r; VALIDATE_SECPAR(_secpar); secpar = _secpar; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; if (!seed) { - gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM); + sym_gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM); seed = iseed; seedlen = FSPRG_RECOMMENDED_SEEDLEN; } @@ -271,25 +274,30 @@ void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigne } if (mpk) { - n = gcry_mpi_new(0); - gcry_mpi_mul(n, p, q); - assert(gcry_mpi_get_nbits(n) == secpar); + n = sym_gcry_mpi_new(0); + sym_gcry_mpi_mul(n, p, q); + assert(sym_gcry_mpi_get_nbits(n) == secpar); store_secpar(mpk + 0, secpar); mpi_export(mpk + 2, secpar / 8, n); - gcry_mpi_release(n); + sym_gcry_mpi_release(n); } - gcry_mpi_release(p); - gcry_mpi_release(q); + sym_gcry_mpi_release(p); + sym_gcry_mpi_release(q); + + return 0; } -void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) { +int FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) { gcry_mpi_t n, x; uint16_t secpar; + int r; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; secpar = read_secpar(mpk + 0); n = mpi_import(mpk + 2, secpar / 8); @@ -299,30 +307,37 @@ void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seed mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); memzero(state + 2 + 2 * secpar / 8, 8); - gcry_mpi_release(n); - gcry_mpi_release(x); + sym_gcry_mpi_release(n); + sym_gcry_mpi_release(x); + + return 0; } -void FSPRG_Evolve(void *state) { +int FSPRG_Evolve(void *state) { gcry_mpi_t n, x; uint16_t secpar; uint64_t epoch; + int r; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; secpar = read_secpar(state + 0); n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8); x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8); epoch = uint64_import(state + 2 + 2 * secpar / 8, 8); - gcry_mpi_mulm(x, x, x, n); + sym_gcry_mpi_mulm(x, x, x, n); epoch++; mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); - gcry_mpi_release(n); - gcry_mpi_release(x); + sym_gcry_mpi_release(n); + sym_gcry_mpi_release(x); + + return 0; } uint64_t FSPRG_GetEpoch(const void *state) { @@ -331,18 +346,21 @@ uint64_t FSPRG_GetEpoch(const void *state) { return uint64_import(state + 2 + 2 * secpar / 8, 8); } -void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { +int FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm; uint16_t secpar; + int r; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; secpar = read_secpar(msk + 0); p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8); q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8); - n = gcry_mpi_new(0); - gcry_mpi_mul(n, p, q); + n = sym_gcry_mpi_new(0); + sym_gcry_mpi_mul(n, p, q); x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */ @@ -350,8 +368,8 @@ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */ kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */ - gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ - gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ + sym_gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ + sym_gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */ @@ -360,22 +378,29 @@ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); - gcry_mpi_release(p); - gcry_mpi_release(q); - gcry_mpi_release(n); - gcry_mpi_release(x); - gcry_mpi_release(xp); - gcry_mpi_release(xq); - gcry_mpi_release(kp); - gcry_mpi_release(kq); - gcry_mpi_release(xm); + sym_gcry_mpi_release(p); + sym_gcry_mpi_release(q); + sym_gcry_mpi_release(n); + sym_gcry_mpi_release(x); + sym_gcry_mpi_release(xp); + sym_gcry_mpi_release(xq); + sym_gcry_mpi_release(kp); + sym_gcry_mpi_release(kq); + sym_gcry_mpi_release(xm); + + return 0; } -void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) { +int FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) { uint16_t secpar; + int r; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; secpar = read_secpar(state + 0); det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx); + + return 0; } diff --git a/src/libsystemd/sd-journal/fsprg.h b/src/libsystemd/sd-journal/fsprg.h index d3d88aab31a..58844885497 100644 --- a/src/libsystemd/sd-journal/fsprg.h +++ b/src/libsystemd/sd-journal/fsprg.h @@ -39,22 +39,22 @@ size_t FSPRG_mpkinbytes(unsigned secpar) _const_; size_t FSPRG_stateinbytes(unsigned secpar) _const_; /* Setup msk and mpk. Providing seed != NULL makes this algorithm deterministic. */ -void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar); +int FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar); /* Initialize state deterministically in dependence on seed. */ /* Note: in case one wants to run only one GenState0 per GenMK it is safe to use the same seed for both GenMK and GenState0. */ -void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen); +int FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen); -void FSPRG_Evolve(void *state); +int FSPRG_Evolve(void *state); uint64_t FSPRG_GetEpoch(const void *state) _pure_; /* Seek to any arbitrary state (by providing msk together with seed from GenState0). */ -void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen); +int FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen); -void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx); +int FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx); #ifdef __cplusplus } diff --git a/src/libsystemd/sd-journal/journal-authenticate.c b/src/libsystemd/sd-journal/journal-authenticate.c index 8e7533eee3d..64f5739ba8a 100644 --- a/src/libsystemd/sd-journal/journal-authenticate.c +++ b/src/libsystemd/sd-journal/journal-authenticate.c @@ -71,7 +71,7 @@ int journal_file_append_tag(JournalFile *f) { return r; /* Get the HMAC tag and store it in the object */ - memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH); + memcpy(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH); f->hmac_running = false; return 0; @@ -80,6 +80,7 @@ int journal_file_append_tag(JournalFile *f) { int journal_file_hmac_start(JournalFile *f) { uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ gcry_error_t err; + int r; assert(f); @@ -90,13 +91,17 @@ int journal_file_hmac_start(JournalFile *f) { return 0; /* Prepare HMAC for next cycle */ - gcry_md_reset(f->hmac); - FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0); - err = gcry_md_setkey(f->hmac, key, sizeof(key)); + sym_gcry_md_reset(f->hmac); + + r = FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0); + if (r < 0) + return r; + + err = sym_gcry_md_setkey(f->hmac, key, sizeof(key)); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "gcry_md_setkey() failed with error code: %s", - gcry_strerror(err)); + "sym_gcry_md_setkey() failed with error code: %s", + sym_gcry_strerror(err)); f->hmac_running = true; @@ -167,7 +172,10 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) { if (epoch == goal) return 0; - FSPRG_Evolve(f->fsprg_state); + r = FSPRG_Evolve(f->fsprg_state); + if (r < 0) + return r; + epoch = FSPRG_GetEpoch(f->fsprg_state); if (epoch < goal) { r = journal_file_append_tag(f); @@ -180,6 +188,7 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) { int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { void *msk; uint64_t epoch; + int r; assert(f); @@ -195,10 +204,8 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { if (goal == epoch) return 0; - if (goal == epoch + 1) { - FSPRG_Evolve(f->fsprg_state); - return 0; - } + if (goal == epoch + 1) + return FSPRG_Evolve(f->fsprg_state); } else { f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); f->fsprg_state = malloc(f->fsprg_state_size); @@ -209,10 +216,12 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { log_debug("Seeking FSPRG key to %"PRIu64".", goal); msk = alloca_safe(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR)); - FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR); - FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size); - return 0; + r = FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR); + if (r < 0) + return r; + + return FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size); } int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { @@ -260,25 +269,25 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin } else if (type > OBJECT_UNUSED && o->object.type != type) return -EBADMSG; - gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); + sym_gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); switch (o->object.type) { case OBJECT_DATA: /* All but hash and payload are mutable */ - gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); - gcry_md_write(f->hmac, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f)); + sym_gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); + sym_gcry_md_write(f->hmac, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f)); break; case OBJECT_FIELD: /* Same here */ - gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash)); - gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload)); + sym_gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash)); + sym_gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload)); break; case OBJECT_ENTRY: /* All */ - gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum)); + sym_gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum)); break; case OBJECT_FIELD_HASH_TABLE: @@ -289,8 +298,8 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin case OBJECT_TAG: /* All but the tag itself */ - gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); - gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch)); + sym_gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); + sym_gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch)); break; default: return -EINVAL; @@ -318,10 +327,10 @@ int journal_file_hmac_put_header(JournalFile *f) { * tail_entry_monotonic, n_data, n_fields, n_tags, * n_entry_arrays. */ - gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); - gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id)); - gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); - gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); + sym_gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); + sym_gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id)); + sym_gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); + sym_gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); return 0; } @@ -406,13 +415,16 @@ int journal_file_fss_load(JournalFile *f) { int journal_file_hmac_setup(JournalFile *f) { gcry_error_t e; + int r; if (!JOURNAL_HEADER_SEALED(f->header)) return 0; - initialize_libgcrypt(true); + r = initialize_libgcrypt(true); + if (r < 0) + return r; - e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + e = sym_gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); if (e != 0) return -EOPNOTSUPP; diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 6f29b47ff2f..11461ee0608 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -20,6 +20,7 @@ #include "fd-util.h" #include "format-util.h" #include "fs-util.h" +#include "gcrypt-util.h" #include "id128-util.h" #include "journal-authenticate.h" #include "journal-def.h" @@ -307,7 +308,7 @@ JournalFile* journal_file_close(JournalFile *f) { free(f->fsprg_seed); if (f->hmac) - gcry_md_close(f->hmac); + sym_gcry_md_close(f->hmac); #endif return mfree(f); diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c index bdaa01d66fa..2e09e715745 100644 --- a/src/libsystemd/sd-journal/journal-verify.c +++ b/src/libsystemd/sd-journal/journal-verify.c @@ -10,6 +10,7 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "gcrypt-util.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" @@ -1224,7 +1225,7 @@ int journal_file_verify( if (r < 0) goto fail; - if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { + if (memcmp(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { error(p, "Tag failed verification"); r = -EBADMSG; goto fail; diff --git a/src/network/meson.build b/src/network/meson.build index 2708b3a5bf4..14810ddb75f 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -147,8 +147,7 @@ if get_option('link-networkd-shared') networkd_link_with = [libshared] else networkd_link_with = [libsystemd_static, - libshared_static, - libbasic_gcrypt] + libshared_static] endif network_includes = [libsystemd_network_includes, include_directories(['.', 'netdev', 'tc'])] diff --git a/src/partition/meson.build b/src/partition/meson.build index 78cde2ff528..52e13681166 100644 --- a/src/partition/meson.build +++ b/src/partition/meson.build @@ -33,7 +33,6 @@ executables += [ 'c_args' : '-DSTANDALONE', 'link_with' : [ libbasic, - libbasic_gcrypt, libshared_fdisk, libshared_static, libsystemd_static, diff --git a/src/resolve/meson.build b/src/resolve/meson.build index d855ded91a3..d336b2c07bf 100644 --- a/src/resolve/meson.build +++ b/src/resolve/meson.build @@ -118,7 +118,6 @@ if conf.get('ENABLE_DNS_OVER_TLS') == 1 endif link_with = [ - libbasic_gcrypt, libshared, libsystemd_resolve_core, ] diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 8456153f1e2..233418affcb 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -890,8 +890,11 @@ static int dnssec_rrset_verify_sig( _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL; void *hash; size_t hash_size; + int r; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; #endif switch (rrsig->rrsig.algorithm) { @@ -1409,7 +1412,9 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, if (md_algorithm < 0) return -EOPNOTSUPP; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL; @@ -1554,7 +1559,9 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { if (algorithm < 0) return algorithm; - initialize_libgcrypt(false); + r = initialize_libgcrypt(false); + if (r < 0) + return r; size_t encoded_length; unsigned hash_size = gcry_md_get_algo_dlen(algorithm); diff --git a/src/shared/meson.build b/src/shared/meson.build index 11f2b5ade91..4c9b45434e0 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -358,7 +358,6 @@ libshared = shared_library( link_depends : libshared_sym_path, link_whole : [libshared_static, libbasic, - libbasic_gcrypt, libsystemd_static], dependencies : [libshared_deps, userspace], diff --git a/src/systemctl/meson.build b/src/systemctl/meson.build index 257c362cea4..88f73bf502a 100644 --- a/src/systemctl/meson.build +++ b/src/systemctl/meson.build @@ -44,8 +44,7 @@ if get_option('link-systemctl-shared') systemctl_link_with = [libshared] else systemctl_link_with = [libsystemd_static, - libshared_static, - libbasic_gcrypt] + libshared_static] endif executables += [ diff --git a/src/sysusers/meson.build b/src/sysusers/meson.build index fcb291d02c2..0f9c067d506 100644 --- a/src/sysusers/meson.build +++ b/src/sysusers/meson.build @@ -15,7 +15,6 @@ executables += [ 'c_args' : '-DSTANDALONE', 'link_with' : [ libbasic, - libbasic_gcrypt, libshared_static, libsystemd_static, ], diff --git a/src/test/test-dlopen-so.c b/src/test/test-dlopen-so.c index 3232506d5a1..00134c305e5 100644 --- a/src/test/test-dlopen-so.c +++ b/src/test/test-dlopen-so.c @@ -7,6 +7,7 @@ #include "compress.h" #include "cryptsetup-util.h" #include "elf-util.h" +#include "gcrypt-util.h" #include "idn-util.h" #include "libarchive-util.h" #include "libfido2-util.h" @@ -88,6 +89,10 @@ static int run(int argc, char **argv) { assert_se(dlopen_lzma() >= 0); #endif +#if HAVE_GCRYPT + assert_se(initialize_libgcrypt(/* secmem= */ false) >= 0); +#endif + return 0; } diff --git a/src/timesync/meson.build b/src/timesync/meson.build index 684448097c6..d843ed78bfa 100644 --- a/src/timesync/meson.build +++ b/src/timesync/meson.build @@ -21,8 +21,7 @@ if get_option('link-timesyncd-shared') timesyncd_link_with = [libshared] else timesyncd_link_with = [libsystemd_static, - libshared_static, - libbasic_gcrypt] + libshared_static] endif libtimesyncd_core = static_library( diff --git a/src/tmpfiles/meson.build b/src/tmpfiles/meson.build index 8a24a21a274..2e918509a7b 100644 --- a/src/tmpfiles/meson.build +++ b/src/tmpfiles/meson.build @@ -21,7 +21,6 @@ executables += [ 'c_args' : '-DSTANDALONE', 'link_with' : [ libbasic, - libbasic_gcrypt, libshared_static, libsystemd_static, ], diff --git a/test/test-functions b/test/test-functions index 112f8b065c7..5d63a41d80d 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1555,7 +1555,7 @@ install_missing_libraries() { local lib path # A number of dependencies is now optional via dlopen, so the install # script will not pick them up, since it looks at linkage. - for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1 libarchive; do + for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1 libarchive libgcrypt; do ddebug "Searching for $lib via pkg-config" if pkg-config --exists "$lib"; then path="$(pkg-config --variable=libdir "$lib")"