Skip to content

Commit 47e676c

Browse files
jarkkojsgregkh
authored andcommitted
tpm2-sessions: Fix out of range indexing in name_size
commit 6e9722e upstream. 'name_size' does not have any range checks, and it just directly indexes with TPM_ALG_ID, which could lead into memory corruption at worst. Address the issue by only processing known values and returning -EINVAL for unrecognized values. Make also 'tpm_buf_append_name' and 'tpm_buf_fill_hmac_session' fallible so that errors are detected before causing any spurious TPM traffic. End also the authorization session on failure in both of the functions, as the session state would be then by definition corrupted. Cc: stable@vger.kernel.org # v6.10+ Fixes: 1085b82 ("tpm: Add the rest of the session HMAC API") Reviewed-by: Jonathan McDowell <noodles@meta.com> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4244015 commit 47e676c

4 files changed

Lines changed: 126 additions & 53 deletions

File tree

drivers/char/tpm/tpm2-cmd.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,11 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
253253
}
254254

255255
if (!disable_pcr_integrity) {
256-
tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
256+
rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
257+
if (rc) {
258+
tpm_buf_destroy(&buf);
259+
return rc;
260+
}
257261
tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
258262
} else {
259263
tpm_buf_append_handle(chip, &buf, pcr_idx);
@@ -268,8 +272,14 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
268272
chip->allocated_banks[i].digest_size);
269273
}
270274

271-
if (!disable_pcr_integrity)
272-
tpm_buf_fill_hmac_session(chip, &buf);
275+
if (!disable_pcr_integrity) {
276+
rc = tpm_buf_fill_hmac_session(chip, &buf);
277+
if (rc) {
278+
tpm_buf_destroy(&buf);
279+
return rc;
280+
}
281+
}
282+
273283
rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
274284
if (!disable_pcr_integrity)
275285
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
@@ -327,7 +337,12 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
327337
| TPM2_SA_CONTINUE_SESSION,
328338
NULL, 0);
329339
tpm_buf_append_u16(&buf, num_bytes);
330-
tpm_buf_fill_hmac_session(chip, &buf);
340+
err = tpm_buf_fill_hmac_session(chip, &buf);
341+
if (err) {
342+
tpm_buf_destroy(&buf);
343+
return err;
344+
}
345+
331346
err = tpm_transmit_cmd(chip, &buf,
332347
offsetof(struct tpm2_get_random_out,
333348
buffer),

drivers/char/tpm/tpm2-sessions.c

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,23 @@ 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;
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);
162+
return -EINVAL;
163+
}
157164
}
158165

159166
static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
@@ -234,9 +241,11 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
234241
* As with most tpm_buf operations, success is assumed because failure
235242
* will be caused by an incorrect programming model and indicated by a
236243
* kernel message.
244+
*
245+
* Ends the authorization session on failure.
237246
*/
238-
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
239-
u32 handle, u8 *name)
247+
int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
248+
u32 handle, u8 *name)
240249
{
241250
#ifdef CONFIG_TCG_TPM2_HMAC
242251
enum tpm2_mso_type mso = tpm2_handle_mso(handle);
@@ -247,18 +256,22 @@ void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
247256

248257
if (!tpm2_chip_auth(chip)) {
249258
tpm_buf_append_handle(chip, buf, handle);
250-
return;
259+
return 0;
251260
}
252261

253262
#ifdef CONFIG_TCG_TPM2_HMAC
254263
slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
255264
if (slot >= AUTH_MAX_NAMES) {
256-
dev_err(&chip->dev, "TPM: too many handles\n");
257-
return;
265+
dev_err(&chip->dev, "too many handles\n");
266+
ret = -EIO;
267+
goto err;
258268
}
259269
auth = chip->auth;
260-
WARN(auth->session != tpm_buf_length(buf),
261-
"name added in wrong place\n");
270+
if (auth->session != tpm_buf_length(buf)) {
271+
dev_err(&chip->dev, "session state malformed");
272+
ret = -EIO;
273+
goto err;
274+
}
262275
tpm_buf_append_u32(buf, handle);
263276
auth->session += 4;
264277

@@ -271,17 +284,29 @@ void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
271284
goto err;
272285
}
273286
} else {
274-
if (name)
275-
dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
287+
if (name) {
288+
dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
289+
handle);
290+
ret = -EIO;
291+
goto err;
292+
}
276293
}
277294

278295
auth->name_h[slot] = handle;
279-
if (name)
280-
memcpy(auth->name[slot], name, name_size(name));
281-
return;
296+
if (name) {
297+
ret = name_size(name);
298+
if (ret < 0)
299+
goto err;
300+
301+
memcpy(auth->name[slot], name, ret);
302+
}
303+
#endif
304+
return 0;
282305

306+
#ifdef CONFIG_TCG_TPM2_HMAC
283307
err:
284308
tpm2_end_auth_session(chip);
309+
return tpm_ret_to_err(ret);
285310
#endif
286311
}
287312
EXPORT_SYMBOL_GPL(tpm_buf_append_name);
@@ -599,11 +624,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
599624
* encryption key and encrypts the first parameter of the command
600625
* buffer with it.
601626
*
602-
* As with most tpm_buf operations, success is assumed because failure
603-
* will be caused by an incorrect programming model and indicated by a
604-
* kernel message.
627+
* Ends the authorization session on failure.
605628
*/
606-
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
629+
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
607630
{
608631
u32 cc, handles, val;
609632
struct tpm2_auth *auth = chip->auth;
@@ -614,9 +637,12 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
614637
u32 attrs;
615638
u8 cphash[SHA256_DIGEST_SIZE];
616639
struct sha256_state sctx;
640+
int ret;
617641

618-
if (!auth)
619-
return;
642+
if (!auth) {
643+
ret = -EIO;
644+
goto err;
645+
}
620646

621647
/* save the command code in BE format */
622648
auth->ordinal = head->ordinal;
@@ -625,9 +651,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
625651

626652
i = tpm2_find_cc(chip, cc);
627653
if (i < 0) {
628-
dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc);
629-
return;
654+
dev_err(&chip->dev, "command 0x%08x not found\n", cc);
655+
ret = -EIO;
656+
goto err;
630657
}
658+
631659
attrs = chip->cc_attrs_tbl[i];
632660

633661
handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
@@ -641,9 +669,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
641669
u32 handle = tpm_buf_read_u32(buf, &offset_s);
642670

643671
if (auth->name_h[i] != handle) {
644-
dev_err(&chip->dev, "TPM: handle %d wrong for name\n",
645-
i);
646-
return;
672+
dev_err(&chip->dev, "invalid handle 0x%08x\n", handle);
673+
ret = -EIO;
674+
goto err;
647675
}
648676
}
649677
/* point offset_s to the start of the sessions */
@@ -674,12 +702,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
674702
offset_s += len;
675703
}
676704
if (offset_s != offset_p) {
677-
dev_err(&chip->dev, "TPM session length is incorrect\n");
678-
return;
705+
dev_err(&chip->dev, "session length is incorrect\n");
706+
ret = -EIO;
707+
goto err;
679708
}
680709
if (!hmac) {
681-
dev_err(&chip->dev, "TPM could not find HMAC session\n");
682-
return;
710+
dev_err(&chip->dev, "could not find HMAC session\n");
711+
ret = -EIO;
712+
goto err;
683713
}
684714

685715
/* encrypt before HMAC */
@@ -711,8 +741,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
711741
if (mso == TPM2_MSO_PERSISTENT ||
712742
mso == TPM2_MSO_VOLATILE ||
713743
mso == TPM2_MSO_NVRAM) {
714-
sha256_update(&sctx, auth->name[i],
715-
name_size(auth->name[i]));
744+
ret = name_size(auth->name[i]);
745+
if (ret < 0)
746+
goto err;
747+
748+
sha256_update(&sctx, auth->name[i], ret);
716749
} else {
717750
__be32 h = cpu_to_be32(auth->name_h[i]);
718751

@@ -733,6 +766,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
733766
sha256_update(&sctx, &auth->attrs, 1);
734767
tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key)
735768
+ auth->passphrase_len, hmac);
769+
return 0;
770+
771+
err:
772+
tpm2_end_auth_session(chip);
773+
return ret;
736774
}
737775
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);
738776

include/linux/tpm.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,8 @@ static inline struct tpm2_auth *tpm2_chip_auth(struct tpm_chip *chip)
523523
#endif
524524
}
525525

526-
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
527-
u32 handle, u8 *name);
526+
int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
527+
u32 handle, u8 *name);
528528
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
529529
u8 attributes, u8 *passphrase,
530530
int passphraselen);
@@ -557,7 +557,7 @@ static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
557557
#ifdef CONFIG_TCG_TPM2_HMAC
558558

559559
int tpm2_start_auth_session(struct tpm_chip *chip);
560-
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
560+
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
561561
int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
562562
int rc);
563563
void tpm2_end_auth_session(struct tpm_chip *chip);
@@ -571,10 +571,13 @@ static inline int tpm2_start_auth_session(struct tpm_chip *chip)
571571
static inline void tpm2_end_auth_session(struct tpm_chip *chip)
572572
{
573573
}
574-
static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip,
575-
struct tpm_buf *buf)
574+
575+
static inline int tpm_buf_fill_hmac_session(struct tpm_chip *chip,
576+
struct tpm_buf *buf)
576577
{
578+
return 0;
577579
}
580+
578581
static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip,
579582
struct tpm_buf *buf,
580583
int rc)

security/keys/trusted-keys/trusted_tpm2.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
283283
goto out_put;
284284
}
285285

286-
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
286+
rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
287+
if (rc)
288+
goto out;
289+
287290
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
288291
options->keyauth, TPM_DIGEST_SIZE);
289292

@@ -331,7 +334,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
331334
goto out;
332335
}
333336

334-
tpm_buf_fill_hmac_session(chip, &buf);
337+
rc = tpm_buf_fill_hmac_session(chip, &buf);
338+
if (rc)
339+
goto out;
340+
335341
rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
336342
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
337343
if (rc)
@@ -448,7 +454,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
448454
return rc;
449455
}
450456

451-
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
457+
rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
458+
if (rc)
459+
goto out;
460+
452461
tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
453462
TPM_DIGEST_SIZE);
454463

@@ -460,7 +469,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
460469
goto out;
461470
}
462471

463-
tpm_buf_fill_hmac_session(chip, &buf);
472+
rc = tpm_buf_fill_hmac_session(chip, &buf);
473+
if (rc)
474+
goto out;
475+
464476
rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
465477
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
466478
if (!rc)
@@ -508,7 +520,9 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
508520
return rc;
509521
}
510522

511-
tpm_buf_append_name(chip, &buf, blob_handle, NULL);
523+
rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
524+
if (rc)
525+
goto out;
512526

513527
if (!options->policyhandle) {
514528
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
@@ -533,7 +547,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
533547
NULL, 0);
534548
}
535549

536-
tpm_buf_fill_hmac_session(chip, &buf);
550+
rc = tpm_buf_fill_hmac_session(chip, &buf);
551+
if (rc)
552+
goto out;
553+
537554
rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
538555
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
539556
if (rc > 0)

0 commit comments

Comments
 (0)