mirror of
https://github.com/systemd/systemd
synced 2026-03-24 07:44:52 +01:00
Compare commits
No commits in common. "7d963260a169199b4734c4f68a7319c2f7f7cfe5" and "a4d9c121cc011d3a4feeaa74f54a69de8c9b0b20" have entirely different histories.
7d963260a1
...
a4d9c121cc
@ -375,9 +375,6 @@ const char *special_glyph(SpecialGlyph code) {
|
||||
[SPECIAL_GLYPH_DEPRESSED_SMILEY] = ":-[",
|
||||
[SPECIAL_GLYPH_LOCK_AND_KEY] = "o-,",
|
||||
[SPECIAL_GLYPH_TOUCH] = "O=", /* Yeah, not very convincing, can you do it better? */
|
||||
[SPECIAL_GLYPH_RECYCLING] = "~",
|
||||
[SPECIAL_GLYPH_DOWNLOAD] = "\\",
|
||||
[SPECIAL_GLYPH_SPARKLES] = "*",
|
||||
},
|
||||
|
||||
/* UTF-8 */
|
||||
@ -424,12 +421,7 @@ const char *special_glyph(SpecialGlyph code) {
|
||||
[SPECIAL_GLYPH_LOCK_AND_KEY] = "\360\237\224\220", /* 🔐 (actually called: CLOSED LOCK WITH KEY) */
|
||||
|
||||
/* This emoji is a single character cell glyph in Unicode, and two in ASCII */
|
||||
[SPECIAL_GLYPH_TOUCH] = "\360\237\221\206", /* 👆 (actually called: BACKHAND INDEX POINTING UP) */
|
||||
|
||||
/* These three emojis are single character cell glyphs in Unicode and also in ASCII. */
|
||||
[SPECIAL_GLYPH_RECYCLING] = "\u267B\uFE0F ", /* ♻️ (actually called: UNIVERSAL RECYCLNG SYMBOL) */
|
||||
[SPECIAL_GLYPH_DOWNLOAD] = "\u2935\uFE0F ", /* ⤵️ (actually called: RIGHT ARROW CURVING DOWN) */
|
||||
[SPECIAL_GLYPH_SPARKLES] = "\u2728", /* ✨ */
|
||||
[SPECIAL_GLYPH_TOUCH] = "\360\237\221\206", /* 👆 (actually called: BACKHAND INDEX POINTING UP */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -69,9 +69,6 @@ typedef enum SpecialGlyph {
|
||||
SPECIAL_GLYPH_DEPRESSED_SMILEY,
|
||||
SPECIAL_GLYPH_LOCK_AND_KEY,
|
||||
SPECIAL_GLYPH_TOUCH,
|
||||
SPECIAL_GLYPH_RECYCLING,
|
||||
SPECIAL_GLYPH_DOWNLOAD,
|
||||
SPECIAL_GLYPH_SPARKLES,
|
||||
_SPECIAL_GLYPH_MAX,
|
||||
_SPECIAL_GLYPH_INVALID = -EINVAL,
|
||||
} SpecialGlyph;
|
||||
@ -98,7 +95,3 @@ static inline void locale_variables_freep(char*(*l)[_VARIABLE_LC_MAX]) {
|
||||
static inline const char *special_glyph_check_mark(bool b) {
|
||||
return b ? special_glyph(SPECIAL_GLYPH_CHECK_MARK) : special_glyph(SPECIAL_GLYPH_CROSS_MARK);
|
||||
}
|
||||
|
||||
static inline const char *special_glyph_check_mark_space(bool b) {
|
||||
return b ? special_glyph(SPECIAL_GLYPH_CHECK_MARK) : " ";
|
||||
}
|
||||
|
||||
@ -65,7 +65,6 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
||||
size_t secret_size, secret2_size, blob_size, hash_size;
|
||||
_cleanup_free_ void *blob = NULL, *hash = NULL;
|
||||
uint16_t pcr_bank;
|
||||
const char *node;
|
||||
int r, keyslot;
|
||||
|
||||
@ -76,7 +75,7 @@ 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);
|
||||
r = tpm2_seal(device, pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -93,7 +92,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, blob, blob_size, hash, hash_size, &secret2, &secret2_size);
|
||||
r = tpm2_unseal(device, pcr_mask, blob, blob_size, hash, hash_size, &secret2, &secret2_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -119,7 +118,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, blob, blob_size, hash, hash_size, &v);
|
||||
r = tpm2_make_luks2_json(keyslot, pcr_mask, blob, blob_size, hash, hash_size, &v);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@ int acquire_tpm2_key(
|
||||
const char *volume_name,
|
||||
const char *device,
|
||||
uint32_t pcr_mask,
|
||||
uint16_t pcr_bank,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
@ -63,7 +62,7 @@ int acquire_tpm2_key(
|
||||
blob = loaded_blob;
|
||||
}
|
||||
|
||||
return tpm2_unseal(device, pcr_mask, pcr_bank, blob, blob_size, policy_hash, policy_hash_size, ret_decrypted_key, ret_decrypted_key_size);
|
||||
return tpm2_unseal(device, pcr_mask, blob, blob_size, policy_hash, policy_hash_size, ret_decrypted_key, ret_decrypted_key_size);
|
||||
}
|
||||
|
||||
int find_tpm2_auto_data(
|
||||
@ -71,7 +70,6 @@ int find_tpm2_auto_data(
|
||||
uint32_t search_pcr_mask,
|
||||
int start_token,
|
||||
uint32_t *ret_pcr_mask,
|
||||
uint16_t *ret_pcr_bank,
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
void **ret_policy_hash,
|
||||
@ -83,7 +81,6 @@ int find_tpm2_auto_data(
|
||||
size_t blob_size = 0, policy_hash_size = 0;
|
||||
int r, keyslot = -1, token = -1;
|
||||
uint32_t pcr_mask = 0;
|
||||
uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
|
||||
|
||||
assert(cd);
|
||||
|
||||
@ -122,23 +119,6 @@ int find_tpm2_auto_data(
|
||||
search_pcr_mask != pcr_mask) /* PCR mask doesn't match what is configured, ignore this entry */
|
||||
continue;
|
||||
|
||||
/* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded to SHA256 */
|
||||
assert(pcr_bank == UINT16_MAX);
|
||||
w = json_variant_by_key(v, "tpm2-pcr-bank");
|
||||
if (w) {
|
||||
/* The PCR bank field is optional */
|
||||
|
||||
if (!json_variant_is_string(w))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"TPM2 PCR bank is not a string.");
|
||||
|
||||
r = tpm2_pcr_bank_from_string(json_variant_string(w));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
|
||||
|
||||
pcr_bank = r;
|
||||
}
|
||||
|
||||
assert(!blob);
|
||||
w = json_variant_by_key(v, "tpm2-blob");
|
||||
if (!w || !json_variant_is_string(w))
|
||||
@ -183,7 +163,6 @@ int find_tpm2_auto_data(
|
||||
*ret_policy_hash_size = policy_hash_size;
|
||||
*ret_keyslot = keyslot;
|
||||
*ret_token = token;
|
||||
*ret_pcr_bank = pcr_bank;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@ int acquire_tpm2_key(
|
||||
const char *volume_name,
|
||||
const char *device,
|
||||
uint32_t pcr_mask,
|
||||
uint16_t pcr_bank,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
@ -29,7 +28,6 @@ int find_tpm2_auto_data(
|
||||
uint32_t search_pcr_mask,
|
||||
int start_token,
|
||||
uint32_t *ret_pcr_mask,
|
||||
uint16_t *ret_pcr_bank,
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
void **ret_policy_hash,
|
||||
@ -43,7 +41,6 @@ static inline int acquire_tpm2_key(
|
||||
const char *volume_name,
|
||||
const char *device,
|
||||
uint32_t pcr_mask,
|
||||
uint16_t pcr_bank,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
@ -63,7 +60,6 @@ static inline int find_tpm2_auto_data(
|
||||
uint32_t search_pcr_mask,
|
||||
int start_token,
|
||||
uint32_t *ret_pcr_mask,
|
||||
uint16_t *ret_pcr_bank,
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
void **ret_policy_hash,
|
||||
|
||||
@ -1103,7 +1103,6 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
name,
|
||||
arg_tpm2_device,
|
||||
arg_tpm2_pcr_mask == UINT32_MAX ? TPM2_PCR_MASK_DEFAULT : arg_tpm2_pcr_mask,
|
||||
UINT16_MAX,
|
||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||
key_data, key_data_size,
|
||||
NULL, 0, /* we don't know the policy hash */
|
||||
@ -1140,14 +1139,12 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
|
||||
for (;;) {
|
||||
uint32_t pcr_mask;
|
||||
uint16_t pcr_bank;
|
||||
|
||||
r = find_tpm2_auto_data(
|
||||
cd,
|
||||
arg_tpm2_pcr_mask, /* if != UINT32_MAX we'll only look for tokens with this PCR mask */
|
||||
token, /* search for the token with this index, or any later index than this */
|
||||
&pcr_mask,
|
||||
&pcr_bank,
|
||||
&blob, &blob_size,
|
||||
&policy_hash, &policy_hash_size,
|
||||
&keyslot,
|
||||
@ -1169,7 +1166,6 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
name,
|
||||
arg_tpm2_device,
|
||||
pcr_mask,
|
||||
pcr_bank,
|
||||
NULL, 0, 0, /* no key file */
|
||||
blob, blob_size,
|
||||
policy_hash, policy_hash_size,
|
||||
|
||||
@ -2624,10 +2624,9 @@ static int partition_encrypt(
|
||||
_cleanup_(erase_and_freep) void *secret = NULL;
|
||||
_cleanup_free_ void *blob = NULL, *hash = NULL;
|
||||
size_t secret_size, blob_size, hash_size;
|
||||
uint16_t pcr_bank;
|
||||
int keyslot;
|
||||
|
||||
r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank);
|
||||
r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to seal to TPM2: %m");
|
||||
|
||||
@ -2649,7 +2648,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, blob, blob_size, hash, hash_size, &v);
|
||||
r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, blob, blob_size, hash, hash_size, &v);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");
|
||||
|
||||
|
||||
@ -369,10 +369,7 @@ struct _packed_ encrypted_credential_header {
|
||||
};
|
||||
|
||||
struct _packed_ tpm2_credential_header {
|
||||
le64_t pcr_mask; /* Note that the spec for PC Clients only mandates 24 PCRs, and that's what systems
|
||||
* generally have. But keep the door open for more. */
|
||||
le16_t pcr_bank; /* For now, either TPM2_ALG_SHA256 or TPM2_ALG_SHA1 */
|
||||
le16_t _zero; /* Filler to maintain 32bit alignment */
|
||||
le64_t pcr_mask;
|
||||
le32_t blob_size;
|
||||
le32_t policy_hash_size;
|
||||
uint8_t policy_hash_and_blob[];
|
||||
@ -442,7 +439,6 @@ int encrypt_credential_and_warn(
|
||||
struct encrypted_credential_header *h;
|
||||
int ksz, bsz, ivsz, tsz, added, r;
|
||||
uint8_t md[SHA256_DIGEST_LENGTH];
|
||||
uint16_t tpm2_pcr_bank = 0;
|
||||
const EVP_CIPHER *cc;
|
||||
#if HAVE_TPM2
|
||||
bool try_tpm2 = false;
|
||||
@ -509,8 +505,7 @@ int encrypt_credential_and_warn(
|
||||
&tpm2_blob,
|
||||
&tpm2_blob_size,
|
||||
&tpm2_policy_hash,
|
||||
&tpm2_policy_hash_size,
|
||||
&tpm2_pcr_bank);
|
||||
&tpm2_policy_hash_size);
|
||||
if (r < 0) {
|
||||
if (!sd_id128_is_null(with_key))
|
||||
return r;
|
||||
@ -603,7 +598,6 @@ int encrypt_credential_and_warn(
|
||||
|
||||
t = (struct tpm2_credential_header*) ((uint8_t*) output + p);
|
||||
t->pcr_mask = htole64(tpm2_pcr_mask);
|
||||
t->pcr_bank = htole16(tpm2_pcr_bank);
|
||||
t->blob_size = htole32(tpm2_blob_size);
|
||||
t->policy_hash_size = htole32(tpm2_policy_hash_size);
|
||||
memcpy(t->policy_hash_and_blob, tpm2_blob, tpm2_blob_size);
|
||||
@ -745,10 +739,6 @@ int decrypt_credential_and_warn(
|
||||
|
||||
if (le64toh(t->pcr_mask) >= (UINT64_C(1) << TPM2_PCRS_MAX))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR mask out of range.");
|
||||
if (!tpm2_pcr_bank_supported(le16toh(t->pcr_bank)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR bank invalid or not supported");
|
||||
if (le16toh(t->_zero) != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 padding space not zero.");
|
||||
if (le32toh(t->blob_size) > CREDENTIAL_FIELD_SIZE_MAX)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected TPM2 blob size.");
|
||||
if (le32toh(t->policy_hash_size) > CREDENTIAL_FIELD_SIZE_MAX)
|
||||
@ -765,7 +755,6 @@ int decrypt_credential_and_warn(
|
||||
|
||||
r = tpm2_unseal(tpm2_device,
|
||||
le64toh(t->pcr_mask),
|
||||
le16toh(t->pcr_bank),
|
||||
t->policy_hash_and_blob,
|
||||
le32toh(t->blob_size),
|
||||
t->policy_hash_and_blob + le32toh(t->blob_size),
|
||||
|
||||
@ -14,114 +14,53 @@
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static const char *skip_protocol_and_hostname(const char *url) {
|
||||
const char *d;
|
||||
size_t n;
|
||||
int import_url_last_component(const char *url, char **ret) {
|
||||
const char *e, *p;
|
||||
char *s;
|
||||
|
||||
/* A very very lenient implementation of RFC3986 Section 3.2 */
|
||||
e = strchrnul(url, '?');
|
||||
|
||||
/* Find colon separating protocol and hostname */
|
||||
d = strchr(url, ':');
|
||||
if (!d || url == d)
|
||||
return NULL;
|
||||
d++;
|
||||
|
||||
/* Skip slashes after colon */
|
||||
d += strspn(d, "/");
|
||||
|
||||
/* Skip everything till next slash or end */
|
||||
n = strcspn(d, "/?#");
|
||||
if (n == 0)
|
||||
return NULL;
|
||||
|
||||
return d + n;
|
||||
}
|
||||
|
||||
int import_url_last_component(
|
||||
const char *url,
|
||||
char **ret) {
|
||||
|
||||
const char *e, *p, *h;
|
||||
|
||||
/* This extracts the last path component of the specified URI, i.e. the last non-empty substrings
|
||||
* between two "/" characters. This ignores "Query" and "Fragment" suffixes (as per RFC3986). */
|
||||
|
||||
h = skip_protocol_and_hostname(url);
|
||||
if (!h)
|
||||
return -EINVAL;
|
||||
|
||||
e = h + strcspn(h, "?#"); /* Cut off "Query" and "Fragment" */
|
||||
|
||||
while (e > h && e[-1] == '/') /* Eat trailing slashes */
|
||||
while (e > url && e[-1] == '/')
|
||||
e--;
|
||||
|
||||
p = e;
|
||||
while (p > h && p[-1] != '/') /* Find component before that */
|
||||
while (p > url && p[-1] != '/')
|
||||
p--;
|
||||
|
||||
if (e <= p) /* Empty component? */
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (ret) {
|
||||
char *s;
|
||||
if (e <= p)
|
||||
return -EINVAL;
|
||||
|
||||
s = strndup(p, e - p);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = s;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int import_url_change_suffix(
|
||||
const char *url,
|
||||
size_t n_drop_components,
|
||||
const char *suffix,
|
||||
char **ret) {
|
||||
|
||||
const char *e, *h;
|
||||
int import_url_change_last_component(const char *url, const char *suffix, char **ret) {
|
||||
const char *e;
|
||||
char *s;
|
||||
|
||||
assert(url);
|
||||
assert(ret);
|
||||
|
||||
/* This drops the specified number of path components of the specified URI, i.e. the specified number
|
||||
* of non-empty substring between two "/" characters from the end of the string, and then append the
|
||||
* specified suffix instead. Before doing all this it chops off the "Query" and "Fragment" suffixes
|
||||
* (they are *not* readded to the final URL). Note that n_drop_components may be 0 (in which case the
|
||||
* component are simply added to the end). The suffix may be specified as NULL or empty string in
|
||||
* which case nothing is appended, only the specified number of components chopped off. Note that the
|
||||
* function may be called with n_drop_components == 0 and suffix == NULL, in which case the "Query"
|
||||
* and "Fragment" is chopped off, and ensured the URL ends in a single "/", and that's it. */
|
||||
e = strchrnul(url, '?');
|
||||
|
||||
h = skip_protocol_and_hostname(url);
|
||||
if (!h)
|
||||
while (e > url && e[-1] == '/')
|
||||
e--;
|
||||
|
||||
while (e > url && e[-1] != '/')
|
||||
e--;
|
||||
|
||||
if (e <= url)
|
||||
return -EINVAL;
|
||||
|
||||
e = h + strcspn(h, "?#"); /* Cut off "Query" and "Fragment" */
|
||||
|
||||
while (e > h && e[-1] == '/') /* Eat trailing slashes */
|
||||
e--;
|
||||
|
||||
/* Drop the specified number of components from the end. Note that this is pretty lenient: if there
|
||||
* are less component we silently drop those and then append the suffix to the top. */
|
||||
while (n_drop_components > 0) {
|
||||
while (e > h && e[-1] != '/') /* Eat last word (we don't mind if empty) */
|
||||
e--;
|
||||
|
||||
while (e > h && e[-1] == '/') /* Eat slashes before the last word */
|
||||
e--;
|
||||
|
||||
n_drop_components--;
|
||||
}
|
||||
|
||||
s = new(char, (e - url) + 1 + strlen_ptr(suffix) + 1);
|
||||
s = new(char, (e - url) + strlen(suffix) + 1);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(stpcpy(mempcpy(s, url, e - url), "/"), strempty(suffix));
|
||||
strcpy(mempcpy(s, url, e - url), suffix);
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -14,16 +14,7 @@ typedef enum ImportVerify {
|
||||
} ImportVerify;
|
||||
|
||||
int import_url_last_component(const char *url, char **ret);
|
||||
|
||||
int import_url_change_suffix(const char *url, size_t n_drop_components, const char *suffix, char **ret);
|
||||
|
||||
static inline int import_url_change_last_component(const char *url, const char *suffix, char **ret) {
|
||||
return import_url_change_suffix(url, 1, suffix, ret);
|
||||
}
|
||||
|
||||
static inline int import_url_append_component(const char *url, const char *suffix, char **ret) {
|
||||
return import_url_change_suffix(url, 0, suffix, ret);
|
||||
}
|
||||
int import_url_change_last_component(const char *url, const char *suffix, char **ret);
|
||||
|
||||
const char* import_verify_to_string(ImportVerify v) _const_;
|
||||
ImportVerify import_verify_from_string(const char *s) _pure_;
|
||||
|
||||
@ -19,9 +19,6 @@
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
/* We treat tmpfs/ramfs + cgroupfs as non-physical file sytems. cgroupfs is similar to tmpfs in a way after
|
||||
* all: we can create arbitrary directory hierarchies in it, and hence can also use rm_rf() on it to remove
|
||||
* those again. */
|
||||
static bool is_physical_fs(const struct statfs *sfs) {
|
||||
return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs);
|
||||
}
|
||||
@ -116,145 +113,133 @@ int fstatat_harder(int dfd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rm_rf_children_inner(
|
||||
int fd,
|
||||
const char *fname,
|
||||
int is_dir,
|
||||
RemoveFlags flags,
|
||||
const struct stat *root_dev) {
|
||||
|
||||
struct stat st;
|
||||
int r;
|
||||
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
int ret = 0, r;
|
||||
struct statfs sfs;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(fname);
|
||||
|
||||
if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) {
|
||||
/* This returns the first error we run into, but nevertheless tries to go on. This closes the passed
|
||||
* fd, in all cases, including on failure.. */
|
||||
|
||||
r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!(flags & REMOVE_PHYSICAL)) {
|
||||
|
||||
r = fstatfs(fd, &sfs);
|
||||
if (r < 0) {
|
||||
safe_close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (is_physical_fs(&sfs)) {
|
||||
/* We refuse to clean physical file systems with this call,
|
||||
* unless explicitly requested. This is extra paranoia just
|
||||
* to be sure we never ever remove non-state data. */
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
(void) fd_get_path(fd, &path);
|
||||
log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.",
|
||||
strna(path));
|
||||
|
||||
safe_close(fd);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
d = fdopendir(fd);
|
||||
if (!d) {
|
||||
safe_close(fd);
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
}
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
bool is_dir;
|
||||
struct stat st;
|
||||
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
|
||||
if (de->d_type == DT_UNKNOWN ||
|
||||
(de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) {
|
||||
r = fstatat_harder(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW, flags);
|
||||
if (r < 0) {
|
||||
if (ret == 0 && r != -ENOENT)
|
||||
ret = r;
|
||||
continue;
|
||||
}
|
||||
|
||||
is_dir = S_ISDIR(st.st_mode);
|
||||
}
|
||||
} else
|
||||
is_dir = de->d_type == DT_DIR;
|
||||
|
||||
if (is_dir) {
|
||||
_cleanup_close_ int subdir_fd = -1;
|
||||
int q;
|
||||
|
||||
/* if root_dev is set, remove subdirectories only if device is same */
|
||||
if (root_dev && st.st_dev != root_dev->st_dev)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
|
||||
if (subdir_fd < 0) {
|
||||
if (ret == 0 && errno != ENOENT)
|
||||
ret = -errno;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Stop at mount points */
|
||||
r = fd_is_mount_point(fd, fname, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = fd_is_mount_point(fd, de->d_name, 0);
|
||||
if (r < 0) {
|
||||
if (ret == 0 && r != -ENOENT)
|
||||
ret = r;
|
||||
|
||||
continue;
|
||||
}
|
||||
if (r > 0)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) {
|
||||
|
||||
/* This could be a subvolume, try to remove it */
|
||||
|
||||
r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
|
||||
r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
|
||||
if (r < 0) {
|
||||
if (!IN_SET(r, -ENOTTY, -EINVAL))
|
||||
return r;
|
||||
if (!IN_SET(r, -ENOTTY, -EINVAL)) {
|
||||
if (ret == 0)
|
||||
ret = r;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ENOTTY, then it wasn't a btrfs subvolume, continue below. */
|
||||
} else
|
||||
/* It was a subvolume, done. */
|
||||
return 1;
|
||||
/* It was a subvolume, continue. */
|
||||
continue;
|
||||
}
|
||||
|
||||
subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
|
||||
if (subdir_fd < 0)
|
||||
return -errno;
|
||||
/* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file
|
||||
* system type again for each directory */
|
||||
r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
|
||||
if (r < 0 && ret == 0)
|
||||
ret = r;
|
||||
|
||||
/* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type
|
||||
* again for each directory */
|
||||
q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
|
||||
|
||||
r = unlinkat_harder(fd, fname, AT_REMOVEDIR, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (q < 0)
|
||||
return q;
|
||||
|
||||
return 1;
|
||||
r = unlinkat_harder(fd, de->d_name, AT_REMOVEDIR, flags);
|
||||
if (r < 0 && r != -ENOENT && ret == 0)
|
||||
ret = r;
|
||||
|
||||
} else if (!(flags & REMOVE_ONLY_DIRECTORIES)) {
|
||||
r = unlinkat_harder(fd, fname, 0, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rm_rf_children(
|
||||
int fd,
|
||||
RemoveFlags flags,
|
||||
const struct stat *root_dev) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
int ret = 0, r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
/* This returns the first error we run into, but nevertheless tries to go on. This closes the passed
|
||||
* fd, in all cases, including on failure. */
|
||||
|
||||
d = fdopendir(fd);
|
||||
if (!d) {
|
||||
safe_close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!(flags & REMOVE_PHYSICAL)) {
|
||||
struct statfs sfs;
|
||||
|
||||
if (fstatfs(dirfd(d), &sfs) < 0)
|
||||
return -errno;
|
||||
|
||||
if (is_physical_fs(&sfs)) {
|
||||
/* We refuse to clean physical file systems with this call, unless explicitly
|
||||
* requested. This is extra paranoia just to be sure we never ever remove non-state
|
||||
* data. */
|
||||
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
(void) fd_get_path(fd, &path);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"Attempted to remove disk file system under \"%s\", and we can't allow that.",
|
||||
strna(path));
|
||||
}
|
||||
}
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
int is_dir;
|
||||
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
|
||||
is_dir =
|
||||
de->d_type == DT_UNKNOWN ? -1 :
|
||||
de->d_type == DT_DIR;
|
||||
|
||||
r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev);
|
||||
r = unlinkat_harder(fd, de->d_name, 0, flags);
|
||||
if (r < 0 && r != -ENOENT && ret == 0)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rm_rf(const char *path, RemoveFlags flags) {
|
||||
int fd, r;
|
||||
struct statfs s;
|
||||
|
||||
assert(path);
|
||||
|
||||
@ -299,10 +284,9 @@ int rm_rf(const char *path, RemoveFlags flags) {
|
||||
if (FLAGS_SET(flags, REMOVE_ROOT)) {
|
||||
|
||||
if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) {
|
||||
struct statfs s;
|
||||
|
||||
if (statfs(path, &s) < 0)
|
||||
return -errno;
|
||||
|
||||
if (is_physical_fs(&s))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"Attempted to remove files from a disk file system under \"%s\", refusing.",
|
||||
@ -330,22 +314,3 @@ int rm_rf(const char *path, RemoveFlags flags) {
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int rm_rf_child(int fd, const char *name, RemoveFlags flags) {
|
||||
|
||||
/* Removes one specific child of the specified directory */
|
||||
|
||||
if (fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
if (!filename_is_valid(name))
|
||||
return -EINVAL;
|
||||
|
||||
if ((flags & (REMOVE_ROOT|REMOVE_MISSING_OK)) != 0) /* Doesn't really make sense here, we are not supposed to remove 'fd' anyway */
|
||||
return -EINVAL;
|
||||
|
||||
if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME))
|
||||
return -EINVAL;
|
||||
|
||||
return rm_rf_children_inner(fd, name, -1, flags, NULL);
|
||||
}
|
||||
|
||||
@ -23,8 +23,7 @@ int fstatat_harder(int dfd,
|
||||
int fstatat_flags,
|
||||
RemoveFlags remove_flags);
|
||||
|
||||
int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev);
|
||||
int rm_rf_child(int fd, const char *name, RemoveFlags flags);
|
||||
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
|
||||
int rm_rf(const char *path, RemoveFlags flags);
|
||||
|
||||
/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
|
||||
|
||||
@ -25,7 +25,6 @@ TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR primaryHand
|
||||
void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
|
||||
TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
|
||||
void (*sym_Esys_Free)(void *ptr) = NULL;
|
||||
TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData);
|
||||
TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
|
||||
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;
|
||||
@ -52,7 +51,6 @@ int dlopen_tpm2(void) {
|
||||
DLSYM_ARG(Esys_Finalize),
|
||||
DLSYM_ARG(Esys_FlushContext),
|
||||
DLSYM_ARG(Esys_Free),
|
||||
DLSYM_ARG(Esys_GetCapability),
|
||||
DLSYM_ARG(Esys_GetRandom),
|
||||
DLSYM_ARG(Esys_Initialize),
|
||||
DLSYM_ARG(Esys_Load),
|
||||
@ -312,93 +310,11 @@ static int tpm2_make_primary(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpm2_get_best_pcr_bank(
|
||||
ESYS_CONTEXT *c,
|
||||
TPMI_ALG_HASH *ret) {
|
||||
|
||||
_cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
|
||||
TPMI_ALG_HASH hash = TPM2_ALG_SHA1;
|
||||
bool found = false;
|
||||
TPMI_YES_NO more;
|
||||
TSS2_RC rc;
|
||||
|
||||
rc = sym_Esys_GetCapability(
|
||||
c,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
TPM2_CAP_PCRS,
|
||||
0,
|
||||
1,
|
||||
&more,
|
||||
&pcap);
|
||||
if (rc != TSS2_RC_SUCCESS)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
|
||||
|
||||
assert(pcap->capability == TPM2_CAP_PCRS);
|
||||
|
||||
for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
|
||||
bool valid = true;
|
||||
|
||||
/* As per
|
||||
* https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
|
||||
* TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over
|
||||
* it. */
|
||||
if (pcap->data.assignedPCR.pcrSelections[i].sizeofSelect < TPM2_PCRS_MAX/8) {
|
||||
log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
|
||||
strna(tpm2_pcr_bank_to_string(pcap->data.assignedPCR.pcrSelections[i].hash)));
|
||||
continue;
|
||||
}
|
||||
|
||||
assert_cc(TPM2_PCRS_MAX % 8 == 0);
|
||||
|
||||
/* It's not enought to check how many PCRs there are, we also need to check that the 24 are
|
||||
* enabled for this bank. Otherwise this TPM doesn't qualify. */
|
||||
for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
|
||||
if (pcap->data.assignedPCR.pcrSelections[i].pcrSelect[j] != 0xFF) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
|
||||
strna(tpm2_pcr_bank_to_string(pcap->data.assignedPCR.pcrSelections[i].hash)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA256) {
|
||||
hash = TPM2_ALG_SHA256;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA1)
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
|
||||
|
||||
if (hash == TPM2_ALG_SHA256)
|
||||
log_debug("TPM2 device supports SHA256 PCR banks, yay!");
|
||||
else {
|
||||
assert(hash == TPM2_ALG_SHA1);
|
||||
log_debug("TPM2 device lacks support for SHA256 PCR banks, falling back to SHA1 banks.");
|
||||
}
|
||||
|
||||
*ret = hash;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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. */
|
||||
ESYS_TR *ret_session,
|
||||
TPM2B_DIGEST **ret_policy_digest,
|
||||
TPMI_ALG_HASH *ret_pcr_bank) {
|
||||
TPM2B_DIGEST **ret_policy_digest) {
|
||||
|
||||
static const TPMT_SYM_DEF symmetric = {
|
||||
.algorithm = TPM2_ALG_AES,
|
||||
@ -411,7 +327,7 @@ static int tpm2_make_pcr_session(
|
||||
};
|
||||
TPML_PCR_SELECTION pcr_selection = {
|
||||
.count = 1,
|
||||
.pcrSelections[0].hash = TPM2_ALG_SHA256, /* overriden below, depending on TPM2 capabilities */
|
||||
.pcrSelections[0].hash = TPM2_ALG_SHA256,
|
||||
.pcrSelections[0].sizeofSelect = 3,
|
||||
.pcrSelections[0].pcrSelect[0] = pcr_mask & 0xFF,
|
||||
.pcrSelections[0].pcrSelect[1] = (pcr_mask >> 8) & 0xFF,
|
||||
@ -426,16 +342,6 @@ static int tpm2_make_pcr_session(
|
||||
|
||||
log_debug("Starting authentication session.");
|
||||
|
||||
if (pcr_bank != UINT16_MAX)
|
||||
pcr_selection.pcrSelections[0].hash = pcr_bank;
|
||||
else {
|
||||
/* No bank configured, pick automatically. Some TPM2 devices only can do SHA1. If we detect
|
||||
* that use that, but preferably use SHA256 */
|
||||
r = tpm2_get_best_pcr_bank(c, &pcr_selection.pcrSelections[0].hash);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
rc = sym_Esys_StartAuthSession(
|
||||
c,
|
||||
ESYS_TR_NONE,
|
||||
@ -506,9 +412,6 @@ static int tpm2_make_pcr_session(
|
||||
if (ret_policy_digest)
|
||||
*ret_policy_digest = TAKE_PTR(policy_digest);
|
||||
|
||||
if (ret_pcr_bank)
|
||||
*ret_pcr_bank = pcr_selection.pcrSelections[0].hash;
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
@ -524,8 +427,7 @@ int tpm2_seal(
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
void **ret_pcr_hash,
|
||||
size_t *ret_pcr_hash_size,
|
||||
uint16_t *ret_pcr_bank) {
|
||||
size_t *ret_pcr_hash_size) {
|
||||
|
||||
_cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
|
||||
_cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
|
||||
@ -537,7 +439,6 @@ int tpm2_seal(
|
||||
TPM2B_SENSITIVE_CREATE hmac_sensitive;
|
||||
ESYS_TR primary = ESYS_TR_NONE;
|
||||
TPM2B_PUBLIC hmac_template;
|
||||
TPMI_ALG_HASH pcr_bank;
|
||||
size_t k, blob_size;
|
||||
usec_t start;
|
||||
TSS2_RC rc;
|
||||
@ -549,7 +450,6 @@ int tpm2_seal(
|
||||
assert(ret_blob_size);
|
||||
assert(ret_pcr_hash);
|
||||
assert(ret_pcr_hash_size);
|
||||
assert(ret_pcr_bank);
|
||||
|
||||
assert(pcr_mask < (UINT32_C(1) << TPM2_PCRS_MAX)); /* Support 24 PCR banks */
|
||||
|
||||
@ -578,7 +478,7 @@ 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, NULL, &policy_digest);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -700,7 +600,6 @@ int tpm2_seal(
|
||||
*ret_blob_size = blob_size;
|
||||
*ret_pcr_hash = TAKE_PTR(hash);
|
||||
*ret_pcr_hash_size = policy_digest->size;
|
||||
*ret_pcr_bank = pcr_bank;
|
||||
|
||||
r = 0;
|
||||
|
||||
@ -712,7 +611,6 @@ finish:
|
||||
int tpm2_unseal(
|
||||
const char *device,
|
||||
uint32_t pcr_mask,
|
||||
uint16_t pcr_bank,
|
||||
const void *blob,
|
||||
size_t blob_size,
|
||||
const void *known_policy_hash,
|
||||
@ -772,7 +670,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, &session, &policy_digest);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -1011,7 +909,6 @@ 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,
|
||||
const void *blob,
|
||||
size_t blob_size,
|
||||
const void *policy_hash,
|
||||
@ -1054,7 +951,6 @@ int tpm2_make_luks2_json(
|
||||
JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
|
||||
JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
|
||||
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("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size))));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1064,36 +960,3 @@ int tpm2_make_luks2_json(
|
||||
|
||||
return keyslot;
|
||||
}
|
||||
|
||||
/* We want the helpers below to work also if TPM2 libs are not available, hence define these two defines if
|
||||
* they are missing. */
|
||||
#ifndef TPM2_ALG_SHA256
|
||||
#define TPM2_ALG_SHA256 0xB
|
||||
#endif
|
||||
|
||||
#ifndef TPM2_ALG_SHA1
|
||||
#define TPM2_ALG_SHA1 0x4
|
||||
#endif
|
||||
|
||||
int tpm2_pcr_bank_supported(uint16_t bank) {
|
||||
/* For now, let's officially only support these two. We can extend this later on, should the need
|
||||
* arise. */
|
||||
return IN_SET(bank, TPM2_ALG_SHA256, TPM2_ALG_SHA1);
|
||||
}
|
||||
|
||||
const char *tpm2_pcr_bank_to_string(uint16_t bank) {
|
||||
/* Similar here, only support the two for now, we can always extend this later. */
|
||||
if (bank == TPM2_ALG_SHA256)
|
||||
return "sha256";
|
||||
if (bank == TPM2_ALG_SHA1)
|
||||
return "sha1";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tpm2_pcr_bank_from_string(const char *bank) {
|
||||
if (streq_ptr(bank, "sha256"))
|
||||
return TPM2_ALG_SHA256;
|
||||
if (streq_ptr(bank, "sha1"))
|
||||
return TPM2_ALG_SHA1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -15,7 +15,6 @@ extern TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR prim
|
||||
extern void (*sym_Esys_Finalize)(ESYS_CONTEXT **context);
|
||||
extern TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle);
|
||||
extern void (*sym_Esys_Free)(void *ptr);
|
||||
extern TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData);
|
||||
extern TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes);
|
||||
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);
|
||||
@ -34,8 +33,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);
|
||||
int tpm2_unseal(const char *device, uint32_t pcr_mask, uint16_t pcr_bank, 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, 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);
|
||||
int tpm2_unseal(const char *device, uint32_t pcr_mask, const void *blob, size_t blob_size, const void *pcr_hash, size_t pcr_hash_size, void **ret_secret, size_t *ret_secret_size);
|
||||
|
||||
#endif
|
||||
|
||||
@ -44,17 +43,13 @@ 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, 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, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, JsonVariant **ret);
|
||||
|
||||
#define TPM2_PCRS_MAX 24
|
||||
|
||||
/* Default to PCR 7 only */
|
||||
#define TPM2_PCR_MASK_DEFAULT (UINT32_C(1) << 7)
|
||||
|
||||
int tpm2_pcr_bank_supported(uint16_t bank);
|
||||
const char *tpm2_pcr_bank_to_string(uint16_t bank);
|
||||
int tpm2_pcr_bank_from_string(const char *bank);
|
||||
|
||||
typedef struct {
|
||||
uint32_t search_pcr_mask;
|
||||
const char *device;
|
||||
|
||||
@ -250,8 +250,6 @@ tests += [
|
||||
|
||||
[['src/test/test-sysctl-util.c']],
|
||||
|
||||
[['src/test/test-import-util.c']],
|
||||
|
||||
[['src/test/test-user-record.c']],
|
||||
|
||||
[['src/test/test-user-util.c']],
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "import-util.h"
|
||||
#include "log.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
static void test_import_url_last_component_one(const char *input, const char *output, int ret) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
assert_se(import_url_last_component(input, &s) == ret);
|
||||
assert_se(streq_ptr(output, s));
|
||||
}
|
||||
|
||||
static void test_import_url_last_component(void) {
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux", "quux", 0);
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux/", "quux", 0);
|
||||
test_import_url_last_component_one("https://foobar/waldo/", "waldo", 0);
|
||||
test_import_url_last_component_one("https://foobar/", NULL, -EADDRNOTAVAIL);
|
||||
test_import_url_last_component_one("https://foobar", NULL, -EADDRNOTAVAIL);
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux?foo=bar", "quux", 0);
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux/?foo=bar", "quux", 0);
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux/?foo=bar#piep", "quux", 0);
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux/#piep", "quux", 0);
|
||||
test_import_url_last_component_one("https://foobar/waldo/quux#piep", "quux", 0);
|
||||
test_import_url_last_component_one("https://", NULL, -EINVAL);
|
||||
test_import_url_last_component_one("", NULL, -EINVAL);
|
||||
test_import_url_last_component_one(":", NULL, -EINVAL);
|
||||
test_import_url_last_component_one(":/", NULL, -EINVAL);
|
||||
test_import_url_last_component_one("x:/", NULL, -EINVAL);
|
||||
test_import_url_last_component_one("x:y", NULL, -EADDRNOTAVAIL);
|
||||
test_import_url_last_component_one("x:y/z", "z", 0);
|
||||
}
|
||||
|
||||
static void test_import_url_change_suffix_one(const char *input, size_t n, const char *suffix, const char *output, int ret) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
assert_se(import_url_change_suffix(input, n, suffix, &s) == ret);
|
||||
assert_se(streq_ptr(output, s));
|
||||
}
|
||||
|
||||
static void test_import_url_change_suffix(void) {
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux", 1, "wuff", "https://foobar/waldo/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux/", 1, "wuff", "https://foobar/waldo/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux///?mief", 1, "wuff", "https://foobar/waldo/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux///?mief#opopo", 1, "wuff", "https://foobar/waldo/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux/quff", 2, "wuff", "https://foobar/waldo/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux/quff/", 2, "wuff", "https://foobar/waldo/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux/quff", 0, "wuff", "https://foobar/waldo/quux/quff/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://foobar/waldo/quux/quff?aa?bb##4", 0, "wuff", "https://foobar/waldo/quux/quff/wuff", 0);
|
||||
test_import_url_change_suffix_one("https://", 0, "wuff", NULL, -EINVAL);
|
||||
test_import_url_change_suffix_one("", 0, "wuff", NULL, -EINVAL);
|
||||
test_import_url_change_suffix_one(":", 0, "wuff", NULL, -EINVAL);
|
||||
test_import_url_change_suffix_one(":/", 0, "wuff", NULL, -EINVAL);
|
||||
test_import_url_change_suffix_one("x:/", 0, "wuff", NULL, -EINVAL);
|
||||
test_import_url_change_suffix_one("x:y", 0, "wuff", "x:y/wuff", 0);
|
||||
test_import_url_change_suffix_one("x:y/z", 0, "wuff", "x:y/z/wuff", 0);
|
||||
test_import_url_change_suffix_one("x:y/z/", 0, "wuff", "x:y/z/wuff", 0);
|
||||
test_import_url_change_suffix_one("x:y/z/", 1, "wuff", "x:y/wuff", 0);
|
||||
test_import_url_change_suffix_one("x:y/z/", 2, "wuff", "x:y/wuff", 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
test_import_url_last_component();
|
||||
test_import_url_change_suffix();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -89,7 +89,7 @@ static void test_keymaps(void) {
|
||||
|
||||
#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
|
||||
static void dump_special_glyphs(void) {
|
||||
assert_cc(SPECIAL_GLYPH_SPARKLES + 1 == _SPECIAL_GLYPH_MAX);
|
||||
assert_cc(SPECIAL_GLYPH_TOUCH + 1 == _SPECIAL_GLYPH_MAX);
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
@ -120,9 +120,6 @@ static void dump_special_glyphs(void) {
|
||||
dump_glyph(SPECIAL_GLYPH_DEPRESSED_SMILEY);
|
||||
dump_glyph(SPECIAL_GLYPH_LOCK_AND_KEY);
|
||||
dump_glyph(SPECIAL_GLYPH_TOUCH);
|
||||
dump_glyph(SPECIAL_GLYPH_RECYCLING);
|
||||
dump_glyph(SPECIAL_GLYPH_DOWNLOAD);
|
||||
dump_glyph(SPECIAL_GLYPH_SPARKLES);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user