|
@@ -328,7 +328,7 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
|
|
|
|
|
|
-static bool tpm_validate_command(struct tpm_chip *chip,
|
|
|
+static int tpm_validate_command(struct tpm_chip *chip,
|
|
|
struct tpm_space *space,
|
|
|
const u8 *cmd,
|
|
|
size_t len)
|
|
@@ -340,10 +340,10 @@ static bool tpm_validate_command(struct tpm_chip *chip,
|
|
|
unsigned int nr_handles;
|
|
|
|
|
|
if (len < TPM_HEADER_SIZE)
|
|
|
- return false;
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
if (!space)
|
|
|
- return true;
|
|
|
+ return 0;
|
|
|
|
|
|
if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) {
|
|
|
cc = be32_to_cpu(header->ordinal);
|
|
@@ -352,7 +352,7 @@ static bool tpm_validate_command(struct tpm_chip *chip,
|
|
|
if (i < 0) {
|
|
|
dev_dbg(&chip->dev, "0x%04X is an invalid command\n",
|
|
|
cc);
|
|
|
- return false;
|
|
|
+ return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
attrs = chip->cc_attrs_tbl[i];
|
|
@@ -362,11 +362,11 @@ static bool tpm_validate_command(struct tpm_chip *chip,
|
|
|
goto err_len;
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
+ return 0;
|
|
|
err_len:
|
|
|
dev_dbg(&chip->dev,
|
|
|
"%s: insufficient command length %zu", __func__, len);
|
|
|
- return false;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -391,8 +391,20 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
|
|
|
unsigned long stop;
|
|
|
bool need_locality;
|
|
|
|
|
|
- if (!tpm_validate_command(chip, space, buf, bufsiz))
|
|
|
- return -EINVAL;
|
|
|
+ rc = tpm_validate_command(chip, space, buf, bufsiz);
|
|
|
+ if (rc == -EINVAL)
|
|
|
+ return rc;
|
|
|
+ /*
|
|
|
+ * If the command is not implemented by the TPM, synthesize a
|
|
|
+ * response with a TPM2_RC_COMMAND_CODE return for user-space.
|
|
|
+ */
|
|
|
+ if (rc == -EOPNOTSUPP) {
|
|
|
+ header->length = cpu_to_be32(sizeof(*header));
|
|
|
+ header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
|
|
|
+ header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE |
|
|
|
+ TSS2_RESMGR_TPM_RC_LAYER);
|
|
|
+ return bufsiz;
|
|
|
+ }
|
|
|
|
|
|
if (bufsiz > TPM_BUFSIZE)
|
|
|
bufsiz = TPM_BUFSIZE;
|