#include "time-util.h"
#include "tpm2-pcr.h"
#include "tpm2-util.h"
+#include "unaligned.h"
#include "virt.h"
#if HAVE_OPENSSL
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) {
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);