1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "analyze-pcrs.h"
6 #include "format-table.h"
8 #include "terminal-util.h"
11 static int get_pcr_alg(const char **ret
) {
14 FOREACH_STRING(alg
, "sha256", "sha384", "sha1") {
15 _cleanup_free_
char *p
= NULL
;
17 if (asprintf(&p
, "/sys/class/tpm/tpm0/pcr-%s/0", alg
) < 0)
20 if (access(p
, F_OK
) < 0) {
22 return log_error_errno(errno
, "Failed to determine whether %s exists: %m", p
);
29 log_notice("Kernel does not support reading PCR values.");
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;
44 if (asprintf(&p
, "/sys/class/tpm/tpm0/pcr-%s/%" PRIu32
, alg
, pcr
) < 0)
47 r
= read_virtual_file(p
, 4096, &s
, &ss
);
49 return log_error_errno(r
, "Failed to read '%s': %m", p
);
51 r
= unhexmem(s
, ss
, &buf
, &bufsize
);
53 return log_error_errno(r
, "Failed to decode hex PCR data '%s': %m", s
);
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
;
66 _cleanup_free_
void *buf
= NULL
;
69 r
= get_current_pcr(alg
, pcr
, &buf
, &bufsize
);
73 h
= hexmem(buf
, bufsize
);
77 /* Grey out PCRs that are not sensibly initialized */
78 if (memeqbyte(0, buf
, bufsize
) ||
79 memeqbyte(0xFFU
, buf
, bufsize
))
83 r
= table_add_many(table
,
85 TABLE_STRING
, tpm2_pcr_index_to_string(pcr
),
87 TABLE_SET_COLOR
, color
);
89 return table_log_add_error(r
);
94 int verb_pcrs(int argc
, char *argv
[], void *userdata
) {
95 _cleanup_(table_unrefp
) Table
*table
= NULL
;
96 const char *alg
= NULL
;
99 if (tpm2_support() != TPM2_SUPPORT_FULL
)
100 log_notice("System lacks full TPM2 support, not showing PCR state.");
102 r
= get_pcr_alg(&alg
);
107 table
= table_new("nr", "name", alg
?: "-");
111 (void) table_set_align_percent(table
, table_get_cell(table
, 0, 0), 100);
112 (void) table_set_ersatz_string(table
, TABLE_ERSATZ_DASH
);
114 if (!alg
) /* hide hash column if we couldn't acquire it */
115 (void) table_set_display(table
, 0, 1);
117 if (strv_isempty(strv_skip(argv
, 1)))
118 for (uint32_t pi
= 0; pi
< _TPM2_PCR_INDEX_MAX_DEFINED
; pi
++) {
119 r
= add_pcr_to_table(table
, alg
, pi
);
124 for (int i
= 1; i
< argc
; i
++) {
127 pi
= tpm2_pcr_index_from_string(argv
[i
]);
129 return log_error_errno(pi
, "PCR index \"%s\" not known.", argv
[i
]);
131 r
= add_pcr_to_table(table
, alg
, pi
);
136 (void) table_set_sort(table
, (size_t) 0);
139 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, /* show_header= */true);
141 return log_error_errno(r
, "Failed to output table: %m");