aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tpm/tpm.c145
1 files changed, 86 insertions, 59 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 379c5d465579..187bcdaf7bf6 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -119,17 +119,57 @@ out:
119} 119}
120 120
121#define TPM_DIGEST_SIZE 20 121#define TPM_DIGEST_SIZE 20
122#define CAP_PCR_RESULT_SIZE 18 122#define TPM_ERROR_SIZE 10
123static const u8 cap_pcr[] = { 123#define TPM_RET_CODE_IDX 6
124#define TPM_GET_CAP_RET_SIZE_IDX 10
125#define TPM_GET_CAP_RET_UINT32_1_IDX 14
126#define TPM_GET_CAP_RET_UINT32_2_IDX 18
127#define TPM_GET_CAP_RET_UINT32_3_IDX 22
128#define TPM_GET_CAP_RET_UINT32_4_IDX 26
129
130#define TPM_CAP_IDX 13
131#define TPM_CAP_SUBCAP_IDX 21
132
133enum tpm_capabilities {
134 TPM_CAP_PROP = 5,
135};
136
137enum tpm_sub_capabilities {
138 TPM_CAP_PROP_PCR = 0x1,
139 TPM_CAP_PROP_MANUFACTURER = 0x3,
140};
141
142/*
143 * This is a semi generic GetCapability command for use
144 * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
145 * and their associated sub_capabilities.
146 */
147
148static const u8 tpm_cap[] = {
124 0, 193, /* TPM_TAG_RQU_COMMAND */ 149 0, 193, /* TPM_TAG_RQU_COMMAND */
125 0, 0, 0, 22, /* length */ 150 0, 0, 0, 22, /* length */
126 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 151 0, 0, 0, 101, /* TPM_ORD_GetCapability */
127 0, 0, 0, 5, 152 0, 0, 0, 0, /* TPM_CAP_<TYPE> */
128 0, 0, 0, 4, 153 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */
129 0, 0, 1, 1 154 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */
130}; 155};
131 156
132#define READ_PCR_RESULT_SIZE 30 157static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
158 char *desc)
159{
160 int err;
161
162 len = tpm_transmit(chip, data, len);
163 if (len < 0)
164 return len;
165 if (len == TPM_ERROR_SIZE) {
166 err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
167 dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
168 return err;
169 }
170 return 0;
171}
172
133static const u8 pcrread[] = { 173static const u8 pcrread[] = {
134 0, 193, /* TPM_TAG_RQU_COMMAND */ 174 0, 193, /* TPM_TAG_RQU_COMMAND */
135 0, 0, 0, 14, /* length */ 175 0, 0, 0, 14, /* length */
@@ -140,8 +180,8 @@ static const u8 pcrread[] = {
140ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, 180ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
141 char *buf) 181 char *buf)
142{ 182{
143 u8 data[READ_PCR_RESULT_SIZE]; 183 u8 data[30];
144 ssize_t len; 184 ssize_t rc;
145 int i, j, num_pcrs; 185 int i, j, num_pcrs;
146 __be32 index; 186 __be32 index;
147 char *str = buf; 187 char *str = buf;
@@ -150,29 +190,24 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
150 if (chip == NULL) 190 if (chip == NULL)
151 return -ENODEV; 191 return -ENODEV;
152 192
153 memcpy(data, cap_pcr, sizeof(cap_pcr)); 193 memcpy(data, tpm_cap, sizeof(tpm_cap));
154 if ((len = tpm_transmit(chip, data, sizeof(data))) 194 data[TPM_CAP_IDX] = TPM_CAP_PROP;
155 < CAP_PCR_RESULT_SIZE) { 195 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
156 dev_dbg(chip->dev, "A TPM error (%d) occurred " 196
157 "attempting to determine the number of PCRS\n", 197 rc = transmit_cmd(chip, data, sizeof(data),
158 be32_to_cpu(*((__be32 *) (data + 6)))); 198 "attempting to determine the number of PCRS");
199 if (rc)
159 return 0; 200 return 0;
160 }
161 201
162 num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); 202 num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
163
164 for (i = 0; i < num_pcrs; i++) { 203 for (i = 0; i < num_pcrs; i++) {
165 memcpy(data, pcrread, sizeof(pcrread)); 204 memcpy(data, pcrread, sizeof(pcrread));
166 index = cpu_to_be32(i); 205 index = cpu_to_be32(i);
167 memcpy(data + 10, &index, 4); 206 memcpy(data + 10, &index, 4);
168 if ((len = tpm_transmit(chip, data, sizeof(data))) 207 rc = transmit_cmd(chip, data, sizeof(data),
169 < READ_PCR_RESULT_SIZE){ 208 "attempting to read a PCR");
170 dev_dbg(chip->dev, "A TPM error (%d) occurred" 209 if (rc)
171 " attempting to read PCR %d of %d\n",
172 be32_to_cpu(*((__be32 *) (data + 6))),
173 i, num_pcrs);
174 goto out; 210 goto out;
175 }
176 str += sprintf(str, "PCR-%02d: ", i); 211 str += sprintf(str, "PCR-%02d: ", i);
177 for (j = 0; j < TPM_DIGEST_SIZE; j++) 212 for (j = 0; j < TPM_DIGEST_SIZE; j++)
178 str += sprintf(str, "%02X ", *(data + 10 + j)); 213 str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -194,7 +229,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
194 char *buf) 229 char *buf)
195{ 230{
196 u8 *data; 231 u8 *data;
197 ssize_t len; 232 ssize_t err;
198 int i, rc; 233 int i, rc;
199 char *str = buf; 234 char *str = buf;
200 235
@@ -208,14 +243,10 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
208 243
209 memcpy(data, readpubek, sizeof(readpubek)); 244 memcpy(data, readpubek, sizeof(readpubek));
210 245
211 if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < 246 err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
212 READ_PUBEK_RESULT_SIZE) { 247 "attempting to read the PUBEK");
213 dev_dbg(chip->dev, "A TPM error (%d) occurred " 248 if (err)
214 "attempting to read the PUBEK\n",
215 be32_to_cpu(*((__be32 *) (data + 6))));
216 rc = 0;
217 goto out; 249 goto out;
218 }
219 250
220 /* 251 /*
221 ignore header 10 bytes 252 ignore header 10 bytes
@@ -245,63 +276,59 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
245 if ((i + 1) % 16 == 0) 276 if ((i + 1) % 16 == 0)
246 str += sprintf(str, "\n"); 277 str += sprintf(str, "\n");
247 } 278 }
248 rc = str - buf;
249out: 279out:
280 rc = str - buf;
250 kfree(data); 281 kfree(data);
251 return rc; 282 return rc;
252} 283}
253EXPORT_SYMBOL_GPL(tpm_show_pubek); 284EXPORT_SYMBOL_GPL(tpm_show_pubek);
254 285
255#define CAP_VER_RESULT_SIZE 18 286#define CAP_VERSION_1_1 6
287#define CAP_VERSION_IDX 13
256static const u8 cap_version[] = { 288static const u8 cap_version[] = {
257 0, 193, /* TPM_TAG_RQU_COMMAND */ 289 0, 193, /* TPM_TAG_RQU_COMMAND */
258 0, 0, 0, 18, /* length */ 290 0, 0, 0, 18, /* length */
259 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 291 0, 0, 0, 101, /* TPM_ORD_GetCapability */
260 0, 0, 0, 6, 292 0, 0, 0, 0,
261 0, 0, 0, 0 293 0, 0, 0, 0
262}; 294};
263 295
264#define CAP_MANUFACTURER_RESULT_SIZE 18
265static const u8 cap_manufacturer[] = {
266 0, 193, /* TPM_TAG_RQU_COMMAND */
267 0, 0, 0, 22, /* length */
268 0, 0, 0, 101, /* TPM_ORD_GetCapability */
269 0, 0, 0, 5,
270 0, 0, 0, 4,
271 0, 0, 1, 3
272};
273
274ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, 296ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
275 char *buf) 297 char *buf)
276{ 298{
277 u8 data[sizeof(cap_manufacturer)]; 299 u8 data[30];
278 ssize_t len; 300 ssize_t rc;
279 char *str = buf; 301 char *str = buf;
280 302
281 struct tpm_chip *chip = dev_get_drvdata(dev); 303 struct tpm_chip *chip = dev_get_drvdata(dev);
282 if (chip == NULL) 304 if (chip == NULL)
283 return -ENODEV; 305 return -ENODEV;
284 306
285 memcpy(data, cap_manufacturer, sizeof(cap_manufacturer)); 307 memcpy(data, tpm_cap, sizeof(tpm_cap));
308 data[TPM_CAP_IDX] = TPM_CAP_PROP;
309 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
286 310
287 if ((len = tpm_transmit(chip, data, sizeof(data))) < 311 rc = transmit_cmd(chip, data, sizeof(data),
288 CAP_MANUFACTURER_RESULT_SIZE) 312 "attempting to determine the manufacturer");
289 return len; 313 if (rc)
314 return 0;
290 315
291 str += sprintf(str, "Manufacturer: 0x%x\n", 316 str += sprintf(str, "Manufacturer: 0x%x\n",
292 be32_to_cpu(*((__be32 *) (data + 14)))); 317 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
293 318
294 memcpy(data, cap_version, sizeof(cap_version)); 319 memcpy(data, cap_version, sizeof(cap_version));
320 data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
321 rc = transmit_cmd(chip, data, sizeof(data),
322 "attempting to determine the 1.1 version");
323 if (rc)
324 goto out;
295 325
296 if ((len = tpm_transmit(chip, data, sizeof(data))) < 326 str += sprintf(str,
297 CAP_VER_RESULT_SIZE) 327 "TCG version: %d.%d\nFirmware version: %d.%d\n",
298 return len; 328 (int) data[14], (int) data[15], (int) data[16],
299 329 (int) data[17]);
300 str +=
301 sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
302 (int) data[14], (int) data[15], (int) data[16],
303 (int) data[17]);
304 330
331out:
305 return str - buf; 332 return str - buf;
306} 333}
307EXPORT_SYMBOL_GPL(tpm_show_caps); 334EXPORT_SYMBOL_GPL(tpm_show_caps);