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

tpm: Add the rest of the session HMAC API

The final pieces of the HMAC API are for manipulating the session area
of the command. To add an authentication HMAC session
tpm_buf_append_hmac_session() is called where tpm2_append_auth() would
go. If a non empty password is passed in, this is correctly added to
the HMAC to prove knowledge of it without revealing it. Note that if
the session is only used to encrypt or decrypt parameters (no
authentication) then tpm_buf_append_hmac_session_opt() must be used
instead. This functions identically to tpm_buf_append_hmac_session()
when TPM_BUS_SECURITY is enabled, but differently when it isn't,
because effectively nothing is appended to the session area.

Next the parameters should be filled in for the command and finally
tpm_buf_fill_hmac_session() is called immediately prior to transmitting
the command which computes the correct HMAC and places it in the
command at the session location in the tpm buffer

Finally, after tpm_transmit_cmd() is called,
tpm_buf_check_hmac_response() is called to check that the returned
HMAC matched and collect the new state for the next use of the
session, if any.

The features of the session are controlled by the session attributes
set in tpm_buf_append_hmac_session(). If TPM2_SA_CONTINUE_SESSION is
not specified, the session will be flushed and the tpm2_auth structure
freed in tpm_buf_check_hmac_response(); otherwise the session may be
used again. Parameter encryption is specified by or'ing the flag
TPM2_SA_DECRYPT and response encryption by or'ing the flag
TPM2_SA_ENCRYPT. the various encryptions will be taken care of by
tpm_buf_fill_hmac_session() and tpm_buf_check_hmac_response()
respectively.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> # crypto API parts
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
1085b827 d0a25bb9

+469
+400
drivers/char/tpm/tpm2-sessions.c
··· 54 54 * handles because handles have to be processed specially when 55 55 * calculating the HMAC. In particular, for NV, volatile and 56 56 * permanent objects you now need to provide the name. 57 + * tpm_buf_append_hmac_session() which appends the hmac session to the 58 + * buf in the same way tpm_buf_append_auth does(). 59 + * tpm_buf_fill_hmac_session() This calculates the correct hash and 60 + * places it in the buffer. It must be called after the complete 61 + * command buffer is finalized so it can fill in the correct HMAC 62 + * based on the parameters. 63 + * tpm_buf_check_hmac_response() which checks the session response in 64 + * the buffer and calculates what it should be. If there's a 65 + * mismatch it will log a warning and return an error. If 66 + * tpm_buf_append_hmac_session() did not specify 67 + * TPM_SA_CONTINUE_SESSION then the session will be closed (if it 68 + * hasn't been consumed) and the auth structure freed. 57 69 */ 58 70 59 71 #include "tpm.h" ··· 115 103 /* scratch for key + IV */ 116 104 u8 scratch[AES_KEY_BYTES + AES_BLOCK_SIZE]; 117 105 }; 106 + /* 107 + * the session key and passphrase are the same size as the 108 + * name digest (sha256 again). The session key is constant 109 + * for the use of the session and the passphrase can change 110 + * with every invocation. 111 + * 112 + * Note: these fields must be adjacent and in this order 113 + * because several HMAC/KDF schemes use the combination of the 114 + * session_key and passphrase. 115 + */ 118 116 u8 session_key[SHA256_DIGEST_SIZE]; 117 + u8 passphrase[SHA256_DIGEST_SIZE]; 118 + int passphrase_len; 119 + struct crypto_aes_ctx aes_ctx; 120 + /* saved session attributes: */ 121 + u8 attrs; 122 + __be32 ordinal; 119 123 120 124 /* 121 125 * memory for three authorization handles. We know them by ··· 337 309 crypto_free_kpp(kpp); 338 310 } 339 311 312 + /** 313 + * tpm_buf_append_hmac_session() - Append a TPM session element 314 + * @chip: the TPM chip structure 315 + * @buf: The buffer to be appended 316 + * @attributes: The session attributes 317 + * @passphrase: The session authority (NULL if none) 318 + * @passphrase_len: The length of the session authority (0 if none) 319 + * 320 + * This fills in a session structure in the TPM command buffer, except 321 + * for the HMAC which cannot be computed until the command buffer is 322 + * complete. The type of session is controlled by the @attributes, 323 + * the main ones of which are TPM2_SA_CONTINUE_SESSION which means the 324 + * session won't terminate after tpm_buf_check_hmac_response(), 325 + * TPM2_SA_DECRYPT which means this buffers first parameter should be 326 + * encrypted with a session key and TPM2_SA_ENCRYPT, which means the 327 + * response buffer's first parameter needs to be decrypted (confusing, 328 + * but the defines are written from the point of view of the TPM). 329 + * 330 + * Any session appended by this command must be finalized by calling 331 + * tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect 332 + * and the TPM will reject the command. 333 + * 334 + * As with most tpm_buf operations, success is assumed because failure 335 + * will be caused by an incorrect programming model and indicated by a 336 + * kernel message. 337 + */ 338 + void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, 339 + u8 attributes, u8 *passphrase, 340 + int passphrase_len) 341 + { 342 + u8 nonce[SHA256_DIGEST_SIZE]; 343 + u32 len; 344 + struct tpm2_auth *auth = chip->auth; 345 + 346 + /* 347 + * The Architecture Guide requires us to strip trailing zeros 348 + * before computing the HMAC 349 + */ 350 + while (passphrase && passphrase_len > 0 351 + && passphrase[passphrase_len - 1] == '\0') 352 + passphrase_len--; 353 + 354 + auth->attrs = attributes; 355 + auth->passphrase_len = passphrase_len; 356 + if (passphrase_len) 357 + memcpy(auth->passphrase, passphrase, passphrase_len); 358 + 359 + if (auth->session != tpm_buf_length(buf)) { 360 + /* we're not the first session */ 361 + len = get_unaligned_be32(&buf->data[auth->session]); 362 + if (4 + len + auth->session != tpm_buf_length(buf)) { 363 + WARN(1, "session length mismatch, cannot append"); 364 + return; 365 + } 366 + 367 + /* add our new session */ 368 + len += 9 + 2 * SHA256_DIGEST_SIZE; 369 + put_unaligned_be32(len, &buf->data[auth->session]); 370 + } else { 371 + tpm_buf_append_u32(buf, 9 + 2 * SHA256_DIGEST_SIZE); 372 + } 373 + 374 + /* random number for our nonce */ 375 + get_random_bytes(nonce, sizeof(nonce)); 376 + memcpy(auth->our_nonce, nonce, sizeof(nonce)); 377 + tpm_buf_append_u32(buf, auth->handle); 378 + /* our new nonce */ 379 + tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE); 380 + tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE); 381 + tpm_buf_append_u8(buf, auth->attrs); 382 + /* and put a placeholder for the hmac */ 383 + tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE); 384 + tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE); 385 + } 386 + EXPORT_SYMBOL(tpm_buf_append_hmac_session); 387 + 388 + /** 389 + * tpm_buf_fill_hmac_session() - finalize the session HMAC 390 + * @chip: the TPM chip structure 391 + * @buf: The buffer to be appended 392 + * 393 + * This command must not be called until all of the parameters have 394 + * been appended to @buf otherwise the computed HMAC will be 395 + * incorrect. 396 + * 397 + * This function computes and fills in the session HMAC using the 398 + * session key and, if TPM2_SA_DECRYPT was specified, computes the 399 + * encryption key and encrypts the first parameter of the command 400 + * buffer with it. 401 + * 402 + * As with most tpm_buf operations, success is assumed because failure 403 + * will be caused by an incorrect programming model and indicated by a 404 + * kernel message. 405 + */ 406 + void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf) 407 + { 408 + u32 cc, handles, val; 409 + struct tpm2_auth *auth = chip->auth; 410 + int i; 411 + struct tpm_header *head = (struct tpm_header *)buf->data; 412 + off_t offset_s = TPM_HEADER_SIZE, offset_p; 413 + u8 *hmac = NULL; 414 + u32 attrs; 415 + u8 cphash[SHA256_DIGEST_SIZE]; 416 + struct sha256_state sctx; 417 + 418 + /* save the command code in BE format */ 419 + auth->ordinal = head->ordinal; 420 + 421 + cc = be32_to_cpu(head->ordinal); 422 + 423 + i = tpm2_find_cc(chip, cc); 424 + if (i < 0) { 425 + dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc); 426 + return; 427 + } 428 + attrs = chip->cc_attrs_tbl[i]; 429 + 430 + handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); 431 + 432 + /* 433 + * just check the names, it's easy to make mistakes. This 434 + * would happen if someone added a handle via 435 + * tpm_buf_append_u32() instead of tpm_buf_append_name() 436 + */ 437 + for (i = 0; i < handles; i++) { 438 + u32 handle = tpm_buf_read_u32(buf, &offset_s); 439 + 440 + if (auth->name_h[i] != handle) { 441 + dev_err(&chip->dev, "TPM: handle %d wrong for name\n", 442 + i); 443 + return; 444 + } 445 + } 446 + /* point offset_s to the start of the sessions */ 447 + val = tpm_buf_read_u32(buf, &offset_s); 448 + /* point offset_p to the start of the parameters */ 449 + offset_p = offset_s + val; 450 + for (i = 1; offset_s < offset_p; i++) { 451 + u32 handle = tpm_buf_read_u32(buf, &offset_s); 452 + u16 len; 453 + u8 a; 454 + 455 + /* nonce (already in auth) */ 456 + len = tpm_buf_read_u16(buf, &offset_s); 457 + offset_s += len; 458 + 459 + a = tpm_buf_read_u8(buf, &offset_s); 460 + 461 + len = tpm_buf_read_u16(buf, &offset_s); 462 + if (handle == auth->handle && auth->attrs == a) { 463 + hmac = &buf->data[offset_s]; 464 + /* 465 + * save our session number so we know which 466 + * session in the response belongs to us 467 + */ 468 + auth->session = i; 469 + } 470 + 471 + offset_s += len; 472 + } 473 + if (offset_s != offset_p) { 474 + dev_err(&chip->dev, "TPM session length is incorrect\n"); 475 + return; 476 + } 477 + if (!hmac) { 478 + dev_err(&chip->dev, "TPM could not find HMAC session\n"); 479 + return; 480 + } 481 + 482 + /* encrypt before HMAC */ 483 + if (auth->attrs & TPM2_SA_DECRYPT) { 484 + u16 len; 485 + 486 + /* need key and IV */ 487 + tpm2_KDFa(auth->session_key, SHA256_DIGEST_SIZE 488 + + auth->passphrase_len, "CFB", auth->our_nonce, 489 + auth->tpm_nonce, AES_KEY_BYTES + AES_BLOCK_SIZE, 490 + auth->scratch); 491 + 492 + len = tpm_buf_read_u16(buf, &offset_p); 493 + aes_expandkey(&auth->aes_ctx, auth->scratch, AES_KEY_BYTES); 494 + aescfb_encrypt(&auth->aes_ctx, &buf->data[offset_p], 495 + &buf->data[offset_p], len, 496 + auth->scratch + AES_KEY_BYTES); 497 + /* reset p to beginning of parameters for HMAC */ 498 + offset_p -= 2; 499 + } 500 + 501 + sha256_init(&sctx); 502 + /* ordinal is already BE */ 503 + sha256_update(&sctx, (u8 *)&head->ordinal, sizeof(head->ordinal)); 504 + /* add the handle names */ 505 + for (i = 0; i < handles; i++) { 506 + enum tpm2_mso_type mso = tpm2_handle_mso(auth->name_h[i]); 507 + 508 + if (mso == TPM2_MSO_PERSISTENT || 509 + mso == TPM2_MSO_VOLATILE || 510 + mso == TPM2_MSO_NVRAM) { 511 + sha256_update(&sctx, auth->name[i], 512 + name_size(auth->name[i])); 513 + } else { 514 + __be32 h = cpu_to_be32(auth->name_h[i]); 515 + 516 + sha256_update(&sctx, (u8 *)&h, 4); 517 + } 518 + } 519 + if (offset_s != tpm_buf_length(buf)) 520 + sha256_update(&sctx, &buf->data[offset_s], 521 + tpm_buf_length(buf) - offset_s); 522 + sha256_final(&sctx, cphash); 523 + 524 + /* now calculate the hmac */ 525 + tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key) 526 + + auth->passphrase_len); 527 + sha256_update(&sctx, cphash, sizeof(cphash)); 528 + sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce)); 529 + sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); 530 + sha256_update(&sctx, &auth->attrs, 1); 531 + tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key) 532 + + auth->passphrase_len, hmac); 533 + } 534 + EXPORT_SYMBOL(tpm_buf_fill_hmac_session); 535 + 340 536 static int tpm2_parse_read_public(char *name, struct tpm_buf *buf) 341 537 { 342 538 struct tpm_header *head = (struct tpm_header *)buf->data; ··· 658 406 memcpy(auth->name[slot], name, name_size(name)); 659 407 } 660 408 EXPORT_SYMBOL(tpm_buf_append_name); 409 + 410 + /** 411 + * tpm_buf_check_hmac_response() - check the TPM return HMAC for correctness 412 + * @chip: the TPM chip structure 413 + * @buf: the original command buffer (which now contains the response) 414 + * @rc: the return code from tpm_transmit_cmd 415 + * 416 + * If @rc is non zero, @buf may not contain an actual return, so @rc 417 + * is passed through as the return and the session cleaned up and 418 + * de-allocated if required (this is required if 419 + * TPM2_SA_CONTINUE_SESSION was not specified as a session flag). 420 + * 421 + * If @rc is zero, the response HMAC is computed against the returned 422 + * @buf and matched to the TPM one in the session area. If there is a 423 + * mismatch, an error is logged and -EINVAL returned. 424 + * 425 + * The reason for this is that the command issue and HMAC check 426 + * sequence should look like: 427 + * 428 + * rc = tpm_transmit_cmd(...); 429 + * rc = tpm_buf_check_hmac_response(&buf, auth, rc); 430 + * if (rc) 431 + * ... 432 + * 433 + * Which is easily layered into the current contrl flow. 434 + * 435 + * Returns: 0 on success or an error. 436 + */ 437 + int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, 438 + int rc) 439 + { 440 + struct tpm_header *head = (struct tpm_header *)buf->data; 441 + struct tpm2_auth *auth = chip->auth; 442 + off_t offset_s, offset_p; 443 + u8 rphash[SHA256_DIGEST_SIZE]; 444 + u32 attrs; 445 + struct sha256_state sctx; 446 + u16 tag = be16_to_cpu(head->tag); 447 + u32 cc = be32_to_cpu(auth->ordinal); 448 + int parm_len, len, i, handles; 449 + 450 + if (auth->session >= TPM_HEADER_SIZE) { 451 + WARN(1, "tpm session not filled correctly\n"); 452 + goto out; 453 + } 454 + 455 + if (rc != 0) 456 + /* pass non success rc through and close the session */ 457 + goto out; 458 + 459 + rc = -EINVAL; 460 + if (tag != TPM2_ST_SESSIONS) { 461 + dev_err(&chip->dev, "TPM: HMAC response check has no sessions tag\n"); 462 + goto out; 463 + } 464 + 465 + i = tpm2_find_cc(chip, cc); 466 + if (i < 0) 467 + goto out; 468 + attrs = chip->cc_attrs_tbl[i]; 469 + handles = (attrs >> TPM2_CC_ATTR_RHANDLE) & 1; 470 + 471 + /* point to area beyond handles */ 472 + offset_s = TPM_HEADER_SIZE + handles * 4; 473 + parm_len = tpm_buf_read_u32(buf, &offset_s); 474 + offset_p = offset_s; 475 + offset_s += parm_len; 476 + /* skip over any sessions before ours */ 477 + for (i = 0; i < auth->session - 1; i++) { 478 + len = tpm_buf_read_u16(buf, &offset_s); 479 + offset_s += len + 1; 480 + len = tpm_buf_read_u16(buf, &offset_s); 481 + offset_s += len; 482 + } 483 + /* TPM nonce */ 484 + len = tpm_buf_read_u16(buf, &offset_s); 485 + if (offset_s + len > tpm_buf_length(buf)) 486 + goto out; 487 + if (len != SHA256_DIGEST_SIZE) 488 + goto out; 489 + memcpy(auth->tpm_nonce, &buf->data[offset_s], len); 490 + offset_s += len; 491 + attrs = tpm_buf_read_u8(buf, &offset_s); 492 + len = tpm_buf_read_u16(buf, &offset_s); 493 + if (offset_s + len != tpm_buf_length(buf)) 494 + goto out; 495 + if (len != SHA256_DIGEST_SIZE) 496 + goto out; 497 + /* 498 + * offset_s points to the HMAC. now calculate comparison, beginning 499 + * with rphash 500 + */ 501 + sha256_init(&sctx); 502 + /* yes, I know this is now zero, but it's what the standard says */ 503 + sha256_update(&sctx, (u8 *)&head->return_code, 504 + sizeof(head->return_code)); 505 + /* ordinal is already BE */ 506 + sha256_update(&sctx, (u8 *)&auth->ordinal, sizeof(auth->ordinal)); 507 + sha256_update(&sctx, &buf->data[offset_p], parm_len); 508 + sha256_final(&sctx, rphash); 509 + 510 + /* now calculate the hmac */ 511 + tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key) 512 + + auth->passphrase_len); 513 + sha256_update(&sctx, rphash, sizeof(rphash)); 514 + sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); 515 + sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce)); 516 + sha256_update(&sctx, &auth->attrs, 1); 517 + /* we're done with the rphash, so put our idea of the hmac there */ 518 + tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key) 519 + + auth->passphrase_len, rphash); 520 + if (memcmp(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE) == 0) { 521 + rc = 0; 522 + } else { 523 + dev_err(&chip->dev, "TPM: HMAC check failed\n"); 524 + goto out; 525 + } 526 + 527 + /* now do response decryption */ 528 + if (auth->attrs & TPM2_SA_ENCRYPT) { 529 + /* need key and IV */ 530 + tpm2_KDFa(auth->session_key, SHA256_DIGEST_SIZE 531 + + auth->passphrase_len, "CFB", auth->tpm_nonce, 532 + auth->our_nonce, AES_KEY_BYTES + AES_BLOCK_SIZE, 533 + auth->scratch); 534 + 535 + len = tpm_buf_read_u16(buf, &offset_p); 536 + aes_expandkey(&auth->aes_ctx, auth->scratch, AES_KEY_BYTES); 537 + aescfb_decrypt(&auth->aes_ctx, &buf->data[offset_p], 538 + &buf->data[offset_p], len, 539 + auth->scratch + AES_KEY_BYTES); 540 + } 541 + 542 + out: 543 + if ((auth->attrs & TPM2_SA_CONTINUE_SESSION) == 0) { 544 + if (rc) 545 + /* manually close the session if it wasn't consumed */ 546 + tpm2_flush_context(chip, auth->handle); 547 + memzero_explicit(auth, sizeof(*auth)); 548 + } else { 549 + /* reset for next use */ 550 + auth->session = TPM_HEADER_SIZE; 551 + } 552 + 553 + return rc; 554 + } 555 + EXPORT_SYMBOL(tpm_buf_check_hmac_response); 556 + 661 557 /** 662 558 * tpm2_end_auth_session() - kill the allocated auth session 663 559 * @chip: the TPM chip structure
+69
include/linux/tpm.h
··· 510 510 int tpm2_start_auth_session(struct tpm_chip *chip); 511 511 void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, 512 512 u32 handle, u8 *name); 513 + void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, 514 + u8 attributes, u8 *passphrase, 515 + int passphraselen); 516 + static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip, 517 + struct tpm_buf *buf, 518 + u8 attributes, 519 + u8 *passphrase, 520 + int passphraselen) 521 + { 522 + tpm_buf_append_hmac_session(chip, buf, attributes, passphrase, 523 + passphraselen); 524 + } 525 + void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf); 526 + int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, 527 + int rc); 513 528 void tpm2_end_auth_session(struct tpm_chip *chip); 514 529 #else 530 + #include <asm/unaligned.h> 531 + 515 532 static inline int tpm2_start_auth_session(struct tpm_chip *chip) 516 533 { 517 534 return 0; ··· 543 526 tpm_buf_append_u32(buf, handle); 544 527 /* count the number of handles in the upper bits of flags */ 545 528 buf->handles++; 529 + } 530 + static inline void tpm_buf_append_hmac_session(struct tpm_chip *chip, 531 + struct tpm_buf *buf, 532 + u8 attributes, u8 *passphrase, 533 + int passphraselen) 534 + { 535 + /* offset tells us where the sessions area begins */ 536 + int offset = buf->handles * 4 + TPM_HEADER_SIZE; 537 + u32 len = 9 + passphraselen; 538 + 539 + if (tpm_buf_length(buf) != offset) { 540 + /* not the first session so update the existing length */ 541 + len += get_unaligned_be32(&buf->data[offset]); 542 + put_unaligned_be32(len, &buf->data[offset]); 543 + } else { 544 + tpm_buf_append_u32(buf, len); 545 + } 546 + /* auth handle */ 547 + tpm_buf_append_u32(buf, TPM2_RS_PW); 548 + /* nonce */ 549 + tpm_buf_append_u16(buf, 0); 550 + /* attributes */ 551 + tpm_buf_append_u8(buf, 0); 552 + /* passphrase */ 553 + tpm_buf_append_u16(buf, passphraselen); 554 + tpm_buf_append(buf, passphrase, passphraselen); 555 + } 556 + static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip, 557 + struct tpm_buf *buf, 558 + u8 attributes, 559 + u8 *passphrase, 560 + int passphraselen) 561 + { 562 + int offset = buf->handles * 4 + TPM_HEADER_SIZE; 563 + struct tpm_header *head = (struct tpm_header *) buf->data; 564 + 565 + /* 566 + * if the only sessions are optional, the command tag 567 + * must change to TPM2_ST_NO_SESSIONS 568 + */ 569 + if (tpm_buf_length(buf) == offset) 570 + head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); 571 + } 572 + static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip, 573 + struct tpm_buf *buf) 574 + { 575 + } 576 + static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip, 577 + struct tpm_buf *buf, 578 + int rc) 579 + { 580 + return rc; 546 581 } 547 582 #endif /* CONFIG_TCG_TPM2_HMAC */ 548 583