1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

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.
This commit is contained in:
Luca Boccassi 2024-03-29 23:36:51 +00:00
parent 72270f29e4
commit 8707c9b244
23 changed files with 339 additions and 173 deletions

View File

@ -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,

View File

@ -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;

View File

@ -9,11 +9,59 @@
#if HAVE_GCRYPT
#include <gcrypt.h>
#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

View File

@ -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)

View File

@ -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),

View File

@ -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);

View File

@ -47,7 +47,6 @@ if get_option('link-journalctl-shared')
journalctl_link_with = [libshared]
else
journalctl_link_with = [
libbasic_gcrypt,
libshared_static,
libsystemd_static,
]

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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'])]

View File

@ -33,7 +33,6 @@ executables += [
'c_args' : '-DSTANDALONE',
'link_with' : [
libbasic,
libbasic_gcrypt,
libshared_fdisk,
libshared_static,
libsystemd_static,

View File

@ -118,7 +118,6 @@ if conf.get('ENABLE_DNS_OVER_TLS') == 1
endif
link_with = [
libbasic_gcrypt,
libshared,
libsystemd_resolve_core,
]

View File

@ -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);

View File

@ -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],

View File

@ -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 += [

View File

@ -15,7 +15,6 @@ executables += [
'c_args' : '-DSTANDALONE',
'link_with' : [
libbasic,
libbasic_gcrypt,
libshared_static,
libsystemd_static,
],

View File

@ -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;
}

View File

@ -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(

View File

@ -21,7 +21,6 @@ executables += [
'c_args' : '-DSTANDALONE',
'link_with' : [
libbasic,
libbasic_gcrypt,
libshared_static,
libsystemd_static,
],

View File

@ -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")"