diff --git a/kernel/power/snapenc.c b/kernel/power/snapenc.c
index 0b38642628f7ce..f32c7347a330a4 100644
--- a/kernel/power/snapenc.c
+++ b/kernel/power/snapenc.c
@@ -22,6 +22,12 @@ static struct tpm_digest known_digest = { .alg_id = TPM_ALG_SHA256,
 		   0xf1, 0x22, 0x38, 0x6c, 0x33, 0xb1, 0x14, 0xb7, 0xec, 0x05,
 		   0x5f, 0x49}};
 
+/* sha256(sha256(empty_pcr | known_digest)) */
+static const char expected_digest[] = {0x2f, 0x96, 0xf2, 0x1b, 0x70, 0xa9, 0xe8,
+	0x42, 0x25, 0x8e, 0x66, 0x07, 0xbe, 0xbc, 0xe3, 0x1f, 0x2c, 0x84, 0x4a,
+	0x3f, 0x85, 0x17, 0x31, 0x47, 0x9a, 0xa5, 0x53, 0xbb, 0x23, 0x0c, 0x32,
+	0xf3};
+
 /* Derive a key from the kernel and user keys for data encryption. */
 static int snapshot_use_user_key(struct snapshot_data *data)
 {
@@ -491,7 +497,7 @@ static int snapshot_setup_encryption_common(struct snapshot_data *data)
 static int snapshot_create_kernel_key(struct snapshot_data *data)
 {
 	/* Create a key sealed by the SRK. */
-	char *keyinfo = "new\t32\tkeyhandle=0x81000000";
+	char *keyinfo = "new\t32\tkeyhandle=0x81000000\tcreationpcrs=0x00800000";
 	const struct cred *cred = current_cred();
 	struct tpm_digest *digests = NULL;
 	struct key *key = NULL;
@@ -612,17 +618,57 @@ int snapshot_get_encryption_key(struct snapshot_data *data,
 	return rc;
 }
 
+/* Currently only PCR23 is included in the creation data. */
+#define SNAPSHOT_KEY_PCR_COUNT 1
+
+/* The standard set of 24 PCRs takes 3 bytes to represent as a bitmask. */
+#define SNAPSHOT_KEY_PCR_SELECTION_BYTES 3
+
+/*
+ * The TPM loves to return variable length structures. This is the form of
+ * TPM2B_CREATION_DATA expected and verified for the snapshot key.
+ */
+struct snapshot_key_creation_data {
+	__be16 size;
+	/* TPMS_CREATION_DATA, the hashed portion */
+	struct {
+		/* TPML_PCR_SELECTION */
+		struct {
+			__be32 count;
+			/* TPMS_PCR_SELECTION */
+			struct {
+				__be16 hash_algo;
+				u8 size;
+				u8 select[SNAPSHOT_KEY_PCR_SELECTION_BYTES];
+			} __packed pcr_selections;
+		} __packed pcr_select;
+
+		/* TPM2B_DIGEST */
+		struct {
+			__be16 size;
+			u8 digest[SHA256_DIGEST_SIZE];
+		} __packed pcr_digest[SNAPSHOT_KEY_PCR_COUNT];
+
+		/* ... additional fields not verified ... */
+	} creation;
+} __packed;
+
 static int snapshot_load_kernel_key(struct snapshot_data *data,
 				    struct uswsusp_key_blob *blob)
 {
 
 	char *keytemplate = "load\t%s\tkeyhandle=0x81000000";
+	struct snapshot_key_creation_data *creation;
 	const struct cred *cred = current_cred();
+	struct trusted_key_payload *payload;
+	char certhash[SHA256_DIGEST_SIZE];
 	struct tpm_digest *digests = NULL;
+	unsigned int creation_hash_length;
 	char *blobstring = NULL;
 	struct key *key = NULL;
 	struct tpm_chip *chip;
 	char *keyinfo = NULL;
+	u32 pcr_selection = 0;
 	int i, ret;
 
 	chip = tpm_default_chip();
@@ -640,8 +686,10 @@ static int snapshot_load_kernel_key(struct snapshot_data *data,
 
 	digests = kcalloc(chip->nr_allocated_banks, sizeof(struct tpm_digest),
 			  GFP_KERNEL);
-	if (!digests)
+	if (!digests) {
+		ret = -ENOMEM;
 		goto out;
+	}
 
 	for (i = 0; i < chip->nr_allocated_banks; i++) {
 		digests[i].alg_id = chip->allocated_banks[i].alg_id;
@@ -681,6 +729,76 @@ static int snapshot_load_kernel_key(struct snapshot_data *data,
 	if (ret != 0)
 		goto out;
 
+	/* Verify the creation hash matches the creation data. */
+	payload = key->payload.data[0];
+	creation = (struct snapshot_key_creation_data *)payload->creation;
+	if (!creation || !payload->creation_hash ||
+	    (payload->creation_len < sizeof(*creation)) ||
+	    (payload->creation_hash_len - 2 != SHA256_DIGEST_SIZE)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	creation_hash_length =
+		payload->creation_len -
+		offsetof(struct snapshot_key_creation_data, creation);
+
+	sha256((const u8 *)&creation->creation, creation_hash_length, certhash);
+	if (memcmp(payload->creation_hash + sizeof(__be16), certhash, SHA256_DIGEST_SIZE) != 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* We now know that the creation data is authentic - parse it */
+
+	/* Verify TPML_PCR_SELECTION.count */
+	if (be32_to_cpu(creation->creation.pcr_select.count) !=
+	    SNAPSHOT_KEY_PCR_COUNT) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Verify the PCRs are SHA256. */
+	if (be16_to_cpu(creation->creation.pcr_select.pcr_selections.hash_algo) !=
+	    TPM_ALG_SHA256) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Gather the PCR selection bitmask. */
+	if (creation->creation.pcr_select.pcr_selections.size !=
+	    SNAPSHOT_KEY_PCR_SELECTION_BYTES) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	for (i = SNAPSHOT_KEY_PCR_SELECTION_BYTES - 1; i >= 0; i--) {
+		pcr_selection <<= 8;
+		pcr_selection |=
+			creation->creation.pcr_select.pcr_selections.select[i];
+	}
+
+	/* Verify PCR 23 is selected. */
+	if (pcr_selection != (1 << 23)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Verify the first and only PCR hash is the expected size. */
+	if (be16_to_cpu(creation->creation.pcr_digest[0].size) !=
+	    SHA256_DIGEST_SIZE) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Verify PCR 23 contained the expected value when the key was created. */
+	if (memcmp(&creation->creation.pcr_digest[0].digest, expected_digest,
+		   SHA256_DIGEST_SIZE) != 0) {
+
+		ret = -EINVAL;
+		goto out;
+	}
+
 	data->key = key;
 	key = NULL;
 
