aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajiv Andrade <srajiv@linux.vnet.ibm.com>2010-03-24 23:55:32 -0400
committerJames Morris <jmorris@namei.org>2010-03-25 18:30:03 -0400
commit225a9be24d799aa16d543c31fb09f0c9ed1d9caa (patch)
treee2db049524c7f153457e55506d1ef4cec0ccf39c
parent310de047eef6685274045db1e6b39c9f313df428 (diff)
TPM: workaround to enforce PCR updates across suspends
Add a workaround for TPM's which fail to flush last written PCR values in a TPM_SaveState, in preparation for suspend. Signed-off-by: David Safford <safford@watson.ibm.com> Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--Documentation/kernel-parameters.txt10
-rw-r--r--drivers/char/tpm/tpm.c47
2 files changed, 50 insertions, 7 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d80930d58dae..e0df679c3902 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -99,6 +99,7 @@ parameter is applicable:
99 SWSUSP Software suspend (hibernation) is enabled. 99 SWSUSP Software suspend (hibernation) is enabled.
100 SUSPEND System suspend states are enabled. 100 SUSPEND System suspend states are enabled.
101 FTRACE Function tracing enabled. 101 FTRACE Function tracing enabled.
102 TPM TPM drivers are enabled.
102 TS Appropriate touchscreen support is enabled. 103 TS Appropriate touchscreen support is enabled.
103 UMS USB Mass Storage support is enabled. 104 UMS USB Mass Storage support is enabled.
104 USB USB support is enabled. 105 USB USB support is enabled.
@@ -2619,6 +2620,15 @@ and is between 256 and 4096 characters. It is defined in the file
2619 2620
2620 tp720= [HW,PS2] 2621 tp720= [HW,PS2]
2621 2622
2623 tpm_suspend_pcr=[HW,TPM]
2624 Format: integer pcr id
2625 Specify that at suspend time, the tpm driver
2626 should extend the specified pcr with zeros,
2627 as a workaround for some chips which fail to
2628 flush the last written pcr on TPM_SaveState.
2629 This will guarantee that all the other pcrs
2630 are saved.
2631
2622 trace_buf_size=nn[KMG] 2632 trace_buf_size=nn[KMG]
2623 [FTRACE] will set tracing buffer size. 2633 [FTRACE] will set tracing buffer size.
2624 2634
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index f06bb37defb1..5c447c991bd5 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1067,6 +1067,27 @@ void tpm_remove_hardware(struct device *dev)
1067} 1067}
1068EXPORT_SYMBOL_GPL(tpm_remove_hardware); 1068EXPORT_SYMBOL_GPL(tpm_remove_hardware);
1069 1069
1070#define TPM_ORD_SAVESTATE cpu_to_be32(152)
1071#define SAVESTATE_RESULT_SIZE 10
1072
1073static struct tpm_input_header savestate_header = {
1074 .tag = TPM_TAG_RQU_COMMAND,
1075 .length = cpu_to_be32(10),
1076 .ordinal = TPM_ORD_SAVESTATE
1077};
1078
1079/* Bug workaround - some TPM's don't flush the most
1080 * recently changed pcr on suspend, so force the flush
1081 * with an extend to the selected _unused_ non-volatile pcr.
1082 */
1083static int tpm_suspend_pcr;
1084static int __init tpm_suspend_setup(char *str)
1085{
1086 get_option(&str, &tpm_suspend_pcr);
1087 return 1;
1088}
1089__setup("tpm_suspend_pcr=", tpm_suspend_setup);
1090
1070/* 1091/*
1071 * We are about to suspend. Save the TPM state 1092 * We are about to suspend. Save the TPM state
1072 * so that it can be restored. 1093 * so that it can be restored.
@@ -1074,17 +1095,29 @@ EXPORT_SYMBOL_GPL(tpm_remove_hardware);
1074int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) 1095int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
1075{ 1096{
1076 struct tpm_chip *chip = dev_get_drvdata(dev); 1097 struct tpm_chip *chip = dev_get_drvdata(dev);
1077 u8 savestate[] = { 1098 struct tpm_cmd_t cmd;
1078 0, 193, /* TPM_TAG_RQU_COMMAND */ 1099 int rc;
1079 0, 0, 0, 10, /* blob length (in bytes) */ 1100
1080 0, 0, 0, 152 /* TPM_ORD_SaveState */ 1101 u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
1081 };
1082 1102
1083 if (chip == NULL) 1103 if (chip == NULL)
1084 return -ENODEV; 1104 return -ENODEV;
1085 1105
1086 tpm_transmit(chip, savestate, sizeof(savestate)); 1106 /* for buggy tpm, flush pcrs with extend to selected dummy */
1087 return 0; 1107 if (tpm_suspend_pcr) {
1108 cmd.header.in = pcrextend_header;
1109 cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
1110 memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
1111 TPM_DIGEST_SIZE);
1112 rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
1113 "extending dummy pcr before suspend");
1114 }
1115
1116 /* now do the actual savestate */
1117 cmd.header.in = savestate_header;
1118 rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
1119 "sending savestate before suspend");
1120 return rc;
1088} 1121}
1089EXPORT_SYMBOL_GPL(tpm_pm_suspend); 1122EXPORT_SYMBOL_GPL(tpm_pm_suspend);
1090 1123