]>
Commit | Line | Data |
---|---|---|
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 | ||
11 | static 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 | ||
34 | static 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 | ||
60 | static 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 | ||
94 | int 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 | } |