Message ID | 20200407162044.168890-3-amirmizi6@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add tpm i2c ptp driver | expand |
On Tue, Apr 07, 2020 at 07:20:39PM +0300, amirmizi6@gmail.com wrote: > From: Amir Mizinski <amirmizi6@gmail.com> > > In order to validate data integrity we need to compute the crc over the data > sent in lower layer (I2C for instance). s/crc/CRC/ > To do that tpm_tis_check_data() calls a "check_data" operation (if available). "check_data" does not exist. > If data integrity check fails, a retry to save the sent/received > data is implemented in tpm_tis_send_main()/tpm_tis_recv() functions. > > Considering this commit, the following steps are done when sending a command: > 1. Host writes to TPM_STS.commandReady. > 2. Host writes command. > 3. Host checks that TPM received data is valid. > 4. If data is currupted go to step 1. > > When receiving data: > 1. Host checks that TPM_STS.dataAvail is set. > 2. Host saves received data. > 3. Host checks that received data is correct. > 4. If data is currupted Host writes to TPM_STS.responseRetry and go to > step 1. These sequences in the commit message look somewhat uselss. Maybe just remove them. > > Co-developed-by: Christophe Ricard <christophe-h.ricard@st.com> > Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> > Signed-off-by: Amir Mizinski <amirmizi6@gmail.com> > --- > drivers/char/tpm/tpm_tis_core.c | 102 +++++++++++++++++++++++++--------------- > drivers/char/tpm/tpm_tis_core.h | 3 ++ > 2 files changed, 67 insertions(+), 38 deletions(-) > > diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c > index 27c6ca0..6c4f232 100644 > --- a/drivers/char/tpm/tpm_tis_core.c > +++ b/drivers/char/tpm/tpm_tis_core.c > @@ -242,6 +242,15 @@ static u8 tpm_tis_status(struct tpm_chip *chip) > return status; > } > > +static bool tpm_tis_check_data(struct tpm_chip *chip, const u8 *buf, size_t len) Not sure if this is the best possible function name, "check" can mean almost anything. > +{ > + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > + > + if (priv->phy_ops->check_data) > + return priv->phy_ops->check_data(priv, buf, len); New line here before the return statement. > + return true; > +} > + > static void tpm_tis_ready(struct tpm_chip *chip) > { > struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > @@ -308,47 +317,59 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) > { > struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > int size = 0; > - int status; > + int status, i; > u32 expected; > + bool check_data = false; > > - if (count < TPM_HEADER_SIZE) { > - size = -EIO; > - goto out; > - } > + for (i = 0; i < TPM_RETRY; i++) { > + if (count < TPM_HEADER_SIZE) { > + size = -EIO; > + goto out; > + } > > - size = recv_data(chip, buf, TPM_HEADER_SIZE); > - /* read first 10 bytes, including tag, paramsize, and result */ > - if (size < TPM_HEADER_SIZE) { > - dev_err(&chip->dev, "Unable to read header\n"); > - goto out; > - } > + size = recv_data(chip, buf, TPM_HEADER_SIZE); > + /* read first 10 bytes, including tag, paramsize, and result */ > + if (size < TPM_HEADER_SIZE) { > + dev_err(&chip->dev, "Unable to read header\n"); > + goto out; > + } > > - expected = be32_to_cpu(*(__be32 *) (buf + 2)); > - if (expected > count || expected < TPM_HEADER_SIZE) { > - size = -EIO; > - goto out; > - } > + expected = be32_to_cpu(*(__be32 *) (buf + 2)); > + if (expected > count || expected < TPM_HEADER_SIZE) { > + size = -EIO; > + goto out; > + } > > - size += recv_data(chip, &buf[TPM_HEADER_SIZE], > - expected - TPM_HEADER_SIZE); > - if (size < expected) { > - dev_err(&chip->dev, "Unable to read remainder of result\n"); > - size = -ETIME; > - goto out; > - } > + size += recv_data(chip, &buf[TPM_HEADER_SIZE], > + expected - TPM_HEADER_SIZE); > + if (size < expected) { > + dev_err(&chip->dev, "Unable to read remainder of result\n"); > + size = -ETIME; > + goto out; > + } > > - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, > - &priv->int_queue, false) < 0) { > - size = -ETIME; > - goto out; > + if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, > + &priv->int_queue, false) < 0) { > + size = -ETIME; > + goto out; > + } > + > + status = tpm_tis_status(chip); > + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ > + dev_err(&chip->dev, "Error left over data\n"); > + size = -EIO; > + goto out; > + } > + > + check_data = tpm_tis_check_data(chip, buf, size); > + if (!check_data) > + tpm_tis_write8(priv, TPM_STS(priv->locality), > + TPM_STS_RESPONSE_RETRY); > + else > + break; > } > - status = tpm_tis_status(chip); > - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ > - dev_err(&chip->dev, "Error left over data\n"); > + if (!check_data) > size = -EIO; > - goto out; > - } > - > out: > tpm_tis_ready(chip); > return size; > @@ -453,14 +474,19 @@ static void disable_interrupts(struct tpm_chip *chip) > static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) > { > struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > - int rc; > + int rc, i; > u32 ordinal; > unsigned long dur; > + bool data_valid = false; > > - rc = tpm_tis_send_data(chip, buf, len); > - if (rc < 0) > - return rc; > - > + for (i = 0; i < TPM_RETRY && !data_valid; i++) { > + rc = tpm_tis_send_data(chip, buf, len); > + if (rc < 0) > + return rc; > + data_valid = tpm_tis_check_data(chip, buf, len); > + } > + if (!data_valid) > + return -EIO; > /* go and do it */ > rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); > if (rc < 0) > diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h > index d06c65b..486c2e9 100644 > --- a/drivers/char/tpm/tpm_tis_core.h > +++ b/drivers/char/tpm/tpm_tis_core.h > @@ -34,6 +34,7 @@ enum tis_status { > TPM_STS_GO = 0x20, > TPM_STS_DATA_AVAIL = 0x10, > TPM_STS_DATA_EXPECT = 0x08, > + TPM_STS_RESPONSE_RETRY = 0x02, > }; > > enum tis_int_flags { > @@ -106,6 +107,8 @@ struct tpm_tis_phy_ops { > int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); > int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); > int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); > + bool (*check_data)(struct tpm_tis_data *data, const u8 *buf, > + size_t len); Aren't you validating the contents of the buf? /Jarkko
There is something seriously wrong in your email client. Please reconfigure your email client according to: https://www.kernel.org/doc/html/v5.5/process/email-clients.html Then re-response. This is.. I've lost to the count how many times I've requsted this. Thanks. /Jarkko
Hello jarkko, I reconfigure my email client by the instructions you've sent, and re-responsing as you requested. please tell me if there are still any issues. thank you. On 2020-04-08 18:33, Jarkko Sakkinen wrote: > On Tue, Apr 07, 2020 at 07:20:39PM +0300, amirmizi6@gmail.com wrote: >> From: Amir Mizinski <amirmizi6@gmail.com> >> >> In order to validate data integrity we need to compute the crc over the data >> sent in lower layer (I2C for instance). > > s/crc/CRC/ > >> To do that tpm_tis_check_data() calls a "check_data" operation (if available). > > "check_data" does not exist. > it is added in this commit to "tpm_tis_phy_ops" struct in "tpm_tis_core.h", which is inherited in "tpm_tis_i2c.c" on later patch (7/7). >> If data integrity check fails, a retry to save the sent/received >> data is implemented in tpm_tis_send_main()/tpm_tis_recv() functions. >> >> Considering this commit, the following steps are done when sending a command: >> 1. Host writes to TPM_STS.commandReady. >> 2. Host writes command. >> 3. Host checks that TPM received data is valid. >> 4. If data is currupted go to step 1. >> >> When receiving data: >> 1. Host checks that TPM_STS.dataAvail is set. >> 2. Host saves received data. >> 3. Host checks that received data is correct. >> 4. If data is currupted Host writes to TPM_STS.responseRetry and go to >> step 1. > > These sequences in the commit message look somewhat uselss. Maybe > just remove them. > Their main porpose is to describe how the retry attempt is implemented in case of currupted data. should i just describe that with a few words or that's unnecessary? >> >> Co-developed-by: Christophe Ricard <christophe-h.ricard@st.com> >> Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> >> Signed-off-by: Amir Mizinski <amirmizi6@gmail.com> >> --- >> drivers/char/tpm/tpm_tis_core.c | 102 +++++++++++++++++++++++++--------------- >> drivers/char/tpm/tpm_tis_core.h | 3 ++ >> 2 files changed, 67 insertions(+), 38 deletions(-) >> >> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c >> index 27c6ca0..6c4f232 100644 >> --- a/drivers/char/tpm/tpm_tis_core.c >> +++ b/drivers/char/tpm/tpm_tis_core.c >> @@ -242,6 +242,15 @@ static u8 tpm_tis_status(struct tpm_chip *chip) >> return status; >> } >> >> +static bool tpm_tis_check_data(struct tpm_chip *chip, const u8 *buf, size_t len) > > Not sure if this is the best possible function name, "check" can > mean almost anything. > Ok, i'm changing it to "verify_data_integrity". is that ok? >> +{ >> + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); >> + >> + if (priv->phy_ops->check_data) >> + return priv->phy_ops->check_data(priv, buf, len); > > New line here before the return statement. > >> + return true; >> +} >> + >> static void tpm_tis_ready(struct tpm_chip *chip) >> { >> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); >> @@ -308,47 +317,59 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) >> { >> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); >> int size = 0; >> - int status; >> + int status, i; >> u32 expected; >> + bool check_data = false; >> >> - if (count < TPM_HEADER_SIZE) { >> - size = -EIO; >> - goto out; >> - } >> + for (i = 0; i < TPM_RETRY; i++) { >> + if (count < TPM_HEADER_SIZE) { >> + size = -EIO; >> + goto out; >> + } >> >> - size = recv_data(chip, buf, TPM_HEADER_SIZE); >> - /* read first 10 bytes, including tag, paramsize, and result */ >> - if (size < TPM_HEADER_SIZE) { >> - dev_err(&chip->dev, "Unable to read header\n"); >> - goto out; >> - } >> + size = recv_data(chip, buf, TPM_HEADER_SIZE); >> + /* read first 10 bytes, including tag, paramsize, and result */ >> + if (size < TPM_HEADER_SIZE) { >> + dev_err(&chip->dev, "Unable to read header\n"); >> + goto out; >> + } >> >> - expected = be32_to_cpu(*(__be32 *) (buf + 2)); >> - if (expected > count || expected < TPM_HEADER_SIZE) { >> - size = -EIO; >> - goto out; >> - } >> + expected = be32_to_cpu(*(__be32 *) (buf + 2)); >> + if (expected > count || expected < TPM_HEADER_SIZE) { >> + size = -EIO; >> + goto out; >> + } >> >> - size += recv_data(chip, &buf[TPM_HEADER_SIZE], >> - expected - TPM_HEADER_SIZE); >> - if (size < expected) { >> - dev_err(&chip->dev, "Unable to read remainder of result\n"); >> - size = -ETIME; >> - goto out; >> - } >> + size += recv_data(chip, &buf[TPM_HEADER_SIZE], >> + expected - TPM_HEADER_SIZE); >> + if (size < expected) { >> + dev_err(&chip->dev, "Unable to read remainder of result\n"); >> + size = -ETIME; >> + goto out; >> + } >> >> - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, >> - &priv->int_queue, false) < 0) { >> - size = -ETIME; >> - goto out; >> + if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, >> + &priv->int_queue, false) < 0) { >> + size = -ETIME; >> + goto out; >> + } >> + >> + status = tpm_tis_status(chip); >> + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ >> + dev_err(&chip->dev, "Error left over data\n"); >> + size = -EIO; >> + goto out; >> + } >> + >> + check_data = tpm_tis_check_data(chip, buf, size); >> + if (!check_data) >> + tpm_tis_write8(priv, TPM_STS(priv->locality), >> + TPM_STS_RESPONSE_RETRY); >> + else >> + break; >> } >> - status = tpm_tis_status(chip); >> - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ >> - dev_err(&chip->dev, "Error left over data\n"); >> + if (!check_data) >> size = -EIO; >> - goto out; >> - } >> - >> out: >> tpm_tis_ready(chip); >> return size; >> @@ -453,14 +474,19 @@ static void disable_interrupts(struct tpm_chip *chip) >> static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) >> { >> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); >> - int rc; >> + int rc, i; >> u32 ordinal; >> unsigned long dur; >> + bool data_valid = false; >> >> - rc = tpm_tis_send_data(chip, buf, len); >> - if (rc < 0) >> - return rc; >> - >> + for (i = 0; i < TPM_RETRY && !data_valid; i++) { >> + rc = tpm_tis_send_data(chip, buf, len); >> + if (rc < 0) >> + return rc; >> + data_valid = tpm_tis_check_data(chip, buf, len); >> + } >> + if (!data_valid) >> + return -EIO; >> /* go and do it */ >> rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); >> if (rc < 0) >> diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h >> index d06c65b..486c2e9 100644 >> --- a/drivers/char/tpm/tpm_tis_core.h >> +++ b/drivers/char/tpm/tpm_tis_core.h >> @@ -34,6 +34,7 @@ enum tis_status { >> TPM_STS_GO = 0x20, >> TPM_STS_DATA_AVAIL = 0x10, >> TPM_STS_DATA_EXPECT = 0x08, >> + TPM_STS_RESPONSE_RETRY = 0x02, >> }; >> >> enum tis_int_flags { >> @@ -106,6 +107,8 @@ struct tpm_tis_phy_ops { >> int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); >> int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); >> int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); >> + bool (*check_data)(struct tpm_tis_data *data, const u8 *buf, >> + size_t len); > > Aren't you validating the contents of the buf? > > /Jarkko i do. when sending, the data is written to the buff in "tpm_tis_send_data(chip,buf, len)". and validated in "data_valid = tpm_tis_check_data(chip, buf, len)". data is not sent until TPM_STS_GO is set. when receiving, the data in the buffer is verified after recv_data, and writing to TPM_STS_RESPONSE_RETRY in case it fails to recive it again. Thank you Amir Mizinski
On Tue, Apr 21, 2020 at 01:34:44PM +0000, Amir Mizinski wrote: > > Hello jarkko, > I reconfigure my email client by the instructions you've sent, and > re-responsing as you requested. > please tell me if there are still any issues. thank you. This is great, thanks a lot! Easy enough to check too: https://lore.kernel.org/linux-integrity/0cfa0486-8ccb-d7d1-acf2-ca103f723b3a@gmail.com/ It wouldn't end up to the ML if your config wasn't correct. /Jarkko
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 27c6ca0..6c4f232 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -242,6 +242,15 @@ static u8 tpm_tis_status(struct tpm_chip *chip) return status; } +static bool tpm_tis_check_data(struct tpm_chip *chip, const u8 *buf, size_t len) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + + if (priv->phy_ops->check_data) + return priv->phy_ops->check_data(priv, buf, len); + return true; +} + static void tpm_tis_ready(struct tpm_chip *chip) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); @@ -308,47 +317,59 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int size = 0; - int status; + int status, i; u32 expected; + bool check_data = false; - if (count < TPM_HEADER_SIZE) { - size = -EIO; - goto out; - } + for (i = 0; i < TPM_RETRY; i++) { + if (count < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } - size = recv_data(chip, buf, TPM_HEADER_SIZE); - /* read first 10 bytes, including tag, paramsize, and result */ - if (size < TPM_HEADER_SIZE) { - dev_err(&chip->dev, "Unable to read header\n"); - goto out; - } + size = recv_data(chip, buf, TPM_HEADER_SIZE); + /* read first 10 bytes, including tag, paramsize, and result */ + if (size < TPM_HEADER_SIZE) { + dev_err(&chip->dev, "Unable to read header\n"); + goto out; + } - expected = be32_to_cpu(*(__be32 *) (buf + 2)); - if (expected > count || expected < TPM_HEADER_SIZE) { - size = -EIO; - goto out; - } + expected = be32_to_cpu(*(__be32 *) (buf + 2)); + if (expected > count || expected < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } - size += recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); - if (size < expected) { - dev_err(&chip->dev, "Unable to read remainder of result\n"); - size = -ETIME; - goto out; - } + size += recv_data(chip, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (size < expected) { + dev_err(&chip->dev, "Unable to read remainder of result\n"); + size = -ETIME; + goto out; + } - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, - &priv->int_queue, false) < 0) { - size = -ETIME; - goto out; + if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, + &priv->int_queue, false) < 0) { + size = -ETIME; + goto out; + } + + status = tpm_tis_status(chip); + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ + dev_err(&chip->dev, "Error left over data\n"); + size = -EIO; + goto out; + } + + check_data = tpm_tis_check_data(chip, buf, size); + if (!check_data) + tpm_tis_write8(priv, TPM_STS(priv->locality), + TPM_STS_RESPONSE_RETRY); + else + break; } - status = tpm_tis_status(chip); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ - dev_err(&chip->dev, "Error left over data\n"); + if (!check_data) size = -EIO; - goto out; - } - out: tpm_tis_ready(chip); return size; @@ -453,14 +474,19 @@ static void disable_interrupts(struct tpm_chip *chip) static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - int rc; + int rc, i; u32 ordinal; unsigned long dur; + bool data_valid = false; - rc = tpm_tis_send_data(chip, buf, len); - if (rc < 0) - return rc; - + for (i = 0; i < TPM_RETRY && !data_valid; i++) { + rc = tpm_tis_send_data(chip, buf, len); + if (rc < 0) + return rc; + data_valid = tpm_tis_check_data(chip, buf, len); + } + if (!data_valid) + return -EIO; /* go and do it */ rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); if (rc < 0) diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index d06c65b..486c2e9 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -34,6 +34,7 @@ enum tis_status { TPM_STS_GO = 0x20, TPM_STS_DATA_AVAIL = 0x10, TPM_STS_DATA_EXPECT = 0x08, + TPM_STS_RESPONSE_RETRY = 0x02, }; enum tis_int_flags { @@ -106,6 +107,8 @@ struct tpm_tis_phy_ops { int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); + bool (*check_data)(struct tpm_tis_data *data, const u8 *buf, + size_t len); }; static inline int tpm_tis_read_bytes(struct tpm_tis_data *data, u32 addr,