diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/tpm.c | 59 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 23 |
2 files changed, 76 insertions, 6 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 677c6e26593f..36e43e50dcef 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -32,12 +32,6 @@ | |||
32 | #include "tpm.h" | 32 | #include "tpm.h" |
33 | #include "tpm_eventlog.h" | 33 | #include "tpm_eventlog.h" |
34 | 34 | ||
35 | enum tpm_const { | ||
36 | TPM_MINOR = 224, /* officially assigned */ | ||
37 | TPM_BUFSIZE = 4096, | ||
38 | TPM_NUM_DEVICES = 256, | ||
39 | }; | ||
40 | |||
41 | enum tpm_duration { | 35 | enum tpm_duration { |
42 | TPM_SHORT = 0, | 36 | TPM_SHORT = 0, |
43 | TPM_MEDIUM = 1, | 37 | TPM_MEDIUM = 1, |
@@ -483,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | |||
483 | #define TPM_INTERNAL_RESULT_SIZE 200 | 477 | #define TPM_INTERNAL_RESULT_SIZE 200 |
484 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) | 478 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) |
485 | #define TPM_ORD_GET_CAP cpu_to_be32(101) | 479 | #define TPM_ORD_GET_CAP cpu_to_be32(101) |
480 | #define TPM_ORD_GET_RANDOM cpu_to_be32(70) | ||
486 | 481 | ||
487 | static const struct tpm_input_header tpm_getcap_header = { | 482 | static const struct tpm_input_header tpm_getcap_header = { |
488 | .tag = TPM_TAG_RQU_COMMAND, | 483 | .tag = TPM_TAG_RQU_COMMAND, |
@@ -1327,6 +1322,58 @@ int tpm_pm_resume(struct device *dev) | |||
1327 | } | 1322 | } |
1328 | EXPORT_SYMBOL_GPL(tpm_pm_resume); | 1323 | EXPORT_SYMBOL_GPL(tpm_pm_resume); |
1329 | 1324 | ||
1325 | #define TPM_GETRANDOM_RESULT_SIZE 18 | ||
1326 | static struct tpm_input_header tpm_getrandom_header = { | ||
1327 | .tag = TPM_TAG_RQU_COMMAND, | ||
1328 | .length = cpu_to_be32(14), | ||
1329 | .ordinal = TPM_ORD_GET_RANDOM | ||
1330 | }; | ||
1331 | |||
1332 | /** | ||
1333 | * tpm_get_random() - Get random bytes from the tpm's RNG | ||
1334 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
1335 | * @out: destination buffer for the random bytes | ||
1336 | * @max: the max number of bytes to write to @out | ||
1337 | * | ||
1338 | * Returns < 0 on error and the number of bytes read on success | ||
1339 | */ | ||
1340 | int tpm_get_random(u32 chip_num, u8 *out, size_t max) | ||
1341 | { | ||
1342 | struct tpm_chip *chip; | ||
1343 | struct tpm_cmd_t tpm_cmd; | ||
1344 | u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); | ||
1345 | int err, total = 0, retries = 5; | ||
1346 | u8 *dest = out; | ||
1347 | |||
1348 | chip = tpm_chip_find_get(chip_num); | ||
1349 | if (chip == NULL) | ||
1350 | return -ENODEV; | ||
1351 | |||
1352 | if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) | ||
1353 | return -EINVAL; | ||
1354 | |||
1355 | do { | ||
1356 | tpm_cmd.header.in = tpm_getrandom_header; | ||
1357 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); | ||
1358 | |||
1359 | err = transmit_cmd(chip, &tpm_cmd, | ||
1360 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, | ||
1361 | "attempting get random"); | ||
1362 | if (err) | ||
1363 | break; | ||
1364 | |||
1365 | recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); | ||
1366 | memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); | ||
1367 | |||
1368 | dest += recd; | ||
1369 | total += recd; | ||
1370 | num_bytes -= recd; | ||
1371 | } while (retries-- && total < max); | ||
1372 | |||
1373 | return total ? total : -EIO; | ||
1374 | } | ||
1375 | EXPORT_SYMBOL_GPL(tpm_get_random); | ||
1376 | |||
1330 | /* In case vendor provided release function, call it too.*/ | 1377 | /* In case vendor provided release function, call it too.*/ |
1331 | 1378 | ||
1332 | void tpm_dev_vendor_release(struct tpm_chip *chip) | 1379 | void tpm_dev_vendor_release(struct tpm_chip *chip) |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 917f727e6740..645136eea890 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -28,6 +28,12 @@ | |||
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/tpm.h> | 29 | #include <linux/tpm.h> |
30 | 30 | ||
31 | enum tpm_const { | ||
32 | TPM_MINOR = 224, /* officially assigned */ | ||
33 | TPM_BUFSIZE = 4096, | ||
34 | TPM_NUM_DEVICES = 256, | ||
35 | }; | ||
36 | |||
31 | enum tpm_timeout { | 37 | enum tpm_timeout { |
32 | TPM_TIMEOUT = 5, /* msecs */ | 38 | TPM_TIMEOUT = 5, /* msecs */ |
33 | }; | 39 | }; |
@@ -269,6 +275,21 @@ struct tpm_pcrextend_in { | |||
269 | u8 hash[TPM_DIGEST_SIZE]; | 275 | u8 hash[TPM_DIGEST_SIZE]; |
270 | }__attribute__((packed)); | 276 | }__attribute__((packed)); |
271 | 277 | ||
278 | /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 | ||
279 | * bytes, but 128 is still a relatively large number of random bytes and | ||
280 | * anything much bigger causes users of struct tpm_cmd_t to start getting | ||
281 | * compiler warnings about stack frame size. */ | ||
282 | #define TPM_MAX_RNG_DATA 128 | ||
283 | |||
284 | struct tpm_getrandom_out { | ||
285 | __be32 rng_data_len; | ||
286 | u8 rng_data[TPM_MAX_RNG_DATA]; | ||
287 | }__attribute__((packed)); | ||
288 | |||
289 | struct tpm_getrandom_in { | ||
290 | __be32 num_bytes; | ||
291 | }__attribute__((packed)); | ||
292 | |||
272 | typedef union { | 293 | typedef union { |
273 | struct tpm_getcap_params_out getcap_out; | 294 | struct tpm_getcap_params_out getcap_out; |
274 | struct tpm_readpubek_params_out readpubek_out; | 295 | struct tpm_readpubek_params_out readpubek_out; |
@@ -277,6 +298,8 @@ typedef union { | |||
277 | struct tpm_pcrread_in pcrread_in; | 298 | struct tpm_pcrread_in pcrread_in; |
278 | struct tpm_pcrread_out pcrread_out; | 299 | struct tpm_pcrread_out pcrread_out; |
279 | struct tpm_pcrextend_in pcrextend_in; | 300 | struct tpm_pcrextend_in pcrextend_in; |
301 | struct tpm_getrandom_in getrandom_in; | ||
302 | struct tpm_getrandom_out getrandom_out; | ||
280 | } tpm_cmd_params; | 303 | } tpm_cmd_params; |
281 | 304 | ||
282 | struct tpm_cmd_t { | 305 | struct tpm_cmd_t { |