166 lines
4.1 KiB
Diff
166 lines
4.1 KiB
Diff
--- a/include/grub/tpm.h
|
|
+++ b/include/grub/tpm.h
|
|
@@ -36,6 +36,12 @@
|
|
|
|
#define EV_IPL 0x0d
|
|
|
|
+struct grub_tpm_digest {
|
|
+ const char * algorithm;
|
|
+ unsigned int size;
|
|
+ unsigned char value[1]; /* variable length */
|
|
+};
|
|
+
|
|
grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size,
|
|
grub_uint8_t pcr, const char *description);
|
|
int grub_tpm_present (void);
|
|
@@ -45,5 +51,7 @@
|
|
{
|
|
return grub_env_get_bool ("tpm_fail_fatal", false);
|
|
}
|
|
+struct grub_tpm_digest *grub_tpm_read_pcr (grub_uint8_t index, const char *algo);
|
|
+void grub_tpm_digest_free (struct grub_tpm_digest *d);
|
|
|
|
#endif
|
|
--- a/grub-core/commands/efi/tpm.c
|
|
+++ b/grub-core/commands/efi/tpm.c
|
|
@@ -24,6 +24,7 @@
|
|
#include <grub/efi/efi.h>
|
|
#include <grub/efi/cc.h>
|
|
#include <grub/efi/tpm.h>
|
|
+#include <grub/tpm2/tpm2.h>
|
|
#include <grub/mm.h>
|
|
#include <grub/tpm.h>
|
|
#include <grub/term.h>
|
|
@@ -186,6 +187,91 @@
|
|
return grub_efi_log_event_status (status);
|
|
}
|
|
|
|
+static void
|
|
+grub_tpm2_select_pcr(TPML_PCR_SELECTION *o, unsigned int pcrIndex, unsigned int algo)
|
|
+{
|
|
+ TPMS_PCR_SELECTION *pcr;
|
|
+
|
|
+ pcr = &o->pcrSelections[o->count++];
|
|
+ pcr->hash = algo;
|
|
+ pcr->sizeOfSelect = 3;
|
|
+ pcr->pcrSelect[TPM2_PCR_TO_SELECT(pcrIndex)] |= TPM2_PCR_TO_BIT(pcrIndex);
|
|
+}
|
|
+
|
|
+struct grub_tpm_hash_info {
|
|
+ const char *name;
|
|
+ grub_size_t size;
|
|
+ int id;
|
|
+};
|
|
+
|
|
+static const struct grub_tpm_hash_info *
|
|
+grub_tpm2_get_digest_info (const char *algo)
|
|
+{
|
|
+ static struct grub_tpm_hash_info __hashes[] = {
|
|
+ { "sha256", 32, TPM_ALG_SHA256 }, /* first entry is the default */
|
|
+ { "sha512", 64, TPM_ALG_SHA512 },
|
|
+ { "sha1", 20, TPM_ALG_SHA1 },
|
|
+ { NULL }
|
|
+ };
|
|
+ struct grub_tpm_hash_info *h;
|
|
+
|
|
+ if (algo == NULL)
|
|
+ return &__hashes[0];
|
|
+
|
|
+ for (h = __hashes; h->name; ++h)
|
|
+ if (!grub_strcmp(h->name, algo))
|
|
+ return h;
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static grub_err_t
|
|
+grub_tpm2_read_pcr (grub_int8_t pcrIndex, const char *algo, struct grub_tpm_digest **ret)
|
|
+{
|
|
+ const struct grub_tpm_hash_info *info;
|
|
+ TPML_PCR_SELECTION inSelection, outSelection;
|
|
+ grub_uint32_t pcrUpdateCounter;
|
|
+ TPML_DIGEST digests = { 0 };
|
|
+ TPM2B_DIGEST *d;
|
|
+ struct grub_tpm_digest *result;
|
|
+ int rc;
|
|
+
|
|
+ info = grub_tpm2_get_digest_info (algo);
|
|
+ if (info == NULL)
|
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Unknown digest algorithm %s"), algo);
|
|
+
|
|
+ grub_memset(&inSelection, 0, sizeof(inSelection));
|
|
+ grub_memset(&outSelection, 0, sizeof(outSelection));
|
|
+ grub_tpm2_select_pcr(&inSelection, pcrIndex, info->id);
|
|
+
|
|
+ rc = TPM2_PCR_Read(
|
|
+ NULL,
|
|
+ &inSelection,
|
|
+ &pcrUpdateCounter,
|
|
+ &outSelection,
|
|
+ &digests,
|
|
+ NULL
|
|
+ );
|
|
+
|
|
+ if (rc != 0)
|
|
+ return grub_error (GRUB_ERR_BAD_DEVICE, "TPM2_PCR_Read failed, status=%d", rc);
|
|
+
|
|
+ d = &digests.digests[0];
|
|
+
|
|
+ *ret = result = grub_malloc (sizeof (*result) + d->size);
|
|
+ grub_memcpy (result->value, d->buffer, d->size);
|
|
+ result->algorithm = info->name;
|
|
+ result->size = d->size;
|
|
+
|
|
+ return GRUB_ERR_NONE;
|
|
+}
|
|
+
|
|
+void
|
|
+grub_tpm_digest_free (struct grub_tpm_digest *d)
|
|
+{
|
|
+ grub_free (d);
|
|
+}
|
|
+
|
|
static grub_err_t
|
|
grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
|
|
grub_size_t size, grub_uint8_t pcr,
|
|
@@ -323,3 +409,26 @@
|
|
return grub_tpm2_present (tpm);
|
|
}
|
|
}
|
|
+
|
|
+struct grub_tpm_digest *
|
|
+grub_tpm_read_pcr (grub_uint8_t pcr, const char *algo)
|
|
+{
|
|
+ grub_efi_handle_t tpm_handle;
|
|
+ grub_efi_uint8_t protocol_version;
|
|
+ struct grub_tpm_digest *result = NULL;
|
|
+
|
|
+
|
|
+ if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
|
|
+ return 0;
|
|
+
|
|
+ if (protocol_version != 2)
|
|
+ {
|
|
+ grub_error (GRUB_ERR_BAD_DEVICE, N_("%s: TPM version %d not implemented"), __func__, protocol_version);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (grub_tpm2_read_pcr (pcr, algo, &result))
|
|
+ return NULL;
|
|
+
|
|
+ return result;
|
|
+}
|
|
--- a/include/grub/tpm2/tpm2.h
|
|
+++ b/include/grub/tpm2/tpm2.h
|
|
@@ -23,6 +23,10 @@
|
|
#include <grub/tpm2/internal/structs.h>
|
|
#include <grub/tpm2/internal/functions.h>
|
|
|
|
+/* Defined in: TCG TPM Specification, v1.59, Part 2, Section 10.6.1. */
|
|
+#define TPM2_PCR_TO_SELECT(x) ((x) / 8)
|
|
+#define TPM2_PCR_TO_BIT(x) (1 << ((x) % 8))
|
|
+
|
|
/* Well-Known Windows SRK handle */
|
|
#define TPM2_SRK_HANDLE 0x81000001
|
|
|