journal: replace libgcrypt with openssl (#42695)
This commit is contained in:
@@ -230,7 +230,6 @@ REQUIREMENTS:
|
||||
libarchive >= 3.0 (optional)
|
||||
libxkbcommon >= 0.3.0 (optional)
|
||||
libpcre2 (optional)
|
||||
libgcrypt (optional)
|
||||
libqrencode >= 3 (optional)
|
||||
libmicrohttpd >= 0.9.33 (optional)
|
||||
libcurl >= 7.32.0 (optional)
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@
|
||||
<structname>sd_journal</structname> objects might cause optional shared libraries to be dynamically
|
||||
loaded via
|
||||
<citerefentry project='man-pages'><refentrytitle>dlopen</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
such as decompression libraries (xz, lz4, zstd) or cryptographic libraries (gcrypt).
|
||||
such as decompression libraries (xz, lz4, zstd).
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
+3
-3
@@ -1206,8 +1206,9 @@ libqrencode = dependency('libqrencode',
|
||||
libqrencode_cflags = libqrencode.partial_dependency(includes: true, compile_args: true)
|
||||
conf.set10('HAVE_QRENCODE', libqrencode.found())
|
||||
|
||||
feature = get_option('gcrypt')
|
||||
libgcrypt = dependency('libgcrypt',
|
||||
required : get_option('gcrypt'))
|
||||
required : feature.disabled() ? feature : false)
|
||||
conf.set10('HAVE_GCRYPT', libgcrypt.found())
|
||||
if libgcrypt.found()
|
||||
libgcrypt_cflags = libgcrypt.partial_dependency(includes: true, compile_args: true)
|
||||
@@ -1813,8 +1814,7 @@ if static_libsystemd != 'false'
|
||||
install_tag: 'libsystemd',
|
||||
install_dir : libdir,
|
||||
pic : static_libsystemd_pic,
|
||||
dependencies : [libgcrypt_cflags,
|
||||
liblz4_cflags,
|
||||
dependencies : [liblz4_cflags,
|
||||
libm,
|
||||
libucontext,
|
||||
libxz_cflags,
|
||||
|
||||
@@ -64,12 +64,6 @@ const char* const systemd_features =
|
||||
|
||||
/* cryptographic libraries */
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
" +GCRYPT"
|
||||
#else
|
||||
" -GCRYPT"
|
||||
#endif
|
||||
|
||||
#if HAVE_GNUTLS
|
||||
" +GNUTLS"
|
||||
#else
|
||||
|
||||
@@ -42,7 +42,6 @@ basic_sources = files(
|
||||
'format-ifname.c',
|
||||
'format-util.c',
|
||||
'fs-util.c',
|
||||
'gcrypt-util.c',
|
||||
'glob-util.c',
|
||||
'glyph-util.c',
|
||||
'gunicode.c',
|
||||
@@ -214,7 +213,6 @@ libbasic_static = static_library(
|
||||
include_directories : basic_includes,
|
||||
implicit_include_directories : false,
|
||||
dependencies : [libbzip2_cflags,
|
||||
libgcrypt_cflags,
|
||||
liblz4_cflags,
|
||||
libxz_cflags,
|
||||
libz_cflags,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "format-util.h"
|
||||
#include "fileio.h"
|
||||
#include "hashmap.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-compression-util.h"
|
||||
#include "journal-remote.h"
|
||||
#include "journal-remote-write.h"
|
||||
@@ -1166,6 +1167,8 @@ static int run(int argc, char **argv) {
|
||||
|
||||
log_setup();
|
||||
|
||||
journal_auth_init();
|
||||
|
||||
r = parse_config();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
#include "alloc-util.h"
|
||||
#include "ansi-color.h"
|
||||
#include "chattr-util.h"
|
||||
#include "crypto-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "fsprg.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "fsprg-openssl.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "io-util.h"
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
static int format_key(
|
||||
const struct iovec *seed,
|
||||
uint64_t start,
|
||||
@@ -60,7 +60,7 @@ static int format_key(
|
||||
#endif
|
||||
|
||||
int action_setup_keys(void) {
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
_cleanup_(unlink_and_freep) char *tmpfile = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
@@ -70,7 +70,7 @@ int action_setup_keys(void) {
|
||||
|
||||
assert(arg_action == ACTION_SETUP_KEYS);
|
||||
|
||||
r = DLOPEN_GCRYPT(LOG_ERR, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
|
||||
r = DLOPEN_LIBCRYPTO(LOG_ERR, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -103,9 +103,8 @@ int action_setup_keys(void) {
|
||||
"Sealing key file %s exists already. Use --force to recreate.", path);
|
||||
|
||||
_cleanup_(iovec_erase) struct iovec
|
||||
mpk = IOVEC_ALLOCA(FSPRG_mpkinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
seed = IOVEC_ALLOCA(FSPRG_RECOMMENDED_SEEDLEN),
|
||||
state = IOVEC_ALLOCA(FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR));
|
||||
state = IOVEC_ALLOCA(fsprg_state_size(FSPRG_RECOMMENDED_SECPAR));
|
||||
|
||||
if (!arg_quiet)
|
||||
log_info("Generating seed...");
|
||||
@@ -113,15 +112,9 @@ int action_setup_keys(void) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire random seed: %m");
|
||||
|
||||
if (!arg_quiet)
|
||||
log_info("Generating key pair...");
|
||||
r = FSPRG_GenMK(NULL, mpk.iov_base, seed.iov_base, seed.iov_len, FSPRG_RECOMMENDED_SECPAR);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate key pair: %m");
|
||||
|
||||
if (!arg_quiet)
|
||||
log_info("Generating sealing key...");
|
||||
r = FSPRG_GenState0(state.iov_base, mpk.iov_base, seed.iov_base, seed.iov_len);
|
||||
r = fsprg_generate_state(FSPRG_RECOMMENDED_SECPAR, /* epoch= */ 0, &seed, &state);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate sealing key: %m");
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "format-table.h"
|
||||
#include "format-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-internal.h"
|
||||
#include "journal-verify.h"
|
||||
#include "journalctl.h"
|
||||
@@ -40,6 +41,8 @@ int action_verify(void) {
|
||||
|
||||
assert(arg_action == ACTION_VERIFY);
|
||||
|
||||
journal_auth_init();
|
||||
|
||||
r = acquire_journal(&j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -81,7 +81,7 @@ bool arg_file_stdin = false;
|
||||
int arg_priorities = 0;
|
||||
Set *arg_facilities = NULL;
|
||||
char *arg_verify_key = NULL;
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
|
||||
bool arg_force = false;
|
||||
#endif
|
||||
@@ -769,7 +769,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) {
|
||||
OPTION_GROUP("Forward Secure Sealing (FSS) Options"): {}
|
||||
|
||||
OPTION_LONG("interval", "TIME", "Time interval for changing the FSS sealing key"):
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
r = parse_sec(opts.arg, &arg_interval);
|
||||
if (r < 0 || arg_interval <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
@@ -781,7 +781,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) {
|
||||
#endif
|
||||
|
||||
OPTION_LONG("verify-key", "KEY", "Specify FSS verification key"):
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
erase_and_free(arg_verify_key);
|
||||
arg_verify_key = strdup(opts.arg);
|
||||
if (!arg_verify_key)
|
||||
@@ -800,7 +800,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) {
|
||||
#endif
|
||||
|
||||
OPTION_LONG("force", NULL, "Override of the FSS key pair with --setup-keys"):
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
arg_force = true;
|
||||
break;
|
||||
#else
|
||||
@@ -909,7 +909,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) {
|
||||
break;
|
||||
|
||||
OPTION_LONG("setup-keys", NULL, "Generate a new FSS key pair"):
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
arg_action = ACTION_SETUP_KEYS;
|
||||
break;
|
||||
#else
|
||||
|
||||
@@ -57,7 +57,7 @@ extern bool arg_file_stdin;
|
||||
extern int arg_priorities;
|
||||
extern Set *arg_facilities;
|
||||
extern char *arg_verify_key;
|
||||
#if HAVE_GCRYPT
|
||||
#if HAVE_OPENSSL
|
||||
extern usec_t arg_interval;
|
||||
extern bool arg_force;
|
||||
#endif
|
||||
|
||||
@@ -697,7 +697,10 @@ static int manager_archive_offline_user_journals(Manager *m) {
|
||||
|
||||
TAKE_FD(fd); /* Donated to journal_file_open() */
|
||||
|
||||
journal_file_write_final_tag(f);
|
||||
r = journal_file_auth_append_tag(f);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to append tag when closing journal, ignoring: %m");
|
||||
|
||||
r = journal_file_archive(f, NULL);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to archive journal file '%s', ignoring: %m", full);
|
||||
@@ -2539,18 +2542,16 @@ int manager_init(Manager *m) {
|
||||
}
|
||||
|
||||
void manager_maybe_append_tags(Manager *m) {
|
||||
#if HAVE_GCRYPT
|
||||
JournalFile *f;
|
||||
usec_t n;
|
||||
assert(m);
|
||||
|
||||
n = now(CLOCK_REALTIME);
|
||||
usec_t n = now(CLOCK_REALTIME);
|
||||
|
||||
if (m->system_journal)
|
||||
journal_file_maybe_append_tag(m->system_journal, n);
|
||||
journal_file_auth_append_tag_maybe(m->system_journal, n);
|
||||
|
||||
JournalFile *f;
|
||||
ORDERED_HASHMAP_FOREACH(f, m->user_journals)
|
||||
journal_file_maybe_append_tag(f, n);
|
||||
#endif
|
||||
journal_file_auth_append_tag_maybe(f, n);
|
||||
}
|
||||
|
||||
Manager* manager_free(Manager *m) {
|
||||
|
||||
@@ -52,6 +52,8 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
sigbus_install();
|
||||
|
||||
journal_auth_init();
|
||||
|
||||
r = manager_new(&m);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@@ -110,14 +112,12 @@ static int run(int argc, char *argv[]) {
|
||||
} else
|
||||
t = USEC_INFINITY;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
if (m->system_journal) {
|
||||
usec_t u;
|
||||
|
||||
if (journal_file_next_evolve_usec(m->system_journal, &u))
|
||||
if (journal_file_auth_next_evolve_usec(m->system_journal, &u) >= 0)
|
||||
t = MIN(t, usec_sub_unsigned(u, n));
|
||||
}
|
||||
#endif
|
||||
|
||||
r = sd_event_run(m->event, t);
|
||||
if (r < 0)
|
||||
|
||||
@@ -94,6 +94,7 @@ executables += [
|
||||
'link_with' : journalctl_link_with,
|
||||
'dependencies' : [
|
||||
liblz4_cflags,
|
||||
libopenssl_cflags,
|
||||
libxz_cflags,
|
||||
libzstd_cflags,
|
||||
],
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
sd_journal_sources = files(
|
||||
'sd-journal/audit-type.c',
|
||||
'sd-journal/catalog.c',
|
||||
'sd-journal/fsprg.c',
|
||||
'sd-journal/journal-authenticate.c',
|
||||
'sd-journal/journal-authenticate-internal.c',
|
||||
'sd-journal/journal-file.c',
|
||||
'sd-journal/journal-send.c',
|
||||
'sd-journal/journal-vacuum.c',
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "journal-authenticate-internal.h"
|
||||
#include "journal-file.h"
|
||||
|
||||
static const JournalAuthOps *auth_ops = NULL;
|
||||
|
||||
void journal_auth_set_ops(const JournalAuthOps *ops) {
|
||||
assert(ops);
|
||||
assert(!auth_ops || auth_ops == ops);
|
||||
|
||||
auth_ops = ops;
|
||||
}
|
||||
|
||||
bool journal_auth_supported(void) {
|
||||
return !!auth_ops;
|
||||
}
|
||||
|
||||
void journal_file_auth_done(JournalFile *f) {
|
||||
assert(f);
|
||||
|
||||
if (!auth_ops)
|
||||
return;
|
||||
|
||||
assert(auth_ops->free);
|
||||
f->auth_context = auth_ops->free(f->auth_context);
|
||||
}
|
||||
|
||||
int journal_file_auth_load(JournalFile *f) {
|
||||
assert(f);
|
||||
|
||||
if (!auth_ops)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (f->auth_context)
|
||||
return -EBUSY;
|
||||
|
||||
assert(auth_ops->load);
|
||||
return auth_ops->load(&f->auth_context);
|
||||
}
|
||||
|
||||
int journal_file_auth_load_key(JournalFile *f, const char *key) {
|
||||
assert(f);
|
||||
|
||||
if (!auth_ops)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (f->auth_context)
|
||||
return -EBUSY;
|
||||
|
||||
assert(auth_ops->load_key);
|
||||
return auth_ops->load_key(&f->auth_context, key);
|
||||
}
|
||||
|
||||
int journal_file_auth_epoch_to_realtime_usec(JournalFile *f, uint64_t epoch, usec_t *ret_start, usec_t *ret_end) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->epoch_to_realtime_usec);
|
||||
return auth_ops->epoch_to_realtime_usec(f->auth_context, epoch, ret_start, ret_end);
|
||||
}
|
||||
|
||||
int journal_file_auth_next_evolve_usec(JournalFile *f, usec_t *ret) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->next_evolve_usec);
|
||||
return auth_ops->next_evolve_usec(f->auth_context, ret);
|
||||
}
|
||||
|
||||
int journal_file_auth_seek(JournalFile *f, uint64_t goal) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->seek);
|
||||
return auth_ops->seek(f->auth_context, goal);
|
||||
}
|
||||
|
||||
int journal_file_auth_start(JournalFile *f) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->start);
|
||||
return auth_ops->start(f->auth_context);
|
||||
}
|
||||
|
||||
int journal_file_auth_end(JournalFile *f, uint8_t ret[static TAG_LENGTH]) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->end);
|
||||
return auth_ops->end(f->auth_context, ret);
|
||||
}
|
||||
|
||||
int journal_file_auth_put_header(JournalFile *f) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->put_header);
|
||||
return auth_ops->put_header(f->auth_context, f);
|
||||
}
|
||||
|
||||
int journal_file_auth_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->put_object);
|
||||
return auth_ops->put_object(f->auth_context, f, type, o, p);
|
||||
}
|
||||
|
||||
int journal_file_auth_append_tag(JournalFile *f) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
if (!journal_file_writable(f))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->append_tag);
|
||||
return auth_ops->append_tag(f->auth_context, f);
|
||||
}
|
||||
|
||||
int journal_file_auth_append_tag_first(JournalFile *f) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
if (!journal_file_writable(f))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->append_tag_first);
|
||||
return auth_ops->append_tag_first(f->auth_context, f);
|
||||
}
|
||||
|
||||
int journal_file_auth_append_tag_maybe(JournalFile *f, usec_t realtime) {
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
if (!journal_file_writable(f))
|
||||
return 0;
|
||||
|
||||
assert(auth_ops);
|
||||
assert(auth_ops->append_tag_maybe);
|
||||
return auth_ops->append_tag_maybe(f->auth_context, f, realtime);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "journal-def.h"
|
||||
#include "sd-forward.h"
|
||||
|
||||
typedef struct JournalAuthOps {
|
||||
JournalAuthContext* (*free)(JournalAuthContext *c);
|
||||
int (*load)(JournalAuthContext **ret);
|
||||
int (*load_key)(JournalAuthContext **ret, const char *key);
|
||||
int (*epoch_to_realtime_usec)(const JournalAuthContext *c, uint64_t epoch, usec_t *ret_start, usec_t *ret_end);
|
||||
int (*next_evolve_usec)(const JournalAuthContext *c, usec_t *ret);
|
||||
int (*seek)(JournalAuthContext *c, uint64_t goal);
|
||||
int (*start)(JournalAuthContext *c);
|
||||
int (*end)(JournalAuthContext *c, uint8_t ret[static TAG_LENGTH]);
|
||||
int (*put_header)(JournalAuthContext *c, JournalFile *f);
|
||||
int (*put_object)(JournalAuthContext *c, JournalFile *f, ObjectType type, Object *o, uint64_t p);
|
||||
int (*append_tag)(JournalAuthContext *c, JournalFile *f);
|
||||
int (*append_tag_first)(JournalAuthContext *c, JournalFile *f);
|
||||
int (*append_tag_maybe)(JournalAuthContext *c, JournalFile *f, usec_t realtime);
|
||||
} JournalAuthOps;
|
||||
|
||||
void journal_auth_set_ops(const JournalAuthOps *ops);
|
||||
bool journal_auth_supported(void);
|
||||
|
||||
void journal_file_auth_done(JournalFile *f);
|
||||
int journal_file_auth_load(JournalFile *f);
|
||||
int journal_file_auth_load_key(JournalFile *f, const char *key);
|
||||
int journal_file_auth_epoch_to_realtime_usec(JournalFile *f, uint64_t epoch, usec_t *ret_start, usec_t *ret_end);
|
||||
int journal_file_auth_next_evolve_usec(JournalFile *f, usec_t *ret);
|
||||
int journal_file_auth_seek(JournalFile *f, uint64_t goal);
|
||||
int journal_file_auth_start(JournalFile *f);
|
||||
int journal_file_auth_end(JournalFile *f, uint8_t ret[static TAG_LENGTH]);
|
||||
int journal_file_auth_put_header(JournalFile *f);
|
||||
int journal_file_auth_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p);
|
||||
int journal_file_auth_append_tag(JournalFile *f);
|
||||
int journal_file_auth_append_tag_first(JournalFile *f);
|
||||
int journal_file_auth_append_tag_maybe(JournalFile *f, usec_t realtime);
|
||||
@@ -1,555 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fsprg.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-def.h"
|
||||
#include "journal-file.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
static void* fssheader_free(FSSHeader *p) {
|
||||
/* mmap() returns MAP_FAILED on error and sets the errno */
|
||||
if (!p || p == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
assert_se(munmap(p, PAGE_ALIGN(sizeof(FSSHeader))) >= 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(FSSHeader*, fssheader_free);
|
||||
|
||||
int journal_file_append_tag(JournalFile *f) {
|
||||
#if HAVE_GCRYPT
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
if (!f->hmac_running) {
|
||||
r = journal_file_hmac_start(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
assert(f->hmac);
|
||||
|
||||
Object *o;
|
||||
uint64_t p;
|
||||
r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint64_t seqnum = le64toh(f->header->n_tags) + 1;
|
||||
f->header->n_tags = htole64(seqnum);
|
||||
|
||||
o->tag.seqnum = htole64(seqnum);
|
||||
o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state.iov_base));
|
||||
|
||||
log_debug("Writing tag %"PRIu64" for epoch %"PRIu64"",
|
||||
le64toh(o->tag.seqnum), le64toh(o->tag.epoch));
|
||||
|
||||
/* Add the tag object itself, so that we can protect its
|
||||
* header. This will exclude the actual hash value in it */
|
||||
r = journal_file_hmac_put_object(f, OBJECT_TAG, o, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Get the HMAC tag and store it in the object */
|
||||
memcpy(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH);
|
||||
f->hmac_running = false;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int journal_file_hmac_start(JournalFile *f) {
|
||||
#if HAVE_GCRYPT
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
if (f->hmac_running)
|
||||
return 0;
|
||||
|
||||
/* Prepare HMAC for next cycle */
|
||||
sym_gcry_md_reset(f->hmac);
|
||||
|
||||
uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
|
||||
CLEANUP_ERASE(key);
|
||||
r = FSPRG_GetKey(f->fsprg_state.iov_base, key, sizeof(key), 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
gcry_error_t 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),
|
||||
"sym_gcry_md_setkey() failed with error code: %s",
|
||||
sym_gcry_strerror(err));
|
||||
|
||||
f->hmac_running = true;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) {
|
||||
uint64_t t;
|
||||
|
||||
assert(f);
|
||||
assert(epoch);
|
||||
assert(JOURNAL_HEADER_SEALED(f->header));
|
||||
|
||||
if (f->fss_start_usec == 0 || f->fss_interval_usec == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (realtime < f->fss_start_usec)
|
||||
return -ESTALE;
|
||||
|
||||
t = realtime - f->fss_start_usec;
|
||||
t = t / f->fss_interval_usec;
|
||||
|
||||
*epoch = t;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) {
|
||||
uint64_t goal, epoch;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
r = journal_file_get_epoch(f, realtime, &goal);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
epoch = FSPRG_GetEpoch(f->fsprg_state.iov_base);
|
||||
if (epoch > goal)
|
||||
return -ESTALE;
|
||||
|
||||
return epoch != goal;
|
||||
}
|
||||
|
||||
int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
|
||||
uint64_t goal, epoch;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
r = journal_file_get_epoch(f, realtime, &goal);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
epoch = FSPRG_GetEpoch(f->fsprg_state.iov_base);
|
||||
if (epoch < goal)
|
||||
log_debug("Evolving FSPRG key from epoch %"PRIu64" to %"PRIu64".", epoch, goal);
|
||||
|
||||
for (;;) {
|
||||
if (epoch > goal)
|
||||
return -ESTALE;
|
||||
if (epoch == goal)
|
||||
return 0;
|
||||
|
||||
r = FSPRG_Evolve(f->fsprg_state.iov_base);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
epoch = FSPRG_GetEpoch(f->fsprg_state.iov_base);
|
||||
if (epoch < goal) {
|
||||
r = journal_file_append_tag(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
assert(iovec_is_set(&f->fsprg_seed));
|
||||
|
||||
if (iovec_is_set(&f->fsprg_state)) {
|
||||
/* Cheaper... */
|
||||
|
||||
uint64_t epoch = FSPRG_GetEpoch(f->fsprg_state.iov_base);
|
||||
if (goal == epoch)
|
||||
return 0;
|
||||
|
||||
if (goal == epoch + 1)
|
||||
return FSPRG_Evolve(f->fsprg_state.iov_base);
|
||||
} else {
|
||||
r = iovec_alloc(FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR), &f->fsprg_state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
log_debug("Seeking FSPRG key to %"PRIu64".", goal);
|
||||
|
||||
_cleanup_(iovec_erase) struct iovec msk = IOVEC_ALLOCA(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR));
|
||||
r = FSPRG_GenMK(msk.iov_base, NULL, f->fsprg_seed.iov_base, f->fsprg_seed.iov_len, FSPRG_RECOMMENDED_SECPAR);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return FSPRG_Seek(f->fsprg_state.iov_base, goal, msk.iov_base, f->fsprg_seed.iov_base, f->fsprg_seed.iov_len);
|
||||
}
|
||||
|
||||
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
if (realtime <= 0)
|
||||
realtime = now(CLOCK_REALTIME);
|
||||
|
||||
r = journal_file_fsprg_need_evolve(f, realtime);
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
|
||||
r = journal_file_append_tag(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = journal_file_fsprg_evolve(f, realtime);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p) {
|
||||
#if HAVE_GCRYPT
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
r = journal_file_hmac_start(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!o) {
|
||||
r = journal_file_move_to_object(f, type, p, &o);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (type > OBJECT_UNUSED && o->object.type != type)
|
||||
return -EBADMSG;
|
||||
|
||||
sym_gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
|
||||
|
||||
switch (o->object.type) {
|
||||
|
||||
case OBJECT_DATA:
|
||||
/* All but hash and payload are mutable */
|
||||
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 */
|
||||
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 */
|
||||
sym_gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum));
|
||||
break;
|
||||
|
||||
case OBJECT_FIELD_HASH_TABLE:
|
||||
case OBJECT_DATA_HASH_TABLE:
|
||||
case OBJECT_ENTRY_ARRAY:
|
||||
/* Nothing: everything is mutable */
|
||||
break;
|
||||
|
||||
case OBJECT_TAG:
|
||||
/* All but the tag itself */
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int journal_file_hmac_put_header(JournalFile *f) {
|
||||
#if HAVE_GCRYPT
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
r = journal_file_hmac_start(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* All but state+reserved, boot_id, arena_size,
|
||||
* tail_object_offset, n_objects, n_entries,
|
||||
* tail_entry_seqnum, head_entry_seqnum, entry_array_offset,
|
||||
* head_entry_realtime, tail_entry_realtime,
|
||||
* tail_entry_monotonic, n_data, n_fields, n_tags,
|
||||
* n_entry_arrays. */
|
||||
|
||||
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;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int journal_file_fss_load(JournalFile *f) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
_cleanup_(fssheader_freep) FSSHeader *header = NULL;
|
||||
struct stat st;
|
||||
sd_id128_t machine;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
/* This function is used to determine whether sealing should be enabled in the journal header so we
|
||||
* can't check the header to check if sealing is enabled here. */
|
||||
|
||||
r = sd_id128_get_machine(&machine);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (asprintf(&path, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
|
||||
SD_ID128_FORMAT_VAL(machine)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
|
||||
if (fd < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_error_errno(errno, "Failed to open %s: %m", path);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (st.st_size < (off_t) sizeof(FSSHeader))
|
||||
return -ENODATA;
|
||||
|
||||
header = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (header == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
if (memcmp(header->signature, (const uint8_t[]) FSS_HEADER_SIGNATURE, 8) != 0)
|
||||
return -EBADMSG;
|
||||
|
||||
if (header->incompatible_flags != 0)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
if (le64toh(header->header_size) < sizeof(FSSHeader))
|
||||
return -EBADMSG;
|
||||
|
||||
if (le64toh(header->fsprg_state_size) != FSPRG_stateinbytes(le16toh(header->fsprg_secpar)))
|
||||
return -EBADMSG;
|
||||
|
||||
f->fss_file_size = le64toh(header->header_size) + le64toh(header->fsprg_state_size);
|
||||
if ((uint64_t) st.st_size < f->fss_file_size)
|
||||
return -ENODATA;
|
||||
|
||||
if (!sd_id128_equal(machine, header->machine_id))
|
||||
return -EHOSTDOWN;
|
||||
|
||||
if (le64toh(header->start_usec) <= 0 || le64toh(header->interval_usec) <= 0)
|
||||
return -EBADMSG;
|
||||
|
||||
size_t sz = PAGE_ALIGN(f->fss_file_size);
|
||||
assert(sz < SIZE_MAX);
|
||||
f->fss_file = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (f->fss_file == MAP_FAILED) {
|
||||
f->fss_file = NULL;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
f->fss_start_usec = le64toh(f->fss_file->start_usec);
|
||||
f->fss_interval_usec = le64toh(f->fss_file->interval_usec);
|
||||
|
||||
f->fsprg_state = IOVEC_MAKE(
|
||||
(uint8_t*) f->fss_file + le64toh(f->fss_file->header_size),
|
||||
le64toh(f->fss_file->fsprg_state_size));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int journal_file_hmac_setup(JournalFile *f) {
|
||||
#if HAVE_GCRYPT
|
||||
gcry_error_t e;
|
||||
int r;
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
r = initialize_libgcrypt(true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
e = sym_gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
|
||||
if (e != 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int journal_file_append_first_tag(JournalFile *f) {
|
||||
uint64_t p;
|
||||
int r;
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return 0;
|
||||
|
||||
log_debug("Calculating first tag...");
|
||||
|
||||
r = journal_file_hmac_put_header(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = le64toh(f->header->field_hash_table_offset);
|
||||
if (p < offsetof(Object, hash_table.items))
|
||||
return -EINVAL;
|
||||
p -= offsetof(Object, hash_table.items);
|
||||
|
||||
r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, NULL, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = le64toh(f->header->data_hash_table_offset);
|
||||
if (p < offsetof(Object, hash_table.items))
|
||||
return -EINVAL;
|
||||
p -= offsetof(Object, hash_table.items);
|
||||
|
||||
r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, NULL, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = journal_file_append_tag(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int journal_file_parse_verification_key(JournalFile *f, const char *key) {
|
||||
_cleanup_(erase_and_freep) uint8_t *seed = NULL;
|
||||
size_t seed_size;
|
||||
const char *k;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
assert(key);
|
||||
|
||||
seed_size = FSPRG_RECOMMENDED_SEEDLEN;
|
||||
seed = malloc(seed_size);
|
||||
if (!seed)
|
||||
return -ENOMEM;
|
||||
|
||||
k = key;
|
||||
for (size_t c = 0; c < seed_size; c++) {
|
||||
int x, y;
|
||||
|
||||
k = skip_leading_chars(k, "-");
|
||||
|
||||
x = unhexchar(*k);
|
||||
if (x < 0)
|
||||
return -EKEYREJECTED;
|
||||
k++;
|
||||
|
||||
y = unhexchar(*k);
|
||||
if (y < 0)
|
||||
return -EKEYREJECTED;
|
||||
k++;
|
||||
|
||||
seed[c] = (uint8_t) (x * 16 + y);
|
||||
}
|
||||
|
||||
if (*k != '/')
|
||||
return -EKEYREJECTED;
|
||||
k++;
|
||||
|
||||
uint64_t start, interval;
|
||||
r = sscanf(k, "%"PRIx64"-%"PRIx64, &start, &interval);
|
||||
if (r != 2)
|
||||
return -EKEYREJECTED;
|
||||
|
||||
if (start == 0 || interval == 0)
|
||||
return -EKEYREJECTED;
|
||||
|
||||
uint64_t start_usec;
|
||||
if (!MUL_SAFE(&start_usec, start, interval))
|
||||
return -EKEYREJECTED;
|
||||
|
||||
f->fsprg_seed = IOVEC_MAKE(TAKE_PTR(seed), seed_size);
|
||||
f->fss_start_usec = start_usec;
|
||||
f->fss_interval_usec = interval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u) {
|
||||
uint64_t epoch;
|
||||
|
||||
assert(f);
|
||||
assert(u);
|
||||
|
||||
if (!JOURNAL_HEADER_SEALED(f->header))
|
||||
return false;
|
||||
|
||||
epoch = FSPRG_GetEpoch(f->fsprg_state.iov_base);
|
||||
|
||||
*u = (usec_t) (f->fss_start_usec + f->fss_interval_usec * epoch + f->fss_interval_usec);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-forward.h"
|
||||
#include "journal-file.h"
|
||||
|
||||
int journal_file_append_tag(JournalFile *f);
|
||||
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime);
|
||||
int journal_file_append_first_tag(JournalFile *f);
|
||||
|
||||
int journal_file_hmac_setup(JournalFile *f);
|
||||
int journal_file_hmac_start(JournalFile *f);
|
||||
int journal_file_hmac_put_header(JournalFile *f);
|
||||
int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p);
|
||||
|
||||
int journal_file_fss_load(JournalFile *f);
|
||||
int journal_file_parse_verification_key(JournalFile *f, const char *key);
|
||||
|
||||
int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime);
|
||||
int journal_file_fsprg_seek(JournalFile *f, uint64_t goal);
|
||||
|
||||
bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u);
|
||||
@@ -43,6 +43,9 @@ typedef struct HashItem HashItem;
|
||||
|
||||
typedef struct FSSHeader FSSHeader;
|
||||
|
||||
typedef struct JournalFile JournalFile;
|
||||
typedef struct JournalAuthContext JournalAuthContext;
|
||||
|
||||
/* Object types */
|
||||
typedef enum ObjectType {
|
||||
OBJECT_UNUSED, /* also serves as "any type" or "additional category" */
|
||||
@@ -207,7 +210,8 @@ enum {
|
||||
HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID |
|
||||
HEADER_COMPATIBLE_SEALED_CONTINUOUS,
|
||||
|
||||
HEADER_COMPATIBLE_SUPPORTED = (HAVE_GCRYPT ? HEADER_COMPATIBLE_SEALED | HEADER_COMPATIBLE_SEALED_CONTINUOUS : 0) |
|
||||
HEADER_COMPATIBLE_SUPPORTED = HEADER_COMPATIBLE_SEALED |
|
||||
HEADER_COMPATIBLE_SEALED_CONTINUOUS |
|
||||
HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
|
||||
};
|
||||
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "id128-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-authenticate-internal.h"
|
||||
#include "journal-def.h"
|
||||
#include "journal-file.h"
|
||||
#include "journal-internal.h"
|
||||
@@ -308,17 +306,7 @@ JournalFile* journal_file_close(JournalFile *f) {
|
||||
free(f->compress_buffer);
|
||||
#endif
|
||||
|
||||
if (f->fss_file) {
|
||||
size_t sz = PAGE_ALIGN(f->fss_file_size);
|
||||
assert(sz < SIZE_MAX);
|
||||
munmap(f->fss_file, sz);
|
||||
} else
|
||||
iovec_done_erase(&f->fsprg_state);
|
||||
|
||||
iovec_done_erase(&f->fsprg_seed);
|
||||
|
||||
if (f->hmac)
|
||||
sym_gcry_md_close(f->hmac);
|
||||
journal_file_auth_done(f);
|
||||
|
||||
return mfree(f);
|
||||
}
|
||||
@@ -404,16 +392,13 @@ static int journal_file_init_header(
|
||||
JournalFileFlags file_flags,
|
||||
JournalFile *template) {
|
||||
|
||||
bool seal = false;
|
||||
ssize_t k;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
/* Try to load the FSPRG state, and if we can't, then just don't do sealing */
|
||||
seal = FLAGS_SET(file_flags, JOURNAL_SEAL) && journal_file_fss_load(f) >= 0;
|
||||
#endif
|
||||
bool seal = FLAGS_SET(file_flags, JOURNAL_SEAL) && journal_file_auth_load(f) >= 0;
|
||||
|
||||
Header h = {
|
||||
.header_size = htole64(ALIGN64(sizeof(h))),
|
||||
@@ -472,14 +457,19 @@ static int journal_file_refresh_header(JournalFile *f) {
|
||||
}
|
||||
|
||||
static bool warn_wrong_flags(const JournalFile *f, bool compatible) {
|
||||
const uint32_t any = compatible ? HEADER_COMPATIBLE_ANY : HEADER_INCOMPATIBLE_ANY,
|
||||
supported = compatible ? HEADER_COMPATIBLE_SUPPORTED : HEADER_INCOMPATIBLE_SUPPORTED;
|
||||
const uint32_t any = compatible ? HEADER_COMPATIBLE_ANY : HEADER_INCOMPATIBLE_ANY;
|
||||
uint32_t supported = compatible ? HEADER_COMPATIBLE_SUPPORTED : HEADER_INCOMPATIBLE_SUPPORTED;
|
||||
const char *type = compatible ? "compatible" : "incompatible";
|
||||
uint32_t flags;
|
||||
|
||||
assert(f);
|
||||
assert(f->header);
|
||||
|
||||
/* When sealing is not supported, refuse to write to an already sealed journal file, but still allow
|
||||
* reading sealed journal files. */
|
||||
if (compatible && journal_file_writable(f) && !journal_auth_supported())
|
||||
supported &= ~(HEADER_COMPATIBLE_SEALED | HEADER_COMPATIBLE_SEALED_CONTINUOUS);
|
||||
|
||||
flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags);
|
||||
|
||||
if (flags & ~supported) {
|
||||
@@ -1833,11 +1823,9 @@ static int journal_file_append_field(
|
||||
/* The linking might have altered the window, so let's only pass the offset to hmac which will
|
||||
* move to the object again if needed. */
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_hmac_put_object(f, OBJECT_FIELD, NULL, p);
|
||||
r = journal_file_auth_put_object(f, OBJECT_FIELD, NULL, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
#endif
|
||||
|
||||
if (ret_object) {
|
||||
r = journal_file_move_to_object(f, OBJECT_FIELD, p, ret_object);
|
||||
@@ -1948,11 +1936,9 @@ static int journal_file_append_data(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
|
||||
r = journal_file_auth_put_object(f, OBJECT_DATA, o, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
#endif
|
||||
|
||||
/* Create field object ... */
|
||||
r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, NULL);
|
||||
@@ -2198,11 +2184,9 @@ static int link_entry_into_array(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, o, q);
|
||||
r = journal_file_auth_put_object(f, OBJECT_ENTRY_ARRAY, o, q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
#endif
|
||||
|
||||
write_entry_array_item(f, o, i, p);
|
||||
|
||||
@@ -2444,11 +2428,9 @@ static int journal_file_append_entry_internal(
|
||||
for (size_t i = 0; i < n_items; i++)
|
||||
write_entry_item(f, o, i, &items[i]);
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np);
|
||||
r = journal_file_auth_put_object(f, OBJECT_ENTRY, o, np);
|
||||
if (r < 0)
|
||||
return r;
|
||||
#endif
|
||||
|
||||
r = journal_file_link_entry(f, o, np, items, n_items);
|
||||
if (r < 0)
|
||||
@@ -2633,11 +2615,9 @@ int journal_file_append_entry(
|
||||
else
|
||||
machine_id = &_machine_id;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_maybe_append_tag(f, ts->realtime);
|
||||
r = journal_file_auth_append_tag_maybe(f, ts->realtime);
|
||||
if (r < 0)
|
||||
return r;
|
||||
#endif
|
||||
|
||||
if (n_iovec < ALLOCA_MAX / sizeof(EntryItem) / 2)
|
||||
items = newa(EntryItem, n_iovec);
|
||||
@@ -4284,13 +4264,11 @@ int journal_file_open(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
if (!newly_created && journal_file_writable(f) && JOURNAL_HEADER_SEALED(f->header)) {
|
||||
r = journal_file_fss_load(f);
|
||||
r = journal_file_auth_load(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (journal_file_writable(f)) {
|
||||
if (metrics) {
|
||||
@@ -4304,12 +4282,6 @@ int journal_file_open(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_hmac_setup(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
if (newly_created) {
|
||||
r = journal_file_setup_field_hash_table(f);
|
||||
if (r < 0)
|
||||
@@ -4319,11 +4291,9 @@ int journal_file_open(
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_append_first_tag(f);
|
||||
r = journal_file_auth_append_tag_first(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mmap_cache_fd_got_sigbus(f->cache_fd)) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "compress.h"
|
||||
#include "sd-forward.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "journal-def.h"
|
||||
#include "mmap-cache.h"
|
||||
#include "sparse-endian.h"
|
||||
@@ -98,17 +97,7 @@ typedef struct JournalFile {
|
||||
void *compress_buffer;
|
||||
#endif
|
||||
|
||||
gcry_md_hd_t hmac;
|
||||
bool hmac_running;
|
||||
|
||||
FSSHeader *fss_file;
|
||||
size_t fss_file_size;
|
||||
|
||||
uint64_t fss_start_usec;
|
||||
uint64_t fss_interval_usec;
|
||||
|
||||
struct iovec fsprg_state;
|
||||
struct iovec fsprg_seed;
|
||||
JournalAuthContext *auth_context;
|
||||
|
||||
/* When we insert this file into the per-boot priority queue 'newest_by_boot_id' in sd_journal, then by these keys */
|
||||
sd_id128_t newest_boot_id;
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-authenticate-internal.h"
|
||||
#include "journal-def.h"
|
||||
#include "journal-file.h"
|
||||
#include "journal-verify.h"
|
||||
@@ -821,7 +820,7 @@ int journal_file_verify(
|
||||
|
||||
int r;
|
||||
Object *o;
|
||||
uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_tag_realtime_end = 0;
|
||||
uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0, last_tag_realtime_end = 0;
|
||||
uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
|
||||
usec_t min_entry_realtime = USEC_INFINITY, max_entry_realtime = 0;
|
||||
sd_id128_t entry_boot_id = {}; /* Unnecessary initialization to appease gcc */
|
||||
@@ -836,21 +835,20 @@ int journal_file_verify(
|
||||
const char *tmp_dir = NULL;
|
||||
MMapCache *m;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
uint64_t last_tag = 0;
|
||||
#endif
|
||||
assert(f);
|
||||
|
||||
if (key) {
|
||||
#if HAVE_GCRYPT
|
||||
r = journal_file_parse_verification_key(f, key);
|
||||
r = journal_file_auth_load_key(f, key);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load verification key: %m");
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
} else if (JOURNAL_HEADER_SEALED(f->header))
|
||||
return -ENOKEY;
|
||||
} else if (JOURNAL_HEADER_SEALED(f->header)) {
|
||||
/* For a sealed journal file, request the verification key when journal sealing is supported.
|
||||
* Otherwise, log that seal verification is skipped. */
|
||||
if (journal_auth_supported())
|
||||
return -ENOKEY;
|
||||
else
|
||||
log_notice("Journal file is sealed, but journal sealing support is disabled. Skipping seal verification.");
|
||||
}
|
||||
|
||||
r = var_tmp_dir(&tmp_dir);
|
||||
if (r < 0) {
|
||||
@@ -1155,14 +1153,15 @@ int journal_file_verify(
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
if (JOURNAL_HEADER_SEALED(f->header)) {
|
||||
if (JOURNAL_HEADER_SEALED(f->header) && journal_auth_supported()) {
|
||||
uint64_t q, rt, rt_end;
|
||||
|
||||
debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
|
||||
|
||||
rt = f->fss_start_usec + le64toh(o->tag.epoch) * f->fss_interval_usec;
|
||||
rt_end = usec_add(rt, f->fss_interval_usec);
|
||||
r = journal_file_auth_epoch_to_realtime_usec(f, le64toh(o->tag.epoch), &rt, &rt_end);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (entry_realtime_set && entry_realtime >= rt_end) {
|
||||
error(p,
|
||||
"tag/entry realtime timestamp out of synchronization (%"PRIu64" >= %"PRIu64")",
|
||||
@@ -1192,16 +1191,16 @@ int journal_file_verify(
|
||||
/* OK, now we know the epoch. So let's now set
|
||||
* it, and calculate the HMAC for everything
|
||||
* since the last tag. */
|
||||
r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
|
||||
r = journal_file_auth_seek(f, le64toh(o->tag.epoch));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = journal_file_hmac_start(f);
|
||||
r = journal_file_auth_start(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (last_tag == 0) {
|
||||
r = journal_file_hmac_put_header(f);
|
||||
r = journal_file_auth_put_header(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -1214,7 +1213,7 @@ int journal_file_verify(
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q);
|
||||
r = journal_file_auth_put_object(f, OBJECT_UNUSED, o, q);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -1226,20 +1225,24 @@ int journal_file_verify(
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (memcmp(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
|
||||
uint8_t tag[TAG_LENGTH];
|
||||
CLEANUP_ERASE(tag);
|
||||
|
||||
r = journal_file_auth_end(f, tag);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (memcmp(o->tag.tag, tag, TAG_LENGTH) != 0) {
|
||||
error(p, "Tag failed verification");
|
||||
r = -EBADMSG;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f->hmac_running = false;
|
||||
last_tag_realtime = rt;
|
||||
last_tag_realtime_end = rt_end;
|
||||
}
|
||||
|
||||
last_tag = p + ALIGN64(le64toh(o->object.size));
|
||||
#endif
|
||||
|
||||
last_epoch = le64toh(o->tag.epoch);
|
||||
|
||||
n_tags++;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "chattr-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-file-util.h"
|
||||
#include "journal-verify.h"
|
||||
#include "log.h"
|
||||
@@ -174,6 +175,8 @@ int main(int argc, char *argv[]) {
|
||||
const char *verification_key = NULL;
|
||||
int max_iterations = 512;
|
||||
|
||||
journal_auth_init();
|
||||
|
||||
if (argc > 1) {
|
||||
/* Don't limit the number of iterations when the verification key
|
||||
* is provided on the command line, we want to do that only in CIs */
|
||||
@@ -187,10 +190,9 @@ int main(int argc, char *argv[]) {
|
||||
ASSERT_OK_ERRNO(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1));
|
||||
run_test(verification_key, max_iterations);
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
/* If we're running without any arguments and we're compiled with gcrypt
|
||||
/* If we're running without any arguments and journal sealing support is enabled,
|
||||
* check the journal verification stuff with a valid key as well */
|
||||
if (argc <= 1) {
|
||||
if (argc <= 1 && journal_auth_supported()) {
|
||||
verification_key = "c262bd-85187f-0b1b04-877cc5/1c7af8-35a4e900";
|
||||
|
||||
ASSERT_OK_ERRNO(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1));
|
||||
@@ -199,7 +201,6 @@ int main(int argc, char *argv[]) {
|
||||
ASSERT_OK_ERRNO(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1));
|
||||
run_test(verification_key, max_iterations);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -55,9 +55,8 @@ static void test_non_empty_one(void) {
|
||||
iovec = IOVEC_MAKE_STRING(test);
|
||||
ASSERT_OK_ZERO(journal_file_append_entry(f, &ts, &fake_boot_id, &iovec, 1, NULL, NULL, NULL, NULL));
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
journal_file_append_tag(f);
|
||||
#endif
|
||||
journal_file_auth_append_tag(f);
|
||||
|
||||
journal_file_dump(f);
|
||||
|
||||
ASSERT_EQ(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p), 1);
|
||||
@@ -200,9 +199,8 @@ static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
|
||||
iovec = IOVEC_MAKE(data, data_size);
|
||||
ASSERT_OK_ZERO(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL, NULL));
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
journal_file_append_tag(f);
|
||||
#endif
|
||||
journal_file_auth_append_tag(f);
|
||||
|
||||
journal_file_dump(f);
|
||||
|
||||
/* We have to partially reimplement some of the dump logic, because the normal next_entry does the
|
||||
@@ -590,6 +588,8 @@ static int intro(void) {
|
||||
if (access("/etc/machine-id", F_OK) != 0)
|
||||
return log_tests_skipped("/etc/machine-id not found");
|
||||
|
||||
journal_auth_init();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+163
-122
@@ -17,7 +17,6 @@
|
||||
#include "strv.h"
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
# include <openssl/core_names.h>
|
||||
# include <openssl/kdf.h>
|
||||
# include <openssl/provider.h>
|
||||
# include <openssl/store.h>
|
||||
@@ -37,14 +36,14 @@ struct OpenSSLAskPasswordUI {
|
||||
#endif
|
||||
};
|
||||
|
||||
static DLSYM_PROTOTYPE(ASN1_INTEGER_dup) = NULL;
|
||||
static DLSYM_PROTOTYPE(ASN1_INTEGER_free) = NULL;
|
||||
static DLSYM_PROTOTYPE(ASN1_INTEGER_set) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_ANY_it) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_BIT_STRING_it) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_BMPSTRING_it) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_BMPSTRING_new) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_IA5STRING_it) = NULL;
|
||||
static DLSYM_PROTOTYPE(ASN1_INTEGER_dup) = NULL;
|
||||
static DLSYM_PROTOTYPE(ASN1_INTEGER_free) = NULL;
|
||||
static DLSYM_PROTOTYPE(ASN1_INTEGER_set) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_OBJECT_it) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_OCTET_STRING_free) = NULL;
|
||||
DLSYM_PROTOTYPE(ASN1_OCTET_STRING_it) = NULL;
|
||||
@@ -73,12 +72,32 @@ DLSYM_PROTOTYPE(BIO_s_mem) = NULL;
|
||||
DLSYM_PROTOTYPE(BIO_write) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_CTX_free) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_CTX_new) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_CTX_secure_new) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_add) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_add_word) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_bin2bn) = NULL;
|
||||
static DLSYM_PROTOTYPE(BN_bn2bin) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_bn2bin) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_bn2binpad) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_bn2nativepad) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_check_prime) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_clear_free) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_cmp) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_copy) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_free) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_is_negative) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mod_exp) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mod_inverse) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mod_lshift1_quick) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mod_mul) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mod_sqr) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mod_sub) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_mul) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_new) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_nnmod) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_num_bits) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_secure_new) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_set_word) = NULL;
|
||||
DLSYM_PROTOTYPE(BN_sub_word) = NULL;
|
||||
DLSYM_PROTOTYPE(CRYPTO_free) = NULL;
|
||||
DLSYM_PROTOTYPE(ECDSA_SIG_free) = NULL;
|
||||
DLSYM_PROTOTYPE(EC_GROUP_free) = NULL;
|
||||
@@ -130,12 +149,13 @@ static DLSYM_PROTOTYPE(EVP_KDF_fetch) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_KDF_free) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_CTX_free) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_MAC_CTX_get_mac_size) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_MAC_CTX_new) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_MAC_fetch) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_MAC_final) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_CTX_new) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_fetch) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_final) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_free) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_MAC_init) = NULL;
|
||||
static DLSYM_PROTOTYPE(EVP_MAC_update) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_init) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MAC_update) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MD_CTX_copy_ex) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MD_CTX_free) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MD_CTX_get0_md) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_MD_CTX_new) = NULL;
|
||||
@@ -185,8 +205,6 @@ DLSYM_PROTOTYPE(EVP_sha256) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_sha384) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_sha512) = NULL;
|
||||
DLSYM_PROTOTYPE(HMAC) = NULL;
|
||||
DLSYM_PROTOTYPE(SHA1) = NULL;
|
||||
DLSYM_PROTOTYPE(SHA512) = NULL;
|
||||
DLSYM_PROTOTYPE(OBJ_nid2obj) = NULL;
|
||||
DLSYM_PROTOTYPE(OBJ_nid2sn) = NULL;
|
||||
DLSYM_PROTOTYPE(OBJ_sn2nid) = NULL;
|
||||
@@ -197,11 +215,11 @@ DLSYM_PROTOTYPE(OPENSSL_sk_pop_free) = NULL;
|
||||
DLSYM_PROTOTYPE(OPENSSL_sk_push) = NULL;
|
||||
DLSYM_PROTOTYPE(OPENSSL_sk_value) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_EC_curve_nid2name) = NULL;
|
||||
static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_new) = NULL;
|
||||
static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_free) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_BLD_free) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_BLD_new) = NULL;
|
||||
static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_push_octet_string) = NULL;
|
||||
static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_push_utf8_string) = NULL;
|
||||
static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_to_param) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_BLD_push_utf8_string) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_BLD_to_param) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_construct_BN) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_construct_end) = NULL;
|
||||
DLSYM_PROTOTYPE(OSSL_PARAM_construct_octet_string) = NULL;
|
||||
@@ -220,12 +238,12 @@ DLSYM_PROTOTYPE(PEM_read_PrivateKey) = NULL;
|
||||
DLSYM_PROTOTYPE(PEM_read_X509) = NULL;
|
||||
static DLSYM_PROTOTYPE(PEM_read_bio_PrivateKey) = NULL;
|
||||
static DLSYM_PROTOTYPE(PEM_read_bio_X509) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS5_PBKDF2_HMAC) = NULL;
|
||||
DLSYM_PROTOTYPE(PEM_write_PUBKEY) = NULL;
|
||||
DLSYM_PROTOTYPE(PEM_write_PrivateKey) = NULL;
|
||||
DLSYM_PROTOTYPE(PEM_write_X509) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_free) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS5_PBKDF2_HMAC) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS7_ATTR_SIGN_it) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_free) = NULL;
|
||||
static DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_new) = NULL;
|
||||
static DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_set) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS7_add0_attrib_signing_time) = NULL;
|
||||
@@ -246,22 +264,24 @@ DLSYM_PROTOTYPE(PKCS7_set_content) = NULL;
|
||||
static DLSYM_PROTOTYPE(PKCS7_set_type) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS7_sign) = NULL;
|
||||
DLSYM_PROTOTYPE(PKCS7_verify) = NULL;
|
||||
static DLSYM_PROTOTYPE(X509_ALGOR_set0) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_NAME_free) = NULL;
|
||||
DLSYM_PROTOTYPE(SHA1) = NULL;
|
||||
DLSYM_PROTOTYPE(SHA512) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_ALGOR_free) = NULL;
|
||||
static DLSYM_PROTOTYPE(X509_ALGOR_set0) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_ATTRIBUTE_free) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_NAME_free) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_NAME_oneline) = NULL;
|
||||
static DLSYM_PROTOTYPE(X509_NAME_set) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_host) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_ip) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set_hostflags) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_free) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_gmtime_adj) = NULL;
|
||||
static DLSYM_PROTOTYPE(X509_get0_serialNumber) = NULL;
|
||||
static DLSYM_PROTOTYPE(X509_get_issuer_name) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_get_pubkey) = NULL;
|
||||
static DLSYM_PROTOTYPE(X509_get_signature_info) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_get_subject_name) = NULL;
|
||||
DLSYM_PROTOTYPE(X509_gmtime_adj) = NULL;
|
||||
DLSYM_PROTOTYPE(d2i_ASN1_OCTET_STRING) = NULL;
|
||||
DLSYM_PROTOTYPE(d2i_ECPKParameters) = NULL;
|
||||
DLSYM_PROTOTYPE(d2i_PKCS7) = NULL;
|
||||
@@ -276,7 +296,6 @@ static DLSYM_PROTOTYPE(i2d_PublicKey) = NULL;
|
||||
DLSYM_PROTOTYPE(i2d_X509) = NULL;
|
||||
DLSYM_PROTOTYPE(i2d_X509_NAME) = NULL;
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_PARAM_BLD*, sym_OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_STORE_CTX*, sym_OSSL_STORE_close, OSSL_STORE_closep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_STORE_INFO*, sym_OSSL_STORE_INFO_free, OSSL_STORE_INFO_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_KDF*, sym_EVP_KDF_free, EVP_KDF_freep, NULL);
|
||||
@@ -304,11 +323,11 @@ DLSYM_PROTOTYPE(EC_KEY_new) = NULL;
|
||||
DLSYM_PROTOTYPE(EC_KEY_set_group) = NULL;
|
||||
DLSYM_PROTOTYPE(EC_KEY_set_public_key) = NULL;
|
||||
DLSYM_PROTOTYPE(EVP_PKEY_assign) = NULL;
|
||||
DLSYM_PROTOTYPE(RSAPublicKey_dup) = NULL;
|
||||
DLSYM_PROTOTYPE(RSA_free) = NULL;
|
||||
DLSYM_PROTOTYPE(RSA_new) = NULL;
|
||||
DLSYM_PROTOTYPE(RSA_set0_key) = NULL;
|
||||
DLSYM_PROTOTYPE(RSA_size) = NULL;
|
||||
DLSYM_PROTOTYPE(RSAPublicKey_dup) = NULL;
|
||||
REENABLE_WARNING;
|
||||
#endif
|
||||
|
||||
@@ -348,15 +367,10 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(ASN1_BIT_STRING_it),
|
||||
DLSYM_ARG(ASN1_BMPSTRING_it),
|
||||
DLSYM_ARG(ASN1_BMPSTRING_new),
|
||||
DLSYM_ARG(ASN1_get_object),
|
||||
DLSYM_ARG(ASN1_IA5STRING_it),
|
||||
DLSYM_ARG(ASN1_INTEGER_dup),
|
||||
DLSYM_ARG(ASN1_INTEGER_free),
|
||||
DLSYM_ARG(ASN1_INTEGER_set),
|
||||
DLSYM_ARG(ASN1_item_d2i),
|
||||
DLSYM_ARG(ASN1_item_free),
|
||||
DLSYM_ARG(ASN1_item_i2d),
|
||||
DLSYM_ARG(ASN1_item_new),
|
||||
DLSYM_ARG(ASN1_OBJECT_it),
|
||||
DLSYM_ARG(ASN1_OCTET_STRING_free),
|
||||
DLSYM_ARG(ASN1_OCTET_STRING_it),
|
||||
@@ -369,35 +383,56 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(ASN1_TIME_free),
|
||||
DLSYM_ARG(ASN1_TIME_set),
|
||||
DLSYM_ARG(ASN1_TYPE_new),
|
||||
DLSYM_ARG(ASN1_get_object),
|
||||
DLSYM_ARG(ASN1_item_d2i),
|
||||
DLSYM_ARG(ASN1_item_free),
|
||||
DLSYM_ARG(ASN1_item_i2d),
|
||||
DLSYM_ARG(ASN1_item_new),
|
||||
DLSYM_ARG(BIO_ctrl),
|
||||
DLSYM_ARG(BIO_find_type),
|
||||
DLSYM_ARG(BIO_free_all),
|
||||
DLSYM_ARG(BIO_free),
|
||||
DLSYM_ARG(BIO_free_all),
|
||||
DLSYM_ARG(BIO_new),
|
||||
DLSYM_ARG(BIO_new_mem_buf),
|
||||
DLSYM_ARG(BIO_new_socket),
|
||||
DLSYM_ARG(BIO_new),
|
||||
DLSYM_ARG(BIO_s_mem),
|
||||
DLSYM_ARG(BIO_write),
|
||||
DLSYM_ARG(BN_bin2bn),
|
||||
DLSYM_ARG(BN_bn2bin),
|
||||
DLSYM_ARG(BN_bn2nativepad),
|
||||
DLSYM_ARG(BN_CTX_free),
|
||||
DLSYM_ARG(BN_CTX_new),
|
||||
DLSYM_ARG(BN_CTX_secure_new),
|
||||
DLSYM_ARG(BN_add),
|
||||
DLSYM_ARG(BN_add_word),
|
||||
DLSYM_ARG(BN_bin2bn),
|
||||
DLSYM_ARG(BN_bn2bin),
|
||||
DLSYM_ARG(BN_bn2binpad),
|
||||
DLSYM_ARG(BN_bn2nativepad),
|
||||
DLSYM_ARG(BN_check_prime),
|
||||
DLSYM_ARG(BN_clear_free),
|
||||
DLSYM_ARG(BN_cmp),
|
||||
DLSYM_ARG(BN_copy),
|
||||
DLSYM_ARG(BN_free),
|
||||
DLSYM_ARG(BN_is_negative),
|
||||
DLSYM_ARG(BN_mod_exp),
|
||||
DLSYM_ARG(BN_mod_inverse),
|
||||
DLSYM_ARG(BN_mod_lshift1_quick),
|
||||
DLSYM_ARG(BN_mod_mul),
|
||||
DLSYM_ARG(BN_mod_sqr),
|
||||
DLSYM_ARG(BN_mod_sub),
|
||||
DLSYM_ARG(BN_mul),
|
||||
DLSYM_ARG(BN_new),
|
||||
DLSYM_ARG(BN_nnmod),
|
||||
DLSYM_ARG(BN_num_bits),
|
||||
DLSYM_ARG(BN_secure_new),
|
||||
DLSYM_ARG(BN_set_word),
|
||||
DLSYM_ARG(BN_sub_word),
|
||||
DLSYM_ARG(CRYPTO_free),
|
||||
DLSYM_ARG(d2i_ASN1_OCTET_STRING),
|
||||
DLSYM_ARG(d2i_ECPKParameters),
|
||||
DLSYM_ARG(d2i_PKCS7),
|
||||
DLSYM_ARG(d2i_PUBKEY),
|
||||
DLSYM_ARG(d2i_X509),
|
||||
DLSYM_ARG(ECDSA_SIG_free),
|
||||
DLSYM_ARG(EC_GROUP_free),
|
||||
DLSYM_ARG(EC_GROUP_get_curve_name),
|
||||
DLSYM_ARG(EC_GROUP_get_curve),
|
||||
DLSYM_ARG(EC_GROUP_get_field_type),
|
||||
DLSYM_ARG(EC_GROUP_get0_generator),
|
||||
DLSYM_ARG(EC_GROUP_get0_order),
|
||||
DLSYM_ARG(EC_GROUP_get_curve),
|
||||
DLSYM_ARG(EC_GROUP_get_curve_name),
|
||||
DLSYM_ARG(EC_GROUP_get_field_type),
|
||||
DLSYM_ARG(EC_GROUP_new_by_curve_name),
|
||||
DLSYM_ARG(EC_POINT_free),
|
||||
DLSYM_ARG(EC_POINT_new),
|
||||
@@ -405,36 +440,11 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(EC_POINT_point2buf),
|
||||
DLSYM_ARG(EC_POINT_point2oct),
|
||||
DLSYM_ARG(EC_POINT_set_affine_coordinates),
|
||||
DLSYM_ARG(ECDSA_SIG_free),
|
||||
#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||
DLSYM_ARG_FORCE(ENGINE_by_id),
|
||||
DLSYM_ARG_FORCE(ENGINE_free),
|
||||
DLSYM_ARG_FORCE(ENGINE_init),
|
||||
DLSYM_ARG_FORCE(ENGINE_load_private_key),
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||
DLSYM_ARG_FORCE(EC_KEY_check_key),
|
||||
DLSYM_ARG_FORCE(EC_KEY_free),
|
||||
DLSYM_ARG_FORCE(EC_KEY_new),
|
||||
DLSYM_ARG_FORCE(EC_KEY_set_group),
|
||||
DLSYM_ARG_FORCE(EC_KEY_set_public_key),
|
||||
DLSYM_ARG_FORCE(ECDSA_do_verify),
|
||||
DLSYM_ARG_FORCE(ECDSA_SIG_new),
|
||||
DLSYM_ARG_FORCE(ECDSA_SIG_set0),
|
||||
DLSYM_ARG_FORCE(EVP_PKEY_assign),
|
||||
DLSYM_ARG_FORCE(RSA_free),
|
||||
DLSYM_ARG_FORCE(RSA_new),
|
||||
DLSYM_ARG_FORCE(RSA_set0_key),
|
||||
DLSYM_ARG_FORCE(RSA_size),
|
||||
DLSYM_ARG_FORCE(RSAPublicKey_dup),
|
||||
#endif
|
||||
DLSYM_ARG(ERR_clear_error),
|
||||
DLSYM_ARG(ERR_error_string_n),
|
||||
DLSYM_ARG(ERR_error_string),
|
||||
DLSYM_ARG(ERR_error_string_n),
|
||||
DLSYM_ARG(ERR_get_error),
|
||||
DLSYM_ARG(ERR_peek_last_error),
|
||||
DLSYM_ARG(EVP_aes_256_ctr),
|
||||
DLSYM_ARG(EVP_aes_256_gcm),
|
||||
DLSYM_ARG(EVP_CIPHER_CTX_ctrl),
|
||||
DLSYM_ARG(EVP_CIPHER_CTX_free),
|
||||
DLSYM_ARG(EVP_CIPHER_CTX_get_block_size),
|
||||
@@ -456,11 +466,9 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(EVP_DigestVerify),
|
||||
DLSYM_ARG(EVP_DigestVerifyInit),
|
||||
DLSYM_ARG(EVP_EncryptFinal_ex),
|
||||
DLSYM_ARG(EVP_EncryptInit_ex),
|
||||
DLSYM_ARG(EVP_EncryptInit),
|
||||
DLSYM_ARG(EVP_EncryptInit_ex),
|
||||
DLSYM_ARG(EVP_EncryptUpdate),
|
||||
DLSYM_ARG(EVP_get_cipherbyname),
|
||||
DLSYM_ARG(EVP_get_digestbyname),
|
||||
DLSYM_ARG(EVP_KDF_CTX_free),
|
||||
DLSYM_ARG(EVP_KDF_CTX_new),
|
||||
DLSYM_ARG(EVP_KDF_derive),
|
||||
@@ -474,59 +482,56 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(EVP_MAC_free),
|
||||
DLSYM_ARG(EVP_MAC_init),
|
||||
DLSYM_ARG(EVP_MAC_update),
|
||||
DLSYM_ARG(EVP_MD_CTX_copy_ex),
|
||||
DLSYM_ARG(EVP_MD_CTX_free),
|
||||
DLSYM_ARG(EVP_MD_CTX_get0_md),
|
||||
DLSYM_ARG(EVP_MD_CTX_new),
|
||||
DLSYM_ARG(EVP_MD_CTX_set_pkey_ctx),
|
||||
DLSYM_ARG(EVP_MD_fetch),
|
||||
DLSYM_ARG(EVP_MD_free),
|
||||
DLSYM_ARG(EVP_MD_get0_name),
|
||||
DLSYM_ARG(EVP_MD_get_size),
|
||||
DLSYM_ARG(EVP_MD_get_type),
|
||||
DLSYM_ARG(EVP_MD_get0_name),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_free),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_new),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_new_from_name),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_new_id),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_new),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_set0_rsa_oaep_label),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_set_ec_paramgen_curve_nid),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_set_rsa_oaep_md),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_set_rsa_padding),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_set_signature_md),
|
||||
DLSYM_ARG(EVP_PKEY_CTX_set0_rsa_oaep_label),
|
||||
DLSYM_ARG(EVP_PKEY_derive),
|
||||
DLSYM_ARG(EVP_PKEY_derive_init),
|
||||
DLSYM_ARG(EVP_PKEY_derive_set_peer),
|
||||
DLSYM_ARG(EVP_PKEY_derive),
|
||||
DLSYM_ARG(EVP_PKEY_encrypt_init),
|
||||
DLSYM_ARG(EVP_PKEY_encrypt),
|
||||
DLSYM_ARG(EVP_PKEY_encrypt_init),
|
||||
DLSYM_ARG(EVP_PKEY_eq),
|
||||
DLSYM_ARG(EVP_PKEY_free),
|
||||
DLSYM_ARG(EVP_PKEY_fromdata_init),
|
||||
DLSYM_ARG(EVP_PKEY_fromdata),
|
||||
DLSYM_ARG(EVP_PKEY_fromdata_init),
|
||||
DLSYM_ARG(EVP_PKEY_get1_encoded_public_key),
|
||||
DLSYM_ARG(EVP_PKEY_get_base_id),
|
||||
DLSYM_ARG(EVP_PKEY_get_bits),
|
||||
DLSYM_ARG(EVP_PKEY_get_bn_param),
|
||||
DLSYM_ARG(EVP_PKEY_get_group_name),
|
||||
DLSYM_ARG(EVP_PKEY_get_id),
|
||||
DLSYM_ARG(EVP_PKEY_get_utf8_string_param),
|
||||
DLSYM_ARG(EVP_PKEY_get1_encoded_public_key),
|
||||
DLSYM_ARG(EVP_PKEY_keygen_init),
|
||||
DLSYM_ARG(EVP_PKEY_keygen),
|
||||
DLSYM_ARG(EVP_PKEY_new_raw_public_key),
|
||||
DLSYM_ARG(EVP_PKEY_keygen_init),
|
||||
DLSYM_ARG(EVP_PKEY_new),
|
||||
DLSYM_ARG(EVP_PKEY_verify_init),
|
||||
DLSYM_ARG(EVP_PKEY_new_raw_public_key),
|
||||
DLSYM_ARG(EVP_PKEY_verify),
|
||||
DLSYM_ARG(EVP_PKEY_verify_init),
|
||||
DLSYM_ARG(EVP_aes_256_ctr),
|
||||
DLSYM_ARG(EVP_aes_256_gcm),
|
||||
DLSYM_ARG(EVP_get_cipherbyname),
|
||||
DLSYM_ARG(EVP_get_digestbyname),
|
||||
DLSYM_ARG(EVP_sha1),
|
||||
DLSYM_ARG(EVP_sha256),
|
||||
DLSYM_ARG(EVP_sha384),
|
||||
DLSYM_ARG(EVP_sha512),
|
||||
DLSYM_ARG(HMAC),
|
||||
DLSYM_ARG(i2d_ASN1_INTEGER),
|
||||
DLSYM_ARG(i2d_PKCS7_fp),
|
||||
DLSYM_ARG(i2d_PKCS7),
|
||||
DLSYM_ARG(i2d_PUBKEY_fp),
|
||||
DLSYM_ARG(i2d_PUBKEY),
|
||||
DLSYM_ARG(i2d_PublicKey),
|
||||
DLSYM_ARG(i2d_X509_NAME),
|
||||
DLSYM_ARG(i2d_X509),
|
||||
DLSYM_ARG(OBJ_nid2obj),
|
||||
DLSYM_ARG(OBJ_nid2sn),
|
||||
DLSYM_ARG(OBJ_sn2nid),
|
||||
@@ -548,30 +553,33 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(OSSL_PARAM_construct_utf8_string),
|
||||
DLSYM_ARG(OSSL_PARAM_free),
|
||||
DLSYM_ARG(OSSL_PROVIDER_try_load),
|
||||
DLSYM_ARG(OSSL_STORE_close),
|
||||
DLSYM_ARG(OSSL_STORE_expect),
|
||||
DLSYM_ARG(OSSL_STORE_INFO_free),
|
||||
DLSYM_ARG(OSSL_STORE_INFO_get1_CERT),
|
||||
DLSYM_ARG(OSSL_STORE_INFO_get1_PKEY),
|
||||
DLSYM_ARG(OSSL_STORE_close),
|
||||
DLSYM_ARG(OSSL_STORE_expect),
|
||||
DLSYM_ARG(OSSL_STORE_load),
|
||||
DLSYM_ARG(OSSL_STORE_open),
|
||||
DLSYM_ARG(PEM_read_PUBKEY),
|
||||
DLSYM_ARG(PEM_read_PrivateKey),
|
||||
DLSYM_ARG(PEM_read_X509),
|
||||
DLSYM_ARG(PEM_read_bio_PrivateKey),
|
||||
DLSYM_ARG(PEM_read_bio_X509),
|
||||
DLSYM_ARG(PEM_read_PrivateKey),
|
||||
DLSYM_ARG(PEM_read_PUBKEY),
|
||||
DLSYM_ARG(PEM_read_X509),
|
||||
DLSYM_ARG(PEM_write_PrivateKey),
|
||||
DLSYM_ARG(PEM_write_PUBKEY),
|
||||
DLSYM_ARG(PEM_write_PrivateKey),
|
||||
DLSYM_ARG(PEM_write_X509),
|
||||
DLSYM_ARG(PKCS5_PBKDF2_HMAC),
|
||||
DLSYM_ARG(PKCS7_ATTR_SIGN_it),
|
||||
DLSYM_ARG(PKCS7_SIGNER_INFO_free),
|
||||
DLSYM_ARG(PKCS7_SIGNER_INFO_new),
|
||||
DLSYM_ARG(PKCS7_SIGNER_INFO_set),
|
||||
DLSYM_ARG(PKCS7_add0_attrib_signing_time),
|
||||
DLSYM_ARG(PKCS7_add1_attrib_digest),
|
||||
DLSYM_ARG(PKCS7_add_attrib_content_type),
|
||||
DLSYM_ARG(PKCS7_add_attrib_smimecap),
|
||||
DLSYM_ARG(PKCS7_add_certificate),
|
||||
DLSYM_ARG(PKCS7_add_signed_attribute),
|
||||
DLSYM_ARG(PKCS7_add_signer),
|
||||
DLSYM_ARG(PKCS7_add0_attrib_signing_time),
|
||||
DLSYM_ARG(PKCS7_add1_attrib_digest),
|
||||
DLSYM_ARG(PKCS7_ATTR_SIGN_it),
|
||||
DLSYM_ARG(PKCS7_content_new),
|
||||
DLSYM_ARG(PKCS7_ctrl),
|
||||
DLSYM_ARG(PKCS7_dataFinal),
|
||||
@@ -582,43 +590,76 @@ int dlopen_libcrypto(int log_level) {
|
||||
DLSYM_ARG(PKCS7_set_content),
|
||||
DLSYM_ARG(PKCS7_set_type),
|
||||
DLSYM_ARG(PKCS7_sign),
|
||||
DLSYM_ARG(PKCS7_SIGNER_INFO_free),
|
||||
DLSYM_ARG(PKCS7_SIGNER_INFO_new),
|
||||
DLSYM_ARG(PKCS7_SIGNER_INFO_set),
|
||||
DLSYM_ARG(PKCS7_verify),
|
||||
DLSYM_ARG(SHA1),
|
||||
DLSYM_ARG(SHA512),
|
||||
#ifndef OPENSSL_NO_UI_CONSOLE
|
||||
DLSYM_ARG(UI_create_method),
|
||||
DLSYM_ARG(UI_destroy_method),
|
||||
DLSYM_ARG(UI_get_default_method),
|
||||
DLSYM_ARG(UI_get_method),
|
||||
DLSYM_ARG(UI_get_string_type),
|
||||
DLSYM_ARG(UI_get0_output_string),
|
||||
DLSYM_ARG(UI_method_get_ex_data),
|
||||
DLSYM_ARG(UI_method_get_reader),
|
||||
DLSYM_ARG(UI_method_set_ex_data),
|
||||
DLSYM_ARG(UI_method_set_reader),
|
||||
DLSYM_ARG(UI_OpenSSL),
|
||||
DLSYM_ARG(UI_set_default_method),
|
||||
DLSYM_ARG(UI_set_result),
|
||||
#endif
|
||||
DLSYM_ARG(X509_ALGOR_free),
|
||||
DLSYM_ARG(X509_ALGOR_set0),
|
||||
DLSYM_ARG(X509_ATTRIBUTE_free),
|
||||
DLSYM_ARG(X509_NAME_free),
|
||||
DLSYM_ARG(X509_NAME_oneline),
|
||||
DLSYM_ARG(X509_NAME_set),
|
||||
DLSYM_ARG(X509_VERIFY_PARAM_set1_host),
|
||||
DLSYM_ARG(X509_VERIFY_PARAM_set1_ip),
|
||||
DLSYM_ARG(X509_VERIFY_PARAM_set_hostflags),
|
||||
DLSYM_ARG(X509_free),
|
||||
DLSYM_ARG(X509_get0_serialNumber),
|
||||
DLSYM_ARG(X509_get_issuer_name),
|
||||
DLSYM_ARG(X509_get_pubkey),
|
||||
DLSYM_ARG(X509_get_signature_info),
|
||||
DLSYM_ARG(X509_get_subject_name),
|
||||
DLSYM_ARG(X509_get0_serialNumber),
|
||||
DLSYM_ARG(X509_gmtime_adj),
|
||||
DLSYM_ARG(X509_NAME_free),
|
||||
DLSYM_ARG(X509_NAME_oneline),
|
||||
DLSYM_ARG(X509_NAME_set),
|
||||
DLSYM_ARG(X509_VERIFY_PARAM_set_hostflags),
|
||||
DLSYM_ARG(X509_VERIFY_PARAM_set1_host),
|
||||
DLSYM_ARG(X509_VERIFY_PARAM_set1_ip));
|
||||
DLSYM_ARG(d2i_ASN1_OCTET_STRING),
|
||||
DLSYM_ARG(d2i_ECPKParameters),
|
||||
DLSYM_ARG(d2i_PKCS7),
|
||||
DLSYM_ARG(d2i_PUBKEY),
|
||||
DLSYM_ARG(d2i_X509),
|
||||
DLSYM_ARG(i2d_ASN1_INTEGER),
|
||||
DLSYM_ARG(i2d_PKCS7),
|
||||
DLSYM_ARG(i2d_PKCS7_fp),
|
||||
DLSYM_ARG(i2d_PUBKEY),
|
||||
DLSYM_ARG(i2d_PUBKEY_fp),
|
||||
DLSYM_ARG(i2d_PublicKey),
|
||||
DLSYM_ARG(i2d_X509),
|
||||
DLSYM_ARG(i2d_X509_NAME),
|
||||
#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||
DLSYM_ARG_FORCE(ENGINE_by_id),
|
||||
DLSYM_ARG_FORCE(ENGINE_free),
|
||||
DLSYM_ARG_FORCE(ENGINE_init),
|
||||
DLSYM_ARG_FORCE(ENGINE_load_private_key),
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||
DLSYM_ARG_FORCE(ECDSA_SIG_new),
|
||||
DLSYM_ARG_FORCE(ECDSA_SIG_set0),
|
||||
DLSYM_ARG_FORCE(ECDSA_do_verify),
|
||||
DLSYM_ARG_FORCE(EC_KEY_check_key),
|
||||
DLSYM_ARG_FORCE(EC_KEY_free),
|
||||
DLSYM_ARG_FORCE(EC_KEY_new),
|
||||
DLSYM_ARG_FORCE(EC_KEY_set_group),
|
||||
DLSYM_ARG_FORCE(EC_KEY_set_public_key),
|
||||
DLSYM_ARG_FORCE(EVP_PKEY_assign),
|
||||
DLSYM_ARG_FORCE(RSAPublicKey_dup),
|
||||
DLSYM_ARG_FORCE(RSA_free),
|
||||
DLSYM_ARG_FORCE(RSA_new),
|
||||
DLSYM_ARG_FORCE(RSA_set0_key),
|
||||
DLSYM_ARG_FORCE(RSA_size),
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_UI_CONSOLE
|
||||
DLSYM_ARG(UI_OpenSSL),
|
||||
DLSYM_ARG(UI_create_method),
|
||||
DLSYM_ARG(UI_destroy_method),
|
||||
DLSYM_ARG(UI_get0_output_string),
|
||||
DLSYM_ARG(UI_get_default_method),
|
||||
DLSYM_ARG(UI_get_method),
|
||||
DLSYM_ARG(UI_get_string_type),
|
||||
DLSYM_ARG(UI_method_get_ex_data),
|
||||
DLSYM_ARG(UI_method_get_reader),
|
||||
DLSYM_ARG(UI_method_set_ex_data),
|
||||
DLSYM_ARG(UI_method_set_reader),
|
||||
DLSYM_ARG(UI_set_default_method),
|
||||
DLSYM_ARG(UI_set_result),
|
||||
#endif
|
||||
NULL);
|
||||
if (r >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
+82
-47
@@ -47,6 +47,7 @@ int dlopen_libcrypto(int log_level);
|
||||
|
||||
# include <openssl/bio.h> /* IWYU pragma: export */
|
||||
# include <openssl/bn.h> /* IWYU pragma: export */
|
||||
# include <openssl/core_names.h> /* IWYU pragma: export */
|
||||
# include <openssl/crypto.h> /* IWYU pragma: export */
|
||||
# include <openssl/ec.h> /* IWYU pragma: export */
|
||||
# include <openssl/err.h> /* IWYU pragma: export */
|
||||
@@ -64,12 +65,7 @@ extern DLSYM_PROTOTYPE(ASN1_ANY_it);
|
||||
extern DLSYM_PROTOTYPE(ASN1_BIT_STRING_it);
|
||||
extern DLSYM_PROTOTYPE(ASN1_BMPSTRING_it);
|
||||
extern DLSYM_PROTOTYPE(ASN1_BMPSTRING_new);
|
||||
extern DLSYM_PROTOTYPE(ASN1_get_object);
|
||||
extern DLSYM_PROTOTYPE(ASN1_IA5STRING_it);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_d2i);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_free);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_i2d);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_new);
|
||||
extern DLSYM_PROTOTYPE(ASN1_OBJECT_it);
|
||||
extern DLSYM_PROTOTYPE(ASN1_OCTET_STRING_free);
|
||||
extern DLSYM_PROTOTYPE(ASN1_OCTET_STRING_it);
|
||||
@@ -82,46 +78,65 @@ extern DLSYM_PROTOTYPE(ASN1_STRING_set0);
|
||||
extern DLSYM_PROTOTYPE(ASN1_TIME_free);
|
||||
extern DLSYM_PROTOTYPE(ASN1_TIME_set);
|
||||
extern DLSYM_PROTOTYPE(ASN1_TYPE_new);
|
||||
extern DLSYM_PROTOTYPE(ASN1_get_object);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_d2i);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_free);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_i2d);
|
||||
extern DLSYM_PROTOTYPE(ASN1_item_new);
|
||||
extern DLSYM_PROTOTYPE(BIO_ctrl);
|
||||
extern DLSYM_PROTOTYPE(BIO_find_type);
|
||||
extern DLSYM_PROTOTYPE(BIO_free_all);
|
||||
extern DLSYM_PROTOTYPE(BIO_free);
|
||||
extern DLSYM_PROTOTYPE(BIO_free_all);
|
||||
extern DLSYM_PROTOTYPE(BIO_new);
|
||||
extern DLSYM_PROTOTYPE(BIO_new_mem_buf);
|
||||
extern DLSYM_PROTOTYPE(BIO_new_socket);
|
||||
extern DLSYM_PROTOTYPE(BIO_new);
|
||||
extern DLSYM_PROTOTYPE(BIO_s_mem);
|
||||
extern DLSYM_PROTOTYPE(BIO_write);
|
||||
extern DLSYM_PROTOTYPE(BN_bin2bn);
|
||||
extern DLSYM_PROTOTYPE(BN_bn2nativepad);
|
||||
extern DLSYM_PROTOTYPE(BN_CTX_free);
|
||||
extern DLSYM_PROTOTYPE(BN_CTX_new);
|
||||
extern DLSYM_PROTOTYPE(BN_CTX_secure_new);
|
||||
extern DLSYM_PROTOTYPE(BN_add);
|
||||
extern DLSYM_PROTOTYPE(BN_add_word);
|
||||
extern DLSYM_PROTOTYPE(BN_bin2bn);
|
||||
extern DLSYM_PROTOTYPE(BN_bn2bin);
|
||||
extern DLSYM_PROTOTYPE(BN_bn2binpad);
|
||||
extern DLSYM_PROTOTYPE(BN_bn2nativepad);
|
||||
extern DLSYM_PROTOTYPE(BN_check_prime);
|
||||
extern DLSYM_PROTOTYPE(BN_clear_free);
|
||||
extern DLSYM_PROTOTYPE(BN_cmp);
|
||||
extern DLSYM_PROTOTYPE(BN_copy);
|
||||
extern DLSYM_PROTOTYPE(BN_free);
|
||||
extern DLSYM_PROTOTYPE(BN_is_negative);
|
||||
extern DLSYM_PROTOTYPE(BN_mod_exp);
|
||||
extern DLSYM_PROTOTYPE(BN_mod_inverse);
|
||||
extern DLSYM_PROTOTYPE(BN_mod_lshift1_quick);
|
||||
extern DLSYM_PROTOTYPE(BN_mod_mul);
|
||||
extern DLSYM_PROTOTYPE(BN_mod_sqr);
|
||||
extern DLSYM_PROTOTYPE(BN_mod_sub);
|
||||
extern DLSYM_PROTOTYPE(BN_mul);
|
||||
extern DLSYM_PROTOTYPE(BN_new);
|
||||
extern DLSYM_PROTOTYPE(BN_nnmod);
|
||||
extern DLSYM_PROTOTYPE(BN_num_bits);
|
||||
extern DLSYM_PROTOTYPE(BN_secure_new);
|
||||
extern DLSYM_PROTOTYPE(BN_set_word);
|
||||
extern DLSYM_PROTOTYPE(BN_sub_word);
|
||||
extern DLSYM_PROTOTYPE(CRYPTO_free);
|
||||
extern DLSYM_PROTOTYPE(d2i_ASN1_OCTET_STRING);
|
||||
extern DLSYM_PROTOTYPE(d2i_ECPKParameters);
|
||||
extern DLSYM_PROTOTYPE(d2i_PKCS7);
|
||||
extern DLSYM_PROTOTYPE(d2i_PUBKEY);
|
||||
extern DLSYM_PROTOTYPE(d2i_X509);
|
||||
extern DLSYM_PROTOTYPE(ECDSA_SIG_free);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_free);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get_curve_name);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get_curve);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get_field_type);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get0_generator);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get0_order);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get_curve);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get_curve_name);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_get_field_type);
|
||||
extern DLSYM_PROTOTYPE(EC_GROUP_new_by_curve_name);
|
||||
extern DLSYM_PROTOTYPE(EC_POINT_free);
|
||||
extern DLSYM_PROTOTYPE(EC_POINT_new);
|
||||
extern DLSYM_PROTOTYPE(EC_POINT_oct2point);
|
||||
extern DLSYM_PROTOTYPE(EC_POINT_point2oct);
|
||||
extern DLSYM_PROTOTYPE(ECDSA_SIG_free);
|
||||
extern DLSYM_PROTOTYPE(ERR_clear_error);
|
||||
extern DLSYM_PROTOTYPE(ERR_error_string_n);
|
||||
extern DLSYM_PROTOTYPE(ERR_error_string);
|
||||
extern DLSYM_PROTOTYPE(ERR_error_string_n);
|
||||
extern DLSYM_PROTOTYPE(ERR_get_error);
|
||||
extern DLSYM_PROTOTYPE(EVP_aes_256_ctr);
|
||||
extern DLSYM_PROTOTYPE(EVP_aes_256_gcm);
|
||||
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_ctrl);
|
||||
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_new);
|
||||
@@ -141,46 +156,48 @@ extern DLSYM_PROTOTYPE(EVP_DigestVerifyInit);
|
||||
extern DLSYM_PROTOTYPE(EVP_EncryptFinal_ex);
|
||||
extern DLSYM_PROTOTYPE(EVP_EncryptInit_ex);
|
||||
extern DLSYM_PROTOTYPE(EVP_EncryptUpdate);
|
||||
extern DLSYM_PROTOTYPE(EVP_get_cipherbyname);
|
||||
extern DLSYM_PROTOTYPE(EVP_get_digestbyname);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_CTX_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_CTX_new);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_fetch);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_final);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_MAC_update);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_CTX_copy_ex);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_CTX_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_CTX_get0_md);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_CTX_new);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_CTX_set_pkey_ctx);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_get_size);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_get0_name);
|
||||
extern DLSYM_PROTOTYPE(EVP_MD_get_size);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new_from_name);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new_id);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_rsa_padding);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_signature_md);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_eq);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_free);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_fromdata_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_fromdata);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_fromdata_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_get_base_id);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_get_id);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_keygen_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_keygen);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_new_raw_public_key);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_keygen_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_new);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_verify_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_new_raw_public_key);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_verify);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_verify_init);
|
||||
extern DLSYM_PROTOTYPE(EVP_aes_256_ctr);
|
||||
extern DLSYM_PROTOTYPE(EVP_aes_256_gcm);
|
||||
extern DLSYM_PROTOTYPE(EVP_get_cipherbyname);
|
||||
extern DLSYM_PROTOTYPE(EVP_get_digestbyname);
|
||||
extern DLSYM_PROTOTYPE(EVP_sha1);
|
||||
extern DLSYM_PROTOTYPE(EVP_sha256);
|
||||
extern DLSYM_PROTOTYPE(EVP_sha384);
|
||||
extern DLSYM_PROTOTYPE(EVP_sha512);
|
||||
extern DLSYM_PROTOTYPE(HMAC);
|
||||
extern DLSYM_PROTOTYPE(i2d_ASN1_INTEGER);
|
||||
extern DLSYM_PROTOTYPE(i2d_PKCS7_fp);
|
||||
extern DLSYM_PROTOTYPE(i2d_PKCS7);
|
||||
extern DLSYM_PROTOTYPE(i2d_PUBKEY);
|
||||
extern DLSYM_PROTOTYPE(i2d_X509_NAME);
|
||||
extern DLSYM_PROTOTYPE(i2d_X509);
|
||||
extern DLSYM_PROTOTYPE(OBJ_nid2obj);
|
||||
extern DLSYM_PROTOTYPE(OBJ_nid2sn);
|
||||
extern DLSYM_PROTOTYPE(OBJ_sn2nid);
|
||||
@@ -191,24 +208,29 @@ extern DLSYM_PROTOTYPE(OPENSSL_sk_pop_free);
|
||||
extern DLSYM_PROTOTYPE(OPENSSL_sk_push);
|
||||
extern DLSYM_PROTOTYPE(OPENSSL_sk_value);
|
||||
extern DLSYM_PROTOTYPE(OSSL_EC_curve_nid2name);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_BLD_free);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_BLD_new);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_BLD_push_utf8_string);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_BLD_to_param);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_BN);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_end);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_octet_string);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_utf8_string);
|
||||
extern DLSYM_PROTOTYPE(OSSL_PARAM_free);
|
||||
extern DLSYM_PROTOTYPE(PEM_read_PrivateKey);
|
||||
extern DLSYM_PROTOTYPE(PEM_read_PUBKEY);
|
||||
extern DLSYM_PROTOTYPE(PEM_read_PrivateKey);
|
||||
extern DLSYM_PROTOTYPE(PEM_read_X509);
|
||||
extern DLSYM_PROTOTYPE(PEM_write_PrivateKey);
|
||||
extern DLSYM_PROTOTYPE(PEM_write_PUBKEY);
|
||||
extern DLSYM_PROTOTYPE(PEM_write_PrivateKey);
|
||||
extern DLSYM_PROTOTYPE(PEM_write_X509);
|
||||
extern DLSYM_PROTOTYPE(PKCS5_PBKDF2_HMAC);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_ATTR_SIGN_it);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_free);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add0_attrib_signing_time);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add1_attrib_digest);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add_attrib_content_type);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add_attrib_smimecap);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add_signed_attribute);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add0_attrib_signing_time);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_add1_attrib_digest);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_ATTR_SIGN_it);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_content_new);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_ctrl);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_dataFinal);
|
||||
@@ -218,21 +240,31 @@ extern DLSYM_PROTOTYPE(PKCS7_get_signer_info);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_new);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_set_content);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_sign);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_free);
|
||||
extern DLSYM_PROTOTYPE(PKCS7_verify);
|
||||
extern DLSYM_PROTOTYPE(SHA1);
|
||||
extern DLSYM_PROTOTYPE(SHA512);
|
||||
extern DLSYM_PROTOTYPE(X509_ALGOR_free);
|
||||
extern DLSYM_PROTOTYPE(X509_ATTRIBUTE_free);
|
||||
extern DLSYM_PROTOTYPE(X509_NAME_free);
|
||||
extern DLSYM_PROTOTYPE(X509_NAME_oneline);
|
||||
extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_host);
|
||||
extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_ip);
|
||||
extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set_hostflags);
|
||||
extern DLSYM_PROTOTYPE(X509_free);
|
||||
extern DLSYM_PROTOTYPE(X509_get_pubkey);
|
||||
extern DLSYM_PROTOTYPE(X509_get_subject_name);
|
||||
extern DLSYM_PROTOTYPE(X509_gmtime_adj);
|
||||
extern DLSYM_PROTOTYPE(X509_NAME_free);
|
||||
extern DLSYM_PROTOTYPE(X509_NAME_oneline);
|
||||
extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set_hostflags);
|
||||
extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_host);
|
||||
extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_ip);
|
||||
extern DLSYM_PROTOTYPE(d2i_ASN1_OCTET_STRING);
|
||||
extern DLSYM_PROTOTYPE(d2i_ECPKParameters);
|
||||
extern DLSYM_PROTOTYPE(d2i_PKCS7);
|
||||
extern DLSYM_PROTOTYPE(d2i_PUBKEY);
|
||||
extern DLSYM_PROTOTYPE(d2i_X509);
|
||||
extern DLSYM_PROTOTYPE(i2d_ASN1_INTEGER);
|
||||
extern DLSYM_PROTOTYPE(i2d_PKCS7);
|
||||
extern DLSYM_PROTOTYPE(i2d_PKCS7_fp);
|
||||
extern DLSYM_PROTOTYPE(i2d_PUBKEY);
|
||||
extern DLSYM_PROTOTYPE(i2d_X509);
|
||||
extern DLSYM_PROTOTYPE(i2d_X509_NAME);
|
||||
|
||||
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||
DISABLE_WARNING_DEPRECATED_DECLARATIONS;
|
||||
@@ -245,11 +277,11 @@ extern DLSYM_PROTOTYPE(EC_KEY_new);
|
||||
extern DLSYM_PROTOTYPE(EC_KEY_set_group);
|
||||
extern DLSYM_PROTOTYPE(EC_KEY_set_public_key);
|
||||
extern DLSYM_PROTOTYPE(EVP_PKEY_assign);
|
||||
extern DLSYM_PROTOTYPE(RSAPublicKey_dup);
|
||||
extern DLSYM_PROTOTYPE(RSA_free);
|
||||
extern DLSYM_PROTOTYPE(RSA_new);
|
||||
extern DLSYM_PROTOTYPE(RSA_set0_key);
|
||||
extern DLSYM_PROTOTYPE(RSA_size);
|
||||
extern DLSYM_PROTOTYPE(RSAPublicKey_dup);
|
||||
REENABLE_WARNING;
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EC_KEY*, sym_EC_KEY_free, EC_KEY_freep, NULL);
|
||||
@@ -262,6 +294,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(RSA*, sym_RSA_free, RSA_freep, NULL);
|
||||
#define sym_BIO_get_mem_ptr(b, pp) sym_BIO_ctrl((b), BIO_C_GET_BUF_MEM_PTR, 0, (char *) (pp))
|
||||
#define sym_BIO_reset(b) sym_BIO_ctrl((b), BIO_CTRL_RESET, 0, NULL)
|
||||
#define sym_BN_num_bytes(a) ((sym_BN_num_bits(a) + 7) / 8)
|
||||
#define sym_BN_one(a) sym_BN_set_word(a, 1)
|
||||
#define sym_EVP_MD_CTX_get_size(ctx) sym_EVP_MD_get_size(sym_EVP_MD_CTX_get0_md(ctx))
|
||||
#define sym_EVP_MD_CTX_get0_name(ctx) sym_EVP_MD_get0_name(sym_EVP_MD_CTX_get0_md(ctx))
|
||||
#define sym_EVP_PKEY_assign_RSA(pkey, rsa) sym_EVP_PKEY_assign((pkey), EVP_PKEY_RSA, (rsa))
|
||||
@@ -272,6 +305,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO_RENAME(void*, sym_OPENSSL_free, OPENSSL_f
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(ASN1_OCTET_STRING*, sym_ASN1_OCTET_STRING_free, ASN1_OCTET_STRING_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(ASN1_TIME*, sym_ASN1_TIME_free, ASN1_TIME_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIGNUM*, sym_BN_free, BN_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIGNUM*, sym_BN_clear_free, BN_clear_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIO*, sym_BIO_free_all, BIO_free_allp, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIO*, sym_BIO_free, BIO_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BN_CTX*, sym_BN_CTX_free, BN_CTX_freep, NULL);
|
||||
@@ -286,6 +320,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_MD_CTX*, sym_EVP_MD_CTX_free, EVP_MD
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_MD*, sym_EVP_MD_free, EVP_MD_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_PKEY_CTX*, sym_EVP_PKEY_CTX_free, EVP_PKEY_CTX_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_PKEY*, sym_EVP_PKEY_free, EVP_PKEY_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_PARAM_BLD*, sym_OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_PARAM*, sym_OSSL_PARAM_free, OSSL_PARAM_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(PKCS7_SIGNER_INFO*, sym_PKCS7_SIGNER_INFO_free, PKCS7_SIGNER_INFO_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(PKCS7*, sym_PKCS7_free, PKCS7_freep, NULL);
|
||||
|
||||
@@ -0,0 +1,668 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
/*
|
||||
* This is based on
|
||||
* fsprg v0.1 - (seekable) forward-secure pseudorandom generator
|
||||
* Copyright © 2012 B. Poettering
|
||||
* Contact: fsprg@point-at-infinity.org
|
||||
*
|
||||
* OpenSSL port of the original libgcrypt-based implementation.
|
||||
*
|
||||
* See "Practical Secure Logging: Seekable Sequential Key Generators"
|
||||
* by G. A. Marson, B. Poettering for details:
|
||||
*
|
||||
* http://eprint.iacr.org/2013/397
|
||||
*/
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#include "alloc-util.h" /* IWYU pragma: keep */
|
||||
#include "crypto-util.h"
|
||||
#include "fsprg-openssl.h"
|
||||
#include "iovec-util.h"
|
||||
#include "logarithm.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
#define RND_GEN_P 0x01
|
||||
#define RND_GEN_Q 0x02
|
||||
#define RND_GEN_X 0x03
|
||||
|
||||
/* Suppress a false positive from GCC's -Wstringop-overflow warning. Keep a local helper so the compiler can
|
||||
* propagate the range check within this translation unit. */
|
||||
static bool secpar_is_valid(uint16_t secpar) {
|
||||
return
|
||||
secpar % 16 == 0 &&
|
||||
secpar >= 16 &&
|
||||
secpar <= 16384;
|
||||
}
|
||||
|
||||
bool fsprg_secpar_is_valid(uint16_t secpar) {
|
||||
return secpar_is_valid(secpar);
|
||||
}
|
||||
|
||||
size_t fsprg_state_size(uint16_t secpar) {
|
||||
assert(secpar_is_valid(secpar));
|
||||
|
||||
/* See comment in parse_state(). */
|
||||
return sizeof(uint16_t) + 2 * secpar / 8 + sizeof(uint64_t);
|
||||
}
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
static int mpi_export(struct iovec *iov, const BIGNUM *x) {
|
||||
assert(iovec_is_set(iov));
|
||||
assert(x);
|
||||
|
||||
if (sym_BN_is_negative(x))
|
||||
return -EINVAL;
|
||||
|
||||
if (sym_BN_num_bytes(x) > (int) iov->iov_len)
|
||||
return -ENOSPC;
|
||||
|
||||
if (sym_BN_bn2binpad(x, iov->iov_base, iov->iov_len) != (int) iov->iov_len)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpi_import(const struct iovec *iov, BIGNUM **ret) {
|
||||
assert(iovec_is_set(iov));
|
||||
assert(ret);
|
||||
|
||||
/* Allocate a new BIGNUM. */
|
||||
_cleanup_(BN_clear_freep) BIGNUM *x = sym_BN_secure_new();
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!sym_BN_bin2bn(iov->iov_base, iov->iov_len, x))
|
||||
return -EIO;
|
||||
|
||||
*ret = TAKE_PTR(x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int det_randomize(const struct iovec *seed, uint32_t idx, struct iovec *iov) {
|
||||
assert(iovec_is_set(seed));
|
||||
assert(iovec_is_valid(iov));
|
||||
|
||||
/* Expand (seed, idx) into a deterministic pseudorandom byte stream. */
|
||||
|
||||
if (!iovec_is_set(iov))
|
||||
return 0;
|
||||
|
||||
_cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = sym_EVP_MD_CTX_new();
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
if (sym_EVP_DigestInit_ex(ctx, sym_EVP_sha256(), NULL) <= 0)
|
||||
return -EIO;
|
||||
|
||||
if (sym_EVP_DigestUpdate(ctx, seed->iov_base, seed->iov_len) <= 0)
|
||||
return -EIO;
|
||||
|
||||
if (sym_EVP_DigestUpdate(ctx, (be32_t[]) { htobe32(idx) }, sizeof(be32_t)) <= 0)
|
||||
return -EIO;
|
||||
|
||||
struct iovec v = *iov;
|
||||
for (uint32_t ctr = 0; iovec_is_set(&v); ctr++) {
|
||||
_cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *tmp = sym_EVP_MD_CTX_new();
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
if (sym_EVP_MD_CTX_copy_ex(tmp, ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
if (sym_EVP_DigestUpdate(tmp, (be32_t[]) { htobe32(ctr) }, sizeof(be32_t)) <= 0)
|
||||
return -EIO;
|
||||
|
||||
unsigned dlen;
|
||||
uint8_t digest[EVP_MAX_MD_SIZE];
|
||||
CLEANUP_ERASE(digest);
|
||||
|
||||
if (sym_EVP_DigestFinal_ex(tmp, digest, &dlen) <= 0)
|
||||
return -EIO;
|
||||
|
||||
size_t n = MIN(v.iov_len, dlen);
|
||||
memcpy(v.iov_base, digest, n);
|
||||
iovec_inc(&v, n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* deterministically generate from seed/idx a prime of length (secpar / 2) bits that is 3 mod 4 */
|
||||
static int generate_prime3mod4(
|
||||
uint16_t secpar,
|
||||
const struct iovec *seed,
|
||||
uint32_t idx,
|
||||
BN_CTX *bn_ctx,
|
||||
BIGNUM **ret) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(seed));
|
||||
assert(bn_ctx);
|
||||
assert(ret);
|
||||
|
||||
if (!secpar_is_valid(secpar))
|
||||
return -EINVAL;
|
||||
|
||||
_cleanup_(iovec_erase) struct iovec iov = IOVEC_ALLOCA(secpar / 2 / 8);
|
||||
r = det_randomize(seed, idx, &iov);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint8_t *buf = iov.iov_base;
|
||||
|
||||
/* Set the upper two bits so that n = pq has the maximum size. */
|
||||
buf[0] |= 0xc0;
|
||||
|
||||
/* Make the candidate congruent to 3 (mod 4). */
|
||||
buf[iov.iov_len - 1] |= 0x03;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *p = NULL;
|
||||
r = mpi_import(&iov, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
/* negative: error, 0: composite, 1: prime */
|
||||
r = sym_BN_check_prime(p, bn_ctx, /* cb= */ NULL);
|
||||
if (r < 0)
|
||||
return -EIO;
|
||||
if (r > 0)
|
||||
break;
|
||||
|
||||
/* Increment p by 4. */
|
||||
if (sym_BN_add_word(p, 4) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* Check if p is still (secpar / 2) bits. */
|
||||
if (sym_BN_num_bits(p) != secpar / 2)
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generate_keys(
|
||||
uint16_t secpar,
|
||||
const struct iovec *seed,
|
||||
BN_CTX *bn_ctx,
|
||||
BIGNUM **ret_p, /* prime */
|
||||
BIGNUM **ret_q, /* prime */
|
||||
BIGNUM **ret_n) { /* n = p * q */
|
||||
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(seed));
|
||||
assert(bn_ctx);
|
||||
assert(ret_p);
|
||||
assert(ret_q);
|
||||
assert(ret_n);
|
||||
|
||||
if (!secpar_is_valid(secpar))
|
||||
return -EINVAL;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *p = NULL;
|
||||
r = generate_prime3mod4(secpar, seed, RND_GEN_P, bn_ctx, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *q = NULL;
|
||||
r = generate_prime3mod4(secpar, seed, RND_GEN_Q, bn_ctx, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *n = sym_BN_secure_new();
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
if (sym_BN_mul(n, p, q, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
if (sym_BN_num_bits(n) != secpar)
|
||||
return -EIO;
|
||||
|
||||
*ret_p = TAKE_PTR(p);
|
||||
*ret_q = TAKE_PTR(q);
|
||||
*ret_n = TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* deterministically generate from seed/idx a quadratic residue (mod n) */
|
||||
static int generate_square(
|
||||
uint16_t secpar,
|
||||
const struct iovec *seed,
|
||||
uint32_t idx,
|
||||
const BIGNUM *n,
|
||||
BN_CTX *bn_ctx,
|
||||
BIGNUM **ret) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(seed));
|
||||
assert(n);
|
||||
assert(bn_ctx);
|
||||
assert(ret);
|
||||
|
||||
if (!secpar_is_valid(secpar))
|
||||
return -EINVAL;
|
||||
|
||||
_cleanup_(iovec_erase) struct iovec iov = IOVEC_ALLOCA(secpar / 8);
|
||||
r = det_randomize(seed, idx, &iov);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*(uint8_t*) iov.iov_base &= 0x7f; /* Clear the upper bit so that we are likely to have x < n. */
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *x = NULL;
|
||||
r = mpi_import(&iov, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* x < n should always hold for a valid modulus generated by generate_keys(). */
|
||||
if (sym_BN_cmp(x, n) >= 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* x := x^2 mod n */
|
||||
if (sym_BN_mod_sqr(x, x, n, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
*ret = TAKE_PTR(x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute 2^m mod phi(p), where p is prime and phi(p) = p - 1. */
|
||||
static int compute_two_pow_mod_phi(
|
||||
uint64_t m,
|
||||
const BIGNUM *p,
|
||||
BN_CTX *bn_ctx,
|
||||
BIGNUM **ret) {
|
||||
|
||||
assert(p);
|
||||
assert(bn_ctx);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *phi = sym_BN_secure_new();
|
||||
if (!phi)
|
||||
return -ENOMEM;
|
||||
|
||||
/* phi := p */
|
||||
if (!sym_BN_copy(phi, p))
|
||||
return -EIO;
|
||||
|
||||
/* phi := p - 1 */
|
||||
if (sym_BN_sub_word(phi, 1) <= 0)
|
||||
return -EIO;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *x = sym_BN_secure_new();
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
/* x := 1 */
|
||||
if (!sym_BN_one(x))
|
||||
return -EIO;
|
||||
|
||||
if (m == 0) {
|
||||
/* 2^0 mod phi = 1. */
|
||||
*ret = TAKE_PTR(x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Square-and-multiply. Iterate over the bits of m from MSB to LSB. */
|
||||
for (int n = LOG2ULL(m); n >= 0; n--) {
|
||||
if (sym_BN_mod_sqr(x, x, phi, bn_ctx) <= 0) /* x := x^2 mod phi */
|
||||
return -EIO;
|
||||
|
||||
if (m & (UINT64_C(1) << n) &&
|
||||
sym_BN_mod_lshift1_quick(x, x, phi) <= 0) /* x := 2x mod phi */
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decompose x ∈ Z_n into (xp, xq) ∈ Z_p × Z_q using the Chinese Remainder Theorem. */
|
||||
static int crt_decompose(
|
||||
const BIGNUM *x,
|
||||
const BIGNUM *p,
|
||||
const BIGNUM *q,
|
||||
BN_CTX *bn_ctx,
|
||||
BIGNUM **ret_xp,
|
||||
BIGNUM **ret_xq) {
|
||||
|
||||
assert(x);
|
||||
assert(p);
|
||||
assert(q);
|
||||
assert(bn_ctx);
|
||||
assert(ret_xp);
|
||||
assert(ret_xq);
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *xp = sym_BN_secure_new();
|
||||
if (!xp)
|
||||
return -ENOMEM;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *xq = sym_BN_secure_new();
|
||||
if (!xq)
|
||||
return -ENOMEM;
|
||||
|
||||
if (sym_BN_nnmod(xp, x, p, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
if (sym_BN_nnmod(xq, x, q, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
*ret_xp = TAKE_PTR(xp);
|
||||
*ret_xq = TAKE_PTR(xq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose (xp, xq) ∈ Z_p × Z_q into x ∈ Z_n using the Chinese Remainder Theorem. */
|
||||
static int crt_compose(
|
||||
const BIGNUM *xp,
|
||||
const BIGNUM *xq,
|
||||
const BIGNUM *p,
|
||||
const BIGNUM *q,
|
||||
BN_CTX *bn_ctx,
|
||||
BIGNUM **ret) {
|
||||
|
||||
assert(xp);
|
||||
assert(xq);
|
||||
assert(p);
|
||||
assert(q);
|
||||
assert(bn_ctx);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *x = sym_BN_secure_new();
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
/* x := xq - xp mod q */
|
||||
if (sym_BN_mod_sub(x, xq, xp, q, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* Compute p^-1 mod q. */
|
||||
_cleanup_(BN_clear_freep) BIGNUM *p_inv = sym_BN_secure_new();
|
||||
if (!p_inv)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!sym_BN_mod_inverse(p_inv, p, q, bn_ctx))
|
||||
return -EIO;
|
||||
|
||||
/* x := (xq - xp) * p^-1 mod q */
|
||||
if (sym_BN_mod_mul(x, x, p_inv, q, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* x := p * ((xq - xp) * p^-1 mod q) */
|
||||
if (sym_BN_mul(x, x, p, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* x := p * ((xq - xp) * p^-1 mod q) + xp */
|
||||
if (sym_BN_add(x, x, xp) <= 0)
|
||||
return -EIO;
|
||||
|
||||
*ret = TAKE_PTR(x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int save_state(
|
||||
uint16_t secpar,
|
||||
const BIGNUM *modulus,
|
||||
const BIGNUM *current,
|
||||
uint64_t epoch,
|
||||
struct iovec *state) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(modulus);
|
||||
assert(current);
|
||||
assert(iovec_is_set(state));
|
||||
|
||||
if (!secpar_is_valid(secpar))
|
||||
return -EINVAL;
|
||||
|
||||
if (state->iov_len != fsprg_state_size(secpar))
|
||||
return -EINVAL;
|
||||
|
||||
uint8_t *s = state->iov_base;
|
||||
|
||||
/* header */
|
||||
unaligned_write_be16(s, secpar / 16 - 1);
|
||||
s += sizeof(uint16_t);
|
||||
|
||||
/* modulus */
|
||||
r = mpi_export(&IOVEC_MAKE(s, secpar / 8), modulus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
s += secpar / 8;
|
||||
|
||||
/* current */
|
||||
r = mpi_export(&IOVEC_MAKE(s, secpar / 8), current);
|
||||
if (r < 0)
|
||||
return r;
|
||||
s += secpar / 8;
|
||||
|
||||
/* epoch */
|
||||
unaligned_write_be64(s, epoch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_state(
|
||||
const struct iovec *state,
|
||||
uint16_t *ret_secpar,
|
||||
BIGNUM **ret_modulus,
|
||||
BIGNUM **ret_current,
|
||||
uint64_t *ret_epoch) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(state));
|
||||
|
||||
/* The serialized state consists of:
|
||||
* - header: 2 bytes. Encodes secpar / 16 - 1, where 16 <= secpar <= 16384.
|
||||
* - modulus (a.k.a. n): secpar / 8 bytes.
|
||||
* - current (a.k.a. x): secpar / 8 bytes.
|
||||
* - epoch: 8 bytes. */
|
||||
|
||||
if (state->iov_len < sizeof(uint16_t))
|
||||
return -EBADMSG;
|
||||
|
||||
uint16_t header = unaligned_read_be16(state->iov_base);
|
||||
if (header >= 1024)
|
||||
return -EBADMSG;
|
||||
|
||||
uint16_t secpar = 16 * (header + 1);
|
||||
if (state->iov_len != fsprg_state_size(secpar))
|
||||
return -EBADMSG;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *modulus = NULL;
|
||||
if (ret_modulus) {
|
||||
r = mpi_import(&IOVEC_MAKE((uint8_t*) state->iov_base + sizeof(uint16_t), secpar / 8), &modulus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *current = NULL;
|
||||
if (ret_current) {
|
||||
r = mpi_import(&IOVEC_MAKE((uint8_t*) state->iov_base + sizeof(uint16_t) + secpar / 8, secpar / 8), ¤t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ret_secpar)
|
||||
*ret_secpar = secpar;
|
||||
if (ret_modulus)
|
||||
*ret_modulus = TAKE_PTR(modulus);
|
||||
if (ret_current)
|
||||
*ret_current = TAKE_PTR(current);
|
||||
if (ret_epoch)
|
||||
*ret_epoch = unaligned_read_be64((uint8_t*) state->iov_base + sizeof(uint16_t) + 2 * secpar / 8);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int fsprg_generate_state(
|
||||
uint16_t secpar,
|
||||
uint64_t epoch,
|
||||
const struct iovec *seed,
|
||||
struct iovec *state) {
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(seed));
|
||||
assert(iovec_is_set(state));
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!secpar_is_valid(secpar))
|
||||
return -EINVAL;
|
||||
|
||||
_cleanup_(BN_CTX_freep) BN_CTX *bn_ctx = sym_BN_CTX_secure_new();
|
||||
if (!bn_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *p = NULL, *q = NULL, *n = NULL;
|
||||
r = generate_keys(secpar, seed, bn_ctx, &p, &q, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(BN_clear_freep) BIGNUM *x = NULL;
|
||||
r = generate_square(secpar, seed, RND_GEN_X, n, bn_ctx, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (epoch != 0) {
|
||||
/* Decompose x from Z_n into Z_p × Z_q using CRT. */
|
||||
_cleanup_(BN_clear_freep) BIGNUM *xp = NULL, *xq = NULL;
|
||||
r = crt_decompose(x, p, q, bn_ctx, &xp, &xq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Compute 2^epoch (mod phi(p)). */
|
||||
_cleanup_(BN_clear_freep) BIGNUM *kp = NULL;
|
||||
r = compute_two_pow_mod_phi(epoch, p, bn_ctx, &kp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Compute 2^epoch (mod phi(q)). */
|
||||
_cleanup_(BN_clear_freep) BIGNUM *kq = NULL;
|
||||
r = compute_two_pow_mod_phi(epoch, q, bn_ctx, &kq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Compute x^(2^epoch) (mod p). */
|
||||
if (sym_BN_mod_exp(xp, xp, kp, p, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* Compute x^(2^epoch) (mod q). */
|
||||
if (sym_BN_mod_exp(xq, xq, kq, q, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* Reconstruct x modulo n from its residues modulo p and q. */
|
||||
BN_clear_freep(&x);
|
||||
r = crt_compose(xp, xq, p, q, bn_ctx, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return save_state(secpar, n, x, epoch, state);
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int fsprg_evolve(struct iovec *state) {
|
||||
#if HAVE_OPENSSL
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(state));
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint16_t secpar;
|
||||
uint64_t epoch;
|
||||
_cleanup_(BN_clear_freep) BIGNUM *n = NULL, *x = NULL;
|
||||
r = parse_state(state, &secpar, &n, &x, &epoch);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(BN_CTX_freep) BN_CTX *bn_ctx = sym_BN_CTX_secure_new();
|
||||
if (!bn_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Update the current state x := x^2 mod n */
|
||||
if (sym_BN_mod_sqr(x, x, n, bn_ctx) <= 0)
|
||||
return -EIO;
|
||||
|
||||
/* Store the updated current state. */
|
||||
uint8_t *s = (uint8_t*) state->iov_base + sizeof(uint16_t) + secpar / 8;
|
||||
r = mpi_export(&IOVEC_MAKE(s, secpar / 8), x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Increment epoch */
|
||||
unaligned_write_be64(s + secpar / 8, epoch + 1);
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int fsprg_get_epoch(const struct iovec *state, uint64_t *ret) {
|
||||
#if HAVE_OPENSSL
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(state));
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return parse_state(
|
||||
state,
|
||||
/* ret_secpar= */ NULL,
|
||||
/* ret_modulus= */ NULL,
|
||||
/* ret_current= */ NULL,
|
||||
ret);
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int fsprg_get_key(const struct iovec *state, struct iovec *key) {
|
||||
#if HAVE_OPENSSL
|
||||
int r;
|
||||
|
||||
assert(iovec_is_set(state));
|
||||
assert(iovec_is_valid(key));
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint16_t secpar;
|
||||
r = parse_state(state,
|
||||
/* ret_secpar= */ &secpar,
|
||||
/* ret_modulus= */ NULL,
|
||||
/* ret_current= */ NULL,
|
||||
/* ret_epoch= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
struct iovec seed = IOVEC_MAKE(
|
||||
(uint8_t*) state->iov_base + sizeof(uint16_t),
|
||||
2 * secpar / 8 + sizeof(uint64_t));
|
||||
|
||||
return det_randomize(&seed, /* idx= */ 0, key);
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-forward.h"
|
||||
|
||||
#define FSPRG_RECOMMENDED_SECPAR 1536
|
||||
#define FSPRG_RECOMMENDED_SEEDLEN (96/8)
|
||||
|
||||
bool fsprg_secpar_is_valid(uint16_t secpar);
|
||||
size_t fsprg_state_size(uint16_t secpar);
|
||||
int fsprg_generate_state(
|
||||
uint16_t secpar,
|
||||
uint64_t epoch,
|
||||
const struct iovec *seed,
|
||||
struct iovec *state);
|
||||
int fsprg_evolve(struct iovec *state);
|
||||
int fsprg_get_epoch(const struct iovec *state, uint64_t *ret);
|
||||
int fsprg_get_key(const struct iovec *state, struct iovec *key);
|
||||
@@ -0,0 +1,596 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "crypto-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fsprg-openssl.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-def.h"
|
||||
#include "journal-file.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
|
||||
struct JournalAuthContext {
|
||||
EVP_MAC *hmac;
|
||||
EVP_MAC_CTX *hmac_ctx;
|
||||
OSSL_PARAM *ossl_params;
|
||||
bool hmac_running;
|
||||
|
||||
FSSHeader *fss_file;
|
||||
size_t fss_mmap_size;
|
||||
|
||||
uint64_t fss_start_usec;
|
||||
uint64_t fss_interval_usec;
|
||||
|
||||
struct iovec fsprg_state;
|
||||
struct iovec fsprg_seed;
|
||||
};
|
||||
|
||||
static JournalAuthContext* journal_auth_free(JournalAuthContext *c) {
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
if (c->fss_file)
|
||||
munmap(c->fss_file, c->fss_mmap_size);
|
||||
else
|
||||
iovec_done_erase(&c->fsprg_state);
|
||||
|
||||
iovec_done_erase(&c->fsprg_seed);
|
||||
|
||||
if (c->ossl_params)
|
||||
sym_OSSL_PARAM_free(c->ossl_params);
|
||||
if (c->hmac_ctx)
|
||||
sym_EVP_MAC_CTX_free(c->hmac_ctx);
|
||||
if (c->hmac)
|
||||
sym_EVP_MAC_free(c->hmac);
|
||||
|
||||
return mfree(c);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(JournalAuthContext*, journal_auth_free);
|
||||
|
||||
static void* fssheader_free(FSSHeader *p) {
|
||||
/* mmap() returns MAP_FAILED on error and sets the errno */
|
||||
if (!p || p == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
assert_se(munmap(p, PAGE_ALIGN(sizeof(FSSHeader))) >= 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(FSSHeader*, fssheader_free);
|
||||
|
||||
static int journal_auth_load(JournalAuthContext **ret) {
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* This function is used to determine whether sealing should be enabled in the journal header so we
|
||||
* can't check the header to check if sealing is enabled here. */
|
||||
|
||||
sd_id128_t machine;
|
||||
r = sd_id128_get_machine(&machine);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ char *path = NULL;
|
||||
if (asprintf(&path, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
|
||||
SD_ID128_FORMAT_VAL(machine)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
_cleanup_close_ int fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
|
||||
if (fd < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_error_errno(errno, "Failed to open %s: %m", path);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (st.st_size < (off_t) sizeof(FSSHeader))
|
||||
return -ENODATA;
|
||||
|
||||
_cleanup_(fssheader_freep) FSSHeader *header =
|
||||
mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (header == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
if (memcmp(header->signature, (const uint8_t[]) FSS_HEADER_SIGNATURE, 8) != 0)
|
||||
return -EBADMSG;
|
||||
|
||||
if (header->incompatible_flags != 0)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
if (le64toh(header->header_size) < sizeof(FSSHeader))
|
||||
return -EBADMSG;
|
||||
|
||||
uint16_t secpar = le16toh(header->fsprg_secpar);
|
||||
if (!fsprg_secpar_is_valid(secpar))
|
||||
return -EBADMSG;
|
||||
|
||||
if (le64toh(header->fsprg_state_size) != fsprg_state_size(secpar))
|
||||
return -EBADMSG;
|
||||
|
||||
uint64_t fss_file_size;
|
||||
if (!ADD_SAFE(&fss_file_size, le64toh(header->header_size), le64toh(header->fsprg_state_size)))
|
||||
return -EBADMSG;
|
||||
|
||||
if (fss_file_size >= SIZE_MAX)
|
||||
return -EBADMSG;
|
||||
|
||||
if ((uint64_t) st.st_size < fss_file_size)
|
||||
return -ENODATA;
|
||||
|
||||
if (!sd_id128_equal(machine, header->machine_id))
|
||||
return -EHOSTDOWN;
|
||||
|
||||
if (le64toh(header->start_usec) <= 0 || le64toh(header->interval_usec) <= 0)
|
||||
return -EBADMSG;
|
||||
|
||||
_cleanup_(journal_auth_freep) JournalAuthContext *c = new0(JournalAuthContext, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
size_t sz = PAGE_ALIGN(fss_file_size);
|
||||
if (sz >= SIZE_MAX)
|
||||
return -EBADMSG;
|
||||
|
||||
FSSHeader *p = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
*c = (JournalAuthContext) {
|
||||
.fss_mmap_size = sz,
|
||||
.fss_file = p,
|
||||
|
||||
.fss_start_usec = le64toh(p->start_usec),
|
||||
.fss_interval_usec = le64toh(p->interval_usec),
|
||||
|
||||
.fsprg_state = IOVEC_MAKE(
|
||||
(uint8_t*) p + le64toh(p->header_size),
|
||||
le64toh(p->fsprg_state_size)),
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_load_key(JournalAuthContext **ret, const char *key) {
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
assert(key);
|
||||
|
||||
size_t seed_size = FSPRG_RECOMMENDED_SEEDLEN;
|
||||
_cleanup_(erase_and_freep) uint8_t *seed = malloc(seed_size);
|
||||
if (!seed)
|
||||
return -ENOMEM;
|
||||
|
||||
const char *k = key;
|
||||
for (size_t c = 0; c < seed_size; c++) {
|
||||
int x, y;
|
||||
|
||||
k = skip_leading_chars(k, "-");
|
||||
|
||||
x = unhexchar(*k);
|
||||
if (x < 0)
|
||||
return -EKEYREJECTED;
|
||||
k++;
|
||||
|
||||
y = unhexchar(*k);
|
||||
if (y < 0)
|
||||
return -EKEYREJECTED;
|
||||
k++;
|
||||
|
||||
seed[c] = (uint8_t) (x * 16 + y);
|
||||
}
|
||||
|
||||
if (*k != '/')
|
||||
return -EKEYREJECTED;
|
||||
k++;
|
||||
|
||||
uint64_t start, interval;
|
||||
r = sscanf(k, "%"PRIx64"-%"PRIx64, &start, &interval);
|
||||
if (r != 2)
|
||||
return -EKEYREJECTED;
|
||||
|
||||
if (start == 0 || interval == 0)
|
||||
return -EKEYREJECTED;
|
||||
|
||||
uint64_t start_usec;
|
||||
if (!MUL_SAFE(&start_usec, start, interval))
|
||||
return -EKEYREJECTED;
|
||||
|
||||
_cleanup_(journal_auth_freep) JournalAuthContext *c = new(JournalAuthContext, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
*c = (JournalAuthContext) {
|
||||
.fss_start_usec = start_usec,
|
||||
.fss_interval_usec = interval,
|
||||
|
||||
.fsprg_seed = IOVEC_MAKE(TAKE_PTR(seed), seed_size),
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_epoch_to_realtime_usec(const JournalAuthContext *c, uint64_t epoch, usec_t *ret_start, usec_t *ret_end) {
|
||||
assert(c);
|
||||
assert(c->fss_start_usec > 0);
|
||||
assert(c->fss_interval_usec > 0);
|
||||
|
||||
uint64_t start, end;
|
||||
if (!MUL_SAFE(&start, epoch, c->fss_interval_usec) ||
|
||||
!INC_SAFE(&start, c->fss_start_usec) ||
|
||||
!ADD_SAFE(&end, start, c->fss_interval_usec))
|
||||
return -ERANGE;
|
||||
|
||||
if (ret_start)
|
||||
*ret_start = start;
|
||||
if (ret_end)
|
||||
*ret_end = end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_next_evolve_usec(const JournalAuthContext *c, usec_t *ret) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
|
||||
uint64_t epoch;
|
||||
r = fsprg_get_epoch(&c->fsprg_state, &epoch);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return journal_auth_epoch_to_realtime_usec(c, epoch, /* ret_start= */ NULL, ret);
|
||||
}
|
||||
|
||||
static int journal_auth_seek(JournalAuthContext *c, uint64_t goal) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(iovec_is_set(&c->fsprg_seed));
|
||||
|
||||
if (iovec_is_set(&c->fsprg_state)) {
|
||||
uint64_t epoch;
|
||||
r = fsprg_get_epoch(&c->fsprg_state, &epoch);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (goal == epoch)
|
||||
return 0;
|
||||
|
||||
if (goal == epoch + 1)
|
||||
return fsprg_evolve(&c->fsprg_state);
|
||||
} else {
|
||||
r = iovec_alloc(fsprg_state_size(FSPRG_RECOMMENDED_SECPAR), &c->fsprg_state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
log_debug("Seeking FSPRG key to %"PRIu64".", goal);
|
||||
return fsprg_generate_state(FSPRG_RECOMMENDED_SECPAR, goal, &c->fsprg_seed, &c->fsprg_state);
|
||||
}
|
||||
|
||||
static int journal_auth_setup(JournalAuthContext *c) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
|
||||
if (c->hmac)
|
||||
return 0;
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(EVP_MAC_freep) EVP_MAC *hmac = sym_EVP_MAC_fetch(NULL, "HMAC", NULL);
|
||||
if (!hmac)
|
||||
return log_openssl_errors(LOG_DEBUG, "EVP_MAC_fetch() failed");
|
||||
|
||||
_cleanup_(EVP_MAC_CTX_freep) EVP_MAC_CTX *ctx = sym_EVP_MAC_CTX_new(hmac);
|
||||
if (!ctx)
|
||||
return log_openssl_errors(LOG_DEBUG, "EVP_MAC_CTX_new() failed");
|
||||
|
||||
_cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = sym_OSSL_PARAM_BLD_new();
|
||||
if (!bld)
|
||||
return log_openssl_errors(LOG_DEBUG, "OSSL_PARAM_BLD_new() failed");
|
||||
|
||||
if (sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_MAC_PARAM_DIGEST, "SHA256", 0) <= 0)
|
||||
return log_openssl_errors(LOG_DEBUG, "OSSL_PARAM_BLD_push_utf8_string() failed");
|
||||
|
||||
_cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = sym_OSSL_PARAM_BLD_to_param(bld);
|
||||
if (!params)
|
||||
return log_openssl_errors(LOG_DEBUG, "OSSL_PARAM_BLD_to_param() failed");
|
||||
|
||||
c->hmac = TAKE_PTR(hmac);
|
||||
c->hmac_ctx = TAKE_PTR(ctx);
|
||||
c->ossl_params = TAKE_PTR(params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_start(JournalAuthContext *c) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
|
||||
if (c->hmac_running)
|
||||
return 0;
|
||||
|
||||
r = journal_auth_setup(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
|
||||
CLEANUP_ERASE(key);
|
||||
r = fsprg_get_key(&c->fsprg_state, &IOVEC_MAKE(key, sizeof(key)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Prepare HMAC for next cycle */
|
||||
if (sym_EVP_MAC_init(c->hmac_ctx, key, sizeof(key), c->ossl_params) <= 0)
|
||||
return log_openssl_errors(LOG_DEBUG, "sym_EVP_MAC_init() failed");
|
||||
|
||||
c->hmac_running = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_end(JournalAuthContext *c, uint8_t ret[static TAG_LENGTH]) {
|
||||
assert(c);
|
||||
assert(ret);
|
||||
|
||||
if (!c->hmac_running)
|
||||
return -EINVAL;
|
||||
|
||||
c->hmac_running = false;
|
||||
|
||||
uint8_t tag[TAG_LENGTH];
|
||||
CLEANUP_ERASE(tag);
|
||||
|
||||
size_t len;
|
||||
if (sym_EVP_MAC_final(c->hmac_ctx, tag, &len, TAG_LENGTH) <= 0 || len != TAG_LENGTH)
|
||||
return -EIO;
|
||||
|
||||
memcpy(ret, tag, TAG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_put_header(JournalAuthContext *c, JournalFile *f) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(f);
|
||||
|
||||
r = journal_auth_start(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* All but state+reserved, boot_id, arena_size,
|
||||
* tail_object_offset, n_objects, n_entries,
|
||||
* tail_entry_seqnum, head_entry_seqnum, entry_array_offset,
|
||||
* head_entry_realtime, tail_entry_realtime,
|
||||
* tail_entry_monotonic, n_data, n_fields, n_tags,
|
||||
* n_entry_arrays. */
|
||||
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)) <= 0)
|
||||
return -EIO;
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id)) <= 0)
|
||||
return -EIO;
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)) <= 0)
|
||||
return -EIO;
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)) <= 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_put_object(JournalAuthContext *c, JournalFile *f, ObjectType type, Object *o, uint64_t p) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(f);
|
||||
|
||||
r = journal_auth_start(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!o) {
|
||||
r = journal_file_move_to_object(f, type, p, &o);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (type > OBJECT_UNUSED && o->object.type != type)
|
||||
return -EBADMSG;
|
||||
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) o, offsetof(ObjectHeader, payload)) <= 0)
|
||||
return -EIO;
|
||||
|
||||
switch (o->object.type) {
|
||||
|
||||
case OBJECT_DATA:
|
||||
/* All but hash and payload are mutable */
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &o->data.hash, sizeof(o->data.hash)) <= 0)
|
||||
return -EIO;
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f)) <= 0)
|
||||
return -EIO;
|
||||
break;
|
||||
|
||||
case OBJECT_FIELD:
|
||||
/* Same here */
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &o->field.hash, sizeof(o->field.hash)) <= 0)
|
||||
return -EIO;
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload)) <= 0)
|
||||
return -EIO;
|
||||
break;
|
||||
|
||||
case OBJECT_ENTRY:
|
||||
/* All */
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum)) <= 0)
|
||||
return -EIO;
|
||||
break;
|
||||
|
||||
case OBJECT_FIELD_HASH_TABLE:
|
||||
case OBJECT_DATA_HASH_TABLE:
|
||||
case OBJECT_ENTRY_ARRAY:
|
||||
/* Nothing: everything is mutable */
|
||||
break;
|
||||
|
||||
case OBJECT_TAG:
|
||||
/* All but the tag itself */
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &o->tag.seqnum, sizeof(o->tag.seqnum)) <= 0)
|
||||
return -EIO;
|
||||
if (sym_EVP_MAC_update(c->hmac_ctx, (void*) &o->tag.epoch, sizeof(o->tag.epoch)) <= 0)
|
||||
return -EIO;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_auth_append_tag(JournalAuthContext *c, JournalFile *f) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(f);
|
||||
|
||||
r = journal_auth_start(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Object *o;
|
||||
uint64_t p;
|
||||
r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint64_t seqnum = le64toh(f->header->n_tags) + 1;
|
||||
f->header->n_tags = htole64(seqnum);
|
||||
|
||||
o->tag.seqnum = htole64(seqnum);
|
||||
|
||||
uint64_t epoch;
|
||||
r = fsprg_get_epoch(&c->fsprg_state, &epoch);
|
||||
if (r < 0)
|
||||
return r;
|
||||
o->tag.epoch = htole64(epoch);
|
||||
|
||||
log_debug("Writing tag %"PRIu64" for epoch %"PRIu64"",
|
||||
le64toh(o->tag.seqnum), epoch);
|
||||
|
||||
/* Add the tag object itself, so that we can protect its
|
||||
* header. This will exclude the actual hash value in it */
|
||||
r = journal_auth_put_object(c, f, OBJECT_TAG, o, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Get the HMAC tag and store it in the object */
|
||||
return journal_auth_end(c, o->tag.tag);
|
||||
}
|
||||
|
||||
static int journal_auth_append_tag_first(JournalAuthContext *c, JournalFile *f) {
|
||||
uint64_t p;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(f);
|
||||
|
||||
log_debug("Calculating first tag...");
|
||||
|
||||
r = journal_auth_put_header(c, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = le64toh(f->header->field_hash_table_offset);
|
||||
if (p < offsetof(Object, hash_table.items))
|
||||
return -EINVAL;
|
||||
p -= offsetof(Object, hash_table.items);
|
||||
|
||||
r = journal_auth_put_object(c, f, OBJECT_FIELD_HASH_TABLE, NULL, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = le64toh(f->header->data_hash_table_offset);
|
||||
if (p < offsetof(Object, hash_table.items))
|
||||
return -EINVAL;
|
||||
p -= offsetof(Object, hash_table.items);
|
||||
|
||||
r = journal_auth_put_object(c, f, OBJECT_DATA_HASH_TABLE, NULL, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return journal_auth_append_tag(c, f);
|
||||
}
|
||||
|
||||
static int journal_auth_append_tag_maybe(JournalAuthContext *c, JournalFile *f, usec_t realtime) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(c->fss_start_usec > 0);
|
||||
assert(c->fss_interval_usec > 0);
|
||||
assert(f);
|
||||
|
||||
if (realtime <= 0)
|
||||
realtime = now(CLOCK_REALTIME);
|
||||
|
||||
uint64_t goal = usec_sub_unsigned(realtime, c->fss_start_usec) / c->fss_interval_usec;
|
||||
|
||||
for (;;) {
|
||||
uint64_t epoch;
|
||||
r = fsprg_get_epoch(&c->fsprg_state, &epoch);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (epoch >= goal)
|
||||
return 0;
|
||||
|
||||
r = journal_auth_append_tag(c, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fsprg_evolve(&c->fsprg_state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static const JournalAuthOps journal_auth_ops = {
|
||||
.free = journal_auth_free,
|
||||
.load = journal_auth_load,
|
||||
.load_key = journal_auth_load_key,
|
||||
.epoch_to_realtime_usec = journal_auth_epoch_to_realtime_usec,
|
||||
.next_evolve_usec = journal_auth_next_evolve_usec,
|
||||
.seek = journal_auth_seek,
|
||||
.start = journal_auth_start,
|
||||
.end = journal_auth_end,
|
||||
.put_header = journal_auth_put_header,
|
||||
.put_object = journal_auth_put_object,
|
||||
.append_tag = journal_auth_append_tag,
|
||||
.append_tag_first = journal_auth_append_tag_first,
|
||||
.append_tag_maybe = journal_auth_append_tag_maybe,
|
||||
};
|
||||
|
||||
void journal_auth_init(void) {
|
||||
journal_auth_set_ops(&journal_auth_ops);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void journal_auth_init(void) {
|
||||
}
|
||||
|
||||
#endif /* HAVE_OPENSSL */
|
||||
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "journal-authenticate-internal.h" /* IWYU pragma: export */
|
||||
#include "shared-forward.h"
|
||||
|
||||
void journal_auth_init(void);
|
||||
@@ -405,23 +405,15 @@ bool journal_file_is_offlining(JournalFile *f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void journal_file_write_final_tag(JournalFile *f) {
|
||||
assert(f);
|
||||
#if HAVE_GCRYPT
|
||||
if (!JOURNAL_HEADER_SEALED(f->header) || !journal_file_writable(f))
|
||||
return;
|
||||
|
||||
int r = journal_file_append_tag(f);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to append tag when closing journal: %m");
|
||||
#endif
|
||||
}
|
||||
|
||||
JournalFile* journal_file_offline_close(JournalFile *f) {
|
||||
int r;
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
journal_file_write_final_tag(f);
|
||||
r = journal_file_auth_append_tag(f);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to append tag when closing journal, ignoring: %m");
|
||||
|
||||
if (sd_event_source_get_enabled(f->post_change_timer, NULL) > 0)
|
||||
journal_file_post_change(f);
|
||||
@@ -464,7 +456,10 @@ int journal_file_rotate(
|
||||
assert(f);
|
||||
assert(*f);
|
||||
|
||||
journal_file_write_final_tag(*f);
|
||||
r = journal_file_auth_append_tag(*f);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to append tag when closing journal, ignoring: %m");
|
||||
|
||||
r = journal_file_archive(*f, &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
int journal_file_set_offline(JournalFile *f, bool wait);
|
||||
bool journal_file_is_offlining(JournalFile *f);
|
||||
void journal_file_write_final_tag(JournalFile *f);
|
||||
JournalFile* journal_file_offline_close(JournalFile *f);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_offline_close);
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ shared_sources = files(
|
||||
'firewall-util.c',
|
||||
'fork-notify.c',
|
||||
'format-table.c',
|
||||
'fsprg-openssl.c',
|
||||
'fstab-util.c',
|
||||
'generator.c',
|
||||
'geneve-util.c',
|
||||
@@ -110,6 +111,7 @@ shared_sources = files(
|
||||
'ioprio-util.c',
|
||||
'ip-protocol-list.c',
|
||||
'ipvlan-util.c',
|
||||
'journal-authenticate.c',
|
||||
'journal-file-util.c',
|
||||
'journal-importer.c',
|
||||
'journal-util.c',
|
||||
@@ -405,7 +407,6 @@ libshared_deps = [libacl_cflags,
|
||||
libelf_cflags,
|
||||
libfdisk_cflags,
|
||||
libfido2_cflags,
|
||||
libgcrypt_cflags,
|
||||
libgnutls_cflags,
|
||||
libidn2_cflags,
|
||||
libkmod_cflags,
|
||||
|
||||
@@ -40,7 +40,6 @@ DLSYM_PROTOTYPE(gcry_mpi_subm) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_mpi_sub_ui) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_prime_check) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_randomize) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_strerror) = NULL;
|
||||
#endif
|
||||
|
||||
int dlopen_gcrypt(int log_level) {
|
||||
@@ -82,8 +81,7 @@ int dlopen_gcrypt(int log_level) {
|
||||
DLSYM_ARG(gcry_mpi_subm),
|
||||
DLSYM_ARG(gcry_mpi_sub_ui),
|
||||
DLSYM_ARG(gcry_prime_check),
|
||||
DLSYM_ARG(gcry_randomize),
|
||||
DLSYM_ARG(gcry_strerror));
|
||||
DLSYM_ARG(gcry_randomize));
|
||||
#else
|
||||
return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"gcrypt support is not compiled in.");
|
||||
@@ -56,7 +56,6 @@ extern DLSYM_PROTOTYPE(gcry_mpi_subm);
|
||||
extern DLSYM_PROTOTYPE(gcry_mpi_sub_ui);
|
||||
extern DLSYM_PROTOTYPE(gcry_prime_check);
|
||||
extern DLSYM_PROTOTYPE(gcry_randomize);
|
||||
extern DLSYM_PROTOTYPE(gcry_strerror);
|
||||
|
||||
/* Copied from gcry_md_putc from gcrypt.h due to the need to call the sym_ variant */
|
||||
#define sym_gcry_md_putc(h,c) \
|
||||
@@ -66,14 +65,8 @@ extern DLSYM_PROTOTYPE(gcry_strerror);
|
||||
sym_gcry_md_write((h__), NULL, 0); \
|
||||
(h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
|
||||
} while(false)
|
||||
#else
|
||||
#define DLOPEN_GCRYPT(log_level, priority) dlopen_gcrypt(log_level)
|
||||
|
||||
typedef struct gcry_md_handle *gcry_md_hd_t;
|
||||
|
||||
static inline void sym_gcry_md_close(gcry_md_hd_t h) {
|
||||
assert(h == NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gcry_md_hd_t, sym_gcry_md_close, NULL);
|
||||
#else
|
||||
#define DLOPEN_GCRYPT(log_level, priority) dlopen_gcrypt(log_level)
|
||||
#endif
|
||||
+17
-1
@@ -300,10 +300,14 @@ executables += [
|
||||
'type' : 'manual',
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-dlopen-so.c'),
|
||||
'sources' : files(
|
||||
'test-dlopen-so.c',
|
||||
'gcrypt-util.c',
|
||||
),
|
||||
'dependencies' : [
|
||||
libblkid_cflags,
|
||||
libfdisk_cflags,
|
||||
libgcrypt_cflags,
|
||||
libgnutls_cflags,
|
||||
libkmod_cflags,
|
||||
libmicrohttpd_cflags,
|
||||
@@ -336,6 +340,18 @@ executables += [
|
||||
'link_with' : libsystemd,
|
||||
'type' : 'manual',
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files(
|
||||
'test-fsprg.c',
|
||||
'fsprg.c',
|
||||
'gcrypt-util.c',
|
||||
),
|
||||
'dependencies' : [
|
||||
libgcrypt_cflags,
|
||||
libopenssl_cflags,
|
||||
],
|
||||
'conditions' : ['HAVE_OPENSSL'],
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files(
|
||||
'test-hashmap.c',
|
||||
|
||||
@@ -0,0 +1,511 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#if HAVE_VALGRIND_VALGRIND_H
|
||||
# include <valgrind/valgrind.h>
|
||||
#endif
|
||||
|
||||
#include "crypto-util.h"
|
||||
#include "fsprg.h"
|
||||
#include "fsprg-openssl.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-def.h"
|
||||
#include "stdio-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define STATE_LENGTH (2 + 2 * FSPRG_RECOMMENDED_SECPAR / 8 + 8)
|
||||
#define KEY_LENGTH 32
|
||||
|
||||
static const uint8_t expected_state[4][STATE_LENGTH] = {
|
||||
{
|
||||
0x00, 0x5f, 0xcd, 0x65, 0x12, 0x14, 0xa6, 0x15,
|
||||
0xe4, 0xd3, 0xc9, 0xe7, 0x5c, 0x70, 0x2c, 0x37,
|
||||
0xca, 0xa7, 0x21, 0xf4, 0x40, 0xf3, 0x6a, 0x88,
|
||||
0xe3, 0xce, 0x85, 0x9b, 0xe4, 0x8f, 0x90, 0x8c,
|
||||
0x4a, 0xad, 0xf4, 0xcf, 0x99, 0xcf, 0xdc, 0x3b,
|
||||
0x29, 0xad, 0x59, 0x72, 0x05, 0xa3, 0xca, 0x3e,
|
||||
0xf9, 0x72, 0x9f, 0x7c, 0xb6, 0xa4, 0xd6, 0x86,
|
||||
0xb4, 0x64, 0x5a, 0xc4, 0xe0, 0x95, 0x98, 0xb7,
|
||||
0xdf, 0xc5, 0x79, 0x8a, 0x48, 0xff, 0xd6, 0x71,
|
||||
0xab, 0x0f, 0x17, 0x54, 0xdd, 0x3d, 0xd0, 0x23,
|
||||
0x18, 0xc9, 0x4c, 0xf4, 0x40, 0xcf, 0x34, 0xc9,
|
||||
0x33, 0x04, 0x35, 0x4b, 0x2c, 0xd9, 0xbd, 0xcf,
|
||||
0x59, 0x62, 0x18, 0x2d, 0x9e, 0x5a, 0x11, 0x71,
|
||||
0x4c, 0x1f, 0x78, 0x0e, 0x65, 0x75, 0xe6, 0x15,
|
||||
0x2f, 0x61, 0x32, 0x3c, 0xac, 0xaa, 0xa8, 0x6a,
|
||||
0x1d, 0x11, 0xb4, 0x91, 0x38, 0xd3, 0x34, 0x31,
|
||||
0xd7, 0xfa, 0xff, 0xef, 0xbf, 0xb9, 0x90, 0x4f,
|
||||
0x0d, 0x29, 0x16, 0xb6, 0x64, 0x48, 0x5b, 0x7b,
|
||||
0x00, 0x42, 0x7a, 0xab, 0x2b, 0xe7, 0xee, 0x9b,
|
||||
0x5d, 0x0c, 0xe9, 0x14, 0x74, 0x72, 0x29, 0xd9,
|
||||
0x10, 0xa5, 0xd5, 0x95, 0xbb, 0x9f, 0x85, 0xc0,
|
||||
0xa2, 0xfa, 0xbb, 0x84, 0xf5, 0x59, 0x11, 0xdb,
|
||||
0xf4, 0xce, 0x08, 0xe4, 0x36, 0x1c, 0xeb, 0xc9,
|
||||
0xa6, 0xcd, 0xdb, 0xf2, 0x10, 0xab, 0x51, 0xb2,
|
||||
0x8c, 0x9d, 0xc9, 0xf8, 0x35, 0xe1, 0xec, 0x25,
|
||||
0xd5, 0xca, 0x98, 0x7a, 0x4f, 0xbd, 0x45, 0x50,
|
||||
0xbf, 0xff, 0x1c, 0xd8, 0x42, 0x95, 0xcb, 0xc5,
|
||||
0xa7, 0x0f, 0x75, 0xda, 0x6d, 0x5b, 0xa2, 0xeb,
|
||||
0x5b, 0x26, 0x9e, 0xe8, 0xa3, 0x23, 0x04, 0x4b,
|
||||
0x5b, 0x26, 0xb7, 0xe4, 0x7f, 0xcd, 0x82, 0x66,
|
||||
0x23, 0x7d, 0xf8, 0x57, 0x2c, 0x22, 0x0b, 0x7e,
|
||||
0x87, 0x3f, 0xe1, 0xc1, 0x1a, 0xea, 0xc3, 0x42,
|
||||
0x40, 0x03, 0xaf, 0x11, 0xd5, 0x07, 0xa1, 0x79,
|
||||
0x55, 0x34, 0x4a, 0x41, 0x6a, 0x75, 0x68, 0x13,
|
||||
0x37, 0xfd, 0x38, 0x97, 0x52, 0x4f, 0xbb, 0x68,
|
||||
0xb4, 0x9f, 0xa8, 0xda, 0x9c, 0x4c, 0x8e, 0x65,
|
||||
0x3e, 0x42, 0x19, 0x40, 0x5f, 0x47, 0xe8, 0x50,
|
||||
0x0c, 0xb3, 0xc5, 0x6e, 0x0e, 0xe6, 0x6b, 0xe7,
|
||||
0xb9, 0x1f, 0xe0, 0x66, 0x2a, 0x38, 0x8e, 0x38,
|
||||
0xa8, 0x7f, 0xfd, 0x2c, 0x92, 0xf8, 0xf2, 0x91,
|
||||
0x36, 0x90, 0xfd, 0x14, 0x1d, 0x07, 0xae, 0x71,
|
||||
0x7f, 0x3c, 0xaa, 0xd6, 0xc4, 0x10, 0x20, 0xe5,
|
||||
0xd0, 0xc2, 0xa2, 0xe7, 0x5e, 0x36, 0x91, 0xf7,
|
||||
0xff, 0x27, 0x4e, 0x81, 0xc0, 0x85, 0xab, 0x0a,
|
||||
0x46, 0x88, 0xe7, 0x32, 0xce, 0x83, 0x4a, 0x09,
|
||||
0x72, 0xb3, 0xae, 0xdd, 0x65, 0xf8, 0x13, 0xd0,
|
||||
0x9f, 0x4f, 0x45, 0x83, 0xfa, 0x41, 0x1f, 0x8d,
|
||||
0xfe, 0x96, 0xbd, 0xe0, 0x32, 0x5c, 0xb9, 0x87,
|
||||
0xd8, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
},
|
||||
{
|
||||
0x00, 0x5f, 0xcd, 0x65, 0x12, 0x14, 0xa6, 0x15,
|
||||
0xe4, 0xd3, 0xc9, 0xe7, 0x5c, 0x70, 0x2c, 0x37,
|
||||
0xca, 0xa7, 0x21, 0xf4, 0x40, 0xf3, 0x6a, 0x88,
|
||||
0xe3, 0xce, 0x85, 0x9b, 0xe4, 0x8f, 0x90, 0x8c,
|
||||
0x4a, 0xad, 0xf4, 0xcf, 0x99, 0xcf, 0xdc, 0x3b,
|
||||
0x29, 0xad, 0x59, 0x72, 0x05, 0xa3, 0xca, 0x3e,
|
||||
0xf9, 0x72, 0x9f, 0x7c, 0xb6, 0xa4, 0xd6, 0x86,
|
||||
0xb4, 0x64, 0x5a, 0xc4, 0xe0, 0x95, 0x98, 0xb7,
|
||||
0xdf, 0xc5, 0x79, 0x8a, 0x48, 0xff, 0xd6, 0x71,
|
||||
0xab, 0x0f, 0x17, 0x54, 0xdd, 0x3d, 0xd0, 0x23,
|
||||
0x18, 0xc9, 0x4c, 0xf4, 0x40, 0xcf, 0x34, 0xc9,
|
||||
0x33, 0x04, 0x35, 0x4b, 0x2c, 0xd9, 0xbd, 0xcf,
|
||||
0x59, 0x62, 0x18, 0x2d, 0x9e, 0x5a, 0x11, 0x71,
|
||||
0x4c, 0x1f, 0x78, 0x0e, 0x65, 0x75, 0xe6, 0x15,
|
||||
0x2f, 0x61, 0x32, 0x3c, 0xac, 0xaa, 0xa8, 0x6a,
|
||||
0x1d, 0x11, 0xb4, 0x91, 0x38, 0xd3, 0x34, 0x31,
|
||||
0xd7, 0xfa, 0xff, 0xef, 0xbf, 0xb9, 0x90, 0x4f,
|
||||
0x0d, 0x29, 0x16, 0xb6, 0x64, 0x48, 0x5b, 0x7b,
|
||||
0x00, 0x42, 0x7a, 0xab, 0x2b, 0xe7, 0xee, 0x9b,
|
||||
0x5d, 0x0c, 0xe9, 0x14, 0x74, 0x72, 0x29, 0xd9,
|
||||
0x10, 0xa5, 0xd5, 0x95, 0xbb, 0x9f, 0x85, 0xc0,
|
||||
0xa2, 0xfa, 0xbb, 0x84, 0xf5, 0x59, 0x11, 0xdb,
|
||||
0xf4, 0xce, 0x08, 0xe4, 0x36, 0x1c, 0xeb, 0xc9,
|
||||
0xa6, 0xcd, 0xdb, 0xf2, 0x10, 0xab, 0x51, 0xb2,
|
||||
0x8c, 0x9d, 0x4a, 0x62, 0x5d, 0xd1, 0x34, 0x5b,
|
||||
0x56, 0x44, 0x04, 0x10, 0x9e, 0x43, 0x7f, 0x62,
|
||||
0x18, 0x1f, 0x5d, 0x68, 0x8f, 0xa8, 0x26, 0xab,
|
||||
0xd4, 0xf9, 0xa6, 0xef, 0xfa, 0x3f, 0x41, 0x09,
|
||||
0xae, 0x44, 0x8f, 0x9e, 0xd3, 0x4c, 0xc5, 0x7b,
|
||||
0x35, 0x50, 0x7f, 0xc0, 0xba, 0xd9, 0x42, 0xe9,
|
||||
0x89, 0x9b, 0x4f, 0x30, 0x40, 0x02, 0x96, 0xed,
|
||||
0x7c, 0x67, 0x7e, 0xab, 0x26, 0x3b, 0xc9, 0x65,
|
||||
0xf6, 0x16, 0x9b, 0x7e, 0x28, 0xf2, 0xed, 0xb9,
|
||||
0xfd, 0x9d, 0xe4, 0x68, 0x67, 0x65, 0xf2, 0x5d,
|
||||
0x54, 0x43, 0xd5, 0x2d, 0xfd, 0xf4, 0x2d, 0xfd,
|
||||
0x49, 0x00, 0xca, 0x35, 0xc9, 0x87, 0x7c, 0xd4,
|
||||
0xfe, 0xfb, 0x9d, 0x8d, 0xda, 0x1c, 0x54, 0xc2,
|
||||
0x26, 0xed, 0xe5, 0xaa, 0xde, 0xa9, 0x41, 0x88,
|
||||
0x88, 0xec, 0x17, 0xab, 0x12, 0x00, 0xc4, 0x71,
|
||||
0x8f, 0xe4, 0x5a, 0xf9, 0x55, 0xe6, 0xd9, 0x56,
|
||||
0x45, 0x86, 0x6a, 0x1c, 0xd1, 0x09, 0xb1, 0xfc,
|
||||
0x0d, 0xd0, 0x15, 0x2c, 0xa1, 0xb6, 0xe9, 0x95,
|
||||
0x01, 0xe1, 0x71, 0xb3, 0xb7, 0xbf, 0x57, 0xd5,
|
||||
0x15, 0xec, 0xe7, 0xde, 0x85, 0x90, 0xb2, 0x47,
|
||||
0x51, 0x0f, 0x0f, 0x9b, 0xcf, 0x21, 0x0c, 0x77,
|
||||
0x21, 0xe7, 0xbb, 0x44, 0xbb, 0x70, 0xbf, 0xfb,
|
||||
0x29, 0x58, 0x50, 0xdc, 0x01, 0xfb, 0x2b, 0xdf,
|
||||
0x8d, 0x74, 0xc5, 0x89, 0xe1, 0x29, 0xcd, 0x97,
|
||||
0xe5, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01,
|
||||
},
|
||||
{
|
||||
0x00, 0x5f, 0xcd, 0x65, 0x12, 0x14, 0xa6, 0x15,
|
||||
0xe4, 0xd3, 0xc9, 0xe7, 0x5c, 0x70, 0x2c, 0x37,
|
||||
0xca, 0xa7, 0x21, 0xf4, 0x40, 0xf3, 0x6a, 0x88,
|
||||
0xe3, 0xce, 0x85, 0x9b, 0xe4, 0x8f, 0x90, 0x8c,
|
||||
0x4a, 0xad, 0xf4, 0xcf, 0x99, 0xcf, 0xdc, 0x3b,
|
||||
0x29, 0xad, 0x59, 0x72, 0x05, 0xa3, 0xca, 0x3e,
|
||||
0xf9, 0x72, 0x9f, 0x7c, 0xb6, 0xa4, 0xd6, 0x86,
|
||||
0xb4, 0x64, 0x5a, 0xc4, 0xe0, 0x95, 0x98, 0xb7,
|
||||
0xdf, 0xc5, 0x79, 0x8a, 0x48, 0xff, 0xd6, 0x71,
|
||||
0xab, 0x0f, 0x17, 0x54, 0xdd, 0x3d, 0xd0, 0x23,
|
||||
0x18, 0xc9, 0x4c, 0xf4, 0x40, 0xcf, 0x34, 0xc9,
|
||||
0x33, 0x04, 0x35, 0x4b, 0x2c, 0xd9, 0xbd, 0xcf,
|
||||
0x59, 0x62, 0x18, 0x2d, 0x9e, 0x5a, 0x11, 0x71,
|
||||
0x4c, 0x1f, 0x78, 0x0e, 0x65, 0x75, 0xe6, 0x15,
|
||||
0x2f, 0x61, 0x32, 0x3c, 0xac, 0xaa, 0xa8, 0x6a,
|
||||
0x1d, 0x11, 0xb4, 0x91, 0x38, 0xd3, 0x34, 0x31,
|
||||
0xd7, 0xfa, 0xff, 0xef, 0xbf, 0xb9, 0x90, 0x4f,
|
||||
0x0d, 0x29, 0x16, 0xb6, 0x64, 0x48, 0x5b, 0x7b,
|
||||
0x00, 0x42, 0x7a, 0xab, 0x2b, 0xe7, 0xee, 0x9b,
|
||||
0x5d, 0x0c, 0xe9, 0x14, 0x74, 0x72, 0x29, 0xd9,
|
||||
0x10, 0xa5, 0xd5, 0x95, 0xbb, 0x9f, 0x85, 0xc0,
|
||||
0xa2, 0xfa, 0xbb, 0x84, 0xf5, 0x59, 0x11, 0xdb,
|
||||
0xf4, 0xce, 0x08, 0xe4, 0x36, 0x1c, 0xeb, 0xc9,
|
||||
0xa6, 0xcd, 0xdb, 0xf2, 0x10, 0xab, 0x51, 0xb2,
|
||||
0x8c, 0x9d, 0x57, 0xb9, 0x1b, 0x5d, 0x82, 0x02,
|
||||
0x77, 0x8c, 0x96, 0x3e, 0x36, 0x0c, 0x17, 0x8f,
|
||||
0x61, 0x3b, 0x3f, 0x17, 0x7d, 0x1d, 0xa9, 0x03,
|
||||
0xf8, 0x57, 0x4b, 0xf7, 0x48, 0xb8, 0x65, 0xfc,
|
||||
0xbb, 0xd4, 0x2b, 0x19, 0x06, 0xa3, 0x82, 0x61,
|
||||
0xe0, 0x21, 0x62, 0x31, 0xb4, 0xd2, 0x5b, 0xf0,
|
||||
0x4b, 0x21, 0xcd, 0xca, 0x84, 0x84, 0xc0, 0x1b,
|
||||
0x55, 0x4d, 0xf0, 0x32, 0xc9, 0x37, 0x57, 0xd9,
|
||||
0x63, 0x1b, 0x00, 0x65, 0x61, 0x93, 0x1d, 0xa4,
|
||||
0xb0, 0x86, 0xef, 0x4f, 0x15, 0x88, 0xf8, 0x58,
|
||||
0xcd, 0xfb, 0xc6, 0x2b, 0x09, 0xcd, 0x9a, 0x32,
|
||||
0x44, 0x97, 0x8e, 0xea, 0xfa, 0x3c, 0x5a, 0x7d,
|
||||
0x94, 0xda, 0x09, 0x94, 0x27, 0xa0, 0xc5, 0x57,
|
||||
0xa8, 0x2d, 0xc5, 0xc4, 0xdf, 0x7c, 0x5f, 0xb4,
|
||||
0x9b, 0x27, 0x0b, 0x62, 0xc1, 0x55, 0xcc, 0x55,
|
||||
0xb6, 0xfa, 0xf8, 0x70, 0x66, 0x48, 0xba, 0x21,
|
||||
0xe5, 0x9c, 0x27, 0x3f, 0x6b, 0xc5, 0xf3, 0x00,
|
||||
0x03, 0x52, 0x90, 0x06, 0xa3, 0xb9, 0xda, 0xee,
|
||||
0x87, 0xab, 0x78, 0x96, 0x93, 0x69, 0x34, 0x5a,
|
||||
0x04, 0x77, 0xcf, 0x0d, 0x20, 0xa3, 0xd7, 0x42,
|
||||
0x27, 0x8d, 0x59, 0xfe, 0x89, 0x67, 0x3e, 0x5d,
|
||||
0xe0, 0x0c, 0xb6, 0xad, 0xf0, 0x36, 0x09, 0x60,
|
||||
0xc1, 0x7c, 0xce, 0x2d, 0xe4, 0x75, 0xaa, 0xf5,
|
||||
0xa3, 0x5f, 0x72, 0x3b, 0xf2, 0x73, 0xb4, 0x9b,
|
||||
0xb5, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x02,
|
||||
},
|
||||
{
|
||||
0x00, 0x5f, 0xcd, 0x65, 0x12, 0x14, 0xa6, 0x15,
|
||||
0xe4, 0xd3, 0xc9, 0xe7, 0x5c, 0x70, 0x2c, 0x37,
|
||||
0xca, 0xa7, 0x21, 0xf4, 0x40, 0xf3, 0x6a, 0x88,
|
||||
0xe3, 0xce, 0x85, 0x9b, 0xe4, 0x8f, 0x90, 0x8c,
|
||||
0x4a, 0xad, 0xf4, 0xcf, 0x99, 0xcf, 0xdc, 0x3b,
|
||||
0x29, 0xad, 0x59, 0x72, 0x05, 0xa3, 0xca, 0x3e,
|
||||
0xf9, 0x72, 0x9f, 0x7c, 0xb6, 0xa4, 0xd6, 0x86,
|
||||
0xb4, 0x64, 0x5a, 0xc4, 0xe0, 0x95, 0x98, 0xb7,
|
||||
0xdf, 0xc5, 0x79, 0x8a, 0x48, 0xff, 0xd6, 0x71,
|
||||
0xab, 0x0f, 0x17, 0x54, 0xdd, 0x3d, 0xd0, 0x23,
|
||||
0x18, 0xc9, 0x4c, 0xf4, 0x40, 0xcf, 0x34, 0xc9,
|
||||
0x33, 0x04, 0x35, 0x4b, 0x2c, 0xd9, 0xbd, 0xcf,
|
||||
0x59, 0x62, 0x18, 0x2d, 0x9e, 0x5a, 0x11, 0x71,
|
||||
0x4c, 0x1f, 0x78, 0x0e, 0x65, 0x75, 0xe6, 0x15,
|
||||
0x2f, 0x61, 0x32, 0x3c, 0xac, 0xaa, 0xa8, 0x6a,
|
||||
0x1d, 0x11, 0xb4, 0x91, 0x38, 0xd3, 0x34, 0x31,
|
||||
0xd7, 0xfa, 0xff, 0xef, 0xbf, 0xb9, 0x90, 0x4f,
|
||||
0x0d, 0x29, 0x16, 0xb6, 0x64, 0x48, 0x5b, 0x7b,
|
||||
0x00, 0x42, 0x7a, 0xab, 0x2b, 0xe7, 0xee, 0x9b,
|
||||
0x5d, 0x0c, 0xe9, 0x14, 0x74, 0x72, 0x29, 0xd9,
|
||||
0x10, 0xa5, 0xd5, 0x95, 0xbb, 0x9f, 0x85, 0xc0,
|
||||
0xa2, 0xfa, 0xbb, 0x84, 0xf5, 0x59, 0x11, 0xdb,
|
||||
0xf4, 0xce, 0x08, 0xe4, 0x36, 0x1c, 0xeb, 0xc9,
|
||||
0xa6, 0xcd, 0xdb, 0xf2, 0x10, 0xab, 0x51, 0xb2,
|
||||
0x8c, 0x9d, 0x24, 0x8b, 0xa0, 0xb7, 0xf0, 0xd8,
|
||||
0xea, 0x6e, 0x24, 0x61, 0x57, 0xfa, 0xd8, 0xd3,
|
||||
0xf8, 0x10, 0xaf, 0x7e, 0x45, 0xc5, 0xea, 0x7d,
|
||||
0xa4, 0x0d, 0x14, 0x2b, 0x4c, 0xc9, 0x64, 0x48,
|
||||
0x12, 0xf1, 0x36, 0x2d, 0xef, 0x33, 0xb6, 0x74,
|
||||
0x4c, 0xdf, 0xd5, 0x59, 0x80, 0xa4, 0xfc, 0xa5,
|
||||
0x7c, 0x09, 0x24, 0xd7, 0xd5, 0xdf, 0xd6, 0xa5,
|
||||
0x2f, 0xa3, 0x49, 0x8a, 0xa3, 0x23, 0xa6, 0x11,
|
||||
0x76, 0x0e, 0xe3, 0xcd, 0xd7, 0x64, 0x0f, 0xbe,
|
||||
0x3f, 0x99, 0x0d, 0x05, 0x14, 0xd7, 0xa8, 0x2b,
|
||||
0x79, 0x6d, 0xb3, 0x12, 0x76, 0x93, 0xae, 0x35,
|
||||
0xbe, 0x81, 0xb7, 0xd2, 0xcf, 0x39, 0xd2, 0xad,
|
||||
0xb9, 0xc4, 0x3f, 0xfb, 0xe2, 0xc3, 0x32, 0x46,
|
||||
0x4d, 0x0b, 0x84, 0x8a, 0x2c, 0x77, 0x2f, 0x49,
|
||||
0xac, 0x96, 0xe0, 0x30, 0xeb, 0x38, 0x8f, 0x2f,
|
||||
0x01, 0x1b, 0xf3, 0x3c, 0xb5, 0xee, 0x8c, 0x62,
|
||||
0x9c, 0x9d, 0x0d, 0xb4, 0x57, 0x6c, 0x8d, 0xf5,
|
||||
0xe2, 0x16, 0xc0, 0x62, 0x9c, 0x52, 0x49, 0xf8,
|
||||
0xc7, 0xac, 0xb0, 0xa0, 0xe8, 0x81, 0xd9, 0x05,
|
||||
0x87, 0xda, 0x09, 0x6f, 0xf7, 0x95, 0xc7, 0x68,
|
||||
0x69, 0xbb, 0x68, 0xf4, 0x76, 0x3e, 0x2f, 0xd1,
|
||||
0x9d, 0x18, 0xc1, 0x47, 0x59, 0x3d, 0x56, 0x57,
|
||||
0x26, 0x10, 0x64, 0xc5, 0x9c, 0x35, 0xe8, 0x58,
|
||||
0x1b, 0x0e, 0x20, 0x97, 0xdf, 0xfa, 0xcc, 0x88,
|
||||
0xa0, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x03,
|
||||
},
|
||||
}, expected_key[4][KEY_LENGTH] = {
|
||||
{
|
||||
0xca, 0xe4, 0x2e, 0xba, 0x74, 0x55, 0x4f, 0x10,
|
||||
0x4f, 0x72, 0xa4, 0x3a, 0x0b, 0x00, 0xa0, 0xc8,
|
||||
0xd8, 0x8f, 0xa7, 0x11, 0x8d, 0x56, 0x2a, 0x72,
|
||||
0xe4, 0xa8, 0xd2, 0x69, 0xf9, 0xd8, 0xa0, 0xf1,
|
||||
},
|
||||
{
|
||||
0x63, 0x1d, 0x52, 0x11, 0xed, 0x13, 0xa8, 0x8e,
|
||||
0x4c, 0xe0, 0x06, 0x2e, 0xe6, 0xa3, 0xa1, 0xf6,
|
||||
0x7a, 0xf1, 0xc4, 0x1e, 0x18, 0xbf, 0x74, 0xe2,
|
||||
0x52, 0x23, 0x86, 0x56, 0x1b, 0x0e, 0x78, 0x7d,
|
||||
},
|
||||
{
|
||||
0x3f, 0xb2, 0xb6, 0x39, 0xe3, 0x54, 0x41, 0x04,
|
||||
0xf3, 0x48, 0x5f, 0x50, 0xf7, 0x8b, 0xd6, 0xe7,
|
||||
0x8e, 0x45, 0xc2, 0xee, 0xbf, 0xdd, 0xfd, 0x83,
|
||||
0x34, 0x7a, 0x9a, 0x8a, 0xf3, 0x4d, 0xd4, 0xc6,
|
||||
},
|
||||
{
|
||||
0x98, 0x76, 0x29, 0xe2, 0x27, 0xf0, 0x0e, 0x2a,
|
||||
0xff, 0xc8, 0xfd, 0x3b, 0xcf, 0xcb, 0x9f, 0x6d,
|
||||
0xe9, 0x80, 0xfe, 0x6e, 0xd9, 0xc0, 0x43, 0x29,
|
||||
0xc5, 0x53, 0x5f, 0xf7, 0x86, 0x33, 0x3b, 0x70,
|
||||
},
|
||||
}, expected_tag[4][TAG_LENGTH] = {
|
||||
{
|
||||
0x10, 0xa4, 0x14, 0x19, 0xec, 0xf1, 0x9b, 0x6d,
|
||||
0xe5, 0xe3, 0x12, 0x2b, 0x06, 0xee, 0x5b, 0xac,
|
||||
0xa7, 0x11, 0x0b, 0x70, 0x15, 0xfd, 0x47, 0xa4,
|
||||
0xb9, 0xd7, 0x45, 0x19, 0x4b, 0xde, 0x92, 0x5d,
|
||||
},
|
||||
{
|
||||
0x75, 0x54, 0x5b, 0x6a, 0xfb, 0x30, 0x43, 0x3b,
|
||||
0x29, 0x94, 0x58, 0xee, 0x62, 0xd9, 0x62, 0x2b,
|
||||
0x61, 0x88, 0xed, 0xce, 0xc9, 0x95, 0x1e, 0x82,
|
||||
0x9e, 0xd6, 0xd1, 0x90, 0x23, 0xc6, 0x90, 0x65,
|
||||
},
|
||||
{
|
||||
0x2f, 0x8b, 0x64, 0xa4, 0x21, 0xe8, 0x74, 0x93,
|
||||
0xa2, 0x3a, 0x6a, 0xa9, 0x0d, 0x7e, 0xb0, 0x80,
|
||||
0xce, 0x74, 0x80, 0xb9, 0x06, 0xae, 0xec, 0x86,
|
||||
0x4c, 0x32, 0x99, 0xf9, 0x48, 0x1f, 0x0c, 0xad,
|
||||
},
|
||||
{
|
||||
0x39, 0x9e, 0xf6, 0xc3, 0x1e, 0xca, 0x02, 0xb2,
|
||||
0x6a, 0xe2, 0xa6, 0x47, 0x0b, 0xb5, 0xb6, 0xaf,
|
||||
0x46, 0xd7, 0x99, 0x13, 0xc6, 0x07, 0xa8, 0x80,
|
||||
0x73, 0x35, 0x75, 0x73, 0xfd, 0x03, 0x5b, 0x3e,
|
||||
},
|
||||
};
|
||||
|
||||
static void generate_seed(struct iovec *seed) {
|
||||
assert(iovec_is_set(seed));
|
||||
|
||||
uint8_t *p = seed->iov_base;
|
||||
for (size_t i = 0; i < seed->iov_len; i++)
|
||||
*p++ = (uint8_t) i;
|
||||
}
|
||||
|
||||
TEST(fsprg) {
|
||||
size_t n_states = 20;
|
||||
|
||||
/* Generating private keys is slow when running on valgrind or with sanitizers. */
|
||||
#if HAVE_VALGRIND_VALGRIND_H
|
||||
if (RUNNING_ON_VALGRIND)
|
||||
n_states = ELEMENTSOF(expected_state);
|
||||
#endif
|
||||
#if HAS_FEATURE_ADDRESS_SANITIZER
|
||||
n_states = ELEMENTSOF(expected_state);
|
||||
#endif
|
||||
|
||||
struct iovec *states = new0(struct iovec, n_states);
|
||||
CLEANUP_ARRAY(states, n_states, iovec_array_free);
|
||||
|
||||
if (initialize_libgcrypt(false) >= 0) {
|
||||
struct iovec seed = IOVEC_ALLOCA(FSPRG_RECOMMENDED_SEEDLEN),
|
||||
msk = IOVEC_ALLOCA(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
mpk = IOVEC_ALLOCA(FSPRG_mpkinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
state = IOVEC_ALLOCA(FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
key = IOVEC_ALLOCA(KEY_LENGTH);
|
||||
|
||||
generate_seed(&seed);
|
||||
|
||||
/* Generate secret keys */
|
||||
ASSERT_OK(FSPRG_GenMK(msk.iov_base, mpk.iov_base, seed.iov_base, seed.iov_len, FSPRG_RECOMMENDED_SECPAR));
|
||||
|
||||
/* Generate states by FSPRG_Seek() */
|
||||
for (size_t i = 0; i < n_states; i++) {
|
||||
ASSERT_OK(FSPRG_Seek(state.iov_base, i, msk.iov_base, seed.iov_base, seed.iov_len));
|
||||
|
||||
/* Verify state */
|
||||
if (i < ELEMENTSOF(expected_state))
|
||||
ASSERT_TRUE(iovec_equal(&state, &IOVEC_MAKE(expected_state[i], sizeof(expected_state[i]))));
|
||||
|
||||
/* Verify key */
|
||||
ASSERT_OK(FSPRG_GetKey(state.iov_base, key.iov_base, key.iov_len, 0));
|
||||
if (i < ELEMENTSOF(expected_key))
|
||||
ASSERT_TRUE(iovec_equal(&key, &IOVEC_MAKE(expected_key[i], sizeof(expected_key[i]))));
|
||||
|
||||
/* Verify epoch */
|
||||
ASSERT_EQ(FSPRG_GetEpoch(state.iov_base), (uint64_t) i);
|
||||
|
||||
ASSERT_NOT_NULL(iovec_memdup(&state, &states[i]));
|
||||
}
|
||||
|
||||
/* Generate state by FSPRG_GetState0() */
|
||||
ASSERT_OK(FSPRG_GenState0(state.iov_base, mpk.iov_base, seed.iov_base, seed.iov_len));
|
||||
ASSERT_TRUE(iovec_equal(&state, &states[0]));
|
||||
|
||||
/* Generate states by FSPRG_Evolve() */
|
||||
for (size_t i = 1; i < n_states; i++) {
|
||||
ASSERT_OK(FSPRG_Evolve(state.iov_base));
|
||||
ASSERT_TRUE(iovec_equal(&state, &states[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (dlopen_libcrypto(LOG_DEBUG) >= 0) {
|
||||
struct iovec seed = IOVEC_ALLOCA(FSPRG_RECOMMENDED_SEEDLEN),
|
||||
state = IOVEC_ALLOCA(fsprg_state_size(FSPRG_RECOMMENDED_SECPAR)),
|
||||
key = IOVEC_ALLOCA(32);
|
||||
|
||||
generate_seed(&seed);
|
||||
|
||||
/* Generate states by fsprg_generate_state() */
|
||||
for (size_t i = 0; i < n_states; i++) {
|
||||
ASSERT_OK(fsprg_generate_state(FSPRG_RECOMMENDED_SECPAR, i, &seed, &state));
|
||||
|
||||
/* Verify state */
|
||||
if (i < ELEMENTSOF(expected_state))
|
||||
ASSERT_EQ(iovec_memcmp(&state, &IOVEC_MAKE(expected_state[i], sizeof(expected_state[i]))), 0);
|
||||
|
||||
/* Verify key */
|
||||
ASSERT_OK(fsprg_get_key(&state, &key));
|
||||
if (i < ELEMENTSOF(expected_key))
|
||||
ASSERT_EQ(iovec_memcmp(&key, &IOVEC_MAKE(expected_key[i], sizeof(expected_key[i]))), 0);
|
||||
|
||||
/* Verify epoch */
|
||||
uint64_t epoch;
|
||||
ASSERT_OK(fsprg_get_epoch(&state, &epoch));
|
||||
ASSERT_EQ(epoch, (uint64_t) i);
|
||||
|
||||
if (iovec_is_set(&states[i]))
|
||||
ASSERT_EQ(iovec_memcmp(&state, &states[i]), 0);
|
||||
else
|
||||
ASSERT_NOT_NULL(iovec_memdup(&state, &states[i]));
|
||||
}
|
||||
|
||||
/* Generate state by fsprg_generate_state(0) */
|
||||
ASSERT_OK(fsprg_generate_state(FSPRG_RECOMMENDED_SECPAR, 0, &seed, &state));
|
||||
ASSERT_EQ(iovec_memcmp(&state, &states[0]), 0);
|
||||
|
||||
/* Generate states by fsprg_evolve() */
|
||||
for (unsigned i = 1; i < n_states; i++) {
|
||||
ASSERT_OK(fsprg_evolve(&state));
|
||||
ASSERT_EQ(iovec_memcmp(&state, &states[i]), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(hmac) {
|
||||
/* This emulates what journald and journalctl does.
|
||||
* 1. journalctl generates random seed, calculate initial state, and write the state in
|
||||
* /var/log/journal/$MACHINE_ID/fss.
|
||||
* 2. journald loads the fss file when a new journal file is created by journal_file_fss_load().
|
||||
* 3. Allocate HMAC with SHA256 by journal_file_hmac_setup().
|
||||
* 4. Write inital tag in journal file by journal_file_append_first_tag().
|
||||
* 5. For each journal entry,
|
||||
* - initialize HMAC with fsprg key by journal_file_hmac_start(),
|
||||
* - put each object data to the HMAC by journal_file_hmac_put_object(),
|
||||
* - finalize HMAC and write the value with the fsprg epoch to a tag object by
|
||||
* journal_file_maybe_append_tag(). */
|
||||
|
||||
size_t n_tags = 20;
|
||||
struct iovec *tags = new0(struct iovec, n_tags);
|
||||
CLEANUP_ARRAY(tags, n_tags, iovec_array_free);
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
if (initialize_libgcrypt(false) >= 0) {
|
||||
struct iovec seed = IOVEC_ALLOCA(FSPRG_RECOMMENDED_SEEDLEN),
|
||||
msk = IOVEC_ALLOCA(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
mpk = IOVEC_ALLOCA(FSPRG_mpkinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
state = IOVEC_ALLOCA(FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR)),
|
||||
key = IOVEC_ALLOCA(KEY_LENGTH),
|
||||
tag = IOVEC_ALLOCA(TAG_LENGTH);
|
||||
|
||||
generate_seed(&seed);
|
||||
|
||||
/* Generate secret keys */
|
||||
ASSERT_OK(FSPRG_GenMK(msk.iov_base, mpk.iov_base, seed.iov_base, seed.iov_len, FSPRG_RECOMMENDED_SECPAR));
|
||||
|
||||
/* Calculate initial state */
|
||||
ASSERT_OK(FSPRG_GenState0(state.iov_base, mpk.iov_base, seed.iov_base, seed.iov_len));
|
||||
|
||||
/* Allocate HMAC */
|
||||
_cleanup_(sym_gcry_md_closep) gcry_md_hd_t hmac = NULL;
|
||||
ASSERT_EQ(gcry_err_code(sym_gcry_md_open(&hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC)), (gcry_err_code_t) GPG_ERR_NO_ERROR);
|
||||
|
||||
for (size_t i = 0; i < n_tags; i++) {
|
||||
/* Reset the previous state */
|
||||
sym_gcry_md_reset(hmac);
|
||||
|
||||
/* Initialize HMAC with fsprg key */
|
||||
ASSERT_OK(FSPRG_GetKey(state.iov_base, key.iov_base, key.iov_len, 0));
|
||||
ASSERT_EQ(gcry_err_code(sym_gcry_md_setkey(hmac, key.iov_base, key.iov_len)), (gcry_err_code_t) GPG_ERR_NO_ERROR);
|
||||
|
||||
/* Put dummy data */
|
||||
_cleanup_free_ char *str = ASSERT_NOT_NULL(asprintf_safe("dummy data: %zu, hoge hoge hoge hoge hoge", i));
|
||||
sym_gcry_md_write(hmac, str, strlen(str));
|
||||
|
||||
/* Finalize HMAC and generate tag. */
|
||||
memcpy(tag.iov_base, sym_gcry_md_read(hmac, 0), tag.iov_len);
|
||||
|
||||
/* Verify tag */
|
||||
if (i < ELEMENTSOF(expected_tag))
|
||||
ASSERT_TRUE(iovec_equal(&tag, &IOVEC_MAKE(expected_tag[i], sizeof(expected_tag[i]))));
|
||||
|
||||
/* Save tag */
|
||||
ASSERT_NOT_NULL(iovec_memdup(&tag, &tags[i]));
|
||||
|
||||
/* Increment epoch */
|
||||
ASSERT_OK(FSPRG_Evolve(state.iov_base));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
if (dlopen_libcrypto(LOG_DEBUG) >= 0) {
|
||||
struct iovec seed = IOVEC_ALLOCA(FSPRG_RECOMMENDED_SEEDLEN),
|
||||
state = IOVEC_ALLOCA(fsprg_state_size(FSPRG_RECOMMENDED_SECPAR)),
|
||||
key = IOVEC_ALLOCA(KEY_LENGTH),
|
||||
tag = IOVEC_ALLOCA(TAG_LENGTH);
|
||||
|
||||
generate_seed(&seed);
|
||||
|
||||
/* Calculate initial state */
|
||||
ASSERT_OK(fsprg_generate_state(FSPRG_RECOMMENDED_SECPAR, 0, &seed, &state));
|
||||
|
||||
/* Allocate HMAC */
|
||||
_cleanup_(EVP_MAC_freep) EVP_MAC *hmac = ASSERT_NOT_NULL(sym_EVP_MAC_fetch(NULL, "HMAC", NULL));
|
||||
_cleanup_(EVP_MAC_CTX_freep) EVP_MAC_CTX *hmac_ctx = ASSERT_NOT_NULL(sym_EVP_MAC_CTX_new(hmac));
|
||||
_cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = ASSERT_NOT_NULL(sym_OSSL_PARAM_BLD_new());
|
||||
ASSERT_OK_POSITIVE(sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_MAC_PARAM_DIGEST, "SHA256", 0));
|
||||
_cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = ASSERT_NOT_NULL(sym_OSSL_PARAM_BLD_to_param(bld));
|
||||
|
||||
for (size_t i = 0; i < n_tags; i++) {
|
||||
/* Initialize HMAC with fsprg key */
|
||||
ASSERT_OK(fsprg_get_key(&state, &key));
|
||||
ASSERT_OK_POSITIVE(sym_EVP_MAC_init(hmac_ctx, key.iov_base, key.iov_len, params));
|
||||
|
||||
/* Put dummy data */
|
||||
_cleanup_(iovec_done) struct iovec data =
|
||||
IOVEC_MAKE_STRING(ASSERT_NOT_NULL(asprintf_safe("dummy data: %zu, hoge hoge hoge hoge hoge", i)));
|
||||
ASSERT_OK_POSITIVE(sym_EVP_MAC_update(hmac_ctx, data.iov_base, data.iov_len));
|
||||
|
||||
/* Finalize HMAC and generate tag. */
|
||||
size_t len;
|
||||
ASSERT_OK_POSITIVE(sym_EVP_MAC_final(hmac_ctx, tag.iov_base, &len, tag.iov_len));
|
||||
ASSERT_EQ(len, tag.iov_len);
|
||||
|
||||
/* Verify tag */
|
||||
if (i < ELEMENTSOF(expected_tag))
|
||||
ASSERT_TRUE(iovec_equal(&tag, &IOVEC_MAKE(expected_tag[i], sizeof(expected_tag[i]))));
|
||||
|
||||
/* Compare with the tag generated by gcrypt */
|
||||
if (iovec_is_set(&tags[i]))
|
||||
ASSERT_TRUE(iovec_equal(&tag, &tags[i]));
|
||||
|
||||
/* Increment epoch */
|
||||
ASSERT_OK(fsprg_evolve(&state));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
if (DLOPEN_GCRYPT(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED) < 0 &&
|
||||
DLOPEN_LIBCRYPTO(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED) < 0)
|
||||
return EXIT_TEST_SKIP;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);
|
||||
@@ -5,8 +5,8 @@ set -o pipefail
|
||||
|
||||
# Forward Secure Sealing
|
||||
|
||||
if ! journalctl --version | grep -F +GCRYPT >/dev/null; then
|
||||
echo "Built without gcrypt, skipping the FSS tests"
|
||||
if ! journalctl --version | grep -F +OPENSSL >/dev/null; then
|
||||
echo "Built without openssl, skipping the FSS tests"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user