]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/analyze/analyze-pcrs.c
man/run0: remove @ syntax for --machine=
[thirdparty/systemd.git] / src / analyze / analyze-pcrs.c
CommitLineData
f70c90f5
LP
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include "analyze.h"
4#include "analyze-pcrs.h"
5#include "fileio.h"
6#include "format-table.h"
7#include "hexdecoct.h"
8#include "terminal-util.h"
9#include "tpm2-util.h"
10
11static int get_pcr_alg(const char **ret) {
12 assert(ret);
13
14 FOREACH_STRING(alg, "sha256", "sha1") {
15 _cleanup_free_ char *p = NULL;
16
17 if (asprintf(&p, "/sys/class/tpm/tpm0/pcr-%s/0", alg) < 0)
18 return log_oom();
19
20 if (access(p, F_OK) < 0) {
be492020 21 if (errno != ENOENT)
f70c90f5
LP
22 return log_error_errno(errno, "Failed to determine whether %s exists: %m", p);
23 } else {
24 *ret = alg;
25 return 1;
26 }
27 }
28
29 log_notice("Kernel does not support reading PCR values.");
30 *ret = NULL;
31 return 0;
32}
33
34static int get_current_pcr(const char *alg, uint32_t pcr, void **ret, size_t *ret_size) {
35 _cleanup_free_ char *p = NULL, *s = NULL;
36 _cleanup_free_ void *buf = NULL;
37 size_t ss = 0, bufsize = 0;
38 int r;
39
40 assert(alg);
41 assert(ret);
42 assert(ret_size);
43
44 if (asprintf(&p, "/sys/class/tpm/tpm0/pcr-%s/%" PRIu32, alg, pcr) < 0)
45 return log_oom();
46
47 r = read_virtual_file(p, 4096, &s, &ss);
48 if (r < 0)
49 return log_error_errno(r, "Failed to read '%s': %m", p);
50
bdd2036e 51 r = unhexmem_full(s, ss, /* secure = */ false, &buf, &bufsize);
f70c90f5
LP
52 if (r < 0)
53 return log_error_errno(r, "Failed to decode hex PCR data '%s': %m", s);
54
55 *ret = TAKE_PTR(buf);
56 *ret_size = bufsize;
57 return 0;
58}
59
60static int add_pcr_to_table(Table *table, const char *alg, uint32_t pcr) {
61 _cleanup_free_ char *h = NULL;
62 const char *color = NULL;
63 int r;
64
65 if (alg) {
66 _cleanup_free_ void *buf = NULL;
67 size_t bufsize = 0;
68
69 r = get_current_pcr(alg, pcr, &buf, &bufsize);
70 if (r < 0)
71 return r;
72
73 h = hexmem(buf, bufsize);
74 if (!h)
75 return log_oom();
76
77 /* Grey out PCRs that are not sensibly initialized */
78 if (memeqbyte(0, buf, bufsize) ||
79 memeqbyte(0xFFU, buf, bufsize))
80 color = ANSI_GREY;
81 }
82
83 r = table_add_many(table,
84 TABLE_UINT32, pcr,
2099cd62 85 TABLE_STRING, tpm2_pcr_index_to_string(pcr),
f70c90f5
LP
86 TABLE_STRING, h,
87 TABLE_SET_COLOR, color);
88 if (r < 0)
89 return table_log_add_error(r);
90
91 return 0;
92}
93
94int verb_pcrs(int argc, char *argv[], void *userdata) {
95 _cleanup_(table_unrefp) Table *table = NULL;
96 const char *alg = NULL;
97 int r;
98
99 if (tpm2_support() != TPM2_SUPPORT_FULL)
ed4a1e0b 100 log_notice("System lacks full TPM2 support, not showing PCR state.");
f70c90f5
LP
101 else {
102 r = get_pcr_alg(&alg);
103 if (r < 0)
104 return r;
105 }
106
9fe4e68c 107 table = table_new("nr", "name", alg ?: "-");
f70c90f5
LP
108 if (!table)
109 return log_oom();
110
111 (void) table_set_align_percent(table, table_get_cell(table, 0, 0), 100);
112 (void) table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
113
114 if (!alg) /* hide hash column if we couldn't acquire it */
115 (void) table_set_display(table, 0, 1);
116
117 if (strv_isempty(strv_skip(argv, 1)))
2099cd62 118 for (uint32_t pi = 0; pi < _TPM2_PCR_INDEX_MAX_DEFINED; pi++) {
f70c90f5
LP
119 r = add_pcr_to_table(table, alg, pi);
120 if (r < 0)
121 return r;
122 }
123 else {
124 for (int i = 1; i < argc; i++) {
125 int pi;
126
2099cd62 127 pi = tpm2_pcr_index_from_string(argv[i]);
f70c90f5
LP
128 if (pi < 0)
129 return log_error_errno(pi, "PCR index \"%s\" not known.", argv[i]);
130
131 r = add_pcr_to_table(table, alg, pi);
132 if (r < 0)
133 return r;
134 }
135
136 (void) table_set_sort(table, (size_t) 0);
137 }
138
139 r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, /* show_header= */true);
140 if (r < 0)
141 return log_error_errno(r, "Failed to output table: %m");
142
143 return EXIT_SUCCESS;
144}