mirror of
https://github.com/systemd/systemd
synced 2024-10-15 04:24:19 +00:00
Merge pull request #31889 from aplanas/fix_pcrlock_stdin
pcrlock: support measurement of big files
This commit is contained in:
commit
6e10417ff6
|
@ -2679,7 +2679,7 @@ static int make_pcrlock_record(
|
|||
assert_se(a = tpm2_hash_alg_to_string(*pa));
|
||||
assert_se(md = EVP_get_digestbyname(a));
|
||||
hash_ssize = EVP_MD_size(md);
|
||||
assert_se(hash_ssize > 0);
|
||||
assert(hash_ssize > 0);
|
||||
hash_usize = hash_ssize;
|
||||
|
||||
hash = malloc(hash_usize);
|
||||
|
@ -2708,6 +2708,101 @@ static int make_pcrlock_record(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void evp_md_ctx_free_all(EVP_MD_CTX *(*md)[TPM2_N_HASH_ALGORITHMS]) {
|
||||
assert(md);
|
||||
FOREACH_ARRAY(alg, *md, TPM2_N_HASH_ALGORITHMS)
|
||||
if (*alg)
|
||||
EVP_MD_CTX_free(*alg);
|
||||
}
|
||||
|
||||
static int make_pcrlock_record_from_stream(
|
||||
uint32_t pcr_mask,
|
||||
FILE *f,
|
||||
JsonVariant **ret_records) {
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *digests = NULL;
|
||||
_cleanup_(evp_md_ctx_free_all) EVP_MD_CTX *mdctx[TPM2_N_HASH_ALGORITHMS] = {};
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
assert(ret_records);
|
||||
|
||||
for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++) {
|
||||
const char *a;
|
||||
const EVP_MD *md;
|
||||
|
||||
assert_se(a = tpm2_hash_alg_to_string(tpm2_hash_algorithms[i]));
|
||||
assert_se(md = EVP_get_digestbyname(a));
|
||||
|
||||
mdctx[i] = EVP_MD_CTX_new();
|
||||
if (!mdctx[i])
|
||||
return log_oom();
|
||||
|
||||
if (EVP_DigestInit_ex(mdctx[i], md, NULL) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to initialize message digest for %s.", a);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
uint8_t buffer[64*1024];
|
||||
size_t n;
|
||||
|
||||
n = fread(buffer, 1, sizeof(buffer), f);
|
||||
if (ferror(f))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to read file: %m");
|
||||
if (n == 0 && feof(f))
|
||||
break;
|
||||
|
||||
for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++)
|
||||
if (EVP_DigestUpdate(mdctx[i], buffer, n) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data.");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++) {
|
||||
const char *a;
|
||||
int hash_ssize;
|
||||
unsigned hash_usize;
|
||||
|
||||
assert_se(a = tpm2_hash_alg_to_string(tpm2_hash_algorithms[i]));
|
||||
hash_ssize = EVP_MD_CTX_size(mdctx[i]);
|
||||
assert(hash_ssize > 0 && hash_ssize <= EVP_MAX_MD_SIZE);
|
||||
hash_usize = hash_ssize;
|
||||
unsigned char hash[hash_usize];
|
||||
|
||||
if (EVP_DigestFinal_ex(mdctx[i], hash, &hash_usize) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to finalize hash context for algorithn '%s'.", a);
|
||||
|
||||
r = json_variant_append_arrayb(
|
||||
&digests,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("hashAlg", JSON_BUILD_STRING(a)),
|
||||
JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(hash, hash_usize))));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build JSON digest object: %m");
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < TPM2_PCRS_MAX; i++) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *record = NULL;
|
||||
|
||||
if (!FLAGS_SET(pcr_mask, UINT32_C(1) << i))
|
||||
continue;
|
||||
|
||||
r = json_build(&record,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(i)),
|
||||
JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(digests))));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build record object: %m");
|
||||
|
||||
r = json_variant_append_array(ret_records, record);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to append to JSON array: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *pcrlock_path(const char *default_pcrlock_path) {
|
||||
return arg_pcrlock_path ?: arg_pcrlock_auto ? default_pcrlock_path : NULL;
|
||||
}
|
||||
|
@ -2771,10 +2866,8 @@ static int unlink_pcrlock(const char *default_pcrlock_path) {
|
|||
}
|
||||
|
||||
static int verb_lock_raw(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
|
||||
_cleanup_free_ char *data = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *records = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
if (arg_pcr_mask == 0)
|
||||
|
@ -2786,26 +2879,11 @@ static int verb_lock_raw(int argc, char *argv[], void *userdata) {
|
|||
return log_error_errno(errno, "Failed to open '%s': %m", argv[1]);
|
||||
}
|
||||
|
||||
r = read_full_stream(f ?: stdin, &data, &size);
|
||||
r = make_pcrlock_record_from_stream(arg_pcr_mask, f ?: stdin, &records);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read data from stdin: %m");
|
||||
return r;
|
||||
|
||||
for (uint32_t i = 0; i < TPM2_PCRS_MAX; i++) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *record = NULL;
|
||||
|
||||
if (!FLAGS_SET(arg_pcr_mask, UINT32_C(1) << i))
|
||||
continue;
|
||||
|
||||
r = make_pcrlock_record(i, data, size, &record);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_append_array(&array, record);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to append to JSON array: %m");
|
||||
}
|
||||
|
||||
return write_pcrlock(array, NULL);
|
||||
return write_pcrlock(records, NULL);
|
||||
}
|
||||
|
||||
static int verb_unlock_simple(int argc, char *argv[], void *userdata) {
|
||||
|
@ -3813,10 +3891,9 @@ static int verb_unlock_kernel_cmdline(int argc, char *argv[], void *userdata) {
|
|||
}
|
||||
|
||||
static int verb_lock_kernel_initrd(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *record = NULL, *array = NULL;
|
||||
_cleanup_free_ void *data = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *records = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
size_t size;
|
||||
uint32_t pcr_mask = UINT32_C(1) << TPM2_PCR_KERNEL_INITRD;
|
||||
int r;
|
||||
|
||||
if (argc >= 2) {
|
||||
|
@ -3825,19 +3902,11 @@ static int verb_lock_kernel_initrd(int argc, char *argv[], void *userdata) {
|
|||
return log_error_errno(errno, "Failed to open '%s': %m", argv[1]);
|
||||
}
|
||||
|
||||
r = read_full_stream(f ?: stdin, (char**) &data, &size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read data from stdin: %m");
|
||||
|
||||
r = make_pcrlock_record(TPM2_PCR_KERNEL_INITRD /* = 9 */, data, size, &record);
|
||||
r = make_pcrlock_record_from_stream(pcr_mask, f ?: stdin, &records);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_new_array(&array, &record, 1);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create record array: %m");
|
||||
|
||||
r = write_pcrlock(array, PCRLOCK_KERNEL_INITRD_PATH);
|
||||
r = write_pcrlock(records, PCRLOCK_KERNEL_INITRD_PATH);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
Loading…
Reference in a new issue