1
0
mirror of https://github.com/systemd/systemd synced 2026-04-23 07:24:51 +02:00

Compare commits

...

14 Commits

Author SHA1 Message Date
Yu Watanabe
06fb09cf40
Merge pull request #22765 from medhefgo/test
test: Use TEST macros in more places
2022-03-17 03:07:36 +09:00
Lennart Poettering
deb5c820ca sd-boot: disable bitlocker reboot feature for now
Conceptually the feature is great and should exist, but in its current
form should be worked to be generic (i.e. not specific to
Windows/Bitlocker, but appliable to any boot entry), not be global (but
be a per-entry thing), not require a BootXXXX entry to exist, and not
check for the BitLocker signature (as TPMs are not just used for
BitLocker).

Since we want to get 251 released, mark it in the documentation, in NEWS
and in code as experimental and make clear it will be reworked in a
future release. Also, make it opt-in to make it less likely people come
to rely on it without reading up on it, and understanding that it will
likely change sooner or later.

Follow-up for: #22043
See: #22390
2022-03-16 18:39:57 +01:00
Lennart Poettering
c2c7eea1e9
Merge pull request #22563 from grigorig/cryptenroll-tpm2-pin
sd-cryptenroll TPM2 PIN protected unlock
2022-03-16 18:04:28 +01:00
Jan Janssen
b405e3aae1 test-journal-syslog: Add some valid priority cases 2022-03-16 14:50:12 +01:00
Jan Janssen
3df208468f test: Use C11 UTF-16 string literal 2022-03-16 14:50:12 +01:00
Jan Janssen
68da8adf54 test: Use TEST macros in more places 2022-03-16 14:50:12 +01:00
Grigori Goronzy
fd8b924820 cryptenroll: add tests for TPM2 unlocking
Add tests for enrolling and unlocking. Various cases are tested:

- Default PCR 7 policy w/o PIN, good and bad cases (wrong PCR)
- PCR 7 + PIN policy, good and bad cases (wrong PCR, wrong PIN)
- Non-default PCR 0+7 policy w/o PIN, good and bad cases (wrong PCR 0)

v2: rename test, fix tss2 library installation, fix CI failures
v3: fix ppc64, load module
2022-03-15 21:17:00 +01:00
Grigori Goronzy
4005d41ef0 cryptsetup: add manual TPM2 PIN configuration
Handle the case where TPM2 metadata is not available and explicitly
provided in crypttab. This adds a new "tpm2-pin" option to crypttab
options for this purpose.
2022-03-15 21:17:00 +01:00
Grigori Goronzy
caeb5604f9 cryptenroll: add TPM2 PIN documentation 2022-03-15 21:17:00 +01:00
Grigori Goronzy
1f895adac2 cryptsetup: add libcryptsetup TPM2 PIN support
This is unfinished: we don't have any way to actually query for PINs
interactively this way. It is similar to FIDO2 and PKCS#11 in this
regard.

Nonetheless, this code is capable of validating and dumping tokens, so
it is already useful as-is.
2022-03-15 21:17:00 +01:00
Grigori Goronzy
bea344a1a4 cryptsetup: add support for TPM2 pin
Extend cryptsetup for TPM2 pin entry, similar to FIDO2.
2022-03-15 21:17:00 +01:00
Grigori Goronzy
6c7a168105 cryptenroll: add support for TPM2 pin
Add support for PIN enrollment with TPM2. A new "tpm2-pin" field is
introduced into metadata to signal that the policy needs to include a
PIN.

v2: fix tpm2_make_luks2_json in sd-repart
2022-03-15 21:17:00 +01:00
Grigori Goronzy
2f5a892aa0 tpm2: support policies with PIN
Modify TPM2 authentication policy to optionally include an authValue, i.e.
a password/PIN. We use the "PIN" terminology since it's used by other
systems such as Windows, even though the PIN is not necessarily numeric.

The pin is hashed via SHA256 to allow for arbitrary length PINs.

v2: fix tpm2_seal in sd-repart
v3: applied review feedback
2022-03-15 21:17:00 +01:00
Grigori Goronzy
e560cf4f71 hmac/sha256: move size define to sha256.h 2022-03-15 21:17:00 +01:00
60 changed files with 779 additions and 535 deletions

11
NEWS
View File

@ -52,6 +52,17 @@ CHANGES WITH 251:
or ID field of /etc/os-release or another suitable identifier before
deploying the image.
* sd-boot gained a new *experimental* setting "reboot-for-bitlocker" in
loader.conf that implements booting Microsoft Windows from the
sd-boot in a way that first reboots the system, to reset the TPM
PCRs. This improves compatibility with BitLocker's TPM use, as the
PCRs will only record the Windows boot process, and not sd-boot
itself, thus retaining the PCR measurements not involving
sd-boot. Note that this feature is experimental for now, and is
likely going to be generalized, renamed and removed in its current
form in a future release, without retaining compatibility with its
current implementation.
* The --make-machine-id-directory= switch to bootctl has been replaced
by --make-entry-directory=, given that the entry directory is not
necessarily named after the machine ID, but after some other suitable

View File

@ -677,6 +677,14 @@
of the current PCR state.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>tpm2-pin=</option></term>
<listitem><para>Takes a boolean argument, defaults to <literal>false</literal>. Controls whether
TPM2 volume unlocking is bound to a PIN in addition to PCRs. Similarly, this option is only useful
when TPM2 enrollment metadata is not available.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>token-timeout=</option></term>

View File

@ -206,8 +206,11 @@
<varlistentry>
<term>reboot-for-bitlocker</term>
<listitem><para>Work around BitLocker requiring a recovery key when the boot loader was
updated (enabled by default).</para>
<listitem><para>Caveat: This feature is experimental, and is likely to be changed (or removed in its
current form) in a future version of systemd.</para>
<para>Work around BitLocker requiring a recovery key when the boot loader was
updated (disabled by default).</para>
<para>Try to detect BitLocker encrypted drives along with an active TPM. If both are found
and Windows Boot Manager is selected in the boot menu, set the <literal>BootNext</literal>

View File

@ -299,6 +299,24 @@
signatures likely will validate against pre-existing certificates.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--tpm2-with-pin=</option><replaceable>BOOL</replaceable></term>
<listitem><para>When enrolling a TPM2 device, controls whether to require the user to enter a PIN
when unlocking the volume in addition to PCR binding, based on TPM2 policy authentication. Defaults
to <literal>no</literal>. Despite being called PIN, any character can be used, not just numbers.
</para>
<para>Note that incorrect PIN entry when unlocking increments the
TPM dictionary attack lockout mechanism, and may lock out users for a prolonged time, depending on
its configuration. The lockout mechanism is a global property of the TPM,
<command>systemd-cryptenroll</command> does not control or configure the lockout mechanism. You may
use tpm2-tss tools to inspect or configure the dictionary attack lockout, with
<citerefentry><refentrytitle>tpm2_getcap</refentrytitle><manvolnum>1</manvolnum></citerefentry> and
<citerefentry><refentrytitle>tpm2_dictionarylockout</refentrytitle><manvolnum>1</manvolnum></citerefentry>
commands, respectively.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--wipe-slot=</option><arg rep="repeat">SLOT</arg></term>

View File

@ -3,7 +3,7 @@
#include "analyze-verify-util.h"
#include "tests.h"
static void test_verify_nonexistent(void) {
TEST(verify_nonexistent) {
/* Negative cases */
assert_se(verify_executable(NULL, &(ExecCommand) {.flags = EXEC_COMMAND_IGNORE_FAILURE, .path = (char*) "/non/existent"}, NULL) == 0);
assert_se(verify_executable(NULL, &(ExecCommand) {.path = (char*) "/non/existent"}, NULL) < 0);
@ -13,8 +13,4 @@ static void test_verify_nonexistent(void) {
assert_se(verify_executable(NULL, &(ExecCommand) {.flags = EXEC_COMMAND_IGNORE_FAILURE, .path = (char*) "/bin/echo"}, NULL) == 0);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_verify_nonexistent();
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -4,7 +4,7 @@
#include <stdint.h>
#include <stdlib.h>
#define SHA256_DIGEST_SIZE 32
#include "sha256.h"
/* Unoptimized implementation based on FIPS 198. 'res' has to be allocated by
* the caller. Prefer external OpenSSL functions, and use this only when

View File

@ -1549,7 +1549,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
.editor = TRUE,
.auto_entries = TRUE,
.auto_firmware = TRUE,
.reboot_for_bitlocker = TRUE,
.reboot_for_bitlocker = FALSE,
.random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN,
.idx_default_efivar = IDX_INVALID,
.console_mode = CONSOLE_MODE_KEEP,
@ -1983,6 +1983,9 @@ static EFI_STATUS boot_windows_bitlocker(void) {
UINTN n_handles;
EFI_STATUS err;
// FIXME: Experimental for now. Should be generalized, and become a per-entry option that can be
// enabled independently of BitLocker, and without a BootXXXX entry pre-existing.
/* BitLocker key cannot be sealed without a TPM present. */
if (!tpm_present())
return EFI_NOT_FOUND;

View File

@ -39,8 +39,7 @@ static void test_get_bcd_title_one(
}
TEST(get_bcd_title) {
const char16_t win10[] = { 'W', 'i', 'n', 'd', 'o', 'w', 's', ' ', '1', '0', '\0' };
test_get_bcd_title_one("test-bcd/win10.bcd.zst", win10, sizeof(win10));
test_get_bcd_title_one("test-bcd/win10.bcd.zst", u"Windows 10", sizeof(u"Windows 10"));
test_get_bcd_title_one("test-bcd/description-bad-type.bcd.zst", NULL, 0);
test_get_bcd_title_one("test-bcd/description-empty.bcd.zst", NULL, 0);

View File

@ -313,7 +313,7 @@ static int on_path(const char *path, void *userdata) {
return 0;
}
static void test_introspect_on_path(void) {
TEST(introspect_on_path) {
static const XMLIntrospectOps ops = {
.on_path = on_path,
};
@ -321,8 +321,6 @@ static void test_introspect_on_path(void) {
_cleanup_set_free_ Set *paths = NULL;
_cleanup_free_ char **l = NULL;
log_info("/* %s */", __func__);
assert_se(set_put_strdup(&paths, "/") > 0);
log_debug("/* parse_xml_introspect(\"/\") */");
@ -363,10 +361,4 @@ static void test_introspect_on_path(void) {
assert_se(strv_equal(l, expected));
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_introspect_on_path();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -1,7 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "ask-password-api.h"
#include "cryptenroll-tpm2.h"
#include "env-util.h"
#include "hexdecoct.h"
#include "json.h"
#include "memory-util.h"
@ -58,11 +60,78 @@ static int search_policy_hash(
return -ENOENT; /* Not found */
}
static int get_pin(char **ret_pin_str, TPM2Flags *ret_flags) {
_cleanup_free_ char *pin_str = NULL;
int r;
TPM2Flags flags = 0;
assert(ret_pin_str);
assert(ret_flags);
r = getenv_steal_erase("NEWPIN", &pin_str);
if (r < 0)
return log_error_errno(r, "Failed to acquire PIN from environment: %m");
if (r > 0)
flags |= TPM2_FLAGS_USE_PIN;
else {
for (size_t i = 5;; i--) {
_cleanup_strv_free_erase_ char **pin = NULL, **pin2 = NULL;
if (i <= 0)
return log_error_errno(
SYNTHETIC_ERRNO(ENOKEY), "Too many attempts, giving up.");
pin = strv_free_erase(pin);
r = ask_password_auto(
"Please enter TPM2 PIN:",
"drive-harddisk",
NULL,
"tpm2-pin",
"cryptenroll.tpm2-pin",
USEC_INFINITY,
0,
&pin);
if (r < 0)
return log_error_errno(r, "Failed to ask for user pin: %m");
assert(strv_length(pin) == 1);
r = ask_password_auto(
"Please enter TPM2 PIN (repeat):",
"drive-harddisk",
NULL,
"tpm2-pin",
"cryptenroll.tpm2-pin",
USEC_INFINITY,
0,
&pin2);
if (r < 0)
return log_error_errno(r, "Failed to ask for user pin: %m");
assert(strv_length(pin) == 1);
if (strv_equal(pin, pin2)) {
pin_str = strdup(*pin);
if (!pin_str)
return log_oom();
flags |= TPM2_FLAGS_USE_PIN;
break;
}
log_error("PINs didn't match, please try again!");
}
}
*ret_flags = flags;
*ret_pin_str = TAKE_PTR(pin_str);
return 0;
}
int enroll_tpm2(struct crypt_device *cd,
const void *volume_key,
size_t volume_key_size,
const char *device,
uint32_t pcr_mask) {
uint32_t pcr_mask,
bool use_pin) {
_cleanup_(erase_and_freep) void *secret = NULL, *secret2 = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
@ -71,7 +140,9 @@ int enroll_tpm2(struct crypt_device *cd,
_cleanup_free_ void *blob = NULL, *hash = NULL;
uint16_t pcr_bank, primary_alg;
const char *node;
_cleanup_(erase_and_freep) char *pin_str = NULL;
int r, keyslot;
TPM2Flags flags = 0;
assert(cd);
assert(volume_key);
@ -80,7 +151,13 @@ int enroll_tpm2(struct crypt_device *cd,
assert_se(node = crypt_get_device_name(cd));
r = tpm2_seal(device, pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg);
if (use_pin) {
r = get_pin(&pin_str, &flags);
if (r < 0)
return r;
}
r = tpm2_seal(device, pcr_mask, pin_str, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg);
if (r < 0)
return r;
@ -97,7 +174,7 @@ int enroll_tpm2(struct crypt_device *cd,
/* Quick verification that everything is in order, we are not in a hurry after all. */
log_debug("Unsealing for verification...");
r = tpm2_unseal(device, pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, &secret2, &secret2_size);
r = tpm2_unseal(device, pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, pin_str, &secret2, &secret2_size);
if (r < 0)
return r;
@ -123,7 +200,7 @@ int enroll_tpm2(struct crypt_device *cd,
if (keyslot < 0)
return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node);
r = tpm2_make_luks2_json(keyslot, pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, &v);
r = tpm2_make_luks2_json(keyslot, pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, flags, &v);
if (r < 0)
return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");

View File

@ -7,9 +7,9 @@
#include "log.h"
#if HAVE_TPM2
int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t pcr_mask);
int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t pcr_mask, bool use_pin);
#else
static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t pcr_mask) {
static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t pcr_mask, bool use_pin) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 key enrollment not supported.");
}

View File

@ -32,6 +32,7 @@ static char *arg_pkcs11_token_uri = NULL;
static char *arg_fido2_device = NULL;
static char *arg_tpm2_device = NULL;
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
static bool arg_tpm2_pin = false;
static char *arg_node = NULL;
static int *arg_wipe_slots = NULL;
static size_t arg_n_wipe_slots = 0;
@ -100,6 +101,8 @@ static int help(void) {
" Enroll a TPM2 device\n"
" --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
" Specify TPM2 PCRs to seal against\n"
" --tpm2-with-pin=BOOL\n"
" Whether to require entering a PIN to unlock the volume\n"
" --wipe-slot=SLOT1,SLOT2,…\n"
" Wipe specified slots\n"
"\nSee the %s for details.\n",
@ -121,6 +124,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_FIDO2_DEVICE,
ARG_TPM2_DEVICE,
ARG_TPM2_PCRS,
ARG_TPM2_PIN,
ARG_WIPE_SLOT,
ARG_FIDO2_WITH_PIN,
ARG_FIDO2_WITH_UP,
@ -139,6 +143,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "fido2-with-user-verification", required_argument, NULL, ARG_FIDO2_WITH_UV },
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
{ "tpm2-with-pin", required_argument, NULL, ARG_TPM2_PIN },
{ "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT },
{}
};
@ -301,6 +306,14 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_TPM2_PIN: {
r = parse_boolean_argument("--tpm2-with-pin=", optarg, &arg_tpm2_pin);
if (r < 0)
return r;
break;
}
case ARG_WIPE_SLOT: {
const char *p = optarg;
@ -558,7 +571,7 @@ static int run(int argc, char *argv[]) {
break;
case ENROLL_TPM2:
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask);
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask, arg_tpm2_pin);
break;
case _ENROLL_TYPE_INVALID:

View File

@ -6,8 +6,10 @@
#include "cryptsetup-token.h"
#include "cryptsetup-token-util.h"
#include "hexdecoct.h"
#include "json.h"
#include "luks2-tpm2.h"
#include "memory-util.h"
#include "strv.h"
#include "tpm2-util.h"
#include "version.h"
@ -78,7 +80,8 @@ _public_ int cryptsetup_token_open(
if (usrptr)
params = *(systemd_tpm2_plugin_params *)usrptr;
r = parse_luks2_tpm2_data(json, params.search_pcr_mask, &pcr_mask, &pcr_bank, &primary_alg, &base64_blob, &hex_policy_hash);
TPM2Flags flags = 0;
r = parse_luks2_tpm2_data(json, params.search_pcr_mask, &pcr_mask, &pcr_bank, &primary_alg, &base64_blob, &hex_policy_hash, &flags);
if (r < 0)
return log_debug_open_error(cd, r);
@ -101,6 +104,7 @@ _public_ int cryptsetup_token_open(
blob_size,
policy_hash,
policy_hash_size,
flags,
&decrypted_key,
&decrypted_key_size);
if (r < 0)
@ -135,6 +139,7 @@ _public_ void cryptsetup_token_dump(
const char *json /* validated 'systemd-tpm2' token if cryptsetup_token_validate is defined */) {
int r;
TPM2Flags flags = 0;
uint32_t pcr_mask;
uint16_t pcr_bank, primary_alg;
size_t decoded_blob_size;
@ -144,7 +149,7 @@ _public_ void cryptsetup_token_dump(
assert(json);
r = parse_luks2_tpm2_data(json, UINT32_MAX, &pcr_mask, &pcr_bank, &primary_alg, &base64_blob, &hex_policy_hash);
r = parse_luks2_tpm2_data(json, UINT32_MAX, &pcr_mask, &pcr_bank, &primary_alg, &base64_blob, &hex_policy_hash, &flags);
if (r < 0)
return (void) crypt_log_debug_errno(cd, r, "Failed to parse " TOKEN_NAME " metadata: %m.");
@ -171,6 +176,7 @@ _public_ void cryptsetup_token_dump(
crypt_log(cd, "\ttpm2-primary-alg: %s\n", strna(tpm2_primary_alg_to_string(primary_alg)));
crypt_log(cd, "\ttpm2-blob: %s\n", blob_str);
crypt_log(cd, "\ttpm2-policy-hash:" CRYPT_DUMP_LINE_SEP "%s\n", policy_hash_str);
crypt_log(cd, "\ttpm2-pin: %s\n", true_false(flags & TPM2_FLAGS_USE_PIN));
}
/*
@ -268,5 +274,13 @@ _public_ int cryptsetup_token_validate(
if (r < 0)
return crypt_log_debug_errno(cd, r, "Invalid base64 data in 'tpm2-policy-hash' field: %m");
w = json_variant_by_key(v, "tpm2-pin");
if (w) {
if (!json_variant_is_boolean(w)) {
crypt_log_debug(cd, "TPM2 PIN policy is not a boolean.");
return 1;
}
}
return 0;
}

View File

@ -1,11 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "ask-password-api.h"
#include "env-util.h"
#include "hexdecoct.h"
#include "json.h"
#include "log.h"
#include "luks2-tpm2.h"
#include "parse-util.h"
#include "random-util.h"
#include "strv.h"
#include "tpm2-util.h"
int acquire_luks2_key(
@ -17,10 +21,12 @@ int acquire_luks2_key(
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
TPM2Flags flags,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
_cleanup_free_ char *auto_device = NULL;
_cleanup_(erase_and_freep) char *pin_str = NULL;
int r;
assert(ret_decrypted_key);
@ -36,12 +42,22 @@ int acquire_luks2_key(
device = auto_device;
}
r = getenv_steal_erase("PIN", &pin_str);
if (r < 0)
return log_error_errno(r, "Failed to acquire PIN from environment: %m");
if (!r) {
/* PIN entry is not supported by plugin, let it fallback, possibly to sd-cryptsetup's
* internal handling. */
if (flags & TPM2_FLAGS_USE_PIN)
return -EOPNOTSUPP;
}
return tpm2_unseal(
device,
pcr_mask, pcr_bank,
primary_alg,
key_data, key_data_size,
policy_hash, policy_hash_size,
policy_hash, policy_hash_size, pin_str,
ret_decrypted_key, ret_decrypted_key_size);
}
@ -53,7 +69,8 @@ int parse_luks2_tpm2_data(
uint16_t *ret_pcr_bank,
uint16_t *ret_primary_alg,
char **ret_base64_blob,
char **ret_hex_policy_hash) {
char **ret_hex_policy_hash,
TPM2Flags *ret_flags) {
int r;
JsonVariant *w, *e;
@ -61,6 +78,7 @@ int parse_luks2_tpm2_data(
uint16_t pcr_bank = UINT16_MAX, primary_alg = TPM2_ALG_ECC;
_cleanup_free_ char *base64_blob = NULL, *hex_policy_hash = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
TPM2Flags flags = 0;
assert(json);
assert(ret_pcr_mask);
@ -138,11 +156,21 @@ int parse_luks2_tpm2_data(
if (!hex_policy_hash)
return -ENOMEM;
w = json_variant_by_key(v, "tpm2-pin");
if (w) {
if (!json_variant_is_boolean(w))
return -EINVAL;
if (json_variant_boolean(w))
flags |= TPM2_FLAGS_USE_PIN;
}
*ret_pcr_mask = pcr_mask;
*ret_pcr_bank = pcr_bank;
*ret_primary_alg = primary_alg;
*ret_base64_blob = TAKE_PTR(base64_blob);
*ret_hex_policy_hash = TAKE_PTR(hex_policy_hash);
*ret_flags = flags;
return 0;
}

View File

@ -2,6 +2,8 @@
#pragma once
#include "tpm2-util.h"
struct crypt_device;
int acquire_luks2_key(
@ -13,6 +15,7 @@ int acquire_luks2_key(
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
TPM2Flags flags,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size);
@ -23,4 +26,5 @@ int parse_luks2_tpm2_data(
uint16_t *ret_pcr_bank,
uint16_t *ret_primary_alg,
char **ret_base64_blob,
char **ret_hex_policy_hash);
char **ret_hex_policy_hash,
TPM2Flags *ret_flags);

View File

@ -1,7 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "ask-password-api.h"
#include "cryptsetup-tpm2.h"
#include "env-util.h"
#include "fileio.h"
#include "hexdecoct.h"
#include "json.h"
@ -9,6 +11,47 @@
#include "random-util.h"
#include "tpm2-util.h"
static int get_pin(usec_t until, AskPasswordFlags ask_password_flags, bool headless, char **ret_pin_str) {
_cleanup_free_ char *pin_str = NULL;
_cleanup_strv_free_erase_ char **pin = NULL;
int r;
assert(ret_pin_str);
r = getenv_steal_erase("PIN", &pin_str);
if (r < 0)
return log_error_errno(r, "Failed to acquire PIN from environment: %m");
if (!r) {
if (headless)
return log_error_errno(
SYNTHETIC_ERRNO(ENOPKG),
"PIN querying disabled via 'headless' option. "
"Use the '$PIN' environment variable.");
pin = strv_free_erase(pin);
r = ask_password_auto(
"Please enter TPM2 PIN:",
"drive-harddisk",
NULL,
"tpm2-pin",
"cryptsetup.tpm2-pin",
until,
ask_password_flags,
&pin);
if (r < 0)
return log_error_errno(r, "Failed to ask for user pin: %m");
assert(strv_length(pin) == 1);
pin_str = strdup(pin[0]);
if (!pin_str)
return log_oom();
}
*ret_pin_str = TAKE_PTR(pin_str);
return r;
}
int acquire_tpm2_key(
const char *volume_name,
const char *device,
@ -22,6 +65,10 @@ int acquire_tpm2_key(
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
TPM2Flags flags,
usec_t until,
bool headless,
AskPasswordFlags ask_password_flags,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
@ -64,7 +111,51 @@ int acquire_tpm2_key(
blob = loaded_blob;
}
return tpm2_unseal(device, pcr_mask, pcr_bank, primary_alg, blob, blob_size, policy_hash, policy_hash_size, ret_decrypted_key, ret_decrypted_key_size);
if (!(flags & TPM2_FLAGS_USE_PIN))
return tpm2_unseal(
device,
pcr_mask,
pcr_bank,
primary_alg,
blob,
blob_size,
policy_hash,
policy_hash_size,
NULL,
ret_decrypted_key,
ret_decrypted_key_size);
for (int i = 5;; i--) {
_cleanup_(erase_and_freep) char *pin_str = NULL;
if (i <= 0)
return -EACCES;
r = get_pin(until, ask_password_flags, headless, &pin_str);
if (r < 0)
return r;
r = tpm2_unseal(
device,
pcr_mask,
pcr_bank,
primary_alg,
blob,
blob_size,
policy_hash,
policy_hash_size,
pin_str,
ret_decrypted_key,
ret_decrypted_key_size);
/* We get this error in case there is an authentication policy mismatch. This should
* not happen, but this avoids confusing behavior, just in case. */
if (IN_SET(r, -EPERM, -ENOLCK))
return r;
if (r < 0)
continue;
return r;
}
}
int find_tpm2_auto_data(
@ -79,11 +170,13 @@ int find_tpm2_auto_data(
void **ret_policy_hash,
size_t *ret_policy_hash_size,
int *ret_keyslot,
int *ret_token) {
int *ret_token,
TPM2Flags *ret_flags) {
_cleanup_free_ void *blob = NULL, *policy_hash = NULL;
size_t blob_size = 0, policy_hash_size = 0;
int r, keyslot = -1, token = -1;
TPM2Flags flags = 0;
uint32_t pcr_mask = 0;
uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
@ -196,6 +289,16 @@ int find_tpm2_auto_data(
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid base64 data in 'tpm2-policy-hash' field.");
w = json_variant_by_key(v, "tpm2-pin");
if (w) {
if (!json_variant_is_boolean(w))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"TPM2 PIN policy is not a boolean.");
if (json_variant_boolean(w))
flags |= TPM2_FLAGS_USE_PIN;
}
break;
}
@ -215,6 +318,7 @@ int find_tpm2_auto_data(
*ret_token = token;
*ret_pcr_bank = pcr_bank;
*ret_primary_alg = primary_alg;
*ret_flags = flags;
return 0;
}

View File

@ -3,9 +3,11 @@
#include <sys/types.h>
#include "ask-password-api.h"
#include "cryptsetup-util.h"
#include "log.h"
#include "time-util.h"
#include "tpm2-util.h"
#if HAVE_TPM2
@ -22,6 +24,10 @@ int acquire_tpm2_key(
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
TPM2Flags flags,
usec_t until,
bool headless,
AskPasswordFlags ask_password_flags,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size);
@ -37,7 +43,8 @@ int find_tpm2_auto_data(
void **ret_policy_hash,
size_t *ret_policy_hash_size,
int *ret_keyslot,
int *ret_token);
int *ret_token,
TPM2Flags *ret_flags);
#else
@ -54,6 +61,10 @@ static inline int acquire_tpm2_key(
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
TPM2Flags flags,
usec_t until,
bool headless,
AskPasswordFlags ask_password_flags,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
@ -73,7 +84,8 @@ static inline int find_tpm2_auto_data(
void **ret_policy_hash,
size_t *ret_policy_hash_size,
int *ret_keyslot,
int *ret_token) {
int *ret_token,
TPM2Flags *ret_flags) {
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support not available.");

View File

@ -82,6 +82,7 @@ static char *arg_fido2_rp_id = NULL;
static char *arg_tpm2_device = NULL;
static bool arg_tpm2_device_auto = false;
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
static bool arg_tpm2_pin = false;
static bool arg_headless = false;
static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
@ -387,6 +388,16 @@ static int parse_one_option(const char *option) {
arg_tpm2_pcr_mask |= mask;
}
} else if ((val = startswith(option, "tpm2-pin="))) {
r = parse_boolean(val);
if (r < 0) {
log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
return 0;
}
arg_tpm2_pin = r;
} else if ((val = startswith(option, "try-empty-password="))) {
r = parse_boolean(val);
@ -1301,9 +1312,15 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
key_file, arg_keyfile_size, arg_keyfile_offset,
key_data, key_data_size,
NULL, 0, /* we don't know the policy hash */
arg_tpm2_pin,
until,
arg_headless,
arg_ask_password_flags,
&decrypted_key, &decrypted_key_size);
if (r >= 0)
break;
if (IN_SET(r, -EACCES, -ENOLCK))
return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */
@ -1335,6 +1352,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
for (;;) {
uint32_t pcr_mask;
uint16_t pcr_bank, primary_alg;
TPM2Flags tpm2_flags;
r = find_tpm2_auto_data(
cd,
@ -1346,7 +1364,8 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
&blob, &blob_size,
&policy_hash, &policy_hash_size,
&keyslot,
&token);
&token,
&tpm2_flags);
if (r == -ENXIO)
/* No further TPM2 tokens found in the LUKS2 header. */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
@ -1369,7 +1388,13 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
NULL, 0, 0, /* no key file */
blob, blob_size,
policy_hash, policy_hash_size,
tpm2_flags,
until,
arg_headless,
arg_ask_password_flags,
&decrypted_key, &decrypted_key_size);
if (IN_SET(r, -EACCES, -ENOLCK))
return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
if (r != -EPERM)
break;

View File

@ -8,6 +8,8 @@
#include "types-fundamental.h"
#define SHA256_DIGEST_SIZE 32
struct sha256_ctx {
uint32_t H[8];

View File

@ -3,6 +3,7 @@
#include <stdbool.h>
#include "journald-server.h"
#include "tests.h"
#define _COMPRESS_PARSE_CHECK(str, enab, thresh, varname) \
do { \
@ -17,7 +18,7 @@
#define COMPRESS_PARSE_CHECK(str, enabled, threshold) \
_COMPRESS_PARSE_CHECK(str, enabled, threshold, conf##__COUNTER__)
static void test_config_compress(void) {
TEST(config_compress) {
COMPRESS_PARSE_CHECK("yes", true, 111);
COMPRESS_PARSE_CHECK("no", false, 111);
COMPRESS_PARSE_CHECK("y", true, 111);
@ -46,8 +47,4 @@ static void test_config_compress(void) {
COMPRESS_PARSE_CHECK("", true, UINT64_MAX);
}
int main(int argc, char *argv[]) {
test_config_compress();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -70,7 +70,7 @@ static void append_number(ManagedJournalFile *f, int n, uint64_t *seqnum) {
free(p);
}
static void test_check_number (sd_journal *j, int n) {
static void test_check_number(sd_journal *j, int n) {
const void *d;
_cleanup_free_ char *k;
size_t l;
@ -84,7 +84,7 @@ static void test_check_number (sd_journal *j, int n) {
assert_se(n == x);
}
static void test_check_numbers_down (sd_journal *j, int count) {
static void test_check_numbers_down(sd_journal *j, int count) {
int i;
for (i = 1; i <= count; i++) {
@ -99,7 +99,7 @@ static void test_check_numbers_down (sd_journal *j, int count) {
}
static void test_check_numbers_up (sd_journal *j, int count) {
static void test_check_numbers_up(sd_journal *j, int count) {
for (int i = count; i >= 1; i--) {
int r;
test_check_number(j, i);
@ -145,7 +145,7 @@ static void mkdtemp_chdir_chattr(char *path) {
(void) chattr_path(path, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
}
static void test_skip(void (*setup)(void)) {
static void test_skip_one(void (*setup)(void)) {
char t[] = "/var/tmp/journal-skip-XXXXXX";
sd_journal *j;
int r;
@ -201,8 +201,12 @@ static void test_skip(void (*setup)(void)) {
puts("------------------------------------------------------------");
}
static void test_sequence_numbers(void) {
TEST(skip) {
test_skip_one(setup_sequential);
test_skip_one(setup_interleaved);
}
TEST(sequence_numbers) {
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
char t[] = "/var/tmp/journal-seq-XXXXXX";
ManagedJournalFile *one, *two;
@ -287,19 +291,14 @@ static void test_sequence_numbers(void) {
}
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
static int intro(void) {
/* managed_journal_file_open requires a valid machine id */
if (access("/etc/machine-id", F_OK) != 0)
return log_tests_skipped("/etc/machine-id not found");
arg_keep = argc > 1;
arg_keep = saved_argc > 1;
test_skip(setup_sequential);
test_skip(setup_interleaved);
test_sequence_numbers();
return 0;
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);

View File

@ -5,8 +5,9 @@
#include "macro.h"
#include "string-util.h"
#include "syslog-util.h"
#include "tests.h"
static void test_syslog_parse_identifier(const char *str,
static void test_syslog_parse_identifier_one(const char *str,
const char *ident, const char *pid, const char *rest, int ret) {
const char *buf = str;
_cleanup_free_ char *ident2 = NULL, *pid2 = NULL;
@ -20,40 +21,50 @@ static void test_syslog_parse_identifier(const char *str,
assert_se(streq(buf, rest));
}
static void test_syslog_parse_priority(const char *str, int priority, int ret) {
const char *buf = str;
static void test_syslog_parse_priority_one(const char *str, bool with_facility, int priority, int ret) {
int priority2 = 0, ret2;
ret2 = syslog_parse_priority(&buf, &priority2, false);
ret2 = syslog_parse_priority(&str, &priority2, with_facility);
assert_se(ret == ret2);
if (ret2 == 1)
assert_se(priority == priority2);
}
int main(void) {
test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", "xxx", 11);
test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, "xxx", 6);
test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, " xxx", 6);
test_syslog_parse_identifier("pidu xxx", NULL, NULL, "pidu xxx", 0);
test_syslog_parse_identifier(" pidu xxx", NULL, NULL, " pidu xxx", 0);
test_syslog_parse_identifier("", NULL, NULL, "", 0);
test_syslog_parse_identifier(" ", NULL, NULL, " ", 0);
test_syslog_parse_identifier(":", "", NULL, "", 1);
test_syslog_parse_identifier(": ", "", NULL, " ", 2);
test_syslog_parse_identifier(" :", "", NULL, "", 2);
test_syslog_parse_identifier(" pidu:", "pidu", NULL, "", 8);
test_syslog_parse_identifier("pidu:", "pidu", NULL, "", 5);
test_syslog_parse_identifier("pidu: ", "pidu", NULL, "", 6);
test_syslog_parse_identifier("pidu : ", NULL, NULL, "pidu : ", 0);
test_syslog_parse_priority("<>", 0, 0);
test_syslog_parse_priority("<>aaa", 0, 0);
test_syslog_parse_priority("<aaaa>", 0, 0);
test_syslog_parse_priority("<aaaa>aaa", 0, 0);
test_syslog_parse_priority(" <aaaa>", 0, 0);
test_syslog_parse_priority(" <aaaa>aaa", 0, 0);
/* TODO: add test cases of valid priorities */
return 0;
TEST(syslog_parse_identifier) {
test_syslog_parse_identifier_one("pidu[111]: xxx", "pidu", "111", "xxx", 11);
test_syslog_parse_identifier_one("pidu: xxx", "pidu", NULL, "xxx", 6);
test_syslog_parse_identifier_one("pidu: xxx", "pidu", NULL, " xxx", 6);
test_syslog_parse_identifier_one("pidu xxx", NULL, NULL, "pidu xxx", 0);
test_syslog_parse_identifier_one(" pidu xxx", NULL, NULL, " pidu xxx", 0);
test_syslog_parse_identifier_one("", NULL, NULL, "", 0);
test_syslog_parse_identifier_one(" ", NULL, NULL, " ", 0);
test_syslog_parse_identifier_one(":", "", NULL, "", 1);
test_syslog_parse_identifier_one(": ", "", NULL, " ", 2);
test_syslog_parse_identifier_one(" :", "", NULL, "", 2);
test_syslog_parse_identifier_one(" pidu:", "pidu", NULL, "", 8);
test_syslog_parse_identifier_one("pidu:", "pidu", NULL, "", 5);
test_syslog_parse_identifier_one("pidu: ", "pidu", NULL, "", 6);
test_syslog_parse_identifier_one("pidu : ", NULL, NULL, "pidu : ", 0);
}
TEST(syslog_parse_priority) {
test_syslog_parse_priority_one("", false, 0, 0);
test_syslog_parse_priority_one("<>", false, 0, 0);
test_syslog_parse_priority_one("<>aaa", false, 0, 0);
test_syslog_parse_priority_one("<aaaa>", false, 0, 0);
test_syslog_parse_priority_one("<aaaa>aaa", false, 0, 0);
test_syslog_parse_priority_one(" <aaaa>", false, 0, 0);
test_syslog_parse_priority_one(" <aaaa>aaa", false, 0, 0);
test_syslog_parse_priority_one(" <aaaa>aaa", false, 0, 0);
test_syslog_parse_priority_one(" <1>", false, 0, 0);
test_syslog_parse_priority_one("<1>", false, 1, 1);
test_syslog_parse_priority_one("<7>", false, 7, 1);
test_syslog_parse_priority_one("<8>", false, 0, 0);
test_syslog_parse_priority_one("<9>", true, 9, 1);
test_syslog_parse_priority_one("<22>", true, 22, 1);
test_syslog_parse_priority_one("<111>", false, 0, 0);
test_syslog_parse_priority_one("<111>", true, 111, 1);
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -23,7 +23,7 @@ static void mkdtemp_chdir_chattr(char *path) {
(void) chattr_path(path, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
}
static void test_non_empty(void) {
TEST(non_empty) {
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
dual_timestamp ts;
ManagedJournalFile *f;
@ -34,8 +34,6 @@ static void test_non_empty(void) {
sd_id128_t fake_boot_id;
char t[] = "/var/tmp/journal-XXXXXX";
test_setup_logging(LOG_DEBUG);
m = mmap_cache_new();
assert_se(m != NULL);
@ -120,13 +118,11 @@ static void test_non_empty(void) {
puts("------------------------------------------------------------");
}
static void test_empty(void) {
TEST(empty) {
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
ManagedJournalFile *f1, *f2, *f3, *f4;
char t[] = "/var/tmp/journal-XXXXXX";
test_setup_logging(LOG_DEBUG);
m = mmap_cache_new();
assert_se(m != NULL);
@ -177,8 +173,6 @@ static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
assert_se(data_size <= sizeof(data));
test_setup_logging(LOG_DEBUG);
m = mmap_cache_new();
assert_se(m != NULL);
@ -228,7 +222,7 @@ static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
return is_compressed;
}
static void test_min_compress_size(void) {
TEST(min_compress_size) {
/* Note that XZ will actually fail to compress anything under 80 bytes, so you have to choose the limits
* carefully */
@ -249,20 +243,14 @@ static void test_min_compress_size(void) {
}
#endif
int main(int argc, char *argv[]) {
arg_keep = argc > 1;
test_setup_logging(LOG_INFO);
static int intro(void) {
arg_keep = saved_argc > 1;
/* managed_journal_file_open requires a valid machine id */
if (access("/etc/machine-id", F_OK) != 0)
return log_tests_skipped("/etc/machine-id not found");
test_non_empty();
test_empty();
#if HAVE_COMPRESSION
test_min_compress_size();
#endif
return 0;
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);

View File

@ -78,12 +78,10 @@ static int test_ifindex = 42;
static unsigned test_client_sent_message_count = 0;
static sd_dhcp6_client *client_ref = NULL;
static void test_client_basic(void) {
TEST(client_basic) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
int v;
log_debug("/* %s */", __func__);
assert_se(sd_dhcp6_client_new(&client) >= 0);
assert_se(client);
@ -144,13 +142,11 @@ static void test_client_basic(void) {
assert_se(sd_dhcp6_client_detach_event(client) >= 0);
}
static void test_parse_domain(void) {
TEST(parse_domain) {
_cleanup_free_ char *domain = NULL;
_cleanup_strv_free_ char **list = NULL;
uint8_t *data;
log_debug("/* %s */", __func__);
data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
assert_se(dhcp6_option_parse_domainname(data, 13, &domain) >= 0);
assert_se(domain);
@ -182,7 +178,7 @@ static void test_parse_domain(void) {
assert_se(dhcp6_option_parse_domainname_list(data, 2, &list) < 0);
}
static void test_option(void) {
TEST(option) {
uint8_t packet[] = {
'F', 'O', 'O', 'H', 'O', 'G', 'E',
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
@ -204,8 +200,6 @@ static void test_option(void) {
uint16_t optcode;
uint8_t *out;
log_debug("/* %s */", __func__);
assert_se(sizeof(packet) == sizeof(result));
offset = 0;
@ -258,7 +252,7 @@ static void test_option(void) {
assert_se(memcmp(packet, result, sizeof(packet)) == 0);
}
static void test_option_status(void) {
TEST(option_status) {
uint8_t option1[] = {
/* IA NA */
0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
@ -330,8 +324,6 @@ static void test_option_status(void) {
be32_t iaid;
int r;
log_debug("/* %s */", __func__);
memcpy(&iaid, option1 + 4, sizeof(iaid));
option = (DHCP6Option*) option1;
@ -384,7 +376,7 @@ static void test_option_status(void) {
ia = dhcp6_ia_free(ia);
}
static void test_client_parse_message_issue_22099(void) {
TEST(client_parse_message_issue_22099) {
static const uint8_t msg[] = {
/* Message type */
DHCP6_MESSAGE_REPLY,
@ -444,8 +436,6 @@ static void test_client_parse_message_issue_22099(void) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
_cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
log_debug("/* %s */", __func__);
assert_se(sd_dhcp6_client_new(&client) >= 0);
assert_se(sd_dhcp6_client_set_iaid(client, 0xcc59117b) >= 0);
assert_se(sd_dhcp6_client_set_duid(client, 2, duid, sizeof(duid)) >= 0);
@ -970,12 +960,10 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *a) {
return TAKE_FD(test_fd[0]);
}
static void test_dhcp6_client(void) {
TEST(dhcp6_client) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
log_debug("/* %s */", __func__);
assert_se(sd_event_new(&e) >= 0);
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
2 * USEC_PER_SEC, 0,
@ -1006,15 +994,4 @@ static void test_dhcp6_client(void) {
test_fd[1] = safe_close(test_fd[1]);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_client_basic();
test_parse_domain();
test_option();
test_option_status();
test_client_parse_message_issue_22099();
test_dhcp6_client();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -100,11 +100,9 @@ static const struct in6_addr test_rdnss = { { { 0x20, 0x01, 0x0d, 0xb8,
static const char *test_dnssl[] = { "lab.intra",
NULL };
static void test_radv_prefix(void) {
TEST(radv_prefix) {
sd_radv_prefix *p;
printf("* %s\n", __func__);
assert_se(sd_radv_prefix_new(&p) >= 0);
assert_se(sd_radv_prefix_set_onlink(NULL, true) < 0);
@ -142,11 +140,9 @@ static void test_radv_prefix(void) {
assert_se(!p);
}
static void test_radv(void) {
TEST(radv) {
sd_radv *ra;
printf("* %s\n", __func__);
assert_se(sd_radv_new(&ra) >= 0);
assert_se(ra);
@ -284,13 +280,11 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
return 0;
}
static void test_ra(void) {
TEST(ra) {
sd_event *e;
sd_radv *ra;
unsigned i;
printf("* %s\n", __func__);
assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
assert_se(sd_event_new(&e) >= 0);
@ -349,14 +343,4 @@ static void test_ra(void) {
sd_event_unref(e);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_radv_prefix();
test_radv();
test_ra();
printf("* done\n");
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -257,13 +257,10 @@ static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router
sd_event_exit(e, 0);
}
static void test_rs(void) {
TEST(rs) {
sd_event *e;
sd_ndisc *nd;
if (verbose)
printf("* %s\n", __func__);
send_ra_function = send_ra;
assert_se(sd_event_new(&e) >= 0);
@ -347,13 +344,10 @@ static int test_timeout_value(uint8_t flags) {
return 0;
}
static void test_timeout(void) {
TEST(timeout) {
sd_event *e;
sd_ndisc *nd;
if (verbose)
printf("* %s\n", __func__);
send_ra_function = test_timeout_value;
assert_se(sd_event_new(&e) >= 0);
@ -381,12 +375,4 @@ static void test_timeout(void) {
sd_event_unref(e);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_rs();
test_timeout();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -6,13 +6,14 @@
#include "macro.h"
#include "string-util.h"
#include "strv.h"
#include "tests.h"
/* According to RFC1035 section 4.1.4, a domain name in a message can be either:
* - a sequence of labels ending in a zero octet
* - a pointer
* - a sequence of labels ending with a pointer
*/
static void test_dhcp_lease_parse_search_domains_basic(void) {
TEST(dhcp_lease_parse_search_domains_basic) {
int r;
_cleanup_strv_free_ char **domains = NULL;
static const uint8_t optionbuf[] = {
@ -26,7 +27,7 @@ static void test_dhcp_lease_parse_search_domains_basic(void) {
assert_se(streq(domains[1], "ABCD.EFG"));
}
static void test_dhcp_lease_parse_search_domains_ptr(void) {
TEST(dhcp_lease_parse_search_domains_ptr) {
int r;
_cleanup_strv_free_ char **domains = NULL;
static const uint8_t optionbuf[] = {
@ -39,7 +40,7 @@ static void test_dhcp_lease_parse_search_domains_ptr(void) {
assert_se(streq(domains[1], "FOO"));
}
static void test_dhcp_lease_parse_search_domains_labels_and_ptr(void) {
TEST(dhcp_lease_parse_search_domains_labels_and_ptr) {
int r;
_cleanup_strv_free_ char **domains = NULL;
static const uint8_t optionbuf[] = {
@ -55,7 +56,7 @@ static void test_dhcp_lease_parse_search_domains_labels_and_ptr(void) {
/* Tests for exceptions. */
static void test_dhcp_lease_parse_search_domains_no_data(void) {
TEST(dhcp_lease_parse_search_domains_no_data) {
_cleanup_strv_free_ char **domains = NULL;
static const uint8_t optionbuf[3] = {0, 0, 0};
@ -63,7 +64,7 @@ static void test_dhcp_lease_parse_search_domains_no_data(void) {
assert_se(dhcp_lease_parse_search_domains(optionbuf, 0, &domains) == -ENODATA);
}
static void test_dhcp_lease_parse_search_domains_loops(void) {
TEST(dhcp_lease_parse_search_domains_loops) {
_cleanup_strv_free_ char **domains = NULL;
static const uint8_t optionbuf[] = {
0x03, 'F', 'O', 'O', 0x00, 0x03, 'B', 'A', 'R', 0xC0, 0x06,
@ -72,7 +73,7 @@ static void test_dhcp_lease_parse_search_domains_loops(void) {
assert_se(dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains) == -EBADMSG);
}
static void test_dhcp_lease_parse_search_domains_wrong_len(void) {
TEST(dhcp_lease_parse_search_domains_wrong_len) {
_cleanup_strv_free_ char **domains = NULL;
static const uint8_t optionbuf[] = {
0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00,
@ -82,12 +83,4 @@ static void test_dhcp_lease_parse_search_domains_wrong_len(void) {
assert_se(dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf) - 5, &domains) == -EBADMSG);
}
int main(int argc, char *argv[]) {
test_dhcp_lease_parse_search_domains_basic();
test_dhcp_lease_parse_search_domains_ptr();
test_dhcp_lease_parse_search_domains_labels_and_ptr();
test_dhcp_lease_parse_search_domains_no_data();
test_dhcp_lease_parse_search_domains_loops();
test_dhcp_lease_parse_search_domains_wrong_len();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -22,13 +22,13 @@ static void test_one_address(sd_bus *b,
}
}
static void test_bus_set_address_system_remote(char **args) {
TEST(bus_set_address_system_remote) {
_cleanup_(sd_bus_unrefp) sd_bus *b = NULL;
assert_se(sd_bus_new(&b) >= 0);
if (!strv_isempty(args)) {
if (!strv_isempty(saved_argv + 1)) {
char **a;
STRV_FOREACH(a, args)
STRV_FOREACH(a, saved_argv + 1)
test_one_address(b, *a, 0, NULL);
return;
};
@ -61,10 +61,4 @@ static void test_bus_set_address_system_remote(char **args) {
-EINVAL, NULL);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_bus_set_address_system_remote(argv + 1);
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -8,8 +8,9 @@
#include "errno-list.h"
#include "errno-util.h"
#include "string-util.h"
#include "tests.h"
static void test_error(void) {
TEST(error) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
const sd_bus_error temporarily_const_error = {
@ -126,7 +127,7 @@ static void test_error(void) {
extern const sd_bus_error_map __start_SYSTEMD_BUS_ERROR_MAP[];
extern const sd_bus_error_map __stop_SYSTEMD_BUS_ERROR_MAP[];
static void dump_mapping_table(void) {
static int dump_mapping_table(void) {
const sd_bus_error_map *m;
printf("----- errno mappings ------\n");
@ -142,9 +143,11 @@ static void dump_mapping_table(void) {
m++;
}
printf("---------------------------\n");
return EXIT_SUCCESS;
}
static void test_errno_mapping_standard(void) {
TEST(errno_mapping_standard) {
assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN);
assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY);
assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL);
@ -186,7 +189,7 @@ static const sd_bus_error_map test_errors_bad2[] = {
SD_BUS_ERROR_MAP_END
};
static void test_errno_mapping_custom(void) {
TEST(errno_mapping_custom) {
assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5);
assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-x", NULL) == -EIO);
@ -214,7 +217,7 @@ static void test_errno_mapping_custom(void) {
assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
}
static void test_sd_bus_error_set_errnof(void) {
TEST(sd_bus_error_set_errnof) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *str = NULL;
@ -288,13 +291,4 @@ static void test_sd_bus_error_set_errnof(void) {
assert_se(error._need_free == 1);
}
int main(int argc, char *argv[]) {
dump_mapping_table();
test_error();
test_errno_mapping_standard();
test_errno_mapping_custom();
test_sd_bus_error_set_errnof();
return 0;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, dump_mapping_table);

View File

@ -15,9 +15,7 @@
#include "tests.h"
#include "util.h"
static void test_bus_gvariant_is_fixed_size(void) {
log_info("/* %s */", __func__);
TEST(bus_gvariant_is_fixed_size) {
assert_se(bus_gvariant_is_fixed_size("") > 0);
assert_se(bus_gvariant_is_fixed_size("()") == -EINVAL);
assert_se(bus_gvariant_is_fixed_size("y") > 0);
@ -42,9 +40,7 @@ static void test_bus_gvariant_is_fixed_size(void) {
assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiivi)))") == 0);
}
static void test_bus_gvariant_get_size(void) {
log_info("/* %s */", __func__);
TEST(bus_gvariant_get_size) {
assert_se(bus_gvariant_get_size("") == 0);
assert_se(bus_gvariant_get_size("()") == -EINVAL);
assert_se(bus_gvariant_get_size("y") == 1);
@ -76,9 +72,7 @@ static void test_bus_gvariant_get_size(void) {
assert_se(bus_gvariant_get_size("((t)(t))") == 16);
}
static void test_bus_gvariant_get_alignment(void) {
log_info("/* %s */", __func__);
TEST(bus_gvariant_get_alignment) {
assert_se(bus_gvariant_get_alignment("") == 1);
assert_se(bus_gvariant_get_alignment("()") == -EINVAL);
assert_se(bus_gvariant_get_alignment("y") == 1);
@ -119,7 +113,7 @@ static void test_bus_gvariant_get_alignment(void) {
assert_se(bus_gvariant_get_alignment("((t)(t))") == 8);
}
static int test_marshal(void) {
TEST_RET(marshal) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ void *blob = NULL;
@ -209,12 +203,4 @@ static int test_marshal(void) {
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_bus_gvariant_is_fixed_size();
test_bus_gvariant_get_size();
test_bus_gvariant_get_alignment();
return test_marshal();
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -6,7 +6,7 @@
#include "test-vtable-data.h"
static void test_manual_introspection(const sd_bus_vtable vtable[]) {
static void test_manual_introspection_one(const sd_bus_vtable vtable[]) {
struct introspect intro = {};
_cleanup_free_ char *s = NULL;
@ -23,13 +23,11 @@ static void test_manual_introspection(const sd_bus_vtable vtable[]) {
fputs("\n", stdout);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_manual_introspection(test_vtable_1);
test_manual_introspection(test_vtable_2);
test_manual_introspection(test_vtable_deprecated);
test_manual_introspection((const sd_bus_vtable *) vtable_format_221);
return 0;
TEST(manual_introspection) {
test_manual_introspection_one(test_vtable_1);
test_manual_introspection_one(test_vtable_2);
test_manual_introspection_one(test_vtable_deprecated);
test_manual_introspection_one((const sd_bus_vtable *) vtable_format_221);
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -3,11 +3,9 @@
#include "device-util.h"
#include "tests.h"
static void test_log_device_full(void) {
TEST(log_device_full) {
int r;
log_info("/* %s */", __func__);
for (int level = LOG_ERR; level <= LOG_DEBUG; level++) {
log_device_full(NULL, level, "test level=%d: %m", level);
@ -22,9 +20,4 @@ static void test_log_device_full(void) {
}
}
int main(int argc, char **argv) {
test_setup_logging(LOG_INFO);
test_log_device_full();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -60,24 +60,20 @@ static void test_sd_device_one(sd_device *d) {
log_info("syspath:%s subsystem:%s initialized:%s", syspath, strna(subsystem), yes_no(i));
}
static void test_sd_device_enumerator_devices(void) {
TEST(sd_device_enumerator_devices) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *d;
log_info("/* %s */", __func__);
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
FOREACH_DEVICE(e, d)
test_sd_device_one(d);
}
static void test_sd_device_enumerator_subsystems(void) {
TEST(sd_device_enumerator_subsystems) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *d;
log_info("/* %s */", __func__);
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
FOREACH_SUBSYSTEM(e, d)
@ -113,7 +109,7 @@ static unsigned test_sd_device_enumerator_filter_subsystem_one(const char *subsy
return n_new_dev;
}
static void test_sd_device_enumerator_filter_subsystem(void) {
TEST(sd_device_enumerator_filter_subsystem) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
_cleanup_(hashmap_freep) Hashmap *subsystems;
unsigned n_new_dev = 0;
@ -121,8 +117,6 @@ static void test_sd_device_enumerator_filter_subsystem(void) {
Hashmap *h;
char *s;
log_info("/* %s */", __func__);
assert_se(subsystems = hashmap_new(&string_hash_ops));
assert_se(sd_device_enumerator_new(&e) >= 0);
@ -164,7 +158,7 @@ static void test_sd_device_enumerator_filter_subsystem(void) {
assert_se(n_new_dev <= 10);
}
static void test_sd_device_new_from_nulstr(void) {
TEST(sd_device_new_from_nulstr) {
const char *devlinks =
"/dev/disk/by-partuuid/1290d63a-42cc-4c71-b87c-xxxxxxxxxxxx\0"
"/dev/disk/by-path/pci-0000:00:0f.0-scsi-0:0:0:0-part3\0"
@ -179,8 +173,6 @@ static void test_sd_device_new_from_nulstr(void) {
const uint8_t *nulstr;
size_t len;
log_info("/* %s */", __func__);
assert_se(sd_device_new_from_syspath(&device, "/sys/class/net/lo") >= 0);
/* Yeah, of course, setting devlink to the loopback interface is nonsense. But this is just a
@ -205,14 +197,4 @@ static void test_sd_device_new_from_nulstr(void) {
}
}
int main(int argc, char **argv) {
test_setup_logging(LOG_INFO);
test_sd_device_enumerator_devices();
test_sd_device_enumerator_subsystems();
test_sd_device_enumerator_filter_subsystem();
test_sd_device_new_from_nulstr();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -195,7 +195,7 @@ static int post_handler(sd_event_source *s, void *userdata) {
return 2;
}
static void test_basic(bool with_pidfd) {
static void test_basic_one(bool with_pidfd) {
sd_event *e = NULL;
sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
static const char ch = 'x';
@ -302,12 +302,15 @@ static void test_basic(bool with_pidfd) {
assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
}
static void test_sd_event_now(void) {
TEST(basic) {
test_basic_one(true); /* test with pidfd */
test_basic_one(false); /* test without pidfd */
}
TEST(sd_event_now) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
uint64_t event_now;
log_info("/* %s */", __func__);
assert_se(sd_event_new(&e) >= 0);
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
@ -341,12 +344,10 @@ static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si
return 0;
}
static void test_rtqueue(void) {
TEST(rtqueue) {
sd_event_source *u = NULL, *v = NULL, *s = NULL;
sd_event *e = NULL;
log_info("/* %s */", __func__);
assert_se(sd_event_default(&e) >= 0);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0);
@ -476,7 +477,7 @@ static int delete_self_handler(sd_event_source *s, const struct inotify_event *e
return 1;
}
static void test_inotify(unsigned n_create_events) {
static void test_inotify_one(unsigned n_create_events) {
_cleanup_(rm_rf_physical_and_freep) char *p = NULL;
sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL;
struct inotify_context context = {
@ -529,6 +530,11 @@ static void test_inotify(unsigned n_create_events) {
sd_event_unref(e);
}
TEST(inotify) {
test_inotify_one(100); /* should work without overflow */
test_inotify_one(33000); /* should trigger a q overflow */
}
static int pidfd_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
assert_se(s);
assert_se(si);
@ -548,14 +554,12 @@ static int pidfd_handler(sd_event_source *s, const siginfo_t *si, void *userdata
return 0;
}
static void test_pidfd(void) {
TEST(pidfd) {
sd_event_source *s = NULL, *t = NULL;
sd_event *e = NULL;
int pidfd;
pid_t pid, pid2;
log_info("/* %s */", __func__);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
pid = fork();
@ -628,15 +632,13 @@ static int ratelimit_expired(sd_event_source *s, void *userdata) {
return ++expired;
}
static void test_ratelimit(void) {
TEST(ratelimit) {
_cleanup_close_pair_ int p[2] = {-1, -1};
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
uint64_t interval;
unsigned count, burst;
log_info("/* %s */", __func__);
assert_se(sd_event_default(&e) >= 0);
assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0);
@ -706,7 +708,7 @@ static void test_ratelimit(void) {
assert_se(expired == 0);
}
static void test_simple_timeout(void) {
TEST(simple_timeout) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
usec_t f, t, some_time;
@ -741,7 +743,7 @@ static int inotify_self_destroy_handler(sd_event_source *s, const struct inotify
return 1;
}
static void test_inotify_self_destroy(void) {
TEST(inotify_self_destroy) {
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
char path[] = "/tmp/inotifyXXXXXX";
@ -759,25 +761,4 @@ static void test_inotify_self_destroy(void) {
assert_se(sd_event_loop(e) >= 0);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_simple_timeout();
test_basic(true); /* test with pidfd */
test_basic(false); /* test without pidfd */
test_sd_event_now();
test_rtqueue();
test_inotify(100); /* should work without overflow */
test_inotify(33000); /* should trigger a q overflow */
test_pidfd();
test_ratelimit();
test_inotify_self_destroy();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -4,6 +4,7 @@
#include <linux/audit.h>
#include "audit-type.h"
#include "tests.h"
static void print_audit_label(int i) {
const char *name;
@ -13,14 +14,11 @@ static void print_audit_label(int i) {
printf("%i → %s → %s\n", i, audit_type_to_string(i), name);
}
static void test_audit_type(void) {
TEST(audit_type) {
int i;
for (i = 0; i <= AUDIT_KERNEL; i++)
print_audit_label(i);
}
int main(int argc, char **argv) {
test_audit_type();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -10,8 +10,9 @@
#include "journal-send.h"
#include "macro.h"
#include "memory-util.h"
#include "tests.h"
static void test_journal_print(void) {
TEST(journal_print) {
assert_se(sd_journal_print(LOG_INFO, "XXX") == 0);
assert_se(sd_journal_print(LOG_INFO, "%s", "YYY") == 0);
assert_se(sd_journal_print(LOG_INFO, "X%4094sY", "ZZZ") == 0);
@ -19,7 +20,7 @@ static void test_journal_print(void) {
assert_se(sd_journal_print(LOG_INFO, "X%*sY", LONG_LINE_MAX - 8 - 2, "ZZZ") == -ENOBUFS);
}
static void test_journal_send(void) {
TEST(journal_send) {
_cleanup_free_ char *huge = NULL;
#define HUGE_SIZE (4096*1024)
@ -98,13 +99,13 @@ static void test_journal_send(void) {
closelog();
}
int main(int argc, char *argv[]) {
test_journal_print();
test_journal_send();
static int outro(void) {
/* Sleep a bit to make it easy for journald to collect metadata. */
sleep(1);
close_journal_fd();
return 0;
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN_FULL(LOG_INFO, NULL, outro);

View File

@ -11,6 +11,7 @@
#include "log.h"
#include "string-util.h"
#include "strv.h"
#include "tests.h"
#include "time-util.h"
#include "user-util.h"
@ -35,7 +36,7 @@ static const char *e(int r) {
return r == 0 ? "OK" : errno_to_name(r);
}
static void test_login(void) {
TEST(login) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_free_ char *pp = NULL, *qq = NULL,
*display_session = NULL, *cgroup = NULL,
@ -259,10 +260,13 @@ static void test_login(void) {
}
}
static void test_monitor(void) {
TEST(monitor) {
sd_login_monitor *m = NULL;
int r;
if (!streq_ptr(saved_argv[1], "-m"))
return;
assert_se(sd_login_monitor_new("session", &m) == 0);
for (unsigned n = 0; n < 5; n++) {
@ -290,16 +294,9 @@ static void test_monitor(void) {
sd_login_monitor_unref(m);
}
int main(int argc, char* argv[]) {
log_parse_environment();
log_open();
static int intro(void) {
log_info("/* Information printed is from the live system */");
test_login();
if (streq_ptr(argv[1], "-m"))
test_monitor();
return 0;
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);

View File

@ -6,11 +6,9 @@
#include "string-util.h"
#include "tests.h"
static void test_find_language_fallback(void) {
TEST(find_language_fallback) {
_cleanup_free_ char *ans = NULL, *ans2 = NULL;
log_info("/*** %s ***/", __func__);
assert_se(find_language_fallback("foobar", &ans) == 0);
assert_se(ans == NULL);
@ -24,12 +22,10 @@ static void test_find_language_fallback(void) {
assert_se(streq(ans2, "szl:pl"));
}
static void test_find_converted_keymap(void) {
TEST(find_converted_keymap) {
_cleanup_free_ char *ans = NULL, *ans2 = NULL;
int r;
log_info("/*** %s ***/", __func__);
assert_se(find_converted_keymap("pl", "foobar", &ans) == 0);
assert_se(ans == NULL);
@ -46,12 +42,10 @@ static void test_find_converted_keymap(void) {
assert_se(streq(ans2, "pl-dvorak"));
}
static void test_find_legacy_keymap(void) {
TEST(find_legacy_keymap) {
Context c = {};
_cleanup_free_ char *ans = NULL, *ans2 = NULL;
log_info("/*** %s ***/", __func__);
c.x11_layout = (char*) "foobar";
assert_se(find_legacy_keymap(&c, &ans) == 0);
assert_se(ans == NULL);
@ -65,11 +59,9 @@ static void test_find_legacy_keymap(void) {
assert_se(streq(ans, "pl2"));
}
static void test_vconsole_convert_to_x11(void) {
TEST(vconsole_convert_to_x11) {
_cleanup_(context_clear) Context c = {};
log_info("/*** %s ***/", __func__);
log_info("/* test emptying first (:) */");
assert_se(free_and_strdup(&c.x11_layout, "foo") >= 0);
assert_se(free_and_strdup(&c.x11_variant, "bar") >= 0);
@ -119,12 +111,10 @@ static void test_vconsole_convert_to_x11(void) {
assert_se(c.x11_variant == NULL);
}
static void test_x11_convert_to_vconsole(void) {
TEST(x11_convert_to_vconsole) {
_cleanup_(context_clear) Context c = {};
int r;
log_info("/*** %s ***/", __func__);
log_info("/* test emptying first (:) */");
assert_se(free_and_strdup(&c.vc_keymap, "foobar") >= 0);
assert_se(x11_convert_to_vconsole(&c) == 1);
@ -189,20 +179,13 @@ static void test_x11_convert_to_vconsole(void) {
assert_se(streq(c.vc_keymap, "ru"));
}
int main(int argc, char **argv) {
static int intro(void) {
_cleanup_free_ char *map = NULL;
test_setup_logging(LOG_DEBUG);
test_find_language_fallback();
test_find_converted_keymap();
assert_se(get_testdata_dir("test-keymap-util/kbd-model-map", &map) >= 0);
assert_se(setenv("SYSTEMD_KBD_MODEL_MAP", map, 1) == 0);
test_find_legacy_keymap();
test_vconsole_convert_to_x11();
test_x11_convert_to_vconsole();
return 0;
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);

View File

@ -2,8 +2,9 @@
#include "login-util.h"
#include "macro.h"
#include "tests.h"
static void test_session_id_valid(void) {
TEST(session_id_valid) {
assert_se(session_id_valid("c1"));
assert_se(session_id_valid("1234"));
@ -12,11 +13,4 @@ static void test_session_id_valid(void) {
assert_se(!session_id_valid("\tid"));
}
int main(int argc, char* argv[]) {
log_parse_environment();
log_open();
test_session_id_valid();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -11,11 +11,9 @@ static void test_FORMAT_LIFETIME_one(usec_t lifetime, const char *expected) {
assert_se(streq(t, expected));
}
static void test_FORMAT_LIFETIME(void) {
TEST(FORMAT_LIFETIME) {
usec_t now_usec;
log_info("/* %s */", __func__);
now_usec = now(clock_boottime_or_monotonic());
test_FORMAT_LIFETIME_one(now_usec, "for 0");
@ -24,10 +22,4 @@ static void test_FORMAT_LIFETIME(void) {
test_FORMAT_LIFETIME_one(USEC_INFINITY, "forever");
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_FORMAT_LIFETIME();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -9,6 +9,7 @@
#include "networkd-manager.h"
#include "networkd-network.h"
#include "strv.h"
#include "tests.h"
static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected, usec_t expected_time) {
DUID actual = {};
@ -22,7 +23,7 @@ static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDTyp
assert_se(expected_time == actual.llt_time);
}
static void test_config_parse_duid_type(void) {
TEST(config_parse_duid_type) {
test_config_parse_duid_type_one("", 0, 0, 0);
test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT, 0);
test_config_parse_duid_type_one("link-layer-time:2000-01-01 00:00:00 UTC", 0, DUID_TYPE_LLT, (usec_t) 946684800000000);
@ -86,7 +87,7 @@ static void test_config_parse_ether_addrs_one(const char *rvalue, const struct e
#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80}
static void test_config_parse_duid_rawdata(void) {
TEST(config_parse_duid_rawdata) {
test_config_parse_duid_rawdata_one("", 0, &(DUID){});
test_config_parse_duid_rawdata_one("00:11:22:33:44:55:66:77", 0,
&(DUID){0, 8, {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}});
@ -102,7 +103,7 @@ static void test_config_parse_duid_rawdata(void) {
test_config_parse_duid_rawdata_one(&BYTES_0_128[2], 0, &(DUID){0, 128, BYTES_1_128});
}
static void test_config_parse_ether_addr(void) {
TEST(config_parse_ether_addr) {
const struct ether_addr t[] = {
{ .ether_addr_octet = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } },
{ .ether_addr_octet = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } },
@ -192,7 +193,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign
}
}
static void test_config_parse_address(void) {
TEST(config_parse_address) {
test_config_parse_address_one("", AF_INET, 0, NULL, 0);
test_config_parse_address_one("/", AF_INET, 0, NULL, 0);
test_config_parse_address_one("/8", AF_INET, 0, NULL, 0);
@ -219,7 +220,7 @@ static void test_config_parse_address(void) {
test_config_parse_address_one("::1/-1", AF_INET6, 0, NULL, 0);
}
static void test_config_parse_match_ifnames(void) {
TEST(config_parse_match_ifnames) {
_cleanup_strv_free_ char **names = NULL;
assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0);
@ -229,7 +230,7 @@ static void test_config_parse_match_ifnames(void) {
assert_se(strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc")));
}
static void test_config_parse_match_strv(void) {
TEST(config_parse_match_strv) {
_cleanup_strv_free_ char **names = NULL;
assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0);
@ -247,16 +248,4 @@ static void test_config_parse_match_strv(void) {
"KEY3=val with \\quotation\\")));
}
int main(int argc, char **argv) {
log_parse_environment();
log_open();
test_config_parse_duid_type();
test_config_parse_duid_rawdata();
test_config_parse_ether_addr();
test_config_parse_address();
test_config_parse_match_ifnames();
test_config_parse_match_strv();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -2656,7 +2656,7 @@ static int partition_encrypt(
uint16_t pcr_bank, primary_alg;
int keyslot;
r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg);
r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, NULL, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg);
if (r < 0)
return log_error_errno(r, "Failed to seal to TPM2: %m");
@ -2678,7 +2678,7 @@ static int partition_encrypt(
if (keyslot < 0)
return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node);
r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, &v);
r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, 0, &v);
if (r < 0)
return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");

View File

@ -9,13 +9,13 @@
#endif
#include "alloc-util.h"
#include "hexdecoct.h"
#include "resolved-dns-dnssec.h"
#include "resolved-dns-rr.h"
#include "string-util.h"
#include "hexdecoct.h"
static void test_dnssec_verify_dns_key(void) {
#include "tests.h"
TEST(dnssec_verify_dns_key) {
static const uint8_t ds1_fprint[] = {
0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
0x80, 0x67, 0x14, 0x01,
@ -88,7 +88,7 @@ static void test_dnssec_verify_dns_key(void) {
assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0);
}
static void test_dnssec_verify_rfc8080_ed25519_example1(void) {
TEST(dnssec_verify_rfc8080_ed25519_example1) {
static const uint8_t dnskey_blob[] = {
0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50, 0x91, 0x47, 0x7d,
0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30, 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59,
@ -180,7 +180,7 @@ static void test_dnssec_verify_rfc8080_ed25519_example1(void) {
#endif
}
static void test_dnssec_verify_rfc8080_ed25519_example2(void) {
TEST(dnssec_verify_rfc8080_ed25519_example2) {
static const uint8_t dnskey_blob[] = {
0xcc, 0xf9, 0xd9, 0xfd, 0x0c, 0x04, 0x7b, 0xb4, 0xbc, 0x0b, 0x94, 0x8f, 0xcf, 0x63, 0x9f,
0x4b, 0x94, 0x51, 0xe3, 0x40, 0x13, 0x93, 0x6f, 0xeb, 0x62, 0x71, 0x3d, 0xc4, 0x72, 0x4,
@ -272,7 +272,7 @@ static void test_dnssec_verify_rfc8080_ed25519_example2(void) {
#endif
}
static void test_dnssec_verify_rfc6605_example1(void) {
TEST(dnssec_verify_rfc6605_example1) {
static const uint8_t signature_blob[] = {
0xab, 0x1e, 0xb0, 0x2d, 0x8a, 0xa6, 0x87, 0xe9, 0x7d, 0xa0, 0x22, 0x93, 0x37, 0xaa, 0x88, 0x73,
0xe6, 0xf0, 0xeb, 0x26, 0xbe, 0x28, 0x9f, 0x28, 0x33, 0x3d, 0x18, 0x3f, 0x5d, 0x3b, 0x7a, 0x95,
@ -359,7 +359,7 @@ static void test_dnssec_verify_rfc6605_example1(void) {
assert_se(result == DNSSEC_VALIDATED);
}
static void test_dnssec_verify_rfc6605_example2(void) {
TEST(dnssec_verify_rfc6605_example2) {
static const uint8_t signature_blob[] = {
0xfc, 0xbe, 0x61, 0x0c, 0xa2, 0x2f, 0x18, 0x3c, 0x88, 0xd5, 0xf7, 0x00, 0x45, 0x7d, 0xf3, 0xeb,
0x9a, 0xab, 0x98, 0xfb, 0x15, 0xcf, 0xbd, 0xd0, 0x0f, 0x53, 0x2b, 0xe4, 0x21, 0x2a, 0x3a, 0x22,
@ -454,8 +454,7 @@ static void test_dnssec_verify_rfc6605_example2(void) {
assert_se(result == DNSSEC_VALIDATED);
}
static void test_dnssec_verify_rrset(void) {
TEST(dnssec_verify_rrset) {
static const uint8_t signature_blob[] = {
0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
@ -533,8 +532,7 @@ static void test_dnssec_verify_rrset(void) {
assert_se(result == DNSSEC_VALIDATED);
}
static void test_dnssec_verify_rrset2(void) {
TEST(dnssec_verify_rrset2) {
static const uint8_t signature_blob[] = {
0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
@ -625,8 +623,7 @@ static void test_dnssec_verify_rrset2(void) {
assert_se(result == DNSSEC_VALIDATED);
}
static void test_dnssec_verify_rrset3(void) {
TEST(dnssec_verify_rrset3) {
static const uint8_t signature_blob[] = {
0x41, 0x09, 0x08, 0x67, 0x51, 0x6d, 0x02, 0xf2, 0x17, 0x1e, 0x61, 0x03, 0xc6, 0x80, 0x7a, 0x82,
0x8f, 0x6c, 0x8c, 0x4c, 0x68, 0x6f, 0x1c, 0xaa, 0x4a, 0xe0, 0x9b, 0x72, 0xdf, 0x7f, 0x15, 0xfa,
@ -755,7 +752,7 @@ static void test_dnssec_verify_rrset3(void) {
assert_se(result == DNSSEC_VALIDATED);
}
static void test_dnssec_nsec3_hash(void) {
TEST(dnssec_nsec3_hash) {
static const uint8_t salt[] = { 0xB0, 0x1D, 0xFA, 0xCE };
static const uint8_t next_hashed_name[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 };
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
@ -787,16 +784,4 @@ static void test_dnssec_nsec3_hash(void) {
assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
}
int main(int argc, char *argv[]) {
test_dnssec_verify_dns_key();
test_dnssec_verify_rfc8080_ed25519_example1();
test_dnssec_verify_rfc8080_ed25519_example2();
test_dnssec_verify_rfc6605_example1();
test_dnssec_verify_rfc6605_example2();
test_dnssec_verify_rrset();
test_dnssec_verify_rrset2();
test_dnssec_verify_rrset3();
test_dnssec_nsec3_hash();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -14,11 +14,9 @@
#include "tests.h"
#include "tmpfile-util.h"
static void test_parse_etc_hosts_system(void) {
TEST(parse_etc_hosts_system) {
_cleanup_fclose_ FILE *f = NULL;
log_info("/* %s */", __func__);
f = fopen("/etc/hosts", "re");
if (!f) {
assert_se(errno == ENOENT);
@ -37,12 +35,10 @@ static void test_parse_etc_hosts_system(void) {
((_addr)->family == AF_INET6 && \
!memcmp(&(_addr)->address.in6, &(struct in6_addr) { .s6_addr = __VA_ARGS__}, 16) )
static void test_parse_etc_hosts(void) {
TEST(parse_etc_hosts) {
_cleanup_(unlink_tempfilep) char
t[] = "/tmp/test-resolved-etc-hosts.XXXXXX";
log_info("/* %s */", __func__);
int fd;
_cleanup_fclose_ FILE *f;
const char *s;
@ -128,7 +124,7 @@ static void test_parse_etc_hosts(void) {
assert_se(!set_contains(hosts.no_address, "foobar.foo.foo"));
}
static void test_parse_file(const char *fname) {
static void test_parse_file_one(const char *fname) {
_cleanup_(etc_hosts_free) EtcHosts hosts = {};
_cleanup_fclose_ FILE *f;
@ -138,14 +134,9 @@ static void test_parse_file(const char *fname) {
assert_se(etc_hosts_parse(&hosts, f) == 0);
}
int main(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);
if (argc == 1) {
test_parse_etc_hosts_system();
test_parse_etc_hosts();
} else
test_parse_file(argv[1]);
return 0;
TEST(parse_file) {
for (int i = 1; i < saved_argc; i++)
test_parse_file_one(saved_argv[i]);
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -4,7 +4,7 @@
#include "resolved-dns-packet.h"
#include "tests.h"
static void test_dns_packet_new(void) {
TEST(dns_packet_new) {
size_t i;
_cleanup_(dns_packet_unrefp) DnsPacket *p2 = NULL;
@ -23,10 +23,4 @@ static void test_dns_packet_new(void) {
assert_se(dns_packet_new(&p2, DNS_PROTOCOL_DNS, DNS_PACKET_SIZE_MAX + 1, DNS_PACKET_SIZE_MAX) == -EFBIG);
}
int main(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);
test_dns_packet_new();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -534,6 +534,7 @@ int encrypt_credential_and_warn(
r = tpm2_seal(tpm2_device,
tpm2_pcr_mask,
NULL,
&tpm2_key,
&tpm2_key_size,
&tpm2_blob,
@ -803,6 +804,7 @@ int decrypt_credential_and_warn(
le32toh(t->blob_size),
t->policy_hash_and_blob + le32toh(t->blob_size),
le32toh(t->policy_hash_size),
NULL,
&tpm2_key,
&tpm2_key_size);
if (r < 0)

View File

@ -14,6 +14,7 @@
#include "hexdecoct.h"
#include "memory-util.h"
#include "random-util.h"
#include "sha256.h"
#include "time-util.h"
static void *libtss2_esys_dl = NULL;
@ -30,10 +31,12 @@ TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_
TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle) = NULL;
TSS2_RC (*sym_Esys_PCR_Read)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1,ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcrSelectionIn, UINT32 *pcrUpdateCounter, TPML_PCR_SELECTION **pcrSelectionOut, TPML_DIGEST **pcrValues);
TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) = NULL;
TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) = NULL;
TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL;
const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
@ -58,10 +61,12 @@ int dlopen_tpm2(void) {
DLSYM_ARG(Esys_Initialize),
DLSYM_ARG(Esys_Load),
DLSYM_ARG(Esys_PCR_Read),
DLSYM_ARG(Esys_PolicyAuthValue),
DLSYM_ARG(Esys_PolicyGetDigest),
DLSYM_ARG(Esys_PolicyPCR),
DLSYM_ARG(Esys_StartAuthSession),
DLSYM_ARG(Esys_Startup),
DLSYM_ARG(Esys_TR_SetAuth),
DLSYM_ARG(Esys_Unseal));
if (r < 0)
return r;
@ -594,6 +599,7 @@ static int tpm2_make_pcr_session(
ESYS_CONTEXT *c,
uint32_t pcr_mask,
uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */
bool use_pin,
ESYS_TR *ret_session,
TPM2B_DIGEST **ret_policy_digest,
TPMI_ALG_HASH *ret_pcr_bank) {
@ -669,6 +675,21 @@ static int tpm2_make_pcr_session(
goto finish;
}
if (use_pin) {
rc = sym_Esys_PolicyAuthValue(
c,
session,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE);
if (rc != TSS2_RC_SUCCESS) {
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to add authValue policy to TPM: %s",
sym_Tss2_RC_Decode(rc));
goto finish;
}
}
if (DEBUG_LOGGING || ret_policy_digest) {
log_debug("Acquiring policy digest.");
@ -717,9 +738,22 @@ finish:
return r;
}
static void hash_pin(const char *pin, size_t len, uint8_t ret_digest[static SHA256_DIGEST_SIZE]) {
struct sha256_ctx hash;
assert(pin);
sha256_init_ctx(&hash);
sha256_process_bytes(pin, len, &hash);
sha256_finish_ctx(&hash, ret_digest);
explicit_bzero_safe(&hash, sizeof(hash));
}
int tpm2_seal(
const char *device,
uint32_t pcr_mask,
const char *pin,
void **ret_secret,
size_t *ret_secret_size,
void **ret_blob,
@ -782,7 +816,8 @@ int tpm2_seal(
if (r < 0)
return r;
r = tpm2_make_pcr_session(c.esys_context, pcr_mask, UINT16_MAX, NULL, &policy_digest, &pcr_bank);
r = tpm2_make_pcr_session(c.esys_context, pcr_mask, UINT16_MAX, !!pin, NULL, &policy_digest,
&pcr_bank);
if (r < 0)
goto finish;
@ -813,6 +848,10 @@ int tpm2_seal(
.size = sizeof(hmac_sensitive.sensitive),
.sensitive.data.size = 32,
};
if (pin) {
hash_pin(pin, strlen(pin), hmac_sensitive.sensitive.userAuth.buffer);
hmac_sensitive.sensitive.userAuth.size = SHA256_DIGEST_SIZE;
}
assert(sizeof(hmac_sensitive.sensitive.data.buffer) >= hmac_sensitive.sensitive.data.size);
(void) tpm2_credit_random(c.esys_context);
@ -910,6 +949,7 @@ int tpm2_seal(
r = 0;
finish:
explicit_bzero_safe(&hmac_sensitive, sizeof(hmac_sensitive));
primary = flush_context_verbose(c.esys_context, primary);
return r;
}
@ -923,6 +963,7 @@ int tpm2_unseal(
size_t blob_size,
const void *known_policy_hash,
size_t known_policy_hash_size,
const char *pin,
void **ret_secret,
size_t *ret_secret_size) {
@ -978,7 +1019,7 @@ int tpm2_unseal(
if (r < 0)
return r;
r = tpm2_make_pcr_session(c.esys_context, pcr_mask, pcr_bank, &session, &policy_digest, NULL);
r = tpm2_make_pcr_session(c.esys_context, pcr_mask, pcr_bank, !!pin, &session, &policy_digest, NULL);
if (r < 0)
goto finish;
@ -1005,11 +1046,38 @@ int tpm2_unseal(
&public,
&hmac_key);
if (rc != TSS2_RC_SUCCESS) {
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to load HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
/* If we're in dictionary attack lockout mode, we should see a lockout error here, which we
* need to translate for the caller. */
if (rc == TPM2_RC_LOCKOUT)
r = log_error_errno(
SYNTHETIC_ERRNO(ENOLCK),
"TPM2 device is in dictionary attack lockout mode.");
else
r = log_error_errno(
SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to load HMAC key in TPM: %s",
sym_Tss2_RC_Decode(rc));
goto finish;
}
if (pin) {
TPM2B_AUTH auth = {
.size = SHA256_DIGEST_SIZE
};
hash_pin(pin, strlen(pin), auth.buffer);
rc = sym_Esys_TR_SetAuth(c.esys_context, hmac_key, &auth);
explicit_bzero_safe(&auth, sizeof(auth));
if (rc != TSS2_RC_SUCCESS) {
r = log_error_errno(
SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to load PIN in TPM: %s",
sym_Tss2_RC_Decode(rc));
goto finish;
}
}
log_debug("Unsealing HMAC key.");
rc = sym_Esys_Unseal(
@ -1223,6 +1291,7 @@ int tpm2_make_luks2_json(
size_t blob_size,
const void *policy_hash,
size_t policy_hash_size,
TPM2Flags flags,
JsonVariant **ret) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *a = NULL;
@ -1263,7 +1332,9 @@ int tpm2_make_luks2_json(
JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(a)),
JSON_BUILD_PAIR_CONDITION(!!tpm2_pcr_bank_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_pcr_bank_to_string(pcr_bank))),
JSON_BUILD_PAIR_CONDITION(!!tpm2_primary_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_primary_alg_to_string(primary_alg))),
JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size))));
JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)))
);
if (r < 0)
return r;

View File

@ -1,9 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
#include "json.h"
#include "macro.h"
typedef enum TPM2Flags {
TPM2_FLAGS_USE_PIN = 1 << 0,
} TPM2Flags;
#if HAVE_TPM2
#include <tss2/tss2_esys.h>
@ -20,10 +26,12 @@ extern TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1
extern TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion);
extern TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle);
extern TSS2_RC (*sym_Esys_PCR_Read)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1,ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcrSelectionIn, UINT32 *pcrUpdateCounter, TPML_PCR_SELECTION **pcrSelectionOut, TPML_DIGEST **pcrValues);
extern TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3);
extern TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest);
extern TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs);
extern TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle);
extern TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType);
extern TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue);
extern TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData);
extern const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc);
@ -35,8 +43,8 @@ extern TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], siz
int dlopen_tpm2(void);
int tpm2_seal(const char *device, uint32_t pcr_mask, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, void **ret_pcr_hash, size_t *ret_pcr_hash_size, uint16_t *ret_pcr_bank, uint16_t *ret_primary_alg);
int tpm2_unseal(const char *device, uint32_t pcr_mask, uint16_t pcr_bank, uint16_t primary_alg, const void *blob, size_t blob_size, const void *pcr_hash, size_t pcr_hash_size, void **ret_secret, size_t *ret_secret_size);
int tpm2_seal(const char *device, uint32_t pcr_mask, const char *pin, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, void **ret_pcr_hash, size_t *ret_pcr_hash_size, uint16_t *ret_pcr_bank, uint16_t *ret_primary_alg);
int tpm2_unseal(const char *device, uint32_t pcr_mask, uint16_t pcr_bank, uint16_t primary_alg, const void *blob, size_t blob_size, const void *pcr_hash, size_t pcr_hash_size, const char *pin, void **ret_secret, size_t *ret_secret_size);
#endif
@ -45,7 +53,7 @@ int tpm2_find_device_auto(int log_level, char **ret);
int tpm2_parse_pcrs(const char *s, uint32_t *ret);
int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, uint16_t pcr_bank, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, JsonVariant **ret);
int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, uint16_t pcr_bank, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, JsonVariant **ret);
#define TPM2_PCRS_MAX 24

View File

@ -9,7 +9,7 @@
#include "umount.h"
#include "util.h"
static void test_mount_points_list(const char *fname) {
static void test_mount_points_list_one(const char *fname) {
_cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
_cleanup_free_ char *testdata_fname = NULL;
MountPoint *m;
@ -33,7 +33,14 @@ static void test_mount_points_list(const char *fname) {
major(m->devnum), minor(m->devnum));
}
static void test_swap_list(const char *fname) {
TEST(mount_points_list) {
test_mount_points_list_one(NULL);
test_mount_points_list_one("/test-umount/empty.mountinfo");
test_mount_points_list_one("/test-umount/garbled.mountinfo");
test_mount_points_list_one("/test-umount/rhbug-1554943.mountinfo");
}
static void test_swap_list_one(const char *fname) {
_cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
_cleanup_free_ char *testdata_fname = NULL;
MountPoint *m;
@ -61,14 +68,9 @@ static void test_swap_list(const char *fname) {
major(m->devnum), minor(m->devnum));
}
int main(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);
test_mount_points_list(NULL);
test_mount_points_list("/test-umount/empty.mountinfo");
test_mount_points_list("/test-umount/garbled.mountinfo");
test_mount_points_list("/test-umount/rhbug-1554943.mountinfo");
test_swap_list(NULL);
test_swap_list("/test-umount/example.swaps");
TEST(swap_list) {
test_swap_list_one(NULL);
test_swap_list_one("/test-umount/example.swaps");
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -7,7 +7,7 @@
#include "timesyncd-conf.h"
#include "tests.h"
static void test_manager_parse_string(void) {
TEST(manager_parse_string) {
/* Make sure that NTP_SERVERS is configured to something
* that we can actually parse successfully. */
@ -25,10 +25,4 @@ static void test_manager_parse_string(void) {
assert_se(manager_parse_server_string(m, SERVER_LINK, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0);
}
int main(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);
test_manager_parse_string();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -5,8 +5,9 @@
#include "fido_id_desc.h"
#include "macro.h"
#include "tests.h"
static void test_is_fido_security_token_desc__fido(void) {
TEST(is_fido_security_token_desc__fido) {
static const uint8_t FIDO_HID_DESC_1[] = {
0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
@ -27,7 +28,7 @@ static void test_is_fido_security_token_desc__fido(void) {
assert_se(is_fido_security_token_desc(FIDO_HID_DESC_2, sizeof(FIDO_HID_DESC_2)) > 0);
}
static void test_is_fido_security_token_desc__non_fido(void) {
TEST(is_fido_security_token_desc__non_fido) {
/* Wrong usage page */
static const uint8_t NON_FIDO_HID_DESC_1[] = {
0x06, 0xd0, 0xf0, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
@ -54,7 +55,7 @@ static void test_is_fido_security_token_desc__non_fido(void) {
assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_3, sizeof(NON_FIDO_HID_DESC_3)) == 0);
}
static void test_is_fido_security_token_desc__invalid(void) {
TEST(is_fido_security_token_desc__invalid) {
/* Size coded on 1 byte, but no byte given */
static const uint8_t INVALID_HID_DESC_1[] = { 0x01 };
assert_se(is_fido_security_token_desc(INVALID_HID_DESC_1, sizeof(INVALID_HID_DESC_1)) < 0);
@ -76,10 +77,4 @@ static void test_is_fido_security_token_desc__invalid(void) {
assert_se(is_fido_security_token_desc(INVALID_HID_DESC_5, sizeof(INVALID_HID_DESC_5)) < 0);
}
int main(int argc, char *argv[]) {
test_is_fido_security_token_desc__fido();
test_is_fido_security_token_desc__non_fido();
test_is_fido_security_token_desc__invalid();
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -3,9 +3,7 @@
#include "tests.h"
#include "udev-builtin.h"
static void test_udev_builtin_cmd_to_ptr(void) {
log_info("/* %s */", __func__);
TEST(udev_builtin_cmd_to_ptr) {
/* Those could have been static asserts, but ({}) is not allowed there. */
#if HAVE_BLKID
assert_se(UDEV_BUILTIN_CMD_TO_PTR(UDEV_BUILTIN_BLKID));
@ -19,8 +17,4 @@ static void test_udev_builtin_cmd_to_ptr(void) {
assert_se(PTR_TO_UDEV_BUILTIN_CMD((void*) 10000) == _UDEV_BUILTIN_INVALID);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_udev_builtin_cmd_to_ptr();
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -132,12 +132,10 @@ static void test_link_info_one(sd_netlink *rtnl, int ifindex) {
}
}
static void test_link_info_get(void) {
TEST(link_info_get) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
log_debug("/* %s */", __func__);
assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0) >= 0);
@ -156,10 +154,4 @@ static void test_link_info_get(void) {
}
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_link_info_get();
return 0;
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -13,7 +13,7 @@ static void test_udev_node_escape_path_one(const char *path, const char *expecte
assert_se(streq(buf, expected));
}
static void test_udev_node_escape_path(void) {
TEST(udev_node_escape_path) {
char a[NAME_MAX+1], b[NAME_MAX+1];
test_udev_node_escape_path_one("/disk/by-id/nvme-eui.1922908022470001001b448b44ccb9d6", "\\x2fdisk\\x2fby-id\\x2fnvme-eui.1922908022470001001b448b44ccb9d6");
@ -47,10 +47,4 @@ static void test_udev_node_escape_path(void) {
test_udev_node_escape_path_one(a, b);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_udev_node_escape_path();
return 0;
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -9,7 +9,7 @@
#include "tmpfile-util.h"
#include "xdg-autostart-service.h"
static void test_translate_name(void) {
TEST(translate_name) {
_cleanup_free_ char *t;
assert_se(t = xdg_autostart_service_translate_name("a-b.blub.desktop"));
@ -24,7 +24,7 @@ static void test_xdg_format_exec_start_one(const char *exec, const char *expecte
assert_se(streq(out, expected));
}
static void test_xdg_format_exec_start(void) {
TEST(xdg_format_exec_start) {
test_xdg_format_exec_start_one("/bin/sleep 100", "/bin/sleep \"100\"");
/* All standardised % identifiers are stripped. */
@ -50,7 +50,7 @@ static const char* const xdg_desktop_file[] = {
"Hidden=\t true\n"),
};
static void test_xdg_desktop_parse(unsigned i, const char *s) {
static void test_xdg_desktop_parse_one(unsigned i, const char *s) {
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-xdg-autostart-parser.XXXXXX";
_cleanup_fclose_ FILE *f = NULL;
_cleanup_(xdg_autostart_service_freep) XdgAutostartService *service = NULL;
@ -80,14 +80,9 @@ static void test_xdg_desktop_parse(unsigned i, const char *s) {
}
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_translate_name();
test_xdg_format_exec_start();
TEST(xdg_desktop_parse) {
for (size_t i = 0; i < ELEMENTSOF(xdg_desktop_file); i++)
test_xdg_desktop_parse(i, xdg_desktop_file[i]);
return 0;
test_xdg_desktop_parse_one(i, xdg_desktop_file[i]);
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -0,0 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
all setup run clean clean-again:
@TEST_BASE_DIR=../ ./test.sh --$@
.PHONY: all setup run clean clean-again

40
test/TEST-70-TPM2/test.sh Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
TEST_DESCRIPTION="cryptenroll/cryptsetup with TPM2 devices"
IMAGE_NAME="tpm2"
TEST_NO_NSPAWN=1
TEST_REQUIRE_INSTALL_TESTS=0
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
command -v swtpm >/dev/null 2>&1 || exit 0
command -v tpm2_pcrextend >/dev/null 2>&1 || exit 0
test_append_files() {
(
local workspace="${1:?}"
instmods tpm tpm_tis tpm_ibmvtpm
install_dmevent
generate_module_dependencies
inst_binary tpm2_pcrextend
)
}
machine="$(uname -m)"
tpmdevice="tpm-tis"
if [ "$machine" = "ppc64le" ]; then
# tpm-spapr support was introduced in qemu 5.0.0. Skip test for old qemu versions.
qemu_min_version "5.0.0" || exit 0
tpmdevice="tpm-spapr"
fi
tpmstate=$(mktemp -d)
swtpm socket --tpm2 --tpmstate dir="$tpmstate" --ctrl type=unixio,path="$tpmstate/sock" &
trap 'kill %%; rm -rf $tpmstate' SIGINT EXIT
QEMU_OPTIONS="-chardev socket,id=chrtpm,path=$tpmstate/sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device $tpmdevice,tpmdev=tpm0"
do_test "$@"

View File

@ -1213,7 +1213,7 @@ install_missing_libraries() {
local lib path
# A number of dependencies is now optional via dlopen, so the install
# script will not pick them up, since it looks at linkage.
for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu libfido2 libbpf libelf libdw; do
for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw; do
ddebug "Searching for $lib via pkg-config"
if pkg-config --exists "$lib"; then
path="$(pkg-config --variable=libdir "$lib")"

View File

@ -0,0 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
Description=TEST-70-TPM2
[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh

48
test/units/testsuite-70.sh Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
export SYSTEMD_LOG_LEVEL=debug
# Prepare fresh disk image
img="/var/tmp/test.img"
dd if=/dev/zero of=$img bs=1024k count=20 status=none
echo -n passphrase >/tmp/passphrase
cryptsetup luksFormat -q --use-urandom $img /tmp/passphrase
# Enroll unlock with default PCR policy
env PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto $img
/usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1
/usr/lib/systemd/systemd-cryptsetup detach test-volume
# Check with wrong PCR
tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000
/usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1 && { echo 'unexpected success'; exit 1; }
# Enroll unlock with PCR+PIN policy
systemd-cryptenroll --wipe-slot=tpm2 $img
env PASSWORD=passphrase NEWPIN=123456 systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=true $img
env PIN=123456 /usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1
/usr/lib/systemd/systemd-cryptsetup detach test-volume
# Check failure with wrong PIN
env PIN=123457 /usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1 && { echo 'unexpected success'; exit 1; }
# Check failure with wrong PCR (and correct PIN)
tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000
env PIN=123456 /usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1 && { echo 'unexpected success'; exit 1; }
# Enroll unlock with PCR 0+7
systemd-cryptenroll --wipe-slot=tpm2 $img
env PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 $img
/usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1
/usr/lib/systemd/systemd-cryptsetup detach test-volume
# Check with wrong PCR 0
tpm2_pcrextend 0:sha256=0000000000000000000000000000000000000000000000000000000000000000
/usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1 && exit 1
echo OK >/testok
exit 0