Skip to content

Commit 6e9722e

Browse files
committed
tpm2-sessions: Fix out of range indexing in name_size
'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>
1 parent 2061f18 commit 6e9722e

4 files changed

Lines changed: 142 additions & 55 deletions

File tree

drivers/char/tpm/tpm2-cmd.c

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

201201
if (!disable_pcr_integrity) {
202-
tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
202+
rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
203+
if (rc) {
204+
tpm_buf_destroy(&buf);
205+
return rc;
206+
}
203207
tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
204208
} else {
205209
tpm_buf_append_handle(chip, &buf, pcr_idx);
@@ -214,8 +218,14 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
214218
chip->allocated_banks[i].digest_size);
215219
}
216220

217-
if (!disable_pcr_integrity)
218-
tpm_buf_fill_hmac_session(chip, &buf);
221+
if (!disable_pcr_integrity) {
222+
rc = tpm_buf_fill_hmac_session(chip, &buf);
223+
if (rc) {
224+
tpm_buf_destroy(&buf);
225+
return rc;
226+
}
227+
}
228+
219229
rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
220230
if (!disable_pcr_integrity)
221231
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
@@ -273,7 +283,12 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
273283
| TPM2_SA_CONTINUE_SESSION,
274284
NULL, 0);
275285
tpm_buf_append_u16(&buf, num_bytes);
276-
tpm_buf_fill_hmac_session(chip, &buf);
286+
err = tpm_buf_fill_hmac_session(chip, &buf);
287+
if (err) {
288+
tpm_buf_destroy(&buf);
289+
return err;
290+
}
291+
277292
err = tpm_transmit_cmd(chip, &buf,
278293
offsetof(struct tpm2_get_random_out,
279294
buffer),

drivers/char/tpm/tpm2-sessions.c

Lines changed: 92 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -144,23 +144,31 @@ 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_parse_read_public(char *name, struct tpm_buf *buf)
160167
{
161168
struct tpm_header *head = (struct tpm_header *)buf->data;
162169
off_t offset = TPM_HEADER_SIZE;
163170
u32 tot_len = be32_to_cpu(head->length);
171+
int ret;
164172
u32 val;
165173

166174
/* we're starting after the header so adjust the length */
@@ -173,8 +181,13 @@ static int tpm2_parse_read_public(char *name, struct tpm_buf *buf)
173181
offset += val;
174182
/* name */
175183
val = tpm_buf_read_u16(buf, &offset);
176-
if (val != name_size(&buf->data[offset]))
184+
ret = name_size(&buf->data[offset]);
185+
if (ret < 0)
186+
return ret;
187+
188+
if (val != ret)
177189
return -EINVAL;
190+
178191
memcpy(name, &buf->data[offset], val);
179192
/* forget the rest */
180193
return 0;
@@ -221,46 +234,72 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
221234
* As with most tpm_buf operations, success is assumed because failure
222235
* will be caused by an incorrect programming model and indicated by a
223236
* kernel message.
237+
*
238+
* Ends the authorization session on failure.
224239
*/
225-
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
226-
u32 handle, u8 *name)
240+
int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
241+
u32 handle, u8 *name)
227242
{
228243
#ifdef CONFIG_TCG_TPM2_HMAC
229244
enum tpm2_mso_type mso = tpm2_handle_mso(handle);
230245
struct tpm2_auth *auth;
231246
int slot;
247+
int ret;
232248
#endif
233249

234250
if (!tpm2_chip_auth(chip)) {
235251
tpm_buf_append_handle(chip, buf, handle);
236-
return;
252+
return 0;
237253
}
238254

239255
#ifdef CONFIG_TCG_TPM2_HMAC
240256
slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
241257
if (slot >= AUTH_MAX_NAMES) {
242-
dev_err(&chip->dev, "TPM: too many handles\n");
243-
return;
258+
dev_err(&chip->dev, "too many handles\n");
259+
ret = -EIO;
260+
goto err;
244261
}
245262
auth = chip->auth;
246-
WARN(auth->session != tpm_buf_length(buf),
247-
"name added in wrong place\n");
263+
if (auth->session != tpm_buf_length(buf)) {
264+
dev_err(&chip->dev, "session state malformed");
265+
ret = -EIO;
266+
goto err;
267+
}
248268
tpm_buf_append_u32(buf, handle);
249269
auth->session += 4;
250270

251271
if (mso == TPM2_MSO_PERSISTENT ||
252272
mso == TPM2_MSO_VOLATILE ||
253273
mso == TPM2_MSO_NVRAM) {
254-
if (!name)
255-
tpm2_read_public(chip, handle, auth->name[slot]);
274+
if (!name) {
275+
ret = tpm2_read_public(chip, handle, auth->name[slot]);
276+
if (ret)
277+
goto err;
278+
}
256279
} else {
257-
if (name)
258-
dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
280+
if (name) {
281+
dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
282+
handle);
283+
ret = -EIO;
284+
goto err;
285+
}
259286
}
260287

261288
auth->name_h[slot] = handle;
262-
if (name)
263-
memcpy(auth->name[slot], name, name_size(name));
289+
if (name) {
290+
ret = name_size(name);
291+
if (ret < 0)
292+
goto err;
293+
294+
memcpy(auth->name[slot], name, ret);
295+
}
296+
#endif
297+
return 0;
298+
299+
#ifdef CONFIG_TCG_TPM2_HMAC
300+
err:
301+
tpm2_end_auth_session(chip);
302+
return tpm_ret_to_err(ret);
264303
#endif
265304
}
266305
EXPORT_SYMBOL_GPL(tpm_buf_append_name);
@@ -533,11 +572,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
533572
* encryption key and encrypts the first parameter of the command
534573
* buffer with it.
535574
*
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.
575+
* Ends the authorization session on failure.
539576
*/
540-
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
577+
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
541578
{
542579
u32 cc, handles, val;
543580
struct tpm2_auth *auth = chip->auth;
@@ -549,9 +586,12 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
549586
u8 cphash[SHA256_DIGEST_SIZE];
550587
struct sha256_ctx sctx;
551588
struct hmac_sha256_ctx hctx;
589+
int ret;
552590

553-
if (!auth)
554-
return;
591+
if (!auth) {
592+
ret = -EIO;
593+
goto err;
594+
}
555595

556596
/* save the command code in BE format */
557597
auth->ordinal = head->ordinal;
@@ -560,9 +600,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
560600

561601
i = tpm2_find_cc(chip, cc);
562602
if (i < 0) {
563-
dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc);
564-
return;
603+
dev_err(&chip->dev, "command 0x%08x not found\n", cc);
604+
ret = -EIO;
605+
goto err;
565606
}
607+
566608
attrs = chip->cc_attrs_tbl[i];
567609

568610
handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
@@ -576,9 +618,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
576618
u32 handle = tpm_buf_read_u32(buf, &offset_s);
577619

578620
if (auth->name_h[i] != handle) {
579-
dev_err(&chip->dev, "TPM: handle %d wrong for name\n",
580-
i);
581-
return;
621+
dev_err(&chip->dev, "invalid handle 0x%08x\n", handle);
622+
ret = -EIO;
623+
goto err;
582624
}
583625
}
584626
/* point offset_s to the start of the sessions */
@@ -609,12 +651,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
609651
offset_s += len;
610652
}
611653
if (offset_s != offset_p) {
612-
dev_err(&chip->dev, "TPM session length is incorrect\n");
613-
return;
654+
dev_err(&chip->dev, "session length is incorrect\n");
655+
ret = -EIO;
656+
goto err;
614657
}
615658
if (!hmac) {
616-
dev_err(&chip->dev, "TPM could not find HMAC session\n");
617-
return;
659+
dev_err(&chip->dev, "could not find HMAC session\n");
660+
ret = -EIO;
661+
goto err;
618662
}
619663

620664
/* encrypt before HMAC */
@@ -646,8 +690,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
646690
if (mso == TPM2_MSO_PERSISTENT ||
647691
mso == TPM2_MSO_VOLATILE ||
648692
mso == TPM2_MSO_NVRAM) {
649-
sha256_update(&sctx, auth->name[i],
650-
name_size(auth->name[i]));
693+
ret = name_size(auth->name[i]);
694+
if (ret < 0)
695+
goto err;
696+
697+
sha256_update(&sctx, auth->name[i], ret);
651698
} else {
652699
__be32 h = cpu_to_be32(auth->name_h[i]);
653700

@@ -668,6 +715,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
668715
hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
669716
hmac_sha256_update(&hctx, &auth->attrs, 1);
670717
hmac_sha256_final(&hctx, hmac);
718+
return 0;
719+
720+
err:
721+
tpm2_end_auth_session(chip);
722+
return ret;
671723
}
672724
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);
673725

include/linux/tpm.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,8 @@ static inline struct tpm2_auth *tpm2_chip_auth(struct tpm_chip *chip)
529529
#endif
530530
}
531531

532-
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
533-
u32 handle, u8 *name);
532+
int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
533+
u32 handle, u8 *name);
534534
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
535535
u8 attributes, u8 *passphrase,
536536
int passphraselen);
@@ -563,7 +563,7 @@ static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
563563
#ifdef CONFIG_TCG_TPM2_HMAC
564564

565565
int tpm2_start_auth_session(struct tpm_chip *chip);
566-
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
566+
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
567567
int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
568568
int rc);
569569
void tpm2_end_auth_session(struct tpm_chip *chip);
@@ -577,10 +577,13 @@ static inline int tpm2_start_auth_session(struct tpm_chip *chip)
577577
static inline void tpm2_end_auth_session(struct tpm_chip *chip)
578578
{
579579
}
580-
static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip,
581-
struct tpm_buf *buf)
580+
581+
static inline int tpm_buf_fill_hmac_session(struct tpm_chip *chip,
582+
struct tpm_buf *buf)
582583
{
584+
return 0;
583585
}
586+
584587
static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip,
585588
struct tpm_buf *buf,
586589
int rc)

security/keys/trusted-keys/trusted_tpm2.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
268268
goto out_put;
269269
}
270270

271-
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
271+
rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
272+
if (rc)
273+
goto out;
274+
272275
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
273276
options->keyauth, TPM_DIGEST_SIZE);
274277

@@ -316,7 +319,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
316319
goto out;
317320
}
318321

319-
tpm_buf_fill_hmac_session(chip, &buf);
322+
rc = tpm_buf_fill_hmac_session(chip, &buf);
323+
if (rc)
324+
goto out;
325+
320326
rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
321327
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
322328
if (rc)
@@ -427,7 +433,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
427433
return rc;
428434
}
429435

430-
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
436+
rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
437+
if (rc)
438+
goto out;
439+
431440
tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
432441
TPM_DIGEST_SIZE);
433442

@@ -439,7 +448,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
439448
goto out;
440449
}
441450

442-
tpm_buf_fill_hmac_session(chip, &buf);
451+
rc = tpm_buf_fill_hmac_session(chip, &buf);
452+
if (rc)
453+
goto out;
454+
443455
rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
444456
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
445457
if (!rc)
@@ -484,7 +496,9 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
484496
return rc;
485497
}
486498

487-
tpm_buf_append_name(chip, &buf, blob_handle, NULL);
499+
rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
500+
if (rc)
501+
goto out;
488502

489503
if (!options->policyhandle) {
490504
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
@@ -509,7 +523,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
509523
NULL, 0);
510524
}
511525

512-
tpm_buf_fill_hmac_session(chip, &buf);
526+
rc = tpm_buf_fill_hmac_session(chip, &buf);
527+
if (rc)
528+
goto out;
529+
513530
rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
514531
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
515532

0 commit comments

Comments
 (0)