Skip to content

Commit 7ca110f

Browse files
committed
tpm: Address !chip->auth in tpm_buf_append_hmac_session*()
Unless tpm_chip_bootstrap() was called by the driver, !chip->auth can cause a null derefence in tpm_buf_hmac_session*(). Thus, address !chip->auth in tpm_buf_hmac_session*() and remove the fallback implementation for !TCG_TPM2_HMAC. Cc: [email protected] # v6.9+ Reported-by: Stefan Berger <[email protected]> Closes: https://lore.kernel.org/linux-integrity/[email protected]/ Fixes: 1085b82 ("tpm: Add the rest of the session HMAC API") Tested-by: Michael Ellerman <[email protected]> # ppc Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent a61809a commit 7ca110f

File tree

2 files changed

+130
-124
lines changed

2 files changed

+130
-124
lines changed

drivers/char/tpm/tpm2-sessions.c

Lines changed: 110 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,110 @@ void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
272272
}
273273
EXPORT_SYMBOL_GPL(tpm_buf_append_name);
274274

275+
/**
276+
* tpm_buf_append_hmac_session() - Append a TPM session element
277+
* @chip: the TPM chip structure
278+
* @buf: The buffer to be appended
279+
* @attributes: The session attributes
280+
* @passphrase: The session authority (NULL if none)
281+
* @passphrase_len: The length of the session authority (0 if none)
282+
*
283+
* This fills in a session structure in the TPM command buffer, except
284+
* for the HMAC which cannot be computed until the command buffer is
285+
* complete. The type of session is controlled by the @attributes,
286+
* the main ones of which are TPM2_SA_CONTINUE_SESSION which means the
287+
* session won't terminate after tpm_buf_check_hmac_response(),
288+
* TPM2_SA_DECRYPT which means this buffers first parameter should be
289+
* encrypted with a session key and TPM2_SA_ENCRYPT, which means the
290+
* response buffer's first parameter needs to be decrypted (confusing,
291+
* but the defines are written from the point of view of the TPM).
292+
*
293+
* Any session appended by this command must be finalized by calling
294+
* tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect
295+
* and the TPM will reject the command.
296+
*
297+
* As with most tpm_buf operations, success is assumed because failure
298+
* will be caused by an incorrect programming model and indicated by a
299+
* kernel message.
300+
*/
301+
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
302+
u8 attributes, u8 *passphrase,
303+
int passphrase_len)
304+
{
305+
#ifdef CONFIG_TCG_TPM2_HMAC
306+
u8 nonce[SHA256_DIGEST_SIZE];
307+
struct tpm2_auth *auth;
308+
u32 len;
309+
#endif
310+
311+
if (!tpm2_chip_auth(chip)) {
312+
/* offset tells us where the sessions area begins */
313+
int offset = buf->handles * 4 + TPM_HEADER_SIZE;
314+
u32 len = 9 + passphrase_len;
315+
316+
if (tpm_buf_length(buf) != offset) {
317+
/* not the first session so update the existing length */
318+
len += get_unaligned_be32(&buf->data[offset]);
319+
put_unaligned_be32(len, &buf->data[offset]);
320+
} else {
321+
tpm_buf_append_u32(buf, len);
322+
}
323+
/* auth handle */
324+
tpm_buf_append_u32(buf, TPM2_RS_PW);
325+
/* nonce */
326+
tpm_buf_append_u16(buf, 0);
327+
/* attributes */
328+
tpm_buf_append_u8(buf, 0);
329+
/* passphrase */
330+
tpm_buf_append_u16(buf, passphrase_len);
331+
tpm_buf_append(buf, passphrase, passphrase_len);
332+
return;
333+
}
334+
335+
#ifdef CONFIG_TCG_TPM2_HMAC
336+
/*
337+
* The Architecture Guide requires us to strip trailing zeros
338+
* before computing the HMAC
339+
*/
340+
while (passphrase && passphrase_len > 0 && passphrase[passphrase_len - 1] == '\0')
341+
passphrase_len--;
342+
343+
auth = chip->auth;
344+
auth->attrs = attributes;
345+
auth->passphrase_len = passphrase_len;
346+
if (passphrase_len)
347+
memcpy(auth->passphrase, passphrase, passphrase_len);
348+
349+
if (auth->session != tpm_buf_length(buf)) {
350+
/* we're not the first session */
351+
len = get_unaligned_be32(&buf->data[auth->session]);
352+
if (4 + len + auth->session != tpm_buf_length(buf)) {
353+
WARN(1, "session length mismatch, cannot append");
354+
return;
355+
}
356+
357+
/* add our new session */
358+
len += 9 + 2 * SHA256_DIGEST_SIZE;
359+
put_unaligned_be32(len, &buf->data[auth->session]);
360+
} else {
361+
tpm_buf_append_u32(buf, 9 + 2 * SHA256_DIGEST_SIZE);
362+
}
363+
364+
/* random number for our nonce */
365+
get_random_bytes(nonce, sizeof(nonce));
366+
memcpy(auth->our_nonce, nonce, sizeof(nonce));
367+
tpm_buf_append_u32(buf, auth->handle);
368+
/* our new nonce */
369+
tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
370+
tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
371+
tpm_buf_append_u8(buf, auth->attrs);
372+
/* and put a placeholder for the hmac */
373+
tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
374+
tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
375+
#endif
376+
}
377+
EXPORT_SYMBOL_GPL(tpm_buf_append_hmac_session);
378+
275379
#ifdef CONFIG_TCG_TPM2_HMAC
276380

277381
static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
@@ -457,82 +561,6 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
457561
crypto_free_kpp(kpp);
458562
}
459563

460-
/**
461-
* tpm_buf_append_hmac_session() - Append a TPM session element
462-
* @chip: the TPM chip structure
463-
* @buf: The buffer to be appended
464-
* @attributes: The session attributes
465-
* @passphrase: The session authority (NULL if none)
466-
* @passphrase_len: The length of the session authority (0 if none)
467-
*
468-
* This fills in a session structure in the TPM command buffer, except
469-
* for the HMAC which cannot be computed until the command buffer is
470-
* complete. The type of session is controlled by the @attributes,
471-
* the main ones of which are TPM2_SA_CONTINUE_SESSION which means the
472-
* session won't terminate after tpm_buf_check_hmac_response(),
473-
* TPM2_SA_DECRYPT which means this buffers first parameter should be
474-
* encrypted with a session key and TPM2_SA_ENCRYPT, which means the
475-
* response buffer's first parameter needs to be decrypted (confusing,
476-
* but the defines are written from the point of view of the TPM).
477-
*
478-
* Any session appended by this command must be finalized by calling
479-
* tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect
480-
* and the TPM will reject the command.
481-
*
482-
* As with most tpm_buf operations, success is assumed because failure
483-
* will be caused by an incorrect programming model and indicated by a
484-
* kernel message.
485-
*/
486-
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
487-
u8 attributes, u8 *passphrase,
488-
int passphrase_len)
489-
{
490-
u8 nonce[SHA256_DIGEST_SIZE];
491-
u32 len;
492-
struct tpm2_auth *auth = chip->auth;
493-
494-
/*
495-
* The Architecture Guide requires us to strip trailing zeros
496-
* before computing the HMAC
497-
*/
498-
while (passphrase && passphrase_len > 0
499-
&& passphrase[passphrase_len - 1] == '\0')
500-
passphrase_len--;
501-
502-
auth->attrs = attributes;
503-
auth->passphrase_len = passphrase_len;
504-
if (passphrase_len)
505-
memcpy(auth->passphrase, passphrase, passphrase_len);
506-
507-
if (auth->session != tpm_buf_length(buf)) {
508-
/* we're not the first session */
509-
len = get_unaligned_be32(&buf->data[auth->session]);
510-
if (4 + len + auth->session != tpm_buf_length(buf)) {
511-
WARN(1, "session length mismatch, cannot append");
512-
return;
513-
}
514-
515-
/* add our new session */
516-
len += 9 + 2 * SHA256_DIGEST_SIZE;
517-
put_unaligned_be32(len, &buf->data[auth->session]);
518-
} else {
519-
tpm_buf_append_u32(buf, 9 + 2 * SHA256_DIGEST_SIZE);
520-
}
521-
522-
/* random number for our nonce */
523-
get_random_bytes(nonce, sizeof(nonce));
524-
memcpy(auth->our_nonce, nonce, sizeof(nonce));
525-
tpm_buf_append_u32(buf, auth->handle);
526-
/* our new nonce */
527-
tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
528-
tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
529-
tpm_buf_append_u8(buf, auth->attrs);
530-
/* and put a placeholder for the hmac */
531-
tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
532-
tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
533-
}
534-
EXPORT_SYMBOL(tpm_buf_append_hmac_session);
535-
536564
/**
537565
* tpm_buf_fill_hmac_session() - finalize the session HMAC
538566
* @chip: the TPM chip structure
@@ -563,6 +591,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
563591
u8 cphash[SHA256_DIGEST_SIZE];
564592
struct sha256_state sctx;
565593

594+
if (!auth)
595+
return;
596+
566597
/* save the command code in BE format */
567598
auth->ordinal = head->ordinal;
568599

@@ -721,6 +752,9 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
721752
u32 cc = be32_to_cpu(auth->ordinal);
722753
int parm_len, len, i, handles;
723754

755+
if (!auth)
756+
return rc;
757+
724758
if (auth->session >= TPM_HEADER_SIZE) {
725759
WARN(1, "tpm session not filled correctly\n");
726760
goto out;

include/linux/tpm.h

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -502,10 +502,6 @@ static inline struct tpm2_auth *tpm2_chip_auth(struct tpm_chip *chip)
502502

503503
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
504504
u32 handle, u8 *name);
505-
506-
#ifdef CONFIG_TCG_TPM2_HMAC
507-
508-
int tpm2_start_auth_session(struct tpm_chip *chip);
509505
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
510506
u8 attributes, u8 *passphrase,
511507
int passphraselen);
@@ -515,9 +511,27 @@ static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
515511
u8 *passphrase,
516512
int passphraselen)
517513
{
518-
tpm_buf_append_hmac_session(chip, buf, attributes, passphrase,
519-
passphraselen);
514+
struct tpm_header *head;
515+
int offset;
516+
517+
if (tpm2_chip_auth(chip)) {
518+
tpm_buf_append_hmac_session(chip, buf, attributes, passphrase, passphraselen);
519+
} else {
520+
offset = buf->handles * 4 + TPM_HEADER_SIZE;
521+
head = (struct tpm_header *)buf->data;
522+
523+
/*
524+
* If the only sessions are optional, the command tag must change to
525+
* TPM2_ST_NO_SESSIONS.
526+
*/
527+
if (tpm_buf_length(buf) == offset)
528+
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
529+
}
520530
}
531+
532+
#ifdef CONFIG_TCG_TPM2_HMAC
533+
534+
int tpm2_start_auth_session(struct tpm_chip *chip);
521535
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
522536
int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
523537
int rc);
@@ -532,48 +546,6 @@ static inline int tpm2_start_auth_session(struct tpm_chip *chip)
532546
static inline void tpm2_end_auth_session(struct tpm_chip *chip)
533547
{
534548
}
535-
static inline void tpm_buf_append_hmac_session(struct tpm_chip *chip,
536-
struct tpm_buf *buf,
537-
u8 attributes, u8 *passphrase,
538-
int passphraselen)
539-
{
540-
/* offset tells us where the sessions area begins */
541-
int offset = buf->handles * 4 + TPM_HEADER_SIZE;
542-
u32 len = 9 + passphraselen;
543-
544-
if (tpm_buf_length(buf) != offset) {
545-
/* not the first session so update the existing length */
546-
len += get_unaligned_be32(&buf->data[offset]);
547-
put_unaligned_be32(len, &buf->data[offset]);
548-
} else {
549-
tpm_buf_append_u32(buf, len);
550-
}
551-
/* auth handle */
552-
tpm_buf_append_u32(buf, TPM2_RS_PW);
553-
/* nonce */
554-
tpm_buf_append_u16(buf, 0);
555-
/* attributes */
556-
tpm_buf_append_u8(buf, 0);
557-
/* passphrase */
558-
tpm_buf_append_u16(buf, passphraselen);
559-
tpm_buf_append(buf, passphrase, passphraselen);
560-
}
561-
static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
562-
struct tpm_buf *buf,
563-
u8 attributes,
564-
u8 *passphrase,
565-
int passphraselen)
566-
{
567-
int offset = buf->handles * 4 + TPM_HEADER_SIZE;
568-
struct tpm_header *head = (struct tpm_header *) buf->data;
569-
570-
/*
571-
* if the only sessions are optional, the command tag
572-
* must change to TPM2_ST_NO_SESSIONS
573-
*/
574-
if (tpm_buf_length(buf) == offset)
575-
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
576-
}
577549
static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip,
578550
struct tpm_buf *buf)
579551
{

0 commit comments

Comments
 (0)