Provide a wrapper for memcpy to load bytes out of the reply, similar to
LOAD32() and friends.

Signed-off-by: David Howells <dhowe...@redhat.com>
---

 drivers/char/tpm/tpm-library.c |   87 ++++++++++++++++++++--------------------
 drivers/char/tpm/tpm-library.h |   43 +++++++++++++++++---
 include/linux/tpm.h            |    3 +
 3 files changed, 82 insertions(+), 51 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 46cd12d30ec6..329b5c3f23a2 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -199,7 +199,7 @@ out:
  * @...: Pairs of size and pointer of data elements to load into hash
  * @0,NULL: Terminator
  */
-static int TSS_checkhmac1(unsigned char *buffer,
+static int TSS_checkhmac1(struct tpm_buf *tb,
                          __be32 ordinal,
                          const struct tpm_odd_nonce *ononce,
                          const unsigned char *key, unsigned keylen,
@@ -219,14 +219,16 @@ static int TSS_checkhmac1(unsigned char *buffer,
        va_list argp;
        int ret;
 
-       bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
-       tag = LOAD16(buffer, 0);
-       result = LOAD32BE(buffer, TPM_RETURN_OFFSET);
+       SET_BUF_OFFSET(tb, 0);
+       tag = LOAD16(tb);
+       bufsize = LOAD32(tb);
+       result = LOAD32BE(tb);
        if (tag == TPM_TAG_RSP_COMMAND)
                return 0;
        if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
                return -EINVAL;
-       authdata = buffer + bufsize - SHA1_DIGEST_SIZE;
+
+       authdata = tb->data + bufsize - SHA1_DIGEST_SIZE;
        continueflag = authdata - 1;
        enonce = (void *)continueflag - TPM_NONCE_SIZE;
 
@@ -255,7 +257,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
                dpos = va_arg(argp, unsigned int);
                if (!dlen && !dpos)
                        break;
-               ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
+               ret = crypto_shash_update(&sdesc->shash, tb->data + dpos, dlen);
                if (ret < 0)
                        break;
        }
@@ -296,7 +298,7 @@ out:
  *
  * verify the AUTH2_COMMAND (unseal) result from TPM
  */
-static int TSS_checkhmac2(const unsigned char *buffer,
+static int TSS_checkhmac2(struct tpm_buf *tb,
                          __be32 ordinal,
                          const struct tpm_odd_nonce *ononce,
                          const unsigned char *key1, unsigned keylen1,
@@ -321,17 +323,17 @@ static int TSS_checkhmac2(const unsigned char *buffer,
        va_list argp;
        int ret;
 
-       bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
-       tag = LOAD16(buffer, 0);
-       result = LOAD32BE(buffer, TPM_RETURN_OFFSET);
+       bufsize = LOAD32(tb);
+       tag = LOAD16(tb);
+       result = LOAD32BE(tb);
 
        if (tag == TPM_TAG_RSP_COMMAND)
                return 0;
        if (tag != TPM_TAG_RSP_AUTH2_COMMAND)
                return -EINVAL;
-       authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1
+       authdata1 = tb->data + bufsize - (SHA1_DIGEST_SIZE + 1
                        + SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);
-       authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);
+       authdata2 = tb->data + bufsize - (SHA1_DIGEST_SIZE);
        continueflag1 = authdata1 - 1;
        continueflag2 = authdata2 - 1;
        enonce1 = (const void *)continueflag1 - TPM_NONCE_SIZE;
@@ -363,7 +365,7 @@ static int TSS_checkhmac2(const unsigned char *buffer,
                dpos = va_arg(argp, unsigned int);
                if (!dlen && !dpos)
                        break;
-               ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
+               ret = crypto_shash_update(&sdesc->shash, tb->data + dpos, dlen);
                if (ret < 0)
                        break;
        }
@@ -404,17 +406,19 @@ out:
  * For key specific tpm requests, we will generate and send our
  * own TPM command packets using the drivers send function.
  */
-static int tpm_send_dump(struct tpm_chip *chip,
-                        unsigned char *cmd, size_t buflen, const char *desc)
+static int tpm_send_dump(struct tpm_chip *chip, struct tpm_buf *cmd,
+                        const char *desc)
 {
        int rc;
 
        dump_tpm_buf(cmd);
-       rc = tpm_send_command(chip, cmd, buflen, desc);
+       rc = tpm_send_command(chip, cmd->data, MAX_BUF_SIZE, desc);
        dump_tpm_buf(cmd);
        if (rc > 0)
                /* Can't return positive return codes values to keyctl */
                rc = -EPERM;
+       else
+               SET_BUF_OFFSET(cmd, TPM_DATA_OFFSET);
        return rc;
 }
 
@@ -442,16 +446,14 @@ static int tpm_create_osap(struct tpm_chip *chip,
        store32(tb, keyhandle);
        store_s(tb, ononce.data, TPM_NONCE_SIZE);
 
-       ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-                           "creating OSAP session");
+       ret = tpm_send_dump(chip, tb, "creating OSAP session");
        if (ret < 0)
                return ret;
 
-       s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-       memcpy(s->enonce.data, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
-              TPM_NONCE_SIZE);
-       memcpy(enonce.data, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
-                                 TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
+       s->handle = LOAD32(tb);
+       LOAD_S(tb, s->enonce.data, TPM_NONCE_SIZE);
+       LOAD_S(tb, enonce.data, TPM_NONCE_SIZE);
+
        return TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
                           TPM_NONCE_SIZE, enonce.data,
                           TPM_NONCE_SIZE, ononce.data,
@@ -470,14 +472,12 @@ static int tpm_create_oiap(struct tpm_chip *chip, struct 
tpm_buf *tb,
        store16(tb, TPM_TAG_RQU_COMMAND);
        store32(tb, TPM_OIAP_SIZE);
        store32(tb, TPM_ORD_OIAP);
-       ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-                           "creating OIAP session");
+       ret = tpm_send_dump(chip, tb, "creating OIAP session");
        if (ret < 0)
                return ret;
 
-       *handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-       memcpy(enonce->data, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
-              TPM_NONCE_SIZE);
+       *handle = LOAD32(tb);
+       LOAD_S(tb, enonce->data, TPM_NONCE_SIZE);
        return 0;
 }
 
@@ -590,27 +590,29 @@ int tpm_seal(struct tpm_chip *chip,
        store_8(tb, cont);
        store_s(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
-       ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-                           "sealing data");
+       ret = tpm_send_dump(chip, tb, "sealing data");
        if (ret < 0)
                goto out;
 
-       /* calculate the size of the returned encrypted data */
-       sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));
-       encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +
-                            sizeof(uint32_t) + sealinfosize);
-       storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +
-           sizeof(uint32_t) + encdatasize;
+       /* Look inside the TPM_STORED_DATA object to calculate the size of the
+        * returned encrypted data.
+        */
+       SET_BUF_OFFSET(tb, TPM_DATA_OFFSET + sizeof(uint32_t));
+       sealinfosize = LOAD32(tb);
+       SET_BUF_OFFSET(tb, TPM_DATA_OFFSET + sizeof(uint32_t) * 2 + 
sealinfosize);
+       storedsize = sizeof(uint32_t) * 2 + sealinfosize +
+               sizeof(uint32_t) + encdatasize;
 
        /* check the HMAC in the response */
-       ret = TSS_checkhmac1(tb->data, ordinal_be, &td->ononce,
+       ret = TSS_checkhmac1(tb, ordinal_be, &td->ononce,
                             sess.secret, SHA1_DIGEST_SIZE,
                             /* 3S */ storedsize, TPM_DATA_OFFSET,
                             0, NULL);
 
        /* copy the encrypted data to caller's buffer */
        if (!ret) {
-               memcpy(encbuffer, tb->data + TPM_DATA_OFFSET, storedsize);
+               SET_BUF_OFFSET(tb, TPM_DATA_OFFSET);
+               LOAD_S(tb, encbuffer, storedsize);
                *_enclen = storedsize;
        }
 out:
@@ -697,15 +699,14 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
        store_8(tb, cont);
        store_s(tb, authdata2, SHA1_DIGEST_SIZE);
 
-       ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-                           "unsealing data");
+       ret = tpm_send_dump(chip, tb, "unsealing data");
        if (ret < 0) {
                pr_info("authhmac failed (%d)\n", ret);
                return ret;
        }
 
-       *_rawlen = LOAD32(tb->data, TPM_DATA_OFFSET);
-       ret = TSS_checkhmac2(tb->data, ordinal, &ononce,
+       *_rawlen = LOAD32(tb);
+       ret = TSS_checkhmac2(tb, ordinal, &ononce,
                             keyauth, SHA1_DIGEST_SIZE,
                             decauth, SHA1_DIGEST_SIZE,
                             /* 3S */ sizeof(uint32_t), TPM_DATA_OFFSET,
@@ -715,7 +716,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
                pr_info("TSS_checkhmac2 failed (%d)\n", ret);
                return ret;
        }
-       memcpy(rawbuffer, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), 
*_rawlen);
+       LOAD_S(tb, rawbuffer, *_rawlen);
        return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_unseal);
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index c12d451704a2..3e288624b8e8 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -11,10 +11,6 @@
  */
 
 
-#define LOAD32BE(buffer, offset) (*(__be32 *)&buffer[(offset)])
-#define LOAD16(buffer, offset) (be16_to_cpu(*(__be16 *)&buffer[(offset)]))
-#define LOAD32(buffer, offset) (be32_to_cpu(LOAD32BE(buffer, (offset))))
-
 struct tpm_even_nonce {
        unsigned char data[TPM_NONCE_SIZE];
 };
@@ -29,6 +25,38 @@ struct tpm_osapsess {
        struct tpm_even_nonce enonce;
 };
 
+static inline void SET_BUF_OFFSET(struct tpm_buf *buffer, unsigned offset)
+{
+       buffer->offset = offset;
+}
+
+static inline uint16_t LOAD16(struct tpm_buf *buffer)
+{
+       __be16 *p = (__be16 *)(buffer->data + buffer->offset);
+       buffer->offset += 2;
+       return be16_to_cpup(p);
+}
+
+static inline __be32 LOAD32BE(struct tpm_buf *buffer)
+{
+       __be32 val = *(__be32 *)(buffer->data + buffer->offset);
+       buffer->offset += 4;
+       return val;
+}
+
+static inline uint32_t LOAD32(struct tpm_buf *buffer)
+{
+       __be32 *p = (__be32 *)(buffer->data + buffer->offset);
+       buffer->offset += 4;
+       return be32_to_cpup(p);
+}
+
+static inline void LOAD_S(struct tpm_buf *buffer, void *data_buffer, size_t 
amount)
+{
+       memcpy(data_buffer, buffer->data + buffer->offset, amount);
+       buffer->offset += amount;
+}
+
 static inline void store_8(struct tpm_buf *buf, unsigned char value)
 {
        buf->data[buf->len++] = value;
@@ -70,13 +98,14 @@ static inline void dump_sess(struct tpm_osapsess *s)
                       16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
 }
 
-static inline void dump_tpm_buf(unsigned char *buf)
+static inline void dump_tpm_buf(struct tpm_buf *tb)
 {
        int len;
 
        pr_info("\ntpm buffer\n");
-       len = LOAD32(buf, TPM_SIZE_OFFSET);
-       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
+       SET_BUF_OFFSET(tb, TPM_SIZE_OFFSET);
+       len = LOAD32(tb);
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, tb->data, len, 
0);
 }
 
 #else
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index cbd13e03a869..398bfaef2325 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -110,7 +110,8 @@ enum tpm_entity_type {
 };
 
 struct tpm_buf {
-       int len;
+       unsigned short len;
+       unsigned short offset;
        unsigned char data[MAX_BUF_SIZE];
 };
 


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
tpmdd-devel mailing list
tpmdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

Reply via email to