|
@@ -580,91 +580,133 @@ void tpm_continue_selftest(struct tpm_chip *chip)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_continue_selftest);
|
|
EXPORT_SYMBOL_GPL(tpm_continue_selftest);
|
|
|
|
|
|
|
|
+#define TPM_INTERNAL_RESULT_SIZE 200
|
|
|
|
+
|
|
ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
|
|
ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
|
|
char *buf)
|
|
char *buf)
|
|
{
|
|
{
|
|
- u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t rc;
|
|
ssize_t rc;
|
|
|
|
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_FLAG;
|
|
data[TPM_CAP_IDX] = TPM_CAP_FLAG;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
|
|
|
|
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
- "attemtping to determine the permanent state");
|
|
|
|
- if (rc)
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
|
|
+ "attemtping to determine the permanent enabled state");
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
- return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
|
|
|
|
+
|
|
|
|
+ kfree(data);
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_enabled);
|
|
EXPORT_SYMBOL_GPL(tpm_show_enabled);
|
|
|
|
|
|
ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
|
|
ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
|
|
char *buf)
|
|
char *buf)
|
|
{
|
|
{
|
|
- u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t rc;
|
|
ssize_t rc;
|
|
|
|
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_FLAG;
|
|
data[TPM_CAP_IDX] = TPM_CAP_FLAG;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
|
|
|
|
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
- "attemtping to determine the permanent state");
|
|
|
|
- if (rc)
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
|
|
+ "attemtping to determine the permanent active state");
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
- return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
|
|
|
|
+
|
|
|
|
+ kfree(data);
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_active);
|
|
EXPORT_SYMBOL_GPL(tpm_show_active);
|
|
|
|
|
|
ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
|
|
ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
|
|
char *buf)
|
|
char *buf)
|
|
{
|
|
{
|
|
- u8 data[sizeof(tpm_cap)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t rc;
|
|
ssize_t rc;
|
|
|
|
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
|
|
|
|
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
"attempting to determine the owner state");
|
|
"attempting to determine the owner state");
|
|
- if (rc)
|
|
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
- return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
|
|
|
|
+
|
|
|
|
+ kfree(data);
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_owned);
|
|
EXPORT_SYMBOL_GPL(tpm_show_owned);
|
|
|
|
|
|
ssize_t tpm_show_temp_deactivated(struct device * dev,
|
|
ssize_t tpm_show_temp_deactivated(struct device * dev,
|
|
struct device_attribute * attr, char *buf)
|
|
struct device_attribute * attr, char *buf)
|
|
{
|
|
{
|
|
- u8 data[sizeof(tpm_cap)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t rc;
|
|
ssize_t rc;
|
|
|
|
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_FLAG;
|
|
data[TPM_CAP_IDX] = TPM_CAP_FLAG;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
|
|
|
|
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
"attempting to determine the temporary state");
|
|
"attempting to determine the temporary state");
|
|
- if (rc)
|
|
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
- return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
|
|
|
|
+
|
|
|
|
+ kfree(data);
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
|
|
EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
|
|
|
|
|
|
@@ -678,7 +720,7 @@ static const u8 pcrread[] = {
|
|
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
|
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
char *buf)
|
|
{
|
|
{
|
|
- u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t rc;
|
|
ssize_t rc;
|
|
int i, j, num_pcrs;
|
|
int i, j, num_pcrs;
|
|
__be32 index;
|
|
__be32 index;
|
|
@@ -688,21 +730,27 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
|
|
|
|
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
"attempting to determine the number of PCRS");
|
|
"attempting to determine the number of PCRS");
|
|
- if (rc)
|
|
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
|
|
+ }
|
|
|
|
|
|
num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
|
|
num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
|
|
for (i = 0; i < num_pcrs; i++) {
|
|
for (i = 0; i < num_pcrs; i++) {
|
|
memcpy(data, pcrread, sizeof(pcrread));
|
|
memcpy(data, pcrread, sizeof(pcrread));
|
|
index = cpu_to_be32(i);
|
|
index = cpu_to_be32(i);
|
|
memcpy(data + 10, &index, 4);
|
|
memcpy(data + 10, &index, 4);
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
"attempting to read a PCR");
|
|
"attempting to read a PCR");
|
|
if (rc)
|
|
if (rc)
|
|
goto out;
|
|
goto out;
|
|
@@ -712,6 +760,7 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
|
str += sprintf(str, "\n");
|
|
str += sprintf(str, "\n");
|
|
}
|
|
}
|
|
out:
|
|
out:
|
|
|
|
+ kfree(data);
|
|
return str - buf;
|
|
return str - buf;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_pcrs);
|
|
EXPORT_SYMBOL_GPL(tpm_show_pcrs);
|
|
@@ -795,7 +844,7 @@ static const u8 cap_version[] = {
|
|
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
|
|
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
char *buf)
|
|
{
|
|
{
|
|
- u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t rc;
|
|
ssize_t rc;
|
|
char *str = buf;
|
|
char *str = buf;
|
|
|
|
|
|
@@ -803,21 +852,27 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
|
|
|
|
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
"attempting to determine the manufacturer");
|
|
"attempting to determine the manufacturer");
|
|
- if (rc)
|
|
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
|
|
+ }
|
|
|
|
|
|
str += sprintf(str, "Manufacturer: 0x%x\n",
|
|
str += sprintf(str, "Manufacturer: 0x%x\n",
|
|
be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
|
|
be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
|
|
|
|
|
|
memcpy(data, cap_version, sizeof(cap_version));
|
|
memcpy(data, cap_version, sizeof(cap_version));
|
|
data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
|
|
data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
|
|
- rc = transmit_cmd(chip, data, sizeof(data),
|
|
|
|
|
|
+ rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
|
|
"attempting to determine the 1.1 version");
|
|
"attempting to determine the 1.1 version");
|
|
if (rc)
|
|
if (rc)
|
|
goto out;
|
|
goto out;
|
|
@@ -828,6 +883,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
|
|
(int) data[17]);
|
|
(int) data[17]);
|
|
|
|
|
|
out:
|
|
out:
|
|
|
|
+ kfree(data);
|
|
return str - buf;
|
|
return str - buf;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_caps);
|
|
EXPORT_SYMBOL_GPL(tpm_show_caps);
|
|
@@ -835,7 +891,7 @@ EXPORT_SYMBOL_GPL(tpm_show_caps);
|
|
ssize_t tpm_show_caps_1_2(struct device * dev,
|
|
ssize_t tpm_show_caps_1_2(struct device * dev,
|
|
struct device_attribute * attr, char *buf)
|
|
struct device_attribute * attr, char *buf)
|
|
{
|
|
{
|
|
- u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
|
|
|
|
|
|
+ u8 *data;
|
|
ssize_t len;
|
|
ssize_t len;
|
|
char *str = buf;
|
|
char *str = buf;
|
|
|
|
|
|
@@ -843,15 +899,20 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
|
|
if (chip == NULL)
|
|
if (chip == NULL)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
memcpy(data, tpm_cap, sizeof(tpm_cap));
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_IDX] = TPM_CAP_PROP;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
|
|
data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
|
|
|
|
|
|
- if ((len = tpm_transmit(chip, data, sizeof(data))) <=
|
|
|
|
- TPM_ERROR_SIZE) {
|
|
|
|
|
|
+ len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE);
|
|
|
|
+ if (len <= TPM_ERROR_SIZE) {
|
|
dev_dbg(chip->dev, "A TPM error (%d) occurred "
|
|
dev_dbg(chip->dev, "A TPM error (%d) occurred "
|
|
"attempting to determine the manufacturer\n",
|
|
"attempting to determine the manufacturer\n",
|
|
be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
|
|
be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
|
|
|
|
+ kfree(data);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -861,8 +922,8 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
|
|
memcpy(data, cap_version, sizeof(cap_version));
|
|
memcpy(data, cap_version, sizeof(cap_version));
|
|
data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
|
|
data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
|
|
|
|
|
|
- if ((len = tpm_transmit(chip, data, sizeof(data))) <=
|
|
|
|
- TPM_ERROR_SIZE) {
|
|
|
|
|
|
+ len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE);
|
|
|
|
+ if (len <= TPM_ERROR_SIZE) {
|
|
dev_err(chip->dev, "A TPM error (%d) occurred "
|
|
dev_err(chip->dev, "A TPM error (%d) occurred "
|
|
"attempting to determine the 1.2 version\n",
|
|
"attempting to determine the 1.2 version\n",
|
|
be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
|
|
be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
|
|
@@ -874,6 +935,7 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
|
|
(int) data[19]);
|
|
(int) data[19]);
|
|
|
|
|
|
out:
|
|
out:
|
|
|
|
+ kfree(data);
|
|
return str - buf;
|
|
return str - buf;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
|
|
EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
|