[PATCH] TPM: Fixup pubek sysfs file

From: Jason Gunthorpe
Date: Fri Sep 04 2009 - 01:01:15 EST


tpm_show_pubek is utterly and completely wrong, all the offsets
into the binary blob are wrong, the output is garbage. Do it again.

Before:
Algorithm: 00 0C 00 00
Encscheme: 08 00
Sigscheme: 00 00
Parameters: 00 00 00 00 01 00 AF 6B 30 9B 0D B3
Modulus length: -1266846667
Modulus:
68 45 8D CA A5 EF A8 8A DD 0F D7 84 8E 8D 1F 40
22 92 09 CF 12 C8 9F 6E 55 57 6A 2C A8 0B 5E 45
C7 5E 3D 56 DA 64 E6 E1 F7 8C DD 41 92 28 2E 06
41 02 3E 11 7D B2 C5 46 38 E5 8C 60 D2 96 EE 0C
D6 3D F8 99 E3 02 3A 32 7A 02 C8 31 29 98 28 B9
1B EF 30 A1 A0 45 A0 C0 05 0E C5 96 95 FD 91 47
0A 35 E0 69 B0 8B 49 BD B9 F6 5D 25 21 25 79 1B
20 0D C3 C7 1F 87 5E 5F 41 4B DE 32 DF 55 F3 BD
7F CA D8 7D 3A B4 D5 0A EF CF 8E 72 20 52 15 FA
FB C6 C0 2E C2 AB C6 07 D0 9D 96 6B 2E 30 F7 54
C4 A5 CD 9B 13 54 A0 D1 71 66 91 97 06 12 B5 2D
B2 33 62 FB 56 62 64 A8 AA E9 F2 F4 03 C3 F4 49
2A 09 0D 7D 75 99 6C F0 47 1E 7D D5 A5 CA CE EF
45 B2 DA 88 93 B4 EE EB FB B0 A6 A4 19 C4 B8 0D
04 46 AE BD C5 2E 30 84 49 57 25 34 78 E6 ED C4
50 AF 3B F6 86 43 54 0A D9 DB 54 9C 06 B3 50 7F

After:
Algorithm: 00 00 00 01
Encscheme: 00 03
Sigscheme: 00 01
Parameters: 00 00 08 00 00 00 00 02 00 00 00 00
Modulus length: 256
Modulus:
AF 6B 30 9B 0D B3 B4 7D 74 35 68 45 8D CA A5 EF
A8 8A DD 0F D7 84 8E 8D 1F 40 22 92 09 CF 12 C8
9F 6E 55 57 6A 2C A8 0B 5E 45 C7 5E 3D 56 DA 64
E6 E1 F7 8C DD 41 92 28 2E 06 41 02 3E 11 7D B2
C5 46 38 E5 8C 60 D2 96 EE 0C D6 3D F8 99 E3 02
3A 32 7A 02 C8 31 29 98 28 B9 1B EF 30 A1 A0 45
A0 C0 05 0E C5 96 95 FD 91 47 0A 35 E0 69 B0 8B
49 BD B9 F6 5D 25 21 25 79 1B 20 0D C3 C7 1F 87
5E 5F 41 4B DE 32 DF 55 F3 BD 7F CA D8 7D 3A B4
D5 0A EF CF 8E 72 20 52 15 FA FB C6 C0 2E C2 AB
C6 07 D0 9D 96 6B 2E 30 F7 54 C4 A5 CD 9B 13 54
A0 D1 71 66 91 97 06 12 B5 2D B2 33 62 FB 56 62
64 A8 AA E9 F2 F4 03 C3 F4 49 2A 09 0D 7D 75 99
6C F0 47 1E 7D D5 A5 CA CE EF 45 B2 DA 88 93 B4
EE EB FB B0 A6 A4 19 C4 B8 0D 04 46 AE BD C5 2E
30 84 49 57 25 34 78 E6 ED C4 50 AF 3B F6 86 43

I've checked this decoded output in two different ways.

Tested on a winbond WPCT200

Signed-off-by: Jason Gunthorpe <jgunthorpe@xxxxxxxxxxxxxxxxxxxx>
---
drivers/char/tpm/tpm.c | 77 +++++++++++++++++++++++++++++++++---------------
1 files changed, 53 insertions(+), 24 deletions(-)

Andrew: More testing found this too. In truth this file is probably
fairly useless since it won't output anything once the TPM is owned,
but if it is going to be there it may as well work right.

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 5d5b324..196bc48 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -460,6 +460,11 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
return err;
}
+ if (len != be32_to_cpu(cmd->header.out.length)) {
+ dev_dbg(chip->dev, "TPM returned the wrong length %x %x\n",
+ len, be32_to_cpu(cmd->header.out.length));
+ return -1;
+ }
return 0;
}

@@ -811,43 +816,67 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
{
u8 *data;
struct tpm_cmd_t tpm_cmd;
- ssize_t err;
- int i, rc;
+ ssize_t len;
+ int i, rc, key_len;
char *str = buf;

struct tpm_chip *chip = dev_get_drvdata(dev);

tpm_cmd.header.in = tpm_readpubek_header;
- err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
- "attempting to read the PUBEK");
- if (err)
+ if (transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+ "attempting to read the PUBEK"))
+ goto out;
+
+ len = be32_to_cpu(tpm_cmd.header.out.length);
+ if (len <= 0)
goto out;

- /*
- ignore header 10 bytes
- algorithm 32 bits (1 == RSA )
- encscheme 16 bits
- sigscheme 16 bits
- parameters (RSA 12->bytes: keybit, #primes, expbit)
- keylenbytes 32 bits
- 256 byte modulus
- ignore checksum 20 bytes
+ /* Format (in bytes):
+ 10 RPC Header (tpm_cmd.header)
+ xx TPM_PUBKEY pubEK
+ xx TPM_KEY_PARMS
+ 4 algorithmID
+ 2 encScheme
+ 2 sigcScheme
+ 4 parmSize
+ xx parms (typically 12 bytes for a RSA key)
+ xx TPM_STORE_PUBKEY
+ 4 keyLength
+ xx key (typically 256 for a RSA key)
+ 20 TPM_DIGEST checksum
*/
data = tpm_cmd.params.readpubek_out_buffer;
+ len -= 10;
+ if (len < 24)
+ goto out;
str +=
sprintf(str,
"Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
"Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
- " %02X %02X %02X %02X %02X %02X %02X %02X\n"
- "Modulus length: %d\nModulus: \n",
- data[10], data[11], data[12], data[13], data[14],
- data[15], data[16], data[17], data[22], data[23],
- data[24], data[25], data[26], data[27], data[28],
- data[29], data[30], data[31], data[32], data[33],
- be32_to_cpu(*((__be32 *) (data + 34))));
-
- for (i = 0; i < 256; i++) {
- str += sprintf(str, "%02X ", data[i + 38]);
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ data[0], data[1], data[2], data[3],
+ data[4], data[5],
+ data[6], data[7],
+ data[12], data[13], data[14], data[15], data[16], data[17],
+ data[18], data[19], data[20], data[21], data[22], data[23]);
+ /* Skip TPM_KEY_PARMS.parms and TPM_STORE_PBUKEY.keyLength */
+ i = 4 + 2 + 2 + 4 + be32_to_cpu(*((__be32 *) (data + 8))) + 4;
+ if (i > len)
+ goto out;
+ data += i;
+ len -= i;
+ key_len = be32_to_cpu(*((__be32 *) (data) - 1));
+
+ /* Note: The value printed here is the TPM_STORE_PUBKEY. For RSA keys
+ this is a modulus, but it can vary for other key types. */
+ str += sprintf(str, "Modulus length: %d\nModulus: \n", key_len);
+
+ /* len is bounded, so key_len is bounded, so sprintf is bounded, so
+ str doesn't overflow. Well, maybe. */
+ if (key_len > len)
+ goto out;
+ for (i = 0; i < key_len; i++) {
+ str += sprintf(str, "%02X ", data[i]);
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
--
1.5.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/