tpm2-util: add tpm2_get_vendor_info() helper for getting TPM2 vendor info from the device

This commit is contained in:
Lennart Poettering
2026-03-04 08:28:29 +01:00
parent 5f85409f93
commit 98a9844f3e
2 changed files with 126 additions and 0 deletions
+109
View File
@@ -43,6 +43,7 @@
#include "time-util.h"
#include "tpm2-pcr.h"
#include "tpm2-util.h"
#include "unaligned.h"
#include "virt.h"
#if HAVE_OPENSSL
@@ -348,6 +349,114 @@ static int tpm2_get_capability(
return more == TPM2_YES;
}
static char *mangle_vendor_chars(char *c, size_t n) {
char *end = c;
assert(c || n == 0);
/* Suppress all control characters, whitespace and non-ASCII bytes */
for (char *x = c; x < c + n; x++) {
if (!IN_SET(*x, ' ', 0))
end = x + 1;
if ((unsigned char) *x <= (unsigned char) ' ' ||
(unsigned char) *x >= 127)
*x = '_';
}
/* Drop trailing spaces and NUL bytes */
*end = 0;
return c;
}
int tpm2_get_vendor_info(
Tpm2Context *c,
Tpm2VendorInfo *ret) {
int r;
assert(c);
assert(ret);
TPMU_CAPABILITIES capabilities = {};
r = tpm2_get_capability(
c,
TPM2_CAP_TPM_PROPERTIES,
TPM2_PT_FAMILY_INDICATOR,
TPM2_PT_FIRMWARE_VERSION_2 - TPM2_PT_FAMILY_INDICATOR + 1, /* get all relevant fields at once */
&capabilities);
if (r < 0)
return r;
Tpm2VendorInfo info = {};
for (uint32_t i = 0; i < capabilities.tpmProperties.count; i++) {
TPMS_TAGGED_PROPERTY *p = capabilities.tpmProperties.tpmProperty + i;
switch (p->property) {
case TPM2_PT_FAMILY_INDICATOR:
unaligned_write_be32(info.family_indicator, p->value);
mangle_vendor_chars(info.family_indicator, sizeof(info.family_indicator));
break;
case TPM2_PT_LEVEL:
info.level = p->value;
break;
case TPM2_PT_REVISION:
info.revision_major = p->value / 100;
info.revision_minor = p->value % 100;
break;
case TPM2_PT_DAY_OF_YEAR:
info.day_of_year = p->value;
break;
case TPM2_PT_YEAR:
info.year = p->value;
break;
case TPM2_PT_MANUFACTURER:
unaligned_write_be32(info.manufacturer, p->value);
mangle_vendor_chars(info.manufacturer, sizeof(info.manufacturer));
break;
case TPM2_PT_VENDOR_STRING_1:
unaligned_write_be32(info.vendor_string+0, p->value);
break;
case TPM2_PT_VENDOR_STRING_2:
unaligned_write_be32(info.vendor_string+4, p->value);
break;
case TPM2_PT_VENDOR_STRING_3:
unaligned_write_be32(info.vendor_string+8, p->value);
break;
case TPM2_PT_VENDOR_STRING_4:
unaligned_write_be32(info.vendor_string+12, p->value);
break;
case TPM2_PT_VENDOR_TPM_TYPE:
info.vendor_tpm_type = p->value;
break;
case TPM2_PT_FIRMWARE_VERSION_1:
info.firmware_version_major = p->value >> 16;
info.firmware_version_minor = p->value & 0xFFFFU;
break;
case TPM2_PT_FIRMWARE_VERSION_2:
info.firmware_version2 = p->value;
break;
}
}
mangle_vendor_chars(info.vendor_string, sizeof(info.vendor_string));
*ret = TAKE_STRUCT(info);
return 0;
}
#define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
static int tpm2_cache_capabilities(Tpm2Context *c) {
+17
View File
@@ -195,6 +195,23 @@ static inline int tpm2_digest_init(TPMI_ALG_HASH alg, TPM2B_DIGEST *digest) {
return tpm2_digest_many(alg, digest, NULL, 0, false);
}
typedef struct Tpm2VendorInfo {
uint32_t level;
uint32_t revision_major;
uint32_t revision_minor;
uint32_t day_of_year;
uint32_t year;
uint32_t vendor_tpm_type;
uint16_t firmware_version_major;
uint16_t firmware_version_minor;
uint32_t firmware_version2;
char family_indicator[4+1];
char manufacturer[4+1];
char vendor_string[4*4+1];
} Tpm2VendorInfo;
int tpm2_get_vendor_info(Tpm2Context *c, Tpm2VendorInfo *ret);
void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg);
void tpm2_log_debug_pcr_value(const Tpm2PCRValue *pcr_value, const char *msg);
void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg);