Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tpm: add session encryption protection to tpm2_get_random()

If some entity is snooping the TPM bus, they can see the random
numbers we're extracting from the TPM and do prediction attacks
against their consumers. Foil this attack by using response
encryption to prevent the attacker from seeing the random sequence.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

authored by

James Bottomley and committed by
Jarkko Sakkinen
1b6d7f9e 6519fea6

+17 -4
+17 -4
drivers/char/tpm/tpm2-cmd.c
··· 292 292 if (!num_bytes || max > TPM_MAX_RNG_DATA) 293 293 return -EINVAL; 294 294 295 - err = tpm_buf_init(&buf, 0, 0); 295 + err = tpm2_start_auth_session(chip); 296 296 if (err) 297 297 return err; 298 298 299 + err = tpm_buf_init(&buf, 0, 0); 300 + if (err) { 301 + tpm2_end_auth_session(chip); 302 + return err; 303 + } 304 + 299 305 do { 300 - tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM); 306 + tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); 307 + tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT 308 + | TPM2_SA_CONTINUE_SESSION, 309 + NULL, 0); 301 310 tpm_buf_append_u16(&buf, num_bytes); 311 + tpm_buf_fill_hmac_session(chip, &buf); 302 312 err = tpm_transmit_cmd(chip, &buf, 303 313 offsetof(struct tpm2_get_random_out, 304 314 buffer), 305 315 "attempting get random"); 316 + err = tpm_buf_check_hmac_response(chip, &buf, err); 306 317 if (err) { 307 318 if (err > 0) 308 319 err = -EIO; 309 320 goto out; 310 321 } 311 322 312 - out = (struct tpm2_get_random_out *) 313 - &buf.data[TPM_HEADER_SIZE]; 323 + out = (struct tpm2_get_random_out *)tpm_buf_parameters(&buf); 314 324 recd = min_t(u32, be16_to_cpu(out->size), num_bytes); 315 325 if (tpm_buf_length(&buf) < 316 326 TPM_HEADER_SIZE + ··· 337 327 } while (retries-- && total < max); 338 328 339 329 tpm_buf_destroy(&buf); 330 + tpm2_end_auth_session(chip); 331 + 340 332 return total ? total : -EIO; 341 333 out: 342 334 tpm_buf_destroy(&buf); 335 + tpm2_end_auth_session(chip); 343 336 return err; 344 337 } 345 338