@@ -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)
{
@@ -486,7 +492,7 @@ static int snapshot_create_kernel_key(struct snapshot_data *data)
struct key *key = NULL;
int ret, i;
/* Create a key sealed by the SRK. */
- char *keyinfo = "new\t32\tkeyhandle=0x81000000";
+ char *keyinfo = "new\t32\tkeyhandle=0x81000000\tcreationpcrs=0x00800000";
chip = tpm_default_chip();
if (!chip)
@@ -605,6 +611,7 @@ static int snapshot_load_kernel_key(struct snapshot_data *data,
struct uswsusp_key_blob *blob)
{
+ char certhash[SHA256_DIGEST_SIZE];
const struct cred *cred = current_cred();
char *keytemplate = "load\t%s\tkeyhandle=0x81000000";
struct tpm_digest *digests = NULL;
@@ -612,6 +619,7 @@ static int snapshot_load_kernel_key(struct snapshot_data *data,
char *keyinfo = NULL;
struct tpm_chip *chip;
struct key *key = NULL;
+ struct trusted_key_payload *payload;
int i, ret;
chip = tpm_default_chip();
@@ -629,8 +637,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;
@@ -670,6 +680,59 @@ 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];
+ if (!payload->creation || !payload->creation_hash ||
+ (payload->creation_len < 3) ||
+ (payload->creation_hash_len < SHA256_DIGEST_SIZE)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ sha256(payload->creation + 2, payload->creation_len - 2, certhash);
+ if (memcmp(payload->creation_hash + 2, certhash, SHA256_DIGEST_SIZE) != 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* We now know that the creation data is authentic - parse it */
+
+ /* TPML_PCR_SELECTION.count */
+ if (be32_to_cpu(*(__be32 *)&payload->creation[2]) != 1) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (be16_to_cpu(*(__be16 *)&payload->creation[6]) != TPM_ALG_SHA256) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (*(char *)&payload->creation[8] != 3) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* PCR 23 selected */
+ if (be32_to_cpu(*(__be32 *)&payload->creation[8]) != 0x03000080) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (be16_to_cpu(*(__be16 *)&payload->creation[12]) !=
+ SHA256_DIGEST_SIZE) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Verify PCR 23 contained the expected value when the key was created. */
+ if (memcmp(&payload->creation[14], expected_digest,
+ SHA256_DIGEST_SIZE) != 0) {
+
+ ret = -EINVAL;
+ goto out;
+ }
+
data->key = key;
key = NULL;