Home | History | Annotate | Download | only in lib
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (c) 2013 The Chromium OS Authors.
      4  * Coypright (c) 2013 Guntermann & Drunck GmbH
      5  */
      6 
      7 #include <common.h>
      8 #include <dm.h>
      9 #include <asm/unaligned.h>
     10 #include <u-boot/sha1.h>
     11 #include <tpm-common.h>
     12 #include <tpm-v1.h>
     13 #include "tpm-utils.h"
     14 
     15 #ifdef CONFIG_TPM_AUTH_SESSIONS
     16 
     17 #ifndef CONFIG_SHA1
     18 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
     19 #endif /* !CONFIG_SHA1 */
     20 
     21 struct session_data {
     22 	int		valid;
     23 	u32	handle;
     24 	u8		nonce_even[DIGEST_LENGTH];
     25 	u8		nonce_odd[DIGEST_LENGTH];
     26 };
     27 
     28 static struct session_data oiap_session = {0, };
     29 
     30 #endif /* CONFIG_TPM_AUTH_SESSIONS */
     31 
     32 u32 tpm_startup(enum tpm_startup_type mode)
     33 {
     34 	const u8 command[12] = {
     35 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
     36 	};
     37 	const size_t mode_offset = 10;
     38 	u8 buf[COMMAND_BUFFER_SIZE];
     39 
     40 	if (pack_byte_string(buf, sizeof(buf), "sw",
     41 			     0, command, sizeof(command),
     42 			     mode_offset, mode))
     43 		return TPM_LIB_ERROR;
     44 
     45 	return tpm_sendrecv_command(buf, NULL, NULL);
     46 }
     47 
     48 u32 tpm_self_test_full(void)
     49 {
     50 	const u8 command[10] = {
     51 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
     52 	};
     53 	return tpm_sendrecv_command(command, NULL, NULL);
     54 }
     55 
     56 u32 tpm_continue_self_test(void)
     57 {
     58 	const u8 command[10] = {
     59 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
     60 	};
     61 	return tpm_sendrecv_command(command, NULL, NULL);
     62 }
     63 
     64 u32 tpm_nv_define_space(u32 index, u32 perm, u32 size)
     65 {
     66 	const u8 command[101] = {
     67 		0x0, 0xc1,		/* TPM_TAG */
     68 		0x0, 0x0, 0x0, 0x65,	/* parameter size */
     69 		0x0, 0x0, 0x0, 0xcc,	/* TPM_COMMAND_CODE */
     70 		/* TPM_NV_DATA_PUBLIC->... */
     71 		0x0, 0x18,		/* ...->TPM_STRUCTURE_TAG */
     72 		0, 0, 0, 0,		/* ...->TPM_NV_INDEX */
     73 		/* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
     74 		0x0, 0x3,
     75 		0, 0, 0,
     76 		0x1f,
     77 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     78 		/* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
     79 		0x0, 0x3,
     80 		0, 0, 0,
     81 		0x1f,
     82 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     83 		/* TPM_NV_ATTRIBUTES->... */
     84 		0x0, 0x17,		/* ...->TPM_STRUCTURE_TAG */
     85 		0, 0, 0, 0,		/* ...->attributes */
     86 		/* End of TPM_NV_ATTRIBUTES */
     87 		0,			/* bReadSTClear */
     88 		0,			/* bWriteSTClear */
     89 		0,			/* bWriteDefine */
     90 		0, 0, 0, 0,		/* size */
     91 	};
     92 	const size_t index_offset = 12;
     93 	const size_t perm_offset = 70;
     94 	const size_t size_offset = 77;
     95 	u8 buf[COMMAND_BUFFER_SIZE];
     96 
     97 	if (pack_byte_string(buf, sizeof(buf), "sddd",
     98 			     0, command, sizeof(command),
     99 			     index_offset, index,
    100 			     perm_offset, perm,
    101 			     size_offset, size))
    102 		return TPM_LIB_ERROR;
    103 
    104 	return tpm_sendrecv_command(buf, NULL, NULL);
    105 }
    106 
    107 u32 tpm_nv_read_value(u32 index, void *data, u32 count)
    108 {
    109 	const u8 command[22] = {
    110 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
    111 	};
    112 	const size_t index_offset = 10;
    113 	const size_t length_offset = 18;
    114 	const size_t data_size_offset = 10;
    115 	const size_t data_offset = 14;
    116 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    117 	size_t response_length = sizeof(response);
    118 	u32 data_size;
    119 	u32 err;
    120 
    121 	if (pack_byte_string(buf, sizeof(buf), "sdd",
    122 			     0, command, sizeof(command),
    123 			     index_offset, index,
    124 			     length_offset, count))
    125 		return TPM_LIB_ERROR;
    126 	err = tpm_sendrecv_command(buf, response, &response_length);
    127 	if (err)
    128 		return err;
    129 	if (unpack_byte_string(response, response_length, "d",
    130 			       data_size_offset, &data_size))
    131 		return TPM_LIB_ERROR;
    132 	if (data_size > count)
    133 		return TPM_LIB_ERROR;
    134 	if (unpack_byte_string(response, response_length, "s",
    135 			       data_offset, data, data_size))
    136 		return TPM_LIB_ERROR;
    137 
    138 	return 0;
    139 }
    140 
    141 u32 tpm_nv_write_value(u32 index, const void *data, u32 length)
    142 {
    143 	const u8 command[256] = {
    144 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
    145 	};
    146 	const size_t command_size_offset = 2;
    147 	const size_t index_offset = 10;
    148 	const size_t length_offset = 18;
    149 	const size_t data_offset = 22;
    150 	const size_t write_info_size = 12;
    151 	const u32 total_length =
    152 		TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
    153 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    154 	size_t response_length = sizeof(response);
    155 	u32 err;
    156 
    157 	if (pack_byte_string(buf, sizeof(buf), "sddds",
    158 			     0, command, sizeof(command),
    159 			     command_size_offset, total_length,
    160 			     index_offset, index,
    161 			     length_offset, length,
    162 			     data_offset, data, length))
    163 		return TPM_LIB_ERROR;
    164 	err = tpm_sendrecv_command(buf, response, &response_length);
    165 	if (err)
    166 		return err;
    167 
    168 	return 0;
    169 }
    170 
    171 u32 tpm_extend(u32 index, const void *in_digest, void *out_digest)
    172 {
    173 	const u8 command[34] = {
    174 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
    175 	};
    176 	const size_t index_offset = 10;
    177 	const size_t in_digest_offset = 14;
    178 	const size_t out_digest_offset = 10;
    179 	u8 buf[COMMAND_BUFFER_SIZE];
    180 	u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
    181 	size_t response_length = sizeof(response);
    182 	u32 err;
    183 
    184 	if (pack_byte_string(buf, sizeof(buf), "sds",
    185 			     0, command, sizeof(command),
    186 			     index_offset, index,
    187 			     in_digest_offset, in_digest,
    188 			     PCR_DIGEST_LENGTH))
    189 		return TPM_LIB_ERROR;
    190 	err = tpm_sendrecv_command(buf, response, &response_length);
    191 	if (err)
    192 		return err;
    193 
    194 	if (unpack_byte_string(response, response_length, "s",
    195 			       out_digest_offset, out_digest,
    196 			       PCR_DIGEST_LENGTH))
    197 		return TPM_LIB_ERROR;
    198 
    199 	return 0;
    200 }
    201 
    202 u32 tpm_pcr_read(u32 index, void *data, size_t count)
    203 {
    204 	const u8 command[14] = {
    205 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
    206 	};
    207 	const size_t index_offset = 10;
    208 	const size_t out_digest_offset = 10;
    209 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    210 	size_t response_length = sizeof(response);
    211 	u32 err;
    212 
    213 	if (count < PCR_DIGEST_LENGTH)
    214 		return TPM_LIB_ERROR;
    215 
    216 	if (pack_byte_string(buf, sizeof(buf), "sd",
    217 			     0, command, sizeof(command),
    218 			     index_offset, index))
    219 		return TPM_LIB_ERROR;
    220 	err = tpm_sendrecv_command(buf, response, &response_length);
    221 	if (err)
    222 		return err;
    223 	if (unpack_byte_string(response, response_length, "s",
    224 			       out_digest_offset, data, PCR_DIGEST_LENGTH))
    225 		return TPM_LIB_ERROR;
    226 
    227 	return 0;
    228 }
    229 
    230 u32 tpm_tsc_physical_presence(u16 presence)
    231 {
    232 	const u8 command[12] = {
    233 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
    234 	};
    235 	const size_t presence_offset = 10;
    236 	u8 buf[COMMAND_BUFFER_SIZE];
    237 
    238 	if (pack_byte_string(buf, sizeof(buf), "sw",
    239 			     0, command, sizeof(command),
    240 			     presence_offset, presence))
    241 		return TPM_LIB_ERROR;
    242 
    243 	return tpm_sendrecv_command(buf, NULL, NULL);
    244 }
    245 
    246 u32 tpm_read_pubek(void *data, size_t count)
    247 {
    248 	const u8 command[30] = {
    249 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
    250 	};
    251 	const size_t response_size_offset = 2;
    252 	const size_t data_offset = 10;
    253 	const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
    254 	u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
    255 	size_t response_length = sizeof(response);
    256 	u32 data_size;
    257 	u32 err;
    258 
    259 	err = tpm_sendrecv_command(command, response, &response_length);
    260 	if (err)
    261 		return err;
    262 	if (unpack_byte_string(response, response_length, "d",
    263 			       response_size_offset, &data_size))
    264 		return TPM_LIB_ERROR;
    265 	if (data_size < header_and_checksum_size)
    266 		return TPM_LIB_ERROR;
    267 	data_size -= header_and_checksum_size;
    268 	if (data_size > count)
    269 		return TPM_LIB_ERROR;
    270 	if (unpack_byte_string(response, response_length, "s",
    271 			       data_offset, data, data_size))
    272 		return TPM_LIB_ERROR;
    273 
    274 	return 0;
    275 }
    276 
    277 u32 tpm_force_clear(void)
    278 {
    279 	const u8 command[10] = {
    280 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
    281 	};
    282 
    283 	return tpm_sendrecv_command(command, NULL, NULL);
    284 }
    285 
    286 u32 tpm_physical_enable(void)
    287 {
    288 	const u8 command[10] = {
    289 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
    290 	};
    291 
    292 	return tpm_sendrecv_command(command, NULL, NULL);
    293 }
    294 
    295 u32 tpm_physical_disable(void)
    296 {
    297 	const u8 command[10] = {
    298 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
    299 	};
    300 
    301 	return tpm_sendrecv_command(command, NULL, NULL);
    302 }
    303 
    304 u32 tpm_physical_set_deactivated(u8 state)
    305 {
    306 	const u8 command[11] = {
    307 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
    308 	};
    309 	const size_t state_offset = 10;
    310 	u8 buf[COMMAND_BUFFER_SIZE];
    311 
    312 	if (pack_byte_string(buf, sizeof(buf), "sb",
    313 			     0, command, sizeof(command),
    314 			     state_offset, state))
    315 		return TPM_LIB_ERROR;
    316 
    317 	return tpm_sendrecv_command(buf, NULL, NULL);
    318 }
    319 
    320 u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
    321 {
    322 	const u8 command[22] = {
    323 		0x0, 0xc1,		/* TPM_TAG */
    324 		0x0, 0x0, 0x0, 0x16,	/* parameter size */
    325 		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
    326 		0x0, 0x0, 0x0, 0x0,	/* TPM_CAPABILITY_AREA */
    327 		0x0, 0x0, 0x0, 0x4,	/* subcap size */
    328 		0x0, 0x0, 0x0, 0x0,	/* subcap value */
    329 	};
    330 	const size_t cap_area_offset = 10;
    331 	const size_t sub_cap_offset = 18;
    332 	const size_t cap_offset = 14;
    333 	const size_t cap_size_offset = 10;
    334 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    335 	size_t response_length = sizeof(response);
    336 	u32 cap_size;
    337 	u32 err;
    338 
    339 	if (pack_byte_string(buf, sizeof(buf), "sdd",
    340 			     0, command, sizeof(command),
    341 			     cap_area_offset, cap_area,
    342 			     sub_cap_offset, sub_cap))
    343 		return TPM_LIB_ERROR;
    344 	err = tpm_sendrecv_command(buf, response, &response_length);
    345 	if (err)
    346 		return err;
    347 	if (unpack_byte_string(response, response_length, "d",
    348 			       cap_size_offset, &cap_size))
    349 		return TPM_LIB_ERROR;
    350 	if (cap_size > response_length || cap_size > count)
    351 		return TPM_LIB_ERROR;
    352 	if (unpack_byte_string(response, response_length, "s",
    353 			       cap_offset, cap, cap_size))
    354 		return TPM_LIB_ERROR;
    355 
    356 	return 0;
    357 }
    358 
    359 u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
    360 {
    361 	const u8 command[22] = {
    362 		0x0, 0xc1,		/* TPM_TAG */
    363 		0x0, 0x0, 0x0, 0x16,	/* parameter size */
    364 		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
    365 		0x0, 0x0, 0x0, 0x4,	/* TPM_CAP_FLAG_PERM */
    366 		0x0, 0x0, 0x0, 0x4,	/* subcap size */
    367 		0x0, 0x0, 0x1, 0x8,	/* subcap value */
    368 	};
    369 	const size_t data_size_offset = TPM_HEADER_SIZE;
    370 	const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
    371 	u8 response[COMMAND_BUFFER_SIZE];
    372 	size_t response_length = sizeof(response);
    373 	u32 err;
    374 	u32 data_size;
    375 
    376 	err = tpm_sendrecv_command(command, response, &response_length);
    377 	if (err)
    378 		return err;
    379 	if (unpack_byte_string(response, response_length, "d",
    380 			       data_size_offset, &data_size))
    381 		return TPM_LIB_ERROR;
    382 	if (data_size < sizeof(*pflags))
    383 		return TPM_LIB_ERROR;
    384 	if (unpack_byte_string(response, response_length, "s",
    385 			       data_offset, pflags, sizeof(*pflags)))
    386 		return TPM_LIB_ERROR;
    387 
    388 	return 0;
    389 }
    390 
    391 u32 tpm_get_permissions(u32 index, u32 *perm)
    392 {
    393 	const u8 command[22] = {
    394 		0x0, 0xc1,		/* TPM_TAG */
    395 		0x0, 0x0, 0x0, 0x16,	/* parameter size */
    396 		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
    397 		0x0, 0x0, 0x0, 0x11,
    398 		0x0, 0x0, 0x0, 0x4,
    399 	};
    400 	const size_t index_offset = 18;
    401 	const size_t perm_offset = 60;
    402 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    403 	size_t response_length = sizeof(response);
    404 	u32 err;
    405 
    406 	if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
    407 			     index_offset, index))
    408 		return TPM_LIB_ERROR;
    409 	err = tpm_sendrecv_command(buf, response, &response_length);
    410 	if (err)
    411 		return err;
    412 	if (unpack_byte_string(response, response_length, "d",
    413 			       perm_offset, perm))
    414 		return TPM_LIB_ERROR;
    415 
    416 	return 0;
    417 }
    418 
    419 #ifdef CONFIG_TPM_FLUSH_RESOURCES
    420 u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
    421 {
    422 	const u8 command[18] = {
    423 		0x00, 0xc1,             /* TPM_TAG */
    424 		0x00, 0x00, 0x00, 0x12, /* parameter size */
    425 		0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
    426 		0x00, 0x00, 0x00, 0x00, /* key handle */
    427 		0x00, 0x00, 0x00, 0x00, /* resource type */
    428 	};
    429 	const size_t key_handle_offset = 10;
    430 	const size_t resource_type_offset = 14;
    431 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    432 	size_t response_length = sizeof(response);
    433 	u32 err;
    434 
    435 	if (pack_byte_string(buf, sizeof(buf), "sdd",
    436 			     0, command, sizeof(command),
    437 			     key_handle_offset, key_handle,
    438 			     resource_type_offset, resource_type))
    439 		return TPM_LIB_ERROR;
    440 
    441 	err = tpm_sendrecv_command(buf, response, &response_length);
    442 	if (err)
    443 		return err;
    444 	return 0;
    445 }
    446 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
    447 
    448 #ifdef CONFIG_TPM_AUTH_SESSIONS
    449 
    450 /**
    451  * Fill an authentication block in a request.
    452  * This func can create the first as well as the second auth block (for
    453  * double authorized commands).
    454  *
    455  * @param request	pointer to the request (w/ uninitialised auth data)
    456  * @param request_len0	length of the request without auth data
    457  * @param handles_len	length of the handles area in request
    458  * @param auth_session	pointer to the (valid) auth session to be used
    459  * @param request_auth	pointer to the auth block of the request to be filled
    460  * @param auth		authentication data (HMAC key)
    461  */
    462 static u32 create_request_auth(const void *request, size_t request_len0,
    463 			       size_t handles_len,
    464 			       struct session_data *auth_session,
    465 			       void *request_auth, const void *auth)
    466 {
    467 	u8 hmac_data[DIGEST_LENGTH * 3 + 1];
    468 	sha1_context hash_ctx;
    469 	const size_t command_code_offset = 6;
    470 	const size_t auth_nonce_odd_offset = 4;
    471 	const size_t auth_continue_offset = 24;
    472 	const size_t auth_auth_offset = 25;
    473 
    474 	if (!auth_session || !auth_session->valid)
    475 		return TPM_LIB_ERROR;
    476 
    477 	sha1_starts(&hash_ctx);
    478 	sha1_update(&hash_ctx, request + command_code_offset, 4);
    479 	if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
    480 		sha1_update(&hash_ctx,
    481 			    request + TPM_REQUEST_HEADER_LENGTH + handles_len,
    482 			    request_len0 - TPM_REQUEST_HEADER_LENGTH
    483 			    - handles_len);
    484 	sha1_finish(&hash_ctx, hmac_data);
    485 
    486 	sha1_starts(&hash_ctx);
    487 	sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
    488 	sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
    489 	sha1_finish(&hash_ctx, auth_session->nonce_odd);
    490 
    491 	if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
    492 			     0, auth_session->handle,
    493 			     auth_nonce_odd_offset, auth_session->nonce_odd,
    494 			     DIGEST_LENGTH,
    495 			     auth_continue_offset, 1))
    496 		return TPM_LIB_ERROR;
    497 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
    498 			     DIGEST_LENGTH,
    499 			     auth_session->nonce_even,
    500 			     DIGEST_LENGTH,
    501 			     2 * DIGEST_LENGTH,
    502 			     request_auth + auth_nonce_odd_offset,
    503 			     DIGEST_LENGTH + 1))
    504 		return TPM_LIB_ERROR;
    505 	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
    506 		  request_auth + auth_auth_offset);
    507 
    508 	return TPM_SUCCESS;
    509 }
    510 
    511 /**
    512  * Verify an authentication block in a response.
    513  * Since this func updates the nonce_even in the session data it has to be
    514  * called when receiving a succesfull AUTH response.
    515  * This func can verify the first as well as the second auth block (for
    516  * double authorized commands).
    517  *
    518  * @param command_code	command code of the request
    519  * @param response	pointer to the request (w/ uninitialised auth data)
    520  * @param handles_len	length of the handles area in response
    521  * @param auth_session	pointer to the (valid) auth session to be used
    522  * @param response_auth	pointer to the auth block of the response to be verified
    523  * @param auth		authentication data (HMAC key)
    524  */
    525 static u32 verify_response_auth(u32 command_code, const void *response,
    526 				size_t response_len0, size_t handles_len,
    527 				struct session_data *auth_session,
    528 				const void *response_auth, const void *auth)
    529 {
    530 	u8 hmac_data[DIGEST_LENGTH * 3 + 1];
    531 	u8 computed_auth[DIGEST_LENGTH];
    532 	sha1_context hash_ctx;
    533 	const size_t return_code_offset = 6;
    534 	const size_t auth_continue_offset = 20;
    535 	const size_t auth_auth_offset = 21;
    536 	u8 auth_continue;
    537 
    538 	if (!auth_session || !auth_session->valid)
    539 		return TPM_AUTHFAIL;
    540 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
    541 			     0, command_code))
    542 		return TPM_LIB_ERROR;
    543 	if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
    544 		return TPM_LIB_ERROR;
    545 
    546 	sha1_starts(&hash_ctx);
    547 	sha1_update(&hash_ctx, response + return_code_offset, 4);
    548 	sha1_update(&hash_ctx, hmac_data, 4);
    549 	if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
    550 		sha1_update(&hash_ctx,
    551 			    response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
    552 			    response_len0 - TPM_RESPONSE_HEADER_LENGTH
    553 			    - handles_len);
    554 	sha1_finish(&hash_ctx, hmac_data);
    555 
    556 	memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
    557 	auth_continue = ((u8 *)response_auth)[auth_continue_offset];
    558 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
    559 			     DIGEST_LENGTH,
    560 			     response_auth,
    561 			     DIGEST_LENGTH,
    562 			     2 * DIGEST_LENGTH,
    563 			     auth_session->nonce_odd,
    564 			     DIGEST_LENGTH,
    565 			     3 * DIGEST_LENGTH,
    566 			     auth_continue))
    567 		return TPM_LIB_ERROR;
    568 
    569 	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
    570 		  computed_auth);
    571 
    572 	if (memcmp(computed_auth, response_auth + auth_auth_offset,
    573 		   DIGEST_LENGTH))
    574 		return TPM_AUTHFAIL;
    575 
    576 	return TPM_SUCCESS;
    577 }
    578 
    579 u32 tpm_terminate_auth_session(u32 auth_handle)
    580 {
    581 	const u8 command[18] = {
    582 		0x00, 0xc1,		/* TPM_TAG */
    583 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
    584 		0x00, 0x00, 0x00, 0xba,	/* TPM_COMMAND_CODE */
    585 		0x00, 0x00, 0x00, 0x00,	/* TPM_HANDLE */
    586 		0x00, 0x00, 0x00, 0x02,	/* TPM_RESOURCE_TYPE */
    587 	};
    588 	const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
    589 	u8 request[COMMAND_BUFFER_SIZE];
    590 
    591 	if (pack_byte_string(request, sizeof(request), "sd",
    592 			     0, command, sizeof(command),
    593 			     req_handle_offset, auth_handle))
    594 		return TPM_LIB_ERROR;
    595 	if (oiap_session.valid && oiap_session.handle == auth_handle)
    596 		oiap_session.valid = 0;
    597 
    598 	return tpm_sendrecv_command(request, NULL, NULL);
    599 }
    600 
    601 u32 tpm_end_oiap(void)
    602 {
    603 	u32 err = TPM_SUCCESS;
    604 
    605 	if (oiap_session.valid)
    606 		err = tpm_terminate_auth_session(oiap_session.handle);
    607 	return err;
    608 }
    609 
    610 u32 tpm_oiap(u32 *auth_handle)
    611 {
    612 	const u8 command[10] = {
    613 		0x00, 0xc1,		/* TPM_TAG */
    614 		0x00, 0x00, 0x00, 0x0a,	/* parameter size */
    615 		0x00, 0x00, 0x00, 0x0a,	/* TPM_COMMAND_CODE */
    616 	};
    617 	const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
    618 	const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
    619 	u8 response[COMMAND_BUFFER_SIZE];
    620 	size_t response_length = sizeof(response);
    621 	u32 err;
    622 
    623 	if (oiap_session.valid)
    624 		tpm_terminate_auth_session(oiap_session.handle);
    625 
    626 	err = tpm_sendrecv_command(command, response, &response_length);
    627 	if (err)
    628 		return err;
    629 	if (unpack_byte_string(response, response_length, "ds",
    630 			       res_auth_handle_offset, &oiap_session.handle,
    631 			       res_nonce_even_offset, &oiap_session.nonce_even,
    632 			       (u32)DIGEST_LENGTH))
    633 		return TPM_LIB_ERROR;
    634 	oiap_session.valid = 1;
    635 	if (auth_handle)
    636 		*auth_handle = oiap_session.handle;
    637 	return 0;
    638 }
    639 
    640 u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
    641 		       const void *parent_key_usage_auth, u32 *key_handle)
    642 {
    643 	const u8 command[14] = {
    644 		0x00, 0xc2,		/* TPM_TAG */
    645 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
    646 		0x00, 0x00, 0x00, 0x41,	/* TPM_COMMAND_CODE */
    647 		0x00, 0x00, 0x00, 0x00,	/* parent handle */
    648 	};
    649 	const size_t req_size_offset = 2;
    650 	const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
    651 	const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
    652 	const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
    653 	u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
    654 		   TPM_REQUEST_AUTH_LENGTH];
    655 	u8 response[COMMAND_BUFFER_SIZE];
    656 	size_t response_length = sizeof(response);
    657 	u32 err;
    658 
    659 	if (!oiap_session.valid) {
    660 		err = tpm_oiap(NULL);
    661 		if (err)
    662 			return err;
    663 	}
    664 	if (pack_byte_string(request, sizeof(request), "sdds",
    665 			     0, command, sizeof(command),
    666 			     req_size_offset,
    667 			     sizeof(command) + key_length
    668 			     + TPM_REQUEST_AUTH_LENGTH,
    669 			     req_parent_handle_offset, parent_handle,
    670 			     req_key_offset, key, key_length
    671 		))
    672 		return TPM_LIB_ERROR;
    673 
    674 	err = create_request_auth(request, sizeof(command) + key_length, 4,
    675 				  &oiap_session,
    676 				  request + sizeof(command) + key_length,
    677 				  parent_key_usage_auth);
    678 	if (err)
    679 		return err;
    680 	err = tpm_sendrecv_command(request, response, &response_length);
    681 	if (err) {
    682 		if (err == TPM_AUTHFAIL)
    683 			oiap_session.valid = 0;
    684 		return err;
    685 	}
    686 
    687 	err = verify_response_auth(0x00000041, response,
    688 				   response_length - TPM_RESPONSE_AUTH_LENGTH,
    689 				   4, &oiap_session,
    690 				   response + response_length -
    691 				   TPM_RESPONSE_AUTH_LENGTH,
    692 				   parent_key_usage_auth);
    693 	if (err)
    694 		return err;
    695 
    696 	if (key_handle) {
    697 		if (unpack_byte_string(response, response_length, "d",
    698 				       res_handle_offset, key_handle))
    699 			return TPM_LIB_ERROR;
    700 	}
    701 
    702 	return 0;
    703 }
    704 
    705 u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
    706 			 size_t *pubkey_len)
    707 {
    708 	const u8 command[14] = {
    709 		0x00, 0xc2,		/* TPM_TAG */
    710 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
    711 		0x00, 0x00, 0x00, 0x21,	/* TPM_COMMAND_CODE */
    712 		0x00, 0x00, 0x00, 0x00,	/* key handle */
    713 	};
    714 	const size_t req_size_offset = 2;
    715 	const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
    716 	const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
    717 	u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
    718 	u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
    719 		    TPM_RESPONSE_AUTH_LENGTH];
    720 	size_t response_length = sizeof(response);
    721 	u32 err;
    722 
    723 	if (!oiap_session.valid) {
    724 		err = tpm_oiap(NULL);
    725 		if (err)
    726 			return err;
    727 	}
    728 	if (pack_byte_string(request, sizeof(request), "sdd",
    729 			     0, command, sizeof(command),
    730 			     req_size_offset,
    731 			     (u32)(sizeof(command)
    732 			     + TPM_REQUEST_AUTH_LENGTH),
    733 			     req_key_handle_offset, key_handle
    734 		))
    735 		return TPM_LIB_ERROR;
    736 	err = create_request_auth(request, sizeof(command), 4, &oiap_session,
    737 				  request + sizeof(command), usage_auth);
    738 	if (err)
    739 		return err;
    740 	err = tpm_sendrecv_command(request, response, &response_length);
    741 	if (err) {
    742 		if (err == TPM_AUTHFAIL)
    743 			oiap_session.valid = 0;
    744 		return err;
    745 	}
    746 	err = verify_response_auth(0x00000021, response,
    747 				   response_length - TPM_RESPONSE_AUTH_LENGTH,
    748 				   0, &oiap_session,
    749 				   response + response_length -
    750 				   TPM_RESPONSE_AUTH_LENGTH,
    751 				   usage_auth);
    752 	if (err)
    753 		return err;
    754 
    755 	if (pubkey) {
    756 		if ((response_length - TPM_RESPONSE_HEADER_LENGTH
    757 		     - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
    758 			return TPM_LIB_ERROR;
    759 		*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
    760 			- TPM_RESPONSE_AUTH_LENGTH;
    761 		memcpy(pubkey, response + res_pubkey_offset,
    762 		       response_length - TPM_RESPONSE_HEADER_LENGTH
    763 		       - TPM_RESPONSE_AUTH_LENGTH);
    764 	}
    765 
    766 	return 0;
    767 }
    768 
    769 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
    770 u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
    771 		      u32 *handle)
    772 {
    773 	u16 key_count;
    774 	u32 key_handles[10];
    775 	u8 buf[288];
    776 	u8 *ptr;
    777 	u32 err;
    778 	u8 digest[20];
    779 	size_t buf_len;
    780 	unsigned int i;
    781 
    782 	/* fetch list of already loaded keys in the TPM */
    783 	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
    784 	if (err)
    785 		return -1;
    786 	key_count = get_unaligned_be16(buf);
    787 	ptr = buf + 2;
    788 	for (i = 0; i < key_count; ++i, ptr += 4)
    789 		key_handles[i] = get_unaligned_be32(ptr);
    790 
    791 	/* now search a(/ the) key which we can access with the given auth */
    792 	for (i = 0; i < key_count; ++i) {
    793 		buf_len = sizeof(buf);
    794 		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
    795 		if (err && err != TPM_AUTHFAIL)
    796 			return -1;
    797 		if (err)
    798 			continue;
    799 		sha1_csum(buf, buf_len, digest);
    800 		if (!memcmp(digest, pubkey_digest, 20)) {
    801 			*handle = key_handles[i];
    802 			return 0;
    803 		}
    804 	}
    805 	return 1;
    806 }
    807 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
    808 
    809 #endif /* CONFIG_TPM_AUTH_SESSIONS */
    810 
    811 u32 tpm_get_random(void *data, u32 count)
    812 {
    813 	const u8 command[14] = {
    814 		0x0, 0xc1,		/* TPM_TAG */
    815 		0x0, 0x0, 0x0, 0xe,	/* parameter size */
    816 		0x0, 0x0, 0x0, 0x46,	/* TPM_COMMAND_CODE */
    817 	};
    818 	const size_t length_offset = 10;
    819 	const size_t data_size_offset = 10;
    820 	const size_t data_offset = 14;
    821 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
    822 	size_t response_length = sizeof(response);
    823 	u32 data_size;
    824 	u8 *out = data;
    825 
    826 	while (count > 0) {
    827 		u32 this_bytes = min((size_t)count,
    828 				     sizeof(response) - data_offset);
    829 		u32 err;
    830 
    831 		if (pack_byte_string(buf, sizeof(buf), "sd",
    832 				     0, command, sizeof(command),
    833 				     length_offset, this_bytes))
    834 			return TPM_LIB_ERROR;
    835 		err = tpm_sendrecv_command(buf, response, &response_length);
    836 		if (err)
    837 			return err;
    838 		if (unpack_byte_string(response, response_length, "d",
    839 				       data_size_offset, &data_size))
    840 			return TPM_LIB_ERROR;
    841 		if (data_size > count)
    842 			return TPM_LIB_ERROR;
    843 		if (unpack_byte_string(response, response_length, "s",
    844 				       data_offset, out, data_size))
    845 			return TPM_LIB_ERROR;
    846 
    847 		count -= data_size;
    848 		out += data_size;
    849 	}
    850 
    851 	return 0;
    852 }
    853