Skip to content

Commit 001eefb

Browse files
committed
Merge tag 'tpmdd-sessions-next-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
Pull more tpm updates from Jarkko Sakkinen: "This is targeted for tpm2-sessions updates. There's two bug fixes and two more cosmetic tweaks for HMAC protected sessions. They provide a baseine for further improvements to be implemented during the the course of the release cycle" * tag 'tpmdd-sessions-next-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: tpm2-sessions: Open code tpm_buf_append_hmac_session() tpm2-sessions: Remove 'attributes' parameter from tpm_buf_append_auth tpm2-sessions: Fix tpm2_read_public range checks tpm2-sessions: Fix out of range indexing in name_size
2 parents f19b841 + b7960b9 commit 001eefb

4 files changed

Lines changed: 204 additions & 116 deletions

File tree

drivers/char/tpm/tpm2-cmd.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
* used by the kernel internally.
1212
*/
1313

14+
#include "linux/dev_printk.h"
15+
#include "linux/tpm.h"
1416
#include "tpm.h"
1517
#include <crypto/hash_info.h>
18+
#include <linux/unaligned.h>
1619

1720
static bool disable_pcr_integrity;
1821
module_param(disable_pcr_integrity, bool, 0444);
@@ -199,11 +202,15 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
199202
}
200203

201204
if (!disable_pcr_integrity) {
202-
tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
205+
rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
206+
if (rc) {
207+
tpm_buf_destroy(&buf);
208+
return rc;
209+
}
203210
tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
204211
} else {
205212
tpm_buf_append_handle(chip, &buf, pcr_idx);
206-
tpm_buf_append_auth(chip, &buf, 0, NULL, 0);
213+
tpm_buf_append_auth(chip, &buf, NULL, 0);
207214
}
208215

209216
tpm_buf_append_u32(&buf, chip->nr_allocated_banks);
@@ -214,8 +221,14 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
214221
chip->allocated_banks[i].digest_size);
215222
}
216223

217-
if (!disable_pcr_integrity)
218-
tpm_buf_fill_hmac_session(chip, &buf);
224+
if (!disable_pcr_integrity) {
225+
rc = tpm_buf_fill_hmac_session(chip, &buf);
226+
if (rc) {
227+
tpm_buf_destroy(&buf);
228+
return rc;
229+
}
230+
}
231+
219232
rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
220233
if (!disable_pcr_integrity)
221234
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
@@ -269,11 +282,24 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
269282

270283
do {
271284
tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
272-
tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT
273-
| TPM2_SA_CONTINUE_SESSION,
274-
NULL, 0);
285+
if (tpm2_chip_auth(chip)) {
286+
tpm_buf_append_hmac_session(chip, &buf,
287+
TPM2_SA_ENCRYPT |
288+
TPM2_SA_CONTINUE_SESSION,
289+
NULL, 0);
290+
} else {
291+
offset = buf.handles * 4 + TPM_HEADER_SIZE;
292+
head = (struct tpm_header *)buf.data;
293+
if (tpm_buf_length(&buf) == offset)
294+
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
295+
}
275296
tpm_buf_append_u16(&buf, num_bytes);
276-
tpm_buf_fill_hmac_session(chip, &buf);
297+
err = tpm_buf_fill_hmac_session(chip, &buf);
298+
if (err) {
299+
tpm_buf_destroy(&buf);
300+
return err;
301+
}
302+
277303
err = tpm_transmit_cmd(chip, &buf,
278304
offsetof(struct tpm2_get_random_out,
279305
buffer),

drivers/char/tpm/tpm2-sessions.c

Lines changed: 128 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -144,59 +144,80 @@ struct tpm2_auth {
144144
/*
145145
* Name Size based on TPM algorithm (assumes no hash bigger than 255)
146146
*/
147-
static u8 name_size(const u8 *name)
147+
static int name_size(const u8 *name)
148148
{
149-
static u8 size_map[] = {
150-
[TPM_ALG_SHA1] = SHA1_DIGEST_SIZE,
151-
[TPM_ALG_SHA256] = SHA256_DIGEST_SIZE,
152-
[TPM_ALG_SHA384] = SHA384_DIGEST_SIZE,
153-
[TPM_ALG_SHA512] = SHA512_DIGEST_SIZE,
154-
};
155-
u16 alg = get_unaligned_be16(name);
156-
return size_map[alg] + 2;
157-
}
158-
159-
static int tpm2_parse_read_public(char *name, struct tpm_buf *buf)
160-
{
161-
struct tpm_header *head = (struct tpm_header *)buf->data;
162-
off_t offset = TPM_HEADER_SIZE;
163-
u32 tot_len = be32_to_cpu(head->length);
164-
u32 val;
165-
166-
/* we're starting after the header so adjust the length */
167-
tot_len -= TPM_HEADER_SIZE;
168-
169-
/* skip public */
170-
val = tpm_buf_read_u16(buf, &offset);
171-
if (val > tot_len)
172-
return -EINVAL;
173-
offset += val;
174-
/* name */
175-
val = tpm_buf_read_u16(buf, &offset);
176-
if (val != name_size(&buf->data[offset]))
149+
u16 hash_alg = get_unaligned_be16(name);
150+
151+
switch (hash_alg) {
152+
case TPM_ALG_SHA1:
153+
return SHA1_DIGEST_SIZE + 2;
154+
case TPM_ALG_SHA256:
155+
return SHA256_DIGEST_SIZE + 2;
156+
case TPM_ALG_SHA384:
157+
return SHA384_DIGEST_SIZE + 2;
158+
case TPM_ALG_SHA512:
159+
return SHA512_DIGEST_SIZE + 2;
160+
default:
161+
pr_warn("tpm: unsupported name algorithm: 0x%04x\n", hash_alg);
177162
return -EINVAL;
178-
memcpy(name, &buf->data[offset], val);
179-
/* forget the rest */
180-
return 0;
163+
}
181164
}
182165

183-
static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
166+
static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
184167
{
168+
u32 mso = tpm2_handle_mso(handle);
169+
off_t offset = TPM_HEADER_SIZE;
170+
int rc, name_size_alg;
185171
struct tpm_buf buf;
186-
int rc;
172+
173+
if (mso != TPM2_MSO_PERSISTENT && mso != TPM2_MSO_VOLATILE &&
174+
mso != TPM2_MSO_NVRAM) {
175+
memcpy(name, &handle, sizeof(u32));
176+
return sizeof(u32);
177+
}
187178

188179
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
189180
if (rc)
190181
return rc;
191182

192183
tpm_buf_append_u32(&buf, handle);
193-
rc = tpm_transmit_cmd(chip, &buf, 0, "read public");
194-
if (rc == TPM2_RC_SUCCESS)
195-
rc = tpm2_parse_read_public(name, &buf);
196184

197-
tpm_buf_destroy(&buf);
185+
rc = tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic");
186+
if (rc) {
187+
tpm_buf_destroy(&buf);
188+
return tpm_ret_to_err(rc);
189+
}
198190

199-
return rc;
191+
/* Skip TPMT_PUBLIC: */
192+
offset += tpm_buf_read_u16(&buf, &offset);
193+
194+
/*
195+
* Ensure space for the length field of TPM2B_NAME and hashAlg field of
196+
* TPMT_HA (the extra four bytes).
197+
*/
198+
if (offset + 4 > tpm_buf_length(&buf)) {
199+
tpm_buf_destroy(&buf);
200+
return -EIO;
201+
}
202+
203+
rc = tpm_buf_read_u16(&buf, &offset);
204+
name_size_alg = name_size(&buf.data[offset]);
205+
206+
if (name_size_alg < 0)
207+
return name_size_alg;
208+
209+
if (rc != name_size_alg) {
210+
tpm_buf_destroy(&buf);
211+
return -EIO;
212+
}
213+
214+
if (offset + rc > tpm_buf_length(&buf)) {
215+
tpm_buf_destroy(&buf);
216+
return -EIO;
217+
}
218+
219+
memcpy(name, &buf.data[offset], rc);
220+
return name_size_alg;
200221
}
201222
#endif /* CONFIG_TCG_TPM2_HMAC */
202223

@@ -221,52 +242,76 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
221242
* As with most tpm_buf operations, success is assumed because failure
222243
* will be caused by an incorrect programming model and indicated by a
223244
* kernel message.
245+
*
246+
* Ends the authorization session on failure.
224247
*/
225-
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
226-
u32 handle, u8 *name)
248+
int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
249+
u32 handle, u8 *name)
227250
{
228251
#ifdef CONFIG_TCG_TPM2_HMAC
229252
enum tpm2_mso_type mso = tpm2_handle_mso(handle);
230253
struct tpm2_auth *auth;
254+
u16 name_size_alg;
231255
int slot;
256+
int ret;
232257
#endif
233258

234259
if (!tpm2_chip_auth(chip)) {
235260
tpm_buf_append_handle(chip, buf, handle);
236-
return;
261+
return 0;
237262
}
238263

239264
#ifdef CONFIG_TCG_TPM2_HMAC
240265
slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
241266
if (slot >= AUTH_MAX_NAMES) {
242-
dev_err(&chip->dev, "TPM: too many handles\n");
243-
return;
267+
dev_err(&chip->dev, "too many handles\n");
268+
ret = -EIO;
269+
goto err;
244270
}
245271
auth = chip->auth;
246-
WARN(auth->session != tpm_buf_length(buf),
247-
"name added in wrong place\n");
272+
if (auth->session != tpm_buf_length(buf)) {
273+
dev_err(&chip->dev, "session state malformed");
274+
ret = -EIO;
275+
goto err;
276+
}
248277
tpm_buf_append_u32(buf, handle);
249278
auth->session += 4;
250279

251280
if (mso == TPM2_MSO_PERSISTENT ||
252281
mso == TPM2_MSO_VOLATILE ||
253282
mso == TPM2_MSO_NVRAM) {
254-
if (!name)
255-
tpm2_read_public(chip, handle, auth->name[slot]);
283+
if (!name) {
284+
ret = tpm2_read_public(chip, handle, auth->name[slot]);
285+
if (ret < 0)
286+
goto err;
287+
288+
name_size_alg = ret;
289+
}
256290
} else {
257-
if (name)
258-
dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
291+
if (name) {
292+
dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
293+
handle);
294+
ret = -EIO;
295+
goto err;
296+
}
259297
}
260298

261299
auth->name_h[slot] = handle;
262300
if (name)
263-
memcpy(auth->name[slot], name, name_size(name));
301+
memcpy(auth->name[slot], name, name_size_alg);
302+
#endif
303+
return 0;
304+
305+
#ifdef CONFIG_TCG_TPM2_HMAC
306+
err:
307+
tpm2_end_auth_session(chip);
308+
return tpm_ret_to_err(ret);
264309
#endif
265310
}
266311
EXPORT_SYMBOL_GPL(tpm_buf_append_name);
267312

268313
void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf,
269-
u8 attributes, u8 *passphrase, int passphrase_len)
314+
u8 *passphrase, int passphrase_len)
270315
{
271316
/* offset tells us where the sessions area begins */
272317
int offset = buf->handles * 4 + TPM_HEADER_SIZE;
@@ -327,8 +372,7 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
327372
#endif
328373

329374
if (!tpm2_chip_auth(chip)) {
330-
tpm_buf_append_auth(chip, buf, attributes, passphrase,
331-
passphrase_len);
375+
tpm_buf_append_auth(chip, buf, passphrase, passphrase_len);
332376
return;
333377
}
334378

@@ -533,11 +577,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
533577
* encryption key and encrypts the first parameter of the command
534578
* buffer with it.
535579
*
536-
* As with most tpm_buf operations, success is assumed because failure
537-
* will be caused by an incorrect programming model and indicated by a
538-
* kernel message.
580+
* Ends the authorization session on failure.
539581
*/
540-
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
582+
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
541583
{
542584
u32 cc, handles, val;
543585
struct tpm2_auth *auth = chip->auth;
@@ -549,9 +591,12 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
549591
u8 cphash[SHA256_DIGEST_SIZE];
550592
struct sha256_ctx sctx;
551593
struct hmac_sha256_ctx hctx;
594+
int ret;
552595

553-
if (!auth)
554-
return;
596+
if (!auth) {
597+
ret = -EIO;
598+
goto err;
599+
}
555600

556601
/* save the command code in BE format */
557602
auth->ordinal = head->ordinal;
@@ -560,9 +605,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
560605

561606
i = tpm2_find_cc(chip, cc);
562607
if (i < 0) {
563-
dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc);
564-
return;
608+
dev_err(&chip->dev, "command 0x%08x not found\n", cc);
609+
ret = -EIO;
610+
goto err;
565611
}
612+
566613
attrs = chip->cc_attrs_tbl[i];
567614

568615
handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
@@ -576,9 +623,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
576623
u32 handle = tpm_buf_read_u32(buf, &offset_s);
577624

578625
if (auth->name_h[i] != handle) {
579-
dev_err(&chip->dev, "TPM: handle %d wrong for name\n",
580-
i);
581-
return;
626+
dev_err(&chip->dev, "invalid handle 0x%08x\n", handle);
627+
ret = -EIO;
628+
goto err;
582629
}
583630
}
584631
/* point offset_s to the start of the sessions */
@@ -609,12 +656,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
609656
offset_s += len;
610657
}
611658
if (offset_s != offset_p) {
612-
dev_err(&chip->dev, "TPM session length is incorrect\n");
613-
return;
659+
dev_err(&chip->dev, "session length is incorrect\n");
660+
ret = -EIO;
661+
goto err;
614662
}
615663
if (!hmac) {
616-
dev_err(&chip->dev, "TPM could not find HMAC session\n");
617-
return;
664+
dev_err(&chip->dev, "could not find HMAC session\n");
665+
ret = -EIO;
666+
goto err;
618667
}
619668

620669
/* encrypt before HMAC */
@@ -646,8 +695,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
646695
if (mso == TPM2_MSO_PERSISTENT ||
647696
mso == TPM2_MSO_VOLATILE ||
648697
mso == TPM2_MSO_NVRAM) {
649-
sha256_update(&sctx, auth->name[i],
650-
name_size(auth->name[i]));
698+
ret = name_size(auth->name[i]);
699+
if (ret < 0)
700+
goto err;
701+
702+
sha256_update(&sctx, auth->name[i], ret);
651703
} else {
652704
__be32 h = cpu_to_be32(auth->name_h[i]);
653705

@@ -668,6 +720,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
668720
hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
669721
hmac_sha256_update(&hctx, &auth->attrs, 1);
670722
hmac_sha256_final(&hctx, hmac);
723+
return 0;
724+
725+
err:
726+
tpm2_end_auth_session(chip);
727+
return ret;
671728
}
672729
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);
673730

0 commit comments

Comments
 (0)