|
49 | 49 | * Under normal operation this function is done by |
50 | 50 | * tpm_buf_check_hmac_response(), so this is only to be used on |
51 | 51 | * error legs where the latter is not executed. |
| 52 | + * tpm_buf_append_name() to add a handle to the buffer. This must be |
| 53 | + * used in place of the usual tpm_buf_append_u32() for adding |
| 54 | + * handles because handles have to be processed specially when |
| 55 | + * calculating the HMAC. In particular, for NV, volatile and |
| 56 | + * permanent objects you now need to provide the name. |
52 | 57 | */ |
53 | 58 |
|
54 | 59 | #include "tpm.h" |
|
60 | 65 | #include <crypto/hash.h> |
61 | 66 | #include <crypto/hmac.h> |
62 | 67 |
|
| 68 | +/* maximum number of names the TPM must remember for authorization */ |
| 69 | +#define AUTH_MAX_NAMES 3 |
| 70 | + |
63 | 71 | /* |
64 | 72 | * This is the structure that carries all the auth information (like |
65 | 73 | * session handle, nonces, session key and auth) from use to use it is |
@@ -96,8 +104,31 @@ struct tpm2_auth { |
96 | 104 | u8 scratch[AES_KEY_BYTES + AES_BLOCK_SIZE]; |
97 | 105 | }; |
98 | 106 | u8 session_key[SHA256_DIGEST_SIZE]; |
| 107 | + |
| 108 | + /* |
| 109 | + * memory for three authorization handles. We know them by |
| 110 | + * handle, but they are part of the session by name, which |
| 111 | + * we must compute and remember |
| 112 | + */ |
| 113 | + u32 name_h[AUTH_MAX_NAMES]; |
| 114 | + u8 name[AUTH_MAX_NAMES][2 + SHA512_DIGEST_SIZE]; |
99 | 115 | }; |
100 | 116 |
|
| 117 | +/* |
| 118 | + * Name Size based on TPM algorithm (assumes no hash bigger than 255) |
| 119 | + */ |
| 120 | +static u8 name_size(const u8 *name) |
| 121 | +{ |
| 122 | + static u8 size_map[] = { |
| 123 | + [TPM_ALG_SHA1] = SHA1_DIGEST_SIZE, |
| 124 | + [TPM_ALG_SHA256] = SHA256_DIGEST_SIZE, |
| 125 | + [TPM_ALG_SHA384] = SHA384_DIGEST_SIZE, |
| 126 | + [TPM_ALG_SHA512] = SHA512_DIGEST_SIZE, |
| 127 | + }; |
| 128 | + u16 alg = get_unaligned_be16(name); |
| 129 | + return size_map[alg] + 2; |
| 130 | +} |
| 131 | + |
101 | 132 | /* |
102 | 133 | * It turns out the crypto hmac(sha256) is hard for us to consume |
103 | 134 | * because it assumes a fixed key and the TPM seems to change the key |
@@ -277,6 +308,104 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip) |
277 | 308 | out: |
278 | 309 | crypto_free_kpp(kpp); |
279 | 310 | } |
| 311 | + |
| 312 | +static int tpm2_parse_read_public(char *name, struct tpm_buf *buf) |
| 313 | +{ |
| 314 | + struct tpm_header *head = (struct tpm_header *)buf->data; |
| 315 | + off_t offset = TPM_HEADER_SIZE; |
| 316 | + u32 tot_len = be32_to_cpu(head->length); |
| 317 | + u32 val; |
| 318 | + |
| 319 | + /* we're starting after the header so adjust the length */ |
| 320 | + tot_len -= TPM_HEADER_SIZE; |
| 321 | + |
| 322 | + /* skip public */ |
| 323 | + val = tpm_buf_read_u16(buf, &offset); |
| 324 | + if (val > tot_len) |
| 325 | + return -EINVAL; |
| 326 | + offset += val; |
| 327 | + /* name */ |
| 328 | + val = tpm_buf_read_u16(buf, &offset); |
| 329 | + if (val != name_size(&buf->data[offset])) |
| 330 | + return -EINVAL; |
| 331 | + memcpy(name, &buf->data[offset], val); |
| 332 | + /* forget the rest */ |
| 333 | + return 0; |
| 334 | +} |
| 335 | + |
| 336 | +static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name) |
| 337 | +{ |
| 338 | + struct tpm_buf buf; |
| 339 | + int rc; |
| 340 | + |
| 341 | + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); |
| 342 | + if (rc) |
| 343 | + return rc; |
| 344 | + |
| 345 | + tpm_buf_append_u32(&buf, handle); |
| 346 | + rc = tpm_transmit_cmd(chip, &buf, 0, "read public"); |
| 347 | + if (rc == TPM2_RC_SUCCESS) |
| 348 | + rc = tpm2_parse_read_public(name, &buf); |
| 349 | + |
| 350 | + tpm_buf_destroy(&buf); |
| 351 | + |
| 352 | + return rc; |
| 353 | +} |
| 354 | + |
| 355 | +/** |
| 356 | + * tpm_buf_append_name() - add a handle area to the buffer |
| 357 | + * @chip: the TPM chip structure |
| 358 | + * @buf: The buffer to be appended |
| 359 | + * @handle: The handle to be appended |
| 360 | + * @name: The name of the handle (may be NULL) |
| 361 | + * |
| 362 | + * In order to compute session HMACs, we need to know the names of the |
| 363 | + * objects pointed to by the handles. For most objects, this is simply |
| 364 | + * the actual 4 byte handle or an empty buf (in these cases @name |
| 365 | + * should be NULL) but for volatile objects, permanent objects and NV |
| 366 | + * areas, the name is defined as the hash (according to the name |
| 367 | + * algorithm which should be set to sha256) of the public area to |
| 368 | + * which the two byte algorithm id has been appended. For these |
| 369 | + * objects, the @name pointer should point to this. If a name is |
| 370 | + * required but @name is NULL, then TPM2_ReadPublic() will be called |
| 371 | + * on the handle to obtain the name. |
| 372 | + * |
| 373 | + * As with most tpm_buf operations, success is assumed because failure |
| 374 | + * will be caused by an incorrect programming model and indicated by a |
| 375 | + * kernel message. |
| 376 | + */ |
| 377 | +void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, |
| 378 | + u32 handle, u8 *name) |
| 379 | +{ |
| 380 | + enum tpm2_mso_type mso = tpm2_handle_mso(handle); |
| 381 | + struct tpm2_auth *auth = chip->auth; |
| 382 | + int slot; |
| 383 | + |
| 384 | + slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE)/4; |
| 385 | + if (slot >= AUTH_MAX_NAMES) { |
| 386 | + dev_err(&chip->dev, "TPM: too many handles\n"); |
| 387 | + return; |
| 388 | + } |
| 389 | + WARN(auth->session != tpm_buf_length(buf), |
| 390 | + "name added in wrong place\n"); |
| 391 | + tpm_buf_append_u32(buf, handle); |
| 392 | + auth->session += 4; |
| 393 | + |
| 394 | + if (mso == TPM2_MSO_PERSISTENT || |
| 395 | + mso == TPM2_MSO_VOLATILE || |
| 396 | + mso == TPM2_MSO_NVRAM) { |
| 397 | + if (!name) |
| 398 | + tpm2_read_public(chip, handle, auth->name[slot]); |
| 399 | + } else { |
| 400 | + if (name) |
| 401 | + dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n"); |
| 402 | + } |
| 403 | + |
| 404 | + auth->name_h[slot] = handle; |
| 405 | + if (name) |
| 406 | + memcpy(auth->name[slot], name, name_size(name)); |
| 407 | +} |
| 408 | +EXPORT_SYMBOL(tpm_buf_append_name); |
280 | 409 | /** |
281 | 410 | * tpm2_end_auth_session() - kill the allocated auth session |
282 | 411 | * @chip: the TPM chip structure |
|
0 commit comments