diff options
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r-- | drivers/char/tpm/tpm.c | 74 |
1 files changed, 64 insertions, 10 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 3af9f4d1a23f..f26afdb1a702 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -30,12 +30,7 @@ | |||
30 | #include <linux/freezer.h> | 30 | #include <linux/freezer.h> |
31 | 31 | ||
32 | #include "tpm.h" | 32 | #include "tpm.h" |
33 | 33 | #include "tpm_eventlog.h" | |
34 | enum tpm_const { | ||
35 | TPM_MINOR = 224, /* officially assigned */ | ||
36 | TPM_BUFSIZE = 4096, | ||
37 | TPM_NUM_DEVICES = 256, | ||
38 | }; | ||
39 | 34 | ||
40 | enum tpm_duration { | 35 | enum tpm_duration { |
41 | TPM_SHORT = 0, | 36 | TPM_SHORT = 0, |
@@ -482,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | |||
482 | #define TPM_INTERNAL_RESULT_SIZE 200 | 477 | #define TPM_INTERNAL_RESULT_SIZE 200 |
483 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) | 478 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) |
484 | #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) | ||
485 | 481 | ||
486 | static const struct tpm_input_header tpm_getcap_header = { | 482 | static const struct tpm_input_header tpm_getcap_header = { |
487 | .tag = TPM_TAG_RQU_COMMAND, | 483 | .tag = TPM_TAG_RQU_COMMAND, |
@@ -919,7 +915,7 @@ EXPORT_SYMBOL_GPL(tpm_show_pcrs); | |||
919 | 915 | ||
920 | #define READ_PUBEK_RESULT_SIZE 314 | 916 | #define READ_PUBEK_RESULT_SIZE 314 |
921 | #define TPM_ORD_READPUBEK cpu_to_be32(124) | 917 | #define TPM_ORD_READPUBEK cpu_to_be32(124) |
922 | struct tpm_input_header tpm_readpubek_header = { | 918 | static struct tpm_input_header tpm_readpubek_header = { |
923 | .tag = TPM_TAG_RQU_COMMAND, | 919 | .tag = TPM_TAG_RQU_COMMAND, |
924 | .length = cpu_to_be32(30), | 920 | .length = cpu_to_be32(30), |
925 | .ordinal = TPM_ORD_READPUBEK | 921 | .ordinal = TPM_ORD_READPUBEK |
@@ -1175,7 +1171,7 @@ int tpm_release(struct inode *inode, struct file *file) | |||
1175 | flush_work(&chip->work); | 1171 | flush_work(&chip->work); |
1176 | file->private_data = NULL; | 1172 | file->private_data = NULL; |
1177 | atomic_set(&chip->data_pending, 0); | 1173 | atomic_set(&chip->data_pending, 0); |
1178 | kfree(chip->data_buffer); | 1174 | kzfree(chip->data_buffer); |
1179 | clear_bit(0, &chip->is_open); | 1175 | clear_bit(0, &chip->is_open); |
1180 | put_device(chip->dev); | 1176 | put_device(chip->dev); |
1181 | return 0; | 1177 | return 0; |
@@ -1227,7 +1223,6 @@ ssize_t tpm_read(struct file *file, char __user *buf, | |||
1227 | del_singleshot_timer_sync(&chip->user_read_timer); | 1223 | del_singleshot_timer_sync(&chip->user_read_timer); |
1228 | flush_work(&chip->work); | 1224 | flush_work(&chip->work); |
1229 | ret_size = atomic_read(&chip->data_pending); | 1225 | ret_size = atomic_read(&chip->data_pending); |
1230 | atomic_set(&chip->data_pending, 0); | ||
1231 | if (ret_size > 0) { /* relay data */ | 1226 | if (ret_size > 0) { /* relay data */ |
1232 | ssize_t orig_ret_size = ret_size; | 1227 | ssize_t orig_ret_size = ret_size; |
1233 | if (size < ret_size) | 1228 | if (size < ret_size) |
@@ -1242,6 +1237,8 @@ ssize_t tpm_read(struct file *file, char __user *buf, | |||
1242 | mutex_unlock(&chip->buffer_mutex); | 1237 | mutex_unlock(&chip->buffer_mutex); |
1243 | } | 1238 | } |
1244 | 1239 | ||
1240 | atomic_set(&chip->data_pending, 0); | ||
1241 | |||
1245 | return ret_size; | 1242 | return ret_size; |
1246 | } | 1243 | } |
1247 | EXPORT_SYMBOL_GPL(tpm_read); | 1244 | EXPORT_SYMBOL_GPL(tpm_read); |
@@ -1326,6 +1323,58 @@ int tpm_pm_resume(struct device *dev) | |||
1326 | } | 1323 | } |
1327 | EXPORT_SYMBOL_GPL(tpm_pm_resume); | 1324 | EXPORT_SYMBOL_GPL(tpm_pm_resume); |
1328 | 1325 | ||
1326 | #define TPM_GETRANDOM_RESULT_SIZE 18 | ||
1327 | static struct tpm_input_header tpm_getrandom_header = { | ||
1328 | .tag = TPM_TAG_RQU_COMMAND, | ||
1329 | .length = cpu_to_be32(14), | ||
1330 | .ordinal = TPM_ORD_GET_RANDOM | ||
1331 | }; | ||
1332 | |||
1333 | /** | ||
1334 | * tpm_get_random() - Get random bytes from the tpm's RNG | ||
1335 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
1336 | * @out: destination buffer for the random bytes | ||
1337 | * @max: the max number of bytes to write to @out | ||
1338 | * | ||
1339 | * Returns < 0 on error and the number of bytes read on success | ||
1340 | */ | ||
1341 | int tpm_get_random(u32 chip_num, u8 *out, size_t max) | ||
1342 | { | ||
1343 | struct tpm_chip *chip; | ||
1344 | struct tpm_cmd_t tpm_cmd; | ||
1345 | u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); | ||
1346 | int err, total = 0, retries = 5; | ||
1347 | u8 *dest = out; | ||
1348 | |||
1349 | chip = tpm_chip_find_get(chip_num); | ||
1350 | if (chip == NULL) | ||
1351 | return -ENODEV; | ||
1352 | |||
1353 | if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) | ||
1354 | return -EINVAL; | ||
1355 | |||
1356 | do { | ||
1357 | tpm_cmd.header.in = tpm_getrandom_header; | ||
1358 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); | ||
1359 | |||
1360 | err = transmit_cmd(chip, &tpm_cmd, | ||
1361 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, | ||
1362 | "attempting get random"); | ||
1363 | if (err) | ||
1364 | break; | ||
1365 | |||
1366 | recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); | ||
1367 | memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); | ||
1368 | |||
1369 | dest += recd; | ||
1370 | total += recd; | ||
1371 | num_bytes -= recd; | ||
1372 | } while (retries-- && total < max); | ||
1373 | |||
1374 | return total ? total : -EIO; | ||
1375 | } | ||
1376 | EXPORT_SYMBOL_GPL(tpm_get_random); | ||
1377 | |||
1329 | /* In case vendor provided release function, call it too.*/ | 1378 | /* In case vendor provided release function, call it too.*/ |
1330 | 1379 | ||
1331 | void tpm_dev_vendor_release(struct tpm_chip *chip) | 1380 | void tpm_dev_vendor_release(struct tpm_chip *chip) |
@@ -1346,7 +1395,7 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); | |||
1346 | * Once all references to platform device are down to 0, | 1395 | * Once all references to platform device are down to 0, |
1347 | * release all allocated structures. | 1396 | * release all allocated structures. |
1348 | */ | 1397 | */ |
1349 | void tpm_dev_release(struct device *dev) | 1398 | static void tpm_dev_release(struct device *dev) |
1350 | { | 1399 | { |
1351 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1400 | struct tpm_chip *chip = dev_get_drvdata(dev); |
1352 | 1401 | ||
@@ -1427,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | |||
1427 | goto put_device; | 1476 | goto put_device; |
1428 | } | 1477 | } |
1429 | 1478 | ||
1479 | if (sys_add_ppi(&dev->kobj)) { | ||
1480 | misc_deregister(&chip->vendor.miscdev); | ||
1481 | goto put_device; | ||
1482 | } | ||
1483 | |||
1430 | chip->bios_dir = tpm_bios_log_setup(devname); | 1484 | chip->bios_dir = tpm_bios_log_setup(devname); |
1431 | 1485 | ||
1432 | /* Make chip available */ | 1486 | /* Make chip available */ |